Interesting FormBook Crypter - unconventional way to store encrypted data Published: 2020-11-05 · Archived: 2026-04-02 11:20:56 UTC 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. https://tccontre.blogspot.com/2020/11/interesting-formbook-crypter.html Page 1 of 11 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. https://tccontre.blogspot.com/2020/11/interesting-formbook-crypter.html Page 2 of 11 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: https://tccontre.blogspot.com/2020/11/interesting-formbook-crypter.html Page 3 of 11 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. https://tccontre.blogspot.com/2020/11/interesting-formbook-crypter.html Page 4 of 11 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. https://tccontre.blogspot.com/2020/11/interesting-formbook-crypter.html Page 5 of 11 figure 5: decrypting FORMBOOK  FORMBOOK MZ HEADER:   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. https://tccontre.blogspot.com/2020/11/interesting-formbook-crypter.html Page 6 of 11 figure 7.A: initial opcode it tries to grab and opcode it skip https://tccontre.blogspot.com/2020/11/interesting-formbook-crypter.html Page 7 of 11 figure 7.B: FormBook opcode condition for parsing its data https://tccontre.blogspot.com/2020/11/interesting-formbook-crypter.html Page 8 of 11 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); https://tccontre.blogspot.com/2020/11/interesting-formbook-crypter.html Page 9 of 11 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); } tag 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 } https://tccontre.blogspot.com/2020/11/interesting-formbook-crypter.html Page 10 of 11 $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 $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 $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 E condition: ($mz at 0) and ($shell at 0) or ($opcode_check) } tag Source: https://tccontre.blogspot.com/2020/11/interesting-formbook-crypter.html https://tccontre.blogspot.com/2020/11/interesting-formbook-crypter.html Page 11 of 11