Manual analysis of Downloader.CUZ malware - rsrc Section

In this article I will describe the manual approach that I followed to analyze one of the numerous features of Downloader.CUZ malware.

Downloader.CUZ is straightforward to analyze because it is not obfuscated and does not use advanced techniques to hide its behavior. Here I describe how it uses Portable Executable format to store an embedded executable file.

Target

The following are the main characteristics of Downloader.CUZ malware:

  • It runs on Windows
  • It is known already
  • It is simple to analyze
Name MD5 Download
Downloader.CUZ 149210e204404d9ac13aee43b9a7e4a7 Link

This malware does a lot of activities. Here I will analyze how it embed a binary file into itself, extract it and save it on the disk as a new malicious file.

.rsrc Section

The Portable Executable (PE) specifies the structure of executable files on Microsoft Windows. PE format defines headers and sections.

PE file header provide considerably information about file type and structure. PE file sections follow PE header, and contains useful information. The most common sections in a PE file are:

  • .text
  • .rdata
  • .data
  • .rsrc

For a detailed description about PF format see [1].

.rsrc section contains the resources used by the executable, such as icons, images and menus. Malwares can use this section also to embed arbitrary data, such as an executable file.

Analysis

The analyzed version of Downloader.CUZ has 4 sections: .text, .rdata, .data, .rsrc.

Section viewer

Awesome tools like ResourceHacker allow to get an overview of the resources into a .rsrc section. Unfortunatly a malware can use custom logic to hide its resources. An in-depth analyses maybe required to extract these embedded data.

The following are the main Windows APIs to use resources: FindResourceA, LoadResource, LockResource. There are others APIs, but for the purpose of this articole these are enough.

Locating one of the above APIs allow to identify the malware routine that uses .rsrc section: sub_401BA0

Win32 FindResourceA() - XREFS

sub_401BA0 has 5 main parts:

  1. Extracts a resource named: 0x6a
  2. Extracts a resource named: 0x69
  3. Merges resources (1) and (2) creating a new file
  4. Saves file (3) to GetSystemDirectory()\lsasvc.exe
  5. Run malicous file (4)

The resource extractions at (1) and (2) are plain. The code initializes resourceName, resourceType and calls WinAPIs FindResourceA, LoadResource and LockResource.

sub_401BA0 - Load resource

Instead, the merge at (3) worth a deeper review. I wrote above that .rsrc section contains 2 resources, named: 0x6a and 0x69. The merge process can be summarized as below:

(1) Take 0x400 bytes of the resource 0x6a

sub_401BA0 - Merge resource - Step 1

(2) Take 0x400 bytes of the resource 0x69, 17 times

sub_401BA0 - Merge resource - Step 2

(3) Take 0x621 bytes of the resource 0x69, skipping its first 0x4400 bytes

sub_401BA0 - Merge resource - Step 3

When completed, merge routine creates a file in GetSystemDirectory()\lsasvc.exe.

Dump!

It is straightforward to create a tool to extract the resource identified in this analysis. The tool below can be launched with the following command:

C:\tmp\> dump.exe C:\tmp\MalwareFolder downloadercuz.exe C:\tmp\resource.bin

#include <Windows.h>
#include <stdio.h>

static LPCVOID LoadMalwareResource(HINSTANCE hModule, const char* resourceName, const char* resourceType) {

	HRSRC hsrc = FindResourceA(hModule, resourceName, resourceType);

	if (!hsrc) {
		fprintf(stderr, "[E][LoadMalwareResource] FindResourceA(): failed! (%d)\n", GetLastError());
		return NULL;
	}

	HGLOBAL hResource = LoadResource(hModule, hsrc);

	if (!hResource) {
		fprintf(stderr, "[E][LoadMalwareResource] LoadResource(): failed! (%d)\n", GetLastError());
		return NULL;
	}

	LPCVOID resource = LockResource(hResource);

	if (!resource) {
		fprintf(stderr, "[E][LoadMalwareResource] LockResource(): failed! (%d)\n", GetLastError());
	}

	return resource;
}

static HINSTANCE LoadMalware(const char* malwareFilePath, const char* malwareFileName) {

	size_t len = strlen(malwareFilePath) + strlen(malwareFileName) + 2;
	char* filename = malloc(len);

	if (!filename) {
		fprintf(stderr, "[E][LoadMalware] free(): failed! (%d)\n", GetLastError());
		return NULL;
	}

	snprintf(filename, len, "%s\\%s", malwareFilePath, malwareFileName);

	HINSTANCE hFile = LoadLibraryA(filename);
	free(filename);

	if (!hFile) {
		fprintf(stderr, "[E][LoadMalware] LoadLibraryA(): failed! (%d)\n", GetLastError());
		return NULL;
	}

	HINSTANCE hModule = GetModuleHandleA(malwareFileName);

	if (!hModule) {
		fprintf(stderr, "[E][LoadMalware] GetModuleHandle(): failed! (%d)\n", GetLastError());
	}

	return hModule;
}

static int SaveMalwareResource(const char* outputFileName, LPCVOID hrA, LPCVOID hrB) {
	
	HANDLE hFile = CreateFileA(outputFileName,
				   GENERIC_WRITE,
				   FILE_SHARE_WRITE,
				   NULL,
				   CREATE_ALWAYS,
				   FILE_ATTRIBUTE_NORMAL,
				   NULL);

	if (hFile == INVALID_HANDLE_VALUE) {
		fprintf(stderr, "[E][SaveMalwareResource] CreateFileA(): failed! (%d)\n", GetLastError());
		return -1;
	}

	long iBytesWritten;
	WriteFile(hFile, hrA, 0x400, &iBytesWritten, NULL);

	const void* phrB = hrB;

	for (int i = 0; i < 17; ++i) {
		WriteFile(hFile, phrB, 0x400, &iBytesWritten, NULL);
		phrB = (char *)phrB + 1024;
	}

	WriteFile(hFile, (char *)hrB + 17408, 0x621, &iBytesWritten, NULL);

	CloseHandle(hFile);

	return 0;
}

int main(int argc, char** argv) {

	if (argc != 4) {
		return -1;
	}

	const char* malwareFilePath = argv[1];
	const char* malwareFileName = argv[2];
	const char* outputFileName = argv[3];

	HINSTANCE hMalware = LoadMalware(malwareFilePath, malwareFileName);

	if (!hMalware) {
		return -1;
	}

	const char* resourceType = "RT_RCDATA";
	LPCVOID hrA = LoadMalwareResource(hMalware, (const char*) 0x6a, resourceType);
	LPCVOID hrB = LoadMalwareResource(hMalware, (const char*) 0x69, resourceType);

	SaveMalwareResource(outputFileName, hrA, hrB);

	return 0;
}

References

Updated: