Disclaimer

Monday, February 22, 2021

Gh0stRat Anti-Debugging : Nested SEH (try - catch) to Decrypt and Load its Payload

 SEH tricks is not a new Anti-Debugging trick. So many malware already used this to make the manual debugging of its code time consuming and confusing. Today I will share how Gh0strat malware make use of nested SEH exception (try{} catch) as anti-debugging trick to hide its decryption routine.

This article is not to tackle the full C++ Exception Internals, but to share how IDAPRO really helps me in analyzing this type of anti-debugging tricks statically. :)

So lets start!!!

SEH:

Structure Exception handler (SEH) is one of the classic Anti-debugging tricks used by malware. where it tries to abuse the mechanism provided by operating system in managing exceptional situation like reference to a non-existence address pointer or execution of code in a read-only page.

This is done usually  by locating the pointer to SEH linked list in the stack known to be the SEH frame. The current SEH frame address is located in 0x00 offset relative to the FS (x32 bit) or GS selection (x64 bit).

figure 1: FS[0] of x32 bit OS

figure 2: The EXCEPTION_REGISTRATION_RECORD in FS[0]

When the exception is triggered, control is transfer to the current SEH handler where it will return one of the _EXCEPTION_DISPOSITION members.

In this Gh0strat variant it used nested SEH (try{} catch{}) that serve as anti-debugging tricks to make the debugging more confusing or let say more time consuming if analyst didn't notice the SEH.

Gh0srat: Nested SEH to decrypt its payload:

The sample we will use here contains a big data section where the encrypted gh0strat payload located. we will notice that using DIE tool or PE-bear that visualized the size of each section with quite high entropy same as text section.

figure 3: high entropy of data section

we all know there are so many faster way to bypassed this anti-debugging technique like monitoring the TIB offset 0x0 dynamically for next SEH or dumping process. In our case I will just want to share how IDA PRO will help you a lot in this case in traversing "FuncInfo" structure since IDAPRO resolved most of this SEH structure.

when you try to load the sample in debugger and breakpoint on some API let say, you may encounter some exception error shown in figure below. This is also a good hint that it may use SEH technique. 

figure 4: exception during debugging

by further checking its code using IDAPRO I notice that it uses nested SEH. yes a nested try{} catch{} exception handler to decrypt its payload. at the entry point of the malware code you will notice right away the first exception handler function registered to FS:0. Exception will be trigger by calling "call    __CxxThrowException" API. 

figure 5: first SEH in malware entrypoint

ehFuncInfo or the exception handler function registered in FS:0 contains some structure that may help us to figure out statically which exception handler function may be call upon the exception is trigger.

I really recommend to read this great presentation of hexblog regarding the Exception and RTTI:
https://www.hexblog.com/wp-content/uploads/2012/06/Recon-2012-Skochinsky-Compiler-Internals.pdf

The ehFuncInfo is a object structure that may lead you to the "AddressOfHandler" which is a address or a function address that will handle the exception encounter of the current thread.

IDAPRO really did a good job to give you some hint how to traverse that structure and lead you the said structure member of HandlerType. FuncInfo structure contains several member so I will just focus on the member that helps me to decrypt the payload.

Below is a simple structure starting from "FuncInfo" that may help you to look for the AddressOfHandler field member of HandlerType structure. 

figure 6: Traversing AddressOfhandler


The figure 6 shows that FuncInfo structure contains TryBlockMap field. this field is another structure object that contains HandlerArray field structure that holds the AddressOfHandler field. so to make use of this structure in our sample lets try to traverse the first SEH in malware entry point.

figure 7: Traversing the AddressOfHandler of SEH in malware entry point


We saw that the possible Address that will handle the exception is in 0x40243d. It works in dynamically test I did with x64dbg where I put break point on this address after the exception then press skip exception shift+f9.

figure 8: AddressOfHandler was triggered

if we follow the call function 0x402200 pushing string address "Shellex" as a parameter. you will notice again that it use another SEH to execute piece of its code. Not like the first SEH, this SEH contains 9 tryblock and HandlerOfAddress like the figure below.

figure 9: multiple try Block Map

Parsing ehFuncInfo structure Using Ida python:

In this case I decided to use IdaPython to parse all the FrameHandler ehFuncInfo structure to locate all AddressOfHandler field available for all tryBlockMap entries and add it as a code reference comment in its IDB. This approach help me to figure out where the decryption routine and learn multi line comment in idapython :).

the script is available here:


figure 10A: before running the script

figure 10B: IDB after running the script
































now with this comment we can verify all possible AddressOfHandler in each tryBlockMap entry to locate the decryption routine. Like the figure above, the first AddressOfHandler isa function waiting for the decryption key, size of the encrypted payload and the address of the encrypted payload.

figure 11: decryption routine


and once you decrypt the payload using this simple xor decryption routine. you can see right away some note worthy string of gh0strat like keylogging, creating services, regrun, download files, backdoor and etc.

figure 12: strings upon decryption

Conclusion:

In this article we just focus on some basic internals of SEH frameHandler and how to look for all possible HandlerOfAddress that may executed upon the trigger of registered SEH. we also learned how IDAPRO did a really good job in giving you all the needed structure for try block entries where you can use IDApython to make your static analysis more easier. :)

IOC:

yara:

import "pe"

rule gh0st_rat_loader {
    meta:
        author =  "tcontre"
        description = "detecting gh0strat_loader"
        date =  "2021-02-22"
sha256 = "70ac339c41eb7a3f868736f98afa311674da61ae12164042e44d6e641338ff1f"

    strings:
        $mz = { 4d 5a }

        $code = { 40 33 FF 89 45 E8 57 8A 04 10 8A 14 0E 32 D0 88 14 0E FF 15 ?? ?? ?? ?? 8B C6 B9 ?? 00 00 00 }
        $str1 = "Shellex"
        $str2 = "VirtualProtect"
       
    
    condition:
        ($mz at 0) and $code and all of ($str*)

    }
    
rule gh0st_rat_payload {
    meta:
        author =  "tcontre"
        description = "detecting gh0strat_payload in memory without MZ header in memory"
        date =  "2021-02-22"
sha256 = "edffd5fc8eb86e2b20dd44e0482b97f74666edc2ec52966be19a6fe43358a5db"

    strings:
    $dos = "DOS mode"
    $av_str1 = "f-secure.exe"
    $av_str2 = "Mcshield.exe"
    $av_str3 = "Sunbelt"
    $av_str4 = "baiduSafeTray.exe"
    
    $clsid = "{4D36E972-E325-11CE-BFC1-08002BE10318}"
    $s1 = "[WIN]"
    $s2 = "[Print Screen]"
    $s3 = "Shellex"
    $s4 = "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"
    $s5 = "%s\\%d.bak"

    
    condition:
        ($dos at 0x6c) and 2 of ($av_str*) and 4 of ($s*) and $clsid

    }
    

References:
https://www.hexblog.com/wp-content/uploads/2012/06/Recon-2012-Skochinsky-Compiler-Internals.pdf

Monday, January 18, 2021

Extracting Shellcode in ICEID .PNG Steganography

 In this past few days I stumble to some new and old variant of ICEID malware that uses .png steganography to hide and execute its encrypted shellcode. In this article I will share how the structure of the Iceid png payload look like and how to extract its encrypted shellcode.

Loader Compression:

same as the other malware, IceID Loader changes its Crypter to execute its main module in memory. From old variant where the encrypted code stub and decryption module is place in the RSRC section as a data .rsrc entry (RC4 encrypted) to applib compression like the figure below.


figure 1: The aplib decompressed module of ICEID

PNG Header:

Before we deal with the ICEID PNG steganography, I think it is a good idea to have some preview what PNG file header format is. It will give as a clear preview how ICEID parse the .PNG header and look for its encrypted shellcode.

The PNG file format started with 8-bytes signature header "89 50 4e 47 0d 0a 1a 0a". after this header is a chunk structure or series of chunk structures that contains either a "critical chunks" like "IHDR", "IDAT" and etc... or "Ancillary chunks" that may contain some attribute related to the color, pixel or metadata of the png file like "sRGB", "gAMA" and many more.

each PNG chunks layout consist of 4 parts or 4 structure member. the figure below show the 4 parts in IHDR chunk type.


figure 2: PNG File header Format

ICEID PNG Module Decryptor:

Now that we have some insight how PNG file format look like, lets dive in to the ICEID PNG decryptor module ("let's call it PNG module") that we already extracted earlier in the memory. This part is really interesting especially in parsing the header. :)

The PNG module start by executing a thread that will do the following:
1. decrypt its data section (C&C url link) using same approach how it decrypt the shellcode in PNG payload file.
2. it will check the existence of the PNG file in %appdata%<randomname>/, if not
3.  it will try to download it to its C&C server
4. then it will parse and check the png file to extract and execute its shellcode.

The first task is decrypting the C&C server URL link that are place in data section that are encrypted in RC4 algorithm. the structure of data it used in decrypting this data section can be seen before a call  function that will do the decryption part.


figure 3: Encrypted Data Structure


The first 8 bytes of the encrypted data section is the RC4 key and the rest is the encrypted data.

figure 4: decrypting C&C server URL link

Next it will create a random name folder in %appdata% using the "username" of the infected machine. 
with the use of RDTSC command to generate random character. If the module didn't find the png payload in the said folder it will try to contact the C&C server to download it.

figure 5: looking for the PNG payload file

Parsing PNG Header:

after reading the PNG and save it in the memory, it will start the checking in offset 0x8 (skipping the PNG header) which is the "chunk_data_length" of the first chunk type in the header which in our case is "IHDR". The way how it parse the header to look for "IDAT" chunk_type structure is by adding:

next_chunk_type_struct = size(chunk_data) + chunk_data_length (4 bytes) + chunk_type (4byes) + chunk_crc32 (4 bytes)

except for the start chunk_type structure where you need to include or add the PNG header size which 8 bytes.

for this topic, I created a simple python script that will parse this header and give you the basic information about the header. it also parse the chunk_data but I place it in the debug.log of this script.


figure 6: parsing the header


Byte Flag and Decryption Key:

as soon as it found the IDAT chunk_type structure it will check first if the chunk_data_length > 5 then it will skip the chunk_data_length , chunk_type and chunk_crc32 by adding 0x0c to the current pointer of the "IDAT" chunk header. the byte in this position looks like a validity flag of the PNG. If this byte is zero, the PNG module will check another value which is one of the parameter to the function that parse the png header which is also zero, so in this case it will exit the flag. 
figure 7: byte flag



after this byte is the 8 byte RC4 decryption key followed by the encrypted shellcode using this RC4 key. the python script I mentioned earlier will parse the RC4 key, extract the shellcode and check the shellcode header and entrypoint by dis-assembling it using capstone python library.

figure 8: script tool parser

Conclusion:

In this analysis we learned how PNG file can be used as a weapon to hide the malicious code and how malware keeps on updating their tools to bypassed detection.

Also thanks to the community for sharing the samples :)

Samples:

sha1: 9a07f8513844e7d3f96c99024fffe6e891338424
sha1: 1ab6006621c354649217a011cd7ca8eb357c3db4
sha1: c1faa9cb4aa7779028008375e7932051ee786a52
sha1: 481bc0cbdcae1cd40b70b93388bf4086781b44b4

https://www.virustotal.com/gui/file/45520a22cdf580f091ae46c45be318c3bb4d3e41d161ba8326a2e29f30c025d4/details

https://www.virustotal.com/gui/file/e6e0adcc94c3c4979ea1659c7125a11aa7cdabe24a36f63bfe1f2aeee2c5d3a1/detection

https://www.virustotal.com/gui/file/cc1030c4c7486f5295444acb205fa9c9947ad41427b6b181d74e7e5fe4e6f8a9/details

https://www.virustotal.com/gui/file/f6ea81aaf9a07e24a82b07254a8ed4fcf63d5a8e6ea7b57062f4c5baf9ef8bf2/detection

References:

https://en.wikipedia.org/wiki/Portable_Network_Graphics
http://www.libpng.org/pub/png/spec/1.2/PNG-Structure.html
https://blog.malwarebytes.com/threat-analysis/2019/12/new-version-of-icedid-trojan-uses-steganographic-payloads/
https://www.malware-traffic-analysis.net/2020/12/11/index.html



Thursday, November 5, 2020

Interesting FormBook Crypter - unconventional way to store encrypted data

This FORMBOOK CRYPTER loader contain a lot of interesting feature to bypassed sandbox, obfuscate its code and many more. It also show a unique way to store and parse its encrypted data to execute. 

so let's start :).

FORMBOOK CRYPTER LOADER (ANTI-VM):

After decrypting some shellcode in the memory it will use several technique to check if its code is running in a virtual machine or not. The screenshot below show 3 techniques it use.
 
  • ANTI-VM I : it use the cpuid with EAX=0x40000000 as input to determined the hypervisor brandname to check if it is running in a virtualize environment
  • ANTI-VM II:  use cpuid with EAX=1 as an input to check the 31st bit of its return value in ECX if set or not. if it is set then it is in VM.
  • ANTI-VM III: check the existence of some known driver component of the virtual machine. for this example it checks the existence of the vmmouse driver in the machine.

figure 1: Different ANTI-VM technique checks


FORMBOOK CRYPTER LOADER (ANTI-SANDBOX):

 It also has some feature to check if its code is running in a sandbox by using the 2 technique shown below.
  • ANTI-SANDBOX 1 : check the file path of its running code using GetModuleFileName API if it contains "sample", "sandox" or "malware". if yes exit the process
  • ANTI-SANDBOX 2: checks the existence of the sbiedll.dll that are component of known sandbox.
figure 2: Anti-Sandbox technique

FORMBOOK CRYPTER LOADER (PROCESS CHECK):

It also enumerate all the process running to the machine and try to check the existence of known debugging tools process if it is exist, if yes exit the process. For AV related process and services, it tries to create a counter how many AV product it saw in the machine max of 2 (it seems like it checks for a testing machine that contain several AV product on it).

below is the list of the process it checks related to malware analysis tools and AV product:

figure 3: Process checking to evade malware lab environment

DECRYPTING THE FORMBOOK IN RSRC:

The next thing it will do is to decrypt the encrypted Formbook malware in its resource section. It is done by looking to 2 entry in rsrc section. The first entry is with rsrc ID "14d" with rsrc type of 17 "RT_DLGINCLUDE" that contain the 16 bytes rc4 key to decryp the rc4 key to decrypt the FORMBOOK.
 
figure 4: decrypting the rc4 key for FORMBOOK
 
 
Once the Rc4 key was parse, it will decrypt the encrypted formbook malware, it will load another resource entry with rsrc id "3e8" type "2". Then it will remove 3 dummy bytes to the data blob before decrypting it using rc4 algorithm.
 
figure 5: decrypting FORMBOOK

 FORMBOOK MZ HEADER:

one of the interesting part of this formbook variant is that the MZ header is used as shellcode to jump to entrypoint of the executable. this technique is also seen in cobaltstrike variant show in my previous blog . https://tccontre.blogspot.com/2019/11/cobaltstrike-beacondll-your-not.html
 
 
figure 6: MZ header shellcode

INTERESTING STORING AND PARSING ENCRYPTED DATA:

The Formbook obfuscate its code. One interesting feature of this is how it store and parse its needed bytes to decrypt or to hash to perform its task. Malware commonly used "stack string technique" to initialized its string or data in stack or in an allocated memory space like the screenshot we saw in anti-vm and anti-sandbox headings of this post. 

But for this variant it used another technique where it save its needed bytes in a code like structure, then it will parse each instruction to check its opcode if it will passed its requirements, if yes it will parse the operand or opcode that is part of its needed bytes to decrypt or to hash.
 
requirement:
  I. if opcode is 0x40-0x5f just grab the opcode itself.
 II. if opcode is 0x70-0x7f which is mostly a conditional jump mnemonics then skip that instruction.
III. (if opcode - 0x40 > 0x1f) and (opcode - 0x70 > 0x0f) then it will check what opcode is that (opcode range from 0x00 to 0xFF) to know what other opcode or how big is the operand it will parsed.

figure 7.A: initial opcode it tries to grab and opcode it skip

figure 7.B: FormBook opcode condition for parsing its data


figure 8: the parse stored data that either to be decrypt or hash it.

And also not all stored data that it will parse to its code will be decrypted, some of those stored data is designed to compute sha1 hash that will serve as the decryption key (rc4 algortihm) to decrypt another blob of code.

 _BYTE *__cdecl Func_DecryptBytesGrabbed(int DestBuff)
{
  int VA_41C3A6; // eax
  int VA_41C50B; // eax
  int VA_41BEF1; // eax
  char dest_buff; // [esp+Ch] [ebp-140h] BYREF
  char v6[215]; // [esp+Dh] [ebp-13Fh] BYREF
  _DWORD sha1_ctx[26]; // [esp+E4h] [ebp-68h] BYREF

  dest_buff = 0;
  Func_MemSet(v6, 0, 0xD4u);
  VA_41C3A6 = sub_41C3A1();
  Func_GrabEncryptedData(&dest_buff, VA_41C3A6 + 2, 0xD3u);
  VA_41C50B = sub_41C506();
  Func_GrabEncryptedData(DestBuff + 0x444, VA_41C50B + 2, 0x2F0u);
  VA_41BEF1 = sub_41BEEC();
  Func_GrabEncryptedData(DestBuff + 0x7B8, VA_41BEF1 + 2, 0x14u);
  Func_SHA1_Init(sha1_ctx);
  Func_Sha1_Update(sha1_ctx, &dest_buff, 0xD3);
  Func_Sha1_Final(sha1_ctx);
  Func_GrabNeededOpcode(DestBuff + 0x7A4, sha1_ctx, 20);
  Func_DecryptWithRc4((DestBuff + 0x444), 0x2F0u, DestBuff + 0x7A4);
  Func_SHA1_Init(sha1_ctx);
  Func_Sha1_Update(sha1_ctx, (DestBuff + 0x7B8), 0x14);
  Func_Sha1_Final(sha1_ctx);
  Func_DecryptWithRc4((DestBuff + 0x444), 0x2F0u, sha1_ctx);
  Func_SHA1_Init(sha1_ctx);
  Func_Sha1_Update(sha1_ctx, (DestBuff + 0x444), 752);
  Func_Sha1_Final(sha1_ctx);
  return Func_DecryptWithRc4((DestBuff + 0x7B8), 0x14u, sha1_ctx);
}

SAMPLES:

filename: Formbook_loader.bin
md5: 65880d23eb6051a1604707371ebb6d2c
sha1: 3f5d0833adbd39715f1d45f1a3c8982c52519bc1
sha256: ac2e9615b368e00fb4bf4d5180bbfc0d6fb7bbce3fa1af603d346d7a8f2450e5
 
 

filename: formbook.bin
md5: df93eecd1799f9c9c674b8cdb2f1dad1
sha1: e66c893f39c7553f59a5381d23a5c65e5c2e84f7
sha256: 5d7eba73b4d29ee17529511bb8b0745e658bf2adfcae57bdfa8d0870f4732a18

YARA RULES:

 import "pe"

rule formbook_loader_crypter {
    meta:
        author =  "tcontre"
        description = "detecting formbook-loader-crypter malware"
        date =  "2020-11-05"
        sha256 = "ac2e9615b368e00fb4bf4d5180bbfc0d6fb7bbce3fa1af603d346d7a8f2450e5"

    strings:
        $mz = { 4d 5a }
 
        $dec = { 03 CE 8A 03 88 45 F9 8B C6 51 B9 03 00 00 00 33 D2 F7 F1 59 85 D2 75 14 8A 45 F9 32 45 FA 88 01 8A 55 FB 8B C1 E8 39 01 00 00 EB 05 8A 45 F9 88}
        $rc4_key = {12 2D 13 EF 23 E2 7F 4B 70 19 C7 F0 4B 68 75 50}
     
    condition:
        ($mz at 0) and ($dec ) or ($rc4_key)
 
    }
    
rule formbook_crypter {
    meta:
        author =  "tcontre"
        description = "detecting formbook-crypter malware"
        date =  "2020-11-05"
        sha256 = "5d7eba73b4d29ee17529511bb8b0745e658bf2adfcae57bdfa8d0870f4732a18"

    strings:
        $mz = { 4d 5a }
 
        $shell = { 4D 5A 45 52 E8 00 00 00 00 58 83 E8 09 8B C8 83 C0 3C 8B 00 03 C1 83 C0 28 03 08 FF E1 90 00 00}
                $opcode_check = {8B 4D FC 8A 04 39 03 CF 88 45 F4 8D 50 C0 80 FA 1F 77 18 6A 01 51 8D 04 1E 50 E8 ?? ?? ?? ?? 46 83 C4 0C FF 45 FC 89 75 F8 EB 25 2C 70 3C 0F 77 }
     
    condition:
        ($mz at 0) and ($shell at 0) or ($opcode_check)
 
    }

    
    
    

 

Gh0stRat Anti-Debugging : Nested SEH (try - catch) to Decrypt and Load its Payload

 SEH tricks is not a new Anti-Debugging trick. So many malware already used this to make the manual debugging of its code time consuming and...