Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

eSinerji Mühendislik - Teklif talebi - Elektrik malzemeleri (Part 2)

Continuing from part 1, I extracted the injected byte array with the following recipe:

Regular_expression('User defined','\\$payloadData = \\(([0-9,]+)\\)',false,false,false,false,false,false,'List capture groups')
From_Decimal('Comma',false)

The resulting payload is a 32-bit MSVC executable with only a .text section and high entropy, indicating compression or encryption.

Dynamic Analysis

First, I analysed the sample in a FLARE-VM sandbox, using WireShark to capture the C2 traffic.

After running it multiple times on a clean snapshot, I observed it attempting to communicate with over 50 different domains, some of which were clearly decoys. This behaviour appears consistent with the Formbook/XLoader malware families which blend requests towards the C2 server with up to 64 different decoy domains. Some of the domains were inactive at the time of the analysis and I wasn’t able to identify the real C2 server.

The sample sends both GET and POST requests with encrypted and base64-encoded data. The requests have the below headers, as well as “Origin” and “Referer” headers matching the URL.

NameValue
Accepttext/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed‑exchange;v=b3;q=0.7
Accept‑Encodinggzip, deflate
Accept‑Languageen-US
Cache‑Controlno-cache
Connectionclose
User‑AgentMozilla/5.0 (GNU/linux S.O.; rv:38.0) Gecko/20100101 Firefox/38.0

The user agent imitates an old Mozilla Firefox browser (version 38.0) running on Linux.

Additionally, the malware copied the Microsoft Edge “Web Data” SQLite database which contains autofill, address, and credit card data to the temporary file “%TEMP%\1U7G2-Ix5”.

No persistence artifacts were observed during the dynamic analysis.

Static Analysis

For the static analysis, I used Ghidra and enlisted the assistance of ChatGPT to break the encryption, after providing it with the exported program listing, decompiled C code, and Intel Hex dump.

First Stage

The malware defines seven functions, with the entry point being on offset 0x004026A0.

entry

The entry point builds a large state structure on the stack and repeatedly calls FUN_00401090, changing a single byte selector before each call.

; ...
0040270b c7857dffffff00bc90cb    MOV  dword ptr [EBP + local_87],0xcb90bc00
00402715 89852dfcffff            MOV  dword ptr [EBP + local_3d7],EAX
0040271b c785d9fcffffc03b5440    MOV  dword ptr [EBP + local_32b],0x40543bc0
00402725 c785ddfbffffe90cc81a    MOV  dword ptr [EBP + local_427],0x1ac80ce9
0040272f c745d5f9000000          MOV  dword ptr [EBP + local_2f],0xf9
00402736 e855e9ffff              CALL FUN_00401090
0040273b c745d588000000          MOV  dword ptr [EBP + local_2f],0x88
00402742 e849e9ffff              CALL FUN_00401090
00402747 c745d559000000          MOV  dword ptr [EBP + local_2f],0x59
0040274e e83de9ffff              CALL FUN_00401090
00402753 c745d5ed000000          MOV  dword ptr [EBP + local_2f],0xed
0040275a e831e9ffff              CALL FUN_00401090
; ...

FUN_00402600

size_t __cdecl FUN_00402600(const char *param_1)

This function is equivalent to the standard strlen function.

FUN_00402620

size_t __cdecl FUN_00402620(const wchar_t *param_1)

This function is equivalent to the standard wcslen function.

FUN_00402640

void __cdecl FUN_00402640(void *param_1, const void *param_2, size_t param_3)

This function is equivalent to the standard memcpy function.

FUN_00402670

void *__cdecl FUN_00402670(void *param_1, int param_2, size_t param_3)

This function is equivalent to the standard memset function.

FUN_00401000

void __cdecl FUN_00401000(uintptr_t *param_1)

The function writes a hardcoded buffer of 62 bytes to the given address.

; ...
0040100b c745c01bc5a2cd    MOV dword ptr [EBP + local_44],0xcda2c51b
00401012 c745c4a242890b    MOV dword ptr [EBP + local_40],0xb8942a2
00401019 c745c8b24e4e4e    MOV dword ptr [EBP + local_3c],0x4e4e4eb2
00401020 c745cc4e890bb6    MOV dword ptr [EBP + local_38],0xb60b894e
00401027 c745d0dc054e4e    MOV dword ptr [EBP + local_34],0x4e4e05dc
0040102e c745d4890bba4e    MOV dword ptr [EBP + local_30],0x4eba0b89
00401035 c745d84e4e4ec5    MOV dword ptr [EBP + local_2c],0xc54e4e4e
0040103c c745dc0bb2750b    MOV dword ptr [EBP + local_28],0xb75b20b
00401043 c745e0b6335ac5    MOV dword ptr [EBP + local_24],0xc55a33b6
0040104a c745e403ba4d03    MOV dword ptr [EBP + local_20],0x34dba03
00401051 c745e8b2c703ba    MOV dword ptr [EBP + local_1c],0xba03c7b2
00401058 c745ecc51bb2cd    MOV dword ptr [EBP + local_18],0xcdb21bc5
0040105f c745f08c44c71b    MOV dword ptr [EBP + local_14],0x1bc7448c
00401066 c745f4b2a5aa7d    MOV dword ptr [EBP + local_10],0x7daaa5b2
0040106d c745f88ec5ab13    MOV dword ptr [EBP + local_c],0x13abc58e
00401074 66c745fc8d00      MOV word ptr [EBP + local_8],0x8d
0040107a c645fe00          MOV byte ptr [EBP + local_6],0x0
; ...

In little endian, the function produces the following buffer:

1B C5 A2 CD A2 42 89 0B B2 4E 4E 4E 4E 89 0B B6
DC 05 4E 4E 89 0B BA 4E 4E 4E 4E C5 0B B2 75 0B
B6 33 5A C5 03 BA 4D 03 B2 C7 03 BA C5 1B B2 CD
8C 44 C7 1B B2 A5 AA 7D 8E C5 AB 13 8D 00

FUN_00401090

This function implements is the main dispatcher of the first stage. Rather than receiving the state structure as a parameter, it searches the caller’s stack for the marker 0x40543BC0 and combines the selector with 0xCB90BC00 to choose the appropriate branch.

SelectorOperation
0x88Obtains a pointer into the current image
0x59Stores the image size
0xEDRecovers the original image base
0x49Materialises an encrypted record
0x5CDerives a 20-byte key
0x5A, 0xAD, 0x01, 0x8FImplement the RC4 processing
0xBC, 0x29, 0x44Walk the TEB/PEB loader structures to locate a DLL
0x7A, 0xEFParse a PE export table and resolve an API
0xB3Builds the temporary stub from FUN_00401000
0x05Executes the stub and decrypts the encrypted chunks
0x24Transfers execution to the recovered stage

Second Stage

The dispatcher first decrypts the complete 273408-byte packed stage with RC4 using the key “1D6A657F0236D3F98130C3D42FA90E164AF87EEA”. It then divides the buffer into 40 chunks and resets RC4 for every chunk using the key “9DCDD799A4C218B5F133FE98CE50CA0D2470444C”.

The recovered stage still contains encrypted functions, which are decrypted at runtime with a custom transform that combines RC4 with forward and backward adjacent-byte addition or subtraction.

Walking the PEB

The malware does not import any libraries but instead resolves functions by walking the Process Environment Block (PEB) via the Thread Environment Block (TEB)1. On 32-bit Windows, FS:[0x18] gives the address of the current TEB and the PEB pointer is then read from offset 0x30 of the TEB structure.

; ...
004020c3 64a118000000    MOV EAX,FS:[0x18]
004020c9 8b4030          MOV EAX,dword ptr [EAX + 0x30]
; ...

From the PEB, the malware accesses the loader data at offset 0x0C and walks the InLoadOrderModuleList at another offset of 0x0C. This list contains an LDR_DATA_TABLE_ENTRY for each loaded DLL. It can then search the entries for a library such as “ntdll.dll”, retrieve its base address, and manually parse its PE export table to resolve the native API functions it needs (e.g., “NtAllocateVirtualMemory”).

Registration

The registration data contains the branch marker “XLNG:”, an eight-character bot ID, the version marker “8.9:”, the operating system, and a Base64-encoded victim ID:

XLNG:23BDFD508.9:Windows 10 Enterprise N x64:REVTS1RPUC00NzdRVDRBLWZsYXJl

The final field decodes to “DESKTOP-477QT4A-flare”, the hostname and username of the sandbox. Before transmission, the plaintext is RC4-encrypted, base64-encoded, and prefixed with “PKT2:”.2

Encryption

The second stage uses a custom reversible transform around RC4. Mode 0x7A performs two adjacent-byte subtraction passes, RC4, and then repeats the subtraction passes, while mode 0x66 uses addition and reverses the operation.3 The registration RC4 key recovered from this sample is “1E603A71E25C3A00BCA282C931545AC3839253F3”.

Junk Code Stub

The temporary stub written by FUN_00401000 is decoded by XORing its first 61 bytes with 0x4E with the NULL byte being padding.

From_Hex('Space')
Take_bytes(0,61,false)
XOR({'option':'Hex','string':'0x4E'},'Standard',false)
To_Hex('Space',0)
Disassemble_x86('32','Full x86 architecture','16','0',true,true)

The resulting shellcode is a sum computation loop with 1935 iterations that always returns 0. It is executed from the base of each encrypted chunk and replaced with the original bytes before RC4 processing.

00000000 55                PUSH EBP
00000001 8BEC              MOV EBP,ESP
00000003 83EC0C            SUB ESP,0000000C
00000006 C745FC00000000    MOV DWORD PTR [EBP-04],00000000
0000000D C745F8924B0000    MOV DWORD PTR [EBP-08],00004B92
00000014 C745F400000000    MOV DWORD PTR [EBP-0C],00000000
0000001B 8B45FC            MOV EAX,DWORD PTR [EBP-04]
0000001E 3B45F8            CMP EAX,DWORD PTR [EBP-08]
00000021 7D14              JGE 00000037
00000023 8B4DF4            MOV ECX,DWORD PTR [EBP-0C]
00000026 034DFC            ADD ECX,DWORD PTR [EBP-04]
00000029 894DF4            MOV DWORD PTR [EBP-0C],ECX
0000002C 8B55FC            MOV EDX,DWORD PTR [EBP-04]
0000002F 83C20A            ADD EDX,0000000A
00000032 8955FC            MOV DWORD PTR [EBP-04],EDX
00000035 EBE4              JMP 0000001B
00000037 33C0              XOR EAX,EAX
00000039 8BE5              MOV ESP,EBP
0000003B 5D                POP EBP
0000003C C3                RET

TCPSVCS Injection

The next runtime is injected into a newly created TCPSVCS.EXE process from SysWOW64. The malware creates the process suspended, creates a section, maps views of that section locally and into the target, and redirects the suspended process to the mapped runtime before resuming it.4

C2 Configuration

The configuration contains 64 indexed hostname/path records. Each record stores a base64 seed and is decrypted with two passes of the custom transform.5

For index n, the first key is derived by XORing the byte value of n across this 20-byte base key:

0A3CA5246592AB350674F7BB794E14A24A889AB3

The second key is constant:

D31E07A4B307F70E02AC8DFE64381712466D1F47

An additional hostname (“www.memecheat.shop”) is encrypted separately with its own seed and key pair. Older XLoader versions treated the separately encrypted hostname as the real C2, but the larger list can also contain working C2 servers and modern versions deliberately mix real and decoy traffic6, with XLoader 8.9 in particular often not using this hostname as the real C27.

Browser Database Staging

The browser collector builds the file path “%TEMP%\1U7G2-Ix5” and uses it as a temporary SQLite staging file for Chromium browser data. The source browser database is read into memory and written to this path before SQLite queries are executed. The filename is reused and its contents depend on which browser collector wrote it most recently.

Data Exfiltration

For each profile, the malware calculates K1 = SHA1(hostname + path) and derives K2 by processing the following network seed with the custom transform using K1: “9C87A9CB85178BEA4A96824B32AB4DC6C3372C03”.

A GET registration parameter can be base64-decoded and decrypted using RC4 with K2 and K1. Removing the PKT2: prefix, base64-decoding the remainder, and applying the registration RC4 key reveals the XLNG: registration string.

POST exfiltration uses an inner form with parameters “dat” (data), “un” (victim ID), and “br” (hardcoded as “9”). The “dat” value is RC4-encrypted with K1 and K2, base64-encoded, and has the characters +, /, and = replaced with -, _, and ..

The complete inner form is then encrypted again with K1 and K2, base64-encoded, and placed under a random outer parameter name. The decrypted values from the dynamic analysis network capture contained clipboard data, browser autofill and recovery data, and browser cookies.

For example, the CyberChef recipe below can be used to decrypt a payload with the associated keys:

  • K1: 6B53C74E2A05B61CD662EA45B1A466AB9E459756
  • K2: B933BF7C09392013D12E323B543E25052318F1DD
RC4({'option':'Hex','string':'6B53C74E2A05B61CD662EA45B1A466AB9E459756'},'Base64','Latin1')
RC4({'option':'Hex','string':'B933BF7C09392013D12E323B543E25052318F1DD'},'Latin1','Latin1')
Regular_expression('User defined','dat=([^&]+)',false,false,false,false,false,false,'List capture groups')
From_Base64('A-Za-z0-9\\-_.',true,false)
RC4({'option':'Hex','string':'6B53C74E2A05B61CD662EA45B1A466AB9E459756'},'Latin1','Latin1')
RC4({'option':'Hex','string':'B933BF7C09392013D12E323B543E25052318F1DD'},'Latin1','UTF16LE')

The result in this case is the following decrypted payload, containing clipboard data:

Clipboard

Program Manager

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run

Persistence

The decrypted strings contain the following registry run keys:

  • \SOFTWARE\Microsoft\Windows\CurrentVersion\Run
  • \SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\Run

The malware resolves NtCreateKey and NtSetValueKey and writes a REG_SZ value under the user or machine hive. It generates a pseudorandom name for the key and the value points to the its installed executable path.

Although no persistence artifact was observed during the dynamic analysis, the persistence capability is present and may be activated after initial communication with the C2 server has been established.

Summary

The final payload is a 32-bit XLoader 8.9 infostealer that uses multiple layers of encryption and obfuscation before transferring execution to its main stage. It avoids relying on a conventional import table by walking the TEB and PEB to locate loaded modules such as “ntdll.dll” and manually resolve the native APIs it requires.

The malware subsequently injects itself into a suspended “TCPSVCS.EXE” process and continues execution from the injected process. During execution, it decrypts a configuration containing multiple C2 or decoy domains and associated URL paths, and communicates over HTTP using encrypted and base64-encoded GET and POST parameters.

Indicators of Compromise

TypeValueLinksComment
Domainwww.2226vip15.comVirusTotalC2/decoy
Domainwww.29870342.xyzVirusTotalC2/decoy
Domainwww.45si.comVirusTotalC2/decoy
Domainwww.464656235.xyzVirusTotalC2/decoy
Domainwww.55rii.comVirusTotalC2/decoy
Domainwww.56781924.xyzVirusTotalC2/decoy
Domainwww.abbyandbenjamin.comVirusTotalC2/decoy
Domainwww.arrow-life.netVirusTotalC2/decoy
Domainwww.axiasolarestimate.comVirusTotalC2/decoy
Domainwww.canal-plus.comVirusTotalC2/decoy
Domainwww.ccn4jab.makeupVirusTotalC2/decoy
Domainwww.christelbriereaymon.chVirusTotalC2/decoy
Domainwww.claimbtc.comVirusTotalC2/decoy
Domainwww.codetrendforge.shopVirusTotalC2/decoy
Domainwww.depict-continue.ruVirusTotalC2/decoy
Domainwww.dodosantoss.spaceVirusTotalC2/decoy
Domainwww.duolingo.comVirusTotalC2/decoy
Domainwww.edmclaw.comVirusTotalC2/decoy
Domainwww.farmasi-mx.comVirusTotalC2/decoy
Domainwww.garycooperofficial.comVirusTotalC2/decoy
Domainwww.google.com.auVirusTotalC2/decoy
Domainwww.hikikagami.comVirusTotalC2/decoy
Domainwww.kaverimetalalloys.comVirusTotalC2/decoy
Domainwww.kvalitnimontaze.czVirusTotalC2/decoy
Domainwww.lafabriqueapopcorn.frVirusTotalC2/decoy
Domainwww.lbrcaahm.cyouVirusTotalC2/decoy
Domainwww.macsupport-online.comVirusTotalC2/decoy
Domainwww.mdc-pixei.cyouVirusTotalC2/decoy
Domainwww.meyeube.vnVirusTotalC2/decoy
Domainwww.modulajf.czVirusTotalC2/decoy
Domainwww.morenovel.aiVirusTotalC2/decoy
Domainwww.nfld5.clickVirusTotalC2/decoy
Domainwww.omcgw.ccVirusTotalC2/decoy
Domainwww.omptrr.comVirusTotalC2/decoy
Domainwww.p201.ccVirusTotalC2/decoy
Domainwww.p207.ccVirusTotalC2/decoy
Domainwww.postimees.eeVirusTotalC2/decoy
Domainwww.qyfg180.comVirusTotalC2/decoy
Domainwww.qz8ueo0.cnVirusTotalC2/decoy
Domainwww.rk88gone.siteVirusTotalC2/decoy
Domainwww.ruvu.lifeVirusTotalC2/decoy
Domainwww.rwafrofreedom.comVirusTotalC2/decoy
Domainwww.sbeomv.comVirusTotalC2/decoy
Domainwww.scale-agency.orgVirusTotalC2/decoy
Domainwww.slabx.ukVirusTotalC2/decoy
Domainwww.soludo.topVirusTotalC2/decoy
Domainwww.sotradis.maVirusTotalC2/decoy
Domainwww.stcq8.comVirusTotalC2/decoy
Domainwww.stone-riser6.ru.comVirusTotalC2/decoy
Domainwww.stphmngm.storeVirusTotalC2/decoy
Domainwww.thestorypedia.comVirusTotalC2/decoy
Domainwww.toshiba.co.jpVirusTotalC2/decoy
Domainwww.tripgenesys.comVirusTotalC2/decoy
Domainwww.tuxhuset.onlineVirusTotalC2/decoy
Domainwww.tvguide.comVirusTotalC2/decoy
Domainwww.wes521.comVirusTotalC2/decoy
Domainwww.wildatheartromania.comVirusTotalC2/decoy
Domainwww.memecheat.shopVirusTotalC2/decoy
Domainwww.xxxread.storeVirusTotalC2/decoy
Domainwww.yogicweetershuns.funVirusTotalC2/decoy
Domainwww.yytk.wangVirusTotalC2/decoy
Domainwww.zfzzqc4.cnVirusTotalC2/decoy
Domainwww.zinosazanfaraz.comVirusTotalC2/decoy
Domainwww.znisjinak.czVirusTotalC2/decoy
Domainwww.zxlj-adguard.proVirusTotalC2/decoy

MITRE ATT&CK® Techniques


  1. The Ministry of Silly Walks Presents: Walking the PEB | by Tom O’Neill | InfoSec Write-ups

  2. Analysis of Xloader’s C2 Network Encryption | ThreatLabz

  3. Technical Analysis of Xloader’s Code Obfuscation in Version 4.3 | ThreatLabz

  4. Technical Analysis of Xloader Versions 6 and 7 P1 | ThreatLabz

  5. Xloader v8.7: Obfuscation, RC4 C2 Encryption & Commands | ThreatLabz

  6. Technical Analysis of Xloader Versions 6 and 7 P2 | ThreatLabz

  7. Chasing XLoader: Tracking a Notoriously Complex Malware Family at Scale - YouTube