HIT CSAPP LAB3
Binary Bomb
二进制炸弹
目 录
第1章 实验基本信息 - 3 -
1.1 实验目的 - 3 -
1.2 实验环境与工具 - 3 -
1.2.1 硬件环境 - 3 -
1.2.2 软件环境 - 3 -
1.2.3 开发工具 - 3 -
1.3 实验预习 - 3 -
第2章 实验环境建立 - 4 -
2.1 UBUNTU下CODEBLOCKS反汇编(10分) - 4 -
2.2 UBUNTU下EDB运行环境建立(10分) - 4 -
第3章 各阶段炸弹**与分析 - 5 -
3.1 阶段1的**与分析 - 5 -
3.2 阶段2的**与分析 - 5 -
3.3 阶段3的**与分析 - 5 -
3.4 阶段4的**与分析 - 5 -
3.5 阶段5的**与分析 - 5 -
3.6 阶段6的**与分析 - 5 -
3.7 阶段7的**与分析(隐藏阶段) - 6 -
第4章 总结 - 7 -
4.1 请总结本次实验的收获 - 7 -
4.2 请给出对本次实验内容的建议 - 7 -
参考文献 - 8 -
第1章 实验基本信息
1.1 实验目的
熟练掌握计算机系统的ISA指令系统与寻址方式
熟练掌握Linux下调试器的反汇编调试跟踪分析机器语言的方法
增强对程序机器级表示、汇编语言、调试器和****等的理解
1.2 实验环境与工具
1.2.1 硬件环境
X64 CPU;2GHz;2G RAM;256GHD Disk 以上
1.2.2 软件环境
Windows7 64位以上;VirtualBox/Vmware 11以上;Ubuntu 16.04 LTS 64位/优麒麟 64位;
1.2.3 开发工具
GDB/OBJDUMP;EDB;KDD等
1.3 实验预习
#include <stdio.h>
#include <string.h>
typedef struct A1{
int x;
double y;
}a1;
typedef struct Linklist{
int x;
struct Linklist *next;
}linklist;
int func1(int n){
if(n <= 1){
return 1;
}
return n * func1(n - 1);
}
int main(){
char a[] = "sadcfaf32d434";
char b[] = "dfdafae";
if(!strcmp(a,b)){
printf("%s == %s\n", a, b);
}
else if(strcmp(a,b) > 0){
printf("%s > %s\n", a, b);
}
else{
printf("%s < %s\n", a, b);
}
int c = 1;
int d = 1;
for(int i = 1; i <= 5; ++i){
int t = c + d;
c = d;
d = t;
printf("f(%d) = %d\n", c, d);
}
printf("%d! = %d\n", 8, func1(8));
char *s = a;
while(*s != '\0' && s != NULL){
printf("%c ", *s);
s++;
}
printf("\n");
a1 first;
first.x = 12546;
first.y = 123.45644;
printf("struct first.x = %d\n",first.x);
printf("struct first.y = %f\n",first.y);
linklist *table1;
linklist *head, *node, *end;
head = (linklist*)malloc(sizeof(linklist));
end = head;
int n = 0;
printf("Please input the number of linklist's node:\n");
scanf("%d\n", &n);
for (int i = 0; i < n; i++) {
node = (linklist*)malloc(sizeof(linklist));
scanf("%d", &node->x);
end->next = node;
end = node;
}
end->next = NULL;
table1 = head;
printf("Linklist:");
while (table1->next != NULL) {
table1 = table1->next;
printf("%d ", table1->x);
}
printf("\n");
return 0;
}
第2章 实验环境建立
2.1 Ubuntu下CodeBlocks反汇编(10分)
CodeBlocks运行hellolinux.c。反汇编查看printf函数的实现。
要求:C、ASM、内存(显示hello等内容)、堆栈(call printf前)、寄存器同时在一个窗口。
图2-1 Ubuntu下CodeBlocks反汇编截图
2.2 Ubuntu下EDB运行环境建立(10分)
用EDB调试hellolinux.c的执行文件,截图,要求同2.1
图2-2 Ubuntu下EDB截图
安装过程参考了https://blog.csdn.net/Lydia_s8023/article/details/61465066
第3章 各阶段炸弹**与分析
每阶段15分(密码10分,分析5分),总分不超过80分
3.1 阶段1的**与分析
密码如下:All your base are belong to us.
**过程:
首先explode_bomb是显示炸弹爆炸的字符串函数,这里不贴出其反汇编代码
Dump of assembler code for function phase_1:
0x00000000004013f5 <+0>: push %rbp
0x00000000004013f6 <+1>: mov %rsp,%rbp
0x00000000004013f9 <+4>: mov $0x403150,%esi
0x00000000004013fe <+9>: callq 0x401818 <strings_not_equal>
0x0000000000401403 <+14>: test %eax,%eax
0x0000000000401405 <+16>: jne 0x401409 <phase_1+20>
0x0000000000401407 <+18>: pop %rbp
0x0000000000401408 <+19>: retq
0x0000000000401409 <+20>: callq 0x401917 <explode_bomb>
0x000000000040140e <+25>: jmp 0x401407 <phase_1+18>
End of assembler dump.
读取地址0x403150的字符串为:All your base are belong to us.
需要输入的字符串满足与如上字符串经过函数strings_not_equal得到返回值0
strings_not_equal其中存在对string_length的调用:
Dump of assembler code for function string_length:
0x0000000000401804 <+0>: mov $0x0,%eax
0x0000000000401809 <+5>: cmpb $0x0,(%rdi)
0x000000000040180c <+8>: je 0x401817 <string_length+19>
0x000000000040180e <+10>: add $0x1,%rdi
0x0000000000401812 <+14>: add $0x1,%eax
0x0000000000401815 <+17>: jmp 0x401809 <string_length+5>
0x0000000000401817 <+19>: retq
End of assembler dump.
移动指针读取%rdi中字符串长度
Dump of assembler code for function strings_not_equal:
0x0000000000401818 <+0>: push %rbp
0x0000000000401819 <+1>: mov %rsp,%rbp
0x000000000040181c <+4>: push %r13
0x000000000040181e <+6>: push %r12
0x0000000000401820 <+8>: push %rbx
0x0000000000401821 <+9>: sub $0x8,%rsp
0x0000000000401825 <+13>: mov %rdi,%rbx
0x0000000000401828 <+16>: mov %rsi,%r12
0x000000000040182b <+19>: callq 0x401804 <string_length>
0x0000000000401830 <+24>: mov %eax,%r13d
0x0000000000401833 <+27>: mov %r12,%rdi
0x0000000000401836 <+30>: callq 0x401804 <string_length>
0x000000000040183b <+35>: cmp %eax,%r13d
0x000000000040183e <+38>: jne 0x40185e <strings_not_equal+70>
0x0000000000401840 <+40>: movzbl (%rbx),%eax
0x0000000000401843 <+43>: test %al,%al
0x0000000000401845 <+45>: je 0x401857 <strings_not_equal+63>
0x0000000000401847 <+47>: cmp %al,(%r12)
0x000000000040184b <+51>: jne 0x40186e <strings_not_equal+86>
0x000000000040184d <+53>: add $0x1,%rbx
0x0000000000401851 <+57>: add $0x1,%r12
0x0000000000401855 <+61>: jmp 0x401840 <strings_not_equal+40>
---Type <return> to continue, or q <return> to quit---
0x0000000000401857 <+63>: mov $0x0,%eax
0x000000000040185c <+68>: jmp 0x401863 <strings_not_equal+75>
0x000000000040185e <+70>: mov $0x1,%eax
0x0000000000401863 <+75>: add $0x8,%rsp
0x0000000000401867 <+79>: pop %rbx
0x0000000000401868 <+80>: pop %r12
0x000000000040186a <+82>: pop %r13
0x000000000040186c <+84>: pop %rbp
0x000000000040186d <+85>: retq
0x000000000040186e <+86>: mov $0x1,%eax
0x0000000000401873 <+91>: jmp 0x401863 <strings_not_equal+75>
End of assembler dump.
可知是字符串比较函数,故密码为All your base are belong to us.
3.2 阶段2的**与分析
密码如下:1 2 4 8 16 32
**过程:
phase_2中有函数read_six_numbers,如下可知,这是输入6个整数的读函数
Dump of assembler code for function read_six_numbers:
0x0000000000401939 <+0>: push %rbp
0x000000000040193a <+1>: mov %rsp,%rbp
0x000000000040193d <+4>: mov %rsi,%rdx
0x0000000000401940 <+7>: lea 0x4(%rsi),%rcx
0x0000000000401944 <+11>: lea 0x14(%rsi),%rax
0x0000000000401948 <+15>: push %rax
0x0000000000401949 <+16>: lea 0x10(%rsi),%rax
0x000000000040194d <+20>: push %rax
0x000000000040194e <+21>: lea 0xc(%rsi),%r9
0x0000000000401952 <+25>: lea 0x8(%rsi),%r8
0x0000000000401956 <+29>: mov $0x403323,%esi
0x000000000040195b <+34>: mov $0x0,%eax
0x0000000000401960 <+39>: callq 0x401120 <aaa@qq.com>
0x0000000000401965 <+44>: add $0x10,%rsp
0x0000000000401969 <+48>: cmp $0x5,%eax
0x000000000040196c <+51>: jle 0x401970 <read_six_numbers+55>
0x000000000040196e <+53>: leaveq
0x000000000040196f <+54>: retq
0x0000000000401970 <+55>: callq 0x401917 <explode_bomb>
End of assembler dump.
Dump of assembler code for function phase_2:
0x0000000000401410 <+0>: push %rbp
0x0000000000401411 <+1>: mov %rsp,%rbp
0x0000000000401414 <+4>: push %rbx
0x0000000000401415 <+5>: sub $0x28,%rsp
0x0000000000401419 <+9>: lea -0x30(%rbp),%rsi
0x000000000040141d <+13>: callq 0x401939 <read_six_numbers>
0x0000000000401422 <+18>: cmpl $0x1,-0x30(%rbp)
0x0000000000401426 <+22>: jne 0x40142f <phase_2+31>
0x0000000000401428 <+24>: mov $0x1,%ebx
0x000000000040142d <+29>: jmp 0x40143e <phase_2+46>
0x000000000040142f <+31>: callq 0x401917 <explode_bomb>
0x0000000000401434 <+36>: jmp 0x401428 <phase_2+24>
0x0000000000401436 <+38>: callq 0x401917 <explode_bomb>
0x000000000040143b <+43>: add $0x1,%ebx
0x000000000040143e <+46>: cmp $0x5,%ebx
0x0000000000401441 <+49>: jg 0x401459 <phase_2+73>
0x0000000000401443 <+51>: movslq %ebx,%rdx
0x0000000000401446 <+54>: lea -0x1(%rbx),%eax
0x0000000000401449 <+57>: cltq
0x000000000040144b <+59>: mov -0x30(%rbp,%rax,4),%eax
0x000000000040144f <+63>: add %eax,%eax
0x0000000000401451 <+65>: cmp %eax,-0x30(%rbp,%rdx,4)
0x0000000000401455 <+69>: je 0x40143b <phase_2+43>
0x0000000000401457 <+71>: jmp 0x401436 <phase_2+38>
0x0000000000401459 <+73>: add $0x28,%rsp
0x000000000040145d <+77>: pop %rbx
0x000000000040145e <+78>: pop %rbp
0x000000000040145f <+79>: retq
End of assembler dump.
如图中标注说明,要求输入的第i个数的两倍等于输入的第i+1个数,共六个数,%ebx=i,第一个数为1,从判断第二个数是否为2开始,判断中途停止时爆炸,判断6个数均正确时返回。故这六个数为1 2 4 8 16 32
3.3 阶段3的**与分析
密码如下:0 543/1 146/2 259/3 -533/4 0/5 -533
**过程:
函数中存在间接跳转语句
jmpq *0x4031a0(,%rax,8)
如下图所示,设两个输入数为x,y,如标注说明,x与y取值有多种:
当x=0时,y=0x18d-0x71+0x318-0x215=543(10)
当x=1时,y=-0x71+0x318-0x215=146(10)
当x=2时,y=0x318-0x215=259(10)
当x=3时,y=-0x215=-533(10)
当x=4时,y=0(10)
当x=5时,y=-0x215=-543(10)
Dump of assembler code for function phase_3:
0x0000000000401460 <+0>: push %rbp
0x0000000000401461 <+1>: mov %rsp,%rbp
0x0000000000401464 <+4>: sub $0x10,%rsp
0x0000000000401468 <+8>: lea -0x8(%rbp),%rcx
0x000000000040146c <+12>: lea -0x4(%rbp),%rdx
0x0000000000401470 <+16>: mov $0x40332f,%esi
0x0000000000401475 <+21>: mov $0x0,%eax
0x000000000040147a <+26>: callq 0x401120 <aaa@qq.com>
0x000000000040147f <+31>: cmp $0x1,%eax
0x0000000000401482 <+34>: jle 0x401494 <phase_3+52>
0x0000000000401484 <+36>: cmpl $0x7,-0x4(%rbp)
0x0000000000401488 <+40>: ja 0x401504 <phase_3+164>
0x000000000040148a <+42>: mov -0x4(%rbp),%eax
0x000000000040148d <+45>: jmpq *0x4031a0(,%rax,8)
0x0000000000401494 <+52>: callq 0x401917 <explode_bomb>
0x0000000000401499 <+57>: jmp 0x401484 <phase_3+36>
0x000000000040149b <+59>: mov $0x0,%eax
0x00000000004014a0 <+64>: jmp 0x4014a7 <phase_3+71>
0x00000000004014a2 <+66>: mov $0x18d,%eax
0x00000000004014a7 <+71>: sub $0x71,%eax
0x00000000004014aa <+74>: add $0x318,%eax
0x00000000004014af <+79>: sub $0x215,%eax
0x00000000004014b4 <+84>: add $0x215,%eax
0x00000000004014b9 <+89>: sub $0x215,%eax
0x00000000004014be <+94>: add $0x215,%eax
0x00000000004014c3 <+99>: sub $0x215,%eax
0x00000000004014c8 <+104>: cmpl $0x5,-0x4(%rbp)
0x00000000004014cc <+108>: jg 0x4014d3 <phase_3+115>
0x00000000004014ce <+110>: cmp %eax,-0x8(%rbp)
0x00000000004014d1 <+113>: je 0x4014d8 <phase_3+120>
0x00000000004014d3 <+115>: callq 0x401917 <explode_bomb>
0x00000000004014d8 <+120>: leaveq
0x00000000004014d9 <+121>: retq
0x00000000004014da <+122>: mov $0x0,%eax
0x00000000004014df <+127>: jmp 0x4014aa <phase_3+74>
0x00000000004014e1 <+129>: mov $0x0,%eax
0x00000000004014e6 <+134>: jmp 0x4014af <phase_3+79>
0x00000000004014e8 <+136>: mov $0x0,%eax
0x00000000004014ed <+141>: jmp 0x4014b4 <phase_3+84>
0x00000000004014ef <+143>: mov $0x0,%eax
0x00000000004014f4 <+148>: jmp 0x4014b9 <phase_3+89>
0x00000000004014f6 <+150>: mov $0x0,%eax
0x00000000004014fb <+155>: jmp 0x4014be <phase_3+94>
0x00000000004014fd <+157>: mov $0x0,%eax
0x0000000000401502 <+162>: jmp 0x4014c3 <phase_3+99>
0x0000000000401504 <+164>: callq 0x401917 <explode_bomb>
0x0000000000401509 <+169>: mov $0x0,%eax
0x000000000040150e <+174>: jmp 0x4014c8 <phase_3+104>
---Type <return> to continue, or q <return> to quit---
End of assembler dump.
3.4 阶段4的**与分析
密码如下:4 2
**过程:
phase_4如下图,只需要y==0并且func(x)==2
Dump of assembler code for function phase_4:
0x000000000040154a <+0>: push %rbp
0x000000000040154b <+1>: mov %rsp,%rbp
0x000000000040154e <+4>: sub $0x10,%rsp
0x0000000000401552 <+8>: lea -0x8(%rbp),%rcx
0x0000000000401556 <+12>: lea -0x4(%rbp),%rdx
0x000000000040155a <+16>: mov $0x40332f,%esi
0x000000000040155f <+21>: mov $0x0,%eax
0x0000000000401564 <+26>: callq 0x401120 <aaa@qq.com>
0x0000000000401569 <+31>: cmp $0x2,%eax
0x000000000040156c <+34>: jne 0x40157a <phase_4+48>
0x000000000040156e <+36>: mov -0x4(%rbp),%eax
0x0000000000401571 <+39>: test %eax,%eax
0x0000000000401573 <+41>: js 0x40157a <phase_4+48>
0x0000000000401575 <+43>: cmp $0xe,%eax
0x0000000000401578 <+46>: jle 0x40157f <phase_4+53>
0x000000000040157a <+48>: callq 0x401917 <explode_bomb>
0x000000000040157f <+53>: mov $0xe,%edx
0x0000000000401584 <+58>: mov $0x0,%esi
0x0000000000401589 <+63>: mov -0x4(%rbp),%edi
0x000000000040158c <+66>: callq 0x401510 <func4>
0x0000000000401591 <+71>: cmp $0x2,%eax
0x0000000000401594 <+74>: jne 0x40159c <phase_4+82>
0x0000000000401596 <+76>: cmpl $0x2,-0x8(%rbp)
0x000000000040159a <+80>: je 0x4015a1 <phase_4+87>
0x000000000040159c <+82>: callq 0x401917 <explode_bomb>
0x00000000004015a1 <+87>: leaveq
0x00000000004015a2 <+88>: retq
End of assembler dump.
下面是func的反汇编代码:
Dump of assembler code for function func4:
0x0000000000401510 <+0>: push %rbp
0x0000000000401511 <+1>: mov %rsp,%rbp
0x0000000000401514 <+4>: mov %edx,%ecx
0x0000000000401516 <+6>: sub %esi,%ecx
0x0000000000401518 <+8>: mov %ecx,%eax
0x000000000040151a <+10>: shr $0x1f,%eax
0x000000000040151d <+13>: add %ecx,%eax
0x000000000040151f <+15>: sar %eax
0x0000000000401521 <+17>: add %esi,%eax
0x0000000000401523 <+19>: cmp %edi,%eax
0x0000000000401525 <+21>: jg 0x401530 <func4+32>
0x0000000000401527 <+23>: jl 0x40153c <func4+44>
0x0000000000401529 <+25>: mov $0x0,%eax
0x000000000040152e <+30>: pop %rbp
0x000000000040152f <+31>: retq
0x0000000000401530 <+32>: lea -0x1(%rax),%edx
0x0000000000401533 <+35>: callq 0x401510 <func4>
0x0000000000401538 <+40>: add %eax,%eax
0x000000000040153a <+42>: jmp 0x40152e <func4+30>
0x000000000040153c <+44>: lea 0x1(%rax),%esi
0x000000000040153f <+47>: callq 0x401510 <func4>
0x0000000000401544 <+52>: lea 0x1(%rax,%rax,1),%eax
0x0000000000401548 <+56>: jmp 0x40152e <func4+30>
End of assembler dump.
递归函数中%rdi存储x,但值始终不变,实际上func4函数如下:
int func4(int x, int a, int b)//%edi存放x,%esi存放a,%edx存放b,返回值存放在%rax
{
int result = ((int)((unsigned)(b - a) >> 1) + b - a) / 2 + a;//result的值为a+(b-a)/2(向0舍入)
if (result > x) {
b = result - 1;
result = func4(x, a, b);
result *= 2;
return result;
}
else if(result < x){
a = result + 1;
result = func4(x, a, b);
result = result * 3 + 1;
return result;
}
return 0;
}
这个函数从func4(x,14,0),类似于二分,递归基为result==x时,由于返回值应该为2,且x介于0和14间,根据2=(3*0+1)*2知,递归从基到顶为result0 == x,result1<x,result2>x,故易知密码为:4 2
3.5 阶段5的**与分析
密码如下:058kmn(答案不唯一)
**过程:反汇编代码如下:
要求输入字符串s[6]长度为6,与arr数组结合计算结果必须为0x32即50
Dump of assembler code for function phase_5:
0x00000000004015a3 <+0>: push %rbp
0x00000000004015a4 <+1>: mov %rsp,%rbp
0x00000000004015a7 <+4>: push %rbx
0x00000000004015a8 <+5>: sub $0x8,%rsp
0x00000000004015ac <+9>: mov %rdi,%rbx
0x00000000004015af <+12>: callq 0x401804 <string_length>
0x00000000004015b4 <+17>: cmp $0x6,%eax
0x00000000004015b7 <+20>: jne 0x4015de <phase_5+59>
0x00000000004015b9 <+22>: mov $0x0,%ecx
0x00000000004015be <+27>: mov $0x0,%eax
0x00000000004015c3 <+32>: cmp $0x5,%eax
0x00000000004015c6 <+35>: jg 0x4015e5 <phase_5+66>
0x00000000004015c8 <+37>: movslq %eax,%rdx
0x00000000004015cb <+40>: movzbl (%rbx,%rdx,1),%edx
0x00000000004015cf <+44>: and $0xf,%edx
0x00000000004015d2 <+47>: add 0x4031e0(,%rdx,4),%ecx
0x00000000004015d9 <+54>: add $0x1,%eax
0x00000000004015dc <+57>: jmp 0x4015c3 <phase_5+32>
0x00000000004015de <+59>: callq 0x401917 <explode_bomb>
0x00000000004015e3 <+64>: jmp 0x4015b9 <phase_5+22>
0x00000000004015e5 <+66>: cmp $0x32,%ecx
0x00000000004015e8 <+69>: jne 0x4015f1 <phase_5+78>
0x00000000004015ea <+71>: add $0x8,%rsp
0x00000000004015ee <+75>: pop %rbx
0x00000000004015ef <+76>: pop %rbp
0x00000000004015f0 <+77>: retq
0x00000000004015f1 <+78>: callq 0x401917 <explode_bomb>
0x00000000004015f6 <+83>: jmp 0x4015ea <phase_5+71>
End of assembler dump.
arr[]数组结果如下:
要求result==32,其中result=Σarr[(s[i]&0xf)]
s[i]&0xf | arr[s[i]&0xf] | s[i]&0xf | arr[s[i]&0xf] |
---|---|---|---|
0 | 2 | 8 | 4 |
1 | 10 | 9 | 7 |
2 | 6 | 10 | 14 |
3 | 1 | 11 | 5 |
4 | 12 | 12 | 11 |
5 | 16 | 13 | 8 |
6 | 9 | 14 | 15 |
7 | 3 | 15 | 13 |
猜想如2+16+4+5+8+15=50如058kmn就可以是答案
3.6 阶段6的**与分析
密码如下:6 5 1 2 3 4
**过程:
反汇编结果如下,程序是储存了一个链表,下一个结点头与本结点尾相连:
链表头的值储存在0x4052d0
Dump of assembler code for function phase_6:
0x00000000004015f8 <+0>: push %rbp
0x00000000004015f9 <+1>: mov %rsp,%rbp
0x00000000004015fc <+4>: push %r13
0x00000000004015fe <+6>: push %r12
0x0000000000401600 <+8>: push %rbx
0x0000000000401601 <+9>: sub $0x58,%rsp
0x0000000000401605 <+13>: lea -0x40(%rbp),%rsi
0x0000000000401609 <+17>: callq 0x401939 <read_six_numbers>
0x000000000040160e <+22>: mov $0x0,%r12d
0x0000000000401614 <+28>: jmp 0x40163f <phase_6+71>
0x0000000000401616 <+30>: callq 0x401917 <explode_bomb>
0x000000000040161b <+35>: jmp 0x401654 <phase_6+92>
0x000000000040161d <+37>: callq 0x401917 <explode_bomb>
0x0000000000401622 <+42>: add $0x1,%ebx
0x0000000000401625 <+45>: cmp $0x5,%ebx
0x0000000000401628 <+48>: jg 0x40163c <phase_6+68>
0x000000000040162a <+50>: movslq %r12d,%rax
0x000000000040162d <+53>: movslq %ebx,%rdx
0x0000000000401630 <+56>: mov -0x40(%rbp,%rdx,4),%edi
0x0000000000401634 <+60>: cmp %edi,-0x40(%rbp,%rax,4)
0x0000000000401638 <+64>: jne 0x401622 <phase_6+42>
0x000000000040163a <+66>: jmp 0x40161d <phase_6+37>
0x000000000040163c <+68>: mov %r13d,%r12d
0x000000000040163f <+71>: cmp $0x5,%r12d
0x0000000000401643 <+75>: jg 0x40165e <phase_6+102>
0x0000000000401645 <+77>: movslq %r12d,%rax
0x0000000000401648 <+80>: mov -0x40(%rbp,%rax,4),%eax
0x000000000040164c <+84>: sub $0x1,%eax
0x000000000040164f <+87>: cmp $0x5,%eax
0x0000000000401652 <+90>: ja 0x401616 <phase_6+30>
0x0000000000401654 <+92>: lea 0x1(%r12),%r13d
0x0000000000401659 <+97>: mov %r13d,%ebx
0x000000000040165c <+100>: jmp 0x401625 <phase_6+45>
0x000000000040165e <+102>: mov $0x0,%esi
0x0000000000401663 <+107>: jmp 0x40167d <phase_6+133>
0x0000000000401665 <+109>: mov 0x8(%rdx),%rdx
0x0000000000401669 <+113>: add $0x1,%eax
0x000000000040166c <+116>: movslq %esi,%rcx
0x000000000040166f <+119>: cmp %eax,-0x40(%rbp,%rcx,4)
0x0000000000401673 <+123>: jg 0x401665 <phase_6+109>
0x0000000000401675 <+125>: mov %rdx,-0x70(%rbp,%rcx,8)
0x000000000040167a <+130>: add $0x1,%esi
0x000000000040167d <+133>: cmp $0x5,%esi
0x0000000000401680 <+136>: jg 0x40168e <phase_6+150>
0x0000000000401682 <+138>: mov $0x1,%eax
0x0000000000401687 <+143>: mov $0x4052d0,%edx
0x000000000040168c <+148>: jmp 0x40166c <phase_6+116>
0x000000000040168e <+150>: mov -0x70(%rbp),%rbx
---Type <return> to continue, or q <return> to quit---
0x0000000000401692 <+154>: mov %rbx,%rcx
0x0000000000401695 <+157>: mov $0x1,%eax
0x000000000040169a <+162>: jmp 0x4016ae <phase_6+182>
0x000000000040169c <+164>: movslq %eax,%rdx
0x000000000040169f <+167>: mov -0x70(%rbp,%rdx,8),%rdx
0x00000000004016a4 <+172>: mov %rdx,0x8(%rcx)
0x00000000004016a8 <+176>: add $0x1,%eax
0x00000000004016ab <+179>: mov %rdx,%rcx
0x00000000004016ae <+182>: cmp $0x5,%eax
0x00000000004016b1 <+185>: jle 0x40169c <phase_6+164>
0x00000000004016b3 <+187>: movq $0x0,0x8(%rcx)
0x00000000004016bb <+195>: mov $0x0,%r12d
0x00000000004016c1 <+201>: jmp 0x4016cb <phase_6+211>
0x00000000004016c3 <+203>: mov 0x8(%rbx),%rbx
0x00000000004016c7 <+207>: add $0x1,%r12d
0x00000000004016cb <+211>: cmp $0x4,%r12d
0x00000000004016cf <+215>: jg 0x4016e2 <phase_6+234>
0x00000000004016d1 <+217>: mov 0x8(%rbx),%rax
0x00000000004016d5 <+221>: mov (%rax),%eax
0x00000000004016d7 <+223>: cmp %eax,(%rbx)
0x00000000004016d9 <+225>: jle 0x4016c3 <phase_6+203>
0x00000000004016db <+227>: callq 0x401917 <explode_bomb>
0x00000000004016e0 <+232>: jmp 0x4016c3 <phase_6+203>
0x00000000004016e2 <+234>: add $0x58,%rsp
0x00000000004016e6 <+238>: pop %rbx
0x00000000004016e7 <+239>: pop %r12
0x00000000004016e9 <+241>: pop %r13
0x00000000004016eb <+243>: pop %rbp
0x00000000004016ec <+244>: retq
End of assembler dump.
由0x00000000004016d7 <+223>: cmp %eax,(%rbx)
0x00000000004016d9 <+225>: jle 0x4016c3 <phase_6+203>
知需要我们按照链表每个结点储存的值重新升序排列,给出新的结点号序:
而0x4052d0为链表头,其值为
排序后为6 5 1 2 3 4
3.7 阶段7的**与分析(隐藏阶段)
密码如下:1001(答案不唯一)
**过程:
如图所示,查询0x43379,0x40332地址中的字符串,前者为”%d %d %s”,初步推测应该在第三关或第四关输入特定字符串开启隐藏关卡;后者为”DrEvil”,由反汇编知输入正确后可进入隐藏关卡secret_phase
Dump of assembler code for function phase_defused:
0x0000000000401aa6 <+0>: cmpl $0x6,0x3cbf(%rip) # 0x40576c <num_input_strings>
0x0000000000401aad <+7>: je 0x401ab0 <phase_defused+10>
0x0000000000401aaf <+9>: retq
0x0000000000401ab0 <+10>: push %rbp
0x0000000000401ab1 <+11>: mov %rsp,%rbp
0x0000000000401ab4 <+14>: sub $0x60,%rsp
0x0000000000401ab8 <+18>: lea -0x50(%rbp),%r8
0x0000000000401abc <+22>: lea -0x58(%rbp),%rcx
0x0000000000401ac0 <+26>: lea -0x54(%rbp),%rdx
0x0000000000401ac4 <+30>: mov $0x403379,%esi
0x0000000000401ac9 <+35>: mov $0x405870,%edi
0x0000000000401ace <+40>: mov $0x0,%eax
0x0000000000401ad3 <+45>: callq 0x401120 <aaa@qq.com>
0x0000000000401ad8 <+50>: cmp $0x3,%eax
0x0000000000401adb <+53>: je 0x401ae9 <phase_defused+67>
0x0000000000401add <+55>: mov $0x4032b8,%edi
0x0000000000401ae2 <+60>: callq 0x401060 <aaa@qq.com>
0x0000000000401ae7 <+65>: leaveq
0x0000000000401ae8 <+66>: retq
0x0000000000401ae9 <+67>: mov $0x403382,%esi
0x0000000000401aee <+72>: lea -0x50(%rbp),%rdi
0x0000000000401af2 <+76>: callq 0x401818 <strings_not_equal>
0x0000000000401af7 <+81>: test %eax,%eax
0x0000000000401af9 <+83>: jne 0x401add <phase_defused+55>
0x0000000000401afb <+85>: mov $0x403258,%edi
0x0000000000401b00 <+90>: callq 0x401060 <aaa@qq.com>
0x0000000000401b05 <+95>: mov $0x403280,%edi
0x0000000000401b0a <+100>: callq 0x401060 <aaa@qq.com>
0x0000000000401b0f <+105>: mov $0x0,%eax
0x0000000000401b14 <+110>: callq 0x401727 <secret_phase>
0x0000000000401b19 <+115>: jmp 0x401add <phase_defused+55>
End of assembler dump.
我们可以看到%eax在进入secret_phase前设置为0了,将0x403379处代码读入成”%d %d %s”格式,在phase_defused的0x401adb处设置断点并调试,发现将-0x50(%rbp)的值作为隐藏秘钥输入的首地址,即秘钥存储在此处:
我们检测0x405870中的值,当它被读写时暂停:
当输入完第四关秘钥时发生暂停,说明0x405870在此时发生读或写操作,进一步,我们验证第四关时输入隐藏密码开启隐藏关卡:
在第四关尝试输入正答+字符串”ppp”,断点处读取%eax,(%rcx+0x10),(%rcx+0xc)的值,发现值存储在
此时%eax=3表示成功读入隐藏秘钥
long int strtol(const char *nptr, char **endptr, int base)
strtol()会将nptr指向的字符串,根据参数base,按权转化为long int, 然后返回这个值。
根据这一信息,查看secret_phase的代码,要求转换后字符串在1~0x3e9之间
Dump of assembler code for function secret_phase:
0x0000000000401727 <+0>: push %rbp
0x0000000000401728 <+1>: mov %rsp,%rbp
0x000000000040172b <+4>: push %rbx
0x000000000040172c <+5>: sub $0x8,%rsp
0x0000000000401730 <+9>: callq 0x401975 <read_line>
0x0000000000401735 <+14>: mov $0xa,%edx
0x000000000040173a <+19>: mov $0x0,%esi
0x000000000040173f <+24>: mov %rax,%rdi
0x0000000000401742 <+27>: callq 0x4010f0 <aaa@qq.com>
0x0000000000401747 <+32>: mov %rax,%rbx
0x000000000040174a <+35>: lea -0x1(%rax),%eax
0x000000000040174d <+38>: cmp $0x3e8,%eax
0x0000000000401752 <+43>: ja 0x40177b <secret_phase+84>
0x0000000000401754 <+45>: mov %ebx,%esi
0x0000000000401756 <+47>: mov $0x4050f0,%edi
0x000000000040175b <+52>: callq 0x4016ed <fun7>
0x0000000000401760 <+57>: cmp $0x7,%eax
0x0000000000401763 <+60>: jne 0x401782 <secret_phase+91>
0x0000000000401765 <+62>: mov $0x403170,%edi
0x000000000040176a <+67>: callq 0x401060 <aaa@qq.com>
0x000000000040176f <+72>: callq 0x401aa6 <phase_defused>
0x0000000000401774 <+77>: add $0x8,%rsp
0x0000000000401778 <+81>: pop %rbx
0x0000000000401779 <+82>: pop %rbp
0x000000000040177a <+83>: retq
0x000000000040177b <+84>: callq 0x401917 <explode_bomb>
0x0000000000401780 <+89>: jmp 0x401754 <secret_phase+45>
0x0000000000401782 <+91>: callq 0x401917 <explode_bomb>
0x0000000000401787 <+96>: jmp 0x401765 <secret_phase+62>
End of assembler dump.
函数中调用了fun7,这一函数几乎与func4一模一样,只是增加了递归基,修改了变换条件,返回值应该为7 = ((0 * 2 + 1) * 2 + 1) * 2 + 1,共4次递归;
int fun7(int *x, int a)//%edi存放x,%esi存放a,返回值存放在%rax
{
if(x == 0){
return -1;
}
int result = *x;
if (result > a) {
x = *(x + 2);
result = fun7(&x, a);
result *= 2;
return result;
}
else if(result < a){
x = *(x + 4);
result = func4(&x, a);
result = result * 2 + 1;
return result;
}
return 0;
}
故而值应该满足4次递归的条件,递归过程中%esi值始终不变。
从开始到递归基:
第一次时%rsi的值>36,并读取0x405100的中存的地址值供递归调用:
第二次时%rsi的值>50,并读取0x405140中存的地址值供递归调用:
第三次时%rsi的值>107,并读取0x4051c0中存的地址值供递归调用:
第四次时%rsi==1001,停止递归调用。
从而1001就是上面strtol返回值,根据该函数的定义,1001*/*-/-+(非数字字符均可)满足答案。