HOOK集合----SSDT Inline Hook(X86 win7)
Posted matthew-memorys
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HOOK集合----SSDT Inline Hook(X86 win7)相关的知识,希望对你有一定的参考价值。
介绍:
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*的函数地址。
1 ULONG GetSSDTFunctionIndexByName(CHAR * FunctionName) 2 { 3 NTSTATUS Status = STATUS_UNSUCCESSFUL; 4 ULONG Offset = 1; 5 WCHAR* FileFullPath = L"SystemRootSystem32 tdll.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 < ImageExportDirectory->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 }
(一)
?首先找到全局导出的KeServiceDescriptorTable。
?然后从ntdll.dll的导出表中获取ZwOpenProcess函数地址。
?从ZwOpenProcess中获取序号。
?在SSDt表中获取NtOpenProcess函数的地址。
?将NtOpenProcess所在页属性改为可读可写的状态。
?计算Fake函数与E9指令后跟着的Offset。
?修改NtOpenProcess函数前五个字节,完成Hook。
Hook前: Hook后:
(二)
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[] = "xe9x00x00x00x00"; UCHAR v2[] = "xe9x00x00x00x00"; 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)的主要内容,如果未能解决你的问题,请参考以下文章