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.
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
sub_401BA0 has 5 main parts:
- Extracts a resource named: 0x6a
- Extracts a resource named: 0x69
- Merges resources (1) and (2) creating a new file
- Saves file (3) to GetSystemDirectory()\lsasvc.exe
- 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.
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
(2) Take 0x400 bytes of the resource 0x69, 17 times
(3) Take 0x621 bytes of the resource 0x69, skipping its first 0x4400 bytes
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;
}