This little analysis is based on leaked banking malware Carbanak's source codes.
What is Carbanak?
In the spring of 2014, specialists from Kaspersky Lab studied a number of bizarre ATM events.
Several ATMs belonging to a Ukrainian bank occasionally began dispensing cash for no apparent reason, and random passers-by who happened to be there pocketed the money and went.
On the computer of the bank, to which these ATMs were connected by VPN, a new Trojan was detected and given the name Carbanak by the analysts who discovered it.
The investigation revealed that early versions of Carbanak are derived from the code of Carberp, a banking Trojan notorious for stealing money via online banking systems.
Carberp and its successors are utilized in the majority of events involving the hacking of Internet banks belonging to individuals and legal bodies. Carberp was initially created and utilized by one of the Russian cybercriminal groups, but its creators quickly began selling it on the dark web for $40,000.
Someone published the Carberp source code on the Internet in the summer of 2013, which a hacking group used to create Carbanak on the cheap.
Carbanak malware has become increasingly prominent in recent years as a malicious program used by hackers to attack banks, e-commerce sites, and other financial institutions. It is a sophisticated form of malware that has been used to steal more than $1 billion from banks, e-commerce sites, and other financial institutions since 2013.
Carbanak malware is a type of banking trojan, which is a type of malicious software designed to steal banking information from an infected computer. It is typically spread through phishing emails, malicious websites, and other malicious attachments. The malware can also be spread through compromised systems or through malicious software updates.
Once the malware is installed on a computer, it can be used to gain access to sensitive data and financial information. The malware can be used to steal passwords, transfer funds, and even delete or modify data. Carbanak malware is particularly dangerous because it is difficult to detect and can be tailored to target specific organizations.
All the curious can see the source code of this creation on GitHub: https://github.com/Aekras1a/Updated-Carbanak-Source-with-Plugins
structure
The source code leak is a Visual Studio solution (contains botep.sln
):
that allows anyone with access to compile banking trojan (in theory).
The ability of properly developed malware to circumvent detection by antivirus software and conceal its actions is typically the first thing that draws our attention to this type of malicious software. Carbanak uses numerous strategies to fight antivirus programs. Moving on, we shall think about them.
First, let's look at how the core of the Trojan works, and first of all, let's look at how it interacts with WinAPI:
As you can see, list of required DLLs where WinAPIs are stored and this is only part of libraries used by the Carbanak trojan bot:
In addition, in the initialization block of this module (function bool Init()
), we see code that dynamically receives the GetProcAddress
and LoadLibraryA
functions by their hash:
PEB
process structure get code:
As you can see, depending on the architecture x64
or i386
, the code logic is different.
Then, find function GetApiAddr
which find Windows API function address by comparing it's hash:
that is, Carbanak uses one of the simplest but effective AV engines bypass tricks: hashing function names
Here we will dwell on the "hashing winapi function names" concept.
hashing function names
This is a simple but efficient technique for hiding WinAPI calls. It is calling functions by hash names and it’s simple and often used in the "wild".
Let's look all at an example and you'll understand that it's not so hard.
standart calling
Let's say we have a "malware":
#include <windows.h>
#include <stdio.h>
int main() {
MessageBoxA(NULL, "Meow-meow!","=^..^=", MB_OK);
return 0;
}
If we compile it, and run strings
command:
strings -n 8 meow.exe | grep MessageBox
As you can see, the WinAPI function are explicitly read in the basic static analysis and:
visible in the application's import table.
hashing trick
Now let's hide the WinAPI function MessageBoxA
we are using from malware analysts. Let's hash it:
# simple stupid hashing example
def myHash(data):
hash = 0x35
for i in range(0, len(data)):
hash += ord(data[i]) + (hash << 1)
print (hash)
return hash
myHash("MessageBoxA")
and run it:
python3 myhash.py
What’s the main idea? The main idea is we create code where we find WinAPI function address by it’s hashing name via enumeration exported WinAPI functions.
First of all, let’s declare a hash function identical in logic to the python code:
DWORD calcMyHash(char* data) {
DWORD hash = 0x35;
for (int i = 0; i < strlen(data); i++) {
hash += data[i] + (hash << 1);
}
return hash;
}
Then, we declared function which find Windows API function address by comparing it’s hash. Something like this:
static LPVOID getAPIAddr(HMODULE h, DWORD myHash) {
PIMAGE_DOS_HEADER img_dos_header = (PIMAGE_DOS_HEADER)h;
PIMAGE_NT_HEADERS img_nt_header = (PIMAGE_NT_HEADERS)((LPBYTE)h + img_dos_header->e_lfanew);
PIMAGE_EXPORT_DIRECTORY img_edt = (PIMAGE_EXPORT_DIRECTORY)(
(LPBYTE)h + img_nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
PDWORD fAddr = (PDWORD)((LPBYTE)h + img_edt->AddressOfFunctions);
PDWORD fNames = (PDWORD)((LPBYTE)h + img_edt->AddressOfNames);
PWORD fOrd = (PWORD)((LPBYTE)h + img_edt->AddressOfNameOrdinals);
for (DWORD i = 0; i < img_edt->AddressOfFunctions; i++) {
LPSTR pFuncName = (LPSTR)((LPBYTE)h + fNames[i]);
if (calcMyHash(pFuncName) == myHash) {
printf("successfully found! %s - %d\n", pFuncName, myHash);
return (LPVOID)((LPBYTE)h + fAddr[fOrd[i]]);
}
}
return nullptr;
}
and at the main()
function we just compare hashes:
int main() {
HMODULE mod = LoadLibrary("user32.dll");
LPVOID addr = getAPIAddr(mod, 17036696);
printf("0x%p\n", addr);
fnMessageBoxA myMessageBoxA = (fnMessageBoxA)addr;
myMessageBoxA(NULL, "Meow-meow!","=^..^=", MB_OK);
return 0;
}
So, if we compile and run again:
our logic is worked. And run strings
command again:
strings -n 8 hack.exe | grep MessageBox
And let's go to see Import Address Table:
If we dig deeper into the investigation of the malware, we will, of course, find our hashes as well as strings such as user32.dll
and so on. On the other hand, this is merely a case study.
hashing algorithm
So if we think like Carbanak trojan developers, is there anything else we can improve? Of course! If we analyze our binary, we can see that the functions we use OpenProcess
, VirtualAllocEx
, WriteProcessMemory
, CreateRemoteThread
, and CloseHandle
for example, are listed in the binary's import address table. This is a red flag as antiviruses are looking for a combination of these Windows APIs which are commonly used for malicious purposes. Therefore, this method is effective against most antivirus engines.
Back to our Trojan. And what hashing algorithm is used by Carbanak?
We see that the hash function is declared in the core/source/misc.cpp
file:
In addition to hashing function names. pay attention to _CT_
macros - they encrypt strings:
And it is used in many places at core:
In addition, a technique for determining the type of anti-virus software being used was discovered in the file known as bot/source/AV.cpp
. This file's name gives it away. The Trojan conducts a search for processes in the conventional manner:
// find process ID by process name
int findMyProc(const char *procname) {
HANDLE hSnapshot;
PROCESSENTRY32 pe;
int pid = 0;
BOOL hResult;
// snapshot of all processes in the system
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (INVALID_HANDLE_VALUE == hSnapshot) return 0;
// initializing size: needed for using Process32First
pe.dwSize = sizeof(PROCESSENTRY32);
// info about first process encountered in a system snapshot
hResult = Process32First(hSnapshot, &pe);
// retrieve information about the processes
// and exit if unsuccessful
while (hResult) {
// if we find the process: return process ID
if (strcmp(procname, pe.szExeFile) == 0) {
pid = pe.th32ProcessID;
break;
}
hResult = Process32Next(hSnapshot, &pe);
}
// closes an open handle (CreateToolhelp32Snapshot)
CloseHandle(hSnapshot);
return pid;
}
, and then the hashes of the discovered processes are compared with those included within this particular instance using the int AVDetect()
function:
In general, hashing is also used throughout the source code of the trojan:
Also we find a function IsPresentKAV()
which also use for AV detection:
There is also another interesting piece of code here, and it is also used to detect antivirus engines:
The crux of this strategy is based on the fact that emulators of antivirus solutions are not always able to correctly reproduce the behavior of the environment in which the application is running. This is the key to the technique's success. In this particular instance, the Carbanak trojan initiates communication with the GetTempPathA
WINAPI function, which provides access to the location of the temporary files folder (temp
), and then attempts to launch an executable file that does not exist from within that location.
If, after these actions, the operating system returns the error ERROR_PATH_NOT_FOUND
which is a common error that occurs when running an application on a real system, the malicious software comes to the conclusion that the code execution is not being emulated by antivirus tools, and control is transferred further.
This concludes the first part of the post on the banking Carbanak trojan.
Conclusion
Carbanak does not reveal itself in any way to the outside world on machines that are infected with it.
All that it is capable of doing is sending a record of the computer user's activities to its owners (in the form of a video of poor quality and a log of the keystrokes), as well as tracking the program that is being launched.
The "silent" phase can extend for several months, during which time the hackers will observe the bank's operational procedures and capacities in great detail.
This is a practical case for educational purposes only.
References
https://github.com/Aekras1a/Updated-Carbanak-Source-with-Plugins