CE训练教程进阶,步骤 9: 注入++

目录

一、找出存放四个玩家健康值的地址

二、找出修改数据的代码

三、找出是谁调用了修改指令

四、分析玩家的内存数据

五、注入修改代码

六、注入C语言代码

七、注入lua代码


相对于前面8个步骤,步骤9稍微要难一点,所以单独写。

 步骤9是在步骤7的基础上,继续讲代码注入。但是它涉及到代码的细粒度区分,比如“攻击”时,上面4个玩家用到的都是同一段代码,这就需要通过代码去判断,什么时候是在攻击自己玩家(玩家1,玩家2),什么时候是在攻击敌方玩家。

一、找出存放四个玩家健康值的地址

精确查找,分别找出存放四个玩家健康值数据的地址,并双击添加到地址栏。注意查找时,数值类型要选单浮点,因为健康值为小数。当然,如果不知道数值是什么类型,也可以用"未知的初始值"查找,只是要麻烦一点

二、找出修改数据的代码

在四个玩家的地址上,右键选择“找出是什么改写了这个地址”后,再点击“攻击”该玩家,修改该玩家健康值的指令就会显示出来。

 最后会发现,攻击每个玩家时,调用的都是这条指令:

10002F25D - F3 0F11 43 08  - movss [rbx+08],xmm0

所以,我们不能直接修改这条指令,实现攻击己方玩家时健康值增加,攻击敌方玩家时健康值降低。

当然,我们说的仅仅是在“攻击”时,如果直接修改玩家的健康值,是可以成功的。

三、找出是谁调用了修改指令

我们需要用反汇编的方式,继续往前找,找出是谁调用了修改健康值的指令。

右键选择“找出指令访问的地址”:

 再分别攻击这四个玩家,四个玩家健康值地址就会显示出来。

 当然,如果我们只是找这个四个玩家健康值的地址,前面早就找出来了,根本不用这么麻烦。下面的步骤才是关键,那就是分析数据。

四、分析玩家的内存数据

选中四个玩家地址,然后右键选择“打开选中地址的分析数据”:

 上面界面选了后,会弹出一个框,点确定即可。

 

 然后给这个数据结构取一个名字:

 然后会弹出一个框,点击“yes”:

 

 这个结构的起始大小默认是4096,点击“ok”:

 

 然后这个数据分析的界面就出现了:

 上面这个界面,分别显示了4个玩家对应的内存数据,我们最开始就已经知道,Dave和Eric是一队,而HAL和KITT是另一个队的。通过上面的数据会发现,只有蓝色框框出的那行,比较符合这个规则。

那么这个界面的作用是什么?

1.找出区分队伍的数据地址偏移量,即+0014;

2.找出各玩家健康值的偏移量,即+0008。

五、注入修改代码

回到汇编界面,点击“自动汇编”:

先选择“CT表框架代码”:

 

 再选择“代码注入”,并填写地址:

 然后会生成一段模板代码,需要稍微改下:

[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048,"Tutorial-x86_64.exe"+2F25D) 
label(returnhere)
label(originalcode)
label(exit)

newmem:
  cmp [rbx+14],1//第1队玩家
  je team1
  cmp [rbx+14],2//第2队玩家
  je team2

team1:
  movss xmm0,[rbx+08]// [rbx+08]就是原健康值的地址,即攻击第1队玩家时健康值不变
  jmp originalcode

team2:
  movss xmm0,[value2]// 第2队敌方玩家的健康值为0
  jmp originalcode

value2:
  dd (float)0

originalcode:
movss [rbx+08],xmm0

exit:
jmp returnhere

"Tutorial-x86_64.exe"+2F25D:
jmp newmem
returnhere:
 
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"Tutorial-x86_64.exe"+2F25D:
movss [rbx+08],xmm0
//Alt: db F3 0F 11 43 08

 上面代码看起很多,实际只有中间那段是手写的,作用就是:

如果玩家是1队的,健康值不变;如果玩家是2队的,健康值设为0。

保存脚本,然后选择“文件”菜单中的“分配到当前CT表”:

回到CE主界面,激活自动汇编脚本:

 然后点击Tutorial-x86_64.exe的步骤9界面,点击“重新启动游戏并自动执行”,然后随便“攻击”一个玩家,就可以激活“下一步”按钮了。

六、注入C语言代码

直接修改汇编代码,需要对汇编指令相当熟悉才可以,而且逻辑稍微复杂一点,修改起来会相当繁琐。比较幸运的是,在CE中,居然可以直接使用C语言的代码来编写。

下面我用C语言来实现一个功能,那就是:

攻击己方玩家时,健康值减少10;而攻击敌方玩家时,健康值减少100。

[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048,"Tutorial-x86_64.exe"+2F25D) 
label(returnhere)

{$c}
// {$c} 表示c语言代码块,可以定义我们需要调用的函数。
void SetHP(void* hpBase)
{
   if(*(int*)(hpBase+0x14)!=1){
     *(float*)(hpBase+0x8)=*(float*)(hpBase+0x8)-100; //攻击敌方玩家,健康值减少100。
   }else{
     *(float*)(hpBase+0x8)=*(float*)(hpBase+0x8)-10; //攻击己方玩家,健康值减少10。
   }
}
{$asm}//c代码块结束

newmem:
// 注意这是里用的是ccode,hpBase代表参数名,rbx代表参数值
{$ccode hpBase=rbx}
  SetHP(hpBase);
{$asm}
  jmp returnhere

"Tutorial-x86_64.exe"+2F25D:
jmp newmem
returnhere:
 
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"Tutorial-x86_64.exe"+2F25D:
movss [rbx+08],xmm0

上面代码总体来说,比汇编代码要容易读一些,也精简了不少,实现效果如下:

最后再说一点,关于movss指令:

MOVSS,Move scalar single precision floating-point value between XMM registers or between an XMM register and memory.

存放float类型的数据大多是xmm寄存器,而movss指令(SSE指令集之一)则用来移动单精度float类型的数据。

七、注入lua代码

除了可以内嵌C语言的代码外,还可以支持lua代码内嵌,把上面的C语言版本改成lua后,代码如下:

[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,2048,"Tutorial-x86_64.exe"+2F25D) 
label(returnhere)

{$lua}//我在win7 64位上面,不加下面这段代码,就不能运行luacode
if not getAddressSafe('luaclient-x86_64.dll') then
  assert(injectDLL('luaclient-x86_64.dll'))
end
{$asm}

newmem:
//hpBase代表参数名,rbx代表参数值
{$luacode hpBase=rbx}
  if readInteger(hpBase+0x14)==1
  then
    writeFloat(hpBase+0x8,readFloat(hpBase+0x8)-10.0)
  else
    writeFloat(hpBase+0x8,0)
  end

{$asm}//这里必须要顶格写,不然会报错
  jmp returnhere

"Tutorial-x86_64.exe"+2F25D:
jmp newmem
returnhere:
 
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"Tutorial-x86_64.exe"+2F25D:
movss [rbx+08],xmm0

 lua语法更加简洁一些,但是在我的电脑(win7 64位)上,需要手动注入luaclient.dll,不然不能运行。

注意,{$asm}、{$ccode}、{$c}、{$lua}、{$luacode}这些代码必须顶格写,前面不能有空格,不然会报错

参考文章:

Cheat Engine

Cheat Engine Tutorial Guide (x64) - Cheat Engine

【CheatEngine基础教程】拾遗篇 - 哔哩哔哩

  • 7
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
这个错误是因为在提取头像的代码中,变量 `y`、`h`、`x` 和 `w` 没有被定义。你需要根据实际情况调整这些变量的值,以确保正确地提取头像。 这些变量通常代表头像在图像中的位置和大小。你可以使用 OpenCV 的图像处理功能(如人脸检测)来获取这些值。 以下是一个示例,展示如何使用 OpenCV 的人脸检测器来提取头像: ```python import cv2 # 加载人脸检测器 face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml') # 加载图像 image = cv2.imread('image.jpg') # 将图像转换为灰度图像 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 使用人脸检测器检测人脸 faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30)) # 遍历检测到的人脸 for (x, y, w, h) in faces: # 提取头像 face = image[y:y+h, x:x+w] # 在头像周围绘制矩形框(可选) cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2) # 显示图像及提取的头像(可选) cv2.imshow('Image', image) cv2.imshow('Face', face) cv2.waitKey(0) cv2.destroyAllWindows() ``` 请注意,该示例仅提供了一个基本的人脸检测方法,并提取了第一个检测到的人脸作为头像。你可能需要根据实际情况调整参数和处理逻辑,以便正确地提取头像。 在代码中,我们使用了名为 `haarcascade_frontalface_default.xml` 的分类器文件,用于检测人脸。你可以从 OpenCV 官方 GitHub 存储库中下载该文件(https://github.com/opencv/opencv/tree/master/data/haarcascades)。 请确保在运行代码之前已将该文件放置在正确的位置,并正确安装了 OpenCV 库。 希望这可以帮助你解决问题。如有进一步的疑问,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值