Kardon

Malware analysis

Published on


Introduction

This is my very first article on malware analysis. The analyzed sample is the Kardon program. In this analysis, we will explore all the features of the malicious program through static analysis.


Information Gathering


CFF Explorer

We begin by gathering some information with CFF Explorer. We see that the executable is a PE type and a 32-bit program coded in C++.
Image
It is possible to see which libraries are imported:
Image


Strings

We can deduce some functionalities of the program even before performing static analysis with IDA by looking at the strings. For example, here we assume that the program checks to determine the target's OS:
Image
Here, we assume it checks if it is running in a virtual machine:
Image
Here we know that the program sends data via a POST request:
Image
We assume here that the program seems to want to persist because we find the path where registry keys for startup programs are placed:
Image
Here, we find what seems to be the site contacted by the program, pointing to the /kardon/gate.php page, where the POST request may be sent.
Image
Finally, in the program's strings, we see many other pieces of information like used functions; for example, here we find functions related to creating and adding a registry key value.
Image


Static Analysis

When we open the program with IDA, we find ourselves in the start function of the code, where each function here seems to play a role in starting up, so nothing particularly interesting. However, at the very end of this start function, there is a function that seems to launch the rest of the program, so we will rename it "main."
Image
Here we are now in the main (sub_402247):
Image
We observe several things, starting with the first call to the function sub_401A43, then we enter what seems to be an infinite loop in the function loc_40224C. In this function, there are two CALLs to the functions sub_401C4A and sub_401DD2, and at the end of the loop, we have a call to the sleep function before restarting the loop.
Let's start by analyzing the function sub_401A43 that we renamed Init:
Image
We will break down this large function into several parts, starting with the part above. This part contains a call to the function sub_40148B and a conditional JUMP based on the value of the AL register.
We also notice that there will be 3 other similar conditional JUMPs, and these 4 JUMPs can lead us to the function loc_401BD3, which calls the function ExitProcess.
Image
We can therefore assume that if each of the conditions is not met, the program stops. It becomes interesting to look at each of the called functions and see how we can obtain a 0 value in the AL register (we could also modify our register manually or add a xor al, al instruction just before the test al, al check) since our 4 conditional JUMPs are of type JNZ, meaning that if the return value is not equal to 0, we jump to the loc_401BD3 function, which we will now call exitFunction.
Here is a part of the first function:
Image
This function will be used to detect if the malware is executed in a virtual environment. The following function calls the cpuid function, which queries the system about the CPU so that the program can understand the type of architecture it is running on and determine if it is a virtualized environment.
Image
Interesting function (still protections):
Image
The above function will load a set of DLLs to gather information about the host machine's behavior. The choice of DLLs is not random, as each represents a component of a tool used for malware analysis.
For example, we find DLLs related to Sandboxes and antivirus (like AVG and Avast in our case).
Here is the last function in the series:
Image
This last function will load the kernel32.dll module, and if it succeeds, it will try to find the address of the wine_get_unix_file_name function. This module will allow the program to know if it was executed under Wine, which is a program that runs Windows on a Linux system.
Image
This function follows the various functions seen just before.
We arrive here if everything has gone well. In this function, several things stand out:

  • - The domain name kardon[.]ddns[.]net
  • - The page /kardon/gate.php
  • - A call to the function getInformations

For now, the two variables domainName and pageName are not used; we will need to wait a little further in the program. For now, let's discover the getInformations function:
Image
In this first part of the getInformations function, we have 3 calls that will allow us to determine several pieces of information:

  • - checkIf64bits: this function will call GetProcAddress to try to resolve the address of the IsWow64Process module. This module contains the executables in the \Windows\system32 folder, but here these programs are compiled in 64-bit. This function will help us identify the architecture type (x86 or x64).
  • - getSystemInfo: this function returns information about the system.
  • -
  • - getComputerNameA: this function returns the machine name.

Image
In this part of the same function, we find a call to the sub_4012A6 function, which retrieves the security token information to determine the rights of the current user and whether they are an admin or not.
The call to the GetVolumeInformationA function will retrieve a set of information about the "C:\\" volume.
Image
This sequence will perform two checks on the "kernel32.dll" library via two functions, GetFileVersionInfoSizeA and GetFileVersionInfoA. If the returned result is not as expected, a JUMP to the end of the function is made.
Image
Next, we have several checks to find the operating system of the host machine.
To summarize, in this getInformations function, we have methods to:

  • - Retrieve the host system's architecture
  • - Retrieve the current user's name
  • - Retrieve the host machine's name
  • - Retrieve information about the host system
  • - Know the user's permission level (whether they are an administrator or not)
  • - Get details about the disk volumes
  • - Know the host operating system

Image
In this function, we will check if the current user is an administrator, and depending on the return, a method of persistence will be established.
For example, here we have:
Image
Here the persistence method will depend on the malware's execution rights; if the program was executed with administrator rights, it will go left; otherwise, it will go right. Only the administrator can write to HKEY_LOCAL_MACHINE. Here, we will place it in this root in the path SOFTWARE\Microsoft\Windows\CurrentVersion\Run if we want to make the program persistent for all users of the machine and have the program run with higher privileges at each new session. By using the HKEY_CURRENT_USER root, the program will only be persistent for the current user and will be executed with simple rights.
Image
Here we are at the end of the Init function, where the program will relocate itself elsewhere via the MoveFileExA function and then make itself persistent by adding the registry value Microst Update to the SOFTWARE\Microsoft\Windows\CurrentVersion\Run registry key via the RegSetValueExA function.
We notice here that the registry value is named Microsoft Update to appear as a legitimate action by the system itself.
We are now back in the main to analyze the continuation of our malware:
Image
We will analyze the sub_401C4A function, which we will rename firstCommunication since it will be the first connection with the attacker's server.
Image
In this firstCommunication function, we observe that several values are put into arguments in the formatting of a string that will be pushed as the variable aIdSosSPvSIpSCn. We also note that the number of values is 7, which we can link to the 7 values collected in the getInformations function discussed earlier. We can therefore assume that the sent values are:

  • - The host system's architecture
  • - The current user's name
  • - The host machine's name
  • - Information about the host system
  • - The user's permission level (whether they are an administrator or not)
  • - Details about the disk volumes
  • - The host operating system

Since the beginning of the analysis of this function, we have been talking about connection and sent values, but we have not yet seen any request or connection attempt. But we finally get there, just after the call to the sub_401CC7 function.
Let's look at the arguments that are pushed into this function:
Image
Here, EAX will contain the size of the value of the variable seen above containing the 7 pieces of information that will be sent. We can know this thanks to the sub_40226B function called just before, which will copy the variable aIdSosSPvSIpSCn containing the information we are interested in into a buffer using the wvsprintfA function.

On paper, the function is represented as follows:
Image

And in our case, we have:
Image
The wvsprintfA function returns an integer as a value, which is the buffer size, and this value will be copied into EAX and finally pushed into the sub_401CC7 function. Moreover, we also have two variables that we know very well that will be pushed during this function call. These variables are:

  • - domaineName: contains the value --> "kardon[.]ddns[.]net"
  • - pageName: contains the value --> "/kardon/gate.php"

We will now analyze this famous function, of which here is the first part:
Image
Here, we have the information that we will make network requests since this small piece of code initializes the Winsock DLL. This DLL allows sending and receiving data packets over TCP/IP networks.
Image
Next, we observe several things: first, the value contained in domainName will be pushed into the gethostbyname function to retrieve information such as the IP address, and if the variable value is already an IP address, the inet_ntoa function will be called to convert the IP address into usable ASCII. The goal is to have the same type of return at the output of the sub_401A0E function. The return we just obtained will be pushed into the inet_addr function, which will allow us to retrieve the IP address compatible with the IN_ADDR structure. Then a call to the connect function occurs.
Here is the part that finally interests us:
Image
We now know that POST requests are sent to: hxxp[:]//kardon[.]ddns[.]net/kardon/gate.php and the sent values are the 7 values we discussed earlier.
Following this, we have several possible return values depending on the result, and depending on this return, we have these different sequences of code:
Image
Here we have three possibilities:

  • - Failed to initiate WSAStartup: returns the value "rqf" (request failed? maybe? idk.)
  • - Failed to send data: returns the value "rqf"
  • - Success: closes the socket and returns a value retrieved by the attacking server (here we understood that it is a C&C)

Here we are again in the main function to move on to the last function of this C&C:
Image
We rename the last function sub_401DD2 to CommandAndControl, and here is its content:
Image
Before getting to the most interesting part, we process the data returned by the previous function, and if this value corresponds to "notask" or "rqf," then a JUMP to the return function will be made. Remember that at the exit of this last function, the sleep function is called to pause the program for 60s, then returns to the call of the firstCommunication function (this is a program that runs in a loop).
If the return value is neither equal to "notask" nor "rqf," the program will check 3 other different values for different contexts:

  • - If the value equals 1, the associated function will be executed.
  • - Otherwise, if the value equals 2, the associated function will be executed.
  • - Otherwise, if the value equals 3, the associated function will be executed.
  • - Otherwise, the program will JUMP into the return function to go back to the main

In the case where the value is 1, we have:
Image
Here we have two interesting functions, sub_4015B3, which we will rename downloadInPathAndExec, and sub_401CC7. Here is downloadInPathAndExec:
Image
This function does 3 things:

  • - Store the temporary folder path in a variable
  • - Download an external file (probably a malicious program) and place it in the temporary folder %TEMP%; if we look closely before the call to the GetTempPathA function, we see the instruction PUSH EAX, which is the buffer, and we notice that before the call to the URLDownloadToFileA function, there are these instructions: PUSH EAX and PUSH EBP+ARG_0. Here, EAX contains the buffer value, meaning it contains the %TEMP% value, and here EBP+ARG_0 likely contains the executable name. Hypothetically, it's as if we had PUSH %TEMP%/ProgramName.
  • - Execute the downloaded program in %TEMP%.

Then the second function, sub_401CC7, which we renamed sendDataAndRecvWithServer, is a function that allows communication with the attacking server. We have already analyzed it earlier, and it is called at these different locations:
Image
A new request is sent to the attacking server, and the program will check if the return value equals 2 or 3. If the return value equals 2, it will go left; otherwise, it will go right:
Image
In the case where we go left (so if the return value = 2), the program will call the downloadInPathAndExec function to download a malicious program in %TEMP% and execute it. Then the program will call the sub_4021BE function, which we renamed goPersistance.
In this function, we find this:
Image
If the program was run by the administrator, it will go left; otherwise, it will go right. This program allows adding a persistence method and adding the "Microsoft Update" key to the SOFTWARE\Microsoft\Windows\CurrentVersion\Run registry. Let's remember that this key already exists, yet the operation is performed again. We can assume that the malicious program downloaded when the return value equals 2 is simply an update of the current program. Returning to the previous function, if we look to the right when the return value equals 3, we simply have a call to the goPersistance function.
In both situations, if the return value equals either 2 or 3, at the end, we will have this:
Image
This piece of code will do what the program has already done before, meaning it will send information but this time it will also exit the program immediately afterward.


Conclusion

As we have detailed above, this C&C does several things:

  • - Checks on the host system to find traces of "anti-malware" programs (VM, Sandbox, AV, etc.)
  • - Declares the data needed for communication (domain name, page)
  • - Retrieves a set of information to be sent to the control server; this information helps establish a profile. Here they are:
    • - The host system's architecture
    • - The current user's name
    • - The host machine's name
    • - Information about the host system
    • - The user's permission level (whether they are an administrator or not)
    • - Details about the disk volumes
    • - The host operating system
  • - C&C persistence
  • - First data exchange with the control server and retrieval of a return value, which can be:
    • - 1
    • - 2
    • - 3
    • - notask
    • - rqf (returned by the program if an error is detected during communication with the server)
  • - Depending on the return value, we have several possible scenarios:
    • - 1: downloads a malicious program, executes it, and sends a request to the control server.
    • - 2: downloads an update of the current program, makes it persistent again, sends a request to the control server, and exits the program.
    • - 3: makes the current program persistent again, sends a request to the control server, and exits the program.
    • - notask: returns to the main.
    • - rqf: returns to the main.
    • - any value: returns to the main.



It should be noted that with each action, a request is sent to the control server, allowing the attacker to obtain the profile of the compromised machine. Continuously retrieving the profile allows the attacker to adapt its behavior and provide an update to the C&C currently on the compromised machine. Each time the program relaunches persistence, it will simply overwrite the existing one, and before that, the program checks if the executor has administrator rights to make itself persistent at a higher level (on HKEY_LOCAL_MACHINE). This privilege escalation allows the attacker to send larger programs that will then be executed as an administrator because if the C&C is executed with admin rights, it will be able to execute with admin rights when it calls the WinExec function, as observed earlier in the analysis.