SDCTF 2023 Writeup
I was so excited to participate in my first SDCTF event as an incoming student of UC San Diego. :-) It was a great opportunity to learn new skills, meet awesome people and have fun solving challenges. I really enjoyed the experience and I can’t wait for the next one!
PWN
Turtle Shell
Bypass the checking with add rax, 0x1
tROPic-thunder
Use open
, read
and write
to read flag
money-printer
v6
is unsigned int but all check against v4
is signed operation, so we can bypass the check with negative number.
Then use the format string to leak flag.
money-printer2
I didn’t manage to brute force the address before the CTF ended, but I still want to note down the solution.
Notice that there are some residual address on the stack
0x00007ffc91e56ce0│+0x0000: 0xfffffb0000000000 ← $rsp
0x00007ffc91e56ce8│+0x0008: 0xfffffef2800004f5
0x00007ffc91e56cf0│+0x0010: 0x0000000000000000 ← $rdi
0x00007ffc91e56cf8│+0x0018: 0x0000000000000000
0x00007ffc91e56d00│+0x0020: 0x000000000000000b ("
"?)
0x00007ffc91e56d08│+0x0028: 0x00007f4026c02660 → push rbp
0x00007ffc91e56d10│+0x0030: 0x00007ffc91e56d78 → 0x00007ffc91e56e48 → 0x00007ffc91e58170 → "./money-printer2"
0x00007f4026c02660
is in ld.so
and 0x00007ffc91e56d78
points the the stack.
So we basically have two approach:
rtld_global
Partially overwrite the address of ld.so
, make it point to _rtld_global+3840
, where the rtld_lock_default_lock_recursive
is stored.
And
_dl_fini()
will be registered by _cxa_atexit
in __libc_start_main()
. And _dl_fini()
will be called by __run_exit_handlers()
when the program exits. And rtld_lock_default_lock_recursive
will be called by _dl_fini()
. So if we overwrite this field, we can jump back to main when the program exits. Then turn the challenge into a normal format string challenge.
Canary
There are also some residual stack pointers on the stack. We can partially overwrite them and make them point to the canary. Then overwrite the GOT entry of __stack_chk_fail
to main
and turn the challenge into a normal format string challenge.
Didn’t have the luck to hit the 1/4096 probability :(
Misc
Secure Runner
CRC32 collision. Easy to find with https://github.com/theonlypwner/crc32/
Fork bomb protector
Use the built-in command to read the flag.
Crypto
Jumbled snake
First, recover the key with
the_quick_brown_fox_jumps_over_the_lazy_dog
By regex matching, we can find the pattern easily.
Now recover the key with __doc__
Some keys can be identified by ourself now
Now try to recover the script, we can notice the second hint.
And recover the script with this hint.
And finally we have
And finally we can have the flag
Lake of Pseudo Random Fire
Notice that pseudorandom(self, msg)
will decrypt the msg
after XOR with 0xff
. So by XORing the first part of the returned strings of pseudorandom(self, msg)
we can recover the msg
sent by us if it is a pseudorandom door.