http://www.csdn 123.com/html/itweb/20130827/83559_83558_83544.htm
免费开源库EasyHook(inline hook),下面是下载地址
http://easyhook.codeplex.com/releases/view/24401 把头文件 lib文件全拷贝在工程文件夹中,把dll拷贝在%system32%中(PS:
64位 应该放在C:WindowsSysWOW64文件夹中)
好的,现在切入正题。
假设我们的工程是要监控Troj.exe的行为。A.exe为监控应用程序,A.exe先遍历当前进程,若找到Troj.exe则将B.dll远程线程注入到Troj.exe进程中
PS: XP CreateRemoteThread win7用NT系列函数,如下:
1 typedef DWORD (WINAPI *PFNTCREATETHREADEX) 2 ( 3 OUT PHANDLE ThreadHandle, 4 ACCESS_MASK DesiredAccess, 5 LPVOID ObjectAttributes, 6 HANDLE ProcessHandle, 7 LPTHREAD_START_ROUTINE lpStartAddress, 8 LPVOID lpParameter, 9 BOOL CreateSuspended, 10 DWORD dwStackSize, 11 DWORD dw1, 12 DWORD dw2, 13 LPVOID Unknown 14 ); 15 16 BOOL IsVistaOrLater() 17 { 18 OSVERSIONINFO osvi; 19 ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); 20 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 21 GetVersionEx(&osvi); 22 if( osvi.dwMajorVersion >= 6 ) 23 { 24 return TRUE; 25 } 26 return FALSE; 27 } 28 29 BOOL MyCreateRemoteThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf) 30 { 31 HANDLE hThread = NULL; 32 FARPROC pFunc = NULL; 33 if( IsVistaOrLater() ) // Vista, 7, Server2008 34 { 35 pFunc = GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtCreateThreadEx"); 36 if( pFunc == NULL ) 37 { 38 ErrorReport(GetLastError()); 39 } 40 ((PFNTCREATETHREADEX)pFunc)(&hThread, 41 0x1FFFFF, 42 NULL, 43 hProcess, 44 pThreadProc, 45 pRemoteBuf, 46 FALSE, 47 NULL, 48 NULL, 49 NULL, 50 NULL); 51 if( hThread == NULL ) 52 { 53 ErrorReport(GetLastError()); 54 } 55 } 56 else // 2000, XP, Server2003 57 { 58 hThread = CreateRemoteThread(hProcess, 59 NULL, 60 0, 61 pThreadProc, 62 pRemoteBuf, 63 0, 64 NULL); 65 if( hThread == NULL ) 66 { 67 ErrorReport(GetLastError()); 68 } 69 } 70 if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) ) 71 { 72 ErrorReport(GetLastError()); 73 } 74 return TRUE; 75 }
注入成功后,DLL和A.exe建立命名管道进行进程间通信。例如,当Troj.exe调用CopyFileW被B.dll拦载时,发送相关数据(简称为M结构体)到A.exe文本控件上显示。
M结构体如下构造:
1 struct WinExec 2 { 3 _In_ CHAR lpCmdLine[0x400]; 4 _In_ UINT uCmdShow; 5 }; 6 7 struct CopyFileW 8 { 9 _In_ TCHAR lpExistingFileName[0x400]; 10 _In_ TCHAR lpNewFileName[0x400]; 11 _In_ BOOL bFailIfExists; 12 }; 13 14 typedef struct _tag_info 15 { 16 DWORD time; 17 DWORD Return; 18 DWORD Info_Type; 19 20 union{ 21 struct WinExec WinExec_; 22 struct CopyFileW CopyFileW_; 23 }; 24 25 }taginfo, *ptaginfo; 26 27 #define WINEXEC_INFO 1 28 #define COPYFILEW 2
我的这个实例很基础,就拦载Winexec函数和CopyFileW函数
请先允许我展示几个头文件
hook.h

1 #pragma once 2 3 4 #ifndef _M_X64 5 #pragma comment(lib, "EasyHook32.lib") 6 #else 7 #pragma comment(lib, "EasyHook64.lib") 8 #endif 9 10 UINT WINAPI MyWinExec( 11 _In_ LPCSTR lpCmdLine, 12 _In_ UINT uCmdShow 13 ); 14 15 typedef UINT (WINAPI * ptrWinExec)( 16 _In_ LPCSTR lpCmdLine, 17 _In_ UINT uCmdShow 18 ); 19 20 extern ptrWinExec realWinExec; 21 22 BOOL WINAPI MyCopyFileW( 23 _In_ LPCTSTR lpExistingFileName, 24 _In_ LPCTSTR lpNewFileName, 25 _In_ BOOL bFailIfExists 26 ); 27 28 typedef BOOL (WINAPI *ptrCopyFileW)( 29 _In_ LPCTSTR lpExistingFileName, 30 _In_ LPCTSTR lpNewFileName, 31 _In_ BOOL bFailIfExists 32 ); 33 34 extern ptrCopyFileW realCopyFileW;
head.h

1 #include "easyhook.h" 2 #include "Hook.h" 3 #include <Shlwapi.h> 4 #include <stdio.h> 5 6 #pragma comment(lib, "Shlwapi.lib") 7 #pragma comment(lib, "winmm.lib") 8 9 ptrWinExec realWinExec = NULL; //真实地址 10 ptrCopyFileW realCopyFileW = NULL; 11 12 TRACED_HOOK_HANDLE hHookWinExec = new HOOK_TRACE_INFO(); 13 TRACED_HOOK_HANDLE hHookCopyFileW = new HOOK_TRACE_INFO(); 14 15 ULONG HookWinExec_ACLEntries[1] = {0}; 16 ULONG HookCopyFileW_ACLEntries[1] = {0}; 17 18 HANDLE hNamedPipe;//命名管道句柄 19 20 DWORD StartTime = 0;//应用程序起始时间 21 22 #define sizeofpipe 0x800 //管道的大小 23 24 void CreateNamedPipeInServer();//声明函数 部分内容非关键内容没有列出来 25 void ErrorReport(DWORD errorid);
DllMain.cpp
1 #include "Header.h" 2 3 int PrepareRealApiEntry() 4 { 5 HMODULE hKernel32 = LoadLibrary(L"Kernel32.dll"); 6 if (!(realWinExec = (ptrWinExec)GetProcAddress(hKernel32, "WinExec")) || 7 !(realCopyFileW = (ptrCopyFileW)GetProcAddress(hKernel32, "CopyFileW"))) 8 { 9 ErrorReport(GetLastError()); 10 } 11 return 0; 12 } 13 14 void DoHook() 15 { 16 LhInstallHook(realWinExec, MyWinExec, NULL, hHookWinExec); 17 LhSetExclusiveACL(HookWinExec_ACLEntries, 1, hHookWinExec); 18 19 LhInstallHook(realCopyFileW, MyCopyFileW, NULL, hHookCopyFileW); 20 LhSetExclusiveACL(HookCopyFileW_ACLEntries, 1, hHookCopyFileW); 21 } 22 23 void DoneHook() 24 { 25 // this will also invalidate "hHook", because it is a traced handle... 26 LhUninstallAllHooks(); 27 28 // this will do nothing because the hook is already removed... 29 30 LhUninstallHook(hHookWinExec); 31 LhUninstallHook(hHookCopyFileW); 32 33 // now we can safely release the traced handle 34 delete hHookWinExec; 35 hHookWinExec = NULL; 36 37 delete hHookCopyFileW; 38 hHookCopyFileW = NULL; 39 40 // even if the hook is removed, we need to wait for memory release 41 LhWaitForPendingRemovals(); 42 } 43 44 BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) 45 { 46 switch (ul_reason_for_call) 47 { 48 case DLL_PROCESS_ATTACH: 49 { 50 StartTime = timeGetTime(); 51 CreateNamedPipeInServer(); 52 if (PrepareRealApiEntry() != 0) 53 { 54 return FALSE; 55 } 56 DoHook(); 57 58 break; 59 } 60 case DLL_THREAD_ATTACH: 61 { 62 break; 63 } 64 case DLL_THREAD_DETACH: 65 { 66 break; 67 } 68 69 case DLL_PROCESS_DETACH: 70 { 71 DoneHook(); 72 break; 73 } 74 } 75 return TRUE; 76 }
hook_fakefunction.cpp
1 BOOL WINAPI MyCopyFileW( //Mystery of Panda 2 _In_ LPCTSTR lpExistingFileName, 3 _In_ LPCTSTR lpNewFileName, 4 _In_ BOOL bFailIfExists 5 ) 6 { 7 //进入真实函数前,跳转到此处 8 bool status = false; 9 status = (realCopyFileW)(lpExistingFileName, lpNewFileName, bFailIfExists);//执行真正的CopyFileW函数 10 ptaginfo tagstruct;//上述M结构体 11 ZeroMemory(tagstruct, sizeof(tagstruct)); 12 if (!(tagstruct = (ptaginfo)malloc(sizeof(_tag_info)))) 13 { 14 return status; 15 } 16 HANDLE hThread; 17 tagstruct->time = timeGetTime() - StartTime;//填充结构体开始 18 tagstruct->Return = status; 19 tagstruct->Info_Type = COPYFILEW; 20 if (lpExistingFileName != NULL) //检查参数 在实际调试中发现如果不检查参数,DLL可能会崩溃 21 { 22 wcscpy(tagstruct->CopyFileW_.lpExistingFileName, lpExistingFileName); 23 } 24 else 25 { 26 free(tagstruct); 27 return status; 28 } 29 tagstruct->CopyFileW_.bFailIfExists = bFailIfExists; 30 if (lpNewFileName != NULL) //检查参数 31 { 32 wcscpy(tagstruct->CopyFileW_.lpNewFileName, lpNewFileName); 33 } 34 else 35 { 36 free(tagstruct); 37 return status; 38 } 39 //填充结构体完毕 40 hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WritePipe, (ptaginfo)tagstruct, 0, 0);//创建线程发送数据到管道 41 if (hThread) 42 { 43 WaitForSingleObject(hThread, INFINITE); 44 CloseHandle(hThread); 45 } 46 free(tagstruct); 47 return status;
48 } 49 50 UINT WINAPI MyWinExec( 51 _In_ LPCSTR lpCmdLine, 52 _In_ UINT uCmdShow 53 ) 54 { 55 ... 56 }
至此,这个简单监控示例就完成了。
题外话:这只是应用层的最简单的钩子,可以轻易的被绕过。如果在应用层上想做的更深一点,例如监控troj.exe的进程创建,可以考虑钩R3上的NtCreateUserProcess函数,下面是网上逆出来的函数参数
1 typedef struct _NT_PROC_THREAD_ATTRIBUTE_ENTRY { 2 ULONG Attribute; // PROC_THREAD_ATTRIBUTE_XXX,参见MSDN中UpdateProcThreadAttribute的说明 3 SIZE_T Size; // Value的大小 4 ULONG_PTR Value; // 保存4字节数据(比如一个Handle)或数据指针 5 ULONG Unknown; // 总是0,可能是用来返回数据给调用者 6 } PROC_THREAD_ATTRIBUTE_ENTRY, *PPROC_THREAD_ATTRIBUTE_ENTRY; 7 8 typedef struct _NT_PROC_THREAD_ATTRIBUTE_LIST { 9 ULONG Length; // 结构总大小 10 NT_PROC_THREAD_ATTRIBUTE_ENTRY Entry[1]; 11 } NT_PROC_THREAD_ATTRIBUTE_LIST, *PNT_PROC_THREAD_ATTRIBUTE_LIST; 12 NTSTATUS NtCreateUserProcess( 13 OUT PHANDLE ProcessHandle, 14 OUT PHANDLE ThreadHandle, 15 IN ACCESS_MASK ProcessDesiredAccess, 16 IN ACCESS_MASK ThreadDesiredAccess, 17 IN POBJECT_ATTRIBUTES ProcessObjectAttributes OPTIONAL, 18 IN POBJECT_ATTRIBUTES ThreadObjectAttributes OPTIONAL, 19 IN ULONG CreateProcessFlags, 20 IN ULONG CreateThreadFlags, 21 IN PRTL_USER_PROCESS_PARAMETERS ProcessParameters, 22 IN PVOID Parameter9, 23 IN PNT_PROC_THREAD_ATTRIBUTE_LIST AttributeList 24 );
不过只能作为统计创建进程数,不能在应用层上得到创建的进程信息(INVALID_HANDLE_VALUE)。