time to bleed by Joe Damato

technical ramblings from a wanna-be unix dinosaur

Ripping OAuth tokens (or other secrets) out of TweetDeck, Twitter.app, and other apps

View Comments


If you enjoy this article, subscribe (via RSS or e-mail) and follow me on twitter.

the setup

So, you have some sort of OSX app. Maybe it’s Twitter.app, TweetDeck, or something else that has a secret stored inside the binary. You want to extract this secret, maybe because you want to impersonate the official client of a service or maybe just because you want to see if you can hack the gibson.

I don’t actually really care about Twitter clients, personally. I just wanted to see if I could rip the OAuth token out of some official clients and how long it would take me.

strings, MITM, objdump, gdb, et al.

Not surprisingly, there are many different ways to rip data out of a binary. You can use strings to dump printable strings, play with mitmproxy, or simply reverse engineer the binary by reading objdump (or GDB or whatever) output. I’ve used all of these methods before with great success when attempting to hack the planet, but I had an idea for something a little bit more interesting that can be easily reused.

what happens at a low level

Turns out that, at least at a low level, usually malloc/calloc/whatever and free end up getting called to allocate and deallocate memory regions used by applications. Sure, some apps only use static memory, other apps are built in languages that have a custom allocator, but there are enough apps out there that after you peel away the various candy coated layers of abstraction just end up calling malloc and free provided in the libc on their system provided by the vendor.

So, I assumed that TweetDeck, Twitter.app, and everyone else would be doing something like this underneath all the fancy frameworks:

/* psuedo code, obviously */
buf = malloc(N);
memcpy(buf, "secretkey", strlen("secretkey"));
/* some functions that talk to the api server and do other stuff */
free(buf);

malloc shims

Many malloc implementations provide an interface for the user to create custom shim functions to execute in place of the system-provided malloc/calloc/realloc/free functions. These shim interfaces are useful for many reasons, including but not limited to memory profilers, leak checkers, and other useful debugging tools.

abuse

What if I abuse malloc’s shim interface on OSX and provide a free function that prints the contents of every buffer it is supposed to free before actually freeing it?

shim code

About 50 lines of horrible C code (also available here.):

void (*real_free)(malloc_zone_t *zone, void *ptr);
void (*real_free_definite_size)(malloc_zone_t *zone, void *ptr, size_t size);

void my_free(malloc_zone_t *zone, void *ptr)
{
  char *tmp = ptr;
  char tmp_buf[1025] = {0};
  size_t total = 0;

  /* lol its fine */
  while (*tmp != '\0') {
    tmp_buf[total] = *tmp;
    total++;
    if (total == 1024)
      break;
    tmp++;
  }

  malloc_printf("%s\n", tmp_buf);
  real_free(zone, ptr);
}

void my_free_definite_size(malloc_zone_t *zone, void *ptr, size_t size)
{
  char tmp_buf[1024] = {0};

  if (size < 1024) {
    memcpy(tmp_buf, ptr, size);
  } else {
    memcpy(tmp_buf, ptr, 1023);
  }

  malloc_printf("%s\n", tmp_buf);
  real_free_definite_size(zone, ptr, size);
}

void __attribute__((constructor)) my_init() {
  malloc_zone_t *zone = malloc_default_zone();

  /* save the addresses of the REAL free functions */
  real_free = zone->free;
  real_free_definite_size = zone->free_definite_size;

  /* replace there with my shims */
  zone->free_definite_size = my_free_definite_size;
  zone->free = my_free;
}

insertion

All you have to do is build a dylib of the above C code and insert it like this:

% DYLD_INSERT_LIBRARIES="mallshim.dylib" /Applications/Twitter.app/Contents/MacOS/Twitter

And, boom. A lot of strings will get printed out, so you should use grep to help sift through the output.

output

Let’s see what happens if we insert this little guy into TweetDeck and Twitter.app:

Twitter.app

% DYLD_INSERT_LIBRARIES="mallshim.dylib" /Applications/Twitter.app/Contents/MacOS/Twitter 2>&1| egrep -i "oauth_token|oauth_consumer|oauth_timestamp|oauth_nonce" --color=auto

(I censored out some of the good stuff)

TweetDeck

DYLD_INSERT_LIBRARIES="mallshim.dylib" /Applications/TweetDeck.app/Contents/MacOS/TweetDeck -psn_0_12827707 2>&1 | egrep -i "oauth_token|oauth_consumer|oauth_timestamp|oauth_nonce" --color=auto

arms race

There isn’t much the app can do about this sort of hack. I mean, sure, the app could zero memory the memory before freeing it. But, then I’ll just use GDB or a hexeditor or whatever to disable the call to memcpy. So on and so forth.

If you ship a binary to a person’s computer and that binary has a secret embedded in it, that secret will eventually be discovered.

other apps

What other interesting strings fall out of OSX apps you use everyday?

If you enjoyed this article, subscribe (via RSS or e-mail) and follow me on twitter.

Written by Joe Damato

August 20th, 2012 at 9:14 am