Small, yes delete: Trojan-Downloader.Win32.Tiny

    Good day to all.
    There are a lot of technical details in today's release. So excuse me if there are too many :)

    Letter


    So here we go. At the entrance we have a letter with the text “Journalist shot in Georgia! See attached video. Password is 123 ”and with the attached file“ Georgia.zip ”.

    For a more or less complete analysis we will need:
    - The best disassembler in the world IDA
    - A good Windbg Debugger
    - python 2.5 (strictly speaking, anyone will, just my 2.5)
    - Visual Studio some and Microsoft SDK to build a small program on c ++.
    - upx program packer
    - and something else on the little things.

    We unpack the file sent to us, and we see that our suspicions are justified: the video didn’t spend the night there.
    joined.exe (md5: 607af96b03addadf28cf9280701df191)
    Dr.Web: Trojan.Packed.151
    Kaspersky: Trojan-Downloader.Win32.Agent.abqe
    


    Unpacking


    The first attack. We save the file to a safe place, remove the execute rights from it, upload it to ida. Immediately, ida swears at the IAT in a non-standard section and warns that not all imported functions will be visible, we agree to continue. After that, ida thinks a little, disassembling and analyzing our file, and, having finished, it goes to Entry Point itself.



    We see some large and complex calculations in the “Navigation” window, and by pressing Ctrl-S, in the list of segments that opens, we see two entries: “UPX0” and “UPX1”. And this is clearly given to us in Mogza: “packaged upx”. More precisely, there is a possibility that upx is packed, and we set off to check this opportunity.

    D: \ programs \ upx> upx -t D: \ prog \ virus \ 0001.Georgia-2008-08-25 \ joined.exe
    testing D: \ prog \ virus \ 0001.Georgia-2008-08-25 \ joined.exe [OK]
    That is, upx recognized its file. We pack:
    D: \ programs \ upx> upx -d D: \ prog \ virus \ 0001.Georgia-2008-08-25 \ joined.exe
            File size Ratio Format Name
       -------------------- ------ ----------- ----------
         10240 <- 7680 75.00% win32 / pe joined.exe
    Unpacked 1 file.
    

    After that, open the unpacked file in ida and quickly look through it.



    The main function looks quite simple: first, some configuration is done using LoadLibrary and GetProcAddress, so as not to shine the functions used in the import. After that comes a call to EnumResourceNames, which lists all resource names. Well, resources, this is interesting, let's see what is in the resources of our file.

    We open the resource editor (I have an old ResourceExplorer), and we see, among other things, an excellent binary resource called "LOADER.19B099.EXE". The executable file inside the resource! Well, it is very likely that the main virus exports the attached virus and launches in some way. I propose for now to postpone the first file and pick this binary resource.



    Trojan in a Trojan



    We export the resource to a file, look what antiviruses say.

    resource-loader.19b099.exe (md5: ca843aed6a7910fcb36bd0146af990ca)
    Dr.Web: Trojan.Packed.151
    Kaspersky: Trojan-Downloader.Win32.Tiny.bvi
    

    (Note, by the way, that Dr.Web marks this file as well as joined.exe).

    Well, firstly, size. 1.6 kilobytes. So they worked thoroughly with a file, forced the compiler to optimize, and in general tried their best. Secondly, such code can easily be injected into some other process - if this code is, of course, correctly written. Thirdly, no imports at all - another plus to the shellcode hypothesis. Well, and fourthly, the body is “encrypted”. Here’s what’s going on at the entry point:



    We see that the code calculates where it is (receives EIP using fnstenv), runs from this place back to the beginning of the current page, that is, roughly speaking, until the last three characters of the address become zero. This is done because the code starts at offset 00001000h relative to the beginning of the image of the file in memory. The decompression algorithm is as follows:

    byte * data = [EIP] obtained by cunning manipulations.
    x = 0A9h;
    while (data & 0xFFF)
    {
    	* data = * data ^ x;
    	x--;
    	data--;
    }

    After that, control is transferred somewhere in the middle of the unpacked code.

    Unpacking-2


    Well, once the file unpacks itself, let it do it. We just need to stop in the right place to see the unpacked code. Run Windbg, press Ctrl-E (Open executable file), after that the debugger stops. This is not an entry point, but only the beginning of the process. Find out the entry point (if we suddenly forgot it when we looked at the disassembled code):

    0: 001>! Dh 00400000 
    File Type: EXECUTABLE IMAGE
    ...
    OPTIONAL HEADER VALUES
         10B magic #
        7.10 linker version
         400 size of code
         200 size of initialized data
           0 size of uninitialized data
    
        132F address of entry point		
    
        1000 base of code


    Go to it:
    0: 000> g 40132F 
    


    We are interested in the final stage of decryption: switching to the decrypted code that occurs in the line:
    .text: 0040135D push offset dword_401135
    

    Go here:
    0: 000> bp 0040135D
    

    Press "g" (Go), and do not have time to blink an eye as the program stops. By the way, we can see right here how this code looks now. At the address where the transition is planned, is this:

    0: 000> uf 00401135
    image00400000 + 0x1135:
    00401 135 55 push ebp
    00401 136 6bec mov ebp, esp
    00401138 81ec98060000 sub esp, 698h
    0040113e 53 push ebx
    


    Well, that’s fine. We start some LordPE, dump the file, and the code in the disassembler now looks more readable. The file size has not changed, it is still tiny. It has only three functions. Let's study them.

    Core functionality



    That's what is at the entry point.



    Of particular interest is a bunch of this type:
    mov ecx, 0D82AFA6Fh
    call my_get_proc_address
    ...
    call eax             
    


    Through ECX, the parameter is passed to the my_get_proc_address function (I called it that. In the original, it was called sub_00401135 :), and what it returns is nothing more than the address of a certain function to which the call instruction is transferred.

    What does my_get_proc_address function do?

    (There is a lot of code there, those who are not lazy will look for themselves, see below). In short:

    1. Gets a pointer to a PEB:
    mov eax, large fs: 30h


    By the way, we can also see what is located there:
    0: 000> dt nt! _PEB
    ntdll! _PEB
       + 0x000 InheritedAddressSpace: UChar
       + 0x001 ReadImageFileExecOptions: UChar
       + 0x002 BeingDebugged: UChar
       + 0x003 SpareBool: UChar
       + 0x004 Mutant: Ptr32 Void
       + 0x008 ImageBaseAddress: Ptr32 Void
       + 0x00c Ldr: Ptr32 _PEB_LDR_DATA
       + 0x010 ProcessParameters: Ptr32 _RTL_USER_PROCESS_PARAMETERS
       + 0x014 SubSystemData: Ptr32 Void
    ...
    


    2. Obtains a list of loaded modules from PEB and walks through it. We also know where this list lies:

    0: 000> dt -r1 nt! _PEB
    ntdll! _PEB
    ...
       + 0x00c Ldr: Ptr32 _PEB_LDR_DATA
          + 0x000 Length: Uint4B
          + 0x004 Initialized: UChar
          + 0x008 SsHandle: Ptr32 Void
          + 0x00c InLoadOrderModuleList: _LIST_ENTRY
          + 0x014 InMemoryOrderModuleList: _LIST_ENTRY
          + 0x01c InInitializationOrderModuleList: _LIST_ENTRY
    ...
    


    3. For each of these modules, the function finds the export table, "gets a list" of exported functions. For each exported function, a certain hash is calculated, which is compared with the same strange number that is passed to the function as an argument.



    By the way, this is a classic of the silkcode genre. Yes, this works a little slower than the usual import procedure, but it hides the names of the functions used well. How do we find those functions that are actually used? In principle, there is an option to put a breakpoint where you need to wait. But since progress does not stand still, and we cannot be left behind, we will digress briefly from analysis and do programming.



    So, this very function is quite simple. We will program it. How on what, on a python! He is now everywhere, and in Google they say they love him.

    #! bin / python
    def rotl (x, n):
        return ((x << n) | (x >> (32-n)))% 2 ** 32
    def hash (s):
        x = 0
        for i in s:
            x = (rotl (x, 5) ^ ord (i))% 2 ** 32
        return x
    


    Python with its support for large numbers prevents us, so we emulate 32-bit arithmetic, taking a module of 2 32 .

    So we recall what we talked about before: "for all exported functions of all modules." But wait a minute, attentive readers will say. After all, shellcode does not import anything! Gotcha! and they rub their hands pretty :) But there is such an eternal Russian sadness in windows executables: when creating a new win32 process from a PE file, the bootloader always loads two standard libraries into it: ntdll and kernel32. Here we already have a list of two modules.

    The good news is that we can also get the names of the functions that these libraries export! Old-old dumpbin utility. And cygwin, of course, would be nice to have on hand.

    dumpbin / exports C: \ WINDOWS \ system32 \ kernel32.dll> krnl-exp 
    gawk '{print $ 4}' krnl-exp> krnl-exp1 
    


    Well, the same for ntdll. Then in the editor we remove the remnants of the header and the total generated by dumpbin, getting the list as a result. We set our python script on these files, we get that for example “0xd82afa6f” means “LdrLoadDll” - an o-very poorly documented function used by the bootloader. However, its name speaks for itself - it loads the library into the address space of the process. As we saw earlier, the line “ole32.dll” appears in the disassembled code, yes, for sure, this is exactly what the malware loads with the LdrLoadDll function.

    We make passes with dumpbin and over ol32.dll, we find with our homegrown bruteforce all the "secret" functions (in the order of the call).

    0xd82afa6f - "LdrLoadDll"
    0x872b8a64 - "GetTempPathW"
    0x4b99cb08 - "CoInitializeEx"
    0x938ed88c - “CoInitializeSecurity”
    0x7279d017 - “CoCreateInstance”
    0xbde95c09 - “GetTempFileNameW”
    0x050798d0 - “Sleep”
    0x4b09a52a - “CreateProcessW”
    0x0f12e6f0 - “
    Use

    process value 0x0f12e6d0dleid we initialize COM (CoInitialize *), create a COM object (CoCreateInstance), get the name of the temporary file (GetTemp *), wait by the sea for weather (Sleep), create a process (CreateProcessW), exit (everything else). Brr, even frost on the skin, how methodically and evenly they are going to infect us with some muck.

    In general, the biggest nuisance is CoCreateInstance and the subsequent CreateProcess. Because calls to methods of the com-object are made dynamically, and these methods are not named at all. That is, we, of course, can find out what is called there, but it will be hemorrhoids ... And what to do.

    What kind of object does this reptile create? Two Guids are passed to CoCreateInstance - in the code they look like this:
    .text: 00401000 rclsid dd 4991D34Bh, 429180A1h, 2833B683h, 97906B36h
    .text: 00401010 riid dd 5CE34C0Dh, 4C1F0DC9h, 0A1DA7C89h, 7CEE8CB7h
    


    Due to the nature of data storage, a “user-friendly” guid looks “jumbled”, for example, if in memory the array {5CE34C0Dh, 4C1F0DC9h, 0A1DA7C89h, 7CEE8CB7h}, means {5CE34C0D-0DC9-4C1F-897C-DAA1B78CEE7C}. Well, something already. The author of the shellcode included the hardcode guid, which means he is sure that on most machines this will work. We look up these identifiers in our registry and get:

    {5CE34C0D-0DC9-4C1F-897C-DAA1B78CEE7C} 
    InProcServer32 = C: \ WINDOWS \ system32 \ qmgrprxy.dll = Background Intelligent Transfer Service Proxy
    {4991d34b-80a1-4291-83b6-3328366b9097}
    Background Intelligent Transfer Control Class 1.0
    


    The ominous shadow of a “reasonable” file upload service looms behind these identifiers. Background Intelligent Transfer Service, or in common terms, BITS, is, by the way, the very thing that downloads updates from the Internet for windows. In short, there is a suspicion that in this way a com-object is created that with the help of BITS pumps another, more dangerous virus to our machine. But this is only speculation so far, and we are heading to the MSND for BITS documentation.

    Having rummaged a bit, we find a small code example in Connecting to the BITS Service .

    hr = CoCreateInstance (__ uuidof (BackgroundCopyManager), NULL,
                            CLSCTX_LOCAL_SERVER,
                            __uuidof (IBackgroundCopyManager),
                            (void **) & g_pbcm);
    


    We compile, disassemble, look what happened in our demo program:

    lea eax, [ebp + ppv]
    push eax; ppv
    push offset dword_408140; riid
    push 4; dwClsContext
    push 0; pUnkOuter
    push offset dword_408130; rclsid
    call ds: CoCreateInstance
    ...
    .rdata: 00408130; CLSID dword_408130
    .rdata: 00408130 dword_408130 dd 4991D34Bh, 429180A1h, 2833B683h, 97906B36h; 0
    .rdata: 00408140; IID dword_408140
    .rdata: 00408140 dword_408140 dd 5CE34C0Dh, 4C1F0DC9h, 0A1DA7C89h, 7CEE8CB7h; 0
    


    Actually, as required. Those Guids! Trying to find out what exactly is downloaded using BITS, we see that the file name is “encrypted”.


    Again, quickly write a python script that decrypts this line for us:
    def xor (enc, key):
        res = ''
        for x in enc:
            y = (x ^ key)% 255
            if y == 0:
                break
            key = (key + 1)% 2 ** 32;
            res = res + (chr (y))
        return res
    


    ... and we get a result that shakes us to the core !!!

    http://reddii.org/traffic/all/files/filebyaka.exe 
    

    (Attention! There is still a virus on the specified address. An attempt to open this file can end fatally for you and your machine).

    The name speaks for itself. This is byaka, and what a mess!

    filebyaka.exe (md5: fc85dab5849416f8796b799fc209395a)
    Dr.Web: Trojan.Packed.619
    Kaspersky: Backdoor.Win32.Agent.ajd
    


    Actually, you can find the analysis of this issue at xanalysis.blogspot.com , which was suggested in the comments .

    Everything that happens next, we can predict, without even returning to the debugger. A job is created for BITS, the download starts. Then every 10 milliseconds the status of the task is checked. When the download is completed, the downloaded file is launched. Phew, sweat kilobytes, and so much fuss!

    Total


    The “big” Trojan horse inside itself contains a “small” Trojan foal as a resource. This virus, only one and a half kilobytes in size (these are two pages of text in my editor), can download and run another, more dangerous virus. It is made in the style of silkcode, directly "according to the textbook". Used on most of the techniques used in the article discussed in detail Evolving Shell Code. The Trojan makes a small feint with its ears, and instead of implementing network connections, http protocol, etc., it simply uses the windows service called Background intelligent transfer service (this is what allows reducing the code size). System functions are not called at direct addresses, and functions that are used to work with files, such as CreateFile, are not called at all. There is a big doubt that any of the existing antiviruses can identify such malicious functionality with heuristic analysis alone. This baby downloads a file with the graceful name filebyaka.exe, which means you know what roots you are.

    Files used in the analysis can be found at this address.

    On this optimistic note, I say goodbye to you. Do not run unfamiliar files. Take care of yourself!

    Also popular now: