CE教程第八关
这个第八题我花了好几个小时,最后靠画图弄明白的。
不管是C语言还是反汇编,涉及到指针和内存,最直观的理解方式就是画图。
题目
步骤 8: 多级指针: (密码=525927)
在这一步将解释如何使用多级指针。 在第 6 步,你已经清楚 1 级指针的概念和用途,并可以利用数值的首个地址找到存放数据真正的基址。
在本关中,你将看到 4
级指针,它由第一个指针指向第二个指针,再由第二个指针指向第三个指针,由第三个指针指向第四个指针,最终指向健康值的真正地址。 开始的几步与在第
6
步中的操作基本相同。找出是什么访问了这个地址,然后分析汇编指令,查找指针地址中的数值,以及它的偏移量,将它们记下来。但这次你按数值找出的仍然是一个指针,你得依据这些数值,使用同样的操作方法找出指向这个指针的指针。看看是什么访问了你发现的那个指针地址,分析汇编指令,留意可能的代码和偏移量,并加以利用。
持续这种过程,直到不能更进一步查找为止(通常基址为静态时,地址将以绿色标示)。 点击"改变数值"改变健康值,
如果你发现列表中那些指针地址所指向的值发生同样的变化时,那表示你可以试着将基址中的值更改为 5000,并锁定它,以便完成本关的任务了。备注1: 本步骤也可以使用自动汇编程序脚本或者使用指针扫描器加以解决。 备注2: 在某些情况下,可以改变 CE 软件"代码查找"的相关设置。
当你遇到类似于 mov eax,[eax] 的指令时,调试程序将显示改变之后的寄存器中的值,也许利用它更容易找出指针的位置。备注3:
你还在读?!当你查看汇编指令时你可能已经注意到,这些指针是在相同的代码块(相同的程序,如果你懂汇编,可以查看程序的起始代码)位置被读写。这种情况并不总会发生,但是当你在查找某个指针遇到问题的时候,没准能起到很大的用处。
这关的意思是要找到指向变量的4级指针,在第六关的时候我学习了如何找1级指针,但是为了以后忘记了回来复习,我还是从头开始记录所有步骤。
解法
首先,让数值变化,最终找到数值存储的地址。
显然,在内存中是这样子的 ↓
由于变量值会改变,所以不写3261,用字符串value代替。
下一步,我想知道这个变量被哪条语句修改了,只需右键搜索结果,选择“找出是什么改写了这个地址”
然后点击游戏按钮,改变变量值。
发现是这条指令改写了变量值,esi+18 就是value的地址(也就是前面搜索到的0019DE10),eax是新值。esi 就是我们要找的第一个指针,它加上一个偏移量18就指向了value,做一个减法算出esi的值等于 0019DDF8。
要寻找二级指针,只需要找到是谁存储了 0019DDF8。
做法是开始新的扫描,16进制搜索 0019DDF8,
一般会找到唯一结果
内存示意图
接下来,希望找到谁通过 0019DDF8 修改了value,右键刚才的结果,选择“谁访问了…”
访问 06508070 可能就是间接修改value的代码。修改value,发现有两条语句访问了 06508070
我们要关注的是第二条 mov esi,[esi]
源操作数没有偏移,意味着二级指针不需要加偏移就能找到一级指针,示意图如下:
同样地,16进制搜索这个 06508070,找到其地址。(如果有多个结果,只需看看谁访问了它,修改value无结果的就可以排除了)
只有第五个地址,修改value会被访问。
和上一步一样的推理过程,画出内存示意图如下。
至此,找到了第二级指针。用同样的方法,直到找到颜色为绿色的地址,即第四级指针。
这个 006426E0 就是四级指针了。补上完整的内存示意图:
最后,点击手动添加地址,勾选指针,填入基址 006426E0,CE自动计算出三级指针的值 0011DD30,如下图:
根据内存示意图,依次添加 0C 14 0 18 偏移量,就能找到 value 啦!
最后根据题目要求,将数值改为5000,锁定他,然后改变指针,即可通关。
这关的意思是,有些变量是动态分配的,并且可能有多级指针,我们要找到最高级的那个不变的指针,才能一直修改变量。
#include <stdio.h>#include <malloc.h>int main(){//__asm {//moveax, 5//addeax, 6//}int *p1 = (int *)malloc(4);int **p2 = &p1;int ***p3 = &p2;int ****p4 = &p3;****p4 = 100;printf("%d\n", *p1);printf("%d\n", **p2);printf("%d\n", ***p3);printf("%d\n", ****p4);****p4 = 5000;printf("%d\n", *p1);printf("%d\n", **p2);printf("%d\n", ***p3);printf("%d\n", ****p4);return 0;}
以C语言举例,其实就是要找到 p4。