17.CE练习
任务
将完成CE自带小练习1~8
这篇写的有点乱了qwq
第一关:
知识点:
- 精确扫描
- 通过数值变化确定地址
任务就是将这个100改成1000,我们可以通过CE打开这个小练习,然后扫描类型选中精确数值,数值类型从4字节开始(这个值有可能是char short int等等)我们从可能性大的DWORD 开始找,然后点击首次扫描就行了。
扫描后这里出现很多100啊,我们应该怎么找到那个100的值呢。这就是CE的精髓了,需要通过寻找变化来获取到那个地址。就例如这里的打我会让数值降低到97,那我们在精确数值那里输入97再次扫描就能看到排除了很多选项了
这个地址的97应该就是我们需要的了,直接双击一下,然后在数值那里改成1000,就可以下一步了:
第二关:
知识点:
- 介于两者之间的扫描类型
- 通过变化扫描
OK,那我们这次就可以在新的扫描前选择介于两者之间
然后回到CE的精髓就是变化,点击”打我”让这个地址的数值发生变化,然后在扫描类型中选择数值变化的方向(增加还是减少)这里”打我”了两次,第二次是-9,那就是数值减少了9,然后再进行再次扫描就扫出来了,然后直接把这个值改成题目要求的就能过了。
第三关
知识点:
- 单精度,双精度浮点扫描
在前面的教程中我们使用字节的方式进行扫描,但有些游戏使用了”浮点数”来存储数值(这么做是为了给菜鸟制造一些麻烦,让他们没那么容易修改游戏)。
正如本关中的健康和弹药,两者都以浮点方法储存数据,不同的是,健康值为单精度浮点数,而弹药值为双精度浮点数。
点击”打我”将减少一些健康值,而点击”开火”则消耗掉 0.5 的弹药。
这个的话就按照上面的方法然后将数值类型换成单浮点和双浮点一个个找就行了。
第四关
知识点:
- 找出什么改写了这个地址的使用
- 修改汇编代码
这关的要求就是:点击改变数值时不让这个数值发生变化
我们可以先通过精确查找找出这个值存放的位置,(观察bianhua!!),接着可以右键查看是什么改写了该地址。就是看看什么指令对这个地址操作了,然后查看汇编窗口直接修改指令就好了。

右键选框,然后再选择找出是什么改写了这个地址,接着就会打开弹出这个页面,选择改变数值后右边的窗口就会出现让这个地址里面的值改变的代码,这时候选中这条指令,显示反汇编程序,就可以将这个指令进行修改了,要想数值不变,直接将这个指令改成nop就行。
可以看到当我们点击改变数值的时候这个值也不会变化了,下一步按钮也亮了
第五关
知识点:
- 指针
- 通过添加地址来设置指针
上一关使用了代码查找器,这一关则使用指针的方法确定地址。
点击 改变数值
数值都会改变。点击 改变指针
有点类似重新开始一局游戏,这意味着,数值的地址会改变。
你需要做的是:将数值锁定在5000,即使点击 改变指针
改变了数值所在地址之后。
首先先通过前面的步骤先找到这个数值所在的地址。然后通过 “找出是什么改写了该地址” 找出这个值变化的指令:
OK,那么这个就是改变数值的指令。不难发现这个[rdx]
就是个指针,然后选中这条指令,详细信息,就可以看到rdx的值。
此时的rdx是这个值,我们直接选择新的扫描,然后把十六进制勾上

这里出现了两个,直觉告诉我是第二个才是。在大一点的程序中分析时搜一个值可能会出现多个情况,这下就要逐一排查了。这里我选择第二个。然后这里存储的就是那个地址了嘛,右键然后更改记录,选择地址

然后勾选指针,可以看出这个就是存着 存着数值的那个地址 的地址了。然后点击确定
这里改成5000,然后激活勾选上(里面的值锁定),点击改变指针就发现5000被锁定了。OK下一关
第六关:代码注入
知识点:
- 当要修改一段指令的时长度不够怎么办
任务要求:点击改变数值时将数值增加
老样子,重复第四关的操作,知道打开正确的汇编代码页面,然后选中修改值的那条指令->工具->自动汇编
然后就会弹出这个框,选择模板,代码注入然后就会自动生成一个模板,在这里修改成add dword ptr [rsi+000007E0],02
就行

点击执行,再回到教程中点击改变数值就已经是增加了。
注入原理:
- 这里的代码注入原理其实与之前课程里面讲到的在空白区域加代码很像,只不过那个是在静态文件中加的,这个是在程序运行后加的
第七关:多级指针
知识点:
- 对指针和多级指针的汇编熟练度
任务要求:还是设置值,然后在改变指针时锁定这个值
还是老样子,先找出这个值所在的地址,然后找出是什么改变了这个地址
发现是这么个东西,这个样子就像是结构体。(不知道也不影响)然后我们记下这个指令和此时rsi的值:
1 | mov [rsi + 0x18] , eax |
那我们就开始往上找了。将这个rsi的值复制出来,然后新的扫描->十六进制->首次扫描,接着就找到了存这个rsi的地址了。
下一步我们右键这个选项,然后选择找出是谁访问了该地址。这里为什么不用改写呢?因为访问包括了改写,但是如果对这里的操作不一定是改写,也有可能是引用。(就是从里面拿值)
接下来找到有两条指令,第一条cmp就不管了没啥影响。直接看第二条,就是将rsi中的值当作地址然后取这个地址里面的值给到rsi,那么我们就来看看这个rsi是什么成分。
诶?不对啊,为什么这个rsi和外面选中的数值是一样的?这里就是CE的一个坑了,当我们选中这段指令的时候,下面各个寄存器的信息都是这条指令执行完之后的状态,也就是说这个rsi是mov完之后的值。那我们怎么找到之前的rsi呢?这里用两种方法:
- 断点调试:在汇编代码中这条指令的前一条指令下段,然后运行到那个位置,就能找到rsi的值了
- 想一想:我们当时找的不是谁访问了这个地方吗,当我们切换数值时这个
mov rsi,[rsi]
访问了这个地址,然后把这个地址,然后把rsi变成了163e170,那原来rsi是什么呢?不就是存着163e170的地址160b750了吗。接下来就按照上面的方法查找rsi所存的地址的值1
2mov rsi,[rsi]
记录下这次的指令和rsi的值:
1 | mov rsi,[rsi+0x18] |
这次就不能直接找这个地址的值了,因为这里的指令时mov rsi,[rsi+0x18]
是加上0x18的,所以找的时候得将地址减去0x18即0x1624180
重复操作,记下这个指令和rsi
1 | mov rsi,[rsi+0x10] |
接着继续搜15a1070
这里已经看见基址了,就说明找指针这个过程完成了,根据上述记录的各个操作我们可以得出以下式子:
1 | # [rsi+0x18] = [[rsi]+0x18] = [[[rsi+0x18]]+0x18] = [[[[rsi + 0x10]+0x18]]+0x18] |
这里的rsi指的是不同级的
所以最终的数值存放的位置用指针来表示就是:
1 | # [[[[基址 + 0x10]+0x18]]+0x18] |
我们在选中最下面的那个选项然后按照之前设置指针的方法将它设置成指针,但是要添加偏移量

点击确定后可以看到已经指向了数值位置了

我们将值改成5000然后锁定,改变指针然后就可以过关了。
总结
这只是CE的一个附带小程序,所以查找会比较方便。但是一些大一点的程序可能每次扫描出来的结果会有很多,这时候就得慢慢查找了。还得不断练习提升。