I turn my attention to the sample that came into the new honeypot, mentioned in the prior post. I uploaded the sample and it pretty much blew up VirusTotal:
Nice. Also, I happened to notice that the file has a PE header, which is a welcome change from all the spammy documents I’ve been looking at so far. I didn’t delve too deep into what else the site found because I want to try to see how much I can find on my own – the point isn’t to just upload stuff and have a sandbox do the work for me, I want to see what I can get out of it myself and then “check my work”, so to speak, in the sandbox.
Static Analysis
I started with some basic static analysis stuff like strings.exe. What I get is some pretty standard looking stuff – in the beginning (not shown) you see the header and see mention of the .text, .data and .rdata sections. Further down you see what we’re meant to believe are imported functions. GetTickCount could be used as an anti-debugging technique, but it could also have a more conventional use. GetVersion could be used to survey the host in order to see what is running and possibly also to inventory the system. VirtualAlloc can be interesting when associated with other imports that might have to do with process injection, but I’m not seeing those other imports here. WriteFile is always a good one, since this means that something is probably being written (either a file is dropping for some purpose on the host, or perhaps data is written to a file before exfiltration).
After this list of function names, there were pages and pages of random strings. Nothing in there resembled anything like a host name, IP address, messages, file names, mutex names, nothing at all. I’m guessing this file isn’t packed due to the plaintext import names and regular section names, but not sure yet and need to look deeper. My guess right now is that whatever strings, arguments, etc. the sample uses are obfuscated somehow.
Opening this sample in PEview reveals some more info. This particular sample is relatively new, compiled on June 4th of this year. Quickly checking a few anti-debugging things, I see there is no TLS table and the number of data directories looks fine (0x10). The virtual and raw sizes of each section are very close in size to one another, again suggesting that the file isn’t packed and reinforcing the assumption that there’s obfuscation of some sort going on here.
The next tool up is Krypto Analyzer (KANAL) for PEiD. KANAL is a tool that looks through files for indications that there might be some sort of encryption going on. These indications include constants associated with various encryption schemes, function imports related to cryptography, and the like. The main issue with using KANAL is that if the sample uses something non-standard (such as a custom base64 index), KANAL will not pick that up. There are also cryptography schemes that do not use “magic constants”, and those won’t be picked up by KANAL either. In this case, KANAL did find something:
Rijndael was the original name for the Advanced Encryption Standard (AES), and superseded DES. The block size for AES is 128 bits, while key lengths can be 128, 192 and 256 bits. It’s a symmetric-key system, so the same key is used for encryption and decryption. The output from KANAL refers to S-boxes (the [S] and [S-inv] in the screen capture above). Substitution boxes (S-boxes) are matrices used in AES. The first reference above (RIJNDAEL [S]) refers to the encryption side, while the second (RIJNDAEL [S-inv]) refers to the inverse S-box that would be used for decryption. This could mean that this sample both encrypts outgoing traffic as well as receives encrypted incoming traffic from C2. Another nice thing about the KANAL output is that it also shows where the references to these constants are, which will help later with disassembly/debugging.
Dynamic Analysis
After this I jumped into disassembly and debugging to try to get a general feel for this sample, and then took a step back and went through a more structured dynamic analysis with the usual tools (procmon, procexp, wireshark, and so on). When I first ran this sample, I observed the original instance of the sample (PID 3688) spawns a child process of itself (PID 760) shortly after execution, and then shortly after that the original instance (3688) terminates.
The first instance imports kernel32.dll and user32.dll, but the second instance imports these and several others including ws2_32.dll and advapi32.dll. The first time I ran this sample, I did it without an Internet connection and I did not notice any files dropping, however the second time I ran this sample I first obtained an Internet connection and this time I observed a call to WriteFile. This was actually a pretty obvious file that dropped – in the directory where the executable is located, a file called wcsqmpbh.bat dropped in the open, containing the following instructions:
@echo off
:deleteagain
del /A:H /F [samplename].exe
del /F [samplename].exe
if exist [samplename].exe goto deleteagain
del wcsqmpbh.bat
Note that [samplename] refers to whatever file name you’ve given the sample. Strangely, this batch file was executed according to procmon, though the original executable and the batch file remain. Perhaps this is a file that the bot controller could remotely execute should the need arise to cover their tracks, but it’s unclear why these files didn’t actually get deleted following execution. The flags indicate that the batch file was trying to force deletion of both hidden and unhidden copies of the malware, regardless if the file was read-only at the time.
The obfuscation at work in this sample made disassembly and debugging difficult, however I was able to look in the strings in the images of the running samples in Process Explorer and saw many interesting strings. I’ll look at some of these in more detail.
One of the first things that stood out to me was a series of what appear to be IRC commands and a channel name (#balengor). These commands match what I observed in the packets captured in Wireshark and line up with how one would connect to and register on an IRC server, followed by strings that are used to build the commands to join the probable C2 channel, set the appropriate modes for the connected user, and so forth. You also see a reference to Eggdrop, an IRC bot and a version number for this software.
UNK
NICK %s
USER %s %s %s :%s
PASS %s
NOTICE %s :
PRIVMSG %s :
message
NOTICE %s :
PRIVMSG %s :
NOTICE
link!link@link PRIVMSG %s :%s
NICK
USERHOST %s
JOIN %s %s
MODE %s +xi
MODE %s +smntu
JOIN
ERROR
VERSION %s
eggdrop v1.6.16
VERSION link v%d.%03d%s (Win32)
PING
PING
VERSION
VERSION
SEND
DCC
PRIVMSG
MODE
PONG
PONG %s
PING
link!link@link
ndEvery1
#balengor
Here are a few examples of where you see some of these strings in the traffic:
Another string that stands out is a standard base64 index:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
There’s an extensive section which contains strings mentioning bots as well as related to the various activities that the bot can carry out. I’ve made some of the more interesting ones bold below, but there are strings related to scanning for remote machines, exploitation of those machines, exploitation statistics, remote shell access, file transfer, references to protocols (tftp, ftp, http), parts of a dynamically created user agent, and status messages related to restarting the malware or terminating it.
Scanned
:%s in
sec.
open IP(s) found
:%s is open
– Scanning
:%s for
second(s)
Scanning
:%s for
second(s)
Scanning
:%s for
second(s), t:%u s:%u
– Attempted
exploitation(s) on
IP(s).
Attempting to exploit
with
– Attempting to exploit IP’s in list.
Attempting to exploit IP’s in list.
Exploit statistics –
Listing exploit statistics
bot(s) found with string
No bots found with string
found string
in %s (
– Listing bots with string
%s bots with string
Killing
Listing
Cmd.exe process has terminated.
Could not read data from process.
cmd.exe
Error while executing command.
Remote cmd thread
open
Received
from
sec with
KB/sec
– Receiving
from
Receiving
from
Content-Length: %u
Content-Length:
GET /%s HTTP/1.0
Host: %s
– Unsupported protocol specified.
– Error while downloading
– Unable to start
– Successfully downloaded
with
KB/sec%s.
, executing
, updating
– No file to download specified.
tftp://
anonymous
ftp://
http://
– Cannot read source file
– Cannot write to destination file
file://
– Downloading
Downloading
.exe
QUIT :restarting
QUIT :exitting [sic]
Near these commands are strings that relate to debugging issues with the malware, including one string that is constructed during crashes that contains information about the CPU state at the time of the crash (in this case you see that it saves the state of the registers), along with some error messages.
debug
– Module “%s” reported a crash in “%s”: N=%u EAX=%08X EBX=%08X ECX=%08X EDX=%08X ESI=%08X EDI=%08X EBP=%08X ESP=%08X EIP=%08X EFLAGS=%08X. Code: %08X (%s). %s…
Continuing
Restarting
EXCEPTION_FLT
EXCEPTION_INT_DIVIDE_BY_ZERO
EXCEPTION_STACK_OVERFLOW
EXCEPTION_NONCONTINUABLE_EXCEPTION
EXCEPTION_BREAKPOINT
EXCEPTION_ACCESS_VIOLATION
EXCEPTION_ILLEGAL_INSTRUCTION
EXCEPTION_OTHER
Many strings relate to system information, probably so that the controllers can inventory the systems in the botnet. The string USA is found in the beginning – perhaps this was generated dynamically since this sample was run on a machine located there. Other strings relate to CPU and memory information, uptime, networking information, firewall status, and storage information. One string seems to mention encryption along with the number 128 – perhaps this is a clue that the key is 128-bit, but I would like to find something in the disassembly that would back this up. Interestingly, you can also see that the bot seems to rate some of these aspects as Good, Avarage [sic] and Bad.
USA
System information – OS: Windows
). CPU: %s
MHz. Ram:
MB free. IPv6:
. Uptime:
day%s
hour%s
minute%s. Computername:
. User:
ProcessorNameString
HARDWARE\DESCRIPTION\System\CentralProcessor\0
Yes
no SP
Sysinfo thread
Network information – Host:
. Name:
. Type:
. IPv6:
. Firewalled:
. Latency:
, %u. IRC Uptime:
day%s
hour%s
minute%s.
Good
Avarage [sic]
Bad
LAN
Modem
Unknown
Netinfo thread
%sTotal drives:
, Total space:
MB free.
MB free
unknown
ramdisk
cd-rom
remote
fixed
removable
Drive information –
Driveinfo thread
thread
btg
debug
– btg tried executing an unreadable address. (%08X)
– No threads running.
– Listing
threads:
QUIT :changing server
link v
%s [Win32]
Uptime – System:
day%s
hour%s
minute%s. IRC:
day%s
hour%s
minute%s
Debug mode is %s.
off
Exe download server:
none
Exe download server:
f128enc+fab decrypted:
f128enc+fab encrypted: =
The network activity was pretty interesting to observe. As noted above, the malware connects via IRC to her.d0kbilo.com (37.59.118.41) on port 4466. There was actually quite a bit of plaintext in the traffic:
The nick that was assigned to my various instances all seemed to follow the same format of “d[a-zA-Z{7}]b”, trying to put it into some sort of pseudo-regular expression. I was able to confirm this by connecting to the server and trying to interact with the bot account from a remote location. If one tries to connect to the IRC server from the same IP, you get the following result:
Upon connecting to the server (independently, not as a malware instance), an operator account sets your user mode to +iwG (which makes the nick invisible, enables wallops message receipt, G which filters out certain words). Joining the malware C2 channel shows that the mode for the channel is set to +smntu, which makes it a secret channel; moderated; external messages disallowed; and only operators are allowed to change the topic (the +u is unknown). Malware nicks receive user mode +xi which makes them hidden and invisible (meaning the username is hidden and makes this nick hidden from /WHO and /NAMES commands when executed from outside the channel).
Trying to obtain a list of channels from my regular IRC client was unsuccessful (which was unsurprising, since the channels are set to be secret) but strangely an online IRC client did show some channels:
If you know a specific nick, you can still contact that person even if they are set to invisible. You can see in the following packets when I was sending traffic to the malware’s IRC instance, which was also a way that I was able to confirm that the nicks are plaintext and not obfuscated (though, the nicks themselves likely follow some sort of coding standard to help identify the victims):
I sent a /QUERY to the malware nick (my nick was gurdaptl and I was connecting from Kiwi IRC):
I created a channel called #flot and invited the malware nick there (no luck):
Apart from this, the only other activity I observed was that the malware would have a PING/PONG exchange with a user “e.TK” about every 90 seconds or so. I recorded about 40 minutes of such traffic but did not observe anything else.
Getting back to some of the other malware behavior, one thing noticeably absent was any indication of persistence – while running as a regular user (i.e., not with administrator privileges). I tried various tools (Autoruns, RegShot, GMER, etc.) to check for changes to the system and for some sort of persistence mechanism, but found nothing. Following a reboot, the malware did not appear to be running. Since I wondered if there was something preventing me from seeing the sample (some sort of hooking, etc.) I captured packets for about five minutes but observed no traffic to the malicious server or really anything out of the ordinary. I can’t imagine that you’d have a useful botnet that didn’t achieve persistence, but perhaps this is again a quirk of either my VM environment (user permissions, etc.) or merely the fact that I am running in a VM.
I re-ran the sample as administrator, and got some very different results this time in terms of how it attempts to both hide itself and achieve persistence. As a side note, I’m going to take an analytical leap of faith and say that this sample doesn’t escalate privileges due to the much different behavior observed when run as an administrator vs. a regular user.
First, the file does succeed in deleting itself after execution, along with the batch file. What was really interesting was the the malware then proceeds to create and replace a number of new processes every 60 seconds or so. The number of processes varied between runs, but ranged from as few as 4 to as many as 16. This long series looked like this (process name and PID):
1. [sample].exe, 3052
2. [sample].exe, 2848
3. winamp.exe, 212
4. winamp.exe, 2616
5. algs.exe, 864
6. algs.exe, 1004
7. logon.exe, 2220
8. logon.exe, 872
9. winlogon.exe, 2980
10. winlogon.exe, 420
11. spoolsvc.exe, 2572
12. spoolsvc.exe, 2536
13. spoolsv.exe, 2556
14. spoolsv.exe, 2476
15. lssas.exe, 2168
16. lssas.exe, 2264
I noticed that the malware always seemed to follow this pattern of creating two processes of the same name during this procedure. The final process in the list is then added to the registry to be run at startup, for example:
No matter the final process that is set to run at startup, it always gets stored in this same place in the registry, at least in my test environment.
Upon restart, I observed the final two steps in the procedure above repeat (i.e., 15 and 16). That was all – there wasn’t another series of processes created as in the original run. Looking at the image confirmed that this was definitely the malware and not a legitimate process after reboot:
Network Activity
The only anomalous activity detected in Wireshark was traffic between 37.59.118.41 (her.d0kbilo.com) on port 4466. Examination of the packets revealed some plain text which appeared to be IRC-related. In the strings recovered from the sample we see some of the same commands (e.g., USERHOST) as in the packets. The values passed to these commands, however, appears to be encrypted.
When I visited the C2 IRC server, it proclaimed that this was a modified version of the UnrealIRCd IRC server. What’s curious to me is that even though this software was modded by the malware author(s), the IRC commands seem to need to be passed in plain text.
Sitting in the C2 channel didn’t reveal anything. The mode set for you as an unregistered user prevents you from saying anything in the channel and the usernames for you and the other accounts in there are set to invisible. I found a document online apparently written by someone from uNkn0wn Crew and it refers to a couple of other channels, but nothing was going on in those either (though I did have voice enabled there, so I could talk in the channel but no one seemed to be listening or responding).
Disassembly/Debugging
One thing I noticed pretty early in this is that this sample does at least two things that makes disassembly and debugging more difficult. One is that many function calls are indirect, so you sort of have to switch back and forth between the disassembler and the debugger to see what is really being called when you see something like call dword ptr [eax+0Ch]. Here’s a screenshot showing some of this along with where I’ve inserted some comments so I can better keep track of what’s actually called:
The other thing is that this sample creates and replaces multiple new processes which makes debugging to be a real pain. I’m going to call out a few specific areas where I found something that looked interesting in this sample.
Starting at the function at 40204F, there’s a series of calls to GetModuleHandleA and GetProcAddress to get handles and addresses of various functions that will be used later for the process replacement:
Looking at it in both IDA Pro and Olly, this series of functions gets handles and addresses of:
The sub at 40224C finds the code to be written in the process replacement:
Then there’s a block to create the suspended process for future replacement:
Looking at this, I didn’t see a call to CreateProcessA, but I saw one of the parameters pushed on to the stack was 0x4. When you want to create a process in a suspended state, you pass 0x4 as the CreationFlags parameter. To confirm this, I checked it out in a debugger and we can see this at work for the first process that the malware spawns (in this case, it creates a suspended process of itself) and you can see that CreationFlags is set to CREATE_SUSPENDED in the stack in the bottom right:
Further along, we see a block of code at 402394 that loops and writes the malware to memory, and then once fully written, the block beginning at 4023D7 resumes the thread to complete the replacement:
After that overall function returns, the malware calls an exit function at 403608:
This sample appears to use AES. As previously stated, KANAL found the constants, which you can see here in this shot from IDA Pro:
I have a very high level understanding of AES, so I sort of know what to look for, but I couldn’t get through too much of the code that appears to deal with this encryption. First, here are a few things about AES:
– Block sizes are always 128-bits
– Key sizes are always either 128-, 192-, or 256-bits
– Using AES comprises the following steps. Note that the number of rounds depends on the size of the key – 10 rounds for a 128-bit key, 12 rounds for a 192-bit key, and 14 rounds for a 256-bit key.
- Key Expansion (round keys derived from cipher key)
- Initial Round
- Add Round Key (each state byte combined with a block of the round key)
- Rounds
- Sub Bytes (where the S-box comes into play)
- Shift Rows (transposition)
- Mix Columns (combining of 4 bytes in each column)
- Add Round Key (see above)
- Final Round
- Sub Bytes (S-box, again)
- Shift Rows (see above)
- Add Round Key (see above)
For more detail, please see the link in the references.
There is a loop beginning at 40121D that could be the Mix Columns loop as it iterates in 4-byte blocks:
Sub 401079 is where we first see the S-box being used:
One interesting thing can be seen later, in a sub at 4016A5. Here we see a function that works with the S-Inv box (MaybeSINVSubBytes) and there’s a local variable that is set to 0xE (14) that is used to loop. One thing we know from earlier is that the number of rounds for a 256-bit key should be 14, so perhaps this is a clue that we’re looking at 256-bit AES:
This represents some things I thought were interesting about this initial run of the malware. In this first run, what appears to happen is that the malware starts and finds several functions that are necessary to do process replacement. Following this, the sample decrypts data beginning at 4061C4 and then replaces the suspended process with this. Here is this section before decryption:
Here is a view of this area in Olly after decryption (you can see the MZ (4D5A) “magic number”):
I took all of this and dumped it from Olly into its own file, and then took a look in PEview:
Nice.
I’m not going to dive into this payload right now (will be a future analysis) however we can already see imports (DLLs like WS2_32, shell32, ADVAPI32) and plaintext strings:
I would have liked to have fully taken the crypto functions apart and recovered the key and the AES parameters in use, but I think that it’s good enough (at least for now) to have recovered the encrypted payload for further analysis.
Attribution
There were some interesting things found pertaining to attribution with this sample. The malware connects to her.d0kbilo.com, which sits behind a domain privacy provider, so nothing much to see in the whois lookup. There were multiple indications of IRC traffic (the Wireshark activity, the #Balengor string in the sample, etc.) so I decided to try to connect to her.d0kbilo.com. The regular IRC port failed but connecting on port 4466 (like the sample) succeeded. Interestingly, I was able to connect as a regular, unregistered user although my activities on the server were constrained. One of the initial messages greeting me on the server was that the box belonged to “uNKn0wn Crew” who apparently could be found at www.uNkn0wn.eu. It also mentioned an email address – [email protected].
One of the few commands that I was allowed to execute on this server showed me the local time on the server, which placed it in the UTC+2 timezone. It’s certainly possible that this server had a random time zone set, but if this timezone is actually indicative of geography, this would actually put this server potentially in many places, from West Africa, to continental Europe, to Southwest Asia. IP address location services place the server in France or Spain.
I’ve found a few mirrors of defaced websites from uNKn0wn Crew and the names I saw associated with those were bebo and warbody. This was from 2004, however. In the #Balengor channel, which I presume is used for C2, there is a topic set by “k” which appears to be a base64 encoded string. Modes are set by an “e.TK” on the server. At this point, the possible identities I’ve seen from this group are:
– iD
– e.TK
– k
– bebo
– warbody
I can’t say that I’ve heard of this group or these people, though I would point out that there used to be a flash cartoon on newgrounds.com about a cat named Beebo, so maybe this person was a fan of that series.
Summary
It’s been an interesting and somewhat frustrating exercise to go through this sample due to all of the anti-analysis features in place here. Recovery of the payload is great, and my next step here is to analyze this sample. Even without the analysis of the payload, we do know that this sample adds the host machine to a botnet and allows robust C2 functions to be run on the victim machine. We also discovered something about the group responsible for it.
There wasn’t a name associated with this sample when submitted to the online sandboxes. Referring to it by its MD5 hash is cumbersome, so I’m going to assign this a name. Since this is related to botnets and this is the first part of a multi-part sample, I’m going with single syllable B reporting names. I’m going to call this one BEAR.
References:
csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf
https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
Findings and observations:
This sample is essentially a launcher for an encrypted payload. This overall malware package establishes C2 via IRC and allows for a robust level of control on infected machines. This malware also indicates that it can be used for typical botnet operations (e.g., scanning for new victims, exploiting targets, etc.)
Recommendations:
When this sample was run as a regular (unprivileged) user, it appeared unable to fully execute however it still did appear to establish C2. Keeping regular users in appropriate (non-admin) levels of access appears to impede this sample’s operations. Specifically, running as a regular user should prevent the sample from achieving persistence which would result in the sample being removed from the host upon reboot.
C2, for the time being, is located at her.d0kbilo.com (currently resolving to 37.59.118.41) on port 4466. Restricting access to this domain, IP address and port would impede or eliminate the C2 function.
Conclusion:
A skillfully executed bot client that uses multiple anti-analysis techniques to hamper the analyst.
Report: MalEXE001
Hashes:
MD5fcc038bc5b7297dffa9a78424c71674f
SHA1ba71062e5266b3e70e3e15b2d963ec7d5e375933
SHA256f6fb4bde73ca1fff1fc90cff03f5c8255467b8b3d7f54330f39ecc3fa48f0e51
ssdeep:1536:W/sLo8xocXN5U3FjAXScUC30SWEk4JgTqkKk6YqwFYtitK2TZ:WEL9okN5U3FjtQ0SWyJgT5D6wK2