Classic Malware: Carbanak

banner 2.png

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:


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


and run it:



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_NT_HEADERS img_nt_header = (PIMAGE_NT_HEADERS)((LPBYTE)h + img_dos_header->e_lfanew);
    (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;
  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;
    hResult = Process32Next(hSnapshot, &pe);

  // closes an open handle (CreateToolhelp32Snapshot)
  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.


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.