37.添加简易的调试功能

上一个内容:36.远程注入到入口点注入

以 36.远程注入到入口点注入 它的代码为基础进行修改

效果图:

CWndINJ.cpp文件中修改的函数OnNMDblclkList1

void CWndINJ::OnNMDblclkList1(NMHDR* pNMHDR, LRESULT* pResult)
{
    LPNMITEMACTIVATE pNMItemActivate = reinterpret_cast<LPNMITEMACTIVATE>(pNMHDR);
    // TODO: 在此添加控件通知处理程序代码
    *pResult = 0;
    int index = pNMItemActivate->iItem;
    if (index < 0)return;

    CString GamePath = ExeLst.GetItemText(index, 2);
    CString GameExe = ExeLst.GetItemText(index, 1);
    CString GameCmds = ExeLst.GetItemText(index, 3);
    CString GameDlls = ExeLst.GetItemText(index, 4);

    // 用来指定创建时进程的主窗口的窗口工作站、桌面、标准句柄和外观。
    // STARTUPINFO si{};
    // si.cb = sizeof(si);
    PROCESS_INFORMATION prinfo{};
    m_INJCET.StartProcess(GameExe, GamePath, GameCmds.GetBuffer(), &prinfo);
    
    PROCESS_INFORMATION odinfo{};
    //F:\其它\OllyDbg\Ollydbg.exe - p 4760
    CString dbgExe, dbgPath, dbgCmds;
    dbgExe = L"F:\\其它\\OllyDbg\\Ollydbg.exe";
    dbgPath = L"F:\\其它\\OllyDbg\\";
    dbgCmds.Format(L"%s -p %d", dbgExe, prinfo.dwProcessId);
    m_INJCET.StartProcess(dbgExe, dbgPath, dbgCmds.GetBuffer(), &odinfo, false);

    //STARTUPINFO si{};
    //si.cb = sizeof(si);
    //CreateProcess(dbgExe,
    //    dbgExe.GetBuffer(),
    //    NULL, NULL,
    //    false,
    //    // 新进程的主线程处于挂起状态创建,在调用 ResumeThread 函数之前不会运行。
    //    0,
    //    NULL,
    //    dbgPath,
    //    &si,
    //    &odinfo
    //);


    m_INJCET.CreateRemoteData(prinfo.hProcess, GameExe, L"F:\\代码存放地\\c\\GAMEHACKER2\\Release\\Dlls.dll");
 

    ResumeThread(prinfo.hThread);
    //ResumeThread(odinfo.hThread);
 //m_INJCET.CodeRemoteData(&_data);
    
    /**
        CreateProcess(GameExe,
        GameCmds.GetBuffer(),
        NULL,NULL,
        FALSE,
        // 新进程的主线程处于挂起状态创建,在调用 ResumeThread 函数之前不会运行。
        CREATE_SUSPENDED,
        NULL,
        GamePath,
        &si,
        &prinfo
        );
    */

    /** 方式一调用api
        CStringA GameExeA;
        GameExeA = GameExe;
        PLOADED_IMAGE image =  ImageLoad(GameExeA, NULL);
        DWORD dEntryPoint = image->FileHeader->OptionalHeader.AddressOfEntryPoint;
        CString wTxt;
        wTxt.Format(L"%X", dEntryPoint);
        AfxMessageBox(wTxt);
        ImageUnload(image)
    */

    /** 方式二(要在32位环境下运行)
    void* image = _imageload(GameExe.GetBuffer());
    IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)image;
    unsigned PEAddress =  dosHeader->e_lfanew + (unsigned)image;
    IMAGE_NT_HEADERS* ntHeader = (IMAGE_NT_HEADERS*)PEAddress;
    DWORD dEntryPoint = ntHeader->OptionalHeader.AddressOfEntryPoint;
    CString wTxt;
    wTxt.Format(L"%X", dEntryPoint);
    AfxMessageBox(wTxt);
    _unloadimage(image);
    */
    //LPVOID adrRemote = VirtualAllocEx(prinfo.hProcess, 0, 0x3000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    //SIZE_T lwt;

    //WriteProcessMemory(prinfo.hProcess, adrRemote, INJECTCode, 0x200, &lwt);

    //CString wTxt;
    //wTxt.Format(L"%X", adrRemote);
    //AfxMessageBox(wTxt);
    // 让游戏继续运行
    //m_INJCET.CreateRemoteData(prinfo.hProcess, GameDlls.GetBuffer());
    
}

INJCET.cpp文件中修改的函数 StartProcess、CreateRemoteData

#include "pch.h"
#include "INJCET.h"
#include <fstream>


void _stdcall INJECTCode() {
    unsigned address = 0xCCCCCCCC;
    PREMOTE_DATA p = (PREMOTE_DATA)address;
    p->f_LoadLibrary(p->dllName);
    unsigned dEntry = p->EntryPoint;
    char* entryCode = (char*)p->EntryPoint;

    entryCode[0] = p->oldCode[0];
    entryCode[1] = p->oldCode[1];
    entryCode[2] = p->oldCode[2];
    entryCode[3] = p->oldCode[3];
    entryCode[4] = p->oldCode[4];

    _asm {
        mov eax, dEntry
        jmp eax
    }
}


DWORD _stdcall RemoteThreadProce(PREMOTE_DATA p) {
    unsigned base = p->f_GetModuleHandleA(0);
    DWORD dRet;

    p->EntryPoint += base;
    p->f_VirtualProtect((LPVOID)p->EntryPoint, 0x1000, PAGE_EXECUTE_READWRITE, &dRet);

    char* entryCode = (char*)p->EntryPoint;

    p->oldCode[0] = entryCode[0];
    p->oldCode[1] = entryCode[1];
    p->oldCode[2] = entryCode[2];
    p->oldCode[3] = entryCode[3];
    p->oldCode[4] = entryCode[4];

    int* entryDis = (int*)(p->EntryPoint + 1);

    *entryCode = 0xE9;
    int Distance = p->HOOKFunction - p->EntryPoint - 5;
    entryDis[0] = Distance;



    return 1;
}


BOOL INJCET::StartProcess(const wchar_t* GameExe, const wchar_t* GamePath, wchar_t* GameCmds, PROCESS_INFORMATION* LPinfo, bool Pause)
{
    // 用来指定创建时进程的主窗口的窗口工作站、桌面、标准句柄和外观。
    STARTUPINFO si{};
    si.cb = sizeof(si);

    DWORD s = 0;
    if (Pause)s = CREATE_SUSPENDED;

    CreateProcess(GameExe,
        GameCmds,
        NULL, NULL,
        false,
        // 新进程的主线程处于挂起状态创建,在调用 ResumeThread 函数之前不会运行。
        s,
        NULL,
        GamePath,
        &si,
        LPinfo
    );

    return TRUE;
}


void* INJCET::ImageLoad(const wchar_t* filename) {
    std::ifstream streamReader(filename, std::ios::binary);
    streamReader.seekg(0, std::ios::end);
    unsigned filesize = streamReader.tellg();
    char* _data = new char[filesize];
    streamReader.seekg(0, std::ios::beg);
    streamReader.read(_data, filesize);
    streamReader.close();
    return _data;
}

void INJCET::UnloadImage(void* _data) {
    delete[] _data;
}

DWORD INJCET::GetEntryPoint(const wchar_t* filename)
{
    // 方式二(要在32位环境下运行根据游戏版本选择运行32还是64位的程序)
    void* image = ImageLoad(filename);
    IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)image;
    unsigned PEAddress = dosHeader->e_lfanew + (unsigned)image;
    IMAGE_NT_HEADERS* ntHeader = (IMAGE_NT_HEADERS*)PEAddress;
    DWORD dEntryPoint = ntHeader->OptionalHeader.AddressOfEntryPoint;
    CString wTxt;
    wTxt.Format(L"%X", dEntryPoint);
    AfxMessageBox(wTxt);
    UnloadImage(image);
    return dEntryPoint;
}

BOOL INJCET::CreateRemoteData(HANDLE hProcess, const wchar_t* GameExe, const wchar_t* dllName)
{
    LPVOID adrRemote = VirtualAllocEx(hProcess, 0, 0x3000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    SIZE_T lwt;
    LPVOID adrRemoteData = (LPVOID)((unsigned)adrRemote + 0x2000);
    LPVOID adrRemoteProc= (LPVOID)((unsigned)adrRemote + 0x500);

    _REMOTE_DATA remoteData{};
    remoteData.EntryPoint = GetEntryPoint(GameExe);

    CodeRemoteData(&remoteData, dllName);
    remoteData.HOOKFunction = (unsigned)adrRemote;

    WriteProcessMemory(hProcess, adrRemoteData, &remoteData, sizeof(remoteData), &lwt);
    char _code[0x200];

    memcpy(_code, INJECTCode, sizeof(_code));

    for (int i = 0; i < 0x100; i++) {
        unsigned* pcode = (unsigned*)(&_code[i]);
        if (pcode[0] == 0xCCCCCCCC) {
            pcode[0] = (unsigned)adrRemoteData;
            break;
        }
    }
    
    WriteProcessMemory(hProcess, adrRemote, _code, 0x200, &lwt);

    


    WriteProcessMemory(hProcess, adrRemoteProc, RemoteThreadProce, 0x200, &lwt);

    CString wTxt;
    wTxt.Format(L"%X", adrRemote);
    AfxMessageBox(wTxt);

    DWORD dwThreadId = 0;
    HANDLE remotehdl = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)adrRemoteProc, adrRemoteData, 0, &dwThreadId);
    WaitForSingleObject(remotehdl, INFINITE);
    
    //DWORD dwThreadId = 0;
    //HANDLE remoteHdl = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)adrRemote, NULL, 0, &dwThreadId);
    //WaitForSingleObject(remoteHdl, INFINITE);
    return TRUE;
}

void INJCET::CodeRemoteData(PREMOTE_DATA _data, const wchar_t* dllName)
{
    short lenth;
    // 求长度
    for (lenth = 0; dllName[lenth]; lenth++);


    HMODULE hKernel = LoadLibrary(_T("kernel32.dll"));
    //_data->f_LoadLibrary = (_LoadLibrary)GetProcAddress(hKernel, "LoadLibraryW");
    _data->f_LoadLibrary = (_LoadLibrary)GetProcAddress(hKernel, "LoadLibraryW");
    _data->f_GetModuleHandleA = (_GetModuleHandleA)GetProcAddress(hKernel, "GetModuleHandleA");
    _data->f_VirtualProtect = (_VirtualProtect)GetProcAddress(hKernel, "VirtualProtect");
    //LoadLibraryW

    // wchar两字节拷贝是一字节所以长度要成2
    memcpy(_data->dllName, dllName, (lenth + 1) * 2);

    /*CString  wTxt;
    wTxt.Format(L"%X", _data->f_LoadLibrary);
    AfxMessageBox(wTxt);*/
}

  • 16
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值