Bài viết mô tả việc dùng
Detours
Software package for re-routing Win32 APIs underneath applications. Under commercial release for over 10 years, Detours is licensed by over 100 ISVs and used within nearly every product team at Microsoft.
để thực hiện API hooking, cụ thể là ReAlloc nhằm lấy được base address của lua_State dùng cho AutoPlay. Lý do để thực hiện việc này là không thể dò lua_State bằng cách thông thường dùng CheatEngine (xem lại bài
Sử dụng Cheat Engine để search base address dùng cho auto play).
Bài viết này không đi sâu chi tiết vào Detours, chỉ mô tả cách sử dụng Detours trong trường hợp ko dùng được CheatEngine. Cách thực hiện này có thể áp dụng trong các trường hợp có logic tương tự.
Do mấy bữa nay bận nên không thể ngồi dò base address của lua_State nên không sửa hoàn chỉnh cái auto Tru Tiên. Hôm nay cuối tuần mình sẽ ngồi viết tutorial cho phần này. Sau này nếu có ai muốn tìm giá trị của lua_State hay những địa chỉ trong trường hợp tương tự thì vẫn biết đường mà mò.
Build Lua library
Đầu tiên mình check phiên bản Lua mà game đang sử dụng (là 5.1.1), sau đó phải kiếm 1 bản lua về tại
http://www.lua.org/download.html. Bản mới nhất hiện tại là 5.1.4, có thể dùng bản này hoặc 5.1.1. Sau khi download về và extract trong 1 folder Lua-5.1.1. Sau đó tạo một project static library
Lua-5.1.1.vcproj, add các files trong thư mục src (
nhớ bỏ 2 file lua.c và luac.c là 2 files build lua command line) vào project.
Mục đích là build static library Lua. Có thể tạo solution riêng để build lua library 1 lần thôi.
Sau khi build xong có
lua-5.1.1d.lib và
lua-5.1.1.lib, có thể copy lên thư mục Lib để dễ reference.
Cách thức cấp phát lua_State
Tạo một project đơn giản dạng Win32 application (dùng cái này khỏi dính dáng đến MFC) để biết lua_State được cấp phát như thế nào. Tạo Win32 application viết dạng Dialog
// Test.cpp : Defines the entry point for the application.
#include "stdafx.h"
// Header for Lua library
extern "C" {
#include "../Lib/Lua-5.1.1/src/lua.h"
#include "../Lib/Lua-5.1.1/src/lauxlib.h"
#include "../Lib/Lua-5.1.1/src/lualib.h"
};
// 21/Nov/2009 fixed link to Lua library
#if defined(_DEBUG)
// Debug libraries
#pragma comment(lib, "../Lib/lua-5.1.1d.lib")
#else
// Release libraries
#pragma comment(lib, "../Lib/lua-5.1.1.lib")
#endif
HINSTANCE g_hInstance = NULL;
BOOL CALLBACK DialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
// TODO: Place code here.
g_hInstance = hInstance;
HWND hDialog = 0;
hDialog = ::CreateDialog(hInstance, MAKEINTRESOURCE(IDD_TEST_DLG), 0, DialogProc);
if (!hDialog)
{
LPVOID lpBuffer;
::FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(), 0, (LPTSTR)&lpBuffer, 0, NULL);
::MessageBox(NULL, (LPTSTR)lpBuffer, _T("CreateDialog"), MB_ICONEXCLAMATION | MB_OK);
::LocalFree(lpBuffer);
return 1;
} else {
::ShowWindow(hDialog, nCmdShow);
}
MSG msg;
int status;
while ((status = ::GetMessage(&msg, 0, 0, 0)) != 0) {
if (status == -1) {
return -1;
}
if (!::IsDialogMessage(hDialog, & msg)) {
::TranslateMessage( & msg );
::DispatchMessage( & msg );
}
}
return msg.wParam;
}
BOOL CALLBACK DialogProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
WORD wId, wEvent;
HICON hIcon = NULL;
lua_State* state = NULL;
TCHAR buffer[1024] = { '\0' };
switch (message)
{
case WM_INITDIALOG:
hIcon = ::LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON));
if(hIcon) {
::SendMessage(hWnd, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)hIcon);
}
return TRUE;
case WM_COMMAND:
wId = LOWORD(wParam);
wEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wId)
{
case IDC_BUTTON_TEST:
state = luaL_newstate();
wsprintf(buffer, _T("[Process %p] "), ::GetCurrentProcessId(), state);
::MessageBox(NULL, buffer, _T("Test"), MB_OK);
if (state != NULL) {
lua_close(state);
}
break;
case IDOK:
::DestroyWindow(hWnd);
break;
case IDCANCEL:
::DestroyWindow(hWnd);
break;
default:
return ::DefWindowProc(hWnd, message, wParam, lParam);
}
return TRUE;
case WM_DESTROY:
::PostQuitMessage(0);
return TRUE;
case WM_CLOSE:
::DestroyWindow(hWnd);
return TRUE;
}
return FALSE;
}
Test project đơn giản chỉ là một dialog có một nút test.
// Header for Lua library
extern "C" {
#include "../Lib/Lua-5.1.1/src/lua.h"
#include "../Lib/Lua-5.1.1/src/lauxlib.h"
#include "../Lib/Lua-5.1.1/src/lualib.h"
};
// 21/Nov/2009 fixed link to Lua library
#if defined(_DEBUG)
// Debug libraries
#pragma comment(lib, "../Lib/lua-5.1.1d.lib")
#else
// Release libraries
#pragma comment(lib, "../Lib/lua-5.1.1.lib")
#endif
File lua-5.1.1d.lib là Lua đã build trong bước trước.
Khi thực hiện nhấn button Test sẽ tạo một lua_State, do đó để break point ngay đây xem có được thông tin gì không. Mình biết lua_State được tạo bởi luaL_newstate.
// Parse the menu selections:
switch (wId)
{
case IDC_BUTTON_TEST:
state = luaL_newstate();
Thực hiện F11 step into sẽ vào lua_newstate xem tiếp
LUALIB_API lua_State *luaL_newstate (void) {
lua_State *L = lua_newstate(l_alloc, NULL);
if (L) lua_atpanic(L, &panic);
return L;
}
Tiếp tục step into lua_newstate với l_alloc
LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
int i;
lua_State *L;
global_State *g;
void *l = (*f)(ud, NULL, 0, state_size(LG));
if (l == NULL) return NULL;
Mình để ý tiếp lua_Alloc và step into lua_Alloc f (line 5), step into lua_Alloc tại bước này
static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) {
(void)ud;
(void)osize;
if (nsize == 0) {
free(ptr);
return NULL;
}
else
return realloc(ptr, nsize);
}
Tới đây mình hầu như đã có thông tin mong muốn
- Lua alloc sử dụng API realloc
- Kích thước cấp phát là nzine
Có nghĩa là lua_State là giá trị trả về của realloc với size là 376. Con số này rất quan trọng mình sẽ ghi nhớ.
Hình: Kích thước cấp phát của lua_State
Tìm giá trị lua_State của game thông qua API hooking
Vấn đề tiếp theo là làm sao lấy được giá trị trả về của
realloc trong game. Khi game bắt đầu khởi động thì
lua_State đã được tạo và load các script, trước cả khi ra màn hình log in.
Khoảng thời gian này rất ngắn và không thể inject dll sau đó được. Nếu game build mode debug thì mình có thể dùng chính Visual Studio để open elementclient.exe với break point là realloc with condition (đó là cách làm lúc trước).
Nhân đây mới nói chẳng hiểu Tru Tiên bản cũ sao nó dám đưa build debug làm bản thương mại ???.
Cách thực hiện theo suy nghĩ là lắng nghe tất cả các cấp phát có kích thước đúng bằng kích thước của lua_State mà bước trên mình đã có
376.
Mình sẽ dùng
Detours một thư viện có sẵn để thực hiện system hook và thực hiện detour realloc. Trang chính của Detours là
http://research.microsoft.com/en-us/projects/detours/ với version mới nhất là 2.1. Mình không biết nó có đổi gì hay có gì mới không nên dùng 1.5 bao gồm 2 file đơn giản detour.lib và detour.h (để trong thư mục Lib).
Libraries Lua và Detours
Bước 1: Chuẩn bị Hook và Installer
Tạo solution Detours có 2 project là Hook và Installer cùng cấp với thư mục Lib.
- Hook project là Win32 dll
- Installer project giống như test project ở trên ngoại trừ có 2 nút là Install và Uninstall.
Trong Hook project sẽ cần sử dụng detours.lib và detours.h.
Bước 2: Project Hook
Trong file Hook.h thực hiện include Detours, và tạo 2 function export install và uninstall.
Mình dùng
file .def để export nên tạo file Hook.def và thêm vào project (có thể dùng
__declspec(dllexport) cũng được)
// -----------------------------------------------------------------------------
// Document : Hook.h
// Description : Hook include file
// Create date : 15/9/2009-13:40:07
// Author : gponster (langxang)
// -----------------------------------------------------------------------------
#ifndef __HOOK_H_B10B0170_CAB8_4F19_8F66_830200F34112__
#define __HOOK_H_B10B0170_CAB8_4F19_8F66_830200F34112__
#include
#include
#include
#if (_MSC_VER < 1310)
#else
#include
#endif
#include "../Lib/detours.h"
#pragma warning(disable: 4099)
#pragma comment(lib, "../Lib/detours.lib")
#if defined(__cplusplus)
extern "C" {
#endif
void InstallHook();
void UninstallHook();
#if defined(__cplusplus)
}
#endif
#endif // __HOOK_H_B10B0170_CAB8_4F19_8F66_830200F34112__
Nội dung Hook.def
; Hook.def : Declares the module parameters for the DLL.
LIBRARY "Hook"
EXPORTS
; Explicit exports can go here
InstallHook
UninstallHook
DLL này ko có gì đặc biệt, nếu bị lỗi SAFESEH thì tắt lý do là compiler mới bị lỗi khi link với lib build bằng compiler cũ (ở đây là Detours)
This happens when you link an .obj or .lib that contains code created by an earlier version of the compiler.
Tắt /SAFESEH:NO Project properties > Configuration Properties > Linker > Advanced
Mình sẽ thực hiện install và uninstall hook với ShellProc. Nếu bạn nào chưa hiểu rõ thì có thể tự tìm hiểu thêm (về API hooking và DLL Injection sẽ có thể ở một bài khác).
// -----------------------------------------------------------------------------
// Document : Hook.cpp
// Description : Hook implementation
// Create date : 15/9/2009-13:40:07
// Author : gponster (langxang)
// -----------------------------------------------------------------------------
#include "Hook.h"
HHOOK g_hHook = NULL;
HANDLE g_hInst = NULL;
DETOUR_TRAMPOLINE(int WINAPI TrampolineMessageBoxA(HWND hWnd, LPCSTR lpText,
LPCSTR lpCaption, UINT uType), MessageBoxA);
DETOUR_TRAMPOLINE(int WINAPI TrampolineMessageBoxW(HWND hWnd, LPCWSTR lpText,
LPCWSTR lpCaption, UINT uType), MessageBoxW);
typedef void* (__cdecl *ReAllocFunc)(void* memptr, size_t newsize);
ReAllocFunc g_lpTargetReAllocMSVCRT = NULL; // Target realloc function pointer in MSVCRT
ReAllocFunc g_lpTrampolineReAllocMSVCRT = NULL; // Trampoline realloc function pointer in MSVCRT
ReAllocFunc g_lpTargetReAllocMSVCR90D = NULL; // Target realloc function pointer in MSVCR90D
ReAllocFunc g_lpTrampolineReAllocMSVCR90D = NULL; // Trampoline realloc function pointer in MSVCR90D
int WINAPI PatchedMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) {
CHAR buffer[1024] = { 0x00 };
::StringCbPrintfA(buffer, sizeof(buffer), "%s - patched by Detours", lpText);
return TrampolineMessageBoxA(hWnd, buffer, lpCaption, uType);
}
int WINAPI PatchedMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType) {
WCHAR buffer[1024] = { 0x00 };
::StringCbPrintfW(buffer, sizeof(buffer), L"%s - patched by Detours", lpText);
return TrampolineMessageBoxW(hWnd, buffer, lpCaption, uType);
}
#define EXPECTED_SIZE (376)
void* __cdecl PatchedReAllocMSVCRT(void* memblock, size_t newsize)
{
void* result = NULL;
result = g_lpTrampolineReAllocMSVCRT(memblock, newsize);
if (newsize == EXPECTED_SIZE)
{
TCHAR buffer[1024] = { 0x00 };
::StringCbPrintf(buffer, sizeof(buffer),
_T("[Process %p] MSVCRT.realloc memptr %p size %d result %p"),
::GetCurrentProcessId(), memblock, newsize, result);
::OutputDebugString(buffer);
}
return result;
}
void* __cdecl PatchedReAllocMSVCR90D(void* memblock, size_t newsize)
{
void* result = NULL;
result = g_lpTrampolineReAllocMSVCR90D(memblock, newsize);
if (newsize == EXPECTED_SIZE)
{
TCHAR buffer[1024] = { 0x00 };
::StringCbPrintf(buffer, sizeof(buffer),
_T("[Process %p] MSVCR90D.realloc memptr %p size %d result %p"),
::GetCurrentProcessId(), memblock, newsize, result);
::OutputDebugString(buffer);
}
return result;
}
void Intercept()
{
DetourFunctionWithTrampoline((PBYTE)TrampolineMessageBoxA, (PBYTE)PatchedMessageBoxA);
DetourFunctionWithTrampoline((PBYTE)TrampolineMessageBoxW, (PBYTE)PatchedMessageBoxW);
g_lpTargetReAllocMSVCRT = (ReAllocFunc)DetourFindFunction("MSVCRT.DLL", "realloc");
if(g_lpTargetReAllocMSVCRT) {
g_lpTrampolineReAllocMSVCRT = (ReAllocFunc)DetourFunction((PBYTE)g_lpTargetReAllocMSVCRT,
(PBYTE)PatchedReAllocMSVCRT);
}
g_lpTargetReAllocMSVCR90D = (ReAllocFunc)DetourFindFunction("MSVCR90D.DLL", "realloc");
if(g_lpTargetReAllocMSVCR90D) {
g_lpTrampolineReAllocMSVCR90D = (ReAllocFunc)DetourFunction((PBYTE)g_lpTargetReAllocMSVCR90D,
(PBYTE)PatchedReAllocMSVCR90D);
}
}
void UnIntercept()
{
DetourRemove((PBYTE)TrampolineMessageBoxA, (PBYTE)PatchedMessageBoxA);
DetourRemove((PBYTE)TrampolineMessageBoxW, (PBYTE)PatchedMessageBoxW);
if(g_lpTrampolineReAllocMSVCRT) {
DetourRemove((PBYTE)g_lpTrampolineReAllocMSVCRT, (PBYTE)PatchedReAllocMSVCRT);
}
if (g_lpTrampolineReAllocMSVCR90D)
{
DetourRemove((PBYTE)g_lpTrampolineReAllocMSVCR90D, (PBYTE)PatchedReAllocMSVCR90D);
}
}
BOOL APIENTRY DllMain(HANDLE hInstDLL, DWORD dwReason, LPVOID lpReserved)
{
g_hInst = hInstDLL;
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
Intercept();
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
UnIntercept();
break;
}
return TRUE;
}
LRESULT CALLBACK ShellProc(int nCode, WPARAM wParam, LPARAM lParam)
{
return ::CallNextHookEx(g_hHook, nCode, wParam, lParam);
}
void InstallHook()
{
if(g_hHook == NULL) {
g_hHook = ::SetWindowsHookEx(WH_SHELL, ShellProc, (HINSTANCE)g_hInst, 0);
}
}
void UninstallHook()
{
if(::UnhookWindowsHookEx(g_hHook)) {
g_hHook = NULL;
}
}
Để ý hàm DllMain sẽ thực hiện Intercept khi DLL_PROCESS_ATTACH và UnIntercept khi DLL_PROCESS_DETACH.
Bước 3: làm quen với Detours
Đơn giản mình sẽ demo thử với MessageBox.
Mình patch 2 version của MessageBox là MessageBoxA và MessageBoxW.
Đầu tiên khai báo với macro của Detours
DETOUR_TRAMPOLINE
DETOUR_TRAMPOLINE(int WINAPI TrampolineMessageBoxA(HWND hWnd, LPCSTR lpText,
LPCSTR lpCaption, UINT uType), MessageBoxA);
DETOUR_TRAMPOLINE(int WINAPI TrampolineMessageBoxW(HWND hWnd, LPCWSTR lpText,
LPCWSTR lpCaption, UINT uType), MessageBoxW);
Hai dòng này khai báo API sẽ bị patched cũng như prototype và calling convention của các API này.
Tạo 2 function detour sao cũng được, ví dụ thêm vào thông báo 1 dòng gì đó, để buffer là 1024 chắc cũng đủ. Lưu ý calling convention của các hàm này cũng phải tương ứng với khai báo Trampoline
int WINAPI PatchedMessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) {
CHAR buffer[1024] = { 0x00 };
::StringCbPrintfA(buffer, sizeof(buffer), "%s - patched by Detours", lpText);
return TrampolineMessageBoxA(hWnd, buffer, lpCaption, uType);
}
int WINAPI PatchedMessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType) {
WCHAR buffer[1024] = { 0x00 };
::StringCbPrintfW(buffer, sizeof(buffer), L"%s - patched by Detours", lpText);
return TrampolineMessageBoxW(hWnd, buffer, lpCaption, uType);
}
Ngoài ra trong Intercept và UnIntercept sẽ thực hiện detour hay remove (Line 76, 94).
Trong source code cũng có sẵn cài đặt detour cho realloc (xem phần sau).
Hai export function là InstallHook và UninstallHook dùng ShellProc.
Sau bước này mình đã có Hook.dll với 2 export function là Install và Uninstall
Bước 4: tạo installer để cài đặt hook vào hệ thống.
Để inject Hook.dll vào hệ thống cần tạo Installer project và dùng lại test project sửa dialog tạo 2 button install và uninstall.
// Installer.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
HINSTANCE g_hInstance = NULL;
BOOL CALLBACK DialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
typedef void (*InstallHookFunc)();
typedef void (*UninstallHookFunc)();
InstallHookFunc g_lpInstallHook = NULL;
UninstallHookFunc g_lpUninstallHook = NULL;
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
// TODO: Place code here.
...
}
BOOL CALLBACK DialogProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
WORD wId, wEvent;
HMODULE hModule = NULL;
HICON hIcon = NULL;
switch (message)
{
case WM_INITDIALOG:
::EnableWindow(::GetDlgItem(hWnd, IDC_BUTTON_UNINSTALL), FALSE);
hModule = ::LoadLibraryA("Hook.dll");
if(hModule) {
g_lpInstallHook = (InstallHookFunc)::GetProcAddress(hModule, "InstallHook");
g_lpUninstallHook = (UninstallHookFunc)::GetProcAddress(hModule, "UninstallHook");
}
hIcon = ::LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_ICON));
if(hIcon) {
::SendMessage(hWnd, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)hIcon);
}
return TRUE;
case WM_COMMAND:
wId = LOWORD(wParam);
wEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wId)
{
case IDC_BUTTON_INSTALL:
if(g_lpInstallHook) {
g_lpInstallHook();
}
::EnableWindow(::GetDlgItem(hWnd, IDC_BUTTON_INSTALL), FALSE);
::EnableWindow(::GetDlgItem(hWnd, IDC_BUTTON_UNINSTALL), TRUE);
break;
case IDC_BUTTON_UNINSTALL:
if(g_lpUninstallHook) {
g_lpUninstallHook();
g_lpUninstallHook = NULL;
}
::EnableWindow(::GetDlgItem(hWnd, IDC_BUTTON_INSTALL), TRUE);
::EnableWindow(::GetDlgItem(hWnd, IDC_BUTTON_UNINSTALL), FALSE);
break;
case IDOK:
if(g_lpUninstallHook) {
g_lpUninstallHook();
g_lpUninstallHook = NULL;
}
::DestroyWindow(hWnd);
break;
case IDCANCEL:
if(g_lpUninstallHook) {
g_lpUninstallHook();
g_lpUninstallHook = NULL;
}
::DestroyWindow(hWnd);
break;
default:
return ::DefWindowProc(hWnd, message, wParam, lParam);
}
return TRUE;
case WM_DESTROY:
if (g_lpUninstallHook) {
g_lpUninstallHook();
g_lpUninstallHook = NULL;
}
::PostQuitMessage(0);
return TRUE;
case WM_CLOSE:
if(g_lpUninstallHook) {
g_lpUninstallHook();
g_lpUninstallHook = NULL;
}
::DestroyWindow(hWnd);
return TRUE;
}
return FALSE;
}
Mình khai báo prototype 2 function Install và Uninstall và 2 global function và thực hiện load từ Hook.dll, thực hiện test một cách đơn giản thôi.
typedef void (*InstallHookFunc)();
typedef void (*UninstallHookFunc)();
InstallHookFunc g_lpInstallHook = NULL;
UninstallHookFunc g_lpUninstallHook = NULL;
Thực hiện load Hook.dll ngay trong WM_INITDIALOG và lấy địa chỉ hàm luôn cho tiện. Tới đây mọi việc xong xuôi, để test mình chạy installer và install hook.
Tới đây mình lấy cái Test.exe cũ ra xài, hoặc xài bất kỳ ứng dụng nào có MessageBox
Nếu thấy nội dung của MessageBox có thay đổi là OK.
OK vậy là đã hook API MessageBox rồi.
Bước 5: patch function realloc. realloc là function của CRT.
CRT có version đi với OS và version của Visual Studio (để VS thực hiện debug).
API realloc trong game sẽ xài CRT ship với OS, mình có thể kiểm tra bằng cách nào cũng được, dùng Command Prompt trong Visual Studio Tools rồi xuất ra file imports.txt trong C chẳng hạn, gõ
dumpbin /imports elementclient.exe > C:\imports.txt
Trong danh sách sẽ thấy realloc trong MSVCRT.DLL.
Trong khi đó code thì mình sẽ dùng MSVCR9D.DLL của Visual Studio 2008 (bản đang dùng). Mình sẽ thực hiện patch 2 version này và test thử với Test.exe cũng tạo lua_State.
Cách làm hơi khác chút xíu, đầu tiên khai báo prototype của realloc.
typedef void* (__cdecl *ReAllocFunc)(void* memptr, size_t newsize);
Khai báo một cặp target và trampoline function
ReAllocFunc g_lpTargetReAllocMSVCRT = NULL; // Target realloc function pointer in MSVCRT
ReAllocFunc g_lpTrampolineReAllocMSVCRT = NULL; // Trampoline realloc function pointer in MSVCRT
ReAllocFunc g_lpTargetReAllocMSVCR90D = NULL; // Target realloc function pointer in MSVCR90D
ReAllocFunc g_lpTrampolineReAllocMSVCR90D = NULL; // Trampoline realloc function pointer in MSVCR90D
Thực hiện tạo function detour đơn giản gọi function trampoline và log lại thông tin trả về vào debug output nếu size của realloc là 376 mà mình đã tìm ở trên.
Thêm trong Intercept và UnIntercept, mình dùng DetourFindFunction để tìm realloc, nếu tìm thấy thì thực hiện detour bằng DetourFunction
g_lpTargetReAllocMSVCRT = (ReAllocFunc)DetourFindFunction("MSVCRT.DLL", "realloc");
if(g_lpTargetReAllocMSVCRT) {
g_lpTrampolineReAllocMSVCRT = (ReAllocFunc)DetourFunction((PBYTE)g_lpTargetReAllocMSVCRT,
(PBYTE)PatchedReAllocMSVCRT);
}
g_lpTargetReAllocMSVCR90D = (ReAllocFunc)DetourFindFunction("MSVCR90D.DLL", "realloc");
if(g_lpTargetReAllocMSVCR90D) {
g_lpTrampolineReAllocMSVCR90D = (ReAllocFunc)DetourFunction((PBYTE)g_lpTargetReAllocMSVCR90D,
(PBYTE)PatchedReAllocMSVCR90D);
}
Trong các hàm này dùng OutputDebugString để output thông tin. Để coi được thông tin xuất bởi OutputDebugString mình dùng Dbgview có thể download tại
http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx.
Đến đây chạy thử với Test, nhấn 2 lần button mình có 2 dòng debug output kết quả của patched MSVCR9D.realloc.