zloader: Simpler XLM and hidden encoded strings

It has been awhile since an interesting document came across my desk. The XLM and sandbox evasion checks in today’s document were different enough where I wasn’t sure if it was going to be zloader or not. But grabbing the executable and tossing it into any.run (or tria.ge, if you’re one of the cool kids) confirmed it was zloader.

Document: https://app.any.run/tasks/476caae4-d8c4-4b62-a33b-f9ce3258cd1e
Executable (any.run): https://app.any.run/tasks/7d3acbcc-d47c-408e-a42f-a8865d758f21
Executable (tria.ge): https://tria.ge/201202-6crv4myx46

Decoding Macro

As per usual, the main XLM macro is in one single column. However, it wasn’t the usual massive block of XLM code. It is conceptually the same in that variables will be set up to control the decoding loops. But rather than that information being in the XLM code itself, the XLM will grab numbers and encoded strings a different sheet. In this case, the decoding macro is in column 1 of sheet JattwdYRiEl and the encoded strings and loop control variables are in Sheet1. Here is a truncated view of the macro to make it easier to understand its flow. Auto_Open sets up a location that points to the beginning of the macro to start decoding strings. vGdNGoO jumps execution to the top of the macro.

SHEET1: Populating Variables

Sheet1 contains what looks very much like some sort of encoded string. Some of the numbers and values in Sheet1 are used to populate the counting variables in the decoding loop. Here are a few examples.

A new development is the location of the encoded strings. They are now defined names within the excel document itself. These names can be found in the Name Manager in Excel. If you look carefully, you can see that a semicolon is used to separate the encoded strings in DLZETTDk.

While the decoding mechanism itself is interesting from an academic perspective, I won’t be diving deeply into it. Suffice it to say, these encoded string gets decoded character by character and tossed into variable ovTMv. Once completed, the XLM code will write the decoded string to R114C1 and overwrite =HALT(). The next string will get decoded and written to R115C1 and so on.

Decoded Strings 1

Once the first round of strings are decoded, RETURN() will jump execution to R114C1. What follows are some more sandbox checks and variable setup. It looks like a file might get written to C:\Users\Public\Documents\. R125C1:R127C1 sets up new variables for the second round of decoding. R131C1 points execution back to the top of the decoding loop which starts the second round of decoding. Those strings will get written starting on R132C1.

Decoded Strings 2

There is a lot going on in the next block of XLM code. The .exe is downloaded to C:\Users\Public\Documents\dfdMmb2W.txt as a text file. Rundll32.exe is used to execute it. Notice the GET.WORKSPACE(1) check in R134C1. If it fails, execution jumps down to R143C1. This sets up a .vbs file, populates it with commands, and then executes it. It will ultimately do the same thing by downloading the executable and executing it with rundll32.exe.

So that’s pretty much it. The main decoding XLM code is cleaner, but the main difference is that the control variables are in another sheet and the encoded strings are defined names.

Thanks for reading!

2 thoughts on “zloader: Simpler XLM and hidden encoded strings

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s