WhiteHat Contest 2024 Quals - gf
Table of Contents
0x00. Introduction
)
A challenge where I got stuck combining gadgets here and there. I figured out the solution 20 minutes before the end…
0x01. Vulnerability
__int64 __fastcall
A simple BOF vulnerability occurs where 0xbc bytes are read into the 16-byte dest.
0x02. Exploit
There’s not a single gadget for ROP, let alone an output function. Then I got a hint from looking at memory.
Looking around dest + 0xb8, the end of read(), there’s a suspicious libc address. The lower 3 bytes are 0x00, and we can write exactly up to this point.
So without a libc leak, we can use this part to craft an expected one-shot gadget address and hope that ASLR loads the actual one-shot gadget at that address.
The register values when returning from main() are as follows.
)
At this point, we need to satisfy the one-shot gadget conditions. After staring at gadgets for hours, the method immediately came to mind.
)
|| ||
|| ||
Among the one-shot gadgets, there was one with constraints on rsi and rdx like above, and the binary has gadgets like these.
# shift_rsi_ret gadget
# pop_rsi_pop_rdx_push_rsi_ret gadget
First, rdx can be controlled through the pop_rsi_pop_rdx_push_rsi_ret gadget, and for some reason, the shift_rsi_ret gadget can right shift rsi by 0.5 bytes. Since rsi is holding 0x404060, calling the shift_rsi_ret gadget 6 times makes rsi 0.
Additionally, there’s a constraint that rbp-0x78 must be writable, so I set it to roughly 0x404800, the middle of the Data section.
Calculating the success rate, 0x7ffff7XXXc88 should be the actual one-shot gadget address, so it’s 1.5 bytes, meaning a 1/4096 probability of successful exploitation.
However, after the preliminaries ended, I saw someone else’s exploit with a method that could succeed 100%. Since this was new to me and seems generally applicable, I’ll make a separate post about it.
0x03. Payload
=
=
=
=
= f
=
# s = remote(server, port)
=
=
=
=
= 0x40112c
= 0x40119e
= b * 0x10
+=
+=
+=
+=
+= * 5
+= *
+= b # 0x754c18 4b ac 88
=
=
=
=