1. 程式人生 > >安全之路 —— C++實現程序守護

安全之路 —— C++實現程序守護

簡介

所謂程序守護,就是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; }