小俊 发表于 2018-7-26 15:35

VEH Hook

#include <Windows.h>
#include <stdio.h>
#include "C:\Program Files\MariaDB 10.3\include\mysql\mysql.h"
#pragma comment(lib,"libmariadb.lib")

#define PATCH_RVA 0x86BFD2
#define Old_Byte 0xE8
#define New_Byte 0xCC

#define HOST "127.0.0.1"
#define PORT 3306
#define USER "root"
#define PWD"123"
#define DB   "test"
MYSQL * MySql;

// 格式化输出调试信息
void MyOutputDebugStringA(LPCSTR szFormat, ...)
{
      va_list argptr;
      va_start(argptr, szFormat);

      char buff;
      vsprintf_s(buff, szFormat, argptr);
      OutputDebugStringA(buff);

      va_end(argptr);
}

DWORD64 RIP = NULL;
// 补丁
void Patch(DWORD64 RVA, BYTE code)
{
      // 获取主模块基址
      RIP = (DWORD64)GetModuleHandle(NULL);
      // 计算偏移
      RIP += RVA;

      // 修改页保护属性
      DWORD OldProtect = NULL;
      VirtualProtect((LPVOID)RIP, 1, PAGE_EXECUTE_READWRITE, &OldProtect);

      // Patch
      *(BYTE*)RIP = code;

      // 还原页保护属性
      VirtualProtect((LPVOID)RIP, 1, OldProtect, &OldProtect);
}

// 枚举玩家名称
void EnumPlayerName(DWORD64 R15)
{
      // 玩家列表基地址
      DWORD64 PlayerListBase = *(DWORD64*)R15;
      // 玩家对象
      DWORD PlayerNum = *(DWORD*)(R15 + 8);

      // 开辟一块空间,用来存放玩家列表
      DWORD64 * pPlayerName = (DWORD64*)malloc(sizeof(DWORD64*)*PlayerNum);

      for (size_t i = 0; i < PlayerNum; i++)
      {
                pPlayerName = *(DWORD*)((*(DWORD*)(PlayerListBase + ((i * 2) * 8))) + 0x58);

                // 插入到数据库
                char SQL;
                sprintf_s(SQL, "INSERT INTO `test`.`player` (`name`) VALUES ('%ws')", pPlayerName);
                mysql_query(MySql, SQL);
      }

      free(pPlayerName);
}

// VEH 句柄
PVOID hVEH = NULL;
// 异常处理函数
LONG NTAPI VEH(EXCEPTION_POINTERS *ExceptionInfo)
{
      if (ExceptionInfo->ContextRecord->Rip == RIP)
      {
                EnumPlayerName(ExceptionInfo->ContextRecord->R15);
                RemoveVectoredExceptionHandler(hVEH);
                Patch(PATCH_RVA, Old_Byte);
                return EXCEPTION_CONTINUE_EXECUTION;
      }
      return EXCEPTION_EXECUTE_HANDLER;
}

// 动态链接库入口
BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID lpReserved)
{
      switch (dwReason)
      {
      case DLL_PROCESS_ATTACH:
                MySql = mysql_init(NULL);
                if (!mysql_real_connect(MySql, HOST, USER, PWD, DB, PORT, 0, 0))
                {
                        MessageBoxA(0, "链接数据库失败!", "错误", 0);
                        ExitProcess(0);
                        return FALSE;
                }
                hVEH = AddVectoredExceptionHandler(1, VEH);
                // 打补丁引发异常
                Patch(PATCH_RVA, New_Byte);
                break;
      case DLL_PROCESS_DETACH:
                RemoveVectoredExceptionHandler(hVEH);
                break;
      }
      return TRUE;
}

心冷、鱼儿 发表于 2018-7-26 16:06

CC断点异常,还是会修改代码,其实可以不修改达到无痕HOOK,但是有瓶颈,效率低。

旧模样y 发表于 2018-7-26 16:52

大佬大佬

haser525 发表于 2018-7-31 13:33

支持做成成品!!!

greenmor 发表于 2018-8-1 22:04

这个帖子好,学习了~

jgs 发表于 2018-11-19 14:23

学习了小俊师傅的思路,谢谢

raymondLei 发表于 2020-5-25 11:08

思路不错,对VEH一直不是太懂,资料相对来说比较少,非常感谢楼主贴出实战代码。
页: [1]
查看完整版本: VEH Hook