Skip to content

Latest commit

 

History

History
417 lines (323 loc) · 21.4 KB

File metadata and controls

417 lines (323 loc) · 21.4 KB

Malware Analysis Report – APT29 C2-Client Dropbox Loader

[Sample + IDA database to download]Password:infected
[Download PDF Report]

  1. Basic Information

    Malicious sample was spread via spear-phishing attack targeted at government organizations with attachment “Meeting Info.img”. The attachment “Meeting Info.img” is disc image file format containing 5 files. Abusing this kind of file format “.img” is leveraging available mounting capability of Windows OS (8, 8.1, 10, 11), preserving of file attributes and NOT supporting ADS (Alternate Data Stream) specifically the “Zone.Identifier” (Mark of the Web). In case of “Meeting Info.img”, 4/5 files have set “hidden” file attribute and after mounting the “.img” file, Windows OS will not show them in default settings as we can see in the picture below.

    After clicking the “Meeting Info.lnk”, hidden program “NV.exe” is executed. DLL hijacking (DLL search order) is abused as “NV.exe” (not malicious program “Original Filename: WCChromeNativeMessagingHost.exe” of company Adobe Systems Inc. – digitally signed) is loading modified version of “vcruntime140.dll” (added record for “AcroSup64.dll” in Import Directory) from application directory and because of that, malicious library code “AcroSup64.dll” is executed.

    Execution of “NV.exe” abusing DLL hijacking and modified version of “vcruntime140.dll” to load an execute malicious “AcroSup64.dll”.

    Because of the main functionality and malicious code resides in “AcroSup64.dll”, further analysis will be focused on this file.

  2. Static Code Analysis – “AcroSup64.dll”

    Upon library loading “AcroSup64.dll”, the first function (functions “DllEntryPoint” and “dllmain_dispatch” are not important in this case) which is performing the intended malicious behavior and gets automatically executed is “DllMain”.

    Right in start of function “DllMain”, we can see that first anti-analysis check is performed. Code is checking if main process module filename is “NV.exe” same as the delivered original filename of program responsible for loading “AcroSup64.dll”. Be aware that through whole this analysis - all code is already annotated and retyped in IDA IDB and functions are renamed according to their capabilities.

    We can also see the first thread execution hijacking which is processed via calling directly “NtCreateThreadEx” syscall. New thread is created in suspended state with flags set also to hide from debugger. Decoy start routine “RtlNewSecurityObjectWithMultipleInheritance” of newly created thread is replaced with setting the thread context of this thread – specifically via setting RCX register (NOT RIP as this new suspended thread is not initiated yet) pointing to code where the execution will be directed. This serves well as AV evasion and anti-debug technique. RCX is the first argument to function “RtlUserThreadStart” (thread start location) and this argument sets new thread entry routine different than the decoy one.

    The “NtCreateThreadEx” syscall is dynamically resolved and gets executed directly via “syscall” assembly instruction where desired syscall number is set in RAX register, as we can see in the picture below:

    Resolving of syscalls is done via function “resolve_and_hash_all_syscalls” only once, on first execution. “resolve_and_hash_all_syscalls” function is hashing syscall names and populates it to table named as “hashed_syscalls_table”. This table later serves as lookup table to find specific syscall number for routine. Function “resolve_and_hash_all_syscalls”:

    Whenever we see this kind of advanced technique (dynamic resolving of syscall via syscall name hashing and creating “hashed_syscalls_table” which serves as lookup table + direct syscall call via stub code similar like in ntdll.dll) we should do a little OSINT if this technique is based on some already published one.

    In this case, our assumption was correct and this technique is based on “SysWhispers2” published on Github [GITHUB - SysWhispers2]. C2-Client Dropbox Loader was reusing most of the original code from “SysWhispers2” also the syscall name hashing algorithm so with this information we can take some structures and implement it in IDA to get better understanding of this code like in pictures below:

    Using “hashed_syscalls_table” as lookup table for desired syscall hash to retrieve its syscall number:

    Hashing syscall names and populating + reordering the “hashed_syscalls_table”:

    The main point of this kind of retrieving syscall numbers for routines is based on the fact that syscall numbers are in ascending order strictly connected to order of syscall´s virtual addresses “Zw*” inside of ntdll.dll – meaning that lowest virtual address of syscall = lowest number of syscall (highest virtual address of syscall = highest number of syscall). We can confirm this fact/idea with simple [python script] + ntdll.dll in IDA:

    Now when we have knowledge how this technique works, we can focus on syscall name hashing algorithm which after annotating and retyping looks similar like below:

    This hashing routine we can easily reproduce in [IDA Python script] and create ENUM for all Syscall hashes:

    So whenever we see hashed syscall name, we can apply newly created ENUM and after we find out the correct invoked routine, we can retype whole function.

    We can get back to the first thread execution hijacking - “Pre_C2client_MAIN_redirect_exec” is the function where thread execution hijacking directs to. This function can be seen in the picture below. Function is trying to find “NV.exe” module name in memory and if found, another thread execution hijacking occurs. This time it hijacks already existing thread (no new thread created) and because of that, code can just set RIP register of thread context. Newly set RIP register is pointing to function named “C2_Client_MAIN” where all the main malicious C2 activity is implemented.

    Start of function “C2_Client_MAIN” can be seen in the picture below. First what this function is doing, is calling function “Map_dll_restore_text_section”. After this, C2_client tries to authenticate itself to Dropbox service and if authentication is successful (there is unintentional exception – see below “http_dropbox_authenticate” function analysis), it sets persistence and continue with Dropbox communication otherwise it waits 5.5 minutes and try to authenticate itself again. All is performed in endless loop.

    “Map_dll_restore_text_section” function serves well as AV evasion, anti-debug and anti-hooking technique as this function is searching for all already loaded modules (WININET.dll is the last one if found), finding them on disc, manually maps their “.text” (code) section into memory and replace with it the one “.text” section in corresponding library already loaded in memory. With this, malware destroys all installed inline hooks of AV and set breakpoints of debugger if any. So the AV solution will be blind from the user-space (ring 3) perspective.

    We can see function “Map_dll_restore_text_section” in the picture below:

    Back to the main function “C2_Client_MAIN”, “http_dropbox_authenticate” function is responsible for decoding strings related to authenticate the C2_Client on Dropbox service. It uses hardcoded token for authentication and if the token is still valid (not expired/revoked) it will receive another temporary token for further communication with Dropbox.

    One probably unintentional bug in code (function “http_dropbox_authenticate”) there is possibility that code will try to set persistence and continue in further communication (with wrong string content interpreting as bearer access token) even if authentication is not successful. This is caused by obtaining authentication response fulfilling certain format condition as explained in the picture below:

    Decoded strings of function “http_dropbox_authenticate” can be seen in the picture below and contains information like HTTP User-Agent, HTTP Host name (api.dropbox.com), URL path, Basic authorization HTTP header and mainly the Token itself.

    We can also see that before the code reach the part of setting persistence (after authentication) it obtains current logged-in username (in NameSamCompatible format) calculates MD5 hash of it and converts it to hexstring. This hexadecimal string of Username MD5 is very important because it is later used to decrypt downloaded payload from Dropbox before execution.

    According to usage of Username MD5 hexstring which is used for downloaded payload decryption, we can assume how C2 Dropbox server (serving payload to Dropbox) operates “per-victim” and is using infected currently logged-in Username MD5 hexstring for “per-victim” payload encryption. The expected functionality of infrastructure according to C2 Dropbox client code is in the picture below:

    Function “set_persistance” is spawning new process to open “blank.pdf” file. After that it starts to copy files “NV.exe”, “AcroSup64.dll” and “vcruntime140.dll” into the “%USERPROFILE%\AppData\Roaming\AdobeAcroSup” directory and sets persistence via ordinary auto-start location for current user “run” registry “HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Run” with value name “Adobe AcroSup” and value data pointing to “%USERPROFILE%\AppData\Roaming\ AdobeAcroSup\NV.exe”.

    Function “C2_Client_MAIN” continue execution and after “set_persistance” function it gets currently logged-in Username and Computername and creates string from it in format “Computername::Username”. In next step, this string is xored with hardcoded value “ME3.99.5UUUUUUUUUUUUUUUUUUUUUUUUUUUU” (which looks very similar to original LAME MP3 encoder header) as in the picture below.

    In next step, it calculates MD5 hash from string “Computername::Username”, converts it to hexstring format and uses it to create filename for uploading to Dropbox “Rock_ComputerNameUsernameMD5HashHexstring.mp3” – registering Client to C2 Dropbox Server (ex. “Rock_70a1e27ba30dd415155e68409d512a2d.mp3”).

    Next function “pre_process_body_add_mp3header_xorkey” is preparing body content of “Rock_ComputerNameUsernameMD5HashHexstring.mp3” to upload. The body content contains xored “Computername::Username”, xor key “ME3.99.5UUUUUUUUUUUUUUUUUUUUUUUUUUUU” and to avoid detection - fictive MP3 header is added to the start of body content. The example structure of this body content is in the picture below:

    This body is uploaded by function “http_dropbox_upload”:

    Decoded strings from function “http_dropbox_upload” (ex. HTTP User-Agent, HTTP Host “content.dropboxapi.com”, URL Path “/2/files/upload”) can be seen in the picture below:

    The next step is preparing filename to download from Dropbox. This file is uploaded to Dropbox by C2 Dropbox Server. Filename to download is in format “Rock_ComputerNameUsernameMD5HashHexstring.mp3.backup” (ex. “Rock_70a1e27ba30dd415155e68409d512a2d.mp3.backup”) so the same as filename which was uploaded by Client but with “.backup” added.

    Function responsible for downloading payload with filename “Rock_ComputerNameUsernameMD5HashHexstring.mp3.backup” is “http_dropbox_download”. Decoded strings of function “http_dropbox_download” (ex. HTTP User-Agent, HTTP Host “content.dropboxapi.com”, URL Path “/2/files/download”) can be seen in the picture below:

    Function responsible for processing downloaded payload is “process_exec_downloaded_payload”. Before stepping into this function we can see some first structure checks of obtained payload which will later help to recreate example structure of delivered payload.

    Function “process_exec_downloaded_payload” is responsible for processing downloaded payload, decrypting it with xor key “Username MD5 hash hexstring” (ex. "70c29c906cfa19759fa4776ea7c0973e") and creating new thread to execute it.

    First what we can see is xor decryption of downloaded payload which avoids processing first 21 bytes and last 36 bytes. Xoring starts with 22. byte of downloaded content and ends (content_length -57 +21). According to this, we can assume example of the downloaded payload format (“X” – unknown, “PAYLOAD_CODE_ENCRYPTED” – encrypted code with unknown length which will be later executed) as in the picture below:

    In next step, this function is allocating enough executable memory for decrypted code. After this, syscalls “NtWriteVirtualMemory” and “NtCreateThreadEx” are resolved in similar manner as syscalls before via “resolve_syscall” function using already created table named “hashed_syscalls_table”. This table is used as lookup table to find specific syscall number for routine.

    Syscall “NtWriteVirtualMemory” is used to to write decrypted code to newly allocated executable memory. Syscall “NtCreateThreadEx” is used to create new thread in suspended state with flags set also to hide from debugger.

    Decoy start routine “RtlNewSecurityObjectWithMultipleInheritance” of newly created thread is replaced with setting the thread context of this thread – specifically via setting RCX register (NOT RIP as this new suspended thread is not initiated yet) pointing to decrypted code, already written to executable memory. Again this combination of directly called syscalls and thread execution hijacking serves as AV evasion and anti-debug technique. RCX is the first argument to function “RtlUserThreadStart” (thread start location) and this argument sets new thread entry routine (downloaded, decrypted code) different than the decoy.

    After the downloaded and decrypted payload is executed in new thread, execution in current thread comes back to the main function “C2_Client_MAIN”.

    Another uploading to Dropbox is processed. This uploading is overwriting the same filename which was downloaded “Rock_ComputerNameUsernameMD5HashHexstring.mp3.backup” (ex. “Rock_70a1e27ba30dd415155e68409d512a2d.mp3.backup”).

    This serves probably to confirm execution of downloaded code. The content for Dropbox uploading which will be overwriting filename - “Rock_ComputerNameUsernameMD5HashHexstring.mp3.backup” is created again with fictive MP3 header, padding and “ME3.99.5UUUUUUUUUUUUUUUUUUUUUUUUUUUU” string which was previously used as xor key. Structure of this content can be seen in the picture bellow:

    All the main functionality of function “C2_Client_MAIN” - (without function “Map_dll_restore_text_section” – performed only once) is executed in endless loop when after each loop the execution sleeps for 5.5 minutes.

  3. Conclusion

    APT29 C2-Client Dropbox Loader is abusing many advanced techniques for AV evasion, anti-debug and network detection.

    Techniques used: DLL hijacking, main process module filename check, thread execution hijacking, decoy start routine of newly created thread, hidden thread creation, dynamic syscall numbers resolving via hashing (“SysWhispers2”), direct syscall calling via stub code, unhooking via replacing “.text” section of in memory modules for manually mapped ones, fictive “MP3” header in network content, string encoding and network content encryption.

    It abuses legitimate “Dropbox” service which acts as middleman between C2 Dropbox client and C2 Dropbox server communication. C2 Dropbox server operates “per-victim” and encrypts code to be executed by C2 Dropbox client with “per-victim” key.

    Token for Dropbox authentication was not valid anymore during the analysis so the next stage payload could not be downloaded. We can assume that similar payload as Cobalt Strike beacon would be downloaded.

  4. Indicators of compromise (IOCs)

    Malicious:

    ==================================================
    Filename: AcroSup64.dll
    MD5: b3b1c5acf3da24e08a655e976309b181
    SHA1: 156fcc4008f2fc3034634c3a620b80727d3f3c95
    SHA-256: 6618a8b55181b1309dc897d57f9c7264e0c07398615a46c2d901dd1aa6b9a6d6
    File Size: 130,560
    Extension: dll
    ==================================================

    ==================================================
    Filename: Meeting Info.lnk
    MD5: 5a4a54eaec3e383f57df3adb61bec68c
    SHA1: dea84f0c4a5a1a30c5740010ff09941be5fb172b
    SHA-256: 244c101f10b722b352faa1160fce05f4e19a2d840b70ef054da26de7dbb0a9da
    File Size: 1,538
    Extension: lnk
    ==================================================

    ==================================================
    Filename: vcruntime140.dll
    MD5: 60e11cc61bc2eeee039f7aa98f96676c
    SHA1: b078c8a1a04c297983a148bae0ec3aa76c7a81fa
    SHA-256: 2028c7deaf1c2a46f3ebbf7bbdf76781d84f9321107d65d9b9dd958e3c88ef5a
    File Size: 88,064
    Extension: dll
    ==================================================

    Benign:

    ==================================================
    Filename: blank.pdf
    MD5: 1c32d785398e3a7eaab0e9b876903cc6
    SHA1: 3dad168e79bc7f421760c98a8b6be2e1630a63ec
    SHA-256: 0622971147486e1900037eff229d921d14f5b51aac7171729b2b66f81cdf6585
    File Size: 4,911
    Extension: pdf
    ==================================================

    ==================================================
    Filename: NV.exe
    MD5: bcb225e7f9a3fc81429de70f7b124a02
    SHA1: dedca09d9a97f719a970883eeaa570434f9ecaba
    SHA-256: e8e63f7cf6c25fb3b93aa55d5745393a34e2a98c5aeacbc42f1362ddf64eb0da
    File Size: 184,544
    Extension: exe
    ==================================================