1. 程式人生 > 實用技巧 >c++ winapi 讓目標程式(target)呼叫當前程式(local)的函式

c++ winapi 讓目標程式(target)呼叫當前程式(local)的函式

如果你的目標程式是x86/x64, 那麼當前程式也需要編譯為x84/x64

#include <iostream>
#include <string>
#include <vector>
#include <regex>

#include "GameCheatEx.h"

using namespace std;

int n = 1;

/*
extern "C" __declspec(dllexport) void __stdcall hello()
{
  n++;
  printf("%d\n", n);
}
*/

void __stdcall hello()
{
  n++;
  printf("%d\n", n);
}

int main()
{
  GameCheatEx::GC gc{ "game2.exe" };
  
  uintptr_t pCreateRemoteThread = GameCheatEx::GC::GetProcAddressEx(gc.hProcess, "kernel32.dll", "CreateRemoteThread");
  uintptr_t pOpenProcess = GameCheatEx::GC::GetProcAddressEx(gc.hProcess, "kernel32.dll", "OpenProcess");
  uintptr_t pCloseHandle = GameCheatEx::GC::GetProcAddressEx(gc.hProcess, "kernel32.dll", "CloseHandle");

#ifdef _WIN64
  /*
    000- 55                    - push rbp
    001- 48 8B EC              - mov rbp,rsp

    // get local hProcess
    004- 48 83 EC 20           - sub rsp,20
    008- 48 B9 FFFF1F0000000000 - mov rcx,00000000001FFFFF { PROCESS_ALL_ACCESS }
    012- 48 31 D2              - xor rdx,rdx
    015- 49 B8 A42A000000000000 - mov r8,0000000000002AA4 { lcoal pid }
    01F- 48 B8 A0A1A640FD7F0000 - mov rax,KERNEL32.OpenProcess
    029- FF D0                 - call rax
    02B- 48 83 C4 20           - add rsp,20

    // save local hProcess
    02F- 48 8B D8              - mov rbx,rax

    032- 48 83 EC 38           - sub rsp,38 { 7*8=56 }
    036- 48 8B C8              - mov rcx,rax
    039- 48 31 D2              - xor rdx,rdx
    03C- 4D 31 C0              - xor r8,r8
    03F- 49 B9 80104832F77F0000 - mov r9,00007FF732481080 { lpLocalFun }
    049- 6A 00                 - push 00
    04B- 6A 00                 - push 00
    04D- 6A 00                 - push 00 { lpParam }
    04F- 48 B8 7059A840FD7F0000 - mov rax,KERNEL32.CreateRemoteThread
    059- FF D0                 - call rax
    05B- 48 83 C4 38           - add rsp,38
    
    // close hThread and hProcess
    05F - 48 83 EC 20           - sub rsp,20
    063 - 49 BC 101EA740FD7F0000 - mov r12,KERNEL32.CloseHandle
    06D - 48 8B C8              - mov rcx,rax
    070 - 41 FF D4              - call r12 { close hThread }
    073 - 48 8B CB              - mov rcx,rbx
    076 - 41 FF D4              - call r12 { close local hProcess }
    079 - 48 83 C4 20           - add rsp,20
    07D - 48 8B E5              - mov rsp,rbp
    080 - 5D                    - pop rbp
    081 - C3                    - ret

  */
  string funcodeStr = ""
    "55\n"
    "48 8B EC\n"

    // get local hProcess
    "48 83 EC 20\n"
    "48 B9 FF FF 1F 00 00 00 00 00\n"
    "48 31 D2\n"
    "49 B8 00 00 00 00 00 00 00 00\n" // local pid
    "48 B8 00 00 00 00 00 00 00 00\n" // OpenProcess
    "FF D0\n"
    "48 83 C4 20\n"

    // save local hProcess
    "48 8B D8\n"

    "48 83 EC 38\n"
    "48 8B C8\n"
    "48 31 D2\n"
    "4D 31 C0\n"
    "49 B9 00 00 00 00 00 00 00 00\n" // lpLocalFun
    "6A 00\n"
    "6A 00\n"
    "6A 00\n"
    "48 B8 00 00 00 00 00 00 00 00\n" // CreateRemoteThread 
    "FF D0\n"
    "48 83 C4 38\n"

    // close hThread and hProcess
    "48 83 EC 20\n"
    "49 BC 00 00 00 00 00 00 00 00\n" // CloseHandle
    "48 8B C8\n"
    "41 FF D4\n"
    "48 8B CB\n"
    "41 FF D4\n"
    "48 83 C4 20\n"
    "48 8B E5\n"
    "5D\n"
    "C3"
    "";
  vector<BYTE> funcode = GameCheatEx::GC::byteStr2Bytes(funcodeStr);
  *(DWORD*)(funcode.data() + 0x17) = (DWORD)GetCurrentProcessId(); // local pid
  *(uintptr_t*)(funcode.data() + 0x21) = (uintptr_t)pOpenProcess; // OpenProcess
  *(uintptr_t*)(funcode.data() + 0x41) = (uintptr_t)&hello; // lpLocalFun
  *(uintptr_t*)(funcode.data() + 0x51) = (uintptr_t)pCreateRemoteThread; // CreateRemoteThread
  *(uintptr_t*)(funcode.data() + 0x65) = (uintptr_t)pCloseHandle; // CloseHandle

#else
  /*
  0000- 55                    - push ebp
  0001- 8B EC                 - mov ebp,esp
  0003- 6A 00                 - push 00 { 0 }
  0005- 6A 00                 - push 00 { 0 }
  0007- 6A 00                 - push 00 { lpParam }
  0009- 68 C0118D00           - push 008D11C0 { lpLocalFun }
  000E- 6A 00                 - push 00 { 0 }
  0010- 6A 00                 - push 00 { 0 }

  // get hProcess
  0012- 68 60210000           - push 00002160 { local pid }
  0017- 6A 00                 - push 00 { 0 }
  0019- 68 FFFF1F00           - push 001FFFFF { PROCESS_ALL_ACCESS }
  001E- B8 00892377           - mov eax,KERNEL32.OpenProcess { }
  0023- FF D0                 - call eax
  0025- 50                    - push eax { local hProcess }

  // call CreateRemoteThread 
  0026- B8 00412577           - mov eax,KERNEL32.CreateRemoteThread {  }
  002B- FF D0                 - call eax

  002D- 8B E5                 - mov esp,ebp
  002F- 5D                    - pop ebp
  0030- C3                    - ret
  */

  string funcodeStr = ""
    "55\n"
    "8B EC\n"
    "6A 00\n"
    "6A 00\n"
    "6A 00\n"
    "68 00 00 00 00\n" // lpLocalFun
    "6A 00\n"
    "6A 00\n"

    // get hProcess
    "68 00 00 00 00\n" // local pid
    "6A 00\n"
    "68 FF FF 1F 00\n"
    "B8 00 00 00 00\n" // OpenProcess
    "FF D0\n"
    "50\n"

    // call CreateRemoteThread
    "B8 00 00 00 00\n" // CreateRemoteThread
    "FF D0\n"
    "8B E5\n"
    "5D\n"
    "C3\n"
    "";
  vector<BYTE> funcode = GameCheatEx::GC::byteStr2Bytes(funcodeStr);

  *(DWORD*)(funcode.data() + 0x0A) = (DWORD)&hello; // lpLocalFun
  *(DWORD*)(funcode.data() + 0x13) = (DWORD)GetCurrentProcessId(); // local pid
  *(DWORD*)(funcode.data() + 0x1F) = (DWORD)pOpenProcess; // OpenProcess
  *(DWORD*)(funcode.data() + 0x27) = (DWORD)pCreateRemoteThread; // CreateRemoteThread
#endif // _WIN64

  BYTE* newmem = (BYTE*)VirtualAllocEx(gc.hProcess, 0, funcode.size(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  printf("newmem: %x\n", newmem);
  WriteProcessMemory(gc.hProcess, newmem, funcode.data(), funcode.size(), 0);

  while (true)
  {
    HANDLE hThread = CreateRemoteThread(gc.hProcess, 0, 0, (LPTHREAD_START_ROUTINE)newmem, 0, 0, 0);
    WaitForSingleObject(hThread, INFINITE);
    CloseHandle(hThread);
    Sleep(1000);
  }

  VirtualFreeEx(gc.hProcess, newmem, 0, MEM_RELEASE);
  return 0;
}