# FORMBOOK ## In-depth malware analysis ----- ## ~/$ whoami ### Rémi Jullian #### Malware Analyst at Stormshield (1+ year) Previously Intrusion Detection Engineer at ANSSI (4 years) Interested in reverse-engineering, vulnerability exploitation, threat- intelligence, software developement, ... @netsecurity1  https://blog.remijullian.fr ----- ## Agenda #### Formbook overview Anti-analysis tricks Code injection and process hollowing Userland hooks Keylogger Password harvesting C&C Network protocol ----- ## Formbook overview ----- ### Form-grabber / password-stealer #### Target 92 different applications Inject code in targeted applications in order to: Intercept network requests Implement a key-logger Harvest users' application passwords Take screenshots Execute C&C commands ----- ### g pp #### Web-Browsers Mail clients, FTP clients, IM apps ----- ### Malware As A Service #### Ready-to-use malware sold/rent directly by the developer Used to be sold on hackforums[.]net by 'ng-Coder' There is no builder available Customers get their own .exe and web-based panel access ----- ----- ----- ## Anti-analysis tricks ----- ### Strings obfuscation and encryption #### Stack-strings obfuscation Strings encryption schema ----- ### Strings hashing #### Formbook uses the BZip2 CRC32 hash function #### Hashes are used to: Perform dynamic import function by hash Check for blacklisted running processes Check for blacklisted loaded modules by module path by module name Check for blacklisted usernames Check for targeted applications 10 0xbf0a5e41 LdrLoadDll 11 0x2902d074 KiFastSystemCal 12 0xf653b199 NtCreateProcess .. 79 0x3ebe9086 vmwareuser.exe 80 0x4c6fddb5 vmwareservice.ex .. 99 0x6484bcb5 \cuckoo\ 100 0x11fc2f72 \sandcastle\ .. 106 0xed297eae cuckoo 107 0xa88492a6 sandbox.. 113 0xb4e1ae2 ntdll.dll 114 0x24a48dcf guard32.dll 115 0xe11da208 SbieDll.dll .. .. 120 0x9e01fc32 iexplore.exe 121 0x216500c2 firefox.exe 10 0xbf0a5e41 LdrLoadDll 11 0x2902d074 KiFastSystemCal 12 0xf653b199 NtCreateProcess .. 79 0x3ebe9086 vmwareuser.exe 80 0x4c6fddb5 vmwareservice.ex .. 99 0x6484bcb5 \cuckoo\ 100 0x11fc2f72 \sandcastle\ .. 106 0xed297eae cuckoo 107 0xa88492a6 sandbox.. 113 0xb4e1ae2 ntdll.dll 114 0x24a48dcf guard32.dll 115 0xe11da208 SbieDll.dll .. .. 120 0x9e01fc32 iexplore.exe 121 0x216500c2 firefox.exe #### List of hashes and related strings  ----- ### Strings hashes recovering #### We wrote a python module named MalwareHash  from malware_hash import MalwareHash import binascii mh = MalwareHash(binascii.crc32) # user-defined hash func string_list = mh.get_strings_by_hash(0x77ae10f7) print(string_list) # ['u'wireshark.exe] .. "dump_files.net":[ "a.exe", "a0380mon.exe", "a1dashboard_launcher.exe", "a1dashboard_service.exe", "a1diagnose.exe", "a2adguard.exe", .. ], #### hash_sources.json files_net.json We also used FireEye's shellcode_hashes plugin .. "sandbox_tools":[ "python.exe", "py.exe", "perl.exe", "ruby.exe", "joeboxserver.exe", "joeboxcontrol.exe" ], .. ----- ### Data encryption #### Formbook uses 'encrypted buffers' stored in the .text section ----- ### Data encryption #### 2 decryption functions Example of encrypted buffers BZip2 CRC32 hashes' array Array of various strings Array of PE images file name The C&C server's URI x86 and x64 instructions ----- ### Manually mapping of NTDLL #### Ntdll exposes the native API used to call system services It is frequently monitored by security solutions Cuckoo sandbox monitors function calls with inline hooks Malware analysts set breakpoints on ntdll.dll related functions Formbook manually maps its own copy of ntdll.dll ----- ### Manually mapping of NTDLL #### Disassembly of NtAdjustPrivilegesToken (WOW64) #### ntdll.dll loaded by the Windows loader #### ntdll.dll manually loaded by Formbook ----- ### Manually mapping of NTDLL #### ntdll.dll loaded by the Windows loader BaseAddr EndAddr+1 RgnSize Type State Protect -----------------------------------------------------------------------77c30000 77c31000 1000 MEM_IMAGE MEM_COMMIT PAGE_READONLY 77c31000 77c40000 f000 MEM_IMAGE MEM_RESERVE 77c40000 77d16000 d6000 MEM_IMAGE MEM_COMMIT PAGE_EXECUTE_READ 77d16000 77d20000 a000 MEM_IMAGE MEM_RESERVE 77d20000 77d21000 1000 MEM_IMAGE MEM_COMMIT PAGE_EXECUTE_READ 77d21000 77d30000 f000 MEM_IMAGE MEM_RESERVE 77d30000 77d31000 1000 MEM_IMAGE MEM_COMMIT PAGE_READWRITE 77d31000 77d32000 1000 MEM_IMAGE MEM_COMMIT PAGE_READONLY 77d32000 77d33000 1000 MEM_IMAGE MEM_COMMIT PAGE_READWRITE 77d33000 77d34000 1000 MEM_IMAGE MEM_COMMIT PAGE_WRITECOPY 77d34000 77d39000 5000 MEM_IMAGE MEM_COMMIT PAGE_READWRITE 77d39000 77d40000 7000 MEM_IMAGE MEM_RESERVE 77d40000 77d97000 57000 MEM_IMAGE MEM_COMMIT PAGE_READONLY 77d97000 77da0000 9000 MEM_IMAGE MEM_RESERVE 77da0000 77da5000 5000 MEM_IMAGE MEM_COMMIT PAGE_READONLY 77da5000 77db0000 b000 MEM_IMAGE MEM_RESERVE #### ntdll.dll manually loaded by formbook BaseAddr EndAddr+1 RgnSize Type State Protect -----------------------------------------------------------------------77c30000 77c31000 1000 MEM_IMAGE MEM_COMMIT PAGE_READONLY 77c31000 77c40000 f000 MEM_IMAGE MEM_RESERVE 77c40000 77d16000 d6000 MEM_IMAGE MEM_COMMIT PAGE_EXECUTE_READ 77d16000 77d20000 a000 MEM_IMAGE MEM_RESERVE 77d20000 77d21000 1000 MEM_IMAGE MEM_COMMIT PAGE_EXECUTE_READ 77d21000 77d30000 f000 MEM_IMAGE MEM_RESERVE 77d30000 77d31000 1000 MEM_IMAGE MEM_COMMIT PAGE_READWRITE 77d31000 77d32000 1000 MEM_IMAGE MEM_COMMIT PAGE_READONLY 77d32000 77d33000 1000 MEM_IMAGE MEM_COMMIT PAGE_READWRITE 77d33000 77d34000 1000 MEM_IMAGE MEM_COMMIT PAGE_WRITECOPY 77d34000 77d39000 5000 MEM_IMAGE MEM_COMMIT PAGE_READWRITE 77d39000 77d40000 7000 MEM_IMAGE MEM_RESERVE 77d40000 77d97000 57000 MEM_IMAGE MEM_COMMIT PAGE_READONLY 77d97000 77da0000 9000 MEM_IMAGE MEM_RESERVE 77da0000 77da5000 5000 MEM_IMAGE MEM_COMMIT PAGE_READONLY 77da5000 77db0000 b000 MEM_IMAGE MEM_RESERVE BaseAddr EndAddr+1 RgnSize Type State Protect -----------------------------------------------------------------------00800000 00b03000 303000 MEM PRIVATE MEM COMMIT PAGE EXECUTE READWRITE BaseAddr EndAddr+1 RgnSize Type State Protect ------------------------------------------------------------------------ 00800000 00b03000 303000 MEM PRIVATE MEM COMMIT PAGE EXECUTE READWRITE ----- ### Loading additional DLLs #### Empty Import Directory Table Likely suggest dynamic function importing ----- ### Dynamic function importing #### Formbook can import functions by Name Function ordinal Function name's hash (BZip2 CRC32) ----- ### WOW64 (Windows 32 bit On Windows 64 bit) #### In WOW64 mode, Windows loads 2 versions of ntdll.dll 32-bits from %windir%\SysWOW64\ 64-bits from %windir%\System32\ ntdll.dll - 32 bits (in WOW64) ntdll.dll - 64 bits 0:002> u ntdll!NtCreateFile ntdll!ZwCreateFile: 77c500a4 mov eax,52h 77c500a9 xor ecx,ecx 77c500ab lea edx,[esp+4] ; fs:[0xc0] points to TEB.WOW32Reserved 77c500af call dword ptr fs:[0C0h] 77c500b6 add esp,4 77c500b9 ret 2Ch ----- ### Check for WOW32Reserved hook #### Without Wow32Reserved hook With Wow32Reserved hook :000> dt ntdll!_TEB WOW32Reserved @$teb 0:000> dt ntdll!_TEB WOW32Reserved @$teb ; Points to wow64cpu.dll (64-bit DLL) ; Points on a dynamically allocated block +0x0c0 WOW32Reserved : 0x74362320 Void +0x0c0 WOW32Reserved : 0x73c72320 Void :000> u 0x74362320 L1 0:000> u 0x73c72320 L1 ; Switch from x86 to x64 mode (Heaven Gate) ; Jmp on a dynamically allocated block of me 74362320 ea1e2736743300 jmp 0033:7436271E 73c72320 e9ebdc320b jmp 7efa0010 #### Formbook checks if WOW32Reserved points to a 64-bit DLL OllyDbg Stealth64 plugin uses Wow32Reserved hooks [VB-2009-05] Use ntdll!NtQueryVirtualMemory to get the base address Check if a 64-bit DLL is mapped at the base address 0:000> dt ntdll!_TEB WOW32Reserved @$teb ; Points to wow64cpu.dll (64-bit DLL) +0x0c0 WOW32Reserved : 0x74362320 Void 0:000> dt ntdll!_TEB WOW32Reserved @$teb ; Points on a dynamically allocated block +0x0c0 WOW32Reserved : 0x73c72320 Void ----- ### Check for a debugger #### ntdll!NtQuerySystemInformation SystemKernelDebuggerInformation Ring-0 debugger ProcessDebugPort Ring-3 debugger #### Reading the PEB typedef struct _PEB { BYTE Reserved1[2]; BYTE BeingDebugged; BYTE Reserved2[1]; PVOID Reserved3[2]; PPEB_LDR_DATA Ldr; .. .. } PEB, *PPEB; ----- ### Check for inline hooks ----- ### Checking anti analysis tests results #### 1. WOW32 Reserved hook 2. Software debugger 3. Kernel debugger 4. Blacklisted base file name 5. Blacklisted username 6. Blacklisted username 7. Blacklisted loaded module path 8. Blacklisted loaded module path 9. Blacklisted running process 10. Blacklisted running process 11. Blacklisted loaded DLL ----- ## Code injection and process hollowing ----- ### Process hollowing overview #### Used to migrate to a Windows like process Formbook code is mapped in explorer.exe APC injection or thread hijacking targets explorer.exe explorer.exe creates a new (suspended) process Formbook migrates to this process ----- #### Process hollowing schema 7. Patch process entry point instructions and resume process NtResumeThread() **3. CreateProcessInternalW()** **4. ret instruction to saved CONTEXT.Eip** **5. NtReadVirtualMemory()** **6. NtOpenProcess(), NtMapViewOfSection()** **7. NtOpenThread(), NtResumeThread()** ----- ### Process hollowing summary #### Formbook is now looking like a geniune Microsoft process It's original process has exited explorer.exe now contains formbook's code (dead code) New formbook process can now inject targeted applications ----- ### Targeted processes injection overview #### Formbook code is mapped in targeted processes Targeted processes main thread is hijacked Inline userland hooks are setup during hijacked thread execution No new thread created ! ----- 4. Restore firefox's saved **Targeted process** **1. NtOpenProcess(), NtCreateSection(), NtMapViewOfSection()** **2. NtOpenThread(), NtSuspendThread(), NtGetThreadContext(), NtSetThreadContext(),** NtResumeThread() **3. NtProtectVirtualMemory()** **4. ret instruction to saved CONTEXT.Eip** ----- ## Userland hooks ----- ### What's a userland hook ? #### Mechanism used to hijack the control flow of targeted functions Each targeted function has its own detour function Targeted functions parameters can be read (and modified) Interesting targets for formbook: Encryption functions Networking functions Keyboard input related functions Formbook uses inline userland hooks ----- #### Override the first bytes of targeted functions with a call 32-bits - call near 64-bits - mov rax, imm64; call rax Must handle targeted architecture specifications x86 and x64 instructions length are variable Calling convention changes between x86 and x64 Function's prologue may differ even on the same architecture WSASend - x86 PR_Write - x86 WS2_32!WSASend: nss3!PR_Write: 8bff mov edi,edi 55 push ebp push ebp 8bec mov ebp,esp 8bec mov ebp,esp 8b4508 mov eax,dword ptr [ebp+8] #### WSASend - x64 PR_Write - x64 WS2_32!WSASend: 8bff mov edi,edi 55 push ebp 8bec mov ebp,esp WS2_32!WSASend: 48895c2408 mov qword ptr [rsp+8],rbx 48896c2410 mov qword ptr [rsp+10h],rbp nss3!PR_Write: 55 push ebp 8bec mov ebp,esp 8b4508 mov eax,dword ptr [ebp+8] nss3!PR_Write: 488b01 mov rax,qword ptr [rcx]; 48ff6018 jmp qword ptr [rax+18h] nss3!PR_Write: 488b01 mov rax,qword ptr [rcx]; 48ff6018 jmp qword ptr [rax+18h] ----- ### How inline userland hooks are setup? #### 1. Retreive the virtual address of the targeted function 2. Disassemble the targeted function prologue 3. Save the instructions altered by the hook 4. Write the trampoline at the end of the detour function 5. Write the call to the detour function ----- **nss3.dll** **_PR_Write:_** E8 F7 D2 E4 A5 | call formbook_detour_func 4E | dec esi FF 75 10 | push dword ptr ss:[ebp+10] .. .. C3 | retn 4 **Formbook section** **_formbook_hook_PR_Write_2:_** 90 | nop 50 | push eax 8B C4 | mov eax, esp 60 | pusha ; save registers 50 | push eax E8 11 A1 FE FF | call formbook_hook_PR_Write_3 83 C4 04 | add esp, 4 61 | popa ; restore registers 58 | pop eax 83 C4 04 | add esp, 4 C3 | retn .. .. **_formbook_hook_PR_Write_1:_** 68 88 88 88 88 | push 0x88888888; patched value E9 4B E1 FF FF | jmp formbook_hook_PR_Write_2 C3 | retn .. .. **_formbook_detour_func:_** 83 C4 04 | add esp, 4 E8 7B 03 FF FF | call formbook_hook_PR_Write_1 55 | push ebp 8B EC | mov ebp, esp 8B 45 08 | mov eax, dword ptr ss:[ebp+8] 46 | inc esi 68 25 E1 EE | push nss.PR_Write+5 trampoline C3 | t 2 saved instructions ----- ### Web-browsers targeted functions #### DLL Function Browser Pre-encryption secur32.dll EncryptMessage Yes #### wininet.dll HttpSendRequestA HttpSendRequestW InternetQueryOptionW #### Yes #### nspr4.dll PR_Write Yes nss3.dll PR_Write Yes ws2_32.dll WSASend No ----- ### Detour functions goals #### Extract credentials from intercepted network requests Search authentication keywords within hooked functions' buffer Web-browsers Mail clients, FTP clients, IM apps ['pass', 'token', 'email', 'login', 'signin', ['user', 'pass', 'auth', 'login'] 'account', 'persistent'] #### The entire buffer containing credentials is sent to the C&C server Extract web-browser's User-Agent value for furtive C&C requests ['pass', 'token', 'email', 'login', 'signin', 'account', 'persistent'] ----- ## Keylogger ----- ### Windows Messaging System #### Messages from the window can be retreived with: GetMessage (blocking) PeekMessage (non-blocking) ----- ### Key-Logger implementation #### All targeted applications are beeing key-logged Functions hooked typedef struct tagMSG { HWND hwnd; UINT message; #### GetMessage WPARAM wParam; LPARAM lParam; #### PeekMessage DWORD time; POINT pt; #### SendMessage DWORD lPrivate; } MSG, *PMSG, *NPMSG, *LPMSG; #### Messages filtered by detour function WM_KEYDOWN WM_SYSKEYDOWN WM_LBUTTONDOWN WM_RBUTTONDOWN typedef struct tagMSG { HWND hwnd; UINT message; // The message identifier WPARAM wParam; // The virtual-key code LPARAM lParam; DWORD time; POINT pt; DWORD lPrivate; } MSG, *PMSG, *NPMSG, *LPMSG; ----- ### Virtual-key to character translation #### Custom virtual-key translation Virtual-Key Character Printable string 0x1b Escape Key [Esc] 0x12 Alt key [Alt] 0x09 Tab Key [Tab] 0x0d Enter key [Enter] 0x08 Backspace key [<-Del] Non-special characters ToUnicode() ----- Writes keystrokes to shared memory area Formbook's thread running in explorer's process |Col1|Same section mapped in all targeted processes and explorer's process|Col3| |---|---|---| **Explorer process** ----- ### Grabbing clipboard data #### A window uses the clipboard when cutting, copying, or pasting data Mouse clicks events are used to trigger clipboard data extraction WM_LBUTTONDOWN WM_RBUTTONDOWN ----- ### Key-logger and Clipboard data file #### Keylogger file Clipboard file Temporary stored in %APPDATA% %APPDATA%\Roaming\PREFIX{8}\PREFIX{3}log.ini %APPDATA%\Roaming\PREFIX{8}\PREFIX{3}logc.ini #### PREFIX matches regexp [a-zA-Z0-9] Derived from the username and C&C server %APPDATA%\Roaming\PREFIX{8}\PREFIX{3}log.ini %APPDATA%\Roaming\PREFIX{8}\PREFIX{3}logc.ini ----- ## Password harvesting ----- ### Password harvesting #### Extract password saved on the filesystem #### Firefox Internet Explorer Chrome Opera Thunderbird Outlook Windows Vault SELECT encryptedUsername, encryptedPassword,\ formSubmitURL FROM moz_login #### Sqlite query targeting Firefox SELECT origin_url, username_value,\ password_value FROM logins #### Sqlite query targeting Chrome SELECT encryptedUsername, encryptedPassword,\ formSubmitURL FROM moz_login #### Browser-dumpwd project  SELECT origin_url, username_value,\ password_value FROM logins ----- ## C&C Network Protocol ----- ### C&C network protocol overview #### Formbook communicates with its C&C using HTTP requests The C&C server is implemented as a PHP web-application HTTP requests are "hand made" using low-level socket API Beaconing requests (GET) are used to pull C&C commands Exfiltration requests (POST) are used to send stolen data Data is encrypted using RC-4 Key is SHA-1(http.host + http.base_uri) A formbook PCAP can be decrypted without sample \o/ ----- ### Beaconing requests #### Send by formbook's thread running within explorer's process GET parameter value after base 64 decode and decryption FBNG:C1EACBB43.8:Windows 7 Enterprise x64:YWRtaW4xMjM0 #### FBNG: 4-bytes magic header C1EACBB4: CRC32 checksum of the user’s SID 3.8: Formbook version Windows 7 Enterprise x64: Operating system YWRtaW4xMjM0: base64 encoded username ----- ### C&C commands #### Specified within HTTP replies to beaconing requests Server replies 200 OK only if a task has been added with the panel C&C command in HTTP reply C&C command menu ----- ### Data exfiltration requests #### Type of exfiltrated data Intercepted network requests Password recoveries Keylogged data Clipboard data Screenshots POST parameter value after base 64 decode and decryption dat=[TRUNC]LNSqnAQI6omSmS~2P0[TRUNC]&un=Ym9tYmVybWFu&br=9 #### dat: base 64 encoded and RC-4 encrypted payload un: base 64 encoded username br: Type of exfiltrated data / Browser id ----- ### Fake C&C servers #### Used to hide the real C&C server during sandbox analysis Randomly selected from the list of encrypted strings Reached as much as the real C&C server ----- ----- ## Conclusion #### Formbook is widely spread Easily accessible by cyber-criminals Uses a lot of anti-analysis tricks Implements interesting code injection techniques Can steal users' data using various mechanisms ----- ## References #### Previous work D. Schwarz, The formidable formbook formgrabber - 09/2017 N. Villeneuve, R. Eitzman, S. Nemes, and T. Dean, Significant formbook distribution campaigns impacting the u.s. and south korea 10/2017 #### IDA Python script / Formbook PCAP decoder ####  https://github.com/ThisIsSecurity/malware/tree/master/formbook Formbook sample (3.8) Original sample Unpacked version -----