HOOK集合----SSDT Inline Hook(X86 win7)
2021-03-08 22:30
标签:指示 direct ken for 进一步 状态 ems ssd nal 介绍: SSDT InlineHook是在SSDT Hook 基础上来进一步Hook的,SSDTHook 是直接将SSDT表中的 Nt*函数替换成Fake函数,而SSDT Inline Hook是将原函数代码的前五个字节改变为 E9 _ _ _ _ ,后面跟的是Offset,也就是我们Fake函数的偏移地址,这样当Ring3层函数,比如OpenProcess在Ring3 层被调用,然后进入Ring0 层的NtOpenProcess,但是前五个字节已经被我们改变,变成了跳板,就会进入我们实现写好的Fake函数中去。 Nt系列函数地址也是通过SSDT表来找到,上次写的SSDT Hook 中是用MmGetSystemRoutineAddress 来获取函数地址的,这次我通过手动的去找ntdll.dll中的导出表,找到的函数地址,然后找到索引,通过SSDT表找Nt*的函数地址。 (一) ?首先找到全局导出的KeServiceDescriptorTable。 ?然后从ntdll.dll的导出表中获取ZwOpenProcess函数地址。 ?从ZwOpenProcess中获取序号。 ?在SSDt表中获取NtOpenProcess函数的地址。 ?将NtOpenProcess所在页属性改为可读可写的状态。 ?计算Fake函数与E9指令后跟着的Offset。 ?修改NtOpenProcess函数前五个字节,完成Hook。 Hook前: Hook后: (二) HOOK集合----SSDT Inline Hook(X86 win7) 标签:指示 direct ken for 进一步 状态 ems ssd nal 原文地址:https://www.cnblogs.com/matthew-memorys/p/12769256.html 1 ULONG GetSSDTFunctionIndexByName(CHAR * FunctionName)
2 {
3 NTSTATUS Status = STATUS_UNSUCCESSFUL;
4 ULONG Offset = 1;
5 WCHAR* FileFullPath = L"\\SystemRoot\\System32\\ntdll.dll";
6 ULONG i;
7 SIZE_T MappingViewSize = 0;
8 PVOID MappingBaseAddress = NULL;
9 PIMAGE_NT_HEADERS ImageNtHeader = NULL;
10 PIMAGE_EXPORT_DIRECTORY ImageExportDirectory = NULL;
11 ULONG* AddressOfFunction = NULL;
12 ULONG* AddressOfName = NULL;
13 USHORT* AddressOfNameOrdinals = NULL;
14 CHAR* szFunctionName = NULL;
15 ULONG FunctionOrdinal = 0;
16 ULONG FunctionAddress = 0;
17 ULONG Index = 0;
18 //将Ntdll 映射到当前内核地址空间中
19 Status = MappingPeFile(FileFullPath, &MappingBaseAddress, &MappingViewSize);
20 if (!NT_SUCCESS(Status))
21 {
22 return 0;
23 }
24
25 __try
26 {
27 ImageNtHeader = RtlImageNtHeader(MappingBaseAddress);
28 if (ImageNtHeader&&ImageNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
29 {
30 ImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((ULONG_PTR)MappingBaseAddress +
31 ImageNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
32 33 //函数名字表
34 AddressOfName = (ULONG*)((ULONG_PTR)MappingBaseAddress + ImageExportDirectory->AddressOfNames);
35 //函数序号表
36 AddressOfNameOrdinals = (USHORT*)((ULONG_PTR)MappingBaseAddress + ImageExportDirectory->AddressOfNameOrdinals);
37 //根据序号表中的序号 函数地址表
38 AddressOfFunction = (ULONG*)((ULONG_PTR)MappingBaseAddress + ImageExportDirectory->AddressOfFunctions);
39
40 for (i = 0;i NumberOfNames;i++)
41 {
42 //获得函数名称
43 szFunctionName = (CHAR*)((ULONG_PTR)MappingBaseAddress + AddressOfName[i]);
44 if (_stricmp(szFunctionName, FunctionName) == 0)
45 {
46 //获得函数序号
47 FunctionOrdinal = AddressOfNameOrdinals[i];
48 //获得函数地址
49 FunctionAddress = AddressOfFunction[FunctionOrdinal]+ (ULONG_PTR)MappingBaseAddress;
50 /*
51 2: kd> u ZwOpenProcess
52 nt!ZwOpenProcess:
53 8485acd8 b8be000000 mov eax,0BEh
54 8485acdd 8d542404 lea edx,[esp+4]
55 8485ace1 9c pushfd
56 8485ace2 6a08 push 8
57 8485ace4 e8d5190000 call nt!KiSystemService (8485c6be)
58 8485ace9 c21000 ret 10h
59
60 */
61 Index = SSDT_INDEX(FunctionAddress);
62 break;
63 }
64 }
65 }
66 }
67 __except(1)
68 {
69 return 0;
70 }
71 ZwUnmapViewOfSection(NtCurrentProcess(), MappingBaseAddress);
72
73 return Index ;
74 }
1 NTSTATUS MappingPeFile(WCHAR * FileFullPath, PVOID * MappingBaseAddress, SIZE_T * MappingViewSize)
2 {
3 NTSTATUS Status = STATUS_UNSUCCESSFUL;
4 UNICODE_STRING FilePath;
5 OBJECT_ATTRIBUTES ObjectAttributes;
6 IO_STATUS_BLOCK IoStatusBlock;
7 HANDLE FileHandle = NULL;
8 HANDLE SectionHandle = NULL;
9 if (!MappingBaseAddress || !MappingViewSize || !FileFullPath)
10 {
11 return Status;
12
13 }
14 RtlInitUnicodeString(&FilePath, FileFullPath);
15 InitializeObjectAttributes(&ObjectAttributes, &FilePath,
16 OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
17 NULL,
18 NULL);
19
20 //获得文件句柄
21
22 Status = ZwCreateFile(&FileHandle,
23 SYNCHRONIZE,
24 &ObjectAttributes,
25 &IoStatusBlock,
26 NULL,
27 FILE_ATTRIBUTE_NORMAL,
28 FILE_SHARE_READ,
29 FILE_OPEN,
30 FILE_SYNCHRONOUS_IO_NONALERT,
31 NULL,
32 0);
33 if (!NT_SUCCESS(Status))
34 {
35 goto EXIT;
36 }
37
38 //创建一个映射对象
39 ObjectAttributes.ObjectName = NULL;
40 Status = ZwCreateSection(&SectionHandle,
41 SECTION_QUERY | SECTION_MAP_READ,
42 &ObjectAttributes,
43 NULL,
44 PAGE_WRITECOPY, //写拷贝
45 SEC_IMAGE, //指示内存对齐
46 FileHandle);
47 if (!NT_SUCCESS(Status))
48 {
49 goto EXIT;
50 }
51
52 //映射到地址空间
53
54 Status = ZwMapViewOfSection(SectionHandle,
55 NtCurrentProcess(),
56 MappingBaseAddress,
57 0, 0, 0,
58 MappingViewSize,
59 ViewUnmap,
60 0,
61 PAGE_WRITECOPY);
62
63
64
65 EXIT:
66 if (FileHandle)
67 {
68 ZwClose(FileHandle);
69 }
70 if (SectionHandle)
71 {
72 ZwClose(SectionHandle);
73 }
74 return Status;
75 }
extern PSYSTEM_SERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;
PVOID __SSDTInlineHook_ServiceTableBase = NULL;
ULONG __SSDTInlineHook_ZwFunctionIndex = 0;
LPFN_NTOPENPROCESS __SSDTInlineHook_NtOpenProcess = 0;
UCHAR* __SSDTInlineHook_NtOpenProcessCode = NULL;
UCHAR* __SSDTInlineHook_NtOpenProcessCode_Pass = NULL;
BOOLEAN __SSDTInlineHook_IsHook = FALSE;
NTSTATUS SSDTInlineHook(BOOLEAN IsOk)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
__SSDTInlineHook_ServiceTableBase = KeServiceDescriptorTable->ServiceTableBase;
if (__SSDTInlineHook_ServiceTableBase == NULL)
{
return Status;
}
//获取Zw 函数索引 通过导入表
__SSDTInlineHook_ZwFunctionIndex = GetSSDTFunctionIndexByName("ZwOpenProcess");
if (__SSDTInlineHook_ZwFunctionIndex)
{
//获取NtOpenpProcess 函数地址
__SSDTInlineHook_NtOpenProcess = (LPFN_NTOPENPROCESS)((ULONG*)__SSDTInlineHook_ServiceTableBase)[__SSDTInlineHook_ZwFunctionIndex];
if (__SSDTInlineHook_NtOpenProcess == NULL)
{
return Status;
}
if (IsOk && !__SSDTInlineHook_IsHook)
{
//开始SSDTInlineHook
Status = SSDTInlineHookInternel((ULONG*)__SSDTInlineHook_NtOpenProcess, (ULONG*)SSDTInlineHook_FakeNtOpenProcess, 5);
__SSDTInlineHook_IsHook = TRUE;
}
else
{
Status = SSDTInlineUnHookInternel((ULONG*)__SSDTInlineHook_NtOpenProcess);
__SSDTInlineHook_IsHook = FALSE;
}
}
return Status;
}
NTSTATUS SSDTInlineHookInternel(ULONG * FunctionAddress, ULONG * FakeFunctionAddress, ULONG Length)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
UCHAR v1[] = "\xe9\x00\x00\x00\x00";
UCHAR v2[] = "\xe9\x00\x00\x00\x00";
ULONG Temp = 0;
//申请空间保存原函数前5个字节指令
__SSDTInlineHook_NtOpenProcessCode = ExAllocatePool(NonPagedPool, Length);
if (!__SSDTInlineHook_NtOpenProcessCode)
{
return Status;
}
//关闭写保护
OnEnableWrite();
/*
2: kd> u 0x84a31ba1
nt!NtOpenProcess:
84a31ba1 8bff mov edi,edi
84a31ba3 55 push ebp
84a31ba4 8bec mov ebp,esp
*/
memcpy(__SSDTInlineHook_NtOpenProcessCode, FunctionAddress, Length);
//开启写保护
OnDisableWrite();
__SSDTInlineHook_NtOpenProcessCode_Pass = ExAllocatePool(NonPagedPool, Length + 5);
if (__SSDTInlineHook_NtOpenProcessCode_Pass == NULL)
{
if (__SSDTInlineHook_NtOpenProcessCode != NULL)
{
ExFreePool(__SSDTInlineHook_NtOpenProcessCode);
__SSDTInlineHook_NtOpenProcessCode = NULL;
}
return Status;
}
//0x90 NOP
RtlFillMemory(__SSDTInlineHook_NtOpenProcessCode_Pass, Length + 5, 0x90);
//22920
/*
0: kd> u NtOpenprocess
nt!NtOpenProcess:
84a31ba1 8bff mov edi,edi
84a31ba3 55 push ebp
84a31ba4 8bec mov ebp,esp
返回地址: 84a31ba6 51 push ecx
84a31ba7 51 push ecx
84a31ba8 64a124010000 mov eax,dword ptr fs:[00000124h]
84a31bae 8a803a010000 mov al,byte ptr [eax+13Ah]
84a31bb4 8b4d14 mov ecx,dword ptr [ebp+14h]
*/
memcpy((PUCHAR)__SSDTInlineHook_NtOpenProcessCode_Pass, __SSDTInlineHook_NtOpenProcessCode, Length);
//__SSDTInlineHook_NtOpenProcessCode_Pass [8b ff 55 8b ec | 90 90 90 90 90]
//SSDTInlineHook 返回地址
Temp = (ULONG_PTR)FunctionAddress + Length;
// Temp = 84a31ba6 [84a31ba1 + 5 ]
*((ULONG*)&v2[1]) = (ULONG_PTR)Temp - ((ULONG_PTR)__SSDTInlineHook_NtOpenProcessCode_Pass + 5 + 5);
// 白名单进程 判断后要 返回原函数执行 也就是 0x84a31ba6 处
//
memcpy(__SSDTInlineHook_NtOpenProcessCode_Pass + Length, v2, 5);
//__SSDTInlineHook_NtOpenProcessCode_Pass [8b ff 55 8b ec | e9 xx xx xx xx ]
Temp = (ULONG_PTR)FakeFunctionAddress;
*((ULONG*)&v1[1]) = (ULONG)Temp - ((ULONG)FunctionAddress + 5);
//FakeFunctionAddress - 0x84a31ba6
// E9 E9当前地址 + 5 + 4字节Offset = Target
OnEnableWrite();
RtlFillMemory((PVOID)FunctionAddress, Length, 0x90);
memcpy((PVOID)FunctionAddress, v1, 5);
OnDisableWrite();
Status = STATUS_SUCCESS;
return Status;
}
NTSTATUS SSDTInlineUnHookInternel(ULONG * FunctionAddress)
{
NTSTATUS Status = STATUS_UNSUCCESSFUL;
if (__SSDTInlineHook_NtOpenProcessCode == NULL)
{
return Status;
}
else
{
OnEnableWrite();
memcpy((PVOID)FunctionAddress, __SSDTInlineHook_NtOpenProcessCode, 5);
OnDisableWrite();
__SSDTInlineHook_ServiceTableBase = NULL;
__SSDTInlineHook_ZwFunctionIndex = 0;
__SSDTInlineHook_NtOpenProcess = 0;
__SSDTInlineHook_NtOpenProcessCode = NULL;
__SSDTInlineHook_NtOpenProcessCode_Pass = NULL;
Status = STATUS_SUCCESS;
}
return Status;
}
NTSTATUS SSDTInlineHook_FakeNtOpenProcess(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId)
{
__try
{
PEPROCESS EProcess = PsGetCurrentProcess();
if (EProcess != NULL && IsRealProcess(EProcess))
{
char * ProcessName = (ULONG_PTR)EProcess + x86_IMAGEFILENAME_OFFSET;
if (strcmp(ProcessName, "HookRing3.exe") == 0)
{
return STATUS_ACCESS_DENIED;
}
}
}
__except (1)
{
return GetExceptionCode();
}
//白名单进程 返回原先函数地址 + 5 处 执行
return ((LPFN_NTOPENPROCESS)__SSDTInlineHook_NtOpenProcessCode_Pass)(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);
}
文章标题:HOOK集合----SSDT Inline Hook(X86 win7)
文章链接:http://soscw.com/index.php/essay/62015.html