1.简介
通过注入一个远程线程到explorer.exe中,该线程对要被保护的进程进行监控,如果发现该进程退出了就重新启动之.
远程代码注入实现:http://www.cnblogs.com/freesec/p/6554518.html
2.测试代码
// lives.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <TlHelp32.h> #include <locale.h> char exepath[MAX_PATH]; //声明需要用到的函数 typedef HMODULE(WINAPI *lpLoadLibraryA)(char* filename); typedef FARPROC(WINAPI *lpGetProcAddress)(HMODULE hModule, char* funcName); typedef UINT( WINAPI* lpWinExec)( IN LPCSTR lpCmdLine, IN UINT uCmdShow ); typedef DWORD( WINAPI* lpWaitForSingleObject)( IN HANDLE hHandle, IN DWORD dwMilliseconds ); typedef HANDLE( WINAPI* lpOpenProcess)( IN DWORD dwDesiredAccess, IN BOOL bInheritHandle, IN DWORD dwProcessId ); typedef struct _thread_param { lpLoadLibraryA loadFunc; lpGetProcAddress GetPFunc; DWORD PID;//被保护的进程的进程id //char mutex[8];//保证只被注入一次 //保存所有参数 //在被注入进程中需要调用的函数:LoadLibrary,GetProcAddress,WaitForSimpleObject,WinExec //因此需要参数:被保护的进程路径,kernel32.dll ,WaitForSingleObject,WinExec, //OpenProcess(这3个作为GetProcAddress的参数) 共5个参数 char data[5][100]; }thread_param; DWORD WINAPI threadProc(LPVOID param) { thread_param* tparam = (thread_param*)param; HMODULE hd=tparam->loadFunc(tparam->data[0]);//data的第一个参数是kernel32.dll lpWaitForSingleObject wfso=(lpWaitForSingleObject)tparam->GetPFunc(hd,tparam->data[2]); lpWinExec we=(lpWinExec)tparam->GetPFunc(hd,tparam->data[3]); lpOpenProcess op=(lpOpenProcess)tparam->GetPFunc(hd,tparam->data[4]); DWORD pid=tparam->PID; HANDLE hProcess=op(PROCESS_ALL_ACCESS,0,pid); wfso(hProcess,INFINITE); we(tparam->data[1],SW_SHOW); return 0; } DWORD codeInject(DWORD pid) { HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid); if (hProcess==0||hProcess==INVALID_HANDLE_VALUE) { return 0; } thread_param param = { 0 }; param.loadFunc = (lpLoadLibraryA)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryA"); param.GetPFunc = (lpGetProcAddress)GetProcAddress(GetModuleHandleA("kernel32.dll"), "GetProcAddress"); memcpy(¶m.data[0], "kernel32.dll", 13); GetModuleFileNameA(0,exepath,MAX_PATH); memcpy(¶m.data[1], exepath, strlen(exepath)+1); memcpy(¶m.data[2], "WaitForSingleObject", 20); memcpy(¶m.data[3], "WinExec", 8); memcpy(¶m.data[4],"OpenProcess",12); param.PID=GetCurrentProcessId(); //DWORD codesize = (DWORD)codeInject - (DWORD)threadProc; //计算线程函数的代码大小 LPVOID database = VirtualAllocEx(hProcess, 0, sizeof(thread_param), MEM_COMMIT, PAGE_READWRITE); DWORD written; HANDLE hThread; if (database==0) { CloseHandle(hProcess); return 0; } WriteProcessMemory(hProcess, database, ¶m, sizeof(thread_param), &written); LPVOID codebase = VirtualAllocEx(hProcess, 0, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (codebase == 0) { VirtualFreeEx(hProcess, database, sizeof(thread_param), MEM_FREE); CloseHandle(hProcess); return 0; } WriteProcessMemory(hProcess, codebase, &threadProc, 0x1000, &written); if ((hThread=CreateRemoteThread(hProcess, 0, 0, (LPTHREAD_START_ROUTINE)codebase, database, 0, 0))!=0) { VirtualFreeEx(hProcess, database, sizeof(thread_param), MEM_FREE); VirtualFreeEx(hProcess, codebase, 0x1000, MEM_FREE); CloseHandle(hThread); CloseHandle(hProcess); return 1; } VirtualFreeEx(hProcess, database, sizeof(thread_param), MEM_FREE); VirtualFreeEx(hProcess, codebase, 0x1000, MEM_FREE); CloseHandle(hProcess); return 0; } DWORD getTargetProcessId() { PROCESSENTRY32W pe32; pe32.dwSize=sizeof(PROCESSENTRY32W); HANDLE snap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); DWORD result=Process32FirstW(snap,&pe32); if(result==0) { return 0; } do { if (lstrcmpW(pe32.szExeFile,L"explorer.exe")==0) { CloseHandle(snap); return pe32.th32ProcessID; } } while (Process32NextW(snap,&pe32)); CloseHandle(snap); return 0; } int wmain(int argc, WCHAR* argv[]) { setlocale(LC_ALL,"chs"); DWORD pid; pid=getTargetProcessId(); if (pid==0) { printf("getTargetProcessId error code is %d\n",GetLastError()); return 0; } codeInject(pid); while(1) { MessageBoxA(0,"kill me!","kill me!",0); Sleep(1000); } return 0; }