一、实战篇

本不想摘代码,既然实战,就不多讲废话了,还是贴上吧,谁都有违背原则的时候:)。

代码一:经典案例,替换NtQuerySystemInformation,列取所有查询到的进程名,我使用修改CR0寄存器的方法。

#include <ntddk.h>

typedef struct _SYSTEM_THREADS

{

LARGE_INTEGER KernelTime;

LARGE_INTEGER UserTime;

LARGE_INTEGER CreateTime;

ULONG WaitTime;

PVOID StartAddress;

CLIENT_ID ClientIs;

KPRIORITY Priority;

KPRIORITY BasePriority;

ULONG ContextSwitchCount;

ULONG ThreadState;

KWAIT_REASON WaitReason;

}SYSTEM_THREADS, *PSYSTEM_THREADS;

typedef struct _SYSTEM_PROCESSES

{

ULONG NextEntryDelta;

ULONG ThreadCount;

ULONG Reserved[6];

LARGE_INTEGER CreateTime;

LARGE_INTEGER UserTime;

LARGE_INTEGER KernelTime;

UNICODE_STRING ProcessName;

KPRIORITY BasePriority;

ULONG ProcessId;

ULONG InheritedFromProcessId;

ULONG HandleCount;

ULONG Reserved2[2];

VM_COUNTERS VmCounters;

IO_COUNTERS IoCounters;

struct _SYSTEM_THREADS Threads[1];

}SYSTEM_PROCESSES, *PSYSTEM_PROCESSES;

NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation(

IN ULONG SystemInformationClass,

IN PVOID SystemInformation,

IN ULONG SystemInformationLength,

OUT PULONG ReturnLength);

NTSTATUS NewNtQuerySystemInformation(

IN ULONG SystemInformationClass,

IN PVOID SystemInformation,

IN ULONG SystemInformationLength,

OUT PULONG ReturnLength);

// SDT Structure

typedef struct _ServiceDescriptorTableEntry

{

unsigned int *ServiceTableBase;

unsigned int *ServiceCounterTableBase;

unsigned int NumberOfServices;

unsigned char *ParamTableBase;

}ServiceDescriptorTableEntry, *PServiceDescriptorTableEntry;

// import KeServiceDescriptorTable

extern PServiceDescriptorTableEntry KeServiceDescriptorTable;

PServiceDescriptorTableEntry pSDT;

// real NtQuerySystemInformation

typedef NTSTATUS (*NTQUERYSYSTEMINFORMATION)(

IN ULONG SystemInformationClass,

IN PVOID SystemInformation,

IN ULONG SystemInformationLength,

OUT PULONG ReturnLength);

NTQUERYSYSTEMINFORMATION OldNtQuerySystemInformation;

UNICODE_STRING usLinkDeviceNameString;

VOID UnloadDriver(IN PDRIVER_OBJECT pDriverObject)

{

ULONG _cr0;

PDEVICE_OBJECT pDeviceObject;

// recovery SSDT

_asm

{

// WP off

cli

mov eax, cr0

mov _cr0, eax

and eax, 0fffeffffh

mov cr0,eax

// recovery SSDT

mov ecx, DWORD PTR [ZwQuerySystemInformation]

mov edx, [ecx+1]

mov eax, DWORD PTR [pSDT];

mov esi, [eax]

mov ebx, DWORD PTR [OldNtQuerySystemInformation]

mov [esi+edx*4],ebx

// WP on

mov eax, _cr0

mov cr0, eax

sti

}

pDeviceObject= pDriverObject->DeviceObject;

IoDeleteSymbolicLink(&usLinkDeviceNameString);

ASSERT(!pDeviceObject->AttachedDevice);

if ( pDeviceObject != NULL )

{

IoDeleteDevice(pDeviceObject);

}

}

NTSTATUS DriverEntry (IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING usRegistryPath)

{

ULONG _cr0;

NTSTATUS ntStatus;

PDEVICE_OBJECT pDeviceObject;

UNICODE_STRING usDeviceNameString;

RtlInitUnicodeString(&usDeviceNameString, L"//Device//SSDTHOOK" );

RtlInitUnicodeString(&usLinkDeviceNameString, L"//DosDevices//SSDTHOOK" );

ntStatus = IoCreateDevice(

pDriverObject,

0,

&usDeviceNameString,

FILE_DEVICE_DISK_FILE_SYSTEM,

FILE_DEVICE_SECURE_OPEN,

FALSE,

&pDeviceObject);

if (!NT_SUCCESS(ntStatus))

{

return ntStatus;

}

ntStatus = IoCreateSymbolicLink(&usLinkDeviceNameString,&usDeviceNameString);

if (!NT_SUCCESS(ntStatus))

{

IoDeleteDevice(pDeviceObject);

return ntStatus;

}

pDriverObject->DriverUnload=UnloadDriver;

pSDT = KeServiceDescriptorTable;

// modify SSDT

_asm

{

// WP off

cli

mov eax, cr0

mov _cr0, eax

and eax, 0fffeffffh

mov cr0, eax

// replace NtQuerySystemInformation with NewNtQuerySystemInformation

mov ecx, DWORD PTR [ZwQuerySystemInformation]

mov edx, [ecx+1]

mov eax, DWORD PTR [pSDT]

mov esi, [eax]

mov edx, [esi+edx*4]

mov DWORD PTR [OldNtQuerySystemInformation], edx

mov ecx, [ecx+1]

mov eax, [eax]

mov dword ptr [eax+ecx*4], offset NewNtQuerySystemInformation

// WP on

mov eax, _cr0

mov cr0, eax

sti

}

return ntStatus;

}

NTSTATUS NewNtQuerySystemInformation(

IN ULONG SystemInformationClass,

IN PVOID SystemInformation,

IN ULONG SystemInformationLength,

OUT PULONG ReturnLength)

{

ANSI_STRING asProcessName;

NTSTATUS ntQuerySystemInformation = (OldNtQuerySystemInformation)

(SystemInformationClass,

SystemInformation,

SystemInformationLength,

ReturnLength);

if(NT_SUCCESS(ntQuerySystemInformation))

{

if(5 == SystemInformationClass)

{

PSYSTEM_PROCESSES curr = (PSYSTEM_PROCESSES)SystemInformation;

PSYSTEM_PROCESSES prev = NULL;

if(curr->NextEntryDelta)((char *)curr += curr->NextEntryDelta);

while(curr)

{

RtlUnicodeStringToAnsiString(&asProcessName, &(curr->ProcessName), TRUE);

DbgPrint(asProcessName.Buffer);

RtlFreeAnsiString(&asProcessName);

if(curr != NULL)

{

prev = curr;

if(curr->NextEntryDelta)((char *)curr += curr->NextEntryDelta);

else curr = NULL;

}

}

}

}

return ntQuerySystemInformation;

}

案例二:修改SDT中NtCreateSection的地址,列出所有创建SECTION的文件名称,我使用了MDL。其实,搞进程很麻烦凡的,windows的大麻烦之一。

#include <ntddk.h>

NTSYSAPI

NTSTATUS

NTAPI ZwCreateSection(

OUT PHANDLE  SectionHandle,

IN ACCESS_MASK  DesiredAccess,

IN POBJECT_ATTRIBUTES  ObjectAttributes OPTIONAL,

IN PLARGE_INTEGER  MaximumSize OPTIONAL,

IN ULONG  SectionPageProtection,

IN ULONG  AllocationAttributes,

IN HANDLE  FileHandle OPTIONAL);

NTSTATUS NewNtCreateSection(

OUT PHANDLE SectionHandle,

IN ULONG DesiredAccess,

IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,

IN PLARGE_INTEGER MaximumSize OPTIONAL,

IN ULONG PageAttributess,

IN ULONG SectionAttributes,

IN HANDLE FileHandle OPTIONAL);

// SDT Structure

#pragma pack(1)

typedef struct _ServiceDescriptorTableEntry

{

unsigned int *ServiceTableBase;

unsigned int *ServiceCounterTableBase;

unsigned int NumberOfServices;

unsigned char *ParamTableBase;

}ServiceDescriptorTableEntry, *PServiceDescriptorTableEntry;

#pragma pack()

__declspec(dllimport)  ServiceDescriptorTableEntry KeServiceDescriptorTable;

#define SYSTEMSERVICE(_function) KeServiceDescriptorTable.ServiceTableBase[*(PULONG)((PUCHAR)_function+1)]

// real NtCreateSection

typedef NTSTATUS (*NTCREATESECTION)(

OUT PHANDLE SectionHandle,

IN ULONG DesiredAccess,

IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,

IN PLARGE_INTEGER MaximumSize OPTIONAL,

IN ULONG PageAttributess,

IN ULONG SectionAttributes,

IN HANDLE FileHandle OPTIONAL);

NTCREATESECTION OldNtCreateSection;

UNICODE_STRING usLinkDeviceNameString;

// MDL define

PMDL  g_pmdlSystemCall;

PVOID *pMappedSystemCallTable;

#define SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function+1)

#define HOOK_SYSCALL(_Function, _Hook, _Orig)/

_Orig = (PVOID) InterlockedExchange( (PLONG) &pMappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)

#define UNHOOK_SYSCALL(_Function, _Hook, _Orig)/

InterlockedExchange( (PLONG) &pMappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)

VOID UnloadDriver(IN PDRIVER_OBJECT pDriverObject)

{

PDEVICE_OBJECT pDeviceObject;

// recovery SSDT

UNHOOK_SYSCALL(ZwCreateSection, OldNtCreateSection, NewNtCreateSection);

// Unlock and Free MDL

if(g_pmdlSystemCall)

{

MmUnmapLockedPages(pMappedSystemCallTable, g_pmdlSystemCall);

IoFreeMdl(g_pmdlSystemCall);

}

pDeviceObject= pDriverObject->DeviceObject;

IoDeleteSymbolicLink(&usLinkDeviceNameString);

ASSERT(!pDeviceObject->AttachedDevice);

if ( pDeviceObject != NULL )

{

IoDeleteDevice(pDeviceObject);

}

}

NTSTATUS DriverEntry (IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING usRegistryPath)

{

NTSTATUS ntStatus;

PDEVICE_OBJECT pDeviceObject;

UNICODE_STRING usDeviceNameString;

RtlInitUnicodeString(&usDeviceNameString, L"//Device//SSDTHOOK" );

RtlInitUnicodeString(&usLinkDeviceNameString, L"//DosDevices//SSDTHOOK" );

ntStatus = IoCreateDevice(

pDriverObject,

0,

&usDeviceNameString,

FILE_DEVICE_DISK_FILE_SYSTEM,

FILE_DEVICE_SECURE_OPEN,

FALSE,

&pDeviceObject);

if (!NT_SUCCESS(ntStatus))

{

return ntStatus;

}

ntStatus = IoCreateSymbolicLink(&usLinkDeviceNameString,&usDeviceNameString);

if (!NT_SUCCESS(ntStatus))

{

IoDeleteDevice(pDeviceObject);

return ntStatus;

}

pDriverObject->DriverUnload=UnloadDriver;

OldNtCreateSection =(NTCREATESECTION)(SYSTEMSERVICE(ZwCreateSection));

g_pmdlSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4);

if(!g_pmdlSystemCall) return STATUS_UNSUCCESSFUL;

MmBuildMdlForNonPagedPool(g_pmdlSystemCall);

// Change the flags of the MDL

g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;

pMappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode);

// hook system calls

HOOK_SYSCALL(ZwCreateSection, NewNtCreateSection, OldNtCreateSection);

return ntStatus;

}

NTSTATUS NewNtCreateSection(

OUT PHANDLE SectionHandle,

IN ULONG DesiredAccess,

IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,

IN PLARGE_INTEGER MaximumSize OPTIONAL,

IN ULONG PageAttributess,

IN ULONG SectionAttributes,

IN HANDLE FileHandle OPTIONAL)

{

HANDLE hHandle;

PFILE_OBJECT pFileObject;

OBJECT_HANDLE_INFORMATION HandleInformationObject;

ANSI_STRING asFileName;

hHandle=(HANDLE)FileHandle;

ObReferenceObjectByHandle(hHandle,0,0,KernelMode,&pFileObject,&HandleInformationObject);

if(pFileObject != NULL)

{

RtlUnicodeStringToAnsiString(&asFileName,&(pFileObject->FileName),TRUE);

DbgPrint(asFileName.Buffer);

RtlFreeAnsiString(&asFileName);

}

return ((NTCREATESECTION)(OldNtCreateSection))(SectionHandle, DesiredAccess, ObjectAttributes, MaximumSize, PageAttributess, SectionAttributes, FileHandle);

}

以上两个例子都是在XP SP2下测试,用来验证第一部分我说的那些废话。代码本身没任何破坏性,有兴趣可以尝试,如有疑问欢迎交流。

二、Anti-SSDT Hook

小学时,课本有一篇寓言《自相矛盾》,当时觉得不可思议,像现在想来,矛与盾的较量永未停止。对SSDT Hook最终都要修改掉KeServiceDescriptorTable的成员ServiceTableBase所指向的内存空间的Nt*系列函数地址,那么只要扫描这段内存空间,抓出非法居民即可。原理是这样的。

先看看‘ROOTKITS: SUVVERING THE WINDOWS KERNEL’的高招。首先,获取ntoskrnl.exe模块的内存地址范围,如果所检测的SDT中的函数地址不在这个范围内就是被HOOK了。不再重复人家的代码了。

Tan Chew Keong在他的’Win2K/XP SDT Restore’大作中的基本思路是不变的,但是,他的SDT是在ntoskrnl.exe的原始文件中加载的,然后使用这个SDT跟操作系统内核中正在使用的那个进行对比,这样更精确到位,而且可以对可疑的HOOK进行恢复。相关代码在网络上有提供。这种加载SDT的方法是90210在rootkit.com中‘A more stable way to locate real KiServiceTable’提出来的。

其他的方法我在师还没有注意到,应该是有的,如果发现新方法,欢迎交流。

三、参考资料

1.       ‘ROOTKITS: SUVVERING THE WINDOWS KERNEL’, Greg Hoglund, James Butler

2.       ‘Defeating Kernel Native API Hookers by Direct KiServiceTable Restoration’, Tan Chew Keong

3.       ‘Win2K/XP SDT Restore 0.2 (Proof-Of-Concept)’, Tan Chew Keong

4.       ‘SDT Hooking 무력화에 대한 연구’, Dual5651

‘A more stable way to locate real KiServiceTable’, 90210

也谈SSDT Hook(二)相关推荐

  1. 也谈SSDT Hook(一)

    一.原理篇 1.            关于系统服务. 系统服务是由操作系统提供一组函数,使得开发者能够通过APIs直接或间接的调用.一个API可以对应一个系统服务,也可以一个API依赖多个系统服务. ...

  2. 进程隐藏与进程保护(SSDT Hook 实现)(二)

    文章目录: 1. 引子 – Demo 实现效果: 2. 进程隐藏与进程保护概念: 3. SSDT Hook 框架搭建: 4. Ring0 实现进程隐藏: 5. Ring0 实现进程保护: 6. 隐藏进 ...

  3. 进程隐藏与进程保护(SSDT Hook 实现)(二) 转载自 Zachary.XiaoZhen - 梦想的天空

    文章目录:                   1. 引子 – Demo 实现效果: 2. 进程隐藏与进程保护概念: 3. SSDT Hook 框架搭建: 4. Ring0 实现进程隐藏: 5. Ri ...

  4. Win64 驱动内核编程-22.SHADOW SSDT HOOK(宋孖健)

    SHADOW SSDT HOOK HOOK 和 UNHOOK SHADOW SSDT 跟之前的 HOOK/UNHOOK SSDT 类似,区别是查找SSSDT的特征码,以及根据索引计算函数地址的公式,还 ...

  5. (52)系统调用阶段测试——基于 SSDT HOOK 的 FindWindowA 监视器

    一.项目说明 SSDT HOOK 内核函数我们已经会了,请看这两篇博客: SSDT HOOK 实现进程保护 补充内容:SSDT HOOK 模板 此次考试和 hook NtOpenProcess 或 N ...

  6. (51)SSDT HOOK 实现进程保护

    一.回顾 在前面的课程里,我们逆向分析了 KiSystemService / KiFastCallEntry 的部分代码,我们发现这两个函数找系统服务表 SystemServiceTable 的方法是 ...

  7. Windows驱动开发学习笔记(五)—— SSDT HOOK

    Windows驱动开发学习笔记(五)-- SSDT HOOK 系统服务表 系统服务描述符表 实验一:通过代码获取SSDT表地址 通过页表基址修改页属性 方法1:修改页属性 方法2:修改CR0寄存器 实 ...

  8. 进程隐藏与进程保护(SSDT Hook 实现)(三)

    文章目录: 1. 引子: 2. 获取当前系统下所有进程: 3. 服务管理(安装,启动,停止,卸载): 4. 应用程序和内核程序通信: 5. 小结: 1. 引子: 关于这个 SSDT Hook 实现进程 ...

  9. 进程隐藏与进程保护(SSDT Hook 实现)(一)

    文章目录: 1. 引子 – Hook 技术: 2. SSDT 简介: 3. 应用层调用 Win32 API 的完整执行流程: 4. 详解 SSDT: 5. SSDT  Hook 原理: 6. 小结: ...

最新文章

  1. iPhone 13 终于等到了!降价、新颜色、电池续航性能大提升
  2. 关于类和对象的进一步讨论 C++
  3. mysql5.6 python_Centos-6.5 + python3 + mysql5.6 环境搭建
  4. springcloud gateway ribbon使用_Github点赞接近 70k 的Spring Cloud学习教程+实战项目推荐!牛批!...
  5. jquery时期到计时插件
  6. meta标签的另一个用法
  7. Android 性能测试——Memory Monitor 工具
  8. 无模型自适应迭代学习控制原理和matlab代码仿真学习记录
  9. Junit介绍与实现
  10. typedef 定义函数指针
  11. rms 公式 有效值_有效值、真有效值、基波有效值、全有效值概念辨析
  12. Android反编译查看源文件
  13. Java8新特性之日期和时间
  14. unity3d FPS 枪的后座力
  15. 吐血分享:QQ群霸屏技术教程之霸屏实施细则
  16. 绝地求生2020服务器维护中,绝地求生2020最新维护公告几点开服?3月18日更新内容一览...
  17. cadence allegro 之如何隐藏/显示单个DRC
  18. C# ComboBox:组合框控件
  19. Vue实现图形化积木式编程(十二)
  20. 太乐地图下载器5.0.5(破解版)

热门文章

  1. Django模型层(models.py)之多表操作
  2. Maven远程仓库:pom依赖以及jar包下载
  3. 使用正則表達式对URL进行解析
  4. [转]Create Custom Exception Filter in ASP.NET Core
  5. 分页原理+分页代码+分页类制作
  6. android Studio 运行不显示avd 无法运行
  7. jquery实现定时调度(倒计时)
  8. Android和.NET通用的AES算法 (转) 好东东 收藏一下
  9. Page.LoadTemplate的使用
  10. 5.6 图像颜色映射