Dutch
English
blue teaming
malware analysis

Classic Malware: Carbanak. Part 2

Zhassulan Zhussupov
18 December, 2022

banner 2.png

As we wrote earlier, it is important to keep in mind that the Carbanak's source codes can be found on github. : https://github.com/Aekras1a/Updated-Carbanak-Source-with-Plugins

structure

The source code leak is a Visual Studio solution (contains botep.sln):

structure

that allows anyone with access to compile banking trojan (in theory).

If we study the file core/source/winapi.cpp further, we will see the function bool BuildImportTable:

123

To sum things up, in order for an executable to execute on Windows, it needs more than simply the code written by the coder.

It is impossible to accomplish practically anything useful without the APIs provided by the operating system. Activities such as writing to disk, reading from disk, showing anything on screen, listening for input from the keyboard, and many more fall under the category of useful activities.

It is necessary to make use of the Windows OS APIs in order to accomplish any of these tasks, and as a result, the software must have access to the API code. In point of fact, even if a programmer runs a program on Windows that makes use of the C standard library, these calls will eventually be converted into OS API calls by the compiler regardless.

These application programming interfaces (APIs) are made accessible by the program by utilizing the Import Address Table to communicate with the Operating System Memory Manager and the image loader regarding where they are located and which APIs are required in the IAT.

What is dynamic import resolving?

There are lots of tricks and techniques that malwares use to evade detection and classification or to make the post-analysis more difficult. One such trick is to resolve windows API calls dynamically, called "dynamic import resolving".

Let's speak about the process of resolving dynamic imports and calling indirect functions. Malware will frequently employ this method in order to conceal their purpose, complicate the process of static analysis, avoid detection in certain situations, and so on.

In this method, the malicious software attempts to generate an IAT (Import Address Table 7) while it is being executed, with the goal of erasing any trace of previously utilized API calls from the PE header.

This method frequently manifests itself in a certain pattern. At the beginning of the execution, the program will generate an array of function pointers that functions like an IAT. Malware can then employ stored function pointers in conjunction with indirect calls, as demonstrated in the following example:

iat

It’s rather difficult to determine which function would be called by these indirect function calls without actually executing the binary.

To dynamically make a function pointer, the two API calls LoadLibraryA() and GetProcAddress() are often used:

bool BuildImportTable( HMODULE imageBase, typeLoadLibraryA _LoadLibraryA, typeGetProcAddress _GetProcAddress )
{
    PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)imageBase;
    PIMAGE_NT_HEADERS headers = (PIMAGE_NT_HEADERS)&((byte*)(imageBase))[dosHeader->e_lfanew];
    PIMAGE_DATA_DIRECTORY directory = &headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];

    if( directory->Size == 0 ) return true; //��� ������� �������
    if ( directory->Size > 0xffff ) return false;

    PIMAGE_IMPORT_DESCRIPTOR importDesc = (PIMAGE_IMPORT_DESCRIPTOR)((SIZE_T)imageBase + directory->VirtualAddress);

    for ( ; importDesc->Name; importDesc++ )
    {
        SIZE_T *thunkRef, *funcRef;
        LPCSTR nameDll = (LPCSTR)((SIZE_T)imageBase + importDesc->Name);
        HMODULE handle = _LoadLibraryA(nameDll);

        if( handle == NULL ) return false;

        if( importDesc->OriginalFirstThunk)
        {
            thunkRef = (SIZE_T*)((SIZE_T)imageBase + (DWORD)importDesc->OriginalFirstThunk);
            funcRef = (SIZE_T*)((SIZE_T)imageBase + (DWORD)importDesc->FirstThunk);
        } 
        else
        {
            thunkRef = (SIZE_T*)((SIZE_T)imageBase + (DWORD)importDesc->FirstThunk);
            funcRef = (SIZE_T*)((SIZE_T)imageBase + (DWORD)importDesc->FirstThunk);
        }
        for (; *thunkRef; thunkRef++, funcRef++)
        {
            SIZE_T addr = 0;
            if IMAGE_SNAP_BY_ORDINAL(*thunkRef)
            {
                addr = (SIZE_T)_GetProcAddress( handle, (LPCSTR)IMAGE_ORDINAL(*thunkRef) );
            }
            else
            {
                PIMAGE_IMPORT_BY_NAME thunkData = (PIMAGE_IMPORT_BY_NAME)((SIZE_T)imageBase + *thunkRef);
                addr = (SIZE_T)_GetProcAddress( handle, (LPCSTR)&thunkData->Name );
            }
            if( addr )
            {
                if( addr != *funcRef )
                    *funcRef = addr;
            }
            else
            {
                return false;
            }
        }
    }
    return true;
}

Now that we've covered the basics, let's move on to the bootstrap and install module and see how everything operates in that section. This module is in charge of launching the bot, keeping it updated, as well as ensuring that it remains persistent within the system:

gchaH6KrAxUyA1pw-vyMY.png

Once we started writing about persistence, we can find a function bool SetAutorun:

3E3zURucEEkq8UHB2lgmD.png

Here we assume the persistence method is used via autorun and registry run keys.

Persistence via Registry Run keys

Malware threats on Windows systems are constantly evolving and becoming more sophisticated, making it increasingly difficult for security professionals to keep up. One of the most common and dangerous techniques used by malicious actors to achieve persistence for their malware is registry manipulation. This technique allows malware to modify registry entries and launch itself when the system boots up, making it difficult to detect and remove.

Registry manipulation is a powerful tool for malware authors because it allows them to add malicious code to the computer’s system registry, where it will run when the computer boots up. By modifying registry entries, malware authors can make their malicious code execute before any other program on the system, making it difficult for security professionals to detect and remove.

Malware authors can use registry manipulation to gain persistence on a system in several ways. For example, they can add malicious registry entries that are triggered by specific events such as user logins, system restarts, or scheduled times. They can also modify existing registry entries to add malicious code that will run when a certain application is launched, or even when the computer is turned on.

In addition to adding malicious registry entries, malware authors can also delete existing registry entries that are necessary for certain programs to run properly. This can cause those programs to crash or malfunction, leading to system instability or even data loss.

Adding an entry to the “run keys” in the registry will cause the app referenced to be executed when a user logs in. These apps will be executed under the context of the user and will have the account’s associated permissions level.

The following run keys are created by default on Windows Systems:

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunOnce

Threat actors can use these configuration locations to execute malware to maintain persistence through system reboots. Threat actors may also use masquerading to make the registry entries look as if they are associated with legitimate programs.

In the simplest implementation, it would look something like this:

int main(int argc, char* argv[]) {
  HKEY hkey = NULL;
  // malicious app
  const char* exe = "C:\\...\\malware.exe";

  // startup
  LONG res = RegOpenKeyEx(HKEY_CURRENT_USER, (LPCSTR)"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", 0 , KEY_WRITE, &hkey);
  if (res == ERROR_SUCCESS) {
    // create new registry key
    RegSetValueEx(hkey, (LPCSTR)"hack", 0, REG_SZ, (unsigned char*)exe, strlen(exe));
    RegCloseKey(hkey);
  }
  return 0;
}

As our practical experience shows, this technique is works at nowadays, for example at Windows 11:

g-xzZyck2p-Ds8h93QuV5.png

lKWen5XRWeRRpOIlNfC7f.png

AAIElqI_b_J_7leK9MOMd.png

_UjEtzNEJB1cjbvanMHcR.png

Run the evil code

And here are the main calls to run the code:

tMc0EArab2aOKcfq05N7N.png

5Xz8Eslruc8yIz4TPhNIq.png

pO42JV5uBXBcNGts8KPXc.png

All this actions is controlled by external commands transmitted from the server (botcmd/source/main.cpp):

CYytIiFbocIcPO178YZaJ.png

Carbanak trojan has a module for privilege escalation:

01n6Z6vKWCTH88iy8T2px.png

Also Carbanak trojan architecture has a module with mimikatz:

ZtVM-S9Gidi0fKUr_b4ZD.png

Mimikatz

Rc3IqzLTZkGJ5q4Lba8ZM.png

Mimikatz is a powerful Windows password auditing tool created by Benjamin Delpy, a French security researcher. It is designed to extract Windows credentials, including usernames, passwords, and NTLM hashes, from memory and local files. Mimikatz is a versatile tool that can be used for both offensive and defensive security purposes.

For offensive security, Mimikatz can be used to extract credentials from memory or local files, or from Active Directory or Kerberos ticket caches. This can be useful for obtaining administrator credentials for lateral movement within a network. Mimikatz can also be used to spoof Kerberos tickets, allowing an attacker to impersonate legitimate users.

For defensive security, Mimikatz can be used to detect weak passwords, or to identify which users have administrator privileges or access to privileged information. It can also be used to detect malware that is attempting to steal credentials or to identify users who are re-using the same password across multiple accounts.

Overall, Mimikatz is a powerful and versatile tool that can be used for both offensive and defensive security purposes. It is important to note, however, that its capabilities can be used for malicious purposes, so it should be handled with caution.

Conclusion

We hope that this note will serve as a starting point in the independent study of Carbanak and will allow you to replenish your knowledge base in the field of malware researching and analysis. We also hope it will also be useful for a wide range of readers to have an idea of how sophisticated the methods of attackers can be, especially in those operating in the financial sector.

This is a practical case for educational purposes only.

References

https://github.com/Aekras1a/Updated-Carbanak-Source-with-Plugins

Authored By
Zhassulan Zhussupov

Cybersecurity enthusiast | Author | Speaker | CTF player | R&D Engineer | Jiu-Jitsu Practicioner

Share with the world!

Need Security?

Are you really sure your organization is secure?

At WebSec we help you answer this question by performing advanced security assessments.

Want to know more? Schedule a call with one of our experts.

Schedule a call
Authored By
Zhassulan Zhussupov

Cybersecurity enthusiast | Author | Speaker | CTF player | R&D Engineer | Jiu-Jitsu Practicioner