Near call hook

今天实现一波Hook目标进程的MessageBoxA,当然其他的API都是一样的。
Hook API和DLL注入很像,唯一不同点在于DLL内的操作:

// hook_dll.cc
#include <iostream>
#include <windows.h>

#ifndef HOOK_DLL_API
#define HOOK_DLL_API extern "C" __declspec(dllimport)

BYTE originalCode[6] = {0};
LPVOID messageBoxAddress;

int WINAPI HookedMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption,
                             UINT uType) {
  std::cout << "HookedMessageBoxA" << std::endl;
  WriteProcessMemory(GetCurrentProcess(), messageBoxAddress, originalCode,
                     sizeof(originalCode), NULL);
  MessageBoxA(hWnd, lpText, lpCaption, uType);
  return 0;
}

DWORD WINAPI HookMessageBoxA() {
  HINSTANCE library = LoadLibraryA("user32.dll");

  // get address of the MessageBox function in memory
  messageBoxAddress = (LPVOID)GetProcAddress(library, "MessageBoxA");
  memcpy(originalCode, messageBoxAddress, 6);
  ReadProcessMemory(GetCurrentProcess(), messageBoxAddress, originalCode, 6,
                    NULL);
  BYTE shellcode[6] = {
      0x68, 0x0, 0x0, 0x0, 0x0, // PUSH 0x00000000
      0xC3                      // RETN
  };
  void *HookedMessageBoxAAddress = (LPVOID)&HookedMessageBoxA;
  std::cout << "HookedMessageBoxA" << (DWORD)&HookedMessageBoxA << std::endl;
  memcpy(&shellcode[1], (LPVOID)&HookedMessageBoxAAddress, 4);
  WriteProcessMemory(GetCurrentProcess(), messageBoxAddress, shellcode,
                     sizeof(shellcode), NULL);

  for (int i = 0; i < sizeof(shellcode); i++) {
    std::cout << std::hex << int(shellcode[i]);
  }
  return 0;
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, // handle to DLL module
                    DWORD fdwReason,    // reason for calling function
                    LPVOID lpvReserved) // reserved
{
  // Perform actions based on the reason for calling.
  switch (fdwReason) {
  case DLL_PROCESS_ATTACH: {
    // Initialize once for each new process.
    // Return FALSE to fail DLL load.
    HANDLE thread = CreateThread(
        NULL, 0, (LPTHREAD_START_ROUTINE)&HookMessageBoxA, NULL, 0, NULL);
    CloseHandle(thread);
    break;
  }

  case DLL_THREAD_ATTACH:
    // Do thread-specific initialization.
    break;

  case DLL_THREAD_DETACH:
    // Do thread-specific cleanup.
    break;

  case DLL_PROCESS_DETACH:

    if (lpvReserved != nullptr) {
      break; // do not do cleanup if process termination scenario
    }

    // Perform any necessary cleanup.
    break;
  }
  return TRUE; // Successful DLL_PROCESS_ATTACH.
}

#endif // HOOK_DLL_API

这里重点关注下HookMessageBoxA这个函数,这里面构造了一个6字节的shellcode,执行了一个push和一个ret,这俩就相当于一个jmp。但我们为啥没直接用jmp呢,因为jmp后面要接一个offset,我们不去算这个offset就直接用一个push+ret代替。

然后我们把push后面的地址换成HookedMessageBoxA函数指针,注意memcpy的时候要对HookedMessageBoxA函数指针再取地址,这样HookedMessageBoxA函数指针就会写入到push后面。我一开始直接把&HookedMessageBoxA作为参数传进了memcpy,然后发现拼接好的shellcode一直不对。

拼接好之后先保存下MessageBoxA开头的6个字节,为了后面自定义操作之后调用MessageBoxA。然后使用MessageBoxA将shellcode写入MessageBoxA。

HookedMessageBoxA很简单,输出一行字符串,把原来MessageBoxA开头6字节写回去然后调用MessageBoxA即可。

// target.cc
#include <iostream>
#include <windows.h>

int main() {
  std::cout << "process ID: " << GetCurrentProcessId();
  while (true) {
    MessageBoxA(NULL, "This is a target client", "Notice", MB_OK);
    getchar();
  }
}

// client.cc
#include <iostream>
#include <windows.h>

constexpr char kDllPath[] =
    "C:\\Users\\chuzhang\\Desktop\\DummyProgram\\hook\\hook_dll.dll";

int main() {
  std::cout << "input process id: " << std::endl;
  int processId;
  std::cin >> processId;
  HANDLE process = OpenProcess(PROCESS_ALL_ACCESS, false, processId);
  if (!process) {
    std::cout << "open process failed, erorr: " << GetLastError() << std::endl;
    return 1;
  }

  LPVOID allocatedAddress = VirtualAllocEx(process, NULL, strlen(kDllPath) + 1,
                                           MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  bool res = WriteProcessMemory(process, allocatedAddress, kDllPath,
                                strlen(kDllPath) + 1, NULL);
  if (!res) {
    std::cout << "write memory failed, erorr: " << GetLastError() << std::endl;
    return 1;
  }
  LPVOID loadLibraryAAdress =
      (LPVOID)GetProcAddress(GetModuleHandleA("kernel32"), "LoadLibraryA");
  if (loadLibraryAAdress == NULL) {
    std::cout << "Find function Address failed, erorr: " << GetLastError()
              << std::endl;
    return 1;
  }
  HANDLE thread = CreateRemoteThread(process, NULL, 0,
                                     (LPTHREAD_START_ROUTINE)loadLibraryAAdress,
                                     allocatedAddress, 0, NULL);
  WaitForSingleObject(thread, INFINITE);
  CloseHandle(thread);
  VirtualFreeEx(process, allocatedAddress, strlen(kDllPath) + 1, MEM_DECOMMIT);
  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值