- The program builds Clang AST and converts it into its own representation.
- The goal is to give it a
.c
file and read/flag
. - The
#
sign is prohibited. Digraphs and trigraphs are off. - There is no interactivity, one can only submit a file.
- The binary is loaded at a fixed address. RELRO is off.
- The goal is to give it a
- The program creates nodes for functions and various statements.
- By adding calls like
annotation("abc")
andtype("def")
inside blocks, it's possible to associate the respective strings with them. - Annotations are stored in
char [64]
(filled withstrcpy()
, protected by a length check) and types are stored instd::string
(no longer than 18 bytes) that immediately follows it.
- By adding calls like
- Bug: the annotation length check is flawed, since it looks for the next
"
without considering escaping. So it thinks"\"AAA"
is only 3 bytes, but copies all 7.- Arbitrary write is achieved by overflowing the annotation into the type's
std::string
pointer with the target address, and then callingtype()
with the desired value. - Since
strcpy()
stops at the first zero, callannotation()
multiple times: first with all zeros changed toA
, then all except the last one, and so on. - Both
type()
andannotation()
preserve binary zeros and non-printable characters. One only has to make sure that\n
and"
do not appear, since they break string literals.
- Arbitrary write is achieved by overflowing the annotation into the type's
- A worthy goal is to call
main(..., ["prog", "/flag"])
. This will print the flag in the Clang error message. - There don't seem to be any good gadgets or GOT targets.
- ret2csu is gone.
- No stack pivot gadgets.
- No useful functions like
system()
orexecve()
.
- There is a global
functionList
variable, which contains function nodes.- Overwrite it with a fake vector containing two fake nodes.
- The first node is the "bomb" node. Its purpose is to stop the infinite
recursion, since the server does not copy the program output on timeouts.
- Leave all fields at 0, in the fake vtable set the pointer to the
dump()
method togetpid()
, essentially making it a no-op. - Fake the heap chunk headers around the node itself, making it possible
to
free()
it once on the originalmain()
invocation, but making the program crash due to double free on the second invocation.
- Leave all fields at 0, in the fake vtable set the pointer to the
- The second node is the "flag" node. Its purpose is to call
main()
with the controlled arguments.- In the fake vtable, set the pointer to the
dump()
method to a gadget that loadsrsi
and jump address from memory pointed to byrdi
(which points to the "flag" node itself). - Make
rsi
point to fake argv. - Use the second instruction of
main()
as a jump address. Jumping tomain()
itself causes the stack to become misaligned, which is fixed by skipping the firstpush %rbp
.
- In the fake vtable, set the pointer to the
- The server's pipe is clogged by clang diagnostics, so it hangs. The diagnostics are emitted, because string literals contain unprintable and NUL characters. Make it less verbose by putting everything on one line.
CST
Folders and files
Name | Name | Last commit date | ||
---|---|---|---|---|
parent directory.. | ||||