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!
