CSAPP-bomb实验
纪念一下bomb实验
看汇编代码感觉要注意以下几点:
1、一个过程开头一般是sub sp,用来分配栈空间
2、然后保存寄存器
3、如果过程A中还调用了其他过程B,那么在调用前会有参数的传递;可以配合过程B的代码和过程A中的参数传递看懂寄存器的意义
4、以$开头的是立即数,就是10进制数,下文中有6304464这样的数作为地址偏移量,(我一开始以为是16进制)这个地址加8就是6304472
phase1
0000000000400ee0 <phase_1>://从地址4203520处读字符串,与输入的字符串比较,如果一样,则通过
400ee0: 48 83 ec 08 subq $8, %rsp
400ee4: be 00 24 40 00 movl $4203520, %esi //内存中字符串的起始地址,在gdb中用 x/sb 4203520可以查看
400ee9: e8 4a 04 00 00 callq 0x401338 <strings_not_equal>
400eee: 85 c0 testl %eax, %eax
400ef0: 74 05 je 0x400ef7 <phase_1+0x17>
400ef2: e8 43 05 00 00 callq 0x40143a <explode_bomb>
400ef7: 48 83 c4 08 addq $8, %rsp
400efb: c3 retq
phase2
0000000000400efc <phase_2>://输入6个int型数字,答案是首项为1,公比为2的等比数列
400efc: 55 pushq %rbp
400efd: 53 pushq %rbx
400efe: 48 83 ec 28 subq $40, %rsp
400f02: 48 89 e6 movq %rsp, %rsi //当前sp存入si中,作为read_six_number的输入参数,输入的6个数字会依次存在si开始向上(地址增大)的地方
400f05: e8 52 05 00 00 callq 0x40145c <read_six_numbers>
400f0a: 83 3c 24 01 cmpl $1, (%rsp) //判断第一个数是不是1,不是则explode
400f0e: 74 20 je 0x400f30 <phase_2+0x34>
400f10: e8 25 05 00 00 callq 0x40143a <explode_bomb>
400f15: eb 19 jmp 0x400f30 <phase_2+0x34>
400f17: 8b 43 fc movl -4(%rbx), %eax
400f1a: 01 c0 addl %eax, %eax //相当于乘2
400f1c: 39 03 cmpl %eax, (%rbx) //判断当前数是不是前一个数的2倍
400f1e: 74 05 je 0x400f25 <phase_2+0x29>
400f20: e8 15 05 00 00 callq 0x40143a <explode_bomb>
400f25: 48 83 c3 04 addq $4, %rbx
400f29: 48 39 eb cmpq %rbp, %rbx
400f2c: 75 e9 jne 0x400f17 <phase_2+0x1b>
400f2e: eb 0c jmp 0x400f3c <phase_2+0x40>
400f30: 48 8d 5c 24 04 leaq 4(%rsp), %rbx
400f35: 48 8d 6c 24 18 leaq 24(%rsp), %rbp
400f3a: eb db jmp 0x400f17 <phase_2+0x1b>
400f3c: 48 83 c4 28 addq $40, %rsp
400f40: 5b popq %rbx
400f41: 5d popq %rbp
400f42: c3 retq
phase3
0000000000400f43 <phase_3>://输入两个数,有7组答案
400f43: 48 83 ec 18 subq $24, %rsp
400f47: 48 8d 4c 24 0c leaq 12(%rsp), %rcx //存第二个数的地址
400f4c: 48 8d 54 24 08 leaq 8(%rsp), %rdx //存第一个数的地址
400f51: be cf 25 40 00 movl $4203983, %esi
400f56: b8 00 00 00 00 movl $0, %eax //eax是用来存scanf读入数据的个数的
400f5b: e8 90 fc ff ff callq 0x400bf0 <__isoc99_sscanf@plt>
400f60: 83 f8 01 cmpl $1, %eax //读入数的数量要大于1
400f63: 7f 05 jg 0x400f6a <phase_3+0x27>
400f65: e8 d0 04 00 00 callq 0x40143a <explode_bomb>
400f6a: 83 7c 24 08 07 cmpl $7, 8(%rsp) //第一个数要小于等于7
400f6f: 77 3c ja 0x400fad <phase_3+0x6a>
400f71: 8b 44 24 08 movl 8(%rsp), %eax
400f75: ff 24 c5 70 24 40 00 jmpq *4203632(,%rax,8) //注意4203632地址处的数为0x400f7c,就是跳转到下一行,加上偏移量8*第一个数,只要第二个数和下面的数对应即可
400f7c: b8 cf 00 00 00 movl $207, %eax
400f81: eb 3b jmp 0x400fbe <phase_3+0x7b>
400f83: b8 c3 02 00 00 movl $707, %eax
400f88: eb 34 jmp 0x400fbe <phase_3+0x7b>
400f8a: b8 00 01 00 00 movl $256, %eax
400f8f: eb 2d jmp 0x400fbe <phase_3+0x7b>
400f91: b8 85 01 00 00 movl $389, %eax
400f96: eb 26 jmp 0x400fbe <phase_3+0x7b>
400f98: b8 ce 00 00 00 movl $206, %eax
400f9d: eb 1f jmp 0x400fbe <phase_3+0x7b>
400f9f: b8 aa 02 00 00 movl $682, %eax
400fa4: eb 18 jmp 0x400fbe <phase_3+0x7b>
400fa6: b8 47 01 00 00 movl $327, %eax
400fab: eb 11 jmp 0x400fbe <phase_3+0x7b>
400fad: e8 88 04 00 00 callq 0x40143a <explode_bomb>
400fb2: b8 00 00 00 00 movl $0, %eax
400fb7: eb 05 jmp 0x400fbe <phase_3+0x7b>
400fb9: b8 37 01 00 00 movl $311, %eax
400fbe: 3b 44 24 0c cmpl 12(%rsp), %eax
400fc2: 74 05 je 0x400fc9 <phase_3+0x86>
400fc4: e8 71 04 00 00 callq 0x40143a <explode_bomb>
400fc9: 48 83 c4 18 addq $24, %rsp
400fcd: c3 retq
phase4
0000000000400fce <func4>:
400fce: 48 83 ec 08 subq $8, %rsp
400fd2: 89 d0 movl %edx, %eax //dx存的14
400fd4: 29 f0 subl %esi, %eax //si存的0,所以ax为14
400fd6: 89 c1 movl %eax, %ecx
400fd8: c1 e9 1f shrl $31, %ecx //逻辑右移31,cx为0
400fdb: 01 c8 addl %ecx, %eax //ax依然14
400fdd: d1 f8 sarl %eax //右移1,ax变7
400fdf: 8d 0c 30 leal (%rax,%rsi), %ecx //cx为7
400fe2: 39 f9 cmpl %edi, %ecx //di存的第一个数
400fe4: 7e 0c jle 0x400ff2 <func4+0x24> //第一个数小于等于7
400fe6: 8d 51 ff leal -1(%rcx), %edx
400fe9: e8 e0 ff ff ff callq 0x400fce <func4>
400fee: 01 c0 addl %eax, %eax
400ff0: eb 15 jmp 0x401007 <func4+0x39>
400ff2: b8 00 00 00 00 movl $0, %eax
400ff7: 39 f9 cmpl %edi, %ecx
400ff9: 7d 0c jge 0x401007 <func4+0x39> //第一个数大于等于7,所以只能为7
400ffb: 8d 71 01 leal 1(%rcx), %esi
400ffe: e8 cb ff ff ff callq 0x400fce <func4>
401003: 8d 44 00 01 leal 1(%rax,%rax), %eax
401007: 48 83 c4 08 addq $8, %rsp
40100b: c3 retq
000000000040100c <phase_4>://输入2个数字
40100c: 48 83 ec 18 subq $24, %rsp
401010: 48 8d 4c 24 0c leaq 12(%rsp), %rcx //第二个数存储地址
401015: 48 8d 54 24 08 leaq 8(%rsp), %rdx //第一个数存储地址
40101a: be cf 25 40 00 movl $4203983, %esi
40101f: b8 00 00 00 00 movl $0, %eax //eax置零,调用scanf后返回读入的数据个数
401024: e8 c7 fb ff ff callq 0x400bf0 <__isoc99_sscanf@plt>
401029: 83 f8 02 cmpl $2, %eax //从这看出来要输入两个数字,不等于2就explode
40102c: 75 07 jne 0x401035 <phase_4+0x29>
40102e: 83 7c 24 08 0e cmpl $14, 8(%rsp) //第一个数小于等于14
401033: 76 05 jbe 0x40103a <phase_4+0x2e>
401035: e8 00 04 00 00 callq 0x40143a <explode_bomb>
40103a: ba 0e 00 00 00 movl $14, %edx
40103f: be 00 00 00 00 movl $0, %esi
401044: 8b 7c 24 08 movl 8(%rsp), %edi //上面3行是传递参数给func4
401048: e8 81 ff ff ff callq 0x400fce <func4>
40104d: 85 c0 testl %eax, %eax
40104f: 75 07 jne 0x401058 <phase_4+0x4c>
401051: 83 7c 24 0c 00 cmpl $0, 12(%rsp) //这个地址存的第二个数
401056: 74 05 je 0x40105d <phase_4+0x51> //第二个数等于0
401058: e8 dd 03 00 00 callq 0x40143a <explode_bomb>
40105d: 48 83 c4 18 addq $24, %rsp
401061: c3 retq
phase5
0000000000401062 <phase_5>://输入长度为6的字符串,分别取他们的低四位作为偏移量(0-15),在另一已知字符串中查找字符作为替换,生成新的字符串并要和密码串一致
401062: 53 pushq %rbx
401063: 48 83 ec 20 subq $32, %rsp
401067: 48 89 fb movq %rdi, %rbx //di存储了输入字符串的首地址,字符串以/0结尾
40106a: 64 48 8b 04 25 28 00 00 00 movq %fs:40, %rax
401073: 48 89 44 24 18 movq %rax, 24(%rsp)
401078: 31 c0 xorl %eax, %eax//ax置零,是string_length的返回值保存处
40107a: e8 9c 02 00 00 callq 0x40131b <string_length>
40107f: 83 f8 06 cmpl $6, %eax //输入字符串长度必须为6
401082: 74 4e je 0x4010d2 <phase_5+0x70>
401084: e8 b1 03 00 00 callq 0x40143a <explode_bomb>
401089: eb 47 jmp 0x4010d2 <phase_5+0x70>
40108b: 0f b6 0c 03 movzbl (%rbx,%rax), %ecx
40108f: 88 0c 24 movb %cl, (%rsp)
401092: 48 8b 14 24 movq (%rsp), %rdx
401096: 83 e2 0f andl $15, %edx //以上4行是取输入字符串每一个字符的低4位,放在dx中
401099: 0f b6 92 b0 24 40 00 movzbl 4203696(%rdx), %edx //用dx作为偏移量,取4203696+偏移量处的字符
4010a0: 88 54 04 10 movb %dl, 16(%rsp,%rax) //生成新字符串,放置在运行时栈中
4010a4: 48 83 c0 01 addq $1, %rax
4010a8: 48 83 f8 06 cmpq $6, %rax
4010ac: 75 dd jne 0x40108b <phase_5+0x29>
4010ae: c6 44 24 16 00 movb $0, 22(%rsp) //保存在栈中的字符串要以\0结尾
4010b3: be 5e 24 40 00 movl $4203614, %esi //密码字符串首地址
4010b8: 48 8d 7c 24 10 leaq 16(%rsp), %rdi //栈中字符串首地址,是函数string-not-equal的输入参数
4010bd: e8 76 02 00 00 callq 0x401338 <strings_not_equal>//判断两个字符串是否相等,所以我们可以根据密码串构造输入串,输入串不唯一(只要ascii低4位一样即可)
4010c2: 85 c0 testl %eax, %eax
4010c4: 74 13 je 0x4010d9 <phase_5+0x77>
4010c6: e8 6f 03 00 00 callq 0x40143a <explode_bomb>
4010cb: 0f 1f 44 00 00 nopl (%rax,%rax)
4010d0: eb 07 jmp 0x4010d9 <phase_5+0x77>
4010d2: b8 00 00 00 00 movl $0, %eax
4010d7: eb b2 jmp 0x40108b <phase_5+0x29>
4010d9: 48 8b 44 24 18 movq 24(%rsp), %rax
4010de: 64 48 33 04 25 28 00 00 00 xorq %fs:40, %rax
4010e7: 74 05 je 0x4010ee <phase_5+0x8c>
4010e9: e8 42 fa ff ff callq 0x400b30 <__stack_chk_fail@plt>
4010ee: 48 83 c4 20 addq $32, %rsp
4010f2: 5b popq %rbx
4010f3: c3 retq
phase6
00000000004010f4 <phase_6>://一个已知的存储int数据的链表,你将他从大到小排序,生成6个数字,分别表示排序后数组中的数对应在原数组的位置,
4010f4: 41 56 pushq %r14 //然后用7分别减它们,就是答案
4010f6: 41 55 pushq %r13
4010f8: 41 54 pushq %r12
4010fa: 55 pushq %rbp
4010fb: 53 pushq %rbx
4010fc: 48 83 ec 50 subq $80, %rsp
401100: 49 89 e5 movq %rsp, %r13
401103: 48 89 e6 movq %rsp, %rsi //si输入参数,下面读6个数字
401106: e8 51 03 00 00 callq 0x40145c <read_six_numbers>
40110b: 49 89 e6 movq %rsp, %r14
40110e: 41 bc 00 00 00 00 movl $0, %r12d
401114: 4c 89 ed movq %r13, %rbp
401117: 41 8b 45 00 movl (%r13), %eax
40111b: 83 e8 01 subl $1, %eax
40111e: 83 f8 05 cmpl $5, %eax
401121: 76 05 jbe 0x401128 <phase_6+0x34>//jbe(无符号)判断这个数是不是在1-6之间,为了排除0,用的先减1再看是不是小于等于5
401123: e8 12 03 00 00 callq 0x40143a <explode_bomb>
401128: 41 83 c4 01 addl $1, %r12d
40112c: 41 83 fc 06 cmpl $6, %r12d
401130: 74 21 je 0x401153 <phase_6+0x5f>
401132: 44 89 e3 movl %r12d, %ebx
401135: 48 63 c3 movslq %ebx, %rax
401138: 8b 04 84 movl (%rsp,%rax,4), %eax
40113b: 39 45 00 cmpl %eax, (%rbp)
40113e: 75 05 jne 0x401145 <phase_6+0x51>//以上判断其他输入的数是不是和他不相等
401140: e8 f5 02 00 00 callq 0x40143a <explode_bomb>
401145: 83 c3 01 addl $1, %ebx
401148: 83 fb 05 cmpl $5, %ebx
40114b: 7e e8 jle 0x401135 <phase_6+0x41>//内循环控制:判断其他输入的数是不是和他不相等
40114d: 49 83 c5 04 addq $4, %r13
401151: eb c1 jmp 0x401114 <phase_6+0x20>//外循环控制:每一个数都要做上述操作:在1-6之间?和其他数不等?
401153: 48 8d 74 24 18 leaq 24(%rsp), %rsi //si为循环边界
401158: 4c 89 f0 movq %r14, %rax
40115b: b9 07 00 00 00 movl $7, %ecx
401160: 89 ca movl %ecx, %edx
401162: 2b 10 subl (%rax), %edx
401164: 89 10 movl %edx, (%rax)
401166: 48 83 c0 04 addq $4, %rax
40116a: 48 39 f0 cmpq %rsi, %rax
40116d: 75 f1 jne 0x401160 <phase_6+0x6c>//以上是拿7去减输入的数字
40116f: be 00 00 00 00 movl $0, %esi
401174: eb 21 jmp 0x401197 <phase_6+0xa3>
401176: 48 8b 52 08 movq 8(%rdx), %rdx。//大于1的话需要循环去找相应的地址(:-)
40117a: 83 c0 01 addl $1, %eax
40117d: 39 c8 cmpl %ecx, %eax
40117f: 75 f5 jne 0x401176 <phase_6+0x82>
401181: eb 05 jmp 0x401188 <phase_6+0x94>
401183: ba d0 32 60 00 movl $6304464, %edx
401188: 48 89 54 74 20 movq %rdx, 32(%rsp,%rsi,2)
40118d: 48 83 c6 04 addq $4, %rsi
401191: 48 83 fe 18 cmpq $24, %rsi
401195: 74 14 je 0x4011ab <phase_6+0xb7>
401197: 8b 0c 34 movl (%rsp,%rsi), %ecx
40119a: 83 f9 01 cmpl $1, %ecx
40119d: 7e e4 jle 0x401183 <phase_6+0x8f>//以上做的是:按照你输入的数字,去找链表对应位置节点的地址
40119f: b8 01 00 00 00 movl $1, %eax //1的话就是直接放首地址6304464 (:-)
4011a4: ba d0 32 60 00 movl $6304464, %edx //6304464为链表首地址,注意这个链表结构是,低地址放int数,高地址放下一个节点地址
4011a9: eb cb jmp 0x401176 <phase_6+0x82>//比如,6304464开始的4个字节为int数,6304472开始的8字节为下一个节点的地址
4011ab: 48 8b 5c 24 20 movq 32(%rsp), %rbx
4011b0: 48 8d 44 24 28 leaq 40(%rsp), %rax
4011b5: 48 8d 74 24 50 leaq 80(%rsp), %rsi
4011ba: 48 89 d9 movq %rbx, %rcx
4011bd: 48 8b 10 movq (%rax), %rdx
4011c0: 48 89 51 08 movq %rdx, 8(%rcx)
4011c4: 48 83 c0 08 addq $8, %rax
4011c8: 48 39 f0 cmpq %rsi, %rax
4011cb: 74 05 je 0x4011d2 <phase_6+0xde>
4011cd: 48 89 d1 movq %rdx, %rcx
4011d0: eb eb jmp 0x4011bd <phase_6+0xc9>//以上为重新链接存储在栈中的新链表,从栈的低地址到高地址依次链接,表头为低
4011d2: 48 c7 42 08 00 00 00 00 movq $0, 8(%rdx)
4011da: bd 05 00 00 00 movl $5, %ebp
4011df: 48 8b 43 08 movq 8(%rbx), %rax
4011e3: 8b 00 movl (%rax), %eax
4011e5: 39 03 cmpl %eax, (%rbx)
4011e7: 7d 05 jge 0x4011ee <phase_6+0xfa> //以上判断链表从头开始是不是递减的
4011e9: e8 4c 02 00 00 callq 0x40143a <explode_bomb>//所以答案就是,从6304464开始用gdb看一下链表,生成6个数字
4011ee: 48 8b 5b 08 movq 8(%rbx), %rbx //分别表示从大到小排序后的数对应在原数组的位置,再用7减,就是输入的正确答案
4011f2: 83 ed 01 subl $1, %ebp
4011f5: 75 e8 jne 0x4011df <phase_6+0xeb>
4011f7: 48 83 c4 50 addq $80, %rsp
4011fb: 5b popq %rbx
4011fc: 5d popq %rbp
4011fd: 41 5c popq %r12
4011ff: 41 5d popq %r13
401201: 41 5e popq %r14
401203: c3 retq