Dev | Disassemble | Debug

Winver: Reverse-Engineering PatchWork APT's recent Golang implant.

Table Of Contents

Background.

Recently, since I started publishing blogs once again in January 2024, I have come across a lot of samples written in Golang, be it generic stealers like the ones in my previous blog posts, be it new stealers in the market, like Planet Stealer, then I did come across a demo or random ransomware which was in the wild, I cannot recall the name, while drafting this blog post. So, I have decided to throw my skill under the golang malware bus and check the calibre of my present skillset of analyzing Golang Malware.

Well, recently in this process of hunting, I did come across a tweet by fellow security researcher Yogesh Londhe, who posted about a fresh implant linked to PatchWork Threat group. Consequently, this blog will predominantly serve as a blog on the reverse-engineering side of things rather than a conventional malware analysis discourse.

Overview of the implant.

In this section of the blog, we will focus on some basic analysis of the implant. Well, there is not much to the implant in terms of usage of external obfuscators & packing software, so I decided to limit the overview to three sections which are Metadata, the interesting Certificate and a few misc artefacts about the sample. Let us dive in.

Metadata.

SHA-256 : 01EA7197094B9ACD50605BDA611111EAA822230F81A3CAC4B47A2F9D01E146C1.

Sample: Available here.

Certificate.

image

Well, it turns out that this certificate has been issued by an IT Consulting company based out of the United Kingdom, and the recent implants of PatchWork have been seen using the same certificate in the campaigns. So, for my defender friends out there, this can be a simple artefact.

Misc.

image

Well, I was initially pretty much confused about the nomenclature of the implant, ‘ Apollo `, as per the security researchers tracking this threat group. Well, then it turns out the project path’s name is Apollo.

image

image

Thanks to PEStudio, for these details. It is a pretty impressive tool as always, it mapped a few artefacts making it clearer and giving a clear overview of the sample. Now, in the next sections of the blog, we will use IDA-Freeware to reverse engineer the implant binary.

Reverse Engineering the implant using IDA-Freeware - I

image

Well, as soon as we load the file in IDA-Freeware and post-autoanalysis, we have the actual main folder, which contains a bunch of interesting functions, well the reason am calling it a folder is because post-recent additions to IDA disassembler’s capabilities allow, a bunch of functions to be scrutinized under a certain package like os, http etc. So, am lucky, that I do not have to hover around every function and find co-relations, saving me some time.

And, as the number of functions is 20. We will cover the working of each function in this blog post by covering the initial ten functions, in this first part and the rest in the next section of blogs.

image

Upon landing in the main folder, we are welcomed with the very first function main_main, which is the actual main function, which calls the other 19 functions. Let us now go ahead to the next function. If you want to understand, a bit in-depth about the main function, refer to this blog post.

image

image

Now, here we encounter a function named setConsoleCodePage, let us go through the workings of this function. As we can see argument 65001 is being passed to the setConsolePage function.

image

Turns out that the code is using exec package from golang, to execute this command cmd chcp /C which will change the current code page to UTF-8 and immediately terminates the cmd window. That’s the purpose of this function.

image

After moving ahead with the code analysis, we could see that a URL is mostly acting as a command & control server here.

image

Then, we see another weird-looking string loaded into the RAX register just like the URL of the C2 had been loaded.

image

Yogesh's tweet

Again, a very similar pattern is being followed, thanks to Wireshark filters, we figured out that the weird-looking string AGCXHMYAJVKDHBRACJNKHX is the unique User-Agent, which will be used to send a simple POST or in layman terms for connecting back to the C2. Next, we have a function known as sendPing.

image

image

Upon browsing, this sendPing function, we see that the implant is trying to enumerate the UUID of the target device using wmic and then later using these individual strings as arguments for os_exec_Command function, to run it. Just when the implant runs, a window wmic.exe pops up and quickly terminates.

image

Then, the implant uses os package code from the Golang library, to enumerate the current username.

image

image

Then, we have another function known as encryptRC4 which performs as per the nomenclature of the function and encrypts the enumerated data performed by those functions, which we just saw using the RC4 algorithm. Let us move ahead with the rest of the code.

image

image

image

Here, we encounter another function known as getHostName. As, the name says it uses hostname function from the os package in Golang to enumerate the hostname and return it, later which gets encrypted using RC4.

image

image

Now, here we encounter another function known as getExternalIPAndCountryCode which enumerates the IP Address and then geolocates it using IP-API service and returns the data for exfiltration. Now, let us continue with the analysis of the rest of the functions in the next section.

Reverse Engineering the implant using IDA-Freeware - II

image

Moving ahead, we encounter another function known as getWindowsVersion let us explore the function.

image

image

This function uses golang_org_x_sys_windows_registry_OpenKey to open the registry key, and then uses another golang function known as golang_org_x_sys_windows_registry_Key_GetStringValue to read the ProductName which helps the function to enumerate the current version of the Windows like for example Microsoft Office Professional Plus 2010. Once the product or version name is enumerated, it goes ahead and returns the value, which then is passed as a plaintext parameter to the encryptRC4 function, which later encrypts it for exfiltration purposes.

image

Next, we encounter another function known as getExecutablePath, let us explore the function.

image

Then, we see that the function is using os_Executable a golang function to query the path which launched the executable, later then once the function returns the path, it uses another function from the file path module, known as Abs which returns an absolute representation of the path. If the path is not absolute it will be joined with the current working directory to turn it into an absolute path.

Therefore, it returns the absolute path of the implant, which launched it.

image

Next, we have another function, known as main_getCurrentProcessID, let us explore the function.

image

We can see that the function is using the getCurrentProcessId function, from the windows syscall package to enumerate all the process IDs running in the current system, then uses a golang native function known as FormatInt which returns a string representation of the integer value, which is later returned by this function, and then this value is passed to EncryptRC4 function to encrypt it which is to be exfiltrated.

image

Next, we see a native golang function known as GetEnv whose function signature goes like func Getenv(key string) string, where the only argument key is the PROCESSOR_ARCHITECTURE. This returns the process architecture.

image

Next, we encounter another function known as sendHTTPRequest. Let us explore the function.

image

image

As we dive into the function, we can see that here, it tries to send a POST request to the C2.

image

image

Well, moving ahead with this function, we can see that this is sending a request, before the function returns we have another interesting function known as checkCommand, which then, jumps to another function known as ExecuteCommand to execute a certain parameter passed to this function from the checkCommand function.

image

Now, we have another function known as getss, let us explore the function.

image

Now, we can see that inside this function, the implant is using a well-known open-source tool known as kbinani to grab screenshots from the victim machine & saving the file as random.PNG for exfiltration.

image

Well, now we have the last function of this implant known as sendResult, let us explore the function.

image

Upon browsing, the disassembly of this function, we can see that it is creating a simple POST request, which will be used to send the data collected by the above functions to the Command & Control(C2) server, using the unique user-agent.

With this, we are done with the reverse-engineering part of the implant.

Features & Capabilities of the implant.

Maturity of the threat actor.

As someone, who enjoys reverse engineering but is still not good at it, it’s my personal opinion from my experience of dealing with Golang malware, it looks like the threat actor has recently adopted Golang as it’s part of the arsenal. We could see that the there the functionalities of the implant heavily rely on open-source projects like kbinani and many more, whose detections are already out there by EDR vendors. No anti-evasion technique or something intriguing in the implant, which overall makes it look like a very hasty-unfinished work, from a developer’s perspective. Apart from the employment of the RC4 algorithm to encrypt, I did not find anything challenging. But again the implant belongs to an industry labelled as supposedly nation-state threat actor, would say the maturity is average, again that’s solely my opinion, which can vary from person to person.

Implants alignment with the common go-malware landscape.

As per my analysis, the implant contains a lot of open-source projects used for various purposes, similar to the implants or generic stealers I have analyzed, like the kbinani project for screen grabbing, so I would say aligning to the current go-malware scenario, the implant is not too different from the other implants or malware samples out there in the wild.

Limitations.

This blog solely focused on the reverse-engineering perspective of the sample, it does not have any methods to detect the sample or any link to analyzing the initial infection vectors which dropped this implant. So, I think that there are some limitations to this current blog post.

Author’s two cents.

The opinions and keywords used in this blog are completely my opinions upon spending time analyzing this implant. If you find any information or term misleading, please do not hesitate to reach out, I will be more than happy to receive criticism & improve further. Thank you for reading.

Resources.