2016년 1월 19일 화요일

TrojanDownloader:Win32/Upatre.CQ

* From IBM X-Force Exchange

Analysis of Upatre, the sample can be found on VT:
https://www.virustotal.com/intelligence/search/?query=c3282545c194df07cfdc50e815f05935bf35ab850b7e1fe06298f1f9ee1643b3
Stage 1. 
Contains base64 encoded string in the resource section. This string is converted to binary by calling CryptStringToBinaryA.
The stack before the call:
000CFF14  0040784D  .rsrc:0040784D            ; source
000CFF18  001D48FC                            ; number of characters to convert
000CFF1C  00000001                            ; base64
000CFF20  01D30020  debug025:01D30020        ; destination buffer
    ; .data:004030F5 FD 48 1D 00             dword_4030F5 dd 1D48FDh 
000CFF24  004030F5  .data:dword_4030F5        ; size of destination buffer    
000CFF28  00000000
000CFF2C  00000000
Beginning of base64 encoded string:
0040784D  59 71 34 52 58 45 75 52  45 52 41 52 45 52 47 54  Yq4RXEuRERARERGT
0040785D  46 52 45 68 37 75 34 52  45 61 6B 52 4B 54 77 51  FREh7u4REakRKTwQ
0040786D  45 56 45 56 4B 51 67 52  65 52 45 64 48 77 34 52  EVEVKQgReREdHw4R
0040787D  71 78 38 52 70 52 6A 63  4D 4B 6B 52 45 46 33 63  qx8RpRjcMKkREF3c
0040788D  4D 45 56 35 65 47 49 54  4D 52 45 56 63 44 46 42  MEV5eGITMREVcDFB
0040789D  56 44 46 30 45 57 6C 30  63 6D 52 6C 63 48 4E 39  VDF0EWl0cmRlcHN9
This base64 decoded binary stream is then decompressed. The stack before the call to RtlDecompressBuffer:
000CFEFC  00000002                        ; LZ
000CFF00  00170000  debug026:00170000    ; uncompressed buffer
000CFF04  00001A00
000CFF08  01D30020  debug025:01D30020
000CFF0C  0015E600  debug016:0015E600
000CFF10  000CFF14  Stack[00000980]:000CFF14    ; uncompressed buffer final size
    ; Stack[00000980]:000CFF14 00 1A 00 00             dd 1A00h
The uncopressed buffer contains PE executable image. Analysis of the malware can be found on VT:
https://www.virustotal.com/en/file/887c6d9c699688996ea34c7cd426ca1334d81437668b5715b2d9cc03ff1f9bf5/analysis/1446827644/
Stage 2.
Creates suspended "svchost.exe" process. The content of the "svchost.exe" is replaced with the content of executable decoded and uncompressed in Stage 1.
The malware implements primitive anti-debugging by calling GetTicksCount and stopping execution if returned ticks count is above 0x0AFED8:
.text:004013B3 BB D8 FE 0A 00          mov     ebx, 0AFED8h
.text:004013B8 FF 55 DC                call    dword ptr [ebp-24h]             ; GetTicksCount
.text:004013BB 3B C3                   cmp     eax, ebx 
Stage 3.
This stage contains a downloader that connects to C&C and downloads contents from remote C&C.
The malware uses InternetConnectW -> HttpOpenRequestW -> HttpSendRequestW APIs from wininet library to communicate with malicious C&C.
The stacks before the calls to InternetConnectW:
0014EAFC  00CC0004                                ; handle 
0014EB00  0014EF00  Stack[0000079C]:0014EF00    ; Stack[0000079C]:0014EF00 69 00 63 00 61 00 6E 00+unicode 0, <icanhazip.com>,0
0014EB04  00000050                                ; port
0014EB08  00000000
0014EB0C  00000000
0014EB10  00000003                                ; INTERNET_SERVICE_HTTP
0014EB14  00000000
0014EB18  00000000

0014EAFC  00CC0004
0014EB00  0014EF00  Stack[0000079C]:0014EF00
    ; 0014EF00  36 00 39 00 2E 00 39 00  2E 00 32 00 30 00 34 00  6.9...9...2.0.4.
    ; 0014EF10  2E 00 31 00 31 00 34 00  00 00 00 00 00 00 6E 00  ..1.1.4.......n.
0014EB04  000001BB                                ; 443 SSL
0014EB08  00000000
0014EB0C  00000000
0014EB10  00000003
0014EB14  00000000
0014EB18  00000000
The malware uses ports 80 and 443. Both ports are hard-coded in the code.
The stacks before the calls to HttpOpenRequestW:
0014EAFC  00CC0008                                        ; handle
0014EB00  00000000                                        ; verb = "GET" here.
0014EB04  0014EF00  Stack[0000079C]:aIcanhazip_com        ; object name Stack[0000079C]:0014EF00 2F 00                   db '/',0
0014EB08  00000000                                        ; version
0014EB0C  00000000                                        ; referer
0014EB10  0014EB84  Stack[0000079C]:0014EB84            ; accept types: 
    ; Stack[0000079C]:0014EB84 40 AC 98 02             dd offset aText       ; "text/*"
0014EB14  80000000                                        ; INTERNET_FLAG_RELOAD, forces download from an object not a cache.
0014EB18  00000000

Returned handle: 00CC000C

0014EAFC  00CC0008                                        ; handle
0014EB00  00000000                                        ; verb "GET"
0014EB04  0014EF00  Stack[0000079C]:0014EF00            ; Stack[0000079C]:0014EF00 2F 00 6D 00 6F 00 72 00+unicode 0, </morna5.doc>,0
0014EB08  00000000
0014EB0C  00000000
0014EB10  0014EB84  Stack[0000079C]:0014EB84            ; Stack[0000079C]:0014EB84 40 AC 98 02             dd offset aText         ; "text/*"
0014EB14  80803000                                        ; INTERNET_FLAG_RELOAD | INTERNET_FLAG_SECURE | INTERNET_FLAG_IGNORE_CERT_DATE_INVALID | 
                                                        ; INTERNET_FLAG_IGNORE_CERT_CN_INVALID
0014EB18  00000000
The list of domains and some interestings strings are hard-coded in the malware in the lightly encrypted form.
The encryption schema is simple xor. The xor key is hard-coded and stored right before the encrypted data starts.
The encrypted data is stored by the malware as an array. Each element of the array at offset 0 keeps the length of the encrypted data to follow, for example:
00080FCE  0C ED 27 55 FE 6B 6E 71  84 15 EB C3 59 0D ED 1F  .f'U¦knqä.d+Y.f.
00080FDE  46 EF 6D 64 6E C3 09 A0  DF 50 F1 0A ED 3A 57 F9  Fnmdn+.á¯P±.f:W·
00080FCE - 1b - 0x0C size of the encrypted string.
00080FCD - ED 27 55 FE 6B 6E 71  84 15 EB C3 59 - xor encoded string, becomes "svchost.exe".
The xor key is (length 0x14):
00080FBA  EC 54 23 9D 03 01 02 F0  3B 8E BB 3C 9D 04 46 A6  8T#....=;Ä+<..Fª
00080FCA  0A 5A 94 C6
This key is re-used for each 0x14 bytes of data if encrypted stream is longer 0x14 bytes.
The decrypted data is:
svchost.exe
Kernel32.dll
ntdll.dll
USER32.DLL
wininet.dll
shell32.dll
open
text/*
application/*
GET
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.37 (KHTML, like Gecko) Chrome/45.0.2455.99 Safari/537.37
197.149.90.166
wahsixtin.exe
icanhazip.com
/
24.33.131.116
/morna5.doc
72.230.82.80
173.248.31.6
69.9.204.114
69.144.171.44
24.148.217.188
173.216.247.74
37.57.144.177
68.70.242.203
208.117.68.78
67.222.201.61
203.129.197.50
112.133.203.43
27.109.20.53
213.92.138.154
82.115.76.211
78.72.233.105
82.160.64.45
197.210.199.21
78.108.101.67
109.199.11.51
94.40.82.66
87.126.65.67
93.183.155.22
87.97.168.205
94.40.82.239
188.167.93.231
91.240.236.148
91.240.236.122
93.115.172.232
67.222.201.105
50.24.13.21
202.79.57.155
202.70.89.57
190.121.164.10
181.40.117.66
197.254.116.190
103.239.52.89
111.118.129.116
177.240.223.45
43.248.24.50
197.254.56.126
36.75.215.195
190.152.0.158
190.63.143.11
190.95.138.66
200.124.243.75
200.25.207.173
201.183.120.103
190.152.13.198
The sample program to decrypt the data:
#include <stdio.h>
#include <string.h>
#include <malloc.h>

#pragma warning (disable:4996)

int main()
{
    unsigned char * buffer = 
        "\xEC\x54\x23\x9D\x03\x01\x02\xF0\x3B\x8E\xBB\x3C\x9D\x04\x46\xA6"
        "\x0A\x5A\x94\xC6\x0C\xED\x27\x55\xFE\x6B\x6E\x71\x84\x15\xEB\xC3"
        "\x59\x0D\xED\x1F\x46\xEF\x6D\x64\x6E\xC3\x09\xA0\xDF\x50\xF1\x0A"
        "\xED\x3A\x57\xF9\x6F\x6D\x2C\x94\x57\xE2\x0B\xED\x01\x70\xD8\x51"
        "\x32\x30\xDE\x7F\xC2\xF7\x0C\xED\x23\x4A\xF3\x6A\x6F\x67\x84\x15"
        "\xEA\xD7\x50\x0C\xED\x27\x4B\xF8\x6F\x6D\x31\xC2\x15\xEA\xD7\x50"
        "\x05\xEE\x3B\x53\xF8\x6D\x07\xEE\x20\x46\xE5\x77\x2E\x28\x0E\xEE"
        "\x35\x53\xED\x6F\x68\x61\x91\x4F\xE7\xD4\x52\xB2\x2E\x04\xEE\x13"
        "\x66\xC9\x6D\xEE\x19\x4C\xE7\x6A\x6D\x6E\x91\x14\xBB\x95\x0C\xBD"
        "\x2C\x11\xCF\x64\x3E\xFB\xB1\x9F\x74\x6D\xC9\x23\x37\x2C\xC1\x00"
        "\xAE\xEC\x73\xCA\x32\x72\x8F\x2A\x1B\xE4\xB6\x80\x31\x74\xF8\x61"
        "\x4A\x6B\x84\x14\xBB\x88\x0B\xB3\x37\x71\x86\x22\x11\xDC\x92\xA1"
        "\x18\x0F\xBD\x6F\x68\x69\x95\x1B\xC9\xDE\x5F\xF6\x6B\x6F\x86\x49"
        "\x32\xE6\xA9\x81\x31\x0C\xA9\x36\x2F\x32\xDE\x09\xBA\x8E\x09\xB3"
        "\x3D\x7F\x86\x59\x3B\xF2\xA7\x9E\x3D\x0C\xA8\x30\x36\x2C\xC3\x0C"
        "\x05\xE8\xF2\x79\x08\xC6\x0E\xEE\x23\x42\xF5\x70\x68\x7A\x84\x52"
        "\xE0\x95\x59\xE5\x61\x0E\xEE\x3D\x40\xFC\x6D\x69\x63\x8A\x52\xFE"
        "\x95\x5F\xF2\x69\x02\xEE\x7B\x05\xE8\x20\xA0\xBC\x1B\x0C\xEE\x7B"
        "\x4E\xF2\x71\x6F\x63\xC5\x15\xEA\xD4\x5F\x05\xE8\x04\x71\x7B\x4B"
        "\x05\xE8\x52\x3C\x65\xAE\x05\xE8\x26\xEF\x94\x46\x05\xE8\x78\x88"
        "\x0D\x46\x05\xE8\xE8\xFA\x09\x1B\x05\xE8\x1E\xD4\x45\xAE\x05\xE8"
        "\xE5\xB3\xA4\x26\x05\xE8\x9F\xD1\xDB\x47\x05\xE8\x1A\x67\xE8\xD3"
        "\x05\xE8\x69\xEA\x43\x40\x05\xE8\x66\xE6\x1C\xC8\x05\xE8\x7F\xE8"
        "\x18\x73\x05\xE8\x61\x37\xF0\x18\x05\xE8\xCE\xA9\xC1\xD6\x05\xE8"
        "\x87\x6F\xEE\x51\x05\xE8\x3D\xCA\xD5\x4D\x05\xE8\x79\x63\x3D\x51"
        "\x05\xE8\x41\xE4\x4F\xC6\x05\xE8\x17\x46\xF1\x4D\x05\xE8\x67\x28"
        "\x5A\x6E\x05\xE8\x16\x71\xB5\x5D\x05\xE8\x17\x62\xE3\x54\x05\xE8"
        "\x42\xB8\x2A\x5E\x05\xE8\x99\x8B\xFC\x54\x05\xE8\xBB\x71\xB5\x5D"
        "\x05\xE8\xB3\x7E\x3A\xBF\x05\xE8\xC0\xCF\x6D\x58\x05\xE8\x2E\xCF"
        "\x6D\x58\x05\xE8\xBC\x8F\xEE\x5E\x05\xE8\x3D\xEA\x43\x40\x05\xE8"
        "\x41\x2E\x85\x31\x05\xE8\xCF\x1A\xD2\xC9\x05\xE8\x6D\x7A\xDB\xC9"
        "\x05\xE8\x5E\x87\xE4\xBD\x05\xE8\x16\x56\xB5\xB6\x05\xE8\xEA\x57"
        "\x63\xC6\x05\xE8\x0D\x17\x72\x64\x05\xE8\x20\xA2\xEB\x6C\x05\xE8"
        "\x79\xFC\x6D\xB2\x05\xE8\x66\x3B\x65\x28\x05\xE8\x2A\x1B\x63\xC6"
        "\x05\xE8\x97\xF4\xD6\x27\x05\xE8\xCA\x23\x05\xBD\x05\xE8\x5F\xAC"
        "\xA2\xBD\x05\xE8\x16\xA9\xC2\xBD\x05\xE8\x1F\xD0\xE1\xCB\x05\xE8"
        "\xF9\xEC\x84\xCB\x05\xE8\x33\x5B\x2A\xCA\x05\xE8\x92\x2E\x05\xBD"
        "\x00";
    unsigned int counter = 0x14;
    unsigned short xor_counter = 0, ip_counter = 0;
    unsigned char * ip = NULL;
    unsigned short ip_size = 0;

    while (buffer[counter])
    {
        ip_size = buffer[counter] + 1;
        if (ip)
            ip = (unsigned char *) realloc(ip,sizeof(unsigned char) * ip_size);
        else 
            ip = (unsigned char *) malloc(sizeof(unsigned char) * ip_size);
        if (!ip)
        {
            printf("Failed to allocate buffer.\n");
            return -1;
        }
        counter++;
        memset(ip, 0, ip_size);

        while (ip_counter < ip_size - 1)
        {
            if (xor_counter > 0x13)
                xor_counter = 0;
            
            ip[ip_counter++] = buffer[xor_counter] ^ buffer[counter++];
            xor_counter++;
        }

        if (ip[0] == 0x4)
            printf("%u.%u.%u.%u\n", ip[4], ip[3], ip[2], ip[1]);
        else
            printf("%s\n",&ip[1]);
        xor_counter = 0;
        ip_counter = 0;
    }

    free(ip);

    return 0;
}