[Z2A] Custom sample 1 challenge write-up

Posted: July 22, 2020 in My Tutorials, [Z2A] Custom sample 1 challenge write-up
Tags: , ,

Challenge requirements:

1. Static Analysis

Throw the sample to PortEx Analyzer, this tool analyses file and focus on malformation characteristics. I get the results:

Resource (.rsrc) section has high entropy (7.99), so may be the sample is packed:

This sample is PE32 with ASLR enabled (can quickly disable this feature by using setdllcharacteristics):

Some anomalies were identified by PortEx:

  • Load libraries/functions dynamically by using LoadLibraryA & GetProcAddress
  • Doing something with file
  • Resource data has big size

2. Advanced static & dynamic analysis

2.1. Decrypt strings

Load sample into IDA, will see the sub function (sub_401300) that is used to decrypt the encrypted strings:

Diving into this function, after analyzing the entire code, I realized that it is rot13 algorithm using custom alphabets “abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890./=“.

Searching and rewriting the above decrypt function in Python, here is the result I got after trying to decode one of strings:

After decrypt the entire strings, I get the following result:

encrypted string: F5gG8e514pbag5kg ---> decrypted string: SetThreadContext
encrypted string: .5ea5/QPY4// ---> decrypted string: kernel32.dll
encrypted string: pe51g5Ceb35ffn ---> decrypted string: CreateProcessA
encrypted string: I9egh1/n//b3rk ---> decrypted string: VirtualAllocEx
encrypted string: E5fh=5G8e514 ---> decrypted string: ResumeThread
encrypted string: Je9g5Ceb35ffz5=bel ---> decrypted string: WriteProcessMemory
encrypted string: I9egh1/n//b3 ---> decrypted string: VirtualAlloc
encrypted string: E514Ceb35ffz5=bel ---> decrypted string: ReadProcessMemory
encrypted string: t5gG8e514pbag5kg ---> decrypted string: GetThreadContext
encrypted string: .5ea5/QPY4// ---> decrypted string: kernel32.dll
encrypted string: F9m5b6E5fbhe35 ---> decrypted string: SizeofResource
encrypted string: s9a4E5fbhe35n ---> decrypted string: FindResourceA
encrypted string: I9egh1/n//b3 ---> decrypted string: VirtualAlloc
encrypted string: yb3.E5fbhe35 ---> decrypted string: LockResource
encrypted string: yb14E5fbhe35 ---> decrypted string: LoadResource

2.2. Decrypt new payload

With the above decrypted strings, malicious code will:

  • Call FindResourceA, LoadResource, SizeofResource, LockResource APIs to find and retrieve resource data. Resource size is 0x1541C.
  • Call malloc to allocate memory with size is 0x1541C+0x1C.
  • Calculate new region size by retrieve dword at [ptr_resdata+8] and multiply with 0xA. The region size is 0x00002200 * 0xA = 0x00015400.
  • Call VirtualAlloc to allocate memory in the address space of process with size of the region, in bytes is 0x00015400.
  • Call memmove to copy resource data at offset (ptr_resdata + 0x1C) to new allocated region.
  • Then using a loop like RC4 algorithm to decrypt all the encrypted data. If the decryption succeeds, the decrypted payload is passed to sub_401000:

For later analysis, I dump this payload to disk:

2.3. Spawn and inject payload

sub_401000 performs the task of injecting new decrypted payload.

  • First, call GetModuleFileNameA to retrieve the fully qualified path of sample. Then call CreateProcessA to create a new process and its primary thread in SUSPENDED state.
  • Call GetThreadContext to retrieve the context of the new created thread. Call VirtualAllocEx to allocate new EXECUTE_READWRITE region in SUSPENDED process, then write the decrypted payload into the new allocated memory.
  • Finally, set EAX in CONTEXT structure point to the payload’s entry-point. Call SetThreadContext, ResumeThread for resuming the suspended, so the payload will execute.

Note: can patch 0xEB 0xFE at the entry point of injected payload in allocated memory for attaching and continue debug by another debugger instance.

3. Analyse injected payload

3.1. Dynamic resolve APIs

First, it retrieves process name and calculates CRC32, then compares with pre-calculated CRC32 (0B925C42Dh) of svchost.exe.

If not equal, we’ll move to another code branch. Here we will see the malicious code performing the task of getting API addresses based on the pre-calculated hashes.

According to the above picture, the f_get_api_func_by_hash function will get library information based on the index passed to the function (0: “kernel32.dll”; 1: “ntdll.dll”; 2: “wininet.dll”). Then, retrieves exported functions of that library and calculate CRC32. If matches the pre-calculated hash, it will return the API name and use GetProcAddress to get the address of an exported function.

With the help of IDA python, i can create enum for those pre-calculated hashes:

3.2. Detect blacklist processes

Next, it calls sub_00401000 (f_find_running_proc_based_on_crc32). This sub resolves CreateToolhelp32Snapshot, Process32FirstW, Process32NextW APIs and uses these APIs for enumerating processes. Then it builds CRC32 table, calculate CRC32 hash of process name and compare with pre-calculated hashes.

Pre-calculated CRC32Process Name

If it detects the processes listed in the above table, the malicious code will exit.

3.3. Inject and run thread inside svchost process

If not discovered the processes in blacklist, it will spawn a new svchost.exe process in SUSPENDED state.

Next, malware gets its base address, calls VirtualAlloc function for allocating new RW memory region inside its process, copies itself to the newly created memory. Then, it calls VirtualAllocEx function for allocating new memory region (RWX) inside svchost process, do relocate based on relocation table info. Finally, calls WriteProcessMemory for writing payload into the allocated memory section inside svchost process and calls CreateRemoteThread to create a thread (sub_401DC0) that runs in the virtual address space of svchost process.

3.4. Download payload and execute

sub_401DC0 will resolve APIs of wininet.dll library for connecting to internet and decrypt the URL. The URL after decrypt is: https://pastebin%5B.%5Dcom/raw/mLem9DGk

Then it calls sub_00401290 (f_download_payload_from_C2(void *lpszUrl)) for downloading the new payload form C2 with fake user_agent is “cruloader“:

I try to use wget command to download payload from C2 and view the file content, get another URL:

Keep using wget to download the file PNG-02-Copy.png, get the image with big dimensions: 8267 x 4650.

I think this challenge is not simple and ends soon because the image link is passed to the final function at sub_4013A0. This function calls f_download_payload_from_C2 once again to download and read the content of image to allocated memory. It resolves GetTempPathW, CreateDirectoryW, CreateFileW, WriteFile functions, creates cruloader folder at %TEMP%, then create output.jpg file at that folder and fill the content of downloaded image into output.jpg.

Next, it decrypts encrypted string to “redaolurc” and uses a loop to search for the position of this string in the image file.

The content bellows “redaolurc” string has lots of repeated 0x61 values, so i guess the xor_key is 0x61. After locate bytes bellow the redaolurc string, the malicious code uses a loop to decode these bytes into a new PE payload.

Once again, svchost.exe process is created in a SUSPENDED state. Then, call sub_00401750 (BOOL __cdecl f_inject_final_payload_into_svchost(HANDLE hsvchost)) for injecting the final payload into the allocated memory within the svchost process and call ResumeThread function to execute payload.

4. Analyse final payload

The final payload performs the task of displaying a message “Uh Oh, Hacked!!”, “FUD 1337 Cruloader Payload Test. Don’t upload to VT”.



Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.