Ghost in the Shellcode 2014: Pillowtalk

Pillowtalk was a 200 point crypto challenge. Provided was a stripped 64-bit binary along with a pcap file. I started off by exercising the behavior of the binary, looking at system calls/library calls to see what it was doing.

  • Client connects to server
  • Server reads 32 bytes from /dev/urandom
  • Server sends 32 bytes on the wire (not same bytes as read from /dev/urandom)
  • Client does same 32 byte read/send
  • Loop:
    • Server reads a line from stdin
    • Server sends 4 byte length
    • Server sends encrypted line
    • Client does the same steps

My first approach was by trying to use scapy to replay the pcap to the server, but this only gave complete noise, so I decided the two 32 byte values must be significant. I even tried controlling /dev/urandom (via LD_PRELOAD) to see if putting in the 32 bytes from the pcap would get to the right key. It didn’t.

I started reversing the binary and the behavior of the translation of the 32 bytes from /dev/urandom to the 32 bytes put on the wire. Eventually I came to the conclusion (later confirmed) that the 32 bytes from /dev/urandom were used as a private key to Curve25519, leading to the 32 bytes on the wire as a public key. The 2 values would then be used by each end for key agreement for the symmetric cipher. Breaking Curve25519 seemd a bit out of scope for a CTF, so I assumed it was an implementation problem with the symmetric crypto.

It was worth noting that the ciphertext was the exact same length as the plaintext, implying that a stream cipher was in use, and that if the same plaintext was sent twice, it encrypted the same way, implying that the cipher was being reset before sending each message. This leaves messages vulnerable to known-plaintext attacks by revealing the keystream.

I started by xoring the last byte of each message with ‘\n’, and recording the position/value pairs, then xoring each byte at those positions in each message with our newly revealed keystream bytes. I also ventured a guess that the first message was ‘hi\n’, so repeated the same process for the first 2 bytes. This gave me enough revealed plaintext to start making guesses about other bytes, and repeating this process with each set of bytes revealed the flag.


Weekly Reading List for 1/18/14

I’ve decided to start posting a weekly reading list of interesting security-related articles I’ve come across in the past week. They’re not guaranteed to be new, but should at least still be relevant.

Using a BeagleBone to bypass 802.1x

Most security practitioners are already aware that NAC doesn’t provide meaningful security. While it’ll keep some random guy from plugging in to an exposed ethernet port in the lobby (shouldn’t that be turned off?), it won’t stop a determined attacker. You can just MITM the legitimate device, let it perform the 802.1x handshake, then send packets appearing to be from the legitimate device. To make it easier, ShellSherpa has put together a BeagleBone-based device to automatically MITM the NAC connection.

Screwing with microcontroller devices

Matasano and Square have announced a joint microcontroller-based CTF.

Which SDR to buy?

SDR continues to be a hot button topic, and Taylor Killian has a post from a couple of months ago to help you choose what SDR device you should get: HackRF vs. bladeRF vs. USRP. While you’ll need to understand basic radio concepts to get much out of the comparison, you should probably be at least at that level before you start doing much with SDR.

New disassembly framework

Capstone is a project to create a framework for disassembling binaries from a wide variety of architectures. Doesn’t seem to have binary extraction yet, so you’ll need to get the text segment yourself and rebase it, but I’m hopeful it’ll make its way into some interesting projects.

Dead Tree Reading

Although I’m mostly reading eBook formats, wanted to highlight which books I’m reading lately.


LD_PRELOAD for Binary Analysis

During the BreakIn CTF, there were a few challenges that depended on the return value of of libc functions like time() or rand(), and had differing behavior depending on those return values. In order to more easily reverse those binaries, it can be nice to control the return values of those functions. In other cases, you have binaries that may call functions like unlink(), system(), etc., where you prefer not to have those functions really called. (Though you are running these untrusted binaries in a VM, right?)

So let’s say there’s a program that’s built from the following source (over simplified for example):

1
2
3
4
5
6
7
8
9
10
11
12
#!c
#include <time.h>
#include <stdio.h>

int main(int argc, char **argv){
  if (time() % 86400 == 0) {
    puts("Win!\n");
    return 0;
  }
  puts("Lose\n");
  return 1;
}

So this is obviously a highly contrived example, but you only win if you hit it exactly at midnight. Now, I suppose you could change your computer clock, but you still only have a one second window to get it right. How can you control this to improve your outcomes?

There’s a wonderful trick that allows you to inject a custom shared library to be loaded before your program is run (and the symbols in it resolved) so that the functions provided by your library are used preferentially over the ones provided by the C library. First, let’s create our replacement version of time, and create one that allows us to set the time by setting an environment variable. (Note that we don’t have to replicate the same behavior of time(), as we know only the return value is used, and no pointer is passed in.)

1
2
3
4
5
6
7
8
9
10
#!c
#include <time.h>
#include <stdlib.h>

time_t time(time_t *out){
    char *tstr = getenv("TIME");
    if (tstr)
      return (time_t)atol(tstr);
    return (time_t)0;
}

Now we can build the shared object and run the program with our version of time. Note that you must use an absolute path for LD_PRELOAD, or it will only look in the LD search path.

1
2
3
4
5
6
#!sh
$ gcc -Wall -fPIC -shared -o time.so time.c
$ TIME=0 LD_PRELOAD=`pwd`/time.so ./challenge
Win!
$ TIME=1 LD_PRELOAD=`pwd`/time.so ./challenge
Lose

Note that you don’t have to completely re-implement the function you want to replace, you can actually get it and call it within your replacement function. (Note that this only works on GNU libc.) Maybe you only want unlink to work if called with the path “/deleteme”.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!c
#define _GNU_SOURCE
#include <dlfcn.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>

#define TARGET "/deleteme"

int unlink(const char *path){
  int (*real_unlink)(const char *) = dlsym(RTLD_NEXT, "unlink");
  
  if (!strncmp(TARGET, path, strlen(TARGET))) {
    return real_unlink(path);
  }
  
  fprintf(stderr, "Would unlink(%s)", path);
  return 0;
}

You can use the same build and preload instructions as before, and this will allow to delete “/deleteme”, otherwise it will just print out what it would’ve done. There are many other uses of LD_PRELOAD, but these are a couple of ways I’ve found useful for quick-and-dirty hacks.


BreakIn CTF 2014

The Threads BreakIn CTF hosted by IIIT Hyderabad has just wrapped up. Shadow Cats did pretty well, placing 16th overall, completing 22/33 challenges, especially considering we only had 2 guys playing this CTF. Mad props goes out to Dan, and here’s hoping for a bigger team turnout next week for Ghost in the Shellcode.

I’m going to be doing some writeups of a couple of the challenges I thought were particularly interesting, as well as some topical information inspired by the CTF. I’ll be linking to the writeups below as they get published.


2014 OKRs

At work, we use the OKR system for managing our objectives. I’ve decided to set myself some annual objectives and list out their key results here. At the end of the year, I’ll grade myself on my OKRs and we’ll see how I’m doing.

  • Get better at reversing
    • Complete OpenSecurityTraining.info x86 class
    • Complete 3 reversing challenges from WeChall
  • Play CTFs
    • Compete in at least 3 CTFs
    • (Stretch Goal) Top 10% Finish
    • Complete the challenges on OverTheWire.org
  • Blogging
    • At least 1 Blog Post/week
  • Lose Weight & Exercise
    • Lose 25 lbs.
    • Get at least 60 minutes aerobic exercise a week
  • Become a more powerful vim/zsh user
    • Use vim keybindings in zsh
    • Read full zsh guide
    • Learn 6 new vim commands