Wednesday, December 6, 2017

Recam Redux - DeConfusing ConfuserEx

Overview

This report shows how to deobfuscate a custom .NET ConfuserEx protected
malware. We identified this recent malware campaign in our Advanced
Malware Protection (AMP) telemetry. Initial infection is via a malicious
Word document, the malware ultimately executes in memory an embedded
payload from the Recam family. Recam is an information stealer. Although
the malware has been around for the past few years, there's a reason
you won't see a significant amount of documentation concerning its
internals. The authors have gone the extra mile to delay analysis of the
sample, including multiple layers of data encryption, string
obfuscation, piecewise nulling, and data buffer constructors. It also
relies on its own C2 binary protocol which is heavily encrypted along
with any relevant data before transmission.

Technical Details

The Dropper

The word document (see above) uses common malware techniques, such as embedded VB
code, to drop a .NET executable. We will not discuss these techniques
further, but concentrate on the deobfuscation of the .NET malware
dropper. The dropper is heavily obfuscated with a custom version of
ConfuserEx, a free .NET Framework protector. On opening the binary in a .NET
decompiler like dnSpy it is initially unreadable (see Fig. 1).

Fig. 1

There are a number of free deobfuscators available for ConfuserEx
protected binaries; however, none of them are effective for this
malware. Only some parts are able to be deobfuscated using these
automated tools, leaving important sections of the binary unchanged, and
breaking execution. This means we have no choice but to do it the hard
way and deobfuscate it manually. There is documentation for manually
unpacking ConfuserEx, but unfortunately, we hit bad luck again. The
available documentation doesn't work with this version.

To get started, we first load the
binary into dnSpy. We go to the <Module>. cctor and set a
breakpoint on the last method (Fig 2). Now we can run the sample in our
debugger and see that it has unpacked the first DLL ("ykMTM…" see Fig.2 )

Fig. 2

We single step into the method where we hit the breakpoint and see in Fig. 3 that it has unpacked the next stage (coral).

Fig. 3

We analysed this stage and found that we can set another breakpoint in the qMayiwZxj class on line 113 (see Fig. 4)

Fig. 4

This unpacks the next stage and we see the new unpacked stub.exe assembly (Fig. 5).

Fig. 5

If you have looked into other ConfuserEx obfuscated binaries, this looks
familiar. Indeed, if you have a closer look, there is a well known
friend, the gchandle.free() call on line 10082. This is our next
breakpoint candidate. This call used to be the end of an unpacking stage
in previous versions.

Fig. 6

As expected, this unpacks another module ConfuserEx is known for: koi.

Fig. 7

We are getting closer, but the classes in koi are still empty and not yet filled with code:

Fig. 8

Again, we set a breakpoint on the last method called in koi's cctor and proceed running the sample.

Fig. 9

Nice, another DLL is unpacked, unfortunately it is nothing important.
Our Main class and most others in stub are still empty. Single stepping,
brings us back into <module>. Once there, we analysed the
methods and found out that we can set another breakpoint at line 92 for
unpacking the next stage (see Fig. 10).

Fig. 10

Tada! If we now look in stub at the classes, they are filled with code.
Now we can set a breakpoint on stub.Run() and start investigating what
this malware loader is actually doing besides unpacking itself.

Fig. 11

We see that it is attempting to bypass some AV scans and reading several
config parameters from the resource section. Below you can see the
malware's configuration which was hidden encrypted in the resource
section (Fig. 12) before unpacking.

Fig. 12

It checks if it was executed from the Startup folder (e.g.
%AppData%\mozilla firefox\firefox ) as configured in the resource
section. If not, it copies itself to the Startup folder and launches
itself via cmd.exe. This means, we need to stop debugging and start
again by loading the firefox.exe from %AppData%\mozilla firefox\firefox
into dnSpy, following the unpacking again up to this point.

Fig. 13

Now we are in the "is executed from Startup location" branch. Here it
gets interesting. First it makes itself persistent on the local machine.
As you can see below, it writes a file called Update.txt with the
following content to the %AppFolder%.

Then it adds this file to the auto-run registry key by executing reg add
in a cmd.exe to make sure the firefox.exe file gets executed at PC
start up:

Fig. 16a

Fig. 16b

It executes a couple of other methods based on the configuration and
then loads and decompresses the LZMA compressed malware payload file
(Recam) from the resources MainFile section. After a couple of runtime fixes it
loads RunPEDLL.dll and tries to inject the file into the user's browser.
In case this fails (e.g. no browser is running), it injects the file
into itself (firefox.exe). In both cases the RunPE.Run() method is used
to do that.

Fig. 17

From here on the work is done for the malware dropper and the loaded Recam binary takes over.

Payload

As mentioned in the introduction, the authors have gone the extra mile
to frustrate analysis of the sample by using multiple obfuscation
techniques, including multiple layers of data encryption, string
obfuscation, piecewise nulling, and data buffer constructors. It also
relies on its own C2 binary protocol. All relevant data is heavily
encrypted before transmission.

The dropped binary is packed with vanilla UPX. This part is easy to
unpack; the tricky part comes in the next stage. After the original
Entry Point (OEP) is restored, it begins with some homebrew
cryptographic initialization for several values that get used
consistently throughout runtime. Most remain constant following the
initialization routine, but some change over time. Some preliminary
string deobfuscation occurs shortly thereafter and includes a single
hard-coded Command and Control server (C2) IP.

This less frequently used deobfuscation routine is primarily based on a
single-byte XOR loop. The other primary routine is JIT based and relies
on a hard-coded decode key. Fortunately, IDA Pro's Appcall feature made short work of these obfuscations.

Fig. 18

Getting to the end of the preamble functions shortly following the PE
Entry Point (EP), we get to an operation selection routine. The presence
of unnecessary code and calculations disguises the fact that the jump
to location 40849B will always be taken and the apparently interesting
code that appears to involve file mangling and process creation is
merely a decoy and always skipped in execution.

Moving forward, the malware sets a Run key for system persistence. Near
the end of the operations function, an additional thread is created to
start up a keylogger component, logging to %APPDATA%\Logs with
<DAY>-<MONTH>-<YEAR> as the file name format. Logged
input is stored in the commonly seen bracket delimiters. However, as one
might expect by now, the final data is encrypted before written to the
file on disk.

Next, the malware will create an ID file entitled .Identifier. If such a
file already exists in the PWD of the sample (extracted via the
GetModuleFilename API), it is simply read in instead of created from
scratch.

Fig. 19

Data to be written to the file is generated piece by piece and results in the following format:

It's often easiest to break on a few instructions prior to deciphering
the C2 beacon for many malware families these days. Whether it was
intentional or not, the authors decided to opt of a homebrew crypto
scheme allowing for randomized beacon data for each run (only the length
bytes & C2 command for the beacon remain the same), or their
homebrew crypto implementation is severely complex & broken.

Fig. 23

Fig. 24

Fig. 25

Once the beacon is sent, the sample waits for a server response. The C2
we encountered is now down and resetting connections, but pcaps captured
in sandbox environments at an earlier date can give us a better idea of
what to expect for the rest of the communications. The following
example shows the beacon, the initial response, one additional client
transmission and a series of "keep alive" messages consisting of the
sole command byte.

Fig. 26

At this point, code execution depends on a flow state that is set only a
few times throughout the binary (initially set to 0xFFFFFFFF). As far
as the response length and C2 command are concerned, this state further
dictates which each attribute must be. For example, the function
responsible for checking the response length checks the flow state too.
If state has changed, it checks if the message length exceeds 0x30000.
If it's still in the default state, it checks if the length is 0x41
(length of the beacon message and its expected response). For the
command byte itself, the default state checks if the command byte is set
for the beacon phase of the communications (0x85). Once changed it will
check to see if the command byte is less than or equal to 0xD2.

Fig. 27

Fig. 28

The response and subsequent data (if any) are relayed to a large jump
table that is responsible for checking the command byte and proceeding
from there with a particular action as issued by the server.

Fig. 29

The beginning of the previously mentioned function and jump table checks
flow state again to see if the relevant parameter now equals a
previously set state outside of the 0xFFFFFFFF. If this is the case, the
data from the last server response is decrypted with the same routine
used by the sample to encrypt data before transit. When in the default
state, the command byte is passed to a LEA (Load Effective Address)
where a calculated address is stored in EAX. In this case, there will be
no calculated address due to the zero-extended command byte being
referenced by the instruction. Instead, 0x7F gets added to the command
byte. The single byte stored in AL taken from the DWORD stored in EAX is
compared against 0x51. If equal, it proceeds to the function end and
returns with no further action taken. Otherwise, the final byte stored
in AL is zero-extended to EAX itself, multiplied by 4 and passed to the
jump to determine the next action as requested by the server.

Fig. 30

As one might have gathered from the jump table, there are 82 possible
commands that can be accepted from the server. However, not every
command is unique. As we can see from the highlighted jump offsets
below, many lead to the address shown earlier (RVA 0x227C) that is
jumped to when completing no action.

Fig. 31

While time did not allow us to deeply examine each and every path,
gathered sandbox pcaps along with our understanding of the command
protocol allowed us to examine the commands sent by the server and
calculate the jumps ourselves. Here are some examples of the
functionality available in this variant of Recam, given the command.

Conclusion

Malware is a moving target, it is constantly evolving in an arms race
between the malware authors and the security researchers. This analysis
shows the level of sophistication employed by threat actors in order to
attempt to escape detection.

Obfuscation is an art form. Techniques can range from frequently changed
packers to the multiple techniques employed in malware such as this.
Often malware packers are modified by their authors very soon after
deobfuscation tools or reports are publically released. In many cases it
is enough for them to change minor parts of the obfuscator to confuse
the deobfuscation tools. Hence, malware researchers can't rely on these
tools and must resort to be able to manually deobfuscate code when
necessary.

Understanding the steps that threat actors will go to to hide from
detection and analysis is vital when it comes to protecting systems from
malware. It is by applying lessons learnt from analyses such as this,
that we are able to detect advanced malware with tools such as Advanced
Malware Protection (AMP) and Threatgrid.

Coverage

Additional ways our customers can detect and block this threat are listed below.

Advanced Malware Protection (AMP) is ideally suited to prevent the execution of the malware used by these threat actors.

CWS or WSA web scanning prevents access to malicious websites and detects malware used in these attacks.

Email Security can block malicious emails sent by threat actors as part of their campaign.