How Cyber Criminals Use Malware To Mine LiteCoins
Recently I came across not so well known downloader trojan . While analysing many interesting things were revealed. Download starts by enumerating a specific list of mutexes opened by all process and if found that particular process is terminated .
Followed by generating Install ID and Installer Subroutine . Install ID is generated using a call to GetTickCount() API
It makes connections to a list of c2 server hardcoded in the binary itself . List may contain 2-3 c2 servers . URI is formatted in this way FOLDER/?user=[InstallID]&id=1&type=5&key=[randomly generated key]
key is generated using a sequence of (GetTickCount() * 1664525 ). This key is later on used to decode a payload sent by c2 server .
C2 replies with an encoded binary buffer . This Buffer is decoded using the same key mentioned above
To decode the payload , we will use a very nice 010 Editor Script XorSelection (http://www.sweetscape.com/010editor/scripts/files/XORSelection.1sc) . After decoding using the key mentioned in the URI . We get the following data .
This block of data consists many important fields which are later on used to decode and execute the payload correctly .
The First 4 Bytes act as a signature for the payload which is ‘DDUU’
The real payload to be decompressed starts at offset 0x1c which happens to be a FSG compressed data block and is passed on to FSG Decompression routine . Decompressed data is stored in a memory region ready to be executed.
Apparently after decompression it is evident that binary block revealed is a PE file with MZ / PE Header stripped . Some information related to the MZ/PE header is stored in the previous binary blob .
At offset 0x08 RVA of Import Table address for the striped PE file is stored .
As the binary is allocated at a random base address , it needs to be relocated . For that purpose offset to relocation table is specified at an offset 0x0c in the previous binary blob . But in this case relocation table is bit modified as we are not aware of the preferred base address , malware author has modified the VirtualAddress of IMAGE_BASE_RELOCATION in such a way to carry base offsets only .
Instead of calculating a delta for base relocation it add’s up the base address of allocation to offset
Base address of the binary payload is located at offset 0x04 from where the execution is resumed .
Crafting the payload in an Exe File
We can leverage these predefined fields and given 0x400 constant header size to craft it back to its original PE format .
For that purpose we will use this nasm file (www.phreedom.org/research/tinype/tiny.356/tiny.asm) and align it to 0x400 bytes
; tiny.asm
BITS 32
;
; MZ header
;
; The only two fields that matter are e_magic and e_lfanew
mzhdr:
dw "MZ" ; e_magic
dw 0 ; e_cblp UNUSED
dw 0 ; e_cp UNUSED
dw 0 ; e_crlc UNUSED
dw 0 ; e_cparhdr UNUSED
dw 0 ; e_minalloc UNUSED
dw 0 ; e_maxalloc UNUSED
dw 0 ; e_ss UNUSED
dw 0 ; e_sp UNUSED
dw 0 ; e_csum UNUSED
dw 0 ; e_ip UNUSED
dw 0 ; e_cs UNUSED
dw 0 ; e_lsarlc UNUSED
dw 0 ; e_ovno UNUSED
times 4 dw 0 ; e_res UNUSED
dw 0 ; e_oemid UNUSED
dw 0 ; e_oeminfo UNUSED
times 10 dw 0 ; e_res2 UNUSED
dd pesig ; e_lfanew
;
; PE signature
;
pesig:
dd "PE"
;
; PE header
;
pehdr:
dw 0x014C ; Machine (Intel 386)
dw 1 ; NumberOfSections
dd 0x4545BE5D ; TimeDateStamp UNUSED
dd 0 ; PointerToSymbolTable UNUSED
dd 0 ; NumberOfSymbols UNUSED
dw opthdrsize ; SizeOfOptionalHeader
dw 0x103 ; Characteristics (no relocations, executable, 32 bit)
;
; PE optional header
;
filealign equ 1
sectalign equ 1
%define round(n, r) (((n+(r-1))/r)*r)
opthdr:
dw 0x10B ; Magic (PE32)
db 8 ; MajorLinkerVersion UNUSED
db 0 ; MinorLinkerVersion UNUSED
dd round(codesize, filealign) ; SizeOfCode UNUSED
dd 0 ; SizeOfInitializedData UNUSED
dd 0 ; SizeOfUninitializedData UNUSED
dd start ; AddressOfEntryPoint
dd code ; BaseOfCode UNUSED
dd round(filesize, sectalign) ; BaseOfData UNUSED
dd 0x400000 ; ImageBase
dd sectalign ; SectionAlignment
dd filealign ; FileAlignment
dw 4 ; MajorOperatingSystemVersion UNUSED
dw 0 ; MinorOperatingSystemVersion UNUSED
dw 0 ; MajorImageVersion UNUSED
dw 0 ; MinorImageVersion UNUSED
dw 4 ; MajorSubsystemVersion
dw 0 ; MinorSubsystemVersion UNUSED
dd 0 ; Win32VersionValue UNUSED
dd round(filesize, sectalign) ; SizeOfImage
dd round(hdrsize, filealign) ; SizeOfHeaders
dd 0 ; CheckSum UNUSED
dw 2 ; Subsystem (Win32 GUI)
dw 0x400 ; DllCharacteristics UNUSED
dd 0x100000 ; SizeOfStackReserve UNUSED
dd 0x1000 ; SizeOfStackCommit
dd 0x100000 ; SizeOfHeapReserve
dd 0x1000 ; SizeOfHeapCommit UNUSED
dd 0 ; LoaderFlags UNUSED
dd 16 ; NumberOfRvaAndSizes UNUSED
;
; Data directories
;
times 16 dd 0, 0
opthdrsize equ $ - opthdr
;
; PE code section
;
db ".text", 0, 0, 0 ; Name
dd codesize ; VirtualSize
dd round(hdrsize, sectalign) ; VirtualAddress
dd round(codesize, filealign) ; SizeOfRawData
dd code ; PointerToRawData
dd 0 ; PointerToRelocations UNUSED
dd 0 ; PointerToLinenumbers UNUSED
dw 0 ; NumberOfRelocations UNUSED
dw 0 ; NumberOfLinenumbers UNUSED
dd 0x60000020 ; Characteristics (code, execute, read) UNUSED
hdrsize equ $ - $$
;
; PE code section data
;
align filealign, db 0
code:
; Entry point
times 672 db 0 ; ALIGN it to 0x400 bytes
start:
;hex binary blob here
After copying the hex bytes and modifying the offset to IAT . We get a nicely made PE file but we still need to fix the relocations . As mentioned above .reloc table for this block has been modified by the author so we cannot force the PE loader to fix the address for us at 0x400000. Rather we will use a slightly modified relocation program or we can patch the value added to the base relocation offset .
delta = (unsigned int) OptHdr.ImageBase;
printf("\n Delta = 0x%x, Prefered Base = 0x%x\n", (unsigned int)delta, (unsigned int)OptHdr.ImageBase);
pRelocEntry = (PIMAGE_BASE_RELOCATION) ((unsigned int) OptHdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress + (unsigned int)pMappedImage);
printf("0x%p", pRelocEntry);
debug();
while ( pRelocEntry->VirtualAddress)
{
iRelocVaddr = pRelocEntry->VirtualAddress;
RelocBlockSize = (pRelocEntry->SizeOfBlock - 8) / 2;
pRelocEntry = (unsigned char*)pRelocEntry + 8;
while (RelocBlockSize--)
{
if (*(unsigned short*)pRelocEntry == 0x3000)
{
pRelocEntry = (unsigned char*)pRelocEntry + 2;
continue;
}
FixUp = (unsigned int*)(*(unsigned short*) pRelocEntry & 0x0fff);
printf("\nFixup value before adding = %x, Page base = %x", FixUp, iRelocVaddr);
FixUp = (unsigned int*)((unsigned int)FixUp +((unsigned int) pMappedImage + (unsigned int)iRelocVaddr));
printf("\nOriginal Address = 0x%p", *FixUp);
*FixUp = *FixUp + delta; // Add offset
pRelocEntry = (unsigned char*)pRelocEntry + 2;
printf("\nReloc Entry = %x", FixUp);
}
}
After fixing entry point and rebuilding in Nasm , we get a PE file with a valid import address table
And it makes use of complex CPU instructions for greater speed in mining Litecoins
which apparently is a compiled version of open source litecoin CPU miner program https://github.com/pooler/cpuminer/ which as expected is having only 2 AV detections
Three more function are loaded at offsets 0x14, 0x18 , 0x10 and is later called with parameters received from c2
And so starts the mining process :)