逆向工程核心原理读书笔记-API钩取之隐藏进程(一)

来源:互联网 发布:xp磁盘碎片整理软件 编辑:程序博客网 时间:2024/06/05 02:19

简评:

整体看了下代码,其实就是应用层的inline hook, 钩子勾住ntdll.dll里面的ZwQuerySystemInformation函数, xp环境测试成功了,win7测试失败了,不知道怎么回事,有时间再测试一下。为什么要给所有进程进行dll注入?因为除了taskmgr.exe进程外可能会有其他的进程也会枚举进程(比如自己写了一个枚举进程的程序),为了使这些未知的程序也看不到隐藏进程,对所有进程下的ntdll.dll里面的ZwQuerySystemInformation函数进行了hook。


我们通过一个示例来练习在ProcExp.exe和taskmgr.exe中隐藏进程。钩取前后的原理图如下所示。



下面我们先测试一下代码。关于代码的使用很简单,就不再多说了。

我们来分析一下源代码,看看是怎么实现的。
HideProc.cpp

[cpp] view plain copy
  1. #include "windows.h"  
  2. #include "stdio.h"  
  3. #include "tlhelp32.h"  
  4. #include "tchar.h"  
  5.   
  6. typedef void (*PFN_SetProcName)(LPCTSTR szProcName);  
  7. enum {INJECTION_MODE = 0, EJECTION_MODE};  
  8.   
  9. BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)   
  10. {  
  11.     TOKEN_PRIVILEGES tp;  
  12.     HANDLE hToken;  
  13.     LUID luid;  
  14.   
  15.     if( !OpenProcessToken(GetCurrentProcess(),  
  16.                           TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,   
  17.                           &hToken) )  
  18.     {  
  19.         printf("OpenProcessToken error: %u\n", GetLastError());  
  20.         return FALSE;  
  21.     }  
  22.   
  23.     if( !LookupPrivilegeValue(NULL,            // lookup privilege on local system  
  24.                               lpszPrivilege,   // privilege to lookup   
  25.                               &luid) )        // receives LUID of privilege  
  26.     {  
  27.         printf("LookupPrivilegeValue error: %u\n", GetLastError() );   
  28.         return FALSE;   
  29.     }  
  30.   
  31.     tp.PrivilegeCount = 1;  
  32.     tp.Privileges[0].Luid = luid;  
  33.     if( bEnablePrivilege )  
  34.         tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;  
  35.     else  
  36.         tp.Privileges[0].Attributes = 0;  
  37.   
  38.     // Enable the privilege or disable all privileges.  
  39.     if( !AdjustTokenPrivileges(hToken,   
  40.                                FALSE,   
  41.                                &tp,   
  42.                                sizeof(TOKEN_PRIVILEGES),   
  43.                                (PTOKEN_PRIVILEGES) NULL,   
  44.                                (PDWORD) NULL) )  
  45.     {   
  46.         printf("AdjustTokenPrivileges error: %u\n", GetLastError() );   
  47.         return FALSE;   
  48.     }   
  49.   
  50.     if( GetLastError() == ERROR_NOT_ALL_ASSIGNED )  
  51.     {  
  52.         printf("The token does not have the specified privilege. \n");  
  53.         return FALSE;  
  54.     }   
  55.   
  56.     return TRUE;  
  57. }  
  58.   
  59. BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath)  
  60. {  
  61.     HANDLE                  hProcess, hThread;  
  62.     LPVOID                  pRemoteBuf;  
  63.     DWORD                   dwBufSize = (DWORD)(_tcslen(szDllPath) + 1) * sizeof(TCHAR);  
  64.     LPTHREAD_START_ROUTINE  pThreadProc;  
  65.   
  66.     if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) )  
  67.     {  
  68.         printf("OpenProcess(%d) failed!!!\n", dwPID);  
  69.         return FALSE;  
  70.     }  
  71.   
  72.     pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize,   
  73.                                 MEM_COMMIT, PAGE_READWRITE);  
  74.   
  75.     WriteProcessMemory(hProcess, pRemoteBuf,   
  76.                        (LPVOID)szDllPath, dwBufSize, NULL);  
  77.   
  78.     pThreadProc = (LPTHREAD_START_ROUTINE)  
  79.                   GetProcAddress(GetModuleHandle(L"kernel32.dll"),   
  80.                                  "LoadLibraryW");  
  81.     hThread = CreateRemoteThread(hProcess, NULL, 0,   
  82.                                  pThreadProc, pRemoteBuf, 0, NULL);  
  83.     WaitForSingleObject(hThread, INFINITE);   
  84.   
  85.     VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE);  
  86.   
  87.     CloseHandle(hThread);  
  88.     CloseHandle(hProcess);  
  89.   
  90.     return TRUE;  
  91. }  
  92.   
  93. BOOL EjectDll(DWORD dwPID, LPCTSTR szDllPath)  
  94. {  
  95.     BOOL                    bMore = FALSE, bFound = FALSE;  
  96.     HANDLE                  hSnapshot, hProcess, hThread;  
  97.     MODULEENTRY32           me = { sizeof(me) };  
  98.     LPTHREAD_START_ROUTINE  pThreadProc;  
  99.   
  100.     if( INVALID_HANDLE_VALUE ==   
  101.         (hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID)) )  
  102.         return FALSE;  
  103.   
  104.     bMore = Module32First(hSnapshot, &me);  
  105.     for( ; bMore ; bMore = Module32Next(hSnapshot, &me) )  
  106.     {  
  107.         if( !_tcsicmp(me.szModule, szDllPath) ||   
  108.             !_tcsicmp(me.szExePath, szDllPath) )  
  109.         {  
  110.             bFound = TRUE;  
  111.             break;  
  112.         }  
  113.     }  
  114.   
  115.     if( !bFound )  
  116.     {  
  117.         CloseHandle(hSnapshot);  
  118.         return FALSE;  
  119.     }  
  120.   
  121.     if( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) )  
  122.     {  
  123.         CloseHandle(hSnapshot);  
  124.         return FALSE;  
  125.     }  
  126.   
  127.     pThreadProc = (LPTHREAD_START_ROUTINE)  
  128.                   GetProcAddress(GetModuleHandle(L"kernel32.dll"),   
  129.                                  "FreeLibrary");  
  130.     hThread = CreateRemoteThread(hProcess, NULL, 0,   
  131.                                  pThreadProc, me.modBaseAddr, 0, NULL);  
  132.     WaitForSingleObject(hThread, INFINITE);   
  133.   
  134.     CloseHandle(hThread);  
  135.     CloseHandle(hProcess);  
  136.     CloseHandle(hSnapshot);  
  137.   
  138.     return TRUE;  
  139. }  
  140.   
  141. BOOL InjectAllProcess(int nMode, LPCTSTR szDllPath)  
  142. {  
  143.     DWORD                   dwPID = 0;  
  144.     HANDLE                  hSnapShot = INVALID_HANDLE_VALUE;  
  145.     PROCESSENTRY32          pe;  
  146.   
  147.     // Get the snapshot of the system  
  148.     pe.dwSize = sizeof( PROCESSENTRY32 );  
  149.     hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPALL, NULL );  
  150.   
  151.     // find process  
  152.     Process32First(hSnapShot, &pe);  
  153.     do  
  154.     {  
  155.         dwPID = pe.th32ProcessID;  
  156.   
  157.         // 鉴于系统安全性的考虑  
  158.         // 对于PID小于100的系统进程  
  159.         // 不执行DLL注入操作  
  160.         if( dwPID < 100 )  
  161.             continue;  
  162.   
  163.         if( nMode == INJECTION_MODE )  
  164.             InjectDll(dwPID, szDllPath);  
  165.         else  
  166.             EjectDll(dwPID, szDllPath);  
  167.     }  
  168.     while( Process32Next(hSnapShot, &pe) );  
  169.   
  170.     CloseHandle(hSnapShot);  
  171.   
  172.     return TRUE;  
  173. }  
  174.   
  175. int _tmain(int argc, TCHAR* argv[])  
  176. {  
  177.     int                     nMode = INJECTION_MODE;  
  178.     HMODULE                 hLib = NULL;  
  179.     PFN_SetProcName         SetProcName = NULL;  
  180.   
  181.     if( argc != 4 )  
  182.     {  
  183.         printf("\n Usage  : HideProc.exe <-hide|-show> "\  
  184.                "<process name> <dll path>\n\n");  
  185.         return 1;  
  186.     }  
  187.   
  188.     // change privilege  
  189.     SetPrivilege(SE_DEBUG_NAME, TRUE);  
  190.   
  191.     // load library  
  192.     hLib = LoadLibrary(argv[3]);  
  193.   
  194.     // set process name to hide  
  195.     SetProcName = (PFN_SetProcName)GetProcAddress(hLib, "SetProcName");  
  196.     SetProcName(argv[2]);  
  197.   
  198.     // Inject(Eject) Dll to all process  
  199.     if( !_tcsicmp(argv[1], L"-show") )  
  200.         nMode = EJECTION_MODE;  
  201.   
  202.     InjectAllProcess(nMode, argv[3]);  
  203.   
  204.     // free library  
  205.     FreeLibrary(hLib);  
  206.   
  207.     return 0;  
  208. }     

首先通过SetPrivilege函数调用AdjustTokenPrivileges提升权限,然后在InjectAllProcess中使用CreateToolhelp32Snapshot获取系统中运行的所有进程的列表,使用Process32First与Process32Next将获得的进程信息存放到PROCESSENTRY32结构体变量pe中,进而获取进程的PID。获取了进程的PID后,要根据所用的命令选项来选择调用InjectDll函数还是EjectDll函数。当某进程的PID小于100时,鉴于系统安全性的考虑,忽略对它的操作。
下面详细讲解Stealth.dll的源代码(stealth.cpp)。
首先看导出函数SetProcName。先创建名为.SHARE的共享内存节区,然后创建g_szProcName缓冲区,最后再由导出函数SetProcName将要隐藏的进程名称保存到g_szProcName中。

[cpp] view plain copy
  1. // global variable (in sharing memory)  
  2. #pragma comment(linker, "/SECTION:.SHARE,RWS")  
  3. #pragma data_seg(".SHARE")  
  4.     TCHAR g_szProcName[MAX_PATH] = {0,};  
  5. #pragma data_seg()  
  6.   
  7. // export function  
  8. #ifdef __cplusplus  
  9. extern "C" {  
  10. #endif  
  11. __declspec(dllexportvoid SetProcName(LPCTSTR szProcName)  
  12. {  
  13.     _tcscpy_s(g_szProcName, szProcName);  
  14. }  
  15. #ifdef __cplusplus  
  16. }  
  17. #endif  
下面看DllMain函数。首先比较字符串,若进程名为HideProc.exe则不钩取API。发生DLL_PROCESS_ATTACH事件时,调用hook_by_code函数钩取API;发生DLL_PROCESS_DETACH事件时,调用unhook_by_code函数取消API钩取。
[cpp] view plain copy
  1. BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)  
  2. {  
  3.     char            szCurProc[MAX_PATH] = {0,};  
  4.     char            *p = NULL;  
  5.   
  6.     // #1. 异常处理  
  7.     // 若当前进程为HookProc.exe则终止,不进行钩取操作  
  8.     GetModuleFileNameA(NULL, szCurProc, MAX_PATH);  
  9.     p = strrchr(szCurProc, '\\');  
  10.     if( (p != NULL) && !_stricmp(p+1, "HideProc.exe") )  
  11.         return TRUE;  
  12.   
  13.     switch( fdwReason )  
  14.     {  
  15.         // #2. API Hooking  
  16.         case DLL_PROCESS_ATTACH :   
  17.         hook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION,   
  18.                      (PROC)NewZwQuerySystemInformation, g_pOrgBytes);  
  19.         break;  
  20.   
  21.         // #3. API Unhooking   
  22.         case DLL_PROCESS_DETACH :  
  23.         unhook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION,   
  24.                        g_pOrgBytes);  
  25.         break;  
  26.     }  
  27.   
  28.     return TRUE;  
  29. }  
接下来是hook_by_code函数,它通过修改代码实现API钩取操作。JMP指令的实际形式为E9 XXXXXXXX,XXXXXXXX=要跳转的地址-当前指令地址-当前指令长度(5)。
[cpp] view plain copy
  1. BOOL hook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PROC pfnNew, PBYTE pOrgBytes)  
  2. {  
  3.     FARPROC pfnOrg;  
  4.     DWORD dwOldProtect, dwAddress;  
  5.     BYTE pBuf[5] = {0xE9, 0, };  
  6.     PBYTE pByte;  
  7.   
  8.     // 获取要钩取的API地址  
  9.     pfnOrg = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);  
  10.     pByte = (PBYTE)pfnOrg;  
  11.   
  12.     // 若已经被钩取则返回FALSE  
  13.     if( pByte[0] == 0xE9 )  
  14.         return FALSE;  
  15.   
  16.     // 向内存添加写属性  
  17.     VirtualProtect((LPVOID)pfnOrg, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);  
  18.   
  19.     // 备份原有代码(5字节)  
  20.     memcpy(pOrgBytes, pfnOrg, 5);  
  21.   
  22.     // 计算JMP地址 (E9 XXXX)  
  23.     // => XXXX = pfnNew - pfnOrg - 5  
  24.     dwAddress = (DWORD)pfnNew - (DWORD)pfnOrg - 5;  
  25.     memcpy(&pBuf[1], &dwAddress, 4);  
  26.   
  27.     // Hook:修改5 byte(JMP XXXX)  
  28.     memcpy(pfnOrg, pBuf, 5);  
  29.   
  30.     // 恢复内存属性  
  31.     VirtualProtect((LPVOID)pfnOrg, 5, dwOldProtect, &dwOldProtect);  
  32.       
  33.     return TRUE;  
  34. }  
unhook_by_code函数是用来取消钩取的函数,原理与hook_by_code函数类似。
[cpp] view plain copy
  1. BOOL unhook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PBYTE pOrgBytes)  
  2. {  
  3.     FARPROC pFunc;  
  4.     DWORD dwOldProtect;  
  5.     PBYTE pByte;  
  6.   
  7.     // 获取API地址  
  8.     pFunc = GetProcAddress(GetModuleHandleA(szDllName), szFuncName);  
  9.     pByte = (PBYTE)pFunc;  
  10.   
  11.     // 若已经脱钩则返回FALSE  
  12.     if( pByte[0] != 0xE9 )  
  13.         return FALSE;  
  14.   
  15.     // 向内存添加写属性  
  16.     VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);  
  17.   
  18.     // Unhook  
  19.     memcpy(pFunc, pOrgBytes, 5);  
  20.   
  21.     // 恢复内存属性  
  22.     VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect);  
  23.   
  24.     return TRUE;  
  25. }  
最后分析钩取函数NewZwQuerySystemInformation。隐藏某进程之前,先要查找与之对应的链表成员,然后断开其与链表的链接。
[cpp] view plain copy
  1. NTSTATUS WINAPI NewZwQuerySystemInformation(  
  2.                 SYSTEM_INFORMATION_CLASS SystemInformationClass,   
  3.                 PVOID SystemInformation,   
  4.                 ULONG SystemInformationLength,   
  5.                 PULONG ReturnLength)  
  6. {  
  7.     NTSTATUS status;  
  8.     FARPROC pFunc;  
  9.     PSYSTEM_PROCESS_INFORMATION pCur, pPrev;  
  10.     char szProcName[MAX_PATH] = {0,};  
  11.       
  12.     // 开始前先脱钩  
  13.     unhook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION, g_pOrgBytes);  
  14.   
  15.     // 调用原始API  
  16.     pFunc = GetProcAddress(GetModuleHandleA(DEF_NTDLL),   
  17.                            DEF_ZWQUERYSYSTEMINFORMATION);  
  18.     status = ((PFZWQUERYSYSTEMINFORMATION)pFunc)  
  19.               (SystemInformationClass, SystemInformation,   
  20.               SystemInformationLength, ReturnLength);  
  21.   
  22.     if( status != STATUS_SUCCESS )  
  23.         goto __NTQUERYSYSTEMINFORMATION_END;  
  24.   
  25.     // 针对SystemProcessInformation类型操作  
  26.     if( SystemInformationClass == SystemProcessInformation )  
  27.     {  
  28.         // SYSTEM_PROCESS_INFORMATION类型转换  
  29.         // pCur是单向链表的头  
  30.         pCur = (PSYSTEM_PROCESS_INFORMATION)SystemInformation;  
  31.   
  32.         while(TRUE)  
  33.         {  
  34.             // 比较进程名称  
  35.             // g_szProcName为要隐藏的进程名称  
  36.             // (=> SetProcName()设置)  
  37.             if(pCur->Reserved2[1] != NULL)  
  38.             {  
  39.                 if(!_tcsicmp((PWSTR)pCur->Reserved2[1], g_szProcName))  
  40.                 {  
  41.                     // 从链表中删除隐藏进程的节点  
  42.                     if(pCur->NextEntryOffset == 0)  
  43.                         pPrev->NextEntryOffset = 0;  
  44.                     else  
  45.                         pPrev->NextEntryOffset += pCur->NextEntryOffset;  
  46.                 }  
  47.                 else          
  48.                     pPrev = pCur;  
  49.             }  
  50.   
  51.             if(pCur->NextEntryOffset == 0)  
  52.                 break;  
  53.   
  54.             // 链表的下一项  
  55.             pCur = (PSYSTEM_PROCESS_INFORMATION)  
  56.                     ((ULONG)pCur + pCur->NextEntryOffset);  
  57.         }  
  58.     }  
  59.   
  60. __NTQUERYSYSTEMINFORMATION_END:  
  61.   
  62.     // 函数终止前再次执行API钩取操作,为下次调用准备  
  63.     hook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION,   
  64.                  (PROC)NewZwQuerySystemInformation, g_pOrgBytes);  
  65.   
  66.     return status;  
  67. }  
完整的代码如下。
[cpp] view plain copy
  1. #include "windows.h"  
  2. #include "tchar.h"  
  3.   
  4. #define STATUS_SUCCESS                      (0x00000000L)   
  5.   
  6. typedef LONG NTSTATUS;  
  7.   
  8. typedef enum _SYSTEM_INFORMATION_CLASS {  
  9.     SystemBasicInformation = 0,  
  10.     SystemPerformanceInformation = 2,  
  11.     SystemTimeOfDayInformation = 3,  
  12.     SystemProcessInformation = 5,  
  13.     SystemProcessorPerformanceInformation = 8,  
  14.     SystemInterruptInformation = 23,  
  15.     SystemExceptionInformation = 33,  
  16.     SystemRegistryQuotaInformation = 37,  
  17.     SystemLookasideInformation = 45  
  18. } SYSTEM_INFORMATION_CLASS;  
  19.   
  20. typedef struct _SYSTEM_PROCESS_INFORMATION {  
  21.     ULONG NextEntryOffset;  
  22.     ULONG NumberOfThreads;  
  23.     BYTE Reserved1[48];  
  24.     PVOID Reserved2[3];  
  25.     HANDLE UniqueProcessId;  
  26.     PVOID Reserved3;  
  27.     ULONG HandleCount;  
  28.     BYTE Reserved4[4];  
  29.     PVOID Reserved5[11];  
  30.     SIZE_T PeakPagefileUsage;  
  31.     SIZE_T PrivatePageCount;  
  32.     LARGE_INTEGER Reserved6[6];  
  33. } SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;  
  34.   
  35. typedef NTSTATUS (WINAPI *PFZWQUERYSYSTEMINFORMATION)  
  36.                  (SYSTEM_INFORMATION_CLASS SystemInformationClass,   
  37.                   PVOID SystemInformation,   
  38.                   ULONG SystemInformationLength,   
  39.                   PULONG ReturnLength);  
  40.   
  41. #define DEF_NTDLL                       ("ntdll.dll")  
  42. #define DEF_ZWQUERYSYSTEMINFORMATION    ("ZwQuerySystemInformation")  
  43.   
  44.   
  45. // global variable (in sharing memory)  
  46. #pragma comment(linker, "/SECTION:.SHARE,RWS")  
  47. #pragma data_seg(".SHARE")  
  48.     TCHAR g_szProcName[MAX_PATH] = {0,};  
  49. #pragma data_seg()  
  50.   
  51. // global variable  
  52. BYTE g_pOrgBytes[5] = {0,};  
  53.   
  54.   
  55. BOOL hook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PROC pfnNew, PBYTE pOrgBytes)  
  56. {  
  57.     FARPROC pfnOrg;  
  58.     DWORD dwOldProtect, dwAddress;  
  59.     BYTE pBuf[5] = {0xE9, 0, };  
  60.     PBYTE pByte;  
  61.   
  62.     // 获取要钩取的API地址  
  63.     pfnOrg = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);  
  64.     pByte = (PBYTE)pfnOrg;  
  65.   
  66.     // 若已经被钩取则返回FALSE  
  67.     if( pByte[0] == 0xE9 )  
  68.         return FALSE;  
  69.   
  70.     // 向内存添加写属性  
  71.     VirtualProtect((LPVOID)pfnOrg, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);  
  72.   
  73.     // 备份原有代码(5字节)  
  74.     memcpy(pOrgBytes, pfnOrg, 5);  
  75.   
  76.     // 计算JMP地址 (E9 XXXX)  
  77.     // => XXXX = pfnNew - pfnOrg - 5  
  78.     dwAddress = (DWORD)pfnNew - (DWORD)pfnOrg - 5;  
  79.     memcpy(&pBuf[1], &dwAddress, 4);  
  80.   
  81.     // Hook  
  82.     memcpy(pfnOrg, pBuf, 5);  
  83.   
  84.     // 恢复内存属性  
  85.     VirtualProtect((LPVOID)pfnOrg, 5, dwOldProtect, &dwOldProtect);  
  86.       
  87.     return TRUE;  
  88. }  
  89.   
  90.   
  91. BOOL unhook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PBYTE pOrgBytes)  
  92. {  
  93.     FARPROC pFunc;  
  94.     DWORD dwOldProtect;  
  95.     PBYTE pByte;  
  96.   
  97.     // 获取API地址  
  98.     pFunc = GetProcAddress(GetModuleHandleA(szDllName), szFuncName);  
  99.     pByte = (PBYTE)pFunc;  
  100.   
  101.     // 若已经脱钩则返回FALSE  
  102.     if( pByte[0] != 0xE9 )  
  103.         return FALSE;  
  104.   
  105.     // 向内存添加写属性  
  106.     VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);  
  107.   
  108.     // Unhook  
  109.     memcpy(pFunc, pOrgBytes, 5);  
  110.   
  111.     // 恢复内存属性  
  112.     VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect);  
  113.   
  114.     return TRUE;  
  115. }  
  116.   
  117.   
  118. NTSTATUS WINAPI NewZwQuerySystemInformation(  
  119.                 SYSTEM_INFORMATION_CLASS SystemInformationClass,   
  120.                 PVOID SystemInformation,   
  121.                 ULONG SystemInformationLength,   
  122.                 PULONG ReturnLength)  
  123. {  
  124.     NTSTATUS status;  
  125.     FARPROC pFunc;  
  126.     PSYSTEM_PROCESS_INFORMATION pCur, pPrev;  
  127.     char szProcName[MAX_PATH] = {0,};  
  128.       
  129.     // 开始前先脱钩  
  130.     unhook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION, g_pOrgBytes);  
  131.   
  132.     // 调用原始API  
  133.     pFunc = GetProcAddress(GetModuleHandleA(DEF_NTDLL),   
  134.                            DEF_ZWQUERYSYSTEMINFORMATION);  
  135.     status = ((PFZWQUERYSYSTEMINFORMATION)pFunc)  
  136.               (SystemInformationClass, SystemInformation,   
  137.               SystemInformationLength, ReturnLength);  
  138.   
  139.     if( status != STATUS_SUCCESS )  
  140.         goto __NTQUERYSYSTEMINFORMATION_END;  
  141.   
  142.     // 针对SystemProcessInformation类型操作  
  143.     if( SystemInformationClass == SystemProcessInformation )  
  144.     {  
  145.         // SYSTEM_PROCESS_INFORMATION类型转换  
  146.         // pCur是单向链表的头  
  147.         pCur = (PSYSTEM_PROCESS_INFORMATION)SystemInformation;  
  148.   
  149.         while(TRUE)  
  150.         {  
  151.             // 比较进程名称  
  152.             // g_szProcName为要隐藏的进程名称  
  153.             // (=> SetProcName()设置)  
  154.             if(pCur->Reserved2[1] != NULL)  
  155.             {  
  156.                 if(!_tcsicmp((PWSTR)pCur->Reserved2[1], g_szProcName))  
  157.                 {  
  158.                     // 从链表中删除隐藏进程的节点  
  159.                     if(pCur->NextEntryOffset == 0)  
  160.                         pPrev->NextEntryOffset = 0;  
  161.                     else  
  162.                         pPrev->NextEntryOffset += pCur->NextEntryOffset;  
  163.                 }  
  164.                 else          
  165.                     pPrev = pCur;  
  166.             }  
  167.   
  168.             if(pCur->NextEntryOffset == 0)  
  169.                 break;  
  170.   
  171.             // 链表的下一项  
  172.             pCur = (PSYSTEM_PROCESS_INFORMATION)  
  173.                     ((ULONG)pCur + pCur->NextEntryOffset);  
  174.         }  
  175.     }  
  176.   
  177. __NTQUERYSYSTEMINFORMATION_END:  
  178.   
  179.     // 函数终止前再次执行API钩取操作,为下次调用准备  
  180.     hook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION,   
  181.                  (PROC)NewZwQuerySystemInformation, g_pOrgBytes);  
  182.   
  183.     return status;  
  184. }  
  185.   
  186.   
  187. BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)  
  188. {  
  189.     char            szCurProc[MAX_PATH] = {0,};  
  190.     char            *p = NULL;  
  191.   
  192.     // #1. 异常处理  
  193.     // 若当前进程为HookProc.exe则终止,不进行钩取操作  
  194.     GetModuleFileNameA(NULL, szCurProc, MAX_PATH);  
  195.     p = strrchr(szCurProc, '\\');  
  196.     if( (p != NULL) && !_stricmp(p+1, "HideProc.exe") )  
  197.         return TRUE;  
  198.   
  199.     switch( fdwReason )  
  200.     {  
  201.         // #2. API Hooking  
  202.         case DLL_PROCESS_ATTACH :   
  203.         hook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION,   
  204.                      (PROC)NewZwQuerySystemInformation, g_pOrgBytes);  
  205.         break;  
  206.   
  207.         // #3. API Unhooking   
  208.         case DLL_PROCESS_DETACH :  
  209.         unhook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION,   
  210.                        g_pOrgBytes);  
  211.         break;  
  212.     }  
  213.   
  214.     return TRUE;  
  215. }  
  216.   
  217.   
  218. #ifdef __cplusplus  
  219. extern "C" {  
  220. #endif  
  221. __declspec(dllexportvoid SetProcName(LPCTSTR szProcName)  
  222. {  
  223.     _tcscpy_s(g_szProcName, szProcName);  
  224. }  
  225. #ifdef __cplusplus  
  226. }  
  227. #endif  
阅读全文
0 0
原创粉丝点击