目录
Lab_2实验报告
屏幕截图
考察内容
本次lab主要考察的是对各种汇编指令的熟悉程度和对gdb的掌握程度。
各题答案
bomb1
Border relations with Canada have never been better.
该答案唯一。
bomb2
1 2 4 8 16 32
该答案唯一。
bomb3
6 682
该答案不唯一。
答案表:
x | y |
---|---|
0 | 207(0xcf) |
1 | 311(0x137) |
2 | 707(0x2c3) |
3 | 256(0x100) |
4 | 389(0x185) |
5 | 206(0xce) |
6 | 682(0x2aa) |
7 | 327(0x147) |
bomb4
0 0
该答案不唯一。
答案表:
x | y |
---|---|
0 | 0 |
1 | 0 |
3 | 0 |
7 | 0 |
bomb5
9/.567
该答案不唯一。
答案规律:
一个长度为6的字符串,其中从左到右每个字符的十六进制形式下ASCII码的末位依次为:9、e、f、5、6、7。
bomb6
4 3 2 1 6 5
该答案唯一。
解题思路
bomb1
核心代码部分只有一个:
400ee4: be 00 24 40 00 mov $0x402400,%esi 400ee9: e8 4a 04 00 00 callq 401338 <strings_not_equal> 400eee: 85 c0 test %eax,%eax 400ef0: 74 05 je 400ef7 <phase_1+0x17> 400ef2: e8 43 05 00 00 callq 40143a <explode_bomb> 400ef7: 48 83 c4 08 add $0x8,%rsp
查看函数
因此结合bomb1中的情景可以发现,调用
bomb2
核心代码以及翻译:
400f0a: 83 3c 24 01 cmpl $0x1,(%rsp) 400f0e: 74 20 je 400f30 <phase_2+0x34> 400f10: e8 25 05 00 00 callq 40143a <explode_bomb> 400f15: eb 19 jmp 400f30 <phase_2+0x34> 400f17: 8b 43 fc mov -0x4(%rbx),%eax 400f1a: 01 c0 add %eax,%eax 400f1c: 39 03 cmp %eax,(%rbx) 400f1e: 74 05 je 400f25 <phase_2+0x29> 400f20: e8 15 05 00 00 callq 40143a <explode_bomb> 400f25: 48 83 c3 04 add $0x4,%rbx 400f29: 48 39 eb cmp %rbp,%rbx 400f2c: 75 e9 jne 400f17 <phase_2+0x1b> 400f2e: eb 0c jmp 400f3c <phase_2+0x40> 400f30: 48 8d 5c 24 04 lea 0x4(%rsp),%rbx 400f35: 48 8d 6c 24 18 lea 0x18(%rsp),%rbp 400f3a: eb db jmp 400f17 <phase_2+0x1b>
if(*rsp!=1)explode_bomb; rbx=rsp+4; rbp=rsp+24; do eax=rbx-4; eax*=2; if(eax!=(*rbx))explode_bomb; rbx+=4; while(rbp!=rbx);
phase_2在调用
bomb3
输入部分
400f51: be cf 25 40 00 mov $0x4025cf,%esi 400f56: b8 00 00 00 00 mov $0x0,%eax 400f5b: e8 90 fc ff ff callq 400bf0 <__isoc99_sscanf@plt> 400f60: 83 f8 01 cmp $0x1,%eax 400f63: 7f 05 jg 400f6a <phase_3+0x27> 400f65: e8 d0 04 00 00 callq 40143a <explode_bomb> 400f6a: 83 7c 24 08 07 cmpl $0x7,0x8(%rsp) 400f6f: 77 3c ja 400fad <phase_3+0x6a>
通过gdb查看首地址为0x4025cf的字符串,结果为"%d %d",结合下文的__isoc99_sscanf@plt可知,要求输入的数字个数为2,进一步通过0x400f63~0x400f65“判断输入个数是否大于1”也能得出相同的结论。最后,0x400f63~0x400f6f语句表示第一个输入的数字为小于7的非负数。
分支部分
400f71: 8b 44 24 08 mov 0x8(%rsp),%eax 400f75: ff 24 c5 70 24 40 00 jmpq *0x402470(,%rax,8) 400f7c: b8 cf 00 00 00 mov $0xcf,%eax 400f81: eb 3b jmp 400fbe <phase_3+0x7b> ... 400fad: e8 88 04 00 00 callq 40143a <explode_bomb> 400fb2: b8 00 00 00 00 mov $0x0,%eax 400fb7: eb 05 jmp 400fbe <phase_3+0x7b> 400fb9: b8 37 01 00 00 mov $0x137,%eax 400fbe: 3b 44 24 0c cmp 0xc(%rsp),%eax 400fc2: 74 05 je 400fc9 <phase_3+0x86> 400fc4: e8 71 04 00 00 callq 40143a <explode_bomb>
该部分代码较长,未完全展示。
通过观察发现,该部分中有大量内容为"jmp 400fbe <phase_3+0x7b>"的语句,判断应该是分支结构,对应到源代码应该是一个switch语句。实现条件跳转的关键在于0x400f75语句:“jmpq *0x402470(,%rax,8)”。这条语句的意思是跳转到以0x402470+8*%rax指向的数为地址的语句处。通过gdb可得出上述答案表。
bomb4
递归部分
递归部分就是整个
确定中点
400fd2: 89 d0 mov %edx,%eax 400fd4: 29 f0 sub %esi,%eax 400fd6: 89 c1 mov %eax,%ecx 400fd8: c1 e9 1f shr $0x1f,%ecx 400fdb: 01 c8 add %ecx,%eax 400fdd: d1 f8 sar %eax 400fdf: 8d 0c 30 lea (%rax,%rsi,1),%ecx
在该部分中,%esi为闭区间左端点,%edx为闭区间右端点。语句0x400fd2~0x400fdb的本质即是%eax=%edx-%esi,随后通过%ecx=%rsi+(%eax>>1)这条语句可以得知,%ecx为区间中点。
比较大小&缩小区间
400fe2: 39 f9 cmp %edi,%ecx 400fe4: 7e 0c jle 400ff2 <func4+0x24> 400fe6: 8d 51 ff lea -0x1(%rcx),%edx 400fe9: e8 e0 ff ff ff callq 400fce <func4> 400fee: 01 c0 add %eax,%eax 400ff0: eb 15 jmp 401007 <func4+0x39> 400ff2: b8 00 00 00 00 mov $0x0,%eax 400ff7: 39 f9 cmp %edi,%ecx 400ff9: 7d 0c jge 401007 <func4+0x39> 400ffb: 8d 71 01 lea 0x1(%rcx),%esi 400ffe: e8 cb ff ff ff callq 400fce <func4> 401003: 8d 44 00 01 lea 0x1(%rax,%rax,1),%eax
%edi为要查找的数。比较%edi和%ecx的大小,如果%ecx>%edi,表示%edi落在左半区间。因此将右端点%edx修改为%rcx-1,向下一层递归,回溯时将%eax修改为2*%eax。否则,表示%edi落在右半区间,此时判断%edi和%ecx是否相等,如果相等则直接退出该递归部分。如果不相等则将左端点%esi修改为%rcx+1,向下一层递归,回溯时将%eax修改为2*%eax+1。
输入&判断部分
这部分主要在
bomb5
phase_5的本质是以输入字符串的从左到右每个字符的ASCII码的十六进制末位为索引,查表得到新字符串后与目标字符串匹配。
索引部分
40108b: 0f b6 0c 03 movzbl (%rbx,%rax,1),%ecx 40108f: 88 0c 24 mov %cl,(%rsp) 401092: 48 8b 14 24 mov (%rsp),%rdx 401096: 83 e2 0f and $0xf,%edx 401099: 0f b6 92 b0 24 40 00 movzbl 0x4024b0(%rdx),%edx 4010a0: 88 54 04 10 mov %dl,0x10(%rsp,%rax,1) 4010a4: 48 83 c0 01 add $0x1,%rax 4010a8: 48 83 f8 06 cmp $0x6,%rax 4010ac: 75 dd jne 40108b <phase_5+0x29>
翻译代码:
do ecx=rax+rbx; //movzbl *rsp=cl; rdx=*rsp; edx&=0xf; edx=*(rdx+4024b0); //movzbl *(rsp+rax+4*4)=dl; rax++; while(rax!=6);
该部分就是遍历所有字符,%rbx是读入字符串的首地址,%edx用来存放字符的ASCII码的十六进制末位,随后将%edx索引至%rdx+0x4024b0处,并存放在%rsp+%rax+16处。
通过gdb调试得知以0x4024b0为首地址的字符串为:"maduiersnfotvbylSo you think you can stop the bomb with ctrl-c, do you?",其中有效项(前16个)为"maduiersnfotvbyl"。
检验部分
检验部分就是判断新字符串是否等于目标字符串,即以0x40245e为首地址的字符串。通过gdb调试得知目标字符串为"flyers",其中每个字符分别在表的第9、14、15、5、6、7位。因此倒推出输入字符串的ASCII码的十六进制末位也应该是9,e,f,5,6,7。
bomb6
PS:(这个phase真的是太太太太长了……里面jmp指令也是非常的多,不用纸打印出来真的没办法看啊QAQ)
phase_6的本质就是将输入的排列取反后以此为基准重新排列一个序列,使其成降序。
判断是否为排列
401128: 41 83 c4 01 add $0x1,%r12d 40112c: 41 83 fc 06 cmp $0x6,%r12d 401130: 74 21 je 401153 <phase_6+0x5f> 401132: 44 89 e3 mov %r12d,%ebx 401135: 48 63 c3 movslq %ebx,%rax 401138: 8b 04 84 mov (%rsp,%rax,4),%eax 40113b: 39 45 00 cmp %eax,0x0(%rbp) 40113e: 75 05 jne 401145 <phase_6+0x51> 401140: e8 f5 02 00 00 callq 40143a <explode_bomb> 401145: 83 c3 01 add $0x1,%ebx 401148: 83 fb 05 cmp $0x5,%ebx 40114b: 7e e8 jle 401135 <phase_6+0x41>
翻译代码:
do r12d++; ebx=r12d; do rax=ebx; //movslq eax=rsp+4*rax; if(eax==*rbp)explode_bomb; ebx++; while(ebx<=5); while(r12d!=6);
读入6个数字后,首先规定每个数不大于6,否则调用
取反部分
401153: 48 8d 74 24 18 lea 0x18(%rsp),%rsi 401158: 4c 89 f0 mov %r14,%rax 40115b: b9 07 00 00 00 mov $0x7,%ecx 401160: 89 ca mov %ecx,%edx 401162: 2b 10 sub (%rax),%edx 401164: 89 10 mov %edx,(%rax) 401166: 48 83 c0 04 add $0x4,%rax 40116a: 48 39 f0 cmp %rsi,%rax 40116d: 75 f1 jne 401160 <phase_6+0x6c>
翻译代码:
rsi=*(rsp+4*6); rax=r14; do ecx=7; edx=ecx; edx-=*rax; *rax=edx; //*rax=7-*rax rax+=4; while(rax!=rsi);
该部分利用一个循环,将元素x转变为7-x。
索引部分
PS:(这部分的条件跳转指令特别多……所以这部分我是在纸上完成的,没办法贴出翻译代码了)
该部分以每个元素值x为索引,索引至0x6032d0+16*x处,将该值赋给%rsp+8*x+32。用gdb调试后发现,0x6032d0+16*x指向的值分别为332,168,924,691,477,443。
检验部分
4011da: bd 05 00 00 00 mov $0x5,%ebp 4011df: 48 8b 43 08 mov 0x8(%rbx),%rax 4011e3: 8b 00 mov (%rax),%eax 4011e5: 39 03 cmp %eax,(%rbx) 4011e7: 7d 05 jge 4011ee <phase_6+0xfa> 4011e9: e8 4c 02 00 00 callq 40143a <explode_bomb> 4011ee: 48 8b 5b 08 mov 0x8(%rbx),%rbx 4011f2: 83 ed 01 sub $0x1,%ebp 4011f5: 75 e8 jne 4011df <phase_6+0xeb>
翻译代码:
ebp=5; do rax=*(rbx+8); eax=*rax; if(*rbx<eax)explode_bomb; rbx=*(rbx+8); while(--ebp!=0);
该部分利用一个循环,判断序列是否为降序,如果不是则调用
Reference
- CSAPP