phase_4拆炸弹

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了phase_4拆炸弹相关的知识,希望对你有一定的参考价值。

08048cc1 <func4>: 8048cc1: 56 push %esi 8048cc2: 53 push %ebx 8048cc3: 83 ec 14 sub $0x14,%esp 8048cc6: 8b 54 24 20 mov 0x20(%esp),%edx 8048cca: 8b 44 24 24 mov 0x24(%esp),%eax 8048cce: 8b 5c 24 28 mov 0x28(%esp),%ebx 8048cd2: 89 d9 mov %ebx,%ecx 8048cd4: 29 c1 sub %eax,%ecx 8048cd6: 89 ce mov %ecx,%esi 8048cd8: c1 ee 1f shr $0x1f,%esi 8048cdb: 01 f1 add %esi,%ecx 8048cdd: d1 f9 sar %ecx 8048cdf: 01 c1 add %eax,%ecx 8048ce1: 39 d1 cmp %edx,%ecx 8048ce3: 7e 17 jle 8048cfc <func4+0x3b> 8048ce5: 83 e9 01 sub $0x1,%ecx 8048ce8: 89 4c 24 08 mov %ecx,0x8(%esp) 8048cec: 89 44 24 04 mov %eax,0x4(%esp) 8048cf0: 89 14 24 mov %edx,(%esp) 8048cf3: e8 c9 ff ff ff call 8048cc1 <func4> 8048cf8: 01 c0 add %eax,%eax 8048cfa: eb 20 jmp 8048d1c <func4+0x5b> 8048cfc: b8 00 00 00 00 mov $0x0,%eax 8048d01: 39 d1 cmp %edx,%ecx 8048d03: 7d 17 jge 8048d1c <func4+0x5b> 8048d05: 89 5c 24 08 mov %ebx,0x8(%esp) 8048d09: 83 c1 01 add $0x1,%ecx 8048d0c: 89 4c 24 04 mov %ecx,0x4(%esp) 8048d10: 89 14 24 mov %edx,(%esp) 8048d13: e8 a9 ff ff ff call 8048cc1 <func4> 8048d18: 8d 44 00 01 lea 0x1(%eax,%eax,1),%eax 8048d1c: 83 c4 14 add $0x14,%esp 8048d1f: 5b pop %ebx 8048d20: 5e pop %esi 8048d21: c3 ret

参考技术A 我不懂,如果还有时间你就把炸弹仍到游泳池里吧 参考技术B 答案为2个整数:14 45

CSAPP lab2 二进制拆弹 binary bombs phase_5 施工中

给出对应于7个阶段的7篇博客

phase_1  https://www.cnblogs.com/wkfvawl/p/10632044.html
phase_2  https://www.cnblogs.com/wkfvawl/p/10636214.html
phase_3  https://www.cnblogs.com/wkfvawl/p/10651205.html
phase_4  https://www.cnblogs.com/wkfvawl/p/10672680.html
phase_5  https://www.cnblogs.com/wkfvawl/p/10703941.html
phase_6  https://www.cnblogs.com/wkfvawl/p/10742405.html
secret_phase  https://www.cnblogs.com/wkfvawl/p/10745307.html

phase_5

 

phase_5要求输入一个包含6个字符的字符串。phase_5函数从中读取这些信息,并判断其正确性,如果不正确,则炸弹爆炸。

phase_5主要考察学生对指针(数组)机器级表示的掌握程度。

观察框架源文件bomb.c:

 

从上可以看出:

1、首先调用了read_line()函数,用于输入炸弹秘钥,输入放置在char* input中。

2、调用phase_5函数,输入参数即为input,可以初步判断,phase_5函数将输入的input字符串作为参数。

因此下一步的主要任务是从asm.txt中查找在哪个地方调用了readline函数以及phase_5函数。

1.1 寻找并分析调用phase_5函数的代码

打开asm.txt,寻找phase_5函数。

 

 

phase_1类似分析:

1、当前栈的位置存放的是read_line函数读入的一串输入;

2、phase_5的函数入口地址为0x8048df7

此时的函数栈为:

 

1.2 phase_5函数分析

继续寻找phase_5,或搜索8048df7,可以找到phase_5函数入口。如下图所示:

 

1541-547行:初始化函数栈帧,并为调用string_length做准备(此时ebx的内容为input字符串首地址:543行)。函数栈帧如下图所示:

注:

1544-545行:mov %gs:0x14, %eax   mov %eax, 0x1c(%esp),将gs(全局段寄存器)+0x14偏移位置的内容放置到eax,然后将其放置到esp + 0x1c的地方。从这里看不出这段代码什么含义,但据后面的分析,这里应该是起到一个“哨兵”的作用,防止数组访问越界。

2546行:xor %eax, %eax,似乎没有什么用,得出来的结果是0,应该只是影响zf标志寄存器(zf为零标志寄存器,即zf=1)。

 

2548行:判断input字符串的长度(esp指向的地方为input的首地址,参见上图),返回结果在eax寄存器中。

3549-551行:判断input的长度是否为6,如果不是,则炸弹爆炸(551行),如果是,跳转到8048e62<phase_5+0x6b>。也即输入的字符串长度应该是6

4、572-573行(8048e62<phase_5+0x6b>):eax寄存器内容赋值为0,然后跳转到8048e22<phase_5+0x2b>

5554行(<8048e22><phase_5+0x2b>):将ebx + eax * 1地址的内容送入到edx。注意, ebxinput首地址,也即将input[%eax]的内容送入到edx。当eax = 0时,即为edx的内容为input[0]

6555行:将edx的内容(input[0])与0x0f位与,相当于取低4位(edx内容为input[eax]的低四位)。

7、556行:将edx + 0x804a470指向的地址的内容送入到edx0x804a470的内容(使用objdump --start-address=0x804a470  -s bomb,参见phase_1分析过程)为:

 

从上面来看,0x804a470应该是指向一个字符串,此时edx的内容应该是0x804a470加上input[eax]4位的偏移的内容。

8557行:将dledx的低8位,为(0x804a470 +input[eax]) & 0xf)的内容送入到esp + eax * 1 + 0x15的地方。

9558-560行:eax += 1,然后判断eax的内容是否等于6,如果不等,则跳转到8048e22<phase_5+0x2b>,重新回到第5步继续进行分析,直到eax=6(即循环6次)。

10、以上代码,以类c语言来简要说明:

for(int i = 0; i < 6; i++){

//0x804a470 +  input[i] & 0x0f这个地址的内容送入到堆栈esp + i + 0x15地址中。

(0x804a470 +  input[i] & 0x0f)  --> (esp + i + 0x15)

}

经过6次循环后,函数栈帧如下:

 

 

显然,从esb + 0x15开始,是根据input的输入的每个字符的低四位,得出来的一个新的字符串。

11561行:以上循环结束后,跳出循环,执行该语句:esp + 0x1b的内容改变为0

12562行:将0x804a446送入到:esp+0x40x804a446的内容为(objdump --start-address=0x804a446 -s bomb):

 

 

也即当前esp+0x4指向的是一个字符串首地址,字符串为sabres

13564-565行:eax的内容变为esp + 0x15,即通过上面循环形成的新的字符串的首地址,然后将其送入到esp

14、调用strings_not_equal函数,显然,前面11~13均在为调用strings_not_equal做准备,调用strings_not_equal前,函数栈帧为:

 

15、显然,strings_not_equal函数判断以(esp + 0x15)为首地址的字符串与0x804a446为首地址的字符串(sabres)相比较,如相等,eax返回0,如不相等eax返回1。(参见phase_1分析)

16567行:判断eax是否为0eaxeax位与),如果为0,0标志寄存器为1

17568-569行:如果eax=0,则跳转到8048e69<phase_5+0x72>,后续直接退出phase_5了,说明输入的input字符串是正确的,否则引爆炸弹。(8048e69<phase_5+0x72>代码后面分析

18、574-577行:将esp + 0x1c地址处的内容送入到eax574行,esp+0x1c的内容应为%gs:0x14的内容),然后与%gs:0x14的内容相异或,如果相等(为0),则跳转到0x8048e7b,正常结束,否则调用__stack_chk_fail函数(应该是栈检查失败);

根据上面分析,%gs:0x14的值送入到esp+0x1c的地方(第544-545行),应该是起到一个“哨兵”的作用,防止数组的访问越界。

 

1.3 phase_5结果分析

根据前面分析,显然phase_5函数的作用(以类C语言进行描述):

 

char array[] = {\'m\',\'a\',\'d\',\'u\',\'i\',\'e\',\'r\',\'s\',\'n\',\'f\',\'o\',\'t\',\'v\',\'b\',\'y\',\'l\'};
char *str = "sabres";
char  new_str[7];
//根据input的每个字符的低4位,以及array,形成新的字符串。
for(int i = 0; i < 6; i ++)
{
    new_str[i] = array[input[i]&0xf]);
}
new_str[6] =\'\\0\';
//如果new_str不等于str("sabres"),则引爆炸弹。
if(strcmp(str, new_str) !=0)
{
    explode_bomb();
}

那么根据上面的代码反推,如果需要使构成的new_str=="sabres",那么输入的input[i]的低4位对应的十进制数分别是array[]数组中字符\'s\',\'a\',\'b\',\'r\',\'e\',\'s\'的下标。

根据以上分析,要形成"sabres"字符串:

array[] = {\'m\', \'a\', \'d\', \'u\', \'i\', \'e\', \'r\', \'s\', \'n\', \'f\', \'o\', \'t\', \'v\', \'b\', \'y\', \'l \'};

1\'s\':对应于array7个 (从0开始),也即input[0]的低4位应该为7,符合条件的可显示字符有:\'\'\'\'7 \'\'G\'\'W\'\'g\'\'w\'(参见附后的ASCII码表):

2\'a\':对应于array1个 (从0开始),也即input[1]的低4位应该为2,符合条件的可显示字符有:\'!\'\'1 \'\'A\'\'Q\',a\'\'q\'

3\'b\':对应于array13个(从0开始),也即input[2]的低4位应该为13,符合条件的可显示字符有:\'-\'\'=\'\'M\'\']\'\'m\', \'}\'

4\'r\':对应于array6个 (从0开始),也即input[3]的低4位应该为6,符合条件的可显示字符有:\'&\'\'6 \'\'F\'\'V\'\'f\'\'v\'

5\'e\':对应于array5个 (从0开始),也即input[4]的低4位应该为5,符合条件的可显示字符有:\'%\'\'5\'\'E\'\'U\'\'e\'\'u\'

6\'s\':对应于array7个 (从0开始),也即input[5]的低4位应该为7,符合条件的可显示字符有:\'\'\'\'7 \'\'G\'\'W\'\'g\'\'w\'

 

 

 

 

因此,对于本题,答案不是唯一的,为6组可选字符的排列组合,如"gamfeg""GAMFEG"等。

以上是关于phase_4拆炸弹的主要内容,如果未能解决你的问题,请参考以下文章

拆炸弹!bomb-whu,phase-1

二进制炸弹,汇编代码解读

二元炸弹 - 第 4 阶段

试图理解这个汇编 x86 代码

炸弹实验室第 6 阶段:卡在最后一步

cmu二进制炸弹