游戏为 Tower.Tactics.Liberation
游戏使用引擎 Godot Engine, 版本3.5.2
游戏中的数值全是脚本中修改, 内部名称为GDScript
游戏运行中脚本的主函数为GDScriptFunction__call, 脚本运行时的ip值只有在栈上储存, 需要在函数中间Hook, 获取到脚本的ip, 顺便一起获取codeptr
AsmHook::HOOK_INFO Info_GDScript_CodeIp;
BOOL WINAPIV Hook_GDScript_CodeIp(VOID *pUserParam, AsmHook::PUSHAD_DAT *pReg)
{
COtherHook *pThis = (COtherHook *)pUserParam;
#ifdef _WIN64
gpCodePtrRun = (int *)pReg->rdx;
codeip = (int)pReg->rax;
return TRUE;
#endif
return TRUE;
}
/*
.text:000000014025DE9A 4C 8B 65 38 mov r12, [rbp+5D0h+script]
.text:000000014025DE9E 4C 8B 75 18 mov r14, [rbp+5D0h+p_stack]
.text:000000014025DEA2 E9 49 93 FF FF jmp loc_1402571F0
.text:000000014025DEA7 ; ---------------------------------------------------------------------------
.text:000000014025DEA7
.text:000000014025DEA7 loc_14025DEA7: ; CODE XREF: GDScriptFunction__call+A45↑j
.text:000000014025DEA7 48 8D 42 FC lea rax, [rdx-4]
*/
BOOL COtherHook::HookGDScript_CodeIp()
{
BOOL bRetVal;
bRetVal = m_pMgr->HookItem(Hook_GDScript_CodeIp, this, &Info_GDScript_CodeIp, 0, "4C8B65384C8B7518E94993FFFF488D42FC");
return TRUE;
}
实际修改值在 Variant__SetVal, 如游戏中gold修改
判断条件:
- 修改的值类型 double
- 当前的ip
- 当前ip的代码片段hash
AsmHook::HOOK_INFO Info_Variant__SetVal;
BOOL WINAPIV Hook_Variant__SetVal(VOID *pUserParam, AsmHook::PUSHAD_DAT *pReg)
{
COtherHook *pThis = (COtherHook *)pUserParam;
static void * DbgPtr = (void *)0x16059768;
#ifdef _WIN64
void *param64[8];
void *backaddr;
void *Self, *Value;
Variant *pValue, *pSelf;
DWORD dwHash;
double dAddVal;
Self = (void *)pReg->rcx;
Value = (void *)pReg->rdx;
pSelf = (Variant *)Self;
pValue = (Variant *)Value;
if(pSelf->type == Variant::REAL)
{
if(DbgPtr == &pSelf->_data._real)
int ccc = 0;
if(codeip == 0x0b)
{
dwHash = NData::HashData(gpCodePtrRun+codeip, sizeof(int)*16);
if(dwHash == 0x120ec788)
{
dAddVal = pValue->_data._real - pSelf->_data._real;
if(dAddVal > 0.0)
{
dAddVal *= 8;
pValue->_data._real = pSelf->_data._real + dAddVal;
NSys::TraceL("Gold add mul 8");;
}
}
}
}
return TRUE;
#endif
return TRUE;
}
/*
.text:0000000141A93090 48 3B CA cmp rcx, rdx
.text:0000000141A93093 0F 84 73 03 00 00 jz locret_141A9340C // 包含jmp 无法Hook
.text:0000000141A93099 48 89 5C 24 10 mov [rsp+arg_8], rbx // 从这开始Hook
.text:0000000141A9309E 48 89 6C 24 18 mov [rsp+arg_10], rbp
.text:0000000141A930A3 56 push rsi
.text:0000000141A930A4 57 push rdi
.text:0000000141A930A5 41 54 push r12
.text:0000000141A930A7 41 56 push r14
.text:0000000141A930A9 41 57 push r15
.text:0000000141A930AB 48 83 EC 40 sub rsp, 40h
*/
BOOL COtherHook::HookVariant__SetVal()
{
BOOL bRetVal;
bRetVal = m_pMgr->HookItem(Hook_Variant__SetVal, this, &Info_Variant__SetVal, 0,
"483BCA0F847303000048895C241048896C241856574154415641574883EC40", NULL, 9);
return TRUE;
}
标签:Engine,__,Godot,游戏,text,void,Variant,Hook,pReg
From: https://www.cnblogs.com/zzz3265/p/18455812