From 503f0561d555841820977373f9ff2b3c7d1b6b71 Mon Sep 17 00:00:00 2001
From: Tharre <tharre3@gmail.com>
Date: Sun, 19 Jan 2020 22:33:05 +0100
Subject: [PATCH] Add tharre/seccon19.md

---
 writeups/tharre/seccon19.md | 80 +++++++++++++++++++++++++++++++++++++
 1 file changed, 80 insertions(+)
 create mode 100644 writeups/tharre/seccon19.md

diff --git a/writeups/tharre/seccon19.md b/writeups/tharre/seccon19.md
new file mode 100644
index 0000000..24f38b5
--- /dev/null
+++ b/writeups/tharre/seccon19.md
@@ -0,0 +1,80 @@
+# SECCON 2019 Online CTF - pwn one
+
+## Overview
+
+This was probably the hardest challange I've done during the course, besides
+engine which was unsolvable anyway. It starts relatively simple, it's a pwn
+challange and you get a binary, `one_ef36d5ef6169aeda65259f627f282930b93cf6e5`
+and `libc-2.27.so_18292bd12d37bfaf58e8dded9db7f1f5da1192cb`. When running the
+binary you're presented with four options, add, show, delete a memo or exit the
+program.
+
+## Find the vulnerability
+
+After playing around with it a bit you find a bug rather quickly, adding a memo
+and then deleting it twice produces a double free:
+
+```
+free(): double free detected in tcache 2
+[1]    43966 abort (core dumped)  ./one_ef36d5ef6169aeda65259f627f282930b93cf6e5
+```
+
+This alone would not really be exploitable, however this was run directly on my
+updated Arch Linux machine which was running `glibc-2.30`. Since there was
+suspiciously also a `libc-2.27.so` included in the challange it was rather
+obvious that it was meant to only be exploitable with that or older versions.
+And indeed if you google `glibc 2.27 double free` you get tons of results
+describing exploitation methods related to tcache double-free.
+
+## Trying to build an exploit
+
+So we know what vulnerability we want to exploit and there's tons of additional
+material available describing similar exploits so this should be easy right?
+
+Well, not so fast. First of all we need to actually run the binary with
+`libc-2.27`. I tried for quite a bit to actually run the thing on my machine
+directly with commands like `LD_LIBRARY_PATH=$(pwd) ./ld-linux-x86-64.so.2
+./one_ef36d5ef6169aeda65259f627f282930b93cf6e5` but couldn't get it to work in a
+timely fashion, so I just settled on working in a Ubuntu 18.04 docker container
+after reading `cluosh` hint that they use the same libc version.
+
+The next difficulty was actually applying what I've read about tcache's freelist
+to write to arbitrary addresses in memory. The details of how this works are
+quite complicated, I probably don't understand them fully myself either, but the
+gist of it is that you can trick glibc into returning a pointer to a memory
+region that was never part of the original heap region that glibc uses and that
+we can control. This happens because after a double free there's a loop in the
+tcache freelist, the linked-list that holds available memory chunks, which
+causes the chunk we recieve from `malloc()` to not be removed from the freelist.
+We can then write to this address by adding a memo, where the first 8 byte will
+override the next pointer, which we can point to any memory region we want. Now
+we just need to do force two more allocations, one to reach our crafted `next`
+pointer and one to actually get back our target pointer.
+
+So to write value to an arbitrary pointer `ptr`, we just do `add -> add(ptr) ->
+add -> add(value)`.
+
+## ASLR makes everything hard
+
+This is were I ultimately got stuck. So we can write to arbitrary memory
+locations, how do we actually turn this into a shell? As `cluosh` also noted on
+mattermost, we can't override GOT entries since the binary is full-relro, so
+probably the easiest way to exploit this is by overriding glibc hooks,
+especially `__free_hook`. And indeed with ASLR turned off and a debugger (and
+some fiddling) attached to get the memory address of `__free_hook` I managed to
+successfully override the hook.
+
+With ASLR turned on not so much. I did manage to find a information leak by
+doing `add -> add -> delete -> delete -> show`, however I ultimately failed to
+do anything useful with the address I leaked. Even worse, leaking the address
+made the rest of the exploit fail. The reason for this is actually rather
+obvious in hindsight, adding a memo twice meant that the tcache was getting
+messed up. Just doing `add -> delete -> delete -> delete -> delete -> show`
+would've been better.
+
+Looking at writeups from other people, the rest would actually have been doable
+as well, I really just failed at properly determining the offset to the libc
+base address.
+
+I spend around 35h on this challange, most of it after the original challange
+already ended though since SECCONs timeframe was so short.
-- 
2.43.0