Vin Ransomware Blog02

Shade is a malware that belongs to the ransomware type. A ransomware is a malicious program that once run, will modify all important data in the computer. The important data may be of any type depending on the particular system it attacks and may include photos, media files, documents and archives. It modifies all the important data that resides in a hard disk, USB disk and/or in the share drives / folders. The modification is performed using Cryptographic algorithms. So, these type of ransomwares are also called CryptoRansomware.


At our Paramount threat research lab (Lakshya Labs), we decided to analyze a sample of Shade Ransomware, as we were getting lot of customer request on removing this infection.

The first step we did was to ensure that the samples that we acquired was not corrupted. We loaded the sample in VirusTotal website to ensure that sample was intact.

b4img1

Figure 1 - The matching hash values between the sample and the uploaded sample

b4img2

Figure 2 - All the antivirus vendors detecting this as a ransomware type

We could also find that the all the major anti-virus vendors were detecting this as a ransomware. Once we were sure that the sample was intact, our next step was to run it inside the virtual machine and observe.

As most of the malwares doesn’t run, if it detects the presence of a Virtual machine, we decided to test go with the following scenario. We loaded our sample zoo machine with this ransomware and some sample files along with it.

The below screenshot shows the machine before running the malware. We created three sample files, one image file, one text file and one PDF document.

b4img3

Figure 3 - The initial shot of the zoo machine

We observed the machine after running the malware. After few minutes of running, we could see that the desktop wallpaper was changed and also the sample files were modified. The screen shot of the same is below.

b4img4

The three sample files that we kept before the infection were modified and thus rendered useless. We could see that windows was not able to open these files.  Screen shots shown below

b4img5

Figure 4 - Windows could not open the files

We loaded the sample into a debugger tool (in this case the Immunity Debugger) to understand the functionality.

But before loading the sample, we wanted to make sure that the file was not packed. We used e tool called PEiD to find whether the PE header was different.

b4img6

Figure 5 - PEiD shows the presence of Visual Basic runtime

PEiD found the absence of any packer, however, we found the presence of a Visual Basic run time. Now it was time to load this in the debugger and analyze. After the sample was loaded into the debugger, we landed up in the EntryPoint, as shown below.

b4img7

Then came, the interesting part. After many trial and error attempts and after setting breakpoints at various places, we found that this ransomware creates a new process and that this new process was responsible for encrypting the data. So we decided to debug this new process deeper to understand on how this ransomware worked. Here was where it turned tricky. Debugging this new process was very difficult and the authors of this code has used a technique called process hallowing that made the process of debugging the target a complex process.

We decided to see how the new process was created initially, before analyzing it.

b4img8

Figure 6 - Creation of a new sub process.

We found that ‘CreateProcess()’ function was used to create a new process. We tried to put a breakpoint at this function to see how it worked.

9

Figure 7 - Setting breakpoint at CreateProcess

Voila, the process broke clearly at the ‘CreateProcess()’ function (API). We could see that the arguments that were being passed into the function. The following was the function prototype from the MSDN page.

BOOL WINAPI CreateProcess(
_In_opt_         LPCTSTR                           lpApplicationName,
_Inout_opt_    LPTSTR                             lpCommandLine,
_In_opt_         LPSECURITY_ATTRIBUTES  lpProcessAttributes,
_In_opt_         LPSECURITY_ATTRIBUTES  lpThreadAttributes,
_In_               BOOL                                bInheritHandles,
_In_               DWORD                             dwCreationFlags,
_In_opt_         LPVOID                             lpEnvironment,
_In_opt_         LPCTSTR                           lpCurrentDirectory,
_In_               LPSTARTUPINFO                 lpStartupInfo,
_Out_             LPPROCESS_INFORMATION lpProcessInformation
);

The first and the sixth arguments were very interesting. The first argument ‘lpApplicationName’ here held the value ‘C:\Lab\ZOO\shade.exe’ and the sixth argument ‘dwCreationFlags’ held the value ‘CREATE_SUSPENDED’. After setting the breakpoint just after the successful completion of this function, we could see that a new process was created in suspended state.

b4img10

Figure 8 - A new shade process is created in suspended state

As mentioned earlier, attaching to this new process did not yield anything interesting, as this malware was using a technique called process hallowing. For example, when we tried to attach to this newly created process, we were thrown with a debugger error.


b4img11

Figure 9 - Debugger error while attaching to the new process

The debugger was unable to attach to this newly created process as it was unable to understand the PE (Portable Executable) executable file format. We decided to locate the PE header. After seeing the first area within the ‘0x00400000’ memory region, we could locate the MS DOS and PE headers.

b4img12

Figure 10 - The MS DOS and PE headers

After going further down within the memory area, we were able to locate the PE header and the address of the entry point as well.

b4img13

Figure 11 - Presence of PE header and information about the entry point

So finally, we were able to locate the ‘AddressOfEntryPoint’ for the newly created process. Basically, the ‘AddressOfEntryPoint’ held the address of the first instruction that gets executed when the process starts running. So, the obvious next step was to set a breakpoint at that address and catch the execution. Unfortunately, it did not work. When a process was put in suspended state, it is not possible to debug it, because the debugger won’t be able to see the process at all.

b4img14

Figure 12 - The debugger is not able to locate the newly created process

We decided to follow a different approach. We decided to find out the API that was sending the signal to the suspended process to resume. We decided to put a break point on ‘LdrGetProcedureAddress’ function and intercept the API calls. After analyzing many calls, we understood that just before the newly created process gets executed, the flowing API flows were very important for analysis:

‘NtAllocateVirtualMemory()’ -> ‘CreateProcessW()’ -> ‘NtUnmapViewOfSection()’ -> ‘NtWriteVirtualMemory()’ -> ‘NtGetContextThread()’ -> ‘NtSetContextThread()’ -> ‘NtResumeThread()’ -> ‘GetExitCodeProcess()’

The following screenshots represent this analysis.

b4img15

Figure 13 - 'NtAllocateVirtualMemory()' getting called.

The ‘NtAllocateVirtualMemory()’ function created a new virtual space in the user-mode address region. After this was over, ‘CreateProcessW()’ was called.

b4img16

Figure 14 - ‘CreateProcessW()’ getting called.

The ‘CreateProcessW()’ function was responsible for creating a new process and a primary thread.
Once a new process was created, the ‘NtUnmapViewOfSection()’ function was called.


b4img17

Figure 15 - ‘NtUnmapViewOfSection()’ getting called.

The ‘NtUnmapViewOfSection()’ function was used to unmap the view of a section from the virtual address space. After the unmap happened, next the ‘NtWriteVirtualMemory()’ function was called.


b4img18

Figure 16 - ‘NtWriteVirtualMemory()’ getting called.

The ‘NtWriteVirtualMemory()’ function was responsible for copying data into the memory region. After the data was written, the ‘NtGetContextThread()’ and ‘NtSetContextThread()’ functions were called.


b4img19

Figure 17 - ‘NtGetContextThread()’ getting called.

b4img20

Figure 18 - ‘NtSetContextThread()’ getting called.

The ‘NtSetContextThread()’ function was responsible for setting the context to the thread. Finally, the ‘NtResumeThread()’ function was called.


b4img21

Figure 19 - 'NtResumeThread()' getting called.

The ‘NtResumeThread()’ function was responsible for putting the SUSPENDED process into the execution mode. This made the primary thread in the suspended process to resume, thus triggering the execution of the newly created process.


b4img22

Figure 20 -'GetExitProcess()' getting called.

Finally, ‘GetExitProcess()’ function was called. As, the newly created process started the execution, the main process was put to exit.


b4img23

Figure 21 - Finally the process ends.

Overall, we understood that the job of the first program is to perform process hallowing and execute the newly created process or target process. So by now our aim was to analyze the newly created or the target process.

We wanted to also see what is happening in ‘NtAllocateVirtualMemory()’ function call. According to MSDN, the ‘NtAllocateVirtualMemory()’ function call has the following prototype:

NTSTATUS ZwAllocateVirtualMemory(
_In_          HANDLE        ProcessHandle,
_Inout_     PVOID          *BaseAddress,
_In_         ULONG_PTR   ZeroBits,
_Inout_    PSIZE_T         RegionSize,
_In_         ULONG          AllocationType,
_In_         ULONG          Protect
);

We tried to map the values with the following screenshot.

b4img24

The first value that was being pushed was 0x40 and that corresponded to ‘Protect’. 0x40 holds the value ‘PAGE_EXECUTE_READWRITE’. Clearly, this malware was making a region where it could read, write and as well as execute. The second value 0x1000 held the value ‘MEM_COMMIT’. We went further down to the ‘CreateProcessW()’ to see what was happening.

b4img25

We could clearly see that a new process was being created with ‘CREATE_SUSPENDED’ flag set. We jumped into ‘NtWriteVirtualMemory()’ API call. As per the undocumented references, ‘NtWriteVirtualMemory()’

NtWriteVirtualMemory(
IN HANDLE     ProcessHandle,
IN PVOID       BaseAddress,
IN PVOID       Buffer,
IN ULONG      NumberOfBytesToWrite,
OUT PULONG NumberOfBytesWritten OPTIONAL
);

b4img26

The ‘Buffer’ variable was an important on in the ‘NtWriteVirtualMemory()’ function and that pointed to the address where the possible new process code was present. We could see that in the above screen shot. We could also see the presence of DOS and PE header in the ‘Buffer’ region. So, this was going in the direction as we are expecting.

Our ultimate objective was to debug the newly created process. While through the earlier analysis, we found that ‘NtResumeThread()’ function is the one that is resuming the newly created process to run from the ‘SUSPENDED’ state. Before that we had found that the ’NtSetContextThread()’ function sets the required fields for the thread. The ’NtSetContextThread()’ function uses a CONTEXT structure that has the crucial information on the newly created process.

typedef struct _CONTEXT
{
ULONG ContextFlags;
ULONG Dr0;
ULONG Dr1;
ULONG Dr2;
ULONG Dr3;
ULONG Dr6;
ULONG Dr7;
FLOATING_SAVE_AREA FloatSave;
ULONG SegGs;
ULONG SegFs;
ULONG SegEs;
ULONG SegDs;
ULONG Edi;
ULONG Esi;
ULONG Ebx;
ULONG Edx;
ULONG Ecx;
ULONG Eax;
ULONG Ebp;
ULONG Eip;
ULONG SegCs;
ULONG EFlags;
ULONG Esp;
ULONG SegSs;
UCHAR ExtendedRegisters[512];
} CONTEXT, *PCONTEXT;

The offset of the EAX register was at 0xb0 from the beginning of the structure. The EAX register holds the address of the entry point with respect the SUSPENDED process. So the beginning of the process space (memory address) plus the value 0xb0 will hold the instruction that gets executed first when ‘NtResumeThread()’ function is called. We patched the memory address that this offset was pointing to.

b4img27

Figure 22 - The CONTEXT structure

From the above picture we could see that the CONTEXT structure starts at the address 0x003E009C. So, the address 0x003E009C plus the 0Xb0 yields 0x3E014C.We wanted to see what is there at the address 0x3E014C.

b4img28

Figure 23 - The EntryPoint address within the context structure

The value at the 0x3E014C address was 0x004BFFC0. We know that in most cases the PE binaries are loaded into the address 0x00400000. So, 0x004BFFC0 minus the 0x00400000 gives the control over the first instruction (i.e. at offset 0xBFFC0). We patched the instruction at 0x004BFFC0. We patched the memory region using the ProcessHacker tool.


b4img29

Figure 24 - The first instruction at the EntryPoint is 60 (PUSHAD)

The HEX value at 0Xbffc0 is 60 and it corresponds to PUSHAD instruction. We modified (patch) this to CC (debug) instruction. Basically, the 60 and CC are called OPCODES. OpCodes are nothing but instruction codes in the Intel Microprocessor language.


b4img30

Figure 25 - Patching the instruction to CC (debug) instruction

Once modified, we changed the opcode at the memory location and changed by writing the opcode. Since the 0xcc belongs to breakpoint opcode, we set the Just-In-Time debugger and used the OllyDebugger as the JIT as shown below.


b4img31

Figure 26 - Making OllyDbg to act as JIT debugger

Once this was done, we allowed the ‘NtResumeThread()’ function to continue. We could see that the modified thread fired an exception and was waiting for us to debug!


b4img32

Figure 27 - The newly created process triggers the debug exception

We selected the Debug the program and there you go, we had hunted down the newly created process.


b4img33

Figure 28 - Landing at the patched memory location of the newly created process

Now we have complete control of the process that was playing the role of encrypting the files. Since, we had full control of this process, it was easy for us to look into on the internal workings of this ransomware.

We will have the in-depth analysis of this in our next blog.