Tuesday, 1 December 2015

Nymaim Malware Obfuscation and System Time Check

Recently in Nov 2015, it was observed that the Nymaim malware is being distributed in a spam campaign. This spam campaign is related to Intuit Quickbooks.

More details of the spam campaign can be found at the following links:

https://techhelplist.com/spam-list/974-intuit-browsers-update-malware
http://blog.dynamoo.com/2015/11/malware-spam-intuit-qb-quickbooks.html

I checked the binary downloaded in these spam campaigns. It uses some interesting code obfuscation techniques and even has a system time check.

System Time Check

Let us first discuss about the system time check.

Each binary which is distributed in these spam campaigns is configured with a time limit. Based on the day this binary is sent in the spam campaign, it will execute completely only if the current system time is less than a configured time limit.

For instance, for the binary with MD5 hash: 563a1f54b9d90965951db0d469ecea6d which was sent in spam campaigns on Nov 18th, the system time check is configured so that it will run only on or before 20th Nov.

Below is the relevant code section which shows the system time check:


As we can see in this code section, the system time check is obfuscated as well. Instead of doing a simple check on the system time returned by GetSystemTime(), it uses obfuscation to make it difficult to understand the time check.

I have added the comments in the code section above which shows the time check performed.

Binary will check the Year, Month and Day fields from the System Time value returned by GetSystemTime and compare it with the following configured time limit.

Year - 0x7df
Month - 0xb
Date - 0x14

Only if the current system time is on or before 20th Nov 2015, it will execute completely.

As a result of this system time check, if we analyze this binary on a date after this, it will not execute completely. This is an anti analysis technique and not an evasion technique.

Code Obfuscation

Nymaim malware also uses interesting code obfuscation techniques. Below are few examples from the malware variants observed in this campaign.

SEH Anti Debugging: In another variant of Nymaim which was distributed in this campaign with MD5 hash: 60b2009138d1b21c1b93b7093bc66109, I noticed that it uses an SEH based anti debugging technique. It is used to make the process of tracing the code in debugger more difficult.

Below are the details:

It registers an exception handler at address, 0x0040116b. It then triggers an exception by executing a privileged instruction like the OUT instruction. Below is the relevant code section which shows the execution of Privileged Instruction.



We can see the usage of junk instructions in the code above. Below are few examples of such instructions:

Mov dh, dh
dec esi
inc esi
cmp esi, esi
cmp esi, esi
cmp esi, esi
and dword ptr ds:[4657b7], ffffffd5

These junk instructions do not impact the behavior of the malware because most of these junk instructions are done to synthesize NOP. In x86 instruction set, we can synthesize NOP instructions in multiple ways and this technique is used by the malware to generate junk instructions.

Now, let us look at the Structured Exception Handler which is invoked when an exception is triggered in the above code section.


We can see in the exception handler code the following things:

1. It uses a lot of junk code as well.
2. It adjusts the value of EIP in the exception record by adding 2 to it. This is done so that when the exception is handled, the execution is resumed after the OUT instruction. Since the size of OUT instruction is 0x2 bytes, the above code adds 2 to the address where exception occurred.
3. It also uses the EDX register as a counter variable which is set in the exception record as well. When we return from the exception handler, we can see that the value of EDX is checked. If it is not 0, then the loop is repeated. The counter value is set to 0x1023b. As a result of this, even if we pass the exception to debugger, the loop is triggered so many times. The code can of course be patched as shown below:

or edx, edx
jnz 00403aea            ; Patch this condition jump instruction
pop dword ptr fs:[edx]        ; value of EDX should be 0, else an exception will be thrown
sub byte ptr ds:[4667f2], 3d
add esp, 4
push esi
retn

While patching the code above, we need to be careful to even set the value of EDX to 0, since it is used in the next instruction as an offset into fs register (fs:[0] -> head of exception list).

API Call Obfuscation

Nymaim also uses an interesting way to perform API call obfuscation. There are multiple reasons to do this. It makes the process of tracing the code in debugger difficult. For instance, if you set a breakpoint at an API, when you follow the return address, instead of returning to the malware code, it returns to a location in ntdll.dll.

For malware analysis, some automation systems use API tracing. They generate a log of different APIs called by the malware. From the API, they backtrace and find the address from where the API was called. The heuristics used in analysis systems are based on API calls coming from malware code. If the API call is coming from a system DLL, it is usually whitelisted. In this way, Nymaim can also bypass some heuristics used in analysis systems.

Let us look at how Nymaim calls the APIs indirectly.

We saw in the code sections above that Nymaim uses a System Time Check. Let us set a breakpoint at GetSystemTime() and observe the state of registers and stack.


Once we hit the breakpoint in debugger, we can see on the call stack that the return address is: 0x7c95ee2d. This address points to ntdll.dll instead of pointing to the malware code.

Now, let us follow the return address in the debugger:

We see that it returns to a code section in ntdll.dll which is corresponding to the x86 instruction, Call EBX. The value of EBX is crafted in such a way that it points to the malware code.

Let us follow this subroutine:

Now, we have returned to the malware code. We can also see usage of junk instructions in above code sections.

Some of the examples are:

1. The value of a local variable is overwritten twice.

mov dword ptr ss:[ebp-c0], eax
...
mov dword ptr ss:[ebp-c0], 71b700

2. Adding, subtracting or performing an XOR operation on a local variable with 0 does not modify the value of local variable. These instructions are equivalent to a NOP instruction:

sub dword ptr ss:[ebp-dc], 0
...
add dword ptr ss:[ebp-c4], 0
...
xor dword ptr ss:[ebp-c4], 0

3. We can also see few comparison instructions however they are not followed by any conditional jump. This is also an indication of instructions which are equivalent to a NOP instruction and are added to make the process of reversing the binary difficult.

In this way, we can see that the Nymaim malware uses some interesting code obfuscation techniques.

No comments:

Post a Comment