#include <iostream>
#include <Windows.h>
#include <cstdint>
#include <stdio.h>
#include <wchar.h>
#define JMP_REAL(addr) __asm { __asm jmp _DWORD PTR [addr##_ ] }
#define NewCountryValue 100
#define JUMPOUT(address) __asm { jmp address }
#define EXPORT extern "C" __declspec(dllexport)
typedef unsigned int _BYTE;
typedef unsigned int _DWORD;
typedef unsigned int _QWORD;
typedef unsigned int _WORD;
// 目标注入地址(原始函数入口点)
constexpr uintptr_t TARGET_ADDR = 0x004E4AA2;
constexpr uintptr_t TARGET_ADDR2 = 0x0053649F;
constexpr uintptr_t TARGET_ADDR3 = 0x005367A7;
constexpr uintptr_t TARGET_ADDR4 = 0x00536A62;
constexpr uintptr_t TARGET_ADDR5 = 0x00536B6A;
// 跳转代码模板: E9 [4字节相对偏移]
uint8_t jmpCode[5] = { 0xE9, 0x00, 0x00, 0x00, 0x00 };
uint8_t jmpCode2[5] = { 0xE9, 0x00, 0x00, 0x00, 0x00 };
// 原始代码备份地址
const int HOOK_LEN = 5;
void* trampolineAddr = nullptr;
void* trampolineAddr2 = nullptr;
void* trampolineAddr3 = nullptr;
void* trampolineAddr4 = nullptr;
void* trampolineAddr5 = nullptr;
const uintptr_t loc_4E4B72 = 0x004E4B72;
const uintptr_t loc_4E4B64 = 0x004E4B64;
const uintptr_t loc_5364C0 = 0x005364C0;
const uintptr_t loc_536A83 = 0x00536A38;
const uintptr_t loc_5367C6 = 0x005367C6;
const uintptr_t loc_4314D3 = 0x004314D3;
const uintptr_t loc_536B73 = 0x00536B73;
const uintptr_t loc_65F406 = 0x0065F406;
const uintptr_t loc_50C9E9 = 0x0050C9E9;
const uintptr_t loc_50CA05 = 0x0050CA05;
const uintptr_t loc_51725C = 0x0051725C;
uintptr_t DWORD_839848 = 0x00839848;
char byte_A3D2C2 = 0x00A3D2C2;
// 函数类型定义
typedef int(__thiscall* Sub4F94D0Func)(void*);
typedef int(__thiscall* Sub491D10Func)(DWORD* This, int a2);
typedef void(*FunctionType)();
// 函数指针初始化
Sub4F94D0Func sub_4F94D0 = (Sub4F94D0Func)0x4F94D0;
Sub491D10Func sub_491D10 = (Sub491D10Func)0x491D10;
typedef int(__stdcall* OriginalSub6437F0)(int);
OriginalSub6437F0 originalSub6437F0 = (OriginalSub6437F0)0x006439ED;
const uintptr_t loc_6439FC = 0x006439FC;
typedef int(__thiscall* Sub4F94D0Func)(void*);
typedef int(__thiscall* Sub491D10Func)(DWORD* This, int a2);
typedef int(__thiscall* Sub50CB00Func)(char* This, const char* a2);
typedef unsigned int(__thiscall* Sub50E9A0Func)(char* This, int a2, int a3, int a4, char* a5, size_t a6);
typedef int(__thiscall* Sub50CE00Func)(char* This, const char* a2, int a3);
typedef int(__thiscall* Sub45E0E0Func)(char* This);
typedef int(__thiscall* Sub70B540Func)(char* This);
typedef wchar_t(__fastcall* Sub6F9EC0Func)(void *a1, DWORD *a2, int a3, int a4);
typedef int(* _sprintf)(char *a1, const char *a2, ...);
typedef int(__stdcall* Sub536D30Func)(int *a1, unsigned __int16 a2, int a3);
typedef int(__stdcall* Sub46ACB0Func)(int a1, int a2, int a3);
typedef int(__cdecl* Sub6437F0Func)(int);
typedef int(__thiscall* Sub493FC0Func)(unsigned int *This, unsigned __int8 *a2, int a3);
// 函数指针初始化
Sub45E0E0Func sub_45E0E0 = (Sub45E0E0Func)0x45E0E0;
Sub70B540Func sub_70B540 = (Sub70B540Func)0x70B540;
Sub50CB00Func sub_50CB00 = (Sub50CB00Func)0x50CB00;
Sub50CE00Func sub_50CE00 = (Sub50CE00Func)0x50CE00;
Sub50E9A0Func sub_50E9A0 = (Sub50E9A0Func)0x50E9A0;
Sub6F9EC0Func sub_6F9EC0 = (Sub6F9EC0Func)0x6F9EC0;
Sub536D30Func sub_536D30 = (Sub536D30Func)0x536D30;
Sub46ACB0Func sub_46ACB0 = (Sub46ACB0Func)0x46ACB0;
Sub6437F0Func sub_6437F0 = (Sub6437F0Func)0x6437F0;
Sub493FC0Func sub_493FC0 = (Sub493FC0Func)0x493FC0;
_sprintf sub_7820F4 = (_sprintf)0x7820F4;
uintptr_t byte_82EE88 = 0x0082EE88; // idb
uintptr_t off_7A906C = 0x007A906C;
uintptr_t off_7A907C = 0x007A907C;
uintptr_t nWidth = 0x008523E0;
uintptr_t nHeight = 0x008523E4;
uintptr_t off_79AF8C = 0x0079AF8C;
uintptr_t off_79AEF8 = 0x0079AEF8;
uintptr_t word_AB6842 = 0x00AB6842;
// 检查内存读写权限
bool IsValidPointer(uintptr_t address) {
MEMORY_BASIC_INFORMATION mbi;
if (VirtualQuery((LPCVOID)address, &mbi, sizeof(mbi))) {
return (mbi.State == MEM_COMMIT &&
(mbi.Protect & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE | PAGE_READONLY)) != 0);
}
return false;
}
// 生成跳转指令
void GenerateJump(uintptr_t from, uintptr_t to) {
if (!IsValidPointer(from) || !IsValidPointer(to)) {
std::cerr << "Invalid memory address for jump!" << std::endl;
return;
}
DWORD oldProtect;
if (!VirtualProtect((LPVOID)from, 5, PAGE_EXECUTE_READWRITE, &oldProtect)) {
std::cerr << "VirtualProtect failed during jump generation! Error: " << GetLastError() << std::endl;
return;
}
*(BYTE*)from = 0xE9;
*(DWORD*)(from + 1) = to - from - 5;
VirtualProtect((LPVOID)from, 5, oldProtect, &oldProtect);
}
__declspec(naked) char HookFunction() {
__asm {
// 保存寄存器状态
pushad
pushfd
lea ebp, [esi + 5430h]
mov ebx, [ecx + 9D4h]
mov ecx, ebp
mov edx, [ebx]
mov eax, [edx + 0xB90]
push eax
call sub_491D10
mov ecx, [ebx + 4]
mov edi, eax
mov edx, [ecx + 0xB90]
mov ecx, ebp
push edx
call sub_491D10
// 调试输出: 再次调用 sub_491D10 后
add edi, eax
mov eax, [esi + 230h]
test eax, eax
jnz loc_return_4E4B72
test edi, edi
jg loc_return_4E4B72
// 调试输出: 测试 edi 后
// 新增逻辑: 判断是否为新建基地车
mov ecx, DWORD_839848
mov ebx, [ecx + 9D0h]
mov ecx, [ebx + 10h]
xor eax, eax
test ecx, ecx
jle short loc_799624
mov edi, 0
mov ebx, edi
loc_799612 :
mov ebp, ebx
test ebp, edx
jnz short loc_799645
inc eax
add ebx, 0xD
cmp eax, ecx
jl short loc_799612
loc_799624 :
xor eax, eax
loc_799626 :
mov edx, 0x39
lea ecx, [esi + 5430h]
push edx
call sub_491D10
test eax, eax
jnz loc_return_4E4B72
jmp loc_return_4E4B64
loc_799645 :
mov eax, 2
jmp short loc_799626
// === 恢复寄存器和返回业务 ===
loc_return_4E4B72 :
popfd
popad
jmp loc_4E4B72
loc_return_4E4B64 :
popfd
popad
jmp loc_4E4B64
}
}
__declspec(dllexport)char aDRa2LdprgmgrCp[20] = "D:\\Ra2\\LdPrgMgr.cpp"; // 假设存储有效地址
__declspec(dllexport)wchar_t aLoadbriefRussi[] = L"潌摡牂敩㩦畒獳慩"; // idbconst wchar_t* aNameTtnk = L"Name:Ttnk";
__declspec(dllexport)char aNameChina[11] = "Name:China"; // idb
__declspec(dllexport)char aLoadbriefChina[16] = "LoadBrief:China"; // idb
__declspec(dllexport)char aNameHowi[10] = "Name:HOWI"; // idb
__declspec(dllexport)wchar_t aNameTtnk[] = L"慎敭吺乔K"; // idb
__declspec(dllexport)wchar_t aNameRussians[] = L"慎敭刺獵楳湡s"; // idb
__declspec(naked) void sub_799910(unsigned int a1 )
{
_asm {
cmp ebp, 8
jnz short loc_79992E
push 0B7h
push offset aDRa2LdprgmgrCp
xor edx, edx
mov ecx, offset aNameRussians
call sub_6F9EC0
mov ebp, eax
ret
loc_79992E :
cmp ebp, 63h
ja short loc_799960
push 0CBh
push offset aDRa2LdprgmgrCp; "D:\\Ra2\\LdPrgMgr.cpp"
push ebp
push offset aNameChina; "Name:China"
mov edx, offset byte_82EE88
push edx
call sub_7820F4
add esp, 0Ch
sub edx, eax
inc edx
mov ecx, edx
xor edx, edx
call sub_6F9EC0
mov ebp, eax
ret
loc_799960 : ; CODE XREF : sub_799910 + 21↑j
xor ebp, ebp
ret
}
}
__declspec(naked) int sub_7999D0(unsigned int a1)
{
_asm {
cmp eax, 8
jnz short loc_7999EE
push 0F5h; int
push offset aDRa2LdprgmgrCp; "D:\\Ra2\\LdPrgMgr.cpp"
xor edx, edx
mov ecx, offset aNameTtnk; "Name:TTNK"
call sub_6F9EC0
ret
loc_7999EE : ; CODE XREF : sub_7999D0 + 3↑j
cmp eax, 63h; 'c'
jg short loc_799A1E
push 10Fh; int
push offset aDRa2LdprgmgrCp; "D:\\Ra2\\LdPrgMgr.cpp"
push eax
push offset aNameHowi; "NameHOWI"
mov edx, offset byte_82EE88
push edx; Buffer
call sub_7820F4
add esp, 0Ch
sub edx, eax
inc edx
mov ecx, edx; Format
xor edx, edx
call sub_6F9EC0
ret
loc_799A1E : ; CODE XREF : sub_7999D0 + 21↑j
xor eax, eax
ret
}
}
__declspec(naked) int sub_799970(unsigned int result)
{
_asm {
cmp eax, 8
jnz short loc_79998E
push 126h; int
push offset aDRa2LdprgmgrCp; "D:\\Ra2\\LdPrgMgr.cpp"
xor edx, edx
mov ecx, offset aLoadbriefRussi; "LoadBrief:Russia"
call sub_6F9EC0
mov edi, eax
ret
loc_79998E : ; CODE XREF : sub_799970 + 3↑j
cmp eax, 63h; 'c'
jg short loc_7999C0
push 128h; int
push offset aDRa2LdprgmgrCp; "D:\\Ra2\\LdPrgMgr.cpp"
push eax
push offset aLoadbriefChina; "LoadBrief:China"
mov edx, offset byte_82EE88
push edx; Buffer
call sub_7820F4
add esp, 0Ch
sub edx, eax
inc edx
mov ecx, edx; Format
xor edx, edx
call sub_6F9EC0
mov edi, eax
ret
loc_7999C0 : ; CODE XREF : sub_799970 + 21↑j
xor edi, edi
ret
}
}
extern "C" __declspec(naked) char loc_53649F() {
_asm {
call sub_799910
jmp loc_5364C0
}
}
extern "C" __declspec(naked) char loc_5367A7() {
_asm {
call sub_7999D0
jmp loc_5367C6
}
}
extern "C" __declspec(naked) char loc_536A62() {
_asm {
call sub_799970
jmp loc_536A83
}
}
extern "C" __declspec(naked) char HookFunction5() {
_asm {
// 保存所有通用寄存器
call sub_536D30
cmp ebx, 0x7C42
jz loc_536B70 // 保存原来的 ebp // 设置新的栈基指针
pop edi
pop esi
pop ebp
pop ebx
jmp loc_536B73
loc_536B70 :
push ebp
push edi
pop edi
pop esi
pop ebp
pop ebx
jmp loc_536B73
}
}
// 处理数据的独立函数
void InstallHookX(uintptr_t TARGET_ADDR, void*& trampolineAddr, void* HookFunction) {
constexpr int HookLen = 5;
DWORD oldProtect;
if (!VirtualProtect((LPVOID)TARGET_ADDR, HookLen, PAGE_EXECUTE_READWRITE, &oldProtect)) {
std::cerr << "VirtualProtect failed\n";
return;
}
if (!trampolineAddr) {
trampolineAddr = VirtualAlloc(NULL, HookLen + 5, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!trampolineAddr) {
std::cerr << "VirtualAlloc failed\n";
return;
}
}
BYTE original_bytes[HookLen];
memcpy(original_bytes, (LPVOID)TARGET_ADDR, HookLen);
memcpy(trampolineAddr, original_bytes, HookLen);
// 跳转回原函数剩下的部分
BYTE jmpBack[5] = { 0xE9 };
intptr_t backOffset = (intptr_t)(TARGET_ADDR + HookLen) - ((intptr_t)trampolineAddr + HookLen + 5);
*(DWORD*)(jmpBack + 1) = (DWORD)backOffset;
memcpy((BYTE*)trampolineAddr + HookLen, jmpBack, 5);
// 写钩子跳转,前5字节jmp,其余填nop
BYTE jmpHook[HookLen];
jmpHook[0] = 0xE9;
intptr_t hookOffset = (intptr_t)HookFunction - ((intptr_t)TARGET_ADDR + 5);
*(DWORD*)(jmpHook + 1) = (DWORD)hookOffset;
for (int i = 5; i < HookLen; i++) {
jmpHook[i] = 0x90;
}
memcpy((LPVOID)TARGET_ADDR, jmpHook, HookLen);
FlushInstructionCache(GetCurrentProcess(), (LPCVOID)TARGET_ADDR, HookLen);
VirtualProtect((LPVOID)TARGET_ADDR, HookLen, oldProtect, &oldProtect);
}
void Unhook1() {
DWORD oldProtect;
if (!VirtualProtect((LPVOID)TARGET_ADDR, 15, PAGE_EXECUTE_READWRITE, &oldProtect)) {
std::cerr << "VirtualProtect failed in Unhook1\n";
return;
}
BYTE original_bytes[5];
memcpy(original_bytes, (LPVOID)trampolineAddr, 5);
memcpy((LPVOID)TARGET_ADDR, original_bytes, 5);
VirtualProtect((LPVOID)TARGET_ADDR, 15, oldProtect, &oldProtect);
}
void Unhook2() {
DWORD oldProtect;
if (!VirtualProtect((LPVOID)TARGET_ADDR2, 15, PAGE_EXECUTE_READWRITE, &oldProtect)) {
std::cerr << "VirtualProtect failed in Unhook2\n";
return;
}
BYTE original_bytes2[5];
memcpy(original_bytes2, (LPVOID)trampolineAddr2, 5);
memcpy((LPVOID)TARGET_ADDR2, original_bytes2, 5);
VirtualProtect((LPVOID)TARGET_ADDR2, 15, oldProtect, &oldProtect);
}
void Unhook3() {
DWORD oldProtect;
if (!VirtualProtect((LPVOID)TARGET_ADDR3, 15, PAGE_EXECUTE_READWRITE, &oldProtect)) {
std::cerr << "VirtualProtect failed in Unhook2\n";
return;
}
BYTE original_bytes3[5];
memcpy(original_bytes3, (LPVOID)trampolineAddr3, 5);
memcpy((LPVOID)TARGET_ADDR3, original_bytes3, 5);
VirtualProtect((LPVOID)TARGET_ADDR3, 15, oldProtect, &oldProtect);
}
void Unhook4() {
DWORD oldProtect;
if (!VirtualProtect((LPVOID)TARGET_ADDR4, 15, PAGE_EXECUTE_READWRITE, &oldProtect)) {
std::cerr << "VirtualProtect failed in Unhook2\n";
return;
}
BYTE original_bytes4[5];
memcpy(original_bytes4, (LPVOID)trampolineAddr4, 5);
memcpy((LPVOID)TARGET_ADDR4, original_bytes4, 5);
VirtualProtect((LPVOID)TARGET_ADDR4, 15, oldProtect, &oldProtect);
}
void Unhook5() {
DWORD oldProtect;
if (!VirtualProtect((LPVOID)TARGET_ADDR5, 15, PAGE_EXECUTE_READWRITE, &oldProtect)) {
std::cerr << "VirtualProtect failed in Unhook2\n";
return;
}
BYTE original_bytes5[5];
memcpy(original_bytes5, (LPVOID)trampolineAddr5, 5);
memcpy((LPVOID)TARGET_ADDR5, original_bytes5, 5);
VirtualProtect((LPVOID)TARGET_ADDR5, 15, oldProtect, &oldProtect);
}
void Unhook6() {
DWORD oldProtect;
if (!VirtualProtect((LPVOID)TARGET_ADDR6, 15, PAGE_EXECUTE_READWRITE, &oldProtect)) {
std::cerr << "VirtualProtect failed in Unhook2\n";
return;
}
BYTE original_bytes6[5];
memcpy(original_bytes6, (LPVOID)trampolineAddr6, 5);
memcpy((LPVOID)TARGET_ADDR6, original_bytes6, 5);
VirtualProtect((LPVOID)TARGET_ADDR6, 15, oldProtect, &oldProtect);
}
void Unhook7() {
DWORD oldProtect;
if (!VirtualProtect((LPVOID)TARGET_ADDR7, 15, PAGE_EXECUTE_READWRITE, &oldProtect)) {
std::cerr << "VirtualProtect failed in Unhook2\n";
return;
}
BYTE original_bytes7[5];
memcpy(original_bytes7, (LPVOID)trampolineAddr7, 5);
memcpy((LPVOID)TARGET_ADDR7, original_bytes7, 5);
VirtualProtect((LPVOID)TARGET_ADDR7, 15, oldProtect, &oldProtect);
}
// 在DLL入口中调用
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
printf("%s\n", aNameChina);
printf("%s\n", aLoadbriefChina);
printf("%s\n", aNameHowi);
// 打印 wchar_t 字符串
wprintf(L"%s\n", aNameTtnk);
wprintf(L"%s\n", aLoadbriefRussi);
wprintf(L"%s\n", aNameRussians);
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
InstallHookX(TARGET_ADDR, trampolineAddr, HookFunction);
InstallHookX(TARGET_ADDR2, trampolineAddr2, loc_53649F);
InstallHookX(TARGET_ADDR3, trampolineAddr3, loc_5367A7);
InstallHookX(TARGET_ADDR4, trampolineAddr4, loc_536A62);
InstallHookX(TARGET_ADDR5, trampolineAddr5, HookFunction5);
//InstallHookX(TARGET_ADDR6, trampolineAddr6, HookFunction6);
//InstallHookX(TARGET_ADDR7, trampolineAddr7, HookFunction7);
break;
case DLL_PROCESS_DETACH:
Unhook1();
Unhook2();
Unhook3();
Unhook4();
Unhook5();
//Unhook6();
//Unhook7();
break;
}
return TRUE;
}