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(&param.data[0], "kernel32.dll", 13);
    GetModuleFileNameA(0,exepath,MAX_PATH);
    memcpy(&param.data[1], exepath, strlen(exepath)+1);
    memcpy(&param.data[2], "WaitForSingleObject", 20);
    memcpy(&param.data[3], "WinExec", 8);
    memcpy(&param.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, &param, 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;
}