Another Malicious HTA File Analysis - Part 3

Published: 2023-05-21
Last Updated: 2023-05-21 17:54:34 UTC
by Didier Stevens (Version: 1)
0 comment(s)

This is part three of a diary entry series. Part one can be found here and part two can be found here.

We ended with the download of a new payload: a .bat file.

Let's take a look:

That looks like more BASE64 code. Let's check with

Indeed, we have rather 2 long BASE64 strings. So maybe 2 payloads. Or a payload and a loader.

What do we find after the BASE64 code:

A BAT file with obfuscated commands. A lot of 3 letter strings between exclamation marks (!).

The one circled in red draws my attention: !tHB!. If I remove that string, I end up with .exe.

So I try a sed command to remove all occurence of 3 characters surrounded by exclamation marks. I do this with regular expression !...!

The result looks like another PowerShell script:

With more obfuscation: I have to remove string pCpCh too.

And we end up with another PowerShell script. It looks similar to the one we analyzed in part 2: another decryptor.

We are again dealing with AES encryption (1), CBC mode this time (2), the key is BASE64-encoded (3) and the initialisation vector too (4). And there is also GZIP decompression (5).

So let's adapt our decryption script from part 2 a bit:

from Crypto.Cipher import AES
import gzip
from Crypto.Util.Padding import pad, unpad

def Transform(items, options):
    if options.parameter == '2':
        ciphertext = items[1]['content']
        ciphertext = items[0]['content']
    key = items[2]['content']
    iv = items[3]['content']

    oAES =, AES.MODE_CBC, iv)
    cleartext = unpad(oAES.decrypt(ciphertext), AES.block_size)
    transformed = gzip.decompress(cleartext)

    return transformed

There are several differences here: we use CBC mode, we have an initialisation vector (iv), and we have to do unpadding (unpad).

And since we have 2 payloads to decrypt this time, we use's option -p (--paramter) to specify which payload we want to decrypt.

If -p is equal to '2', we take the second payload (items[1]), otherwise we take the first payload (items[0]).

This is the output from

We have our 2 payloads, the key and the iv.

We let produce JSON output and feed this into with script. As I suspect that this payload will be binary (PE file), I do an ASCII dump (-A) of the decrypted data:

This looks indeed like a PE file. Let's verify with my tool:

It's a .NET assembly: 5c5f55987a79e29a3bc46aeeb78209331d6cdbb4d1dde7f24a0b41ae51b5de8f.

Let's take a look at the second payload, using -p 2:

That one too is a .NET assembly: 5f5b1e4a6cb96f0611a8374e504cee8ceb7dc59dedf0f4059fd93dcd8315699c.

Didier Stevens
Senior handler
Microsoft MVP

0 comment(s)


Diary Archives