AgentTesla: .rtf and Equation Editor

While extracting Equation Editor shellcode is nothing new on this blog, it never hurts to practice the skills necessary to do this. To that end, we will be working on this document right here:

.rtf document?

Using against the document, we see that item 8 contains objdata. This is a good place to start.

We can select item 8 (-s) and decode it as hexadecimal data (-H) in order to take an initial look at that object. We can see that this object contains a call to Equation Editor (EQNEDT32.exe).

To extract this as a file, we will decode it as hexadecimal (-H), dump it (-d), and then send the output to another file which we will call output.bin.

We can use XORSearch.exe to search that binary file for various signatures of 32-bit shellcode. We see that GetEIP was found in two locations. This indicates that shellcode might start at 0xF2. This information will be useful in the next step.


scDbg.exe is a shellcode emulator. If we load up our .bin file and start with the offset of 0xF2, decoded shellcode may appear.

Based on the output, it looks like we had a good offset address. We can tell because we see some decoded lines… but not too many decoded lines. However, we’ve seen ExpandEnvironmentStringsW before and we know how to deal with that. Notice also where it says “Change found at 706…” and that it dumped to a new file called output.unpack.

The change was found at position 706. This means that there are a bunch of extraneous characters before our useful shellcode. While there are a variety of ways to get rid of them, will also do the trick.

We can see a variety of useful strings by opening output-cut.unpack in a hex editor.

One of the reasons we didn’t get this output before was that the shellcode used ExpandEnvironmentStringsW. scDbg.exe doesn’t hook into that function. Instead, it will hook into ExpandEnvironmentStringsA. If we overwrite the W in our file with an A, we ought to be able to get some much cleaner output.

Save your changes and toss it back into scDbg.exe. Note, there is no need to include an offset address or create a dump.

We now have the decoded shellcode!

Thanks for reading!

AgentTesla (01.24.2020) – Document Analysis

We will be working on this document here: This one is interesting because it was an attached .xlsx spreadsheet. It spawns powershell, which in turn spawns csc.exe. This downloads the executable.

We’ll be coming across a few decoding functions throughout this blog. I created powershell and python versions of them so you can decode them yourself. They will be found at the bottom of this post.

Yanking out the macros, we see that there is only one. You’ll notice that it isn’t obfuscated, but it does contain a lot of white space. Upon cleaning it up, we see that things make more sense.

Embedded macro

Looking at this macro, we see a couple of things.

Line 11: Workbook_Open()
Line 21: Contains a reference to Cell 136, 8 (We should look here)
Line 25: Shell command on variable bedeswomen.
Line 31: Converts an ANSI character code to a character, stores it in variable bedeswomen.
Line 35: Contains a reference to Cell 135, 8 (We should look here)

So it seems that information in certain cells of the spreadsheet are converted to something else and executed. What gets created? A powershell string to execute!

Powershell spawned from excel.exe

Once again, we see a long string of information getting decoded. A few of the lines are explained below.

Line 2: The decoding function
Line 9: Takes characters two at a time and converts them to bytes.
Line 10: XORs the bytes from line 9 against the key(?) in line 5.
Line 14: The line being decoded (it is 3444 characters long)

The decoded output is below. I also cleaned it up and highlighted the pertinent parts.

csc.exe spawned from Powershell.exe

Lines 14, 19, 35, and 36: Long strings to be decoded.
Line 35: Download file location C:\Users\[user]\AppData\Roaming\f3ad7.exe
Line 36: Download file.
Line 38: Execute initial download.
Line 41: Decoding function.

Let’s look at that decoding function a little more carefully:


This decoding function should look familiar to the decoding function used in the powershell string above.

Line 47: Take the characters in the string two at a time, convert them to bytes.
Line 48: XOR the bytes from line 47 against the key(?) in line 43.
Line 50: Return the output.

And to what does it decode?  http://www%5B.%5Dclassicpalace%5B.%5Dae/engine/Mymet%5B.%5Dexe

Let’s look at the entire process to see what happens next.


We can see that Excel.exe calls up powershell.exe which then starts csc.exe. This in turn downloads Mymet.exe which gets renamed to f3ad7.exe.


Once f3ad7.exe executes, it steals personal data, changes the autorun registry, and then sends data outbound via SMTP.


Python and Powershell Decoding functions

Powershell decoding function. Just copy and paste encoded string at the top.

$string = "[paste string here]"
$key = "gf17c9b"
$decoded = ""
For ($i = 0; $i -lt $string.Length; $i+=2)
     $var_bytes = [Convert]::ToInt32($string.Substring($i,2), 16)
     $decoded += [char]($var_bytes -bxor [byte]($key[($i/2) % $key.Length]))

Python version. Again, just copy the string to decode at the top.

string = "[paste string here]"
decoded = ""
i = 0
while i < len(string):
     key = "gf17c9b"
     var_bytes = int(string[i:i+2],16)
     decoded += chr(var_bytes ^ (ord(key[(i/2) % len(key)])))
     i += 2
print decoded

Thanks for reading!