plaidCTF 2014 - curlcore (for250)

For PlaidCTF2014, Eindbazen and fail0verflow joined forces as 0xffa, the Final Fail Alliance.
Don't miss out on other write-ups at Eindbazen's site!

Last week we played plaidCTF with Eindbazen under the name 0xffa (can you figure out why that name?). Write-ups are mandatory in the rules, so let’s start with an easy one :-)

curlcore
Forensics (250 pts)
-------------------
We managed to grab a memory dump off of The Plague's computer while
he was making a secure download. We think he may have been looking
for new places to hide the Prime Factorizer. Can you figure out what
messages were sent through his computer?

For this challenge, you get 3 files:

  • capture (a network capture)
  • corefile (a memory dump)
  • coremaps (the process’s memory map)

and the shell script which helped generating those files

#/bin/sh

sudo rm /tmp/capture 2>/dev/null
sudo dumpcap -i eth0 -w /tmp/capture &
DUMPCAPPID=$!

sleep 1
OUTPUT="`/usr/bin/env -i /bin/dash -c 'ulimit -c unlimited; curl -k https://curlcore.local.plaidctf.com/flag.html & PID=$!;     sleep 5; printf "generate-core-file\ninfo proc mappings\ndetach\n" | sudo gdb attach $PID; wait'`"
sleep 1

sudo kill -INT $DUMPCAPPID
wait

sudo chown `whoami` /tmp/capture

echo "$OUTPUT"

sudo mv "`echo "$OUTPUT" | grep -o 'Saved corefile .*$' | cut -c 16-`" /tmp/corefile
sudo chown `whoami` /tmp/corefile


echo "$OUTPUT" | awk '/Mapped address spaces/,/(gdb)/' | grep -v '(gdb)' > /tmp/coremaps

rm /tmp/curlcore.tgz 2>/dev/null
tar czf /tmp/curlcore.tgz `grep -o ' /.*$' /tmp/coremaps | sort -us | tr '\n' ' '` /tmp/corefile /tmp/coremaps /tmp/capture     "$0"

Since we have a network capture of the https download, we need to find a way to decrypt the SSL communication…

Step 1 - Wireshark to the rescue!

The first step is to open the capture under wireshark and copy the session ID from the server Hello message.

Wireshark Session ID

19ab5edc02f097d5074890e44b483a49b083b043682993f046a55f265f11b5f4

Step 2 - Finding the SSL master key

With this session ID at hand, we can search for it in the memory dump (corefile) using any hexeditor

0004fbe0  30 00 00 00 19 1e 50 42  e6 b3 13 71 aa 65 25 8e  |0.....PB...q.e%.|
0004fbf0  13 b2 dc 71 4d 98 4d f8  d6 8f ad 67 8f f0 a2 fc  |...qM.M....g....|
0004fc00  49 47 6d 65 c3 a1 61 f7  18 57 2c 3f 5d b8 56 6a  |IGme..a..W,?].Vj|
0004fc10  0d e8 9e 58 20 00 00 00  19 ab 5e dc 02 f0 97 d5  |...X .....^.....|
0004fc20  07 48 90 e4 4b 48 3a 49  b0 83 b0 43 68 29 93 f0  |.H..KH:I...Ch)..|
0004fc30  46 a5 5f 26 5f 11 b5 f4  00 00 00 00 00 00 00 00  |F._&_...........|

Not boring you with too much details, what we have just found is the ssl_session_st struct from ssl.h

struct ssl_session_st
{
    // [...]
    int master_key_length;
    unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH];
    unsigned int session_id_length;
    unsigned char session_id[SSL_MAX_SSL_SESSION_ID_LENGTH];
    // [...]
};

At 0x0004fc14 you can see the session ID length, at 0x0004fc18 the session ID and of course the SSL master key at 0x0004fbe4.

The master key is therefore:

191E5042E6B31371AA65258E13B2DC714D984DF8D68FAD678FF0A2FC49476D65C3A161F718572C3F5DB8566A0DE89E58

Armed with both the session ID and the master key we can now create a file ‘key.txt’:

RSA Session-ID:19ab5edc02f097d5074890e44b483a49b083b043682993f046a55f265f11b5f4 Master-Key:191E5042E6B31371AA65258E13B2DC714D984DF8D68FAD678FF0A2FC49476D65C3A161F718572C3F5DB8566A0DE89E58

load this file in wireshark with Edit->Preferences->Protocols->SSL:‘(Pre)-Master-Secret log filename’ and apply.

Step 3 - Profit!

Right-click on any of the https messages and select ‘Follow SSL Stream’

Wireshark Decoded SSL Stream

Your flag is: congratz_you_beat_openssl_as_a_whitebox

The fastest 250 points you could get ;-)