How Cyber Criminals Use Malware To Mine LiteCoins

43227_dirty_old_gold_miner_finding_nuggets_in_his_tray.jpg

_009D0000.png

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 .

FinalAnalysis.odt.png
FinalAnalysis.odt.png

Followed by generating Install ID and Installer Subroutine . Install ID is generated using a call to GetTickCount() API

3.png

4.png

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

5.png

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 .

6.png

The First 4 Bytes act as a signature for the payload which is ‘DDUU’

FinalAnalysis.odt.png

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.

FinalAnalysis.odt.png

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 .

FinalAnalysis.odt.png

FinalAnalysis.odt.png

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

FinalAnalysis.odt.png

Base address of the binary payload is located at offset 0x04 from where the execution is resumed .
FinalAnalysis.odt.png

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 .

FinalAnalysis.odt.png

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

FinalAnalysis.odt.png

And it makes use of complex CPU instructions for greater speed in mining Litecoins
FinalAnalysis.odt.png

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

FinalAnalysis.odt.png

Three more function are loaded at offsets 0x14, 0x18 , 0x10 and is later called with parameters received from c2

FinalAnalysis.odt.png
FinalAnalysis.odt.png

FinalAnalysis.odt.png

FinalAnalysis.odt.png

And so starts the mining process :)

 
22
Kudos
 
22
Kudos

Now read this

Analysing Windows Malware on Apple Mac M1/M2 ( Windows 11 ARM ) - Part I

x86/x64 emulation internals on Windows 11 ARM # Introduction # Since the introduction of Intel processors for the MacBooks, malware analysis on Mac has become quite popular, and it has become the hardware of choice for malware analysts.... Continue →