The original White Hat

Thu Nov 13 21:13:52 UTC 2008

Hunting for simple shellcode

--

Didier Stevens posted a reasonably simple challenge on his blog recently; find the message hidden in a simple all-black BMP file.

A simple disassembly using ndisasm (from the Ubuntu package nasm) finds a series of single-byte moves that often indicate text strings.

    $ ndisadm -u picture-puzzle.bmp
    ...
    000001D4  C645E455          mov byte [ebp-0x1c],0x55
    000001D8  C645E572          mov byte [ebp-0x1b],0x72
    000001DC  C645E679          mov byte [ebp-0x1a],0x79
    000001E0  C645E779          mov byte [ebp-0x19],0x79
    000001E4  C645E862          mov byte [ebp-0x18],0x62
    000001E8  C645E920          mov byte [ebp-0x17],0x20
    ...

In order to look at these bytes, we use a few of the standard unix/posix text processing commands. grep will select the target lines, cut will isolate the part of the line we want, sed will re-write the output into the format we want for printf, tr will be used to change the output from line-based to a single line. Yes, we could do all this in sed or perl, but it would be less readable; yes, it would be quicker, but this is hardly a big job.

So, grep and cut to get just the bytes …

    $ ndisasm -u picture-puzzle.bmp | grep 'mov byte' | cut -d, -f2
    ...
    0x55
    0x72
    0x79
    0x79
    0x62
    0x20
    ...

Transform those bytes from the ‘0x..’ format to ‘\x..’ that printf wants …

    $ ndisasm -u picture-puzzle.bmp | grep 'mov byte' | cut -d, -f2 | sed -e 's/^0x/\\x/'
    ...
    \x55
    \x72
    \x79
    \x79
    \x62
    \x20
    ...

Some of the bytes are nulls, generally indicating end-of-string. Add a second clause to the sed command, to replace them with LFs, making the output nicer.

    $ ndisasm -u picture-puzzle.bmp | grep 'mov byte' | cut -d, -f2 | sed -e 's/^0x/\\x/; s/x0$/x0a/'
    ...
    \x55
    \x72
    \x79
    \x79
    \x62
    \x20
    ...

Now use tr to squeeze everything into one line, and pass the whole lot to printf. Now, printf doesn't like to be used as a filter, so I'll use the shell $(…) construct to pop the ndisadm output into printf.

    $ printf $(ndisasm -u picture-puzzle.bmp | grep 'mov byte' | cut -d, -f2 | sed -e 's/^0x/\\x/; s/x0$/x0a/' | tr -d '\n')
    Uryyb sebz OZC furyypbqr!
    user32
    MessageBoxA

OK, the first line is the only interesting one. The letter distribution makes it look like a simple alphabet substitution, and the most common is rot13 … but let's go one better, the caesar program (in Ubuntu's bsdgames) will do an English frequency analysis for us …

    $ printf $(ndisasm -u picture-puzzle.bmp | grep 'mov byte' | cut -d, -f2 | sed -e 's/^0x/\\x/; s/x0$/x0a/' | tr -d '\n') | caesar
    Hello from BMP shellcode!
    hfre32
    ZrffntrObkN

Here's thet command-line again, broken onto multiple lines to make it easier to read …

    $ printf $( ndisasm -u picture-puzzle.bmp | \
                grep 'mov byte' | \
                cut -d, -f2 | \
                sed -e 's/^0x/\\x/; s/x0$/x0a/' | \
                tr -d '\n') | caesar

    Hello from BMP shellcode!
    hfre32
    ZrffntrObkN

Now, real shellcode isn't going to be as easy to spot visually like this, but sometimes the obvious is a good place to look!

blog comments powered by Disqus --