Most Popular Blogs

  1. DbgEng based Kernel Debugger

    DbgEng based Kernel Debugger

    refer to the prior articles discussing how to use dbgeng functions and make a simple user mode debugger in part 1
    building upon it attaching to a local kernel and peeking around kernel memory was discussed in part 2 and part 2 contd...

    lets see how to make a real kernel debugger (KD clone) using dbgeng interfaces
    remember the steps we used to create a user mode debugger ? if not refresh by visiting
    Creating A client using DebugCreate querying other required interfaces ,implementing the callbacks Setting a console ctrl+c handler a common exit releasing the interfaces and a main
    where a process was created and an infinte loop waiting for events and exiting when debuggee exits

    now copy paste the whole folder you created in the part 1 example
    (dbgengdbg.cpp , sources file , makefile , prebuild.bat the test folder that contains all windbg dlls )
    rename dbgengdbg.cpp to dbgengKD.cpp change the sources file to reflect the renaming

    and make one simple change in the dbgengKD.cpp

    Comparing files dbgengdbg.cpp and ..\DBGENGKD\DBGENGKD.CPP
    ***** dbgengdbg.cpp
            SetConsoleCtrlHandler(&HandlerRoutine,TRUE);  // Set control +c handler 
            if ((Status = g_Client->CreateProcess(0, Argv[1], DEBUG_ONLY_THIS_PROCESS)) != S_OK)  // create a process 
            SetConsoleCtrlHandler(&HandlerRoutine,TRUE);  // Set control +c handler 
            if ((Status = g_Client->AttachKernel(DEBUG_ATTACH_KERNEL_CONNECTION, "com:pipe,port=\\\\.\\pipe\\debugPipe,resets=0,recnnect")) != S_OK)  // create a process 
    and build

    the resulting binary is now capable of attaching to a real machine via any of the connection methods

    the connection method i have provided in this example is to connect to a virtual machine using serial interface redirected to a NamedPipe

    provide appropriate connection strings and you can connect via 1394 \ vmkd \ usb\ the new win8 network protocol apart from the trusty old serial and null modem cable

    just start the binary and it will wait for a kernel connection on com port 1
    start the vm on kernel debugging mode and connect for real kernel debugging session

    or if you have a vm running in debug mode hit the ctrl+sysreq in the vm and connect to the binary for a kd session

    see below

    Microsoft (R) Windows Debugger Version 6.12.0002.633 X86
    Copyright (c) Microsoft Corporation. All rights reserved.
    Opened \\.\pipe\debugPipe
    Waiting to reconnect...
    Connected to Windows XP 2600 x86 compatible target at (Sat Jan 26 03:46:12.656 2
    013 (UTC + 5:30)), ptr64 FALSE
    Kernel Debugger connection established.
    Symbol search path is: SRV*F:\symbols*
    Executable search path is:
    Windows XP Kernel Version 2600 (Service Pack 3) UP Free x86 compatible
    Product: WinNt, suite: TerminalServer SingleUserTS
    Built by: 2600.xpsp.080413-2111
    Machine Name:
    Kernel base = 0x804d7000 PsLoadedModuleList = 0x8055b1c0
    Debug session time: Sat Jan 26 03:40:03.650 2013 (UTC + 5:30)
    System Uptime: 0 days 2:54:32.638
    Break instruction exception - code 80000003 (first chance)
    *                                                                             *
    *   You are seeing this message because you pressed either                    *
    *       CTRL+C (if you run kd.exe) or,                                        *
    *       CTRL+BREAK (if you run WinDBG),                                       *
    *   on your debugger machine's keyboard.                                      *
    *                                                                             *
    *                   THIS IS NOT A BUG OR A SYSTEM CRASH                       *
    *                                                                             *
    * If you did not intend to break into the debugger, press the "g" key, then   *
    * press the "Enter" key now.  This message might immediately reappear.  If it *
    * does, press "g" and "Enter" again.                                          *
    *                                                                             *
    804e3593 c20400          ret     4
    kd>!process 0 0 letsreversewomen.exe
    PROCESS ffad4960  SessionId: 0  Cid: 01d8    Peb: 7ffde000  ParentCid: 0114
        DirBase: 03d77000  ObjectTable: e119d860  HandleCount:  48.
        Image: letsreversewomen.exe
    kd>.process /p /r ffad4960
    Implicit process is now ffad4960
    .cache forcedecodeuser done
    Loading User Symbols
    804e3593 c20400          ret     4
    kd>s -[l 7]sa 12f500 L?9000
    0012fa34  "{FF24CF9A-EE48-4cde-AC10-15D1CE2"
    0012fa54  "C272C}.dat"
    0012fa97  "|{83D33F3A-9482-446f-ABFF-7B69D5"
    0012fab7  "8C1634}"
    0012fc78  "C:\DOCUME~1\rr\LOCALS~1\Temp\"
    0012fd2c  "C:\Documents and Settings\rr\Des"
    0012fd4c  "ktop\letsreversewomen\letsrevers"
    0012fd6c  "ewomen.exe"
    0012fdcc  "{A37340FD-F043-41e3-9C16-2F26323"
    0012fdec  "87199}"
    kd>.echo ollydbgs ghost is creating a file named <guid>.dat in temp folder and
    ollydbgs ghost is creating a file named <guid>.dat in temp folder and
    i have attached the cpp . sources and make file tweak the connection string to your preference build and enjoy your own KD.exe:)

    code for ready reference

    #include <windows.h>
    #include <stdio.h>
    #include <string.h>
    #include <dbgeng.h>
    IDebugClient*        g_Client        = NULL; // globals
    IDebugControl*        g_Control        = NULL; // globals
    IDebugBreakpoint*    g_Breakpoint    = NULL; // globals
    bool                State            = NULL; // globals
    void Exit(int Code, PCSTR Format, ...)        // release the interfaces on last in first out  basis
        if (g_Control != NULL)                    // print message if given 
            g_Control->Release();                // and exit the program
            g_Control = NULL;
        if (g_Client != NULL)
            g_Client = NULL;
        if (Format != NULL)
            va_list Args;
            va_start(Args, Format);
            vfprintf(stderr, Format, Args);
    class EventCallbacks : public DebugBaseEventCallbacks   // event callback class has 16 methods
        STDMETHOD_(ULONG, AddRef)        ( THIS );
        STDMETHOD_(ULONG, Release)        ( THIS );
        STDMETHOD(Breakpoint)            ( THIS_ IN PDEBUG_BREAKPOINT Bp );
        STDMETHOD(ChangeDebuggeeState)    ( THIS_ IN ULONG Flags, IN ULONG64  Argument );
        STDMETHOD(ChangeEngineState)    ( THIS_ IN ULONG Flags, IN ULONG64  Argument );
        STDMETHOD(ChangeSymbolState)    ( THIS_ IN ULONG Flags, IN ULONG64  Argument );
        STDMETHOD(CreateThread)            ( THIS_ IN ULONG64  Handle, IN ULONG64  DataOffset,IN ULONG64  StartOffset);
        STDMETHOD(Exception)            ( THIS_ IN PEXCEPTION_RECORD64 Exception, IN ULONG FirstChance );
        STDMETHOD(ExitProcess)            ( THIS_ IN ULONG  ExitCode );
        STDMETHOD(ExitThread)            ( THIS_ IN ULONG  ExitCode );
        STDMETHOD(GetInterestMask)        ( THIS_ OUT PULONG Mask );
        STDMETHOD(SessionStatus)        ( THIS_ IN ULONG Status );
        STDMETHOD(SystemError)            ( THIS_ IN ULONG  Error, IN ULONG  Level );
        STDMETHOD(UnloadModule)            ( THIS_ IN PCSTR  ImageBaseName, IN ULONG64  BaseOffset );
        STDMETHOD(LoadModule)            ( 
            THIS_ IN ULONG64 ImageFileHandle, IN ULONG64 BaseOffset, IN ULONG ModuleSize,
            IN PCSTR ModuleName,IN PCSTR ImageName,  IN ULONG CheckSum, IN ULONG TimeDateStamp );
        STDMETHOD(CreateProcess)        ( 
            THIS_ IN ULONG64 ImageFileHandle, IN ULONG64 Handle, IN ULONG64 BaseOffset, IN ULONG ModuleSize,
            IN PCSTR ModuleName, IN PCSTR ImageName, IN ULONG CheckSum, IN ULONG TimeDateStamp, 
            IN ULONG64 InitialThreadHandle,    IN ULONG64 ThreadDataOffset, IN ULONG64 StartOffset );
    class StdioOutputCallbacks : public IDebugOutputCallbacks  // output callback class 3 methods
        STDMETHOD(QueryInterface)( THIS_ IN REFIID InterfaceId, OUT PVOID* Interface );
        STDMETHOD_(ULONG, AddRef)( THIS );
    Attached Thumbnails Attached Files
  2. Making an advanced api redirection more advanced?

    Anyways, I was playing around with a funny target today after school. Its got a bunch of features; I usually break one of them per week This week's "feature to break" was something I have dubbed advanced API redirection.

    Pretty much, what the protection does is take a huge routine of the target program, and stores it in a new section. There it replaces a bunch of the FF 15 calls with its own sort of 'macro', which calls into the protector code, where the protector then does whatever protectors do, and forwards it to the correct api. Here is a good example similar to what I am talking about:

    Original code:
    PUSH 00401000  
    CALL DWORD PTR[11223344] ; VirtualAlloc
    After protection process:
    PUSH 50010007
    MOV EAX, _protector_routine
    the push 50010007 was just a pointer to an identifier used by the protector to see which API to forward to...

    Now this is pretty basic stuff, right? Just search for a byte pattern, execute it, let the code execute up to some hook you have in the code of the protector, where EAX will hold the correct API address, and then just NOP out the entire thing above and replace it with a FF 15 <correct addr>. If you want to be extra neat you could also resolve the XORing obfuscation above to the correct command before obfuscation, which was:
    push 00401000

    Well, the thing is, this protector added a bit o spice to the game. Instead of having just one type of routine that is used for API handling, they used five types. So the above routine could also be:

    PUSH 00401000  
    PUSH 50010007
    MOV DWORD PTR[ESP], xxxxxxxx
    XOR DWORD PTR[ESP], xxxxxxxx
    and then you have 3 other types of routines that the protector can replace the original call with...

    Now, the trick in the protection is that you have to find and record the byte patterns for all 5 of these routines, and then subsequently fix them back to call dword <correct addr>.

    So, fixing this protection is a two step process:
    1) Identify all of the protector calls
    2) fixing them one by one.

    It is easily automated and fixed, once you have spent an hour hunting down the random crashes in your dump caused because your code has missed one of the protector calls.

    But this got me thinking. What if the protection devs were to add metamorphoses? It shouldn't be hard to write a metamorphic code generator to morph the above 5 routines into even more complex routines.

    Consider: only a couple of the same commands are being used in each of the protector routines:
    CALL EAX...
    MOV DWORD PTR[ESP], xxxxxxx
    XOR DWORD PTR[ESP], xxxxxxx

    and so on.

    Now, what if for each of those instructions your metamorphic code generator could morph into 4 different code chunks? For example, the CALL EAX could be morphed into:

    CALL _geteip
    ADD AL, 9
    db 0FF

    call _geteip
    ADD EAX, 0F
    ADD ESP, 4

    and so on...

    Now lets assume that the devs took a couple of hours and coded this simple metamorphic code generator. Now all they have to do is:
    a) protect each call dword ptr with the old method (using one of the 5 possible protector routines)
    b) mark the offsets of each protected CALL in a list for later use
    c) after all the CALL DWORD's have been protected via the old method, take your metamorphic code generator and feed it the list of offsets of protected CALLS, and let it morph each protector routine to a new one.

    After it is done morphing, every single protector routine should be unique. This will throw a wrench in the prospective hacker's plans, because he can no longer easily identify all the protected CALLs that he needs to fix.

    Anyways, this was just an idea I had kicking around in my head for some time. Hope that someone could actually understand it.

    I'll re read this blog post and fix any errors in it later today.

    Updated October 1st, 2007 at 21:04 by rendari (bleh)

  3. 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

    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.

    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

    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

    launch fuzzer and Avast Scan, as you can see Driver resists to Fuzzing attempts, its time to see code referred to 0xB2D60030 and 0xB2D60034.


    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.


    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:

    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:
    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.

    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:


    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:

    <?xml version=Ē1.0″ encoding=Ēwindows-1251″?>
    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

    Arg1: 00000008, EXCEPTION_DOUBLE_FAULT
    Arg2: 80042000
    Arg3: 00000000
    Arg4: 00000000_KERNEL_MODE_TRAP_M (1000007f)
    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
  4. Explorer Suite III (CFF Explorer VII)

    Scripting documentation:


    - Fixed a lot of bugs
    - Fixed a minor bug in the MetaData tables
    - Fixed minor resizing bug on Vista
    - General improvements
    - Significantly improved the interface
    - Improved Resource Editor
    - Improved Rebuilder (added checksum update and strip debug directory)
    - Improved Data Directories viewer
    - Improved Hex Editor
    - Improved Sections Dialog (added section's hex view)
    - Improved MetaData Tables
    - Extended the SDK
    - Added powerful very scripting language
    - Added documentation for the scripting language
    - Added security features for the scripting language
    - Added support for generic files
    - Added Name Unmangler
    - Added Debug Directory
    - Added Dependency Walker
    - Added Quick Disassembler (x86, x64)

    Hope you like it..
  5. (Part 2 of .NET native exe insights)Serial fishing and patching .NET exes with Ollydb

    (Part 2 of .NET native exe insights)Serial fishing and patching .NET exes with Ollydbg.

    Last blog post I pointed out how native exes, when used improperly, do nothing to deter reverse engineer of
    completely decompiling your product, and doing with it as they please (cracking). Now, I would like to assume
    that the developer bothered reading my blog post, and actually bothered wiping the IL from his native exe. While
    I do admit that this is a "final" solution to decompilation, as I mentioned before it is faaaar from a "final"
    solution to crackers. Hackers have been going at native code for years, so with a bit of brainpower and Olly, a
    native .NET exe should pose no challenge to them.

    In this post I will observe a simple keygenme, and I will show you how I was able to
    a) patch it
    b) fish a serial for it...

    in less that 5 minutes with Olly.

    Here is the link to the keygenme we will be dealing with(same as in last blog post):

    Download it, extract it anywhere, and Ngen it

    >ngen unpackme.exe.

    Then, take unpackme.exe, and load it into Olly. Check all exceptions, and run the Unpackme. It will pop up with
    a little dialogue asking for a name and serial. Click the "Check" button, and observe the error message:

    "Invalid serial. Pls don't hack me :'("

    Hardy harr.

    Well, now lets think for a second. This is a string that is needed for the unpackme to run. Therefore, it can
    probably be found the native image of the unpackme. We also know that all strings in a .NET exe are stored in
    the metadata. As I pointed out in the last tutorial, the metadata of a .NET exe is in the .IL section of the
    native exe. So, we know that somewhere in the .IL section of our native exe, we will find a string saying:
    "Invalid serial. Pls don't hack me :'("

    Furthermore, if you paid close attention to the .NET file format, you know that all strings in .NET are stored as
    unicode. So, somewhere in the .IL section of our native .NET exe there will be a UNICODE string that says:
    "Invalid serial. Pls don't hack me :'(".

    Now, suppose that we locate this string. What do we do with it? Quite simple: We put a hardware breakpoint upon
    it. Once it is accessed, we know that the routine it was accessed from is part of the serial checking routine.

    Alright, now in Olly, with the unpackme running in the background, press ALT+M to open a list of all modules.
    Scroll down a bit until you find the native image of unpackme.exe ( You should see this:

    30000000    00001000 (  Unpack_1 3             PE header     Imag   R         RWE
    30002000    00004000 (  Unpack_1 3  .text      code          Imag   R E       RWE
    30006000    00001000 (  Unpack_1 3  .extrel    code          Imag   R E       RWE
    30008000    00005000 (  Unpack_1 3  .data      code,data     Imag   RW        RWE
    3000E000    00001000 (  Unpack_1 3  .xdata                   Imag   RWE       RWE
    30010000    00001000 (  Unpack_1 3  .dbgmap                  Imag   R         RWE
    30012000    00004000 (  Unpack_1 3  .il                      Imag   R         RWE
    30016000    00001000 (  Unpack_1 3  .rsrc      resources     Imag   R         RWE
    30018000    00001000 (  Unpack_1 3  .reloc     relocations   Imag   R         RWE
    Now, we are interested in the .IL section of this native exe, because that is where the string we are trying to
    breakpoint is. In the dump window of Ollydbg, press CTRL+G, type 30012000, and press enter. This will move the
    Ollydbg hex dump window to the beginning of the .IL section. Then, still in the dump window, press
    CTRL+B (binary search), and under unicode type in:
    "Invalid serial.". Then press enter to let Olly search. It should end up here:

    300142FD   49 00 6E 00 76 00 61 00  I.n.v.a.
    30014305   6C 00 69 00 64 00 20 00  l.i.d. .
    3001430D   53 00 65 00 72 00 69 00  S.e.r.i.
    30014315   61 00 6C 00 2E 00 20 00  a.l... .
    3001431D   50 00 6C 00 73 00 20 00  P.l.s. .
    30014325   64 00 6F 00 6E 00 27 00  d.o.n.'.
    3001432D   74 00 20 00 68 00 61 00  t. .h.a.
    30014335   63 00 6B 00 20 00 6D 00  c.k. .m.
    3001433D   65 00 20 00 3A 00 27 00  e. .:.'.
    30014345   28 00 01 81 7B 54 00 68  (.Ā{T.h
    3001434D   00 65 00 20 00 70 00 6F  .e. .p.o
    30014355   00 69 00 6E 00 74 00 20  .i.n.t.
    3001435D   00 6F 00 66 00 20 00 74  .o.f. .t
    30014365   00 68 00 69 00 73 00 20  .h.i.s.
    3001436D   00 55 00 6E 00 70 00 61  .U.n.p.a
    30014375   00 63 00 6B 00 6D 00 65  .c.k.m.e
    3001437D   00 20 00 69 00 73 00 20  . .i.s.
    30014385   00 66 00 6F 00 72 00 20  .f.o.r.
    Cool! This is the badboy string we are interested in. Write down the address, restart the target in Olly, and
    press F9 to run Olly once again. Do not click on the check button yet. First, go to the address we wrote down
    (300142FD) select the first 4 bytes,
    Right click -> breakpoint -> hardware, on access -> byte

    Now, go back to the unpackme, and click on the "Check" button. Olly should break with a hardware DWORD on access
    at a place that looks like this:

    7814507A    F3:A5              REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
    7814507C    FF2495 94511478    JMP DWORD PTR DS:[EDX*4+78145194]
    78145083    90                 NOP
    Alright now, go to
    Debug -> hardware breakpoints

    in Olly, and delete your hardware breakpoint that you set upon this string.

    Now, its time to trace a bit with F8 until we get to the .text section of Unpackme.exe. Just hold F8 until
    you end up here:

    300041D0    57                 PUSH EDI
    300041D1    56                 PUSH ESI
    300041D2    53                 PUSH EBX
    300041D3    55                 PUSH EBP
    300041D4    83EC 10            SUB ESP,10
    300041D7    891424             MOV DWORD PTR SS:[ESP],EDX
    300041DA    8BF1               MOV ESI,ECX
    300041DC    8B05 0CE00030      MOV EAX,DWORD PTR DS:[3000E00C]                 ; Unpack_1.300081B4
    300041E2    8338 00            CMP DWORD PTR DS:[EAX],0
    300041E5    74 05              JE SHORT Unpack_1.300041EC
    300041E7    E8 12E1084A        CALL mscorwks.7A0922FE
    After you've debugged .NET exe's a bit in Olly you will recognize this as the beginning of a method, just like

    usually marks the beginning of a routine in VC++...

    Anyways, since this routine has accessed the "Invalid serial" string, we can assume that this routine is the
    serial check routine. Start tracing at it with F8. A messagebox telling you you entered the wrong serial will
    pop up after you trace over this call:

    300042A6    8B05 18BF0030      MOV EAX,DWORD PTR DS:[3000BF18]
    300042AC    8B08               MOV ECX,DWORD PTR DS:[EAX]
    300042AE    FF15 C0BF0030      CALL DWORD PTR DS:[3000BFC0]                    ; System_W.7B26EC88
    300042B4    90                 NOP
    Interesting... look around in Olly and try to get a feel for what is happening. Even a noob should be able to
    understand what is happening here:

    30004270    8BF8               MOV EDI,EAX
    30004272    6A 00              PUSH 0
    30004274    8BD3               MOV EDX,EBX
    30004276    8BCF               MOV ECX,EDI
    30004278    FF15 BCBF0030      CALL DWORD PTR DS:[3000BFBC]                    ; Compare strings (Microsoft.VisualBasic.dll)
    3000427E    8BF8               MOV EDI,EAX
    30004280    85FF               TEST EDI,EDI
    30004282    0F94C0             SETE AL
    30004285    0FB6C0             MOVZX EAX,AL
    30004288    894424 04          MOV DWORD PTR SS:[ESP+4],EAX
    3000428C    837C24 04 00       CMP DWORD PTR SS:[ESP+4],0			; were they the same?
    30004291    74 12              JE SHORT Unpack_1.300042A5			; if not, JMP
    30004293    8B05 14BF0030      MOV EAX,DWORD PTR DS:[3000BF14]
    30004299    8B08               MOV ECX,DWORD PTR DS:[EAX]
    3000429B    FF15 C0BF0030      CALL DWORD PTR DS:[3000BFC0]                    ; good boy message. 
    300042A1    90                 NOP
    300042A2    90                 NOP
    300042A3    EB 10              JMP SHORT Unpack_1.300042B5
    300042A5    90                 NOP
    300042A6    8B05 18BF0030      MOV EAX,DWORD PTR DS:[3000BF18]
    300042AC    8B08               MOV ECX,DWORD PTR DS:[EAX]
    300042AE    FF15 C0BF0030      CALL DWORD PTR DS:[3000BFC0]                    ; bad boy message.
    300042B4    90                 NOP
    300042B5    90                 NOP
    300042B6    90                 NOP
    300042B7    90                 NOP
    300042B8    83C4 10            ADD ESP,10
    300042BB    5D                 POP EBP
    300042BC    5B                 POP EBX
    300042BD    5E                 POP ESI
    300042BE    5F                 POP EDI
    300042BF    C2 0400            RETN 4
    Simple, eh? Just for kicks, nop the JE at 30004291 and press F9 to run the unpackme. Click on the "Check" button and watch ...

    Updated March 24th, 2008 at 02:00 by rendari

  6. My "Unofficial" ReCon Video

    My "Unofficial" video is now available from the ReCon website along with my pdf slides.

    The official videos recorded live are not out yet.
    I recorded this one after the conference so it is available before all the others.
    The live version is funnier though.

    Also, I messed-up a bit my live Armadillo demo.
    But it happens...

    So this video is a little less than 60 minutes with voice and a TOC.
    And the Armadillo demo works.

    Don't forget to watch ALL the official ones too when they come out.
    Every speaker out there was really great.

    And yes dELTA, I mentioned the CRCETL.
  7. Playstation3 / PS3 - Harddisk encryption

    Hey all,

    after I got my first used PS3, i played a bit around with it. The hdd is pretty easy to remove and so i did a full dump of the installed 40 gb hdd. during the dump the hdd contained the data from the former owner.
    next step was to format the disk with the included ps3 format utility. i chose the strong format mode in order to erase the data on the disk. took about 2,5 hours.
    again i made a full dump.
    what i was expecting were two totally different dump. what i found instead was that the first 0x1E bytes were equal.

    you see a small part of the dumps here: dump:

    00000000 C5 48 55 A0 E6 EE 4F 8F 0A C5 63 AD FA C2 0E 52 .HU...O...c....R
    00000010 30 FA 16 FA C7 F2 FF 55 FE 31 B5 2F 40 40 52 DA 0......U.1./@@R.
    00000020 E2 86 2B 3C 00 D1 2D B1 B8 C4 DE DD E6 EC 12 E3 ..+<..-.........
    00000030 6B 31 C0 0A 9E DE 8A 7C 8C 65 1F 85 B7 22 8E 3A k1.....|.e...".:
    00000040 9D 8D 1E 8A A6 BD 63 96 14 7D 14 BB EF CF B2 F0 ......c..}......
    00000050 E3 E4 10 90 D8 8E 73 94 7A D6 12 CE E8 0C F6 FC ......s.z.......
    00000060 52 C7 55 50 8C 61 F2 DE 5E 00 C3 65 AF 54 13 BC R.UP.a..^..e.T..
    00000070 65 D1 F9 E8 08 C9 64 F6 7D 77 A7 37 D1 94 0B 91 e.....d.}w.7....
    00000080 6E 97 89 3E 17 61 B2 29 BA B7 87 36 C5 51 EC 88 n..>.a.)...6.Q..
    00000090 27 BB D9 6B 0E 1B F8 74 EA B6 15 12 C6 E9 6F 19 '..k...t......o.
    000000A0 10 48 60 AC 0C 0B AF 50 99 0C 6A 11 7A 09 79 AC .H`....P..j.z.y.
    000000B0 97 AD 1F A3 5C B4 15 B4 27 DC DE 6A 2B 16 43 78 ....\...'..j+.Cx
    000000C0 01 28 67 E9 7E B6 22 73 D8 30 03 82 78 1E 6B 05 .(g.~."s.0..x.k.
    000000D0 0B D4 3C 5D 75 0D 95 BB 83 48 DB D6 B2 C7 93 93 ..<]u....H......
    000000E0 37 56 A6 C7 18 0B B4 A4 26 22 C6 7E 6B 02 D9 25 7V......&".~k..%
    000000F0 54 E3 F3 4A 3F 4E CA 21 EB 2F E0 A8 91 4C 2D 4F T..J?N.!./...L-O
    2nd dump:
    00000000 C5 48 55 A0 E6 EE 4F 8F 0A C5 63 AD FA C2 0E 52 .HU...O...c....R
    00000010 30 FA 16 FA C7 F2 FF 55 FE 31 B5 2F 40 40 52 DA 0......U.1./@@R.
    00000020 9E F3 C6 89 94 FD C6 2A 62 D9 8F 20 3D 1B 14 9B .......*b.. =...
    00000030 29 A9 04 C2 1D 08 16 3A 09 15 5E DC AF 1C AC AD )......:..^.....
    00000040 F8 70 C4 70 78 48 2F D9 D8 94 90 89 6F D3 DD 42 .p.pxH/.....o..B
    00000050 14 BC 08 05 E7 CF 36 C9 A0 80 DA 58 1F C4 D7 7D ......6....X...}
    00000060 1D AE 34 E6 AF 03 EF 5E E4 B6 B9 F7 E2 5F 9A 9F ..4....^....._..
    00000070 1D B4 D4 81 7D 48 8B C5 D8 FB 82 BE E7 A6 62 FB ....}H........b.
    00000080 0E 4B 8E 21 D6 7B E5 47 03 F9 6D 4B FF 35 05 91 .K.!.{.G..mK.5..
    00000090 41 92 5E 41 C1 24 73 46 E0 27 6A A4 3B AC 14 D0 A.^A.$sF.'j.;...
    000000A0 1D 80 C5 EF DE 19 7A 82 2E A8 7D 95 96 78 76 F6 ......z...}..xv.
    000000B0 1F 9C 01 A0 A6 BF 37 E7 06 C5 11 20 09 3F 33 B6 ......7.... .?3.
    000000C0 76 58 B0 AE 10 3F F4 AA 34 B7 DB 42 3E 31 9F 10 vX...?..4..B>1..
    000000D0 BD BA AD 23 A1 7C B3 3B 41 79 30 7C C4 13 60 EC ...#.|.;Ay0|..`.
    000000E0 48 B0 35 47 C6 B8 7E FF 55 E7 34 97 5C EC F1 FC H.5G..~.U.4.\...
    000000F0 6A F1 34 C0 B6 33 0D 4D 2F F5 C1 B9 BC D7 5F CE j.4..3.M/....._.
    Thats pretty interesting because i thougth that they are using a FULL hardware harddisk encryption. what i found so far is pointing that they also store something encryption/decryption related stuff in these first equal bytes.

    Another interesting fact ist, that both dump can be nearly compressed like text, what is also pretty strange.


    PS3 - Homebrew
  8. [WinInternals] Reverse Engineering of kdbgctrl - How are builded Kernel Triage Dumps


    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.

    .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:

    .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.
    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

    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;
    Immediately before NtSystemDebugControl we meet:

    .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

    .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

    .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.

    .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.

    .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.

    .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.

    .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.
    .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
  9. imports are easy to fix

    Well I read post at openrce posted by blabberer in X-Code thread here at woodmann ( and saw interesting discussion between Rolf Rolles (waz up man ) and Kris Kaspersky debating which way of generic fixing is better. Kris votes for adding loader, but Rolf likes clean import to have good disasm in IDA. Infact I had this same problem a few months ago, it was easy to locate all APIs and add loader, who cares, app works, well it works and you don't have to analyse it as long as registration scheme is located in the wraper, but what if registration is located in program itself and you have to analyse it? It would be mess and boring task in IDA not seeing real APIs Basically that small discussion was inspiration to write this blog post

    Look at this messy fixed import. It looks like, for example, armadillo shuffled IAT or maybe ActiveMARK v6.xx fixed IAT. But take a closer
    look where are APIs located:

    00BBC368 >7C80A447  kernel32.QueryPerformanceCounter
    00BBC36C >7E450702  USER32.MessageBoxA
    kernel32.QueryPerformanceCounter = BBC364
    user32.MessageBoxA               = BBC368
    You might wonder how did I get this to work? Using API loader? No!!!

    What I have used here is 1API = 1 image import descriptor concept which I use to fix imports always. Basically this is how it works:

    typedef struct _IMAGE_IMPORT_DESCRIPTOR {
        union {
            DWORD   Characteristics;            
            DWORD   OriginalFirstThunk;         
        DWORD   TimeDateStamp;                  
        DWORD   ForwarderChain;                 
        DWORD   Name;
        DWORD   FirstThunk;                     
    According to PE specification OriginalFirstThunk points to API names, but if it is 0 then FirstThunk is pointing to API names, also FirstThunk is used to know where to store API addresses.

    So what we shall do to make this concept work?

    1. Build OriginalFirstThunk such that it only points to one API name
    2. place RVA in FirstThunk where we want API loaded
    3. When import table is built simply walk firstthunk and set it to
    specific value != 0 as windows loader will deny loading image if
    address to which FirstThunk is pointing is 0. Weird?! I didn't find
    anything in PE specification about this behaviour

    Lets see some code snipets from this library which you may find in src of my GenericUnpacker and import engine at

    First we define some struct which will hold our imports:

    import_struct           struct
            is_address      dd      ?               <--- RVA where we want API address to be
                                                         writen by windows loader
            is_dlllen       dd      ?               <--- len of dll name including terminating 0
            is_apilen       dd      ?               <--- len of API string including terminating 0
                                                         or 4 if API is imported by ordinal
            is_dllname      db      256     dup(0)  <--- dllname (ASCII)
            is_apiname      db      256     dup(0)  <--- API name or ordinal | 0x80000000
    import_struct           ends
    Now it's very simply to fix IAT:

    By number of this structs we know how many IMAGE_IMPORT_DESCRIPTORs we will have, but
    also tnhx to lengths stored in structs we can estimate size of newly built IAT including
    APIs aswell.

    OriginalFirstThunk will always point to API name or ordinal and also will take one more
    DWORD for 0 to tell windows loader that there are no more APIs to be loaded.

    EBX = memory used for IMAGE_IMPORT_DESCRIPTOR
    EDI = pointer where we write dll, api names or ordinals and is calculated
    as EBX + (number_of_import_structs + 1) * sizeof (IMAGE_IMPORT_DESCRIPTOR)

                            sub     edx, size import_struct
    __cycle_main_loop:      add     edx, size import_struct
                            cmp     [edx.is_address], 0
                            je      __done_building
                            ;copy dll name
                            mov     esi, edi
                            sub     esi, new_iat_mem
                            add     esi, iat_sec_rva
                            mov     [ebx.id_name], esi 
                            lea     esi, [edx.is_dllname]
                            mov     ecx, [edx.is_dlllen]
                            rep     movsb
                            ;write original first thunk
                            mov     esi, eax
                            sub     esi, new_iat_mem
                            add     esi, iat_sec_rva
                            mov     [ebx.id_originalfirstthunk], esi
                            mov     esi, dword ptr[edx.is_apiname]
                            test    esi, 80000000h
                            jz      __api_has_name
                            mov     [eax], esi
                            jmp     __firstthunk         
                            mov     esi, edi
                            sub     esi, new_iat_mem
                            add     esi, iat_sec_rva
                            mov     [eax], esi
                            lea     esi, [edx.is_apiname]
                            add     edi, 2
                            mov     ecx, [edx.is_apilen]
                            rep     movsb
                            mov     esi, [edx.is_address]
                            mov     [ebx.id_firstthunk], esi
                            add     ebx, size import_directory
                            add     eax, 8
                            jmp     __cycle_main_loop
    When this small loop is done, all we have to do is to walk all first_thunks and set them
    to != 0 so win loader can actually load this import table.

    With this concept you don't have to write sorting algos to get nice and clean IAT, who
    cares where are APIs located. In my, aspr2.3 dumper for example, I scan original code
    for APIs that are not stolen, then I go for stolen APIs and write them into array
    and I don't care if I have something like this:



    After this is done, then I go for APIs located in poly oep, or other stolen procedures
    which are located in markers. At this point IAT looks like nightmare and importrec nor
    any other public known engine can fix this IAT... But 1API = 1IDD concept fixes this
    without a problem!!!

    Think about it when writing unpacker and protection developers think too when
    you try to make "hard" IAT to stop importrec, you will lose one way or another
    Remember that not many people are using it lately

    Updated October 23rd, 2007 at 11:53 by deroko

  10. IDC scripting a Win32.Virut variant - Part 1

    I had started live tracing this piece of malware when I realized it was a prime candidate for some IDA idc scripting. There are a few things about the program which makes static analysis difficult.

    1. It's encrypted. It's a rather simple encryption however which is easily scripted out.
    2. The code is primarily executed in the .data section and there are many inline character strings and non-standard code instructions which prevent IDA from getting an accurate disassembly.
    3. Variable pointers and import calls are referenced as EBP offsets, so IDA can't recognize absolute addresses to create the proper Xrefs, autogeneration and all the other wonderful analysis it normally performs.
    4. Imports are determined dynamically through GetProcAddress, so until we define them IDA can't recognize them.

    Let's address each of these problems through a bit of idc scripting and static analysis to supplement our live tracing. In Part 2 I'll mention a few points about the viral code itself.

    I've included several files in the attachment, the idc scripts, a header file prototyping some functions and structures not included in the internal IDA definitions. As well there is as an IDB file in IDA 4.9 freeware version format which is fully commented with all functions and variables defined (or at least named, this is meant to be a "working" disassembly for further analysis, not necessarily a definitive treatise). The IDB file can be opened in any IDA version 4.9 and above.

    Also included is of course the virus, or else what fun would this be? The win32_virut.exe file has been renamed with a .VXE extension and zip password protected with the password malware. It is quite an infectious file, but it readily detects a normal virtual machine sandbox and won't infect under those conditions. You actually have to force the code to decrypt its payload under a VM. Also, the remote site it tries to connect to has been closed for Terms Of Agreement violations (ya think?), so no live connection is ever made.

    You may find it easier to read the idc scripts by downloading the originals or by reading this post in the Blogs Forum (follow the link under 'Post or View Comments' at the bottom of this blog).

    A brief description of the virus family from

    This virus is a polymorphic, memory-resident file-infector, with backdoor behaviour. Once executed, it injects itself into WINLOGON, creates a new thread in that process, and passes the execution control to the host file.

    It also hooks the following functions in each running process (in NTDLL module):
    NtCreateFile, NtOpenFile, NtCreateProcess, NtCreateProcessEx
    so that every time an infected process calls one of these functions, the execution is passed to the virus, which infects the accessed file, and then returns the control to the original function.

    It infects EXE and SCR files, using different infection techniques:
    Appending to the last section of the victim, and setting the Entry Point directly to the viral code. (our variant)

    The virus is able to avoid emulators and virtual machines. To ensure there's only one instance of it running in the system, it creates an event with one of the following names:
    VT_3, VT_4, VevT, Vx_4

    It tries to connect to some IRC server, and join a certain channel. Once it joins the channel, it waits for commands that instruct it to download several files from Internet, and then execute them. The IRC server can be: (our variant, site no longer active)
    Much of what is written above can be figured out by live tracing the malware and eventually letting it infect our sandbox. But let's see what damage we can do to it before it does damage to us..

    Step 1: Decrypt

    Here is the Entry Point of the virus, which is in the .data section:
    :00403200                 cld
    :00403201                 call    loc_40322E
    :00403206                 push    ebx
    Take note that the return address of the Call pushed onto the stack will be 0x403206. Trace into the Call and after a bit of preliminary code we reach here:

    :00403257  mov     ebp, [esp+4]
        // call return of 0x403206 placed in ebp
    :0040325B  sub     dword ptr [esp+4], 21E9h
        // new return address of (0x403206 - 0x21E9) = 0x40101D placed on stack
    :0040326A  sub     ebp, 301006h
    // ebp offset becomes (0x403206 - 0x301006) = 0x102200
    :00403270  lea     eax, [ebp+301082h]
    // eax = (0x102200 + 0x301082) = 0x403282
    // this is the starting address of the encrypted code
    :00403276  mov     dx, [eax-65h]
    // word pointer at 0x40321D is a decryption seed value:  db 8Eh, 0C8h
    :0040327D  call    sub_403206      // Decryption routine
    // the code from here on down is all encrypted
    :00403282  db      65h
    :00403282  enter   0BDDh, 0C1h
    :00403287  push    ss
    The fact that none of the code from address 0x403282 onwards doesn't make much sense indicates that Call sub_403206 is a decryption routine. Let's take a look at that call:

    :00403206 Decrypt         proc near               ; CODE XREF: :0040327D
    :00403206                 push    ebx
    :00403207                 mov     ecx, 0DA5h
    :0040320C                 mov     ebx, edx
    :0040320E loc_40320E:                             ; CODE XREF: Decrypt+13
    :0040320E                 xor     [eax], dx
    :00403211                 lea     eax, [eax+2]
    :00403214                 xchg    dl, dh
    :00403216                 lea     edx, [ebx+edx]
    :00403219                 loop    loc_40320E
    :0040321B                 pop     ebx
    :0040321C                 retn
    :0040321C Decrypt         endp
    :0040321C ; ---------------------------------------------------------------
    :0040321D Initial_Decrypt_Seed db 8Eh, 0C8h
    :0040321F; ----------------------------------------------------------------
    A simple XOR loop decryption where the xor value is modified on each iteration by the XCHG instruction. ECX is a counter decremented by the LOOP opcode. The initial decryption seed value is the db 8Eh, 0C8h we discovered above.

    Armed with this small bit of analysis we can create the following idc script for decrypting.

    PHP Code:
    #include <idc.idc>
    // Step 1: idc to decrypt section between .data:0x403282 and .data:0x404DCC    
    // performs the equivalent asm function (xchg dl, dh)
    #define    bswap16(x)                    \
    ((((x) & 0xff00) >> 8) |        \
    x) & 0x00ff) << 8))
    auto startdecryptsizeenddecryptseedeadecryptwordx;
    // starting values determined from decrypt function
    startdecrypt 0x403282;
    size 0x0DA5 2;                          // word size replacement
    enddecrypt = (startdecrypt size);         // = 0x404DCC
    seed 0xC88E;
    ea startdecrypt;
    decryptword seed;
    Message("\nDecrypting... \n");
        while (
    ea enddecrypt)
    // (xor [eax], dx)
    Word(ea);                               // fetch the word
    = (decryptword);                      // decrypt it
    PatchWord(eax);                           // put it back            
    decryptword bswap16(decryptword);     // xchg dl, dh
    decryptword decryptword seed;       // lea edx, [ebx+edx]
    ea ea 2;    
    // Let's try to get IDA to reanalyze the code
    MakeUnknown (startdecryptsize1);
    AnalyzeArea (startdecryptenddecrypt);
    Message("...Done \n");

    After running this script you MUST go through the decrypted section and manually resolve the embedded string pointers with the IDA A(scii) command and any unrecognized or incorrect disassembly with the C(ode) command. This is a necessary step for the subsequent IDC scripts to work properly!

    You will find a lot of things like the following, which you need to make sure is correctly resolved. By itself IDA won't properly disassemble the code.

    :004032D8 E8 0D     call    loc_4032EA
    :004032D8                   ; --------------------------------------------
    :004032DD 47 65+ aGetlasterror   db 'GetLastError',0 // LPCSTR lpProcName
    :004032EA                   ; --------------------------------------------
    :004032EA        loc_4032EA:       ; CODE XREF: :004032D8
    :004032EA 03 F3     add     esi, ebx
    :004032EC 53        push    ebx     // HMODULE hModule
    :004032ED FF D6     call    esi     // GetProcAddress
    Notice the neat little trick in the above code of how the second parameter of GetProcAddress is automatically pushed onto the stack by effectively being the return address of Call loc_4032EA, which jumps over the string. This type of thing is repeated throughout the program.

    Chances are you won't get every bit of disassembly and ascii string identified correctly the first time through a manual fixup, but after applying ...
    Attached Thumbnails Attached Files
  11. Idc script and stack frame variables length

    Among all the precious information retrieved by Ida thereís something I always use when I need to study a target: stack frame. Itís quite useful when you want to see the list of parameters and local variables, but it would be great to see the size of each item. Yes, you can get the length but you have to calculate it each time. I sometimes need this kind of information, especially when I have to deal with fixed length buffers. I tried inspecting through some Idaís menu without luck, itís strange that Ida doesnít provide such information so I decided to write a little idc script able to retrieve local *big* buffers. (If thereís an Ida hidden feature please tell meÖ)
    I wanted to attach the original script I wrote here, but I think itís much more useful to explain some details about the functions I used leaving the script to you as an exercize. In this simple example Iíll show you how to find out the length of each item inside a stack frame. Letís start with a simple function:

    The stack frame created by Ida is divided into some parts, it looks like a sequence of fields:
    - local variables
    - saved registers
    - return address
    - function parameters

    Looking at the picture above is pretty easy to locate local variables (ObjectAttributes, KeyValueInformationLength, ResultLength) and function parameters (Handle, ValueName). Moreover you can guess the length of each item. According to the four parts I mentioned above there are some more items that are not specified by Ida, Iím referring to ďsaved registersĒ and ďreturn addressĒ. If you look at the offset of each item youíll surely find out something odd. Look at the gap between ResultLength and Handle: 0◊0C bytes. 4 bytes are reserved for ResultLength variable, but there are 8 unreferenced bytes. Itís time to take a look at the stack frame window (ctrl-k):

    Here is the answer. Ida uses two special fields named Ē rĒ and Ē sĒ, the length of each field is 4 bytes. They are the ďreturn addressĒ and the ďsaved registersĒ.

    Ok, how to get the size of the items using an idc script? As you can see from the picture the stack frame looks like a structure definition, the idea is to read each item in sequence.
    #include <idc.idc>
    static main()
       auto id, i, firstM, lastM, address;
       auto mName, mSize, mFlag;
       address = 0◊00013C92;        //    Address of the function to check
       id = GetFrame(address);
       firstM = GetFirstMember(id);
       lastM = GetLastMember(id);
          mName = GetMemberName(id,i);   // Get the name
          mSize = GetMemberSize(id, i);  // Get the size (in byte)
          mFlag = GetMemberFlag(id, i);  // Get the flag
          Message(Ē\n%s   %d   %xĒ, mName, mSize, mFlag);
    First of all I need to get the function frame structure. I use GetFrame, it returns the id of the function frame structure. Itís the first information to retrieve because you need the id when youíll have to deal with the internal fields of the structure. Once you have the id you can start scanning the entire structure from the first till the last item. GetFirstMember and GetLastMember functions give you the first and the last offset. At this point you can retrieve all the information you need, in this example I get name, size and flag value from every item. The functions I used are GetMemberName, GetMemberSize and GetMemberFlag; pretty intuitive and easy to use. An output line will look like:
    ObjectAttributes   24   60000400
    where name=ObjectAttributes, size=24 and flag=60000400. Which kind of information are hidden inside the flag value? idc.idc file contains all the necessary definitions:
    #define FF_DATA 0x00000400L             // Data ?
    #define FF_STRU 0◊60000000L             // Struct ?
    The field contains data and itís a structure (OBJECT_ATTRIBUTES). And, what about Handle field?
    Handle   4   25500400
    Browsing idc.idc file youíll get:
    #define FF_DATA  0x00000400L            // Data ?
    #define FF_0OFF  0◊00500000L            // Offset?
    #define FF_1OFF  0◊05000000L            // Offset?
    #define FF_DWRD  0◊20000000L            // dword
    Ok, thereís only a little behaviour to fix inside the script. Run the script and youíll see some repeated lines, hereís a snippet taken from the output:
    ObjectAttributes   24   60000400
    ObjectAttributes   24   60000400
    ObjectAttributes   24   60000400
    KeyValueInformationLength   4   20000400
    KeyValueInformationLength   4   20000400
    KeyValueInformationLength   4   20000400
    KeyValueInformationLength   4   20000400
    ResultLength   4   20000400
    ResultLength   4   20000400
    ResultLength   4   20000400
    Ida repeats the field information on every byte of the field itself. To display only one item per field you can update the Ďií variable inside the for statement, add the next line after the Message instruction:
    i = i + GetMemberSize(id, i) - 1;
    The example ends here. It works almost fine, but it goes into an infinite loop with certain functions. From what Iíve seen the problem occours when Ida is not able to understand which kind of variable has been declared. Look at this simple example:
    INIT:BF9B0786 var_1A4         = dword ptr -1A4h
    INIT:BF9B0786 var_18E         = byte ptr -18Eh
    INIT:BF9B0786 var_4           = dword ptr -4
    var_18E is marked as byte but thereís a big gap between var_18E and var_4. Stack frame windows reveals an interesting thing:
    -0000018E var_18E         db ?
    -0000018D                 db ? ; undefined
    -0000018C                 db ? ; undefined
    -0000018B                 db ? ; undefined
    -0000018A                 db ? ; undefined
    -00000189                 db ? ; undefined
    -00000188                 db ? ; undefined
    -00000187                 db ? ; undefined
    -00000186                 db ? ; undefined
    -00000185                 db ? ; undefined
    -00000184                 db ? ; undefined
    -00000183                 db ? ; undefined
    var_18E length is 394 byte and as you can see Ida doesnít collapse the definition into a single line, but it ďexplodesĒ the variable through the 394 bytes.
    How can you solve this problem? You can use my initial script adding some more checks. Nothing hard of course, you have all the necessary functions, just use your brain defining a good algo. Hint: take a look at the value returned by GetMemberSize.

    Once you have a working script you can extend it covering all the declared functions and filtering the information youíll get.

    Good luck and let me know if you are not able to solve this exercize!!!
  12. Rebuilding native .NET exes into managed .NET exes by Exploiting lefotver IL...

    In the last article I wrote about native exe's, I briefly touched upon the issue of IL code being
    left over in generated Native EXE's, and how this could be a possible security hole that hackers could
    exploit when trying to reverse your .NET app. How big of a hole is this, you might ask? Very big. I
    managed to fully rebuild my old managed .NET exe just from the native image provided by Ngen. I aim
    to explain the steps I took in this blog post.

    First things first, we will be using this .NET exe for out experimentations:

    It's just a simple Unpackme I wrote and submitted to If you suspect malicous code, feel
    free to decompile it in Reflector.

    Anyways, extract the exe anywhere, and execute Ngen upon it

    H:\temp>ngen unpackme.exe
    Microsoft (R) CLR Native Image Generator - Version 2.0.50727.42
    Copyright (C) Microsoft Corporation 1998-2002. All rights reserved.
    Installing assembly H:\temp\unpackme.exe
    Compiling 1 assembly:
        Compiling assembly H:\temp\unpackme.exe ...
    UnpackMe, Version=, Culture=neutral, PublicKeyToken=null <debug>
    Then browse to your Global Assembly Cache at H:\WINDOWS\assembly\NativeImages_v2.0.50727_32\UnpackMe,
    find, and copy it over to some temporary location, where we can "work" on it.

    Now, the interesting thing about Ngen is that it does not eliminate the IL or the metadata, because
    while the IL code is not needed for execution, the metadata is, because all the strings and other
    relevant data that the program needs are contained within the metadata. So, Ngen copies all the
    metadata to the .IL section of the native exe, and copies the IL code as an afterthought (I assume
    for debugging purposes). Anyways, the point is that native exe's generated with Ngen have the
    IL code and metadata still in them, so a wily hacker should be able to use them to rebuild a managed
    exe similar to the original exe before Ngen had its way with it. The hacker can then load this
    managed exe into Reflector to decompile it, and steal your code or crack it with ease.

    NOTE: managed code = bytecode (decompilable)
    unmanaged code = native code (I wish we could decompile that =( )

    This is a major issue because all protectors that boast converting IL code to native code to protect
    your programs all use Ngen, so if the protectors forget to remove the IL you (the reverser) can just
    reconstruct the original exe and then have fun with it =)

    Anyways, so you have a copy of This is what you would get after a "native" protector
    converted your IL code into native code. So, is all a reverser trying to reverse this
    target would have availible to him.

    Now, let us proceed to convert into a decompilable exe =).

    Load into CFF explorer, and browse around a bit. You will see that the exe is not
    a valid win32 exe (no entrypoint) and that there appears to be next to no metadata (No Methods metadata
    table or any of that other good stuff...). Seems like we have our work cut out for us.

    In hindsight: no, not really.

    First things first: we want to have valid metadata. Thankfuly, with CFF explorer this is easy to
    achieve since Daniel Pistelli (the author) documented the native header of .NET exe's enough for us
    so that we don't have to use a hex editor to find the IL code/metadata anymore (btw, thanks Daniel
    for this neat lil tool =) )

    In CFF Explorer, go to a little tab on the left market "Native header". You will see that the "Native
    Header" is mostly populated with unknown RVA's and sizes. However, there are 4 DWORD's that are of interest
    to us. They are:
    Original metadata RVA - 0x00012000
    Original metadata size - 0x00002BC0
    Original MSIL code RVA - 0x00014D30
    Original MSIL Code Size - 0x00000DBF

    Ok, write down these values somewhere. Now, go to the tab in the left of CFF Explorer marked ".NET directory",
    and replace the values "Metadata RVA" and "Metadata Size" with the "Original metadata RVA" and
    "Original metadata size" values that we got from the native header. Also change the Flags dword from
    00000004 (IL Library) to 00000004 (IL only). Cool, now click on the "Tables" tab, so that we can browse the
    metadata tables that now became availible to us.

    The "Method" tables are of particular interest to us, because these are the ones that tell us where the IL code
    is. So, click on the "Method" tables to open the list. There are 56 Methods btw. Note that, since we will need
    that later on. Now, click on the first Method you see. In this case, it is cctor. CFF Explorer will then display
    all the interesting things about the "cctor" method. If you look at the method RVA, you will see that it is
    00000004. That's way too low. So, what is wrong here? Well, that RVA is actually the displacement from the
    "Original MSIL code RVA" value in the Native header. So, to get the "real" RVA is actually:

    cctor RVA + Original MSIL code RVA = Real RVA.

    Our next step, therefore is to replace all the RVA's in these tables with their "Real RVA's", so that reflector
    and ILDasm may load them. I wrote a primitive little CFF explorer script for this. Here it is:

    -- this functions checks if a flag is set
    function IsFlag(value, flag)
        if (value & flag) == flag then
            return true
        return false
    -- --------------------------------------------------
    -- the main code starts here
    -- --------------------------------------------------
    filename = GetOpenFile("Open...",  "All\n*.*\nexe\n*.exe\ndll\n*.dll\n")
    if filename == null then
    pehandle = OpenFile(filename)
    if pehandle == null then
    -- get dotNet Directory offset if any
    dotnetoffset = GetOffset(pehandle, PE_DotNETDirectory)
    MethodRVA = 0x0000D406
    MethodCounter = 0
    OrigMSILRVA = 0x00014D30
    NumberOfMethod = 56
    junkDWORD = 0
    while MethodCounter < NumberOfMethod do
        junkDWORD = ReadDword(pehandle, MethodRVA)
        junkDWORD = junkDWORD + OrigMSILRVA
        WriteDword(pehandle, MethodRVA, junkDWORD)
        MethodRVA = MethodRVA + 0x0E
        MethodCounter = MethodCounter + 1      
        filename = GetSaveFile("Save As...",  "All\n*.*\nexe\n*.exe\ndll\n*.dll\n")
        if filename == null then
            MsgBox("Couldn't save file", "fast dotnet fix", MB_ICONEXCLAMATION)
            if SaveFileAs(pehandle, filename) == true then
                MsgBox("File successfully saved.", "fast dotnet fix", MB_ICONINFORMATION)
                MsgBox("Couldn't save file", "fast dotnet fix", MB_ICONEXCLAMATION)
    NOTE: If you are working on an executable other than the one I provided, fill in
    with the appropriate values from the exe you are working on.

    NOTE: MethodRVA = the RVA of the first Method table entry in the metadata. In this case, the offset of
    where the Method table for the "cctor" method starts.

    Take the above script, and copy paste it into a new file called *anything*.cff. Then double click on the
    script to get CFF explorer to execute it, select "" to be processed, and save the processed
    file as "fixing1.exe". Remember to save the changes we have done to before executing this
    script on it.

    Now, close and open fixing1.exe ...
  13. IDA disasms reserved opcodes, is it a bug?

    Few days ago I was inspecting a malware using my disassembler, and I stumbled on this piece of code:

    I use ď!?!?!Ē string for undefined/reserved opcode. I had some problems testing reserved opcodes so I decided to check this case carefully. The first check is given by a comparative method, I loaded the malware into IDA. Look here:

    The first thing I thought of was: ďDamn, thereís a bug inside my disasm engineĒ.

    I took a look at the printed version of my ďIntelģ IA-32 Architectures Software Developerís Manual - Volume 2B: Instruction Set Reference, N-ZĒ. According to one-byte opcode map, C6 opcode is defined as a ďGrp 11 (1A) - MOVĒ.

    What does it mean?
    The opcode canít give me the exact meaning of the instruction. I need some extra information, which are given by the opcode extension: ModR/M byte (0◊22 in the example). To retrieve the necessary information about this opcode I have to check a new table: ďOpcode Extensions for One- and Two-byte Opcodes by Group NumberĒ. Iím interested in row denoted as Group_11:

    This is only a part of the entire table, it shows the header and the row of the group Iím focused on.

    ModR/M byte is divided into 3 parts: mod, nnn and r/m.
    0◊22 = 00100010b
    mod = 00 (bit 7, 6)
    nnn = 100 (bit 5, 4, 3)
    r/m = 010 (bit 2,1,0)

    These numbers help you to locate the right instruction definition into the opcode extensionís table. To make things short, nnn value identifies the right cell to pick out. In this case 100b points to a blank cell, what does it mean? According to Intel manual: ďAll blanks in all opcode maps are reserved and must not be used. Do not depend on the operation of undefined or reserved opcodesď.

    Is it really an invalid instruction? All my initial investigations were done using the printed version of the Intel manual, and since of I had found some errors in it I decided to look at the most recent online version.
    This new check doesnít change anything, seems like IDA is able to disassemble an invalid instruction. Weird.

    Now the question is: is this a bug or do they (IDAís developers) know how to handle undocumented opcodes? To answer this question I have two options:
    1. try loading the malware into some more disassemblers
    2. try stepping the instruction using a debugger

    Option number 1
    Windbgís output:

    Ollydbgís output

    The result is the same, itís an invalid instruction.

    Option number 2
    This is the last check I did. I wrote a new exe file including an instruction with C6 opcode in it. The program is really simple and the source is right here:
    .text:00401000 BA B2 10 40 00 mov  edx, offset word_4010B2
    .text:00401005 C6 22 FB       mov  byte ptr [edx], 0FBh
    .text:00401008 6A 00          push 0
    .text:0040100A 68 1D 30 40 00 push offset Caption
    .text:0040100F 68 55 30 40 00 push offset Text
    .text:00401014 6A 00          push 0
    .text:00401016 E8 91 00 00 00 call MessageBoxA
    .text:0040101B C3             retn

    According to Ida it should move a byte inside 0◊4010B2 address (it has full access) showing a simple messagebox, nothing more. Unfortunately the result is not the same.

    If you run the file without a debugger it crashes and the classic error box appears. Spying inside the message errorís box I see that the error occours at offset 0◊1005, C6 opcode!
    If you run the file with Ollydbg youíll get almost the same result, the debugger stops signalling the error ďIllegal instructionĒ at 0◊401005. Again, C6 opcode!
    If you run the file using IDAís debugger youíll get a simple warning: ďAn attempt was mode to execute an illegal instruction (0◊401005)Ē. After that youíll get a sequence of error boxes, seems like Idaís debugger is not fully able to handle execution of illegal instructionÖthis is another story, btw.

    I did some more test and seems like the problem occours with all the *blank cells*; I tried with all the possible C6 combinations and with some different opcodes too. The result is always the same, Ida shows a disassembled instruction which is totally wrong!!!

    I tried reading Idaís help file but there was no mention about the problem, I donít think thereís an hidden option to set. I tried googling without luck. Due to this fact Iím not 100% sure butÖ I think itís a bug!
  14. Ollydbg v1.10 and 6E/6F/A6 opcodes, a little oversight

    Just yesterday a new version of Ollydbg was released, but Iím still using the old 1.10 version. Itís a really good debugger and until some days ago I didnít hit on few errors inside the disasm engine, nothing compared with Ida's bug btw. Look here:

    0047C720 6E OUTS DX,BYTE PTR ES:[EDI]
    0047C721 6F OUTS DX,DWORD PTR ES:[EDI]

    According to Intel Manualís opcode map 0◊6E is defined as ďOUTS/OUTSB DX, XbĒ.
    The first operand is DX register, and the second one is defined as an ďXbĒ operand.
    X: memory addressed by DS: (E)SI
    b : byte, regardless of operand-size attribute
    The error is obvious, Ollydbg shows EDI instead of ESI.

    Thereís something similar with A6 opcode. Ollydbg v1.10 shows:
    but the right line is:

    Itís an oversight on X and Y addressing method.
    The errors occour in v1.10 only, v2 shows the right instructions. I asked to Olly (Oleh Yuschuk) and he kindly replied: ďUnfortunately, I will not correct it in 1.10ÖThis project is closed, and I donít want to make any modifications.Ē. Ok, Iíll switch to v2.
  15. Downloader.Win32.Small or Win32/PolyCrypt Reversing


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


    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-
    , 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:

    {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
    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:


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

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


    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 ; "" ...
    Reverse Engineering
Page 1 of 5 12345 LastLast