Post 0x10: A Gh0st: Initialization Analysis

So I haven’t posted in a while, primarily due to the fact I have been quite busy recently – but I should be posting more frequently – that’s if I can analyse the malware correctly, without it sending off errors left, right and center. I was having a look at uploaded samples on VirusBay and noticed something quite peculiar. A user called Bondey had uploaded a sample and tagged it as Gh0stRATGh0stRat is a remote access tool that has been used for quite a long time, and has had multiple variants and changes – but the RAT seemed to have disappeared for a while, until now. Currently, the main group using Gh0st to gain remote access goes by the name of Iron Tiger, a Chinese APT group, that is currently targeting the government, technology, education, and telecommunications organizations in Asia and the US. I always enjoy having a look at malware used by APT groups, so I downloaded the sample in order to analyse it. (And yes, I have realized I screwed up the whole hexadecimal post count thing – and no I am not changing it!)

MD5: abdabfea475959703fb1957413b39cad

Before performing the usual analysis methods I do, I checked the hash on VirusTotal, and surprisingly, nothing came up. I uploaded the file, only to realize I was the first to upload it to VT. I just checked and the THOR APT Scanner has commented on the sample, clarifying that it is a variant of Gh0st, specifically s.exe used by Iron Tiger.

I am currently working on a project that downloads new samples and performs basic dynamic analysis on them, so that a beginner is able to pick which type of malware they want to analyse. Using the dynamic analysis section of it, I ran it against the RAT, to get a narrowed down list of strings:

As it is a work in progress, not everything was picked up, however it picked up several interesting strings. There seems to be references to a termsrvhack.dll stored in the dllcache and system32 folder – perhaps this is a stager, which drops a DLL to disk? You may also notice the entropy at the bottom – in the future this will be used to guess whether or not a sample is packed/obfuscated. In this case, it doesn’t seem to be, and you’ll see why when I run strings against this in order to get the full output:

You may recognize the strings as keys on a keyboard, which would be entirely correct. These strings hint to a keylogger functionality inside of the RAT – this raises the question that if an Advanced Persistent Threat Group were using this as their malware of choice, why did they not even try to pack or obfuscate it? Not only did strings return a list of keys, it also returned a URL embedded in the executable:

hxxp://user.qzone.qq.com/

This URL leads to what seems to be a Chinese social media site – but that doesn’t help me understand why it is in the EXE. Now that we had analysed the strings, it was time to put it in PEStudio to gather information about the file itself.

Upon checking the Resources section, I found several resources stored in the file, but one stuck out – a resource with a HTML signature. I dumped it to the disk to see what was inside of the resource, however there was nothing overly incriminating – what seems to be some possibly encrypted text, and a number – 360.

Next, I examined the imports to see if I could get a better idea about what this sample did – at the time of analyzing I was not entirely sure what the it could do. The sample imported functions using ordinals (numerical values corresponding to API names), as well as API names. Luckily, PEStudio is able to resolve most of the ordinal imports, revealing the proper name. Because of this, we can see that the sample is importing multiple functions from the Winsock Library, meaning there is a high chance that the program is making or receiving connections to or from somewhere.

Looking at the imported DLL’s, you can see a msvfw32.dll is imported – it seems this DLL provides video capabilities to executables, so perhaps this sample is able to screen record the victims computer?

So now we have finished the basic executable analysis, time to put it into IDA to disassemble the executable and get an idea of how it functions. I examined the list of strings in the binary once more, to see if I had missed anything in the original list, and discovered what looks to be a Visual Basic Script file name:

Jingtisanmenxiachuanxiao.vbs

There was no context to this filename, as far as I could tell, so perhaps it is a file that will be downloaded to the system? Moving on, I decided to view the TCP connection routine, so I searched for cross references for connect. Three different results came up, possibly hinting to three different connections to C2 servers.

I also noticed an interesting string stored in the offset aProgramFilesRu being pushed to the stack. This variable contained the file path \\ProgramFiles\\Ru%d.EXE”. This could be a drop location for the next stages of malware, or the directory where the malware copies itself to. I spent a little longer staring at the disassembled sample, but found nothing extremely useful and so I fired up x32dbg and opened the sample with it.

Using x32dbg I was able to locate the “main” function of the executable, where the interesting parts were occurring, rather than just initialization. Upon entering the main function, I immediately noticed how the program is importing libraries and API calls. Rather than running LoadLibrary(“Kernel32.dll”), an array of letters would be initialized and passed to the LoadLibrary call, resulting in the disassembly looking like this:

After passing over the calls to LoadLibrary, I found an interesting loop. This loop cleared an area in memory, and filled it with nonsensical strings, such as Ruiswe wgzawios. These strings look like they would be important at some point, so I made sure to take note of them. You can also see %SystemRoot% being stored as well.

This loop is run once more, however it clears a different region of memory and writes an IP Address to that memory region: 218.60.67.75. But the loop does not finish after writing the IP address – it continues and writes a URL to the region: http://xxx.ys168.com. I attempted to search for this online, however I got nothing back.

The program then uses sprintf in order to form the path where the executable will be copied to:

C:\\Windows\\Kbwgmwu.exe

This filename is hardcoded into the executable, so it will be the same name every time. In order to form the string that will be passed to sprintf, the same routine is followed that is used for importing DLL’s. %s\\%s is first written to memory as an array and then passed as a string, where %s is just a place holder for a string. The first %s contains C:\\Windows, and the second %s contains Kbwgmwu.exe. Once sprintf is called, the final path is formed, C:\\Windows\\Kbwgmwu.exe.

Continuing down the rabbit hole, another string is written to program memory as an array – this time a registry key:

SYSTEM\\CurrentControlSet\\Services\\%s

Once again, this is first written as an array, and then pushed to the stack for formatting. Before the registry is used, another string is formed: rundll32.exe. This string is passed to a function that imports and calls 3 functions:

GetToolhelp32Snapshot
Process32First
Process32Next

If you don’t know what these functions are used for, the first function gets a list of currently running processes, the second function gets a handle to the first process in the list, and the final function is used to iterate through the list. For each running process, the program calls strcmpi, to compare the process name to the passed argument (rundll32.exe). If rundll32.exe is found, the function will return and then execute taskkill /f /im rundll32.exe, using the imported API call, WinExec. If rundll32.exe is not running, the function will return and execution will continue, without taskkill being executed. I am still not entirely sure as to why the program checks for rundll, unless it is checking for previous versions of Gh0stRat, which were in a DLL format.

Once it has checked for RunDLL32.exe, the program imports Registry functions so that keys can be created and/or queried. Remember the Reg key I mentioned earlier? The %s is formatted to read Ruiswe wgzawios, so the full Reg key is:

SYSTEM\\CurrentControlSet\\Services\\Ruiswe wgzawios

The program checks to see if the key exists, and if it doesn’t, the handle to the key is closed. Once again, RegCloseKey is imported as an array and called, so you see this in the debugger:

Once the registry had been queried, the malware finds its own executable name using GetModuleFileName, and compares the result with the hardcoded file path C:\\Windows\\Kbwgmwu.exe. If the names do not match, the “installation” routine begins. Otherwise, it seems the program continues its regular execution.

If the file names are different, the malware creates a registry key using the registry key we found in the debugger:

SYSTEM\\CurrentControlSet\\Services\\Ruiswe wgzawios

Here is the first indication that the file must be run as admin, because it is attempting to create a HKLM registry value, which require admin privileges. Funnily enough, for an piece of “Advanced” malware, I saw no error handling when it failed to access the registry key, but I continued anyway just in case it altered the Current User registry. Whether or not the registry key had been added, the malware copies itself to the Windows directory, under the name Kbwgmwu.exe. To do this,  CopyFile is imported and executed. Once again, it will fail as the program is running as a regular user, and no attempts are made to handle the errors.

Once the file has been “copied”, the malware imports ShellExecute. The malware then gets a list of running processes (as with the RunDLL loop), and loops through it, comparing each value with Kbwgmwu.exe. If there are no matches, ShellExecute is called, executing the file Kbwgmwu.exe in the Windows directory. Once the file has been “executed”, the malware will loop back to the process search function, to check that Kbwgmwu.exe is actually running. As Kbwgmwu.exe does not exist (because the malware did not have elevated privileges), the ShellExecute failed. This loop ran 4 times and then exit, which seems to be the only form of error handling so far.

As the malware exited (and the original file was deleted), I ran another instance of it to see if any file names or registry values had changed. Only two values had changed, but they did not seem like they were important. It was time to debug the sample as admin and see what the malware could really do.

I skipped past the sections up until I reached the part where the registry key was added, and then I checked the registry. Sure enough there it was, the newly created key.

The registry name is also hardcoded into the binary, as it is important to the sample in order to check for previous instances. After the key is created, a value is added to it – Releice Name – and the data that is set seems to be randomized. In this case, the data reads Uuzvmm ceypla. Very cryptic.

I noticed that this registry creation function was running several times, so I put a breakpoint on each time it was called, and eventually located a new registry key being created: Uuzvmm ceypla. A value is set inside of this key, denoted as ConnectGroup. The data of this value was even more cryptic: Ä¬ÉÏ·Ö×é. Next, the program creates another value in the key, called MarkTime. The data that is written to this value is the current time – this could be an indicator for the malware to see how long it has been alive for?

Once MarkTime has been written to the registry, the main registry function exits, and CopyFile is called – this time successfully.

Now that the file has been copied successfully, the malware opens the Service Manager using OpenSCManager. This is also an indication that admin privileges are required – you must be admin to open the service manager. A service is then created using CreateService, under the name Uuzvmm ceypla – the same name as the registry key. This service is given a randomly generated description. This service is set to Auto Start, and is linked to the executable in the Windows Directory, Kbwgmwu. The malware then calls StartService in order to execute Kbwgmwu.exe.

The description of the service is then edited to show a longer random string – I am not entirely sure as to why it does this, but it does it anyhow. I checked the registry key after the description was changed, and it contained a lot more values:

During the debugging phase, I had no internet connection, so it was interesting to see the sample was listening over UDP – I do believe this could have been an error, as I had not seen any WSAStartup or listen calls being made.

Now I had seen it run as admin, it was time to find out what would happen if I ran the malware as if it had just been installed. I restarted the virtual machine to a clean state, and ran the original malware so it would root itself into the system. Once the Kbwgmwu.exe was executed, I attached a debugger to it and restarted the malware. This time, when the malware had checked the file names, it continued down the right path, rather than the left.

I came across the string Cao360 being pushed as an argument to CreateEvent, and I decided to quickly google it to see what came up. One of the first results to come up was a link to a Trend Micro threat encyclopedia page about TROJ_BEAUGRIT. I did not see any analysis of the trojan itself, but the information that I had seemed to correlate with what my analysis showed – I also do not have enough information about Gh0stRat to say that this is not Gh0stRat, and so I decided to ignore it for the moment.

Soon after noticing Cao360, I found 3 very useful strings – the IP address, the URL, and “123456789”, being moved into a memory address. The reason this is useful is because it indicates that the connections will be initiated very soon, so the malware will soon be connecting to the attackers C2 server.

Sure enough, after continuing through the program execution, WSAStartup was called. In order to create network connections using Winsock, WSAStartup must be called to initiate the library.

wsastartup.png

Further down, the malware calls connect in order to connect to the IP Address we saw in the sample. As I was offline when the malware attempted to connect back, it failed. I went back online, started up Wireshark, and ran the connect function. The malware established a connection to the C2 server via Port 8000. I searched for the URL online, and found several hits in Abuse IP websites, especially this one. It is located in China and based on the Abuse reports, seems to have been quite active recently, port scanning and brute forcing different services. Based on the fact that China has been banning VPN’s for civilian use, if the malicious actor is not linked to the government, there is a high chance that this IP address is the home address of the attackers computer – or a compromised host that is being used as a proxy, it all depends on the skill level.

connect_.png

Once a connection has been successfully made, the malware creates a new thread using beginthreadex, and execution resumes in that thread. That, is where all the interesting stuff happens (although I may be wrong, my analysis is not fully finished).

So now the first part of analysis is complete, as always, here is the summary of events. I will be finishing up the analysis and posting the final part – hopefully soon. If you have any questions, feel free to contact me!

Summary:

  • The program is executed
  • Form 3 randomized strings used for file names, registry values etc.
  • Writes a URL and IP address to program memory, for later use
  • Checks for RunDLL32.exe in list of running processes
    • If it is running, execute taskkill to stop it from running
    • Otherwise, continue
  • Form full registry key SYSTEM\\CurrentControlSet\\Services\\Ruiswe wgzawios
  • Checks to see if the key exists
    • If the key doesn’t exist, the handle is closed
  • The malware retreives its current name and compares it to the %Windows%\\Kbwgmwu.exe path
  • If the strings match, the “installation” routine begins
    • The malware creates the registry key SYSTEM\\CurrentControlSet\\Services\\Ruiswe wgzawios
    • The value “Releice Name” is written to the registry key, with the data being randomized
    • The randomized data is then used to create another key at SYSTEM\\CurrentControlSet\\Services\\%s
    • The value “ConnectGroup” is written to the registry key, with the data being “ĬÉÏ·Ö×é”
    • The value “MarkTime” is written to the registry key, with the data being the current data and time
    • The value “Description” is written to the registry key, with the data being 3 randomized words
    • The value “DisplayName” is written to the registry key, with the data being randomized
    • The malware finishes writing the last parts to the registry, and continues
    • CopyFile is called and the malware copies itself to C:\\Windows\\Kbwgmwu.exe
    • Admin Privileges:
      • The malware creates a Service using the randomized data at the start
        • This service is set to auto start and executes C:\\Windows\\Kbwgmwu.exe
        • StartService is then called, executing the newly created service.
    • User Privileges
      • The malware checks for running instances of Kbwgmwu.exe
        • If none are found, execute C:\\Windows\\Kbwgmwu.exe with ShellExecute
        • This loops 4 times, and then ExitProcess is called
  • If the strings do match, and the original registry key exists, the program continues execution
    • WSAStartup is called, initializing WinSock
    • The malware connects to the C2 IP address, using the connect call
    • BeginThreadEx is called, creating a second thread to resume the execution of the program.

IOCs

  • MD5: abdabfea475959703fb1957413b39cad
  • C2 Server: 218.60.67.75
  • URL: http://xxx.ys168.com
  • File Path: C:\\Windows\\Kbwgmwu.exe
  • Registry Key: SYSTEM\\CurrentControlSet\\Services\\Ruiswe wgzawios

4 Replies to “Post 0x10: A Gh0st: Initialization Analysis”

  1. Those writeups help me alot learning malware analysis as a rookie, so thank you for that :)! Also may I ask you what OS / distro you’re using as your host machine?

Leave a Reply

Your email address will not be published. Required fields are marked *