观前提示:本文并非速通指南,偏向于如何一步步思考与解题,也许会分析得有些拖沓。且本文为系列文章,每一篇会分析一关的破解思路,前文提到的知识点后面不会赘述,分析过的类似的汇编代码段也不会再分析,除非是没见过的结构,所以越往后分析得越少。
本文共一千一百余字。
前言
如果这些解析对你有帮助,那么我会非常荣幸和开心!
如果我的解析存在错误,非常抱歉误导了你!请在评论区提出!我也是一个正在不断学习的学生。
谢谢你!
正式破解
概览全局
白色部分是需要开始分析的地方。其他部分是一些栈操作和堆栈溢出检查,与解题无关,简单说就是程序最开始设置一个值,执行过程中如果发生溢出情况,这个值就会被溢出的数值覆盖掉,最后检查这个值有没有变过,就可以知道有没有发生过溢出。后记会附上几个详细解释的文章链接。
这一关没什么新玩意,只是一些跳转赋值,所以只提几个稍微需要注意的小点。
(1)跳转指令的区别
-
jmp *0x804a000(,%eax,4)
这是一条间接跳转指令。它的含义是跳转到存储在内存地址0x804a000 + 4 * %eax的位置的指令。这种寻址方式通常用于实现函数指针的跳转。具体来说,它会读取内存地址0x804a000 + 4 * %eax处的内容,将其解释为一个地址,并跳转到那个地址所指向的指令。
-
jmp 0x804a000(,%eax,4)
这是一条直接跳转指令。它的含义是将当前指令指针增加到存储在内存地址0x804a000 + 4 * %eax的值,然后继续执行该地址上的指令。换句话说,它不会读取内存中的内容,而是直接将地址作为跳转目标。
总结区别:
- 第一条指令是间接跳转,它从内存中读取一个指针值并跳转到该指针所指的位置。
- 第二条指令是直接跳转,它将内存中的值作为一个偏移量,将当前指令指针增加该偏移量,并跳转到结果地址上的指令。
所以,来到这一步的时候,需要用到x/a
命令,它用于查看内存中存储的指针值,并将这些值解释为内存地址。a指的是address。
然后下一步就会跳转到0x8048c38 <phase_3+131>处继续执行命令。
(2)输入参数个数的限制方法
0x08048bd7 <+34>: call 0x8048810 <__isoc99_sscanf@plt>
0x08048bdf <+42>: cmp $0x1,%eax
0x08048be2 <+45>: jg 0x8048be9 <phase_3+52>
0x08048be4 <+47>: call 0x804907d <explode_bomb>
可能有的人是这样推理的:sscanf出来后,eax存的是输入参数的个数,cmp指令和jg指令连起来看就是:if eax greater than 1, jump to <phase_3+52>, if not, call <explode_bomb>.
0x08048be9 <+52>: cmpl $0x7,0x4(%esp) ;查看内存可以发现0x4(%esp)是我们输入的第一个参数
0x08048bee <+57>: ja 0x8048c2c <phase_3+119>;结合下文知道<phase_3+119>会引爆炸弹
然后接着分析,cmpl指令和ja指令连起来看就是:if input above 7,jump to 0x8048c2c to call <explode_bomb>.
所以得出我们的输入个数要大于1,而且第一个数值要小于等于7,再加上一般自己测试不会想到负数,所以看上去也对,也不会触发炸弹。但是,这忽略了一点细节:
ja
指令: “Jump if Above” 的缩写,它用于无符号整数的比较。jg
指令: “Jump if Greater” 的缩写,它用于有符号整数的比较。
所以实际上,更完整地说,cmpl指令和ja指令连起来限制了第一个数值要小于等于7,同时,也限制了它要大于等于0。因为负数的最高位会是1,正数是0,如果按无符号数比较,即把符号位按数值位来解析,负数会大于正数。
还原成C代码
void phase_3(char *input){
int numbersInput[2];
int num = sscanf(input, "%d %d", &numbersInput[0],&numbersInput[1]);
if(num > 1){
int result;
if( (unsigned int) numbersInput[1] <= 7 ){ //无符号比较
switch (numbersInput[0]) {
case 0:
result = 979;break;
case 1:
result = 790;break;
// 其余 case 分支 略 会一直到case 7
}
if(numbersInput[1] == result){
return;
}
}
}
explode_bomb();
}
后记
详细参考文章:
what-is-gs-in-assembly
what-does-this-instruction-do-mov-gs0x14-eax
感谢你看到这里!