← cd ../

~/labs/cases/whatsapp-web-hta-dropper

A strange WhatsApp Web file that turned into a contact-spreading dropperA suspicious HTA hides a multi-stage VBScript dropper that installs Python automation tooling and abuses WhatsApp Web to exfiltrate contacts and spread a remote file.

On February 12, 2026, I received a file from a known contact. That was the part that made it dangerous: the sender was familiar, but the filename was not. The artifact was not a photo, not a PDF, and not anything I would expect in a normal WhatsApp Web conversation. It was an HTA file named A-8dd9b4be89d585d36.hta.

I treated it as hostile and did not execute it. The goal of this analysis was to follow the routine of an analyst receiving the file cold: identify the type, observe the expected first behavior, peel back the obfuscation, reconstruct the execution chain, and understand the final impact.

Sample

File:   whats/A-8dd9b4be89d585d36.hta
Type:   HTML Application / VBScript HTA
Size:   994,809 bytes
SHA256: 5a822a163d0787bcfd52b2ae3ace6cb6a92eb158a52b0fbe3cf0380acc2cb702

I started with basic triage, without opening the file on Windows:

$ file whats/A-8dd9b4be89d585d36.hta
whats/A-8dd9b4be89d585d36.hta: HTML document, ASCII text, with very long lines (2800)

$ sha256sum whats/A-8dd9b4be89d585d36.hta
5a822a163d0787bcfd52b2ae3ace6cb6a92eb158a52b0fbe3cf0380acc2cb702  whats/A-8dd9b4be89d585d36.hta

$ wc -c whats/A-8dd9b4be89d585d36.hta
994809 whats/A-8dd9b4be89d585d36.hta

$ xxd -g 1 -l 256 whats/A-8dd9b4be89d585d36.hta
00000000: 3c 68 74 6d 6c 3e 0a 3c 68 65 61 64 3e 0a 3c 74  <html>.<head>.<t
00000010: 69 74 6c 65 3e 53 79 73 74 65 6d 20 41 75 74 6f  itle>System Auto
00000020: 6d 61 74 69 6f 6e 3c 2f 74 69 74 6c 65 3e 0a 3c  mation</title>.<
00000030: 48 54 41 3a 41 50 50 4c 49 43 41 54 49 4f 4e 20  HTA:APPLICATION 
00000040: 0a 20 20 20 20 20 41 50 50 4c 49 43 41 54 49 4f  .     APPLICATIO
00000050: 4e 4e 41 4d 45 3d 22 53 79 73 74 65 6d 20 50 72  NNAME="System Pr
00000060: 6f 63 65 73 73 22 0a 20 20 20 20 20 53 43 52 4f  ocess".     SCRO
00000070: 4c 4c 3d 22 6e 6f 22 0a 20 20 20 20 20 53 49 4e  LL="no".     SIN
00000080: 47 4c 45 49 4e 53 54 41 4e 43 45 3d 22 79 65 73  GLEINSTANCE="yes
00000090: 22 0a 20 20 20 20 20 49 4e 4e 45 52 42 4f 52 44  ".     INNERBORD
000000a0: 45 52 3d 22 6e 6f 22 0a 20 20 20 20 20 42 4f 52  ER="no".     BOR
000000b0: 44 45 52 3d 22 74 68 69 6e 22 0a 20 20 20 20 20  DER="thin".     
000000c0: 4d 41 58 49 4d 49 5a 45 42 55 54 54 4f 4e 3d 22  MAXIMIZEBUTTON="
000000d0: 6e 6f 22 0a 20 20 20 20 20 4d 49 4e 49 4d 49 5a  no".     MINIMIZ
000000e0: 45 42 55 54 54 4f 4e 3d 22 6e 6f 22 0a 20 20 20  EBUTTON="no".   
000000f0: 20 20 53 48 4f 57 49 4e 54 41 53 4b 42 41 52 3d    SHOWINTASKBAR=

The result changes how the case should be handled. On Windows, .hta is executed by mshta.exe; it is not just an HTML page. An HTA can run VBScript/JScript with local access, which makes it a classic format for phishing and malware loaders.

First read: the file tries to disappear

The header did not look like a normal user-facing application:

<title>System Automation</title>
<HTA:APPLICATION
     APPLICATIONNAME="System Process"
     SHOWINTASKBAR="no"
     WINDOWSTATE="minimize">

Sub Window_OnLoad
    On Error Resume Next
    Self.Close
End Sub

This gave me the first operational hypothesis: the attacker expects the victim to double-click a file received in a trusted chat. When the file opens, it tries not to leave a useful window: it runs minimized, does not appear in the taskbar, and closes its visible window from Window_OnLoad.

To the victim, the expected effect is mundane: “I clicked it and nothing opened.” To the attacker, that is enough. The click already handed execution to mshta.exe.

Obfuscation levels

Before discussing the final payload, it helps to separate the layers. This kind of file is confusing because it mixes social tricks, UI tricks, and code tricks.

LevelTechniqueWhat it hides
0Delivery through a known contactThe file inherits trust from the chat
1HTA with minimized window and Self.CloseThe user does not see an app running
2On Error Resume NextFailures are not shown to the user
3Empty functions and fake commentsManual reading becomes noisier
4Numeric arrays with modular subtractionReal strings do not appear in simple searches
5Chr((a-b) Xor k) expressionsAnother per-character string hiding format
6554 Layer blocksArtificial volume slows analysis
7ExecuteGlobalThe real script only exists at runtime
8A second obfuscated stageThe first deobfuscation is not the end
9Remote MSI/Python/script downloadThe first HTA does not need to carry the whole malware

The important point: this is not strong cryptography. It is a deterministic chain of simple transformations repeated many times.

Array layer: input and output

The first useful block starts like this:

' Layer 1 - Array decode
eSTozhYKiMeDheJ = "178|215|219|142|185|187|227|228|192|223|196|..."

For Each hYz6RqRS5 In Split(eSTozhYKiMeDheJ, "|")
    DX8XfEmqzNr = CInt(hYz6RqRS5)
    DX8XfEmqzNr = (DX8XfEmqzNr - 110 + 256) Mod 256
    cN6ZiOQ0QI8 = cN6ZiOQ0QI8 & Chr(DX8XfEmqzNr)
Next
g9FTeNPd0SD = g9FTeNPd0SD & cN6ZiOQ0QI8

There is nothing magical here. The script takes each number, subtracts a key, and converts the result to a character.

The formula is:

byte = (number - key + 256) % 256
char = Chr(byte)

To demonstrate without executing the HTA, I used only the first numbers from the layer:

$ nums='178|215|219|142|185|187|227|228|192|223|196'
$ key=110
$ tr '|' '\n' <<< "$nums" \
>   | awk -v k="$key" '{ printf "%c", ($1-k+256)%256 } END { print "" }'
Dim KMuvRqV

That output matters. The first layer is not already reconstructing a URL or a final command; it starts reconstructing another VBScript. The visible HTA is only a decoder that builds a second script.

XOR layer: different shape, same idea

Some layers do not use arrays. They concatenate many Chr calls:

g9FTeNPd0SD = g9FTeNPd0SD & Chr((242-49) Xor 225) &
                              Chr((237-44) Xor 225) &
                              Chr((179-11) Xor 225) & ...

The per-character operation is:

byte = (a - b) XOR key
char = Chr(byte)

A minimal example is saved as a real script in whats/analysis/decode_xor_example.py:

$ python3 whats/analysis/decode_xor_example.py
  If Len(mme

Again, this is not a complex cipher. It is arithmetic hiding text. The attacker’s defense is volume: repeat it hundreds of times.

Safe first-stage deobfuscation

To automate extraction, I wrote a small parser that looks for two patterns: numeric arrays and Chr((a-b) Xor k) sequences. It does not execute the HTA and does not call ExecuteGlobal; it only interprets text.

Usage:

$ python3 whats/analysis/decode_vbs_layers.py \
>   whats/A-8dd9b4be89d585d36.hta \
>   whats/analysis/stage1.vbs
decoded 47051 bytes to whats/analysis/stage1.vbs

The result confirms what layer 1 suggested: the first recovered payload is another VBScript. It uses a different accumulator (KMuvRqV) and ends with dynamic execution again:

ExecuteGlobal KMuvRqV

This is the second teaching point in the case. Deobfuscating one layer does not mean reaching the final malware. Many campaigns use “decode -> execute -> decode again” to frustrate quick analysis.

In an isolated lab, another path would be replacing ExecuteGlobal X with WScript.Echo X and running the VBS in a controlled VM to print the next stage. For teaching material, I prefer the static parser when possible because it avoids executing attacker logic.

The end of the first HTA

At the end of the original file, the structure is explicit:

' Layer 554
g9FTeNPd0SD = g9FTeNPd0SD & Chr((196-5) Xor 241)&...

' Execute decoded payload
ExecuteGlobal g9FTeNPd0SD

I counted 554 Layer blocks. The number is more psychological than technical. It makes the file large, confusing, and unfriendly to manual review. The method, however, stays the same: rebuild a string and execute it.

What the loader does next

After staged deobfuscation, the chain becomes a dropper:

HTA
  -> decoded VBScript
  -> second decoded VBScript
  -> C:\temp\instalar.bat
  -> remote MSI + embedded Python
  -> whats.py / whatsz.py
  -> WhatsApp Web automation

The batch file at C:\temp\instalar.bat prepares the environment:

  1. Picks a download URL from centrogauchodabahia123.com.
  2. Downloads an MSI payload with PowerShell.
  3. Installs it silently with msiexec /qn.
  4. Prepares an embedded Python runtime under C:\temp.
  5. Installs automation libraries: Selenium, PyAutoGUI, keyboard/mouse hooks, OpenCV, Pillow, Requests, webdriver-manager, and related tooling.
  6. Downloads the final WhatsApp automation script.
  7. Starts it with pythonw.exe, without a visible console.

This shows the HTA’s job: it does not need to contain the whole malware. It only needs to gain execution and build the base for the real payload.

The final payload: WhatsApp Web automation

The Python stage is built around browser automation. The goal is not to “break” WhatsApp authentication. It abuses the victim’s local session.

If the victim already uses WhatsApp Web, the malware tries to reuse or copy local browser profile data. It then injects JavaScript into the WhatsApp Web page to operate the victim’s own account.

The recovered behavior shows four main capabilities:

1. Fetch campaign configuration from the attacker's server.
2. Reuse Chrome, Edge, or Firefox profile data when possible.
3. Inject WPPConnect/WA-JS into WhatsApp Web.
4. Enumerate contacts and send messages/files in bulk.

Observed infrastructure:

https://centrogauchodabahia123.com/api/config.php
https://centrogauchodabahia123.com/api/contacts.php
https://centrogauchodabahia123.com/api/log.php
https://centrogauchodabahia123.com/api/contador.php
https://centrogauchodabahia123.com/altor/wppconnect-wa.js
https://centrogauchodabahia123.com/altor/gera2.php

Contact theft is immediate damage. Before the spreading phase even matters, the operator receives names and phone numbers from the victim’s WhatsApp contact graph. Then the same automation can send a greeting, attach a remotely configured file, and send a closing message to many contacts.

That is the attacker’s real expectation: each new victim becomes a trusted sender. The next target receives a file from someone they know, not from a random number.

How the attacker hides intent

The sample combines several simple techniques:

  • Social trust: the file arrives from a known account.
  • HTA instead of a common document: the user may not realize it is executable.
  • Invisible window: the HTA minimizes, disappears from the taskbar, and closes on load.
  • Silenced failures: On Error Resume Next avoids visible error messages.
  • Structural noise: empty functions and fake comments simulate complexity.
  • Missing strings: URLs and commands do not appear in a first simple grep.
  • Dynamic execution: ExecuteGlobal runs code assembled in memory.
  • Silent installation: msiexec /qn and redirected output hide activity.
  • Console-less Python: pythonw.exe keeps automation in the background.
  • Remote configuration: messages, delays, and the distributed file can change on the server.

Impact

The victim does not lose a WhatsApp password in the normal sense. Instead, the malware rides the authenticated local session.

The practical impact is still severe:

  • Contacts are exfiltrated to the attacker.
  • The victim’s own WhatsApp account can be used to send files and messages.
  • Recipients trust the message because it came from a known account.
  • The operator can adjust the campaign remotely.
  • The machine keeps local tooling under C:\temp, including Python and browser automation dependencies.

The final result is a propagation loop: one trusted account sends the bait to the next set of trusted contacts.

How I would teach this

For a class, I would split the exercise into four blocks:

  1. Triage: identify HTA, hash, size, header, and self-closing behavior.
  2. Obfuscation: explain array decode and XOR decode with small input/output.
  3. Safe extraction: use a text parser or replace ExecuteGlobal with print inside an isolated VM.
  4. Final chain: map the dropper, infrastructure, Python setup, and WhatsApp Web abuse.

The main teaching point is that “looks complex” does not mean “cryptographically strong.” Most of the work is having the discipline to separate noise, deterministic transformation, and real behavior.

Indicators

SHA256
5a822a163d0787bcfd52b2ae3ace6cb6a92eb158a52b0fbe3cf0380acc2cb702

Suspicious local paths
C:\temp\instalar.bat
C:\temp\whats.py
C:\temp\python.exe
C:\temp\python312._pth

Suspicious process chain
mshta.exe -> powershell.exe
mshta.exe -> msiexec.exe
mshta.exe -> pythonw.exe

Network indicators
centrogauchodabahia123.com
/api/config.php
/api/contacts.php
/api/log.php
/api/contador.php
/api/api.php
/altor/wppconnect-wa.js
/altor/gera2.php

Conclusion

The file is a WhatsApp Web propagation dropper. The HTA is the first-stage camouflage: it hides the window, decodes a payload, and moves execution into a script chain. The recovered payload builds a Python automation environment, contacts attacker-controlled infrastructure, reuses the victim’s browser session, extracts WhatsApp contacts, and sends a remotely controlled file to those contacts.

The important lesson is that the attacker does not need to break WhatsApp’s authentication. They use the trust already present on the victim’s machine and in the victim’s social graph.