Written by Mike Sweeney, Senior Incident Response/Forensics Analyst at Critical Defence. Mike has achieved a GREM certification from SANS GIAC twice, and graduated from the Rochester Institute of Technology in 2013.
Part 1 can be found here.
Part 2 can be found here.
On Monday, we were busy unpacking the malware sample and analyzing API calls. We ended up having a problem, as our final unpacked sample has two different exports to start execution at. The default just does nothing, and we want to start executing at Work.
Restore your VM from Monday, and get ready to finish this sample off!
Getting to where we want to be
In x32dbg, select the “Symbols” tab, and on the lefthand pane, click the name of the executable that we’re working with. In my case, I named it ‘unpack.exe’. Once you click unpack.exe in the lefthand pane, the righthand pane fills with both the imports and exports, and where they live. You should be looking at this:
In the righthand pane, double-click on “Work”. Now, this is more like it!
But all we’re doing right now is looking at this memory address, we won’t start executing here when we push “Run”. We need to execute from this point forward. Right click on the “EIP” register in the righthand pane, and select “Modify Value”. If you’re familiar with what EIP does, you might have already figured out what we’re doing.
Input the value of our currently selected address in the “Expression” field. In my case, it’s 75183510. Click OK, and your EIP register should now look like this:
X32dbg resolves it to <unpack.Work>. Now we’re in the right place. What did we just do?
EIP is a register which holds the address of the memory that the processor is executing. It can help to remember this as Instruction Pointer. A good thing to remember – when working with 64 bit binaries and processors, this register is actually called “RIP”.
Snapshot your current VM – this will be our starting point going forward. Let’s continue.
Now that we’ve snapshotted our VM, we can come back to this point whenever we like. Let’s start out by tracking down how the malware uses import WriteFile.
In the Command window of x32dbg, execute SetBPX WriteFile. Then run the malware. Now let’s take a look at the stack, in the lower righthand corner of the window.
Interesting – we’re writing an EXE file to AppData\local? That’s really suspicious activity. This is our first IOC – the malware writes a file to this directory. It turns out that the name of this file changes, but we can certainly work with this information.
Restore your VM to its previous snapshot. Let’s go back to our listing of Imports to see what else we can follow up on. Let’s take a look at some of the registry-related imports.
The difference between some of these is a little unclear at first glance.
In IDA Pro, double click on RegOpenKeyA. Then push the ‘x’ key on your keyboard – this will show us places where code calls RegOpenKeyA. Select the call in sub_10002900.
Double click on this specific call. Here’s where we end up:
Interestingly, it looks like we’re using the string we found from earlier, “Software\\Microsoft\\Windows\\CurrentVersion\\Run” as a path to a registry key. If you dig into the history of malware abusing this key, then you’ll know that if you create a value in this key with a path to a file, Windows will attempt to open that file when the OS starts or the user logs in. This is indicator #2.
Specifically, the WS2_32 imports are interesting:
|WSAStartup||“…Initiates use of the Winsock DLL by a process”|
|gethostbyname||“…retrieves host information corresponding to a host name from a host database”|
|gethostname||“…retrieves the standard host name for the local computer”|
|inet_addr||“…convert[s] the string pointed to by cp, in the standard IPv4 dotted decimal notation, to an integer value suitable for use as an Internet address.”|
|inet_ntoa||“…convert[s] the Internet host address specified by in to a string in the Internet standard dot notation.”|
As are the WININET imports:
|InternetCloseHandle||“Closes a single internet handle.”|
|InternetOpenA||“Initializes an application’s use of the WinINet functions.”|
|InternetOpenUrlA||“Opens a resource specified by a complete FTP or HTTP URL.”|
|InternetReadFile||“Reads data from a handle opened by the InternetOpenUrl, FtpOpenFile, or HttpOpenRequest function.”|
The lifecycle for the WININET imports, as the malware uses it, seems pretty simple:
- Initialize the library by calling InternetOpenA
- Use InternetOpenUrlA, passing a URL as an argument, to access a web page. We get back, as a result, a handle.
- We then pass the handle to InternetReadFile to read the actual data
- We then close the handle by calling InternetCloseHandle
Given all of this, we could always set breakpoints on each of these, run the malware, and see what happens. But let’s do something a little smarter. Let’s analyze our imports, and figure out which one is most likely to help us.
Here’s our goal: We want to catch a bare IP address. Which import is most likely to help us with that?
It looks like inet_ntoa is probably our best option. It takes a host address in, and converts it to a string. We should be able to see that converted string and analyze it afterinet_ntoa has finished calling.
This process is going to be a lot like VirtualAlloc’s was, when we were originally unpacking the malware. Return to x32dbg’s window. If you’re not sitting with your EIP pointing to the “Work” export, restore your VM.
Run the command “SetBPX inet_ntoa” in x32dbg, then run the malware. Something strange will happen. The malware will just run and run. Just let it do it’s thing, you’ll probably wait a minute or two. This is normal – the malware is running the “Sleep” function in an attempt to throw you off track. But we’re smarter than that – and more patient!
When it’s done sleeping, you’ll see a notepad window open like the following. In the background, your import will have also been hit. You’ll see something like this:
This just gave us another indicator! The malware, when it gets to a certain point in execution, creates a file on disk and pastes this text on it. It also names the text file for what the current process, which in this case is x32dbg. Were the malware running naturally, this would probably be named something like “bwigleph.txt”.
This actually ties into the social engineering aspect of this malware infection process. This malware originally came in via email, and suggested that the individual download and run the attachment so they could find out the progress on a surprise package they have yet to get.
Anyway, back to our breakpoint.
Digging up IP addresses with inet_ntoa
Looking at our x32dbg window – we can see that we’re still inside of ws2_32.dll, so let’s run until user code.
Here, we can see that EAX is currently pointing to string “127.0.0.1” in memory. That’s weird though – that’s our loopback address. Let’s try again. Run the malware one more time – then “Run to User Code”.
Aha! Now check out what is living at the pointer held in EAX!
That certainly looks like an external IP address, and it certainly isn’t ours. In fact –
That’s a pretty well known bad IP address – specifically tied to Kuluoz by Sophos at the bottom result.
Push run again. The malware will continue running, let it run (this will take a little bit). However, take a look at our stack:
It’s a full URL! It looks like the malware is attempting to use port 8080 to send that encoded string to IP address 188.8.131.52.
If we restore our VM and do this process again, we’ll derive IP addresses 184.108.40.206 and 220.127.116.11 too.
So, after a week of work, what do we have to show for it? A listing of Indicators of Compromise that you can use to positively detect this malware on a network and on a computer! Here’s everything we found together:
|Writes to registry key “Software\\Microsoft\\
|Registry key (Persistence)||Static Analysis, following import RegOpenKeyA|
|Writes EXE file to C:\Users\[Username]\AppData\Roaming||File creation (Persistence)||Dynamic analysis, following import WriteFile|
|799325a4d5e0a1a620ac06cc7d12fce7||MD5 Hash of malware||MD5 hash calculation|
|Creation of a .txt file in the directory the malware was run from||File creation (social engineering)||Dynamic analysis|
|Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)||User agent string for network communications||Strings dump|
|18.104.22.168:8080||IP address and port for callback||Dynamic analysis, following import inet_ntoa|
|22.214.171.124:8080||IP address and port for callback||Dynamic analysis, following import inet_ntoa|
|126.96.36.199:8080||IP address and port for callback||Dynamic analysis, following import inet_ntoa|
From here, the process involves updating our network defense tools with this information, and sharing the details with friends. This is a really solid listing of indicators, and it gives us a lot to work with, detection wise.
Reversing malware, and binaries in general, are a lot like un-doing a blanket thread by thread. It takes a long time to get information that you’re after, and its often meticulous work. But, when you’ve gotten enough practice, you’ll be more nimble and faster at pulling the threads out.
There’s a lot of other fascinating detail to this specific sample, but we won’t be covering anything additional in this series.
Thanks for joining us for this post series! We hope that you got a little something out of it. If you did, feel free to let us know down below in the comments section, or via our Facebook, LinkedIn, or Twitter accounts!