从 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 覆盖到您注入的代码中,将游戏代码中的流引导到您自己的代码中