After downloading the-binary.tar.gz I compared the MD5sum to ensure it was
not tampered with.
After extracting the-binary.tar.gz and execute the file command
and saw it was an ELF 32-bit executable.
I then ran strings the-binary > strings.txt. Reviewed the file and
noted many interesting sections. The following stood out the most and
red flags:
[mingetty]
/tmp/.hj237349
/bin/csh -f -c "%s" 1> %s 2>&1
PATH
HISTFILE
linux
TERM
/bin/sh
There where also several sections that apparently used libraries (statically
linked) for YP/RPC and DNS services.
After seeing the different applications strings (YP, RPC, etc) I decided to
make sure there wasn't more than one executable. To do this I check to
multiple ELF headers via xxd the-binary | grep ELF. The was only
one.
Then I disassembled the-binary to a text file with: objdump -d the-binary > objdump.txt. Using vi I began to comment on some sections.
At this time I also created a root jail environment on a system with no
network connectivity. And I ran the-binary with strace:
strace -ff -x -o strace.log ./the-binary Here you could see it
chdir into "/" and fork off a few processes. The first child process
just sets up the final daemon process. The final daemon process listens
to a raw socket at protocol 11. This process shows up as [mingetty].
This can be viewed with both ps and netstat.
Then I dump the .rodata section from the binary for editing into the objdump
disassembly. objdump -j .rodata -s the-binary > objdump.rodata.
Using this information I looked up some key strings in the objdump.txt and
inserted some comments. I also edited the file and commented the functions
that had interrupt calls.
I looked up the interrupt calls and cross-referenced them with
/usr/src/linux/include/asm/unistd.h. I had to look at the DX registers
to differentiate the socketcall functions and cross-referenced those
with /usr/include/linux/net.h.
After doing this for a few hours I decided it would be best to write a
program that could analyze disassembled output and do what I was doing but
make it automatic. So I got distracted and worked on a program to do
just that. After several hours I had a working version of the
examiner which will be included for public use and submitted
with this challenge.
The examiner is a utility that does the disassembly steps already described.
It can't do a good of a job as going over it by hand but will attempt to
map out all functions and references to .rodata. This can be a good starting
block to start editing the disassembled binary. It can also give you a
quick overview of what kind of system calls are in the binary and where
.rodata calls are located. It provides commented disassembly text.
Once I felt I had a good understanding of what the binary basically does. I
put it in a test environment and executed it with gdb. Gdb ran
until it hit the recv() function call at which pointed it just waited for a
packet.
I searched for programs that open up raw sockets and speak on covert
channels. After finding around 5 I looked at the most promising. I downloaded
loki's program from phrack and modified it to speak at protocol 11 (0xb).
I then sent some packets to the local loopback and attempted to debug how
it received the packet. Unfortunately the debugger would barf after receiving
the packet. Through strace the program would run fine but I was forced
to really understand what all was going on in the assembly text.
After playing with loki and trying to guess what all needs to be set
based on the objdump output I was unable to make a client that could
communicate with the-binary. So most of the analysis in this document
is based on the assembly source. For areas read purely in source hex
address references will be given.
The-binary can be made to fork of a listening raw IP socket. This socket
is a root shell backdoor. Packets sent to this socket will have the first
19 bytes checked for a password. If the password is "TfOjG" an interactive
shell will open and the HISTFILE will be unset. If you give it the wrong
password it will send back "fffb01". Ref: 0x80488c9 to 0x8048aa9.
There is a function that forks off a shell and run /bin/csh -f -c %s
It seems odd to me to call /bin/sh /bin/csh command but that appears
to be what it's doing. The function itself is at 0x80447e8. It seems to
be able to run a command passed to this function. It also
appears that there is a tmp file that can be executed via this same
method. The temp file is always /tmp/.hj237349. This use of
the temp file can be found from 0x80485f3 to 0x8048611.
Around section 0x804edbf You can find DNS related strings such as
";; response truncated". Searching on google you can find DNS related
postings regarding commands like dig and host. A little
more digging turned up the libresolv/res_send.c. This code seems
to match the the assembly contents and I would be willing to conclude
that libresolv or something very close derivative was used for the
static compile.
I did the same procedure with a few other strings as well. And it appears
that NIS+ libnsl Was also used. Two strings that seemed to stand
out were "*nazgul*" and "Message Catalog System". After searching on them
a bit it appeared that these messages were fairly normal of statically
compiled binaries. After finding a very similar message for
nls/msgcat.c. It may simply be a developer named Ken Hinckley who
goes by the name nazgul (Denoted by his email). This file also has the
strange "Message Catalog System" constant in it. I then concluded that
*nazgul* was not a string from the intruders code but a bi-product of the
static compile.
I did not see any shell code in the-binary. So it doesn't appear that
these libraries were included to exploit other computers via remote
buffer overflows. It appears that protocol 255 may be used for DNS
type operations.
On 5/28/02 I noticed the snort logs were posted that had some sample
encrypted packets. This rekindled my interest and help greatly in better
understanding the assembly code. I used Ethereal to look at the packet and
was able to notice a difference of 0x17 in ~90% of the packet. That is,
if one byte was 0x45 then the next byte was most likely 0x5c. The first few
bytes didn't follow this pattern but I assumed the rest was just padding.
Assuming the padding was a NULL it was easy to come up with a stair-stepping
algorithm to decode most of the packet. I then looked back through the
source code and found some sections that would be relevant to this decryption.
There was a few sections that followed that I must admit that I didn't
really follow.
I then wrote decoder.pl mainly just for me to test my theory.
It's not user friendly and would be a bad tool for someone else to use but
it served it's purpose. It's just a small simply perl script that displays
a bunch of information about each byte. There appears to be a second stage
to decoding the packet but that is where I got a bit lost.
Based on the snort logs and looking at the code it appears that there
is an identifier in the begging of the data section. It is a 0x02 for
client->server and a 0x03 for server->outbound. This is useful for making
a little better signatures for an IDS.