从 EAs FIFA 19 读取分数
Read score from EAs FIFA 19
你好堆栈溢出,
我打算创建一个程序,当它在足球模拟器 FIFA 19 中实际进球时播放主队的守门员。
我知道游戏本身没有开放 API。我看到使用的唯一方法是实际从内存中轮询结果。我不知道这是否符合游戏的最终用户许可协议,但我没有想以任何方式实际作弊。
为了研究,我从 https://github.com/xAranaktu/FIFA-19---Career-Mode-Cheat-Table 找到并查找了 Cheat Engine Table。它提供了通过 Cheat Engine 读取或写入匹配分数的能力。
遗憾的是,我无法对 table 进行逆向工程。我找到了从内存中读取值的代码。但是我很难弄清楚每一行的作用。
[ENABLE]
aobscanmodule(INJECT_matchScore,FIFA19.exe,48 8B 41 20 48 89 42 20 8B 41 28 89 42 28 41 8B 54) // should be unique
alloc(matchscore_cave,00,"FIFA19.exe"+2578D85)
alloc(ptrHomeTeamScore, 8)
registersymbol(ptrHomeTeamScore)
ptrHomeTeamScore:
dq 00
alloc(ptrAwayTeamScore, 8)
registersymbol(ptrAwayTeamScore)
ptrAwayTeamScore:
dq 00
label(code_matchscore)
label(home_matchscore)
label(away_matchscore)
label(return_matchscore)
matchscore_cave:
pushf
cmp rdx, 00
je home_matchscore
cmp rdx, 01
je away_matchscore
jmp code_matchscore
home_matchscore:
mov [ptrHomeTeamScore], rcx
jmp code_matchscore
away_matchscore:
mov [ptrAwayTeamScore], rcx
jmp code_matchscore
code_matchscore:
mov r8d,[rcx+0000011C]
popf
jmp return_matchscore
INJECT_matchScore+5B:
jmp matchscore_cave
nop
nop
return_matchscore:
registersymbol(INJECT_matchScore)
我对什么是指针、堆栈以及汇编程序的作用有基本的了解。但我无法理解这里发生的事情。也许你可以给我逐行描述发生了什么。
提前谢谢你。
本质上这是一个钩子,它使用 Cheat Engine 脚本功能将代码流引导到您注入的 shellcode 中。我将把每一行分解成它的基本目的,以帮助解释它。在 Cheat Engine Wiki
中了解更多信息
aobscanmodule(INJECT_matchScore,FIFA19.exe,48 8B 41 20 48 89 42 20 8B 41 28 89 42 28 41 8B 54) // should be unique
扫描该特定模式的进程,将匹配模式的位置存储在 INJECT_matchScore
alloc(matchscore_cave,00,"FIFA19.exe"+2578D85)
在"FIFA19.exe"+2578D85附近分配内存,大小为1000字节,并存储此内存的地址inmatchscore_cave。这是你的 shellcode 将被放置的地方
alloc(ptrHomeTeamScore, 8)
registersymbol(ptrHomeTeamScore)
ptrHomeTeamScore:
dq 00
分配8个字节存放一个64位的指针,注册变量符号名并赋QWORD值为0x0
alloc(ptrAwayTeamScore, 8)
registersymbol(ptrAwayTeamScore)
ptrAwayTeamScore:
dq 00
同上
label(code_matchscore)
label(home_matchscore)
label(away_matchscore)
label(return_matchscore)
为您可以跳转到的装配块创建一些标签,定义如下
matchscore_cave:
pushf
cmp rdx, 00
je home_matchscore
cmp rdx, 01
je away_matchscore
jmp code_matchscore
推旗
如果 rdx == 0,跳转到 home_matchscore
否则,如果 rdx == 1,跳转到 away_matchscore
否则 jmp code_matchscore
home_matchscore:
mov [ptrHomeTeamScore], rcx
jmp code_matchscore
away_matchscore:
mov [ptrAwayTeamScore], rcx
jmp code_matchscore
获取rcx中存储的指针并将其存储在ptrHomeTeamScore中
code_matchscore:
mov r8d,[rcx+0000011C]
popf
jmp return_matchscore
在RCX的偏移量0x11C处,获取值并将其存储在寄存器r8d中
弹出标志,将它们恢复到初始挂钩之前的状态
跳跃
INJECT_matchScore+5B:
jmp matchscore_cave
nop
nop
将原始程序集和 jmp 覆盖到您注入的代码中,将游戏代码中的流引导到您自己的代码中
你好堆栈溢出,
我打算创建一个程序,当它在足球模拟器 FIFA 19 中实际进球时播放主队的守门员。
我知道游戏本身没有开放 API。我看到使用的唯一方法是实际从内存中轮询结果。我不知道这是否符合游戏的最终用户许可协议,但我没有想以任何方式实际作弊。
为了研究,我从 https://github.com/xAranaktu/FIFA-19---Career-Mode-Cheat-Table 找到并查找了 Cheat Engine Table。它提供了通过 Cheat Engine 读取或写入匹配分数的能力。
遗憾的是,我无法对 table 进行逆向工程。我找到了从内存中读取值的代码。但是我很难弄清楚每一行的作用。
[ENABLE]
aobscanmodule(INJECT_matchScore,FIFA19.exe,48 8B 41 20 48 89 42 20 8B 41 28 89 42 28 41 8B 54) // should be unique
alloc(matchscore_cave,00,"FIFA19.exe"+2578D85)
alloc(ptrHomeTeamScore, 8)
registersymbol(ptrHomeTeamScore)
ptrHomeTeamScore:
dq 00
alloc(ptrAwayTeamScore, 8)
registersymbol(ptrAwayTeamScore)
ptrAwayTeamScore:
dq 00
label(code_matchscore)
label(home_matchscore)
label(away_matchscore)
label(return_matchscore)
matchscore_cave:
pushf
cmp rdx, 00
je home_matchscore
cmp rdx, 01
je away_matchscore
jmp code_matchscore
home_matchscore:
mov [ptrHomeTeamScore], rcx
jmp code_matchscore
away_matchscore:
mov [ptrAwayTeamScore], rcx
jmp code_matchscore
code_matchscore:
mov r8d,[rcx+0000011C]
popf
jmp return_matchscore
INJECT_matchScore+5B:
jmp matchscore_cave
nop
nop
return_matchscore:
registersymbol(INJECT_matchScore)
我对什么是指针、堆栈以及汇编程序的作用有基本的了解。但我无法理解这里发生的事情。也许你可以给我逐行描述发生了什么。
提前谢谢你。
本质上这是一个钩子,它使用 Cheat Engine 脚本功能将代码流引导到您注入的 shellcode 中。我将把每一行分解成它的基本目的,以帮助解释它。在 Cheat Engine Wiki
中了解更多信息aobscanmodule(INJECT_matchScore,FIFA19.exe,48 8B 41 20 48 89 42 20 8B 41 28 89 42 28 41 8B 54) // should be unique
扫描该特定模式的进程,将匹配模式的位置存储在 INJECT_matchScore
alloc(matchscore_cave,00,"FIFA19.exe"+2578D85)
在"FIFA19.exe"+2578D85附近分配内存,大小为1000字节,并存储此内存的地址inmatchscore_cave。这是你的 shellcode 将被放置的地方
alloc(ptrHomeTeamScore, 8)
registersymbol(ptrHomeTeamScore)
ptrHomeTeamScore:
dq 00
分配8个字节存放一个64位的指针,注册变量符号名并赋QWORD值为0x0
alloc(ptrAwayTeamScore, 8)
registersymbol(ptrAwayTeamScore)
ptrAwayTeamScore:
dq 00
同上
label(code_matchscore)
label(home_matchscore)
label(away_matchscore)
label(return_matchscore)
为您可以跳转到的装配块创建一些标签,定义如下
matchscore_cave:
pushf
cmp rdx, 00
je home_matchscore
cmp rdx, 01
je away_matchscore
jmp code_matchscore
推旗 如果 rdx == 0,跳转到 home_matchscore 否则,如果 rdx == 1,跳转到 away_matchscore 否则 jmp code_matchscore
home_matchscore:
mov [ptrHomeTeamScore], rcx
jmp code_matchscore
away_matchscore:
mov [ptrAwayTeamScore], rcx
jmp code_matchscore
获取rcx中存储的指针并将其存储在ptrHomeTeamScore中
code_matchscore:
mov r8d,[rcx+0000011C]
popf
jmp return_matchscore
在RCX的偏移量0x11C处,获取值并将其存储在寄存器r8d中 弹出标志,将它们恢复到初始挂钩之前的状态 跳跃
INJECT_matchScore+5B:
jmp matchscore_cave
nop
nop
将原始程序集和 jmp 覆盖到您注入的代码中,将游戏代码中的流引导到您自己的代码中