KPOT AutoIt Script: Analysis
In diary entry "KPOT Deployed via AutoIt Script" I obtained 3 files:
- A legitimate, signed AutoIt interpreter (this is not malware)
- A heavily obfuscated AutoIt script, that is encoded as a PEM certificate
- An encrypted EXE: KPOT info stealer
In this diary entry, I'll share more details on the analysis of the AutoIt script.
It is encoded as PEM certificate:
I can decode this file with my tool base64dump.py:
This AutoIt script is heavily obfuscated: code obfuscation (a lot of unnecessary code) and string obfuscation. The function highlighted in the code above, is an obfuscated string decoding function.
Here I grep for calls to this function:
The function takes 2 arguments: a string and a number. The string is a sequence of numbers separated by "*". The encoding is not complex: to decode an obfuscated string, substract the second argument from every number in the first argument, convert to characters and concatenate.
Example: ("111*114*113*106", 3)
Subtracting 3 from each number: 108, 111, 110, 103. Converting to characters and concatenate: "long".
My translate.py tool can do this decoding in-place: it can replace each call to the decoding function, byt the decoded string. With option -r, I provide a regular expression that will match each call to the decoding function:
GovUcjGgXxPeoI\(\x22[^\x22]+\x22,[0-9]+\)
I also add a capture group () for both arguments:
GovUcjGgXxPeoI\(\x22([^\x22]+)\x22,([0-9]+)\)
Then I provide a Python function as argument to translate.py, to do the decoding. It receives a regex match object (capture groups are in oMatch.groups()), and returns the decoded string:
lambda oMatch: '\x27' + ''.join([chr(int(n) - int(oMatch.groups()[1])) for n in oMatch.groups()[0].split('*')]) + '\x27'
Here is the AutoIt script with deobfuscated strings:
Scrolling through the decoded script, I find a set of hexadecimal strings:
I'm going to decode this hexadecimal data. First I select all the lines with these hexadecimal strings (my Python template process-text-file.py can also be used as an enhanced grep tool):
With my tool re-search.py, I extract all the hexadecimal strings like this:
Then, with sed, I removed the leading "0x" string and then convert the hexadecimal data to binary data (hex-to-bin.py) and as a first analysis step, I extract strings with my tool strings.py:
Most of these are 4 character long strings, and when I concatenate the first strings, I read: NtOpenSection, NtMapViewOfSecti.
These are Windows API functions that are typical for process hollowing code: this is very likely process hollowing shellcode.
Disassembling with the netwide disassembler shows code that indeed looks like shellcode (I first try to disassemble this shellcode as 64-bit code, because the AutoIt interpreter is a 64-bit application):
In disassembled shellcode, constant values that are moved to registers, or pushed on the stack, are often used to build strings that interest us (like API function names). Here strings MZ and PE further confirm that this is shellcode that does something with a PE file.
I grep for all these constant, hexadecimal values:
And then I convert them to binary data. I can't use my hex-to-bin.py tool here to achieve this, because the hexadecimal strings need some extra processing. First, uneven length strings need to be prefixed with 0 before converting to binary data, and then each converterd value needs to be reversed (the data is little-endian). I use my tool to achieve this, and my tool to concatenate all the strings:
Not only are there many API functions here used in processing hollowing, but also crypto API functions, and also a function to create a mutex. This is typical for "frenchy shellcode", process hollowing shellcode that is popular now with malware authors, and that works with an encrypted PE file (the guest) and creates a mutex: frenchy_shellcode_{VERSION}.
Let's find this mutex:
frenchy_shellcode_06: this confirms that this is process hollowing shellcode.
Remark that you will only find this "frenchy_shellcode_06" mutex via static analysis. If you perform dynamic analysis, a mutex with a random name will be created in stead. That's because in the AutoIt script, there is code to replace the hexadecimal code for this mutex with other hexadecimal code with a random mutex name:
Comments