- https://www.youtube.com/watch?v=wiX5LmdD5yk&list=PL2C03D3BB7FAF2EA0&index=2
# 读取值,和写入值
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
#include <vector>
// 获取进程名的pid
DWORD getPID(const wchar_t* name)
{
DWORD pid = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnap != INVALID_HANDLE_VALUE)
{
PROCESSENTRY32 pe;
pe.dwSize = sizeof(pe);
if (Process32First(hSnap, &pe))
{
do {
if (!_wcsicmp(pe.szExeFile, name)) {
pid = pe.th32ProcessID;
break;
}
} while (Process32Next(hSnap, &pe));
}
}
CloseHandle(hSnap);
return pid;
}
// 获取模块基址
uintptr_t getModuleBaseAddress(DWORD pid, const wchar_t* modName)
{
uintptr_t modBaseAddr = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid);
if (hSnap != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 me;
me.dwSize = sizeof(me);
if (Module32First(hSnap, &me))
{
do {
if (!_wcsicmp(me.szModule, modName)) {
modBaseAddr = (uintptr_t)me.modBaseAddr;
break;
}
} while (Module32Next(hSnap, &me));
}
}
CloseHandle(hSnap);
return modBaseAddr;
}
uintptr_t readIntger(HANDLE hProc, uintptr_t ptr, std::vector<unsigned int> offsets)
{
uintptr_t addr = ptr;
for (unsigned int i = 0; i < offsets.size(); ++i)
{
// 进程句柄, 内存地址(从这里读), 值引用(存读取得值),值的字节大小(读多大), null
ReadProcessMemory(hProc, (BYTE*)addr, &addr, sizeof(addr), 0);
addr += offsets[i];
}
return addr;
}
int main()
{
// 地址: [game.exe+009E820C]+338
// 1 获取进程pid
DWORD pid = getPID(L"game.exe");
printf_s("pid: %d\n", pid);
// 2 打开进程
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (hProcess == NULL) return 0; // 打开进程失败
// 3 获取模块地址
uintptr_t moduleBaseAddress = getModuleBaseAddress(pid, L"game.exe");
// 00905A4D
printf_s("module address: %x\n", moduleBaseAddress);
uintptr_t r = 0;
ReadProcessMemory(hProcess, (LPCVOID)(moduleBaseAddress + 0x9E820C), &r, sizeof(uintptr_t), 0);
ReadProcessMemory(hProcess, (LPCVOID)(r + 0x338), &r, 4, 0);
printf_s("value: %d\n", r);
// 写入新的值
uintptr_t newValue = 20;
ReadProcessMemory(hProcess, (LPCVOID)(moduleBaseAddress + 0x9E820C), &r, sizeof(r), 0);
WriteProcessMemory(hProcess, (LPVOID)(r + 0x338), (LPCVOID)&newValue, sizeof(newValue), 0);
CloseHandle(hProcess);
return 0;
}
# DLL
使用dll你可以向开发人员一样编写程序
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
#include <vector>
#include <regex>
#include <sstream>
#include <string>
// 获取模块基址
uintptr_t getModuleBaseAddress(const wchar_t* modName)
{
uintptr_t modBaseAddr = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, 0);
if (hSnap != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 me;
me.dwSize = sizeof(me);
if (Module32First(hSnap, &me))
{
do {
if (!_wcsicmp(me.szModule, modName)) {
modBaseAddr = (uintptr_t)me.modBaseAddr;
break;
}
} while (Module32Next(hSnap, &me));
}
}
CloseHandle(hSnap);
return modBaseAddr;
}
int Mythread(HMODULE hModule)
{
// 创建控制台
AllocConsole();
FILE* f;
freopen_s(&f, "CONOUT$", "w", stdout);
std::cout << "run...";
uintptr_t miduleAddress = getModuleBaseAddress(L"game.exe");
std::cout << "miduleAddress: " << std::hex << miduleAddress << std::endl;
// hack loop
while (true)
{
// 按下f2,修改值
if (GetAsyncKeyState(VK_F2) & 1)
{
// [game.exe+009E820C]+338
// addr = *(uintptr_t*)addr => mov addr [addr]
// lea a, [miduleAddress + 0x009E820C]
uintptr_t* a = (uintptr_t*)(miduleAddress + 0x009E820C);
// mov eax, [miduleAddress + 0x009E820C]
std::cout << "a value: " << std::hex << *a << std::endl;
if (a)
{
std::cout << "old value: " << std::hex << *(int*)(*a + 0x338) << std::endl;
// mov [eax+0x338], #10
*(int*)(*a + 0x338) = 10; // 设置新值
}
break;
}
// 修改字节集
if (GetAsyncKeyState(VK_F3) & 1)
{
BYTE* address = (BYTE*)(miduleAddress + 0x3B79F7);
// code: F3 0F 11 84 90 B8 02 00 00
BYTE* bytes = (BYTE*)"\x90\x90\x90\x90\x90\x90\x90\x90\x90";
int size = 9;
// 保存旧的保护值
DWORD oldprotect;
// 要更改任何进程的访问保护
VirtualProtect(address, size, PAGE_EXECUTE_READWRITE, &oldprotect);
// 从缓冲区复制字符
// 设置新的,不同的字节集
_memccpy(address, bytes, 0, size);
// 将缓冲区设置为指定字符
// 如果要设置相同的字节用这个方便点
// memset(address, 0x90, size);
VirtualProtect(address, size, oldprotect, &oldprotect);
break;
}
if (GetAsyncKeyState(VK_F12) & 1)
{
// 释放资源
fclose(f);
FreeConsole();
FreeLibraryAndExitThread(hModule, 0);
break;
}
Sleep(5);
}
return 0;
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
CloseHandle(CreateThread(0, 0, (LPTHREAD_START_ROUTINE)Mythread, hModule, 0, 0));
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
# AAScript to c++
- https://www.youtube.com/watch?v=jTl3MFVKSUM
ce的aa脚本是一种绕行/挂钩技术
源地址为00433F86: mov [edi+00005578],esi
,将这里绕行到我们定义的函数,在最后jmp回去
AAScript:
[ENABLE]
aobscanmodule(INJECT,PlantsVsZombies.exe,89 B7 78 55 00 00)
alloc(newmem,$1000)
label(return)
newmem:
add esi,#100
mov [edi+00005578],esi
jmp return
INJECT:
jmp newmem
nop
return:
registersymbol(INJECT)
[DISABLE]
INJECT:
db 89 B7 78 55 00 00
unregistersymbol(INJECT)
dealloc(newmem)
{
00433F84: 2B F3 - sub esi,ebx
// ---------- INJECTING HERE ----------
00433F86: 89 B7 78 55 00 00 - mov [edi+00005578],esi
// ---------- DONE INJECTING ----------
00433F8C: B0 01 - mov al,01
}
cpp DLL:
#include "pch.h"
#include <iostream>
#include <Windows.h>
bool handleHook(void * oldHook, void * newFunc, int len)
{
if (len < 5) return false;
// 更改访问保护
DWORD oldProc;
VirtualProtect(oldHook, len, PAGE_EXECUTE_READWRITE, &oldProc);
// 先将旧的字节集设置为nop
memset(oldHook, 0x90, len);
// 计算新的字节集
// 跳转目标地址 - 当前指令地址 - 5 = 字节集
DWORD relativeAddress = ((DWORD)newFunc - (DWORD)oldHook - 5);
// 设置jmp指令
*(BYTE*)oldHook = 0xE9;
*(DWORD*)((DWORD)oldHook + 1) = relativeAddress;
// 修改后还原访问保护
VirtualProtect(oldHook, len, oldProc, &oldProc);
return true;
}
DWORD returnAddress;
// 定义新的处理函数
void __declspec(naked) myNewFunc() {
//newmem:
__asm {
add esi, 0x64
mov[edi + 0x00005578], esi
jmp [returnAddress]
}
}
int Mythread(HMODULE hModule)
{
DWORD oldHookAddress = 0x00433F86;
int oldHookAddressLen = 6;
// 0x433F8C
returnAddress = oldHookAddress + oldHookAddressLen;
handleHook((void*)oldHookAddress, myNewFunc, oldHookAddressLen);
while (true)
{
if (GetAsyncKeyState((VK_F2))) break;
Sleep(10);
}
// 脱钩
FreeLibraryAndExitThread(hModule, 0);
return 0;
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
CloseHandle(CreateThread(0, 0, (LPTHREAD_START_ROUTINE)Mythread, hModule, 0, 0));
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
# module scan
- https://www.youtube.com/watch?v=5M2rjjdX6DQ
- https://www.youtube.com/watch?v=S_SR5l_hquw
aa脚本:
[ENABLE]
aobscanmodule(INJECT,game2.exe,A3 24 37 4B 00)
alloc(newmem,$1000)
label(code)
label(return)
newmem:
code:
mov [004B3724],eax
jmp return
INJECT:
jmp newmem
return:
registersymbol(INJECT)
[DISABLE]
INJECT:
db A3 24 37 4B 00
unregistersymbol(INJECT)
dealloc(newmem)
{
00401570: E8 97 FA FF FF - call game2.exe+100C
// ---------- INJECTING HERE ----------
00401575: A3 24 37 4B 00 - mov [game2.exe+B3724],eax
// ---------- DONE INJECTING ----------
0040157A: 68 01 03 00 80 - push 80000301
}
c++
#include "pch.h"
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
#include <Psapi.h>
MODULEINFO GetModuleInfo(const wchar_t* mName)
{
MODULEINFO mInfo = { 0 };
HMODULE hModule = GetModuleHandleW(mName);
if (hModule == 0) return mInfo;
// 在MODULEINFO结构中检索有关指定模块的信息
GetModuleInformation(GetCurrentProcess(), hModule, &mInfo, sizeof(MODULEINFO));
return mInfo;
}
DWORD ModuleScan(const wchar_t* moduleName, BYTE* bytes, const wchar_t* mask)
{
// https://docs.microsoft.com/en-us/windows/win32/api/psapi/ns-psapi-moduleinfo
MODULEINFO mInfo = GetModuleInfo(moduleName);
// 起始位置
uintptr_t base = (uintptr_t)mInfo.lpBaseOfDll;
// 模块大小
uintptr_t size = (uintptr_t)mInfo.SizeOfImage;
int patternLen = wcslen(mask);
wchar_t anyByte{ L'?' };
for (size_t i = 0; i < size - patternLen; i++)
{
bool found = true;
for (size_t j = 0; j < patternLen; j++)
{
found &= mask[j] == anyByte || bytes[j] == *(BYTE*)(base + i + j);
}
// return find address start
if (found) return base + i;
}
return 0;
}
int Mythread(HMODULE hModule)
{
AllocConsole();
FILE* f;
freopen_s(&f, "CONOUT$", "w", stdout);
const wchar_t* moduleName = L"game2.exe";
BYTE* bytes = (BYTE*)"\xA3\x24\x37\x4B\x00";
// std::cout << (bytes[0] == 0xA3) << std::endl;
const wchar_t* mask = L"xxxxx"; // 每一个代表一个字节?代表any
DWORD address = ModuleScan(moduleName, bytes, mask);
// 00401575
std::cout << std::hex << address << std::endl;
while (true)
{
if (GetAsyncKeyState(VK_F12) & 1)
{
break;
}
Sleep(10);
}
fclose(f);
FreeConsole();
// 脱钩
FreeLibraryAndExitThread(hModule, 0);
return 0;
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
CloseHandle(CreateThread(0, 0, (LPTHREAD_START_ROUTINE)Mythread, hModule, 0, 0));
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
# C++调用游戏函数
- https://www.youtube.com/watch?v=jmgwFpVnRmU
- https://www.youtube.com/watch?v=gZN2damgYHg
- https://www.youtube.com/watch?v=-hwUPT5Gyvc
# 绕行挂钩技术 x86
#include "pch.h"
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
using namespace std;
uintptr_t GetModuleBaseAddr(const wchar_t* name)
{
uintptr_t addr = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, 0);
if (hSnap != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 me;
me.dwSize = sizeof(me);
if (Module32First(hSnap, &me))
{
do
{
if (!_wcsicmp(me.szModule, name))
{
addr = (uintptr_t)me.modBaseAddr;
break;
}
} while (Module32Next(hSnap, &me));
}
}
CloseHandle(hSnap);
return addr;
}
uintptr_t returnAddr = 0;
void __declspec(naked) mymemnew()
{
__asm {
inc [esi]
push edi
mov edi, [esp + 0x14]
jmp [returnAddr]
}
}
int MyThread(HMODULE hModule)
{
AllocConsole();
FILE* f;
freopen_s(&f, "CONOUT$", "w", stdout);
cout << "INJECT OK" << endl;
// 1.获取模块地址
// 2.创建钩子
// 3.将源地址跳到钩子
uintptr_t addr = GetModuleBaseAddr(L"ac_client.exe");
BYTE* address = (BYTE*)(addr + 0x637E9);
BYTE bytes[] = { 0xFF, 0x0E, 0x57, 0x8B, 0x7C, 0x24, 0x14 };
unsigned int size = sizeof(bytes);
returnAddr = (uintptr_t)address + size;
DWORD jmpBytes = (DWORD)mymemnew - (DWORD)address - 5;
bool bEnable = false;
while (true)
{
if (GetAsyncKeyState(VK_F2) & 1)
{
bEnable = !bEnable;
DWORD oldProc;
VirtualProtect(address, size, PAGE_EXECUTE_READWRITE, &oldProc);
if (bEnable)
{
memset(address, 0x90, size);
*(BYTE*)address = 0xE9;
*(DWORD*)(address + 1) = jmpBytes;
}
else
{
_memccpy(address, bytes, 0, size);
}
VirtualProtect(address, size, oldProc, 0);
}
if( GetAsyncKeyState(VK_F12)&1 )
{
break;
}
Sleep(20);
}
fclose(f);
FreeConsole();
FreeLibraryAndExitThread(hModule, 0);
return 0;
}
# 绕行挂钩技术 x64
#include "pch.h"
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
#include <Psapi.h>
using namespace std;
MODULEINFO GetModuleInfo(const wchar_t* modname)
{
MODULEINFO mi{ 0 };
HMODULE hMod = GetModuleHandle(modname);
GetModuleInformation(GetCurrentProcess(), hMod, &mi, sizeof(mi));
return mi;
}
int Mythread(HMODULE hModule)
{
AllocConsole();
FILE* f;
freopen_s(&f, "CONOUT$", "w", stdout);
cout << "INJECT OK" << endl;
// 获取模块信息
MODULEINFO mi = GetModuleInfo(L"MonsterHunterWorld.exe");
// "MonsterHunterWorld.exe"+CE7462A
BYTE* address = (BYTE*)((uintptr_t)mi.lpBaseOfDll + 0xCE7462A);
BYTE bytes[] = {
0xF3, 0x0F, 0x11, 0x41, 0x6C, // movss [rcx+6C],xmm0
};
int bytesSize = sizeof(bytes);
// "MonsterHunterWorld.exe"+CE7462F
uintptr_t returnAddr = (uintptr_t)address + bytesSize;
/* newmem */
BYTE codeBytes[] = {
0xC7, 0x41, 0x6C, 0x00, 0x00, 0xC8, 0x42, // mov [rcx+6C],42C80000
};
int codeSize = sizeof(codeBytes);
// 申请500字节虚拟空间存代码
BYTE* newmem = (BYTE*)VirtualAlloc((BYTE*)((uintptr_t)mi.lpBaseOfDll - 0x10000)/* 2-4GB */, 500,
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
/*
BYTE* newmem2 = (BYTE*)VirtualAlloc((BYTE*)((uintptr_t)newmem - 0x10000), 4,
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
*/
// 将代码复制到newmem
memcpy_s(newmem, codeSize, codeBytes, codeSize);
// jmp return
uintptr_t newmemJmpReturnAddr = ((uintptr_t)newmem + codeSize);
// 计算jmp字节集,丢弃高位
DWORD returnBytes = (DWORD)(returnAddr - newmemJmpReturnAddr - 5);
// jmp "MonsterHunterWorld.exe"+CE7462F
*(BYTE*)(newmemJmpReturnAddr) = 0xE9; // jmp
*(DWORD*)(newmemJmpReturnAddr + 1) = returnBytes; //
/* newmem */
DWORD jmpNewmemBytes = (DWORD)((uintptr_t)newmem - (uintptr_t)address - 5);
bool bEnable = false;
while (true)
{
if (GetAsyncKeyState(VK_F2) & 1)
{
bEnable = !bEnable;
DWORD oldProc;
VirtualProtect(address, bytesSize, PAGE_EXECUTE_READWRITE, &oldProc);
if (bEnable)
{
cout << "[ENABLE]" << endl;
memset(address, 0x90, bytesSize);
// jmp newmem
*(BYTE*)(address) = 0xE9; // jmp
*(DWORD*)(address + 1) = jmpNewmemBytes;
}
else
{
cout << "[DISABLE]" << endl;
memcpy_s(address, bytesSize, bytes, bytesSize);
}
VirtualProtect(address, bytesSize, oldProc, 0);
}
if (GetAsyncKeyState(VK_F12) & 1)
{
break;
}
Sleep(20);
}
VirtualFree(newmem, 0, MEM_RELEASE);
fclose(f);
FreeConsole();
FreeLibraryAndExitThread(hModule, 0);
return 0;
}
# 钩住opengl32.dll->wglSwapBuffers函数头
- https://guidedhacking.com/threads/how-to-hook-functions-code-detouring-guide.14185/
#include "pch.h"
#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>
using namespace std;
typedef BOOL(__stdcall* mywglSwapBuffers)(HDC hDc);
mywglSwapBuffers owglSwapBuffers;
HMODULE _hModule = 0;
FILE* _f;
// 定义自己的钩子函数
BOOL __stdcall mywglSwapBuffersHook(HDC hDc)
{
if (GetAsyncKeyState(VK_F2) & 1)
{
cout << "F2" << endl;
}
/* 脱钩失败
if (GetAsyncKeyState(VK_F12) & 1)
{
fclose(_f);
FreeConsole();
FreeLibraryAndExitThread(_hModule, 0);
}
*/
return owglSwapBuffers(hDc);
}
uintptr_t GetModuleBaseAddress(const wchar_t* modName)
{
uintptr_t modBaseAddr = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, 0);
if (hSnap != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 me;
me.dwSize = sizeof(me);
if (Module32First(hSnap, &me))
{
do {
if (!_wcsicmp(me.szModule, modName)) {
modBaseAddr = (uintptr_t)me.modBaseAddr;
break;
}
} while (Module32Next(hSnap, &me));
}
}
CloseHandle(hSnap);
return modBaseAddr;
}
/* 钩住wglSwapBuffers */
bool Detour32(BYTE* origen, BYTE* hook, int len)
{
if (len < 5) return false;
DWORD oldProc;
VirtualProtect(origen, len, PAGE_EXECUTE_READWRITE, &oldProc);
// 将wglSwapBuffers函数开始处设置为
// jmp mywglSwapBuffersHook
uintptr_t jmpHookBytes = hook - origen - 5;
*origen = 0xE9;
*(uintptr_t*)(origen + 1) = jmpHookBytes;
VirtualProtect(origen, len, oldProc, 0);
}
BYTE* TrampHook32(BYTE* origen, BYTE* hook, int len)
{
if (len < 5) return 0;
// 申请一块虚拟内存存代码
BYTE* gateway = (BYTE*)VirtualAlloc(0, len,
MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
// 从origen中拷贝len大小的字节到gateway
_memccpy(gateway, origen, 0, len);
// jmp wglSwapBuffers+5
// uintptr_t returnBytes = (origen+len) - (gateway+len) - 5;
uintptr_t returnBytes = origen - gateway - 5;
*(gateway + len) = 0xE9;
*(uintptr_t*)((uintptr_t)gateway + len + 1) = returnBytes;
Detour32(origen, hook, len);
return gateway;
}
int Mythread()
{
AllocConsole();
freopen_s(&_f, "CONOUT$", "w", stdout);
cout << "INJECT OK" << endl;
// 显示连接DLL函数
// opengl32.dll导出的wglSwapBuffers函数
owglSwapBuffers = (mywglSwapBuffers)GetProcAddress(
GetModuleHandleW(L"opengl32.dll"), "wglSwapBuffers");
// 将返回的虚拟内存地址给owglSwapBuffers
// 在mywglSwapBuffersHook中的owglSwapBuffers将执行
owglSwapBuffers = (mywglSwapBuffers)TrampHook32(
(BYTE*)owglSwapBuffers, (BYTE*)mywglSwapBuffersHook, 5);
return 0;
}
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
_hModule = hModule;
CloseHandle(CreateThread(0, 0, (LPTHREAD_START_ROUTINE)Mythread, 0, 0, 0));
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}