This is the second entry in our series showing how to use JEB and its well-known and lesser-known features to reverse engineer malware more efficiently. Part 1 is here.
Today, we’re having a look at an interesting portion of a x86-64 Windows malware that carries encrypted strings. Those strings happen to be decrypted on the fly, the first time they’re required by some calling routine.
SHA256: 056cba26f07ab6eebca61a7921163229a3469da32c81be93c7ee35ddec6260f1. The file is not packed, it was compiled for Intel x86 64-bit processors, using an unknown version of Visual Studio. The file is dropped by another malware and its purpose is reconnaissance and information gathering. Let’s load it in JEB 5.8 and do a standard analysis (default settings).
Initial decompilations
For the sake of showing what mechanism is at play, we’re first looking at sub_1400011F0
. Let’s decompile it by pressing the TAB key (menu: Action, Decompile…).
Then, let’s decompile the callee sub_140001120
.
JEB can now thoroughly look at the routine and refines the initial prototype that was applied earlier, when the caller sub_1400011F0
was decompiled. It is now set to: void(LPSTR)
.
The code itself is a wrapper around CreateProcess
; it executes the command line provided as argument.
Press escape to navigate back to the caller, or alternatively, examine the callers by pressing X (menu: Action, Cross-references…) and select sub_1400011F0
. You will notice that JEB is now warning us that the decompilation is “stale”.
Second decompilation
The reason is that the prototype of sub_140001120
was refined by the second decompilation (to void(LSPTR)
), and the method can be re-decompiled to a more accurate version.
Let’s redecompile it: press F5 (menu: Window, Refresh). You can see that second decompilation below. What happened to the calls to sub_140001040
?
String auto-decryption
Notice the following:
- A “deobfuscation score” note was added as a method comment (refer to part 1 of the series)
- The calls to
sub_140001040
are gone, they have been replaced by dark-pink strings
JEB also notified us in the console:
Dark-pink strings represent synthetic strings not present in the binary itself. Here, they are the result of JEB auto-decrypting buffers by emulating the calls to routine sub_140001040
, which was identified as a string provider. Indeed, the decompilation of sub_140001120
helped, since the inferred parameter LPSTR
was back-propagated to the callers, which in that case, was the return value of sub_140001040
.
Auto-decryption can be very handy. In the case of this malware, we can immediately see what will be executed by CreateProcess
: shells executing whoami
and dir
and redirecting outputs to files in the local folder. However, if necessary, this feature can be disabled via the “Decryptor Options” in the decompiler properties:
- Menu: Options, Back-end properties… to globally disable this in the future, except for your current project
- Menu: Options, Specific Project properties… for the current project only
- Or you may simply redecompile the method with CTRL+TAB (menu: Action, Decompile with options…) and disable string decryptor for specific code
The decryptor routine
What is sub_140001040
anyway? Let’s navigate to the routine in the disassembly and decompile it.
After examination of the code, we can adjust things slightly:
- The global
gvar_140022090
is an array ofPCHAR
(double-click on the item; rename it with N; change the type to a PCHAR using Y; create an array from that using the * key). - The prototype is really
PCHAR(int)
, we can adjust that with Y. - The first byte of an entry into
encrypted_strings
is the number of encrypted bytes remaining in the string; if 0, it is fully decrypted and subsequent calls will not attempt to decrypt bytes again. - The key variable is v3 is the key; let’s rename it with N. Note that the key at (i) is the sum of the previous two keys used by indices (i-1), (i-2); the initial tuple is (0, 1). This looks like a Fibonacci sequence.1
Comparison with GHIDRA
For comparison sake, here are GHIDRA 11 decompilations.
Conclusion
JEB decompilers2 do their best to clean-up and restore code, and that includes decrypting strings when it is deemed reasonable and safe.
That concludes our second entry in this “How to use JEB” series. In the next episodes, we will look at other features and how to write interesting IR and AST plugins to help us further deobfuscate and beautify decompiled code.
As always, thank you for your support, and happy new year 2024 to All 😊 – Nicolas
–