内存劫持

  1. 本章内存主要涉及 在 其他程序中 申请/读取/修改 执行内存块
  2. 我们通过劫持目标窗口 回掉函数来 劫持程序的消息

远程线程注入/劫持运行

  1. 函数运行的本质是 函数地址的执行
  2. DLL 中的函数在不同设备上有不同的地址
  3. 每个程序都有DLL导入表格

    1. 表格 属性 :函数标志 函数地址
    2. 在实际程序中(机器码),没有记录函数地址,记录的是函数标志
    3. 程序运行前 系统填充 DLL表
    4. 程序运行时 将函数标志替换成函数地址
  4. 所以我们劫持内存,运行我们插入的代码 要避免使用DLL导入表
  5. CreateRemoteThread 执行的函数的 函数声明是指定的(一个输入,一个返回值)

方案一

  1. 在远程线程中 注入机器码
  2. 机器码中不能有DLL的函数
  3. 机器码中可以有DLL某个函数的函数指针
  4. CreateRemoteThread 远程执行,传输所需DLL的函数指针

方案二

  1. 我们不注入机器码
  2. 我们将 我们自己的函数 封装在DLL中
  3. 我们直接在远程线程中CreateRemoteThread->loadlibrary 加载我们自己的DLL

    1. 注意loadlibrary 的函数 兼容 CreateRemoteThread 所需的函数指针
  4. 这样程序就直接运行我们的DllMain

    void Inject() {
    
    //1. 获取目标进程句柄
    DWORD dwPID = 0;
    HWND hGame = FindWindowA(NULL, "扫雷");

    if (hGame == NULL) {
        return;
    }
    
    GetWindowThreadProcessId(hGame, &dwPID);
    
    HANDLE hGameProcess = OpenProcess(PROCESS_ALL_ACCESS,
        TRUE,
        dwPID);
    if (hGameProcess == NULL || hGameProcess == INVALID_HANDLE_VALUE) {
        return;
    }
    
    //2 在目标进程空间中,开辟一块内存,存放待注入的dll路径
    LPVOID lpAddr = VirtualAllocEx(hGameProcess,
        NULL,
        0x1000,
        MEM_COMMIT,
        PAGE_EXECUTE_READWRITE);
    
    if (lpAddr == NULL) {
        return;
    }
    
    DWORD dwWritedBytes = 0;
    //3 向目标进程的写入注入dll路径
    BOOL bRet = WriteProcessMemory(hGameProcess,
                                    lpAddr,
                                    "Superd.dll",
                                    sizeof("Superd.dll"),
                                    &dwWritedBytes);

    //4 调用远程线程,使用LoadLibraryA,加载目标dll.
    HANDLE hRemoteThread = CreateRemoteThread(hGameProcess,
        NULL,
        0,
        (LPTHREAD_START_ROUTINE)LoadLibraryA,
        lpAddr,
        0,
        NULL);
    
    //5 等待DLL 结束运行
    WaitForSingleObject(hRemoteThread, INFINITE);
    
    DWORD dwExitCode = 0;
    
    //6 获取DLL句柄
    GetExitCodeThread(hRemoteThread, &dwExitCode);
    
    //释放目标进程的注入dll FreeLibrary
    CreateRemoteThread(hGameProcess,
        NULL,
        0,
        (LPTHREAD_START_ROUTINE)FreeLibrary,
        (LPVOID)dwExitCode,
        0,
        NULL);
    }

申请内存空间

  1. 参见 进程间通信->virtualallocex
  2. 注意权限 申请的内存块权限PAGE_EXECUTE_READWRITE

修改_读取 内存数据

重要函数

    FindWindow                  //根据 窗口class 获取 窗口句柄
    getwindowthreadprocessid    //根据 窗口句柄  获取 进程句柄
    OpenProcess                 //利用 进程句柄  打开 内存句柄
    
    ReadProcessMemory   //读取进程内存
    WriteProcessMemory  //向进程写入内存

实例

    void change_to_god(){
    
    DWORD dwPID = 0;
    
    //根据 窗口名称/窗口class名称 获取 窗口句柄 ,这里是根据 class名称
    HWND hGame = FindWindowA(NULL, "摿孭");
    
    //根据 窗口句柄 获取 进程句柄
    GetWindowThreadProcessId(hGame, &dwPID);
    
    //根据 进程句柄 获取 内存句柄
    HANDLE hGameProcess = OpenProcess(PROCESS_ALL_ACCESS,
        FALSE,
        dwPID);
        
    //准备写入的数据
    BYTE btCode = 0xEB;
    //接受 一共写了多少数据
    DWORD dwWritedBytes = 0;
    
    //修改数据
    BOOL bRet = WriteProcessMemory(hGameProcess,
        (LPVOID)0x00403616,
        &btCode,
        sizeof(BYTE),
        &dwWritedBytes);//返回修改了多少数据
    }
Last modification:November 19, 2020
如果觉得我的文章对你有用,请随意赞赏