实验目的:进一步了解机器级代码,提高汇编语言、调试器和逆向工程等方面原理与技能的掌握。
实验环境:C、linux
实验获取:进入csapp官网,点击linux/x86-64 binary bomb下载实验压缩包。
实验说明:一共有6个关卡,每个关卡可以输入一串字符,只有输入正确才能拆出炸弹。
只有可执行程序,不知道六个关卡函数具体的代码都是什么。
可以应用反汇编技术把可执行程序转化为汇编程序。通过阅读汇编程序,推断出程序的具体作用,从而给出正确的密码输入。
sCS:APP3e, Bryant and O'Hallaron
解压:tar -xvf bomb.tar
从bomb.c可以看出phase_1接受一个输入,需要反汇编推测phase_1对input做了什么处理。
反汇编整个程序:
objdump -d bomb > bomb.txt
bomb.txt可以查看bomb的汇编代码
gdb进入调式模式
gdb bomb
在phase_1函数打断点
(gdb)break phase_1
运行到断点处
(gdb)run
可以看到断点在0x400ee0,从汇编文件中可以找到phase_1的汇编代码
此外,还可以在gdb中查看phase_1的汇编代码
disas phase_1
在使用 test %eax, %eax
指令后,通常会检查标志位,以确定 %eax
中的值是否为零。如果结果为零,则零标志位会被设置为 1,表示 %eax
中的值为零;如果结果不为零,则零标志位会被清除为 0,表示 %eax
中的值不为零。
如果%eax不为0,执行explode_bomb函数,所以只有当string_not_equal返回的值为0,才可以解开炸弹。
查看string_not_equal的汇编代码
0000000000401338 <strings_not_equal>:
401338: 41 54 push %r12
40133a: 55 push %rbp
40133b: 53 push %rbx
40133c: 48 89 fb mov %rdi,%rbx
40133f: 48 89 f5 mov %rsi,%rbp
401342: e8 d4 ff ff ff call 40131b <string_length>
401347: 41 89 c4 mov %eax,%r12d
40134a: 48 89 ef mov %rbp,%rdi
40134d: e8 c9 ff ff ff call 40131b <string_length>
401352: ba 01 00 00 00 mov $0x1,%edx
401357: 41 39 c4 cmp %eax,%r12d
40135a: 75 3f jne 40139b <strings_not_equal+0x63>
40135c: 0f b6 03 movzbl (%rbx),%eax
40135f: 84 c0 test %al,%al
401361: 74 25 je 401388 <strings_not_equal+0x50>
401363: 3a 45 00 cmp 0x0(%rbp),%al
401366: 74 0a je 401372 <strings_not_equal+0x3a>
401368: eb 25 jmp 40138f <strings_not_equal+0x57>
40136a: 3a 45 00 cmp 0x0(%rbp),%al
40136d: 0f 1f 00 nopl (%rax)
401370: 75 24 jne 401396 <strings_not_equal+0x5e>
401372: 48 83 c3 01 add $0x1,%rbx
401376: 48 83 c5 01 add $0x1,%rbp
40137a: 0f b6 03 movzbl (%rbx),%eax
40137d: 84 c0 test %al,%al
40137f: 75 e9 jne 40136a <strings_not_equal+0x32>
401381: ba 00 00 00 00 mov $0x0,%edx
401386: eb 13 jmp 40139b <strings_not_equal+0x63>
401388: ba 00 00 00 00 mov $0x0,%edx
40138d: eb 0c jmp 40139b <strings_not_equal+0x63>
40138f: ba 01 00 00 00 mov $0x1,%edx
401394: eb 05 jmp 40139b <strings_not_equal+0x63>
401396: ba 01 00 00 00 mov $0x1,%edx
40139b: 89 d0 mov %edx,%eax
40139d: 5b pop %rbx
40139e: 5d pop %rbp
40139f: 41 5c pop %r12
4013a1: c3 ret
- 该函数保存了一些寄存器的值(
%r12
、%rbp
、%rbx
)并将参数传递到寄存器中(%rdi
和%rsi
) - 两次调用
string_length
函数,分别计算了两个输入字符串的长度,将长度分别存储在%r12d
和%eax
中。 - 对比字符串长度,如果长度不相等 (
jne 40139b
),则直接返回 1,表示字符串不相等。 - 如果字符串长度相等,接着执行逐字符比较的部分: 首先检查
%rbx
指向的字符是否为字符串结束符(\0
),如果是,则直接返回 0,表示字符串相等。 如果不是结束符,则比较%rbx
和%rbp
指向的字符。如果不相等,立即返回 1,表示字符串不相等。如果相等,则继续比较下一个字符。循环执行字符比较的过程,直到找到不相等的字符或者两个字符串都到达结尾为止。最后,根据比较结果,将 1 或 0 存储在%eax
中作为返回值,表示字符串是否不相等。最后,恢复被保存的寄存器值,并通过ret
指令返回函数。
查看0x402400地址的值,就是要和输入比较的值。
炸弹一被拆除!