Most Popular Blogs

  1. 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.
  2. 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
  3. Why is secure development so important?

    Here's a conversation I had recently with somebody:
    A: Why do you check the length of your strings so often and do that much validation of inputs?
    Me: It's more secure that way.
    A: Why do you need to make you program secure?
    Me: Better secure than sorry.
    A: It's a useless loss of time.
    Me: Bah, it's surprising sometimes the unforeseen problems that it can save.

    Here's a good example of an unforeseen problem that might happen, somebody managed to exploit a buffer overflow in OllyDbg and ImpREC.
    It happens when an export from a dll has a name longer than the buffer.

    CHimpREC does not get fooled by this trick:

    Better secure than sorry...
  4. Qt Internals & Reversing

    Today I took a break from the larger article I'm currently writing. To relax, I wrote a smaller article about the Qt framework. I hope you enjoy.

    Qt Internals & Reversing

    Half of the text of this article comes from my larger paper "Dynamic C++ Proposal". I decided that it was useful to take the part about Qt internals, put it into another article and extend it by adding a reversing part. Because of its nature, this is not the usual kind of article I write. In fact, I wrote the reversing part in less than a day. So, this is a very easy one. However, I think it is useful for people who need to reverse a Qt application and certainly wouldn't consider reading my other paper about Dynamic C++, which doesn't sound like a paper about Qt and, in fact, isn't a paper about Qt: the paragraph about Qt is only one among many others. Moreover, I haven't seen serious articles about this subject.

    The first thing which needs to be considered when reversing Qt applications is what Qt brought to the C++ language. Events (inside the Qt framework) are just virtual functions, so nothing new there. This is not a C++ reversing guide. What is new in Qt are signals and slots, which rely on the dynamism of the Qt framework.

    So, first thing I'm going to show how this dynamism works. The second part focus on reversing and, at that point, I will show how to obtain all the metadata one needs when disassembling a "Q_OBJECT" class.

    Updated November 27th, 2008 at 19:42 by Daniel Pistelli

  5. VMprotect VM_logic (in v1.8 demo)

    VM-protect hides CPU instruction by dividing single instruction into many VM_opcodes.
    But correct VM must fully reproduce CPU instructions and care about
    correct result in EFlags, so any kind simulation is not acceptable!
    lets look at VM_handlers
    VM_handlers ( ~71 )
    (SA = StackAdd , SS = StackSub)
    PopfD_SA4  (mostly used on VM_STD, VM_CLD)
    (also can be for CS,FS,GS case)
    ^^^^for byte/word/dword parts access in VM-Registers ( EAX,  AX, AL)
    PushBP_SS2  (push VM_SP)
    PushEBP_SS4  (push VM_ESP)
    (also can be for CS,FS,GS case)
    PushCPUID_SS12 (value)
    CRCsum_SA4 (pmem, size)
    all Logical & Arithmetic Handlers, which must care on EFlags, has code to store Eflags:
    pop    d, [ebp+0]
    then after such handler VM will always call PopDwordToVMRegsOpcID_SA4
    for store EFlags into VM-Registers (intermediate or main).
    so we can state, they are VM-opcode-pairs
    in VM_handlers we not see exact handlers for And/Or/Not/Xor/Sub/Rol... instructions;
    How are they emulated!?
    For Logical-instructions author builds main VM-handler "NotNotAnd";
    it's assembly  code looks so:
    Mov eax [ebp+0]
    Mov edx [ebp+4]
    Not  eax
    Not  edx
    And eax edx
    Mov [ebp+4] eax
    Pop  d,[ebp+0]
    NotNotAnd (var1, var2) = And (Not var1) (Not var2)
    and seems it is NOR LOGIC GATE!
    (below i will leave name  "NotNotAnd"; I wrote this before did search,
     but you can search in internet for "NOR LOGIC" and see all in images!)
    Other main logical instuctions will done via this NOR LOGIC GATE.
    This sequence produces valid result in EFlags for emulated logical instructions,
    so no further works need on EFlags.
    VM_NOT (A) = NotNotAnd (A, A)
    PushEBP_SS4 + PushMemDwordSS  =  push dword[esp]
    usually uses in VM_NOT, to prevent dubble calculation
    VM_AND (A, B) = NotNotAnd {VM_NOT (A), VM_NOT (B)}
                  = NotNotAnd {NotNotAnd (A, A) , NotNotAnd (B, B)}
    VM_TEST  = VM_AND ; result value stored in intermediate VM-regs, discarded
    VM_OR (A, B) = VM_NOT [NotNotAnd (A, B)]
                 = NotNotAnd {NotNotAnd (A, B) ,  <SamePushed }
    VM_XOR (A, B) = NotNotAnd {NotNotAnd (A, B)} {VM_AND (A, B)}
                  = NotNotAnd {NotNotAnd (A, B)} {NotNotAnd [NotNotAnd (A, A) , NotNotAnd (B, B)]}
    VM_AND has also truncated variant, if one parameter is Immediate value.
    VMprotect compiles Immediate value already inverted, so part VM_NOT(Immediate) skipped
    in VM_AND construction. (see "AND ecx 7 " example; also in EFlags management)
    Rol,Ror,Sar are emulated via SHLD & SHRD  handlers;
    VM_RCL and VM_RCR will handled by RclDword_SS2 & RclDword_SS2 handlers,
    for which Carry-Flag should extracted from VM_regs_Eflags;
    then instuction in handler-code "SHR CH, 1" will load extracted CFlag & do RCL/RCR
    VM_ADD is normal Addition
    for other Arithmetic-instructions VM uses VM_ADD + logic constructions for EFlags management
    (but for decompiling they are useless junk!)
    VM_ADC (A, B) = VM_ADD(A, (B+Carry_flag))
    VM_SUB (A, B) = VM_NOT [VM_ADD {B, (VM_NOT A)}] 
                EFlags = [And(0815, VM_ADD>>EFlags)] + [And( {Not(0815) }, final-VM_NOT>>EFlags)]
    (virtualized into 36 VM-bytes)
    VM_SBB (A, B) = VM_SUB(A, (B+Carry_flag))
    VM_CMP = VM_SUB ; result value stored in intermediate VM-regs, discarded
    VM_NEG (A) = VM_SUB (0, A)  ;   (constant 0 is already  inverted)
    Inc & Dec instructions in CPU not affects Carry-flag, so Carry-flag should leaved in previous state.
    VM_INC (A) = VM_ADD(1, A)
    	Carry-flag restore in EFlags
    VM_DEC (A) = VM_ADD(-1, A)
    	Carry-flag restore in EFlags | Align-Flag managing
    VMprotect virtualizes also CPU's complex-instructions,
    if such can be represented by simple instructions.
    VM_SETLE (virtualized into 80 VM-bytes!)
    there will huge EFlags testing and produced result_byte will copied into destination.
    same kind EFlags testing as SETLE, + VM_Conitional_Jump
    for example VM_MOVSB
    this complex-instruction is re-presented into simple instructions assembly group,
    then this group virtualized.
    VM_BSWAP is done in following way (27 VM-bytes)
    HiWord(result) = HiWord {Shl (LoWord_LoWord) 8}
    LoWord(result) = HiWord {Shl (HiWord_HiWord) 8}
    VM does same as CPU
    VM_XCHG !?
    while VMprotect author cares about LOCK prefix & not virtualizes instruction with it,
    author did mistake and virtualized XCHG instruction.. oops!
    to prevent XCHG virtualization, author recommends LOCK prefix
    for FLD, FSTP instructions memory content will copied on stack, & load-store from there.
    VM-Registers space is 16 dwords.
    8 of them are for Eax,Ecx,Edx,Ebx,Ebp,Esi,Edi,EFlags ;
    Esp is directly assigned to VM_stack(Ebp) ;
    2 used for Relocation-Difference & passed_Mem_pointer ;
    other  6  are used for temporal storage. mostly for intermediate EFlags,
    also for intermediate or temporal results (VM_TEST, VM_CMP), also for cleanup VM-stack;
    look at VM_SUB, where 2-intermediate Eflags will used in calculation.
     Place of real registers in this space is different not only for every other VM,
    but also can change inside one VM!
    Register read from one place, after CAN placed on intermediate place and
    old place become intermediate. so VM-Registers tracking need!
    VM-entry works so:
    we are at current stack; lets call it TOP-ESP
    at original Opcode place VMprotect puts call to VM:
    push offset-VM_IP
    call VM-StartCode
    push Registers, EFlags ; << Order of push CAN be other then order of pop on ExitVM!
    push [passed_pointer_for_security  + "crypt-constant" ] 
    ; <<new from 1.8, passed from StartupVM, which  allocates this memory,
    ; resolves imports, does file CRC-check,
    push 0 ; Relocation-Difference
    mov  esi, [esp+030] ; offset-VM_IP
    mov  ebp, esp ; ebp will VM-stack
    sub  esp, 0C0 ; 040 bytes reserved for 16 VM-Registers, other free 080 byte space will used
                  ; for user-pushed-variables. if too low become VM-stack, then VM-Registers will
                  ; moved down
    mov  edi, esp ; edi holds VM-Registers pointer
    add  esi, [ebp+0] ; add Relocation-Difference to offset-VM_IP
    			; also here jumps LoadVmIP handler
    and now code is on VM_main_loop:
    {VM_main_loop has 2 variations, down-read VM-bytes as below, or inverse - up-read}
    mov    al,[esi]
    movzx  eax,al
    inc    esi
    jmp    [JumpTable + eax*4]
    here starts  VM_BLOCK execution,
    which will move all pushed by VM-StartCode Registers/EFlags/others to VM-Registers space,
    until VM-Stack(ebp) will reach TOP-ESP.
    now starts virtualized user-code execution;
    VM-exit works so:
    VM-stack(Ebp) is at TOP-ESP; (can be above start value, if Ret_nn emulated or Esp changed)
    now VM executes VM_BLOCK-Epilog-bytes, which will pop all required values (+ return_IP).
    from VM-Registers_space to stack and Ebp is ready for ExitVM-handler;
    then last VM-byte will call ExitVM-handler,
    which pops all from stack to Registers/EFlags and does Ret to return_IP.
     because of it's original way of Jump management,
    Attached Thumbnails Attached Files
  6. 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:


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

    #- First Thread

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

    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;
    At this point we have all elements to use with success kldbgdrv.sys, that means the possibility to have access to the kernel ...
  7. Video #5 is up.

    New addition to the Reverse Code Engineering Community Forum video tutorial website:

    Video #5: x64 Disassembling and Fixing obfuscated APIs with IDA

    In this one I compare two programs compiled in x86 PE format and x64 PE32+ format with GoAsm from the same source.

    Also previous download packages have been updated (some files were missing) and I added a warning about a bug when tracing with IDA 5.1 in video #3.

    Comments/Questions/Suggestions are always welcome.
  8. Hello World

    Hey There,

    First blog entry here, hope good things will come up

    Wordpress unfortunaly does not have Code Wrappers, here code will have a better look

    Thanks for Blog Feature Woodmann!

    See you to the next post!
  9. stuffz

    DDD - Deadline Driven Development :P

    Deadline approaching again, i'm supposed to deliver that great integration-synchronization-soap-service on monday, 56hrs of 60hr estimate used, 6 operations of 15 implemented.

    And then theres the problem of converting shit ("(C00-D48, E14.5-7)*; E23**; E25**; E27**; E89.3**; E89.6**; T86; Z94" stored in a varchar2 column) to gold (
    )... talk about data quality to these guys..

    going to be a long weekend

    Updated April 14th, 2008 at 15:30 by upb

  10. Editable Listview control

    Few days ago I started renewing my PE editor's gui, I wanted to replace some edit box controls with a listview control. Everything was going well until I had to edit the value inside a cell. With the original listview control you can change the text of the first subitem of a row only, but I would like to edit every single subitem. How can I solve the problem? I didn't want to waste time solving the problem so I decided to take a look at the usual programming places starting from Code Project. Hm, nothing. I'm not so good in searching information through the net, but seems like there are working samples on mfc, .net and vb only. No win32 programming stuff... Well, I decided to give it a try subclassing the control.
    I have never subclass-ed a control before, it's my first try. I don't know if there's a better approach. I don't even know if it's the correct way to solve the problem, but it seems to works well. Let's start.

    The steps to follow are:
    1. Create an edit box that will be used to insert the new text
    2. Set the new window procedure able to handle edit control's messages
    3. Apply/abort text modification

    I use VS creating a win32 project. Add a listview control to your dialog setting "Edit labels" to FALSE. If you set the option to TRUE the OS will handle subitem modification, I prefer to avoid this behaviour.

    The idea is to change the subitem's text when a double click occours. I catch the event in the main window procedure calling the function (named SubClass_ListView_Editable) which subclasses the control.

    The first step consists of creating the edit box over the clicked subitem. To create the edit box I need to know where to put it. LVM_GETSUBITEMRECT returns information about the rectangle for a subitem of a listview control. With this information I can create the new control:
    ListView_GetSubItemRect(hListView, _lParam->iItem, _lParam->iSubItem, LVIR_LABEL, &r);
    //    Time to create the new edit box
    hEditable = CreateWindowEx(0, "EDIT", "Edit me", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_LEFT | ES_MULTILINE, r.left,, r.right-r.left,, _lParam->hdr.hwndFrom, NULL, hInst, 0);
    "r" is defined as a RECT structure:

    typedef struct _RECT {
    LONG left;        //      x-coordinate of the upper-left corner of the rectangle
    LONG top;        //    y-coordinate of the upper-left corner of the rectangle
    LONG right;      //    x-coordinate of the lower-right corner of the rectangle
    LONG bottom;   //    y-coordinate of the lower-right corner of the rectangle
    } RECT, *PRECT;
    As you can see I use "r" inside CreateWindowEx function specifying the coordinates of the new control.
    The third parameter of CreateWindowEx is the text that will be shown in the control. I use a static text but you can leave it blank or display the subitem's text, it's up to you. Now, the new control has been created and I'm going to set some features:

    SendMessage(hEditable, EM_LIMITTEXT, 8, 0);        //    It accepts no more than 8 chars
    SendMessage(hEditable, EM_SETSEL, 0, 8);        //    Text selected
    SetFocus(hEditable);                    //    Focus to the new box
    If you don't need a particular behaviour (limit text, accept only numbers...) you can avoid the first two calls but I think the third one is useful, it gives the focus to the new edit box.

    The control is complete, I have to add the new window procedure. This can be done using SetWindoLong function:

    LONG SetWindowLong(
    HWND hWnd,    //    Handle of the new edit control
    int nIndex,        //    The attribute to change
    LONG dwNewLong    //    The new value
    The function changes an attribute of a specified window, in this case I'm going to change the address of the dialog procedure. The aim is to add a new window procedure for handling edit box's messages only. I'll pass over all the other messages forwarding them towards the old window procedure.

    wpOld = (WNDPROC)SetWindowLong(hEditable, GWL_WNDPROC, SubClass_ListView_WndProc);
    SetProp(hEditable, "WP_OLD", (HANDLE)wpOld);
    SubClass_ListView_WndProc represents the new dialog procedure.
    I have to save the address of the original window procedure because I have to restore it when I'll destroy the edit box. To save the address I use SetProp function, but if you prefer you can use global variables. To end this piece of code I save some more useful information: row and column of the subitem to change:

    SetProp(hEditable, "ITEM", (HANDLE)_lParam->iItem);
    SetProp(hEditable, "SUBITEM", (HANDLE)_lParam->iSubItem);
    Which kind of messages will I have to catch? WM_KEYDOWN and WM_DESTROY only, all the other messages are passed to the original window procedure in this way:

    return CallWindowProc((WNDPROC)GetProp(hEditable, "WP_OLD"), hwnd, uMsg, wParam, lParam);
    I catch WM_KEYDOWN because I have to handle ENTER ans ESC key. When you hit ENTER the text will be saved in the subitem, and when you click ESC the operation will be aborted:

    case WM_KEYDOWN:
    if (LOWORD(wParam) == VK_RETURN)
    // Item and suibtem to change
    LvItem.iItem = GetProp(hEditable, "ITEM");
    LvItem.iSubItem = GetProp(hEditable, "SUBITEM");
    // Where to store the new text
    LvItem.pszText = text;
    // Get new text and set it in the subitem
    GetWindowText(hEditable, text, sizeof(text));
    SendMessage(hListView, LVM_SETITEMTEXT, (WPARAM)GetProp(hEditable, "ITEM"), (LPARAM)&LvItem);
    else if (LOWORD(wParam) == VK_ESCAPE)
    If you press ESC the edit box will be destroyed without changing the subitem's text.
    When ENTER is pressed I simply get the text storing it in the subitem. After that I can destroy the edit box.
    There's something more to say about VK_RETURN. Look at CreateWindowEx parameters, there's a ES_MULTILINE value. The value is necessary otherwise the application refuses to catch ENTER.
    The last thing I check in the new window procedure is WM_DESTROY message, I simply remove the saved properties and then I restore the original window procedure calling SetWindowLong again.

    What about mouse click when I'm changing the subitem's value? It's like VK_ESCAPE key, I remove the edit box aborting the operation. See the attached source code for details.

    The picture represents the subclassing method in action:

    The code can be optimized for sure, just fix/change/remove/add everything you need.
    Feel free to post your comment/suggestion/criticism here.
    Download the VS project from

    Game over!

    Updated November 6th, 2007 at 07:05 by ZaiRoN

  11. Weird export forwarding thanks to Vista x64 SP1

    After installing the SP1 for Vista x64, I noticed that ImpREC stopped working properly on some files using DefWindowProcA and DefWindowProcW from user32.dll.
    These 2 APIs are forwarded as usual respectively to NtdllDefWindowProc_A and NtdllDefWindowProc_W from ntdll.dll but cannot be "unforwarded" back to user32.dll using the traditional method.

    I'll explain how the loader usually resolves forwarded exports, the unforwarding method used by ImpREC and why it fails on those 2 particular cases.

    Using the information provided by the Import Directory of the executable, the loader looks for a matching name or ordinal in the specified dll.
    After a match is found, the corresponding entry from the AddressOfFunctions array is retrieved from the Export Directory and augmented by the ImageBase of the dll.
    That value is then written to the IAT.

    Sometimes, for compatibility reasons, an import can be forwarded to another one from a different module.
    In that case, the AddressOfFunctions entry does not lead to code but to an ASCII string composed of the module name and the import name or ordinal.
    .text:7DCA751E ; LRESULT __stdcall DefWindowProcA(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam)
    .text:7DCA751E DefWindowProcA  db 'NTDLL.NtdllDefWindowProc_A',0
    .text:7DCA7539 ; Exported entry 151. DefWindowProcW
    .text:7DCA7539                 public DefWindowProcW
    .text:7DCA7539 ; LRESULT __stdcall DefWindowProcW(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam)
    .text:7DCA7539 DefWindowProcW  db 'NTDLL.NtdllDefWindowProc_W',0
    The loader then restarts the whole process from the beginning, using the info from the forwarding string rather than the original info from the Import Directory of the executable.
    The Entry Point of the newly-found function is written to the IAT instead.

    ImpREC finds the IAT and goes through it to identify all the imports that it contains.
    Some entries belong to ntdll.dll and need to be "unforwarded" to their original location.
    DefWindowProcA should be unforwarded from NtdllDefWindowProc_A.

    If everything goes well, the original import is found by "bruteforcing" the Entry Point of every function until a forwarding string is found: NTDLL.DefWindowProc_A at the Entry Point of DefWindowProcA in user32.dll and then comes in some guesswork.

    Because an import could have been forwarded from another module, doesn't mean that it really was, there are some false-positives.
    The guesswork is based on a very crude probability analysis based on the module name of the previous import and the module name of the next import.
    EndDialog from user32.dll is almost never forwarded from shlwapi32.dll.

    Something changed with Vista x64 SP1 through some modifications of wow64.dll since the content of the \SysWOW64 directory should be the same as the standard Vista 32-bit SP1.
    Some hotfix is applied only during run-time by WoW64.

    During execution, the AddressOfFunctions entries of DefWindowProcA and DefWindowProcW from user32.dll are modified.
    The RVA based at the ImageBase becomes greater than the SizeOfImage and leads into the memory area of ntdll.dll rather than the usual forwarding string.
    Instead of 0x0001751E, the AddressOfFunctions becomes 0x015C3D42 or 0x01793D42 or 0x01B83D42 for DefWindowProcA.

    The same result is achieved but this method prevents the unforwarding of some imports through the traditional method since there is no forwarding string anymore.
    It leads into code now:
    ntdll.dll:77C43D42 ntdll_NtdllDefWindowProc_A:
    ntdll.dll:77C43D42 jmp     ds:off_77CB6020
    ntdll.dll:77CB6020 off_77CB6020 dd offset loc_7669C0E7     ; DATA XREF: ntdll.dll:ntdll_NtdllDefWindowProc_Ar
    And jumps back to user32.dll:
    user32.dll:7669C0E7 loc_7669C0E7:                           ; DATA XREF: ntdll.dll:off_77CB6020o
    user32.dll:7669C0E7 push    10h
    user32.dll:7669C0E9 push    offset unk_7669C158
    user32.dll:7669C0EE call    near ptr unk_766BC240
    user32.dll:7669C0F3 call    near ptr unk_766980D7
    Unforwarding is still possible anyway since a side-effect could be identified: the Entry Point of both imports become identical.
    GetProcAddress(DefWindowProcA) == GetProcAddress(NtdllDefWindowProc_A)
    GetProcAddress(DefWindowProcW) == GetProcAddress(NtdllDefWindowProc_W)

    To sum everything up:
    It doesn't really matter, the average user of Vista x64 SP1 would never notice the difference.
    Unpacking in a 32-bit VM instead is still more reliable than under WoW64.

    This will be a part of my proposed upcoming ReCon talk.
  12. Guidelines to MFC reversing

    Tools - References
    Reversing Microsoft Visual C++ Part II: Classes, Methods and RTTI

    Prologue: What is MFC?
    The Microsoft Foundation Classes Library (also Microsoft Foundation Classes or MFC) is a library that wraps portions of the Windows API in C++ classes, including functionality that allows to use a default application framework. Classes are defined for many of the handle-managed Windows objects and also for predefined windows and common controls.

    Software developed with MFC may import MFC80U.dll (MFC80U is the name of the last version of the dll, as I'm writing), it depends on the type of compilation: as a static library or as a shared DLL.
    I'll analyze a software which imports the dll and has debug infos, just to make the job easier.
    Once you understand MFC in this way, you can analyze MFC software compiled statically just adding to IDA the signatures of MFC and VisualC.

    This is a standard C source code for windows:
    LRESULT CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
            case WM_COMMAND:
                    case IDC_ABOUT:
                            DialogBoxParam(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_DIALOG1), NULL, (DLGPROC)MainDialogProc, 0);
                            // ...
    Instead this is source code that uses MFC:
    class CAboutDlg : public CDialog
    // Dialog Data
            enum { IDD = IDD_ABOUTBOX };
            virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
    // Implementation
    CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)  //CAboutDlg::IDD is dialog ID          
    void CAboutDlg::DoDataExchange(CDataExchange* pDX)
    BEGIN_MESSAGE_MAP(CAboutDlg, CDialog) //Dialog Message Map: is like DialogProc
    // App command to run the dialog
    void CProvaRevApp::OnAppAbout()
            CAboutDlg aboutDlg;
    How you can imagine the disasm of MFC software is harder to understand.

    MFC Main
    This is the Main disasm of our target:
    .text:00401CBB                 public start
    .text:00401CBB                 call    ___security_init_cookie
    .text:00401CC0                 jmp     ___tmainCRTStartup
    .text:004019FB ___tmainCRTStartup proc near            ; CODE XREF: start+5�j
    .text:004019FB                 push    5Ch
    .text:004019FD                 push    offset unk_403DD8
    .text:00401A02                 call    __SEH_prolog4
    ;... other initialization code
    .text:00401B3E                 push    ecx             ; nShowCmd
    .text:00401B3F                 push    eax             ; lpCmdLine
    .text:00401B40                 push    ebx             ; hPrevInstance
    .text:00401B41                 push    400000h         ; hInstance
    .text:00401B46                 call    _wWinMain@16    ; wWinMain(x,x,x,x)
    ; int __stdcall wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd)
    _wWinMain@16 proc near
            jmp     ?AfxWinMain@@YGHPAUHINSTANCE__@@0PA_WH@Z ; AfxWinMain(HINSTANCE__ *,HINSTANCE__ *,wchar_t *,int)
    _wWinMain@16 endp
    As you can see WinMain calls AfxWinMain.
    If you have VisualStudio you can see MFC source code, in this article I'll report only the functions we'll need.
    int AFXAPI AfxWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
            _In_ LPTSTR lpCmdLine, int nCmdShow)
            ASSERT(hPrevInstance == NULL);
            int nReturnCode = -1;
            CWinThread* pThread = AfxGetThread();
            CWinApp* pApp = AfxGetApp();
            // AFX internal initialization
            if (!AfxWinInit(hInstance, hPrevInstance, lpCmdLine, nCmdShow))
                    goto InitFailure;
            // App global initializations (rare)
            if (pApp != NULL && !pApp->InitApplication())
                    goto InitFailure;
            // Perform specific initializations
            if (!pThread->InitInstance())
                    if (pThread->m_pMainWnd != NULL)
                            TRACE(traceAppMsg, 0, "Warning: Destroying non-NULL m_pMainWnd\n");
                    nReturnCode = pThread->ExitInstance();
                    goto InitFailure;
            nReturnCode = pThread->Run();
            return nReturnCode;
    This is the disasm of AfxWinMain:
    .text:7831D2D2                 public AfxWinMain
    .text:7831D2D2 AfxWinMain      proc near
    .text:7831D2D2                 push    ebx
    .text:7831D2D3                 push    esi
    .text:7831D2D4                 push    edi
    .text:7831D2D5                 or      ebx, 0FFFFFFFFh
    .text:7831D2D8                 call    AfxGetModuleThreadState
    .text:7831D2DD                 mov     esi, [eax+4] ;pThread
    .text:7831D2E0                 call    AfxGetModuleState
    .text:7831D2E5                 push    [esp+0Ch+arg_C]
    .text:7831D2E9                 mov     edi, [eax+4]  ;pApp
    .text:7831D2EC                 push    [esp+10h+arg_8]
    .text:7831D2F0                 push    [esp+14h+arg_4]
    .text:7831D2F4                 push    [esp+18h+arg_0]
    .text:7831D2F8                 call    AfxWinInit
    .text:7831D2FD                 test    eax, eax
    .text:7831D2FF                 jz      short loc_7831D33D
    .text:7831D301                 test    edi, edi    
    .text:7831D303                 jz      short loc_7831D313
    .text:7831D305                 mov     eax, [edi]
    .text:7831D307                 mov     ecx, edi
    .text:7831D309                 call    dword ptr [eax+98h]
    .text:7831D30F                 test    eax, eax
    .text:7831D311                 jz      short loc_7831D33D
    .text:7831D313 loc_7831D313:
    .text:7831D313                 mov     eax, [esi]
    .text:7831D315                 mov     ecx, esi
    .text:7831D317                 call    dword ptr [eax+58h]
    .text:7831D31A                 test    eax, eax
    .text:7831D31C                 jnz     short loc_7831D334
    .text:7831D31E                 cmp     [esi+20h], eax
    .text:7831D321                 jz      short loc_7831D32B
    .text:7831D323                 mov     ecx, [esi+20h]
    .text:7831D326                 mov     eax, [ecx]
    .text:7831D328                 call    dword ptr [eax+68h]
    .text:7831D32B loc_7831D32B:
    .text:7831D32B                 mov     eax, [esi]
    .text:7831D32D                 mov     ecx, esi
    .text:7831D32F                 call    dword ptr [eax+70h]
    .text:7831D332                 jmp     short loc_7831D33B
    .text:7831D334 loc_7831D334:
    .text:7831D334                 mov     eax, [esi]
    .text:7831D336                 mov     ecx, esi
    .text:7831D338                 call    dword ptr [eax+5Ch]
    .text:7831D33B loc_7831D33B:  
    .text:7831D33B                 mov     ebx, eax
    .text:7831D33D loc_7831D33D:
    .text:7831D33D                 call    AfxWinTerm
    .text:7831D342                 pop     edi
    .text:7831D343                 pop     esi
    .text:7831D344                 mov     eax, ebx
    .text:7831D346                 pop     ebx
    .text:7831D347                 retn    10h
    .text:7831D347 AfxWinMain      endp
    In the code there are calls as call [eax+XXh]: actually the call to AfxGetApp (and AfxGetThread) gives back a pointer to a structure that has offsets of all functions used by MFC framework.
    In this case edi (pApp) holds the offset of 405498, which value is 40349C VA, where the virtual functions table of CWinApp is stored:
    .rdata:0040349C off_40349C      dd offset ?GetRuntimeClass@CWinApp@@UBEPAUCRuntimeClass@@XZ ;CWinApp::GetRuntimeClass(void)
    .rdata:004034A0                 dd offset sub_401010
    .rdata:004034A4                 dd offset nullsub_1
    .rdata:004034A8                 dd offset nullsub_2
    .rdata:004034AC                 dd offset nullsub_1
    .rdata:004034B0                 dd offset ?OnCmdMsg@CCmdTarget@@UAEHIHPAXPAUAFX_CMDHANDLERINFO@@@Z ; CCmdTarget::OnCmdMsg(uint,int,void *,AFX_CMDHANDLERINFO *)
    .rdata:004034B4                 dd offset ?OnFinalRelease@CCmdTarget@@UAEXXZ ; CCmdTarget::OnFinalRelease(void)
    .rdata:004034B8                 dd offset ?IsInvokeAllowed@CCmdTarget@@UAEHJ@Z ; CCmdTarget::IsInvokeAllowed(long)
  13. Using nt!_MiSystemVaType to navigate dynamic kernel address space in Windows7

    32-bit Windows Vista and later use a feature known as Dynamic Kernel Address Space. To quote from a technical article - the Memory Manager dynamically manages the kernel's address space, allocating and deallocating space to various uses to meet the needs of the system. As a result, the amount of virtual memory being used for internal components, device drivers, the file system cache, kernel stacks, system PTE's, per-session code data structures as well as paged and nonpaged pool memory will grow and shrink based on system activity.

    The key to keeping track of all this dynamic memory lies in the unexported pointer nt!_MiSystemVaType, a mapped array of byte values that describes both the type of memory allocation, and by virtue of the indexed position within the array, the location and size of the memory block. Each time there is a new memory allocation, the MiSystemVaType array is updated.

    In this code project I will try to show how to use MiSystemVaType to navigate the dynamic kernel address space to get a complete mapping of the various allocation types. In addition, I'll give an example of how to use it to find and identify loaded drivers, as well as discuss how it might be used to conduct efficient memory pool searches.

    Here are a few background articles on the subject at hand:

    Understanding the kernel address space on 32-bit Windows Vista

    Inside the Windows Vista Kernel: Part 2

    Windows® Internals, Fifth Edition
    9.5.7 Dynamic System Virtual Address Space Management


    nt!_MiSystemVaType is a pointer to an array of byte values of enum type MI_SYSTEM_VA_TYPE. Each byte in the array describes a single Large Page and maps, in sequential order, the entire upper 2GB of logical address space from 0x80000000 (MmSystemRangeStart) - 0xFFFFFFFF. The size of the byte array is either 0x400 when PAE is enabled, where the default size of a Large Page is 2MB, or 0x200 in non-PAE mode, which uses a Large Page size of 4MB.

    The enum type values can be listed with WinDbg/LiveKd:

    kd> dt nt!_MI_SYSTEM_VA_TYPE
       MiVaUnused = 0n0
       MiVaSessionSpace = 0n1
       MiVaProcessSpace = 0n2
       MiVaBootLoaded = 0n3
       MiVaPfnDatabase = 0n4
       MiVaNonPagedPool = 0n5
       MiVaPagedPool = 0n6
       MiVaSpecialPoolPaged = 0n7
       MiVaSystemCache = 0n8
       MiVaSystemPtes = 0n9
       MiVaHal = 0n10
       MiVaSessionGlobalSpace = 0n11
       MiVaDriverImages = 0n12
       MiVaSpecialPoolNonPaged = 0n13
       MiVaMaximumType = 0n14

    PAE mode:

    The Physical Address Extension (PAE) processor feature enables use of 64-bit page table entries for physical addresses that are wider than 32 bits. If PAE is enabled, the size of page table entries (PTEs) are increased from 32 to 64 bits (4 to 8 bytes). Consequently, the size of a Large Page is reduced from 4MB to 2MB in PAE mode. One can determine the size of the PTE data structure, nt!_MMPTE, (and hence if PAE is enabled or not) with the command:

    kd> dt -v nt!_MMPTE
    struct _MMPTE, 1 elements, 0x8 bytes
    To determine if PAE is enabled programmatically we can read the ProcessorFeatures field of KUSER_SHARED_DATA, a shared memory structure mapped to all processes and located at 0x7FFE0000 in usermode. This is equivalent to what the IsProcessorFeaturePresent API does.

    KUSER_SHARED_DATA is duplicated at 0xFFDF0000 in kernelmode. Fortunately ntddk.h gives us a handy macro with which to work with it. The snippet below will give us (by inference) the size of nt!_MMPTE, from which we can derive the size of a large page and the size of the MiSystemVaType array.

    PHP Code:
    #define KI_USER_SHARED_DATA         0xffdf0000
    #define SharedUserData  ((KUSER_SHARED_DATA * const)   KI_USER_SHARED_DATA)

    // Determine if PAE is enabled from  KI_USER_SHARED_DATA.ProcessorFeatures

    DbgPrint ("PAE enabled\n");

    sizeof_MMPTE 8;

    } else {

    DbgPrint ("PAE not enabled\n");

    sizeof_MMPTE 4;

    In the registry the PAE status can be read from
    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\PhysicalAddressExtension

    Here is a summary of the differences between PAE and non-PAE mode which are relevant to our code:

    (PAGE_SIZE = 0x1000)
    PAE enabled:
        nt kernel version:
             ntkrnlpa.exe: 1 CPU, PAE
             ntkpamp.exe:  n CPU, SMP, PAE
        sizeof_MMPTE = 8
        LARGE_PAGE_SIZE = PAGE_SIZE * PAGE_SIZE / sizeof_MMPTE = 0x200000  (2MB)
        sizeof MiSystemVaType array = (0xFFFFFFFF+1 -  (ULONG)MmSystemRangeStart) / LARGE_PAGE_SIZE = 0x400
        0x400 * 0x200000 = 0x80000000 = (0x80000000 / 1024 /1024 /1024) =  2GB
    PAE disabled:
        nt kernel version:
            ntoskrnl.exe: 1 CPU
            ntkrnlmp.exe: n CPU, SMP
        sizeof_MMPTE = 4
        LARGE_PAGE_SIZE = PAGE_SIZE * PAGE_SIZE / sizeof_MMPTE = 0x400000  (4MB)
        sizeof MiSystemVaType array = (0xFFFFFFFF+1 -  (ULONG)MmSystemRangeStart) / LARGE_PAGE_SIZE = 0x200
        0x200 * 0x400000 = 0x80000000 = 2GB
    PAE is enabled by default in Windows 7, if you wish to test the included code in non-PAE mode use BCDEdit as follows:

    If DEP is enabled, PAE cannot be disabled. Use the following BCDEdit /set commands to disable both DEP and PAE:

    bcdedit /set nx AlwaysOff
    bcdedit /set pae ForceDisable

    To restore:

    bcdedit /set nx Optout (or one of [Optin |OptOut | AlwaysOn])
    bcdedit /set pae ForceEnable

    Finding the unexported pointer nt!_MiSystemVaType:

    We need to programmatically find the offset to nt!_MiSystemVaType. Since this is an unexported pointer we'll have to parse a known kernel function which makes use of the variable. Uh Oh. Production code need not apply . Oh well, this is an RCE forum, right? At least that's better than using a hard-coded value, not as good as using symbols.

    Rather than using a classic byte-pattern search that is often used to find unexported variables, I made use of a clever idea Zairon mentioned to me, that of looking for cross references between code and data sections in order to pick up instances of data variable usage. In essence, derive XREFS similar to IDA.

    I really like Zairon's idea of using XREF analysis over a byte-pattern search method because it's simple, highly adaptable, and is less susceptible to changing byte patterns between different OS kernel versions.

    The function I chose to parse for the offset of MiSystemVaType was the exported MmIsNonPagedSystemAddressValid procedure. The simple algorithm logic I used was: "Scan for the first data XREF to the section called '.data''"

    See the source code for the specific algorithm I implemented, plus a few suggestions for creating a more rigorous algorithm if desired, such as using a length disassembly engine (LDE) to avoid the possibility a false XREF could occur across instructions.

    The simple logic above should be valid for all current 32-bit nt* kernel versions in Windows 7 / Vista / Server 2008. Even better, MmIsNonPagedSystemAddressValid has been deemed to be obsolete and is exported to support existing drivers only, so it's more unlikely to change anytime soon.

    _MmIsNonPagedSystemAddressValid@4 proc
    8B FF                             mov     edi, edi
    55                                push    ebp
    8B EC                             mov     ebp, esp
    53                                push    ebx
    56                                push    esi
    8B 35 18 57 97 82                 mov     esi, ds:_MmSystemRangeStart //  xref to ALMOSTRO
    57                                push    edi
    8B 7D 08                          mov     edi, [ebp+VirtualAddress]
    BB F8 3F 00 00                    mov     ebx, 3FF8h
    3B FE                             cmp     edi, esi
    72 25                             jb      short loc_828F17A8
    8B C6                             mov     eax, esi
    C1 E8 12                          shr     eax, 12h
    8B CF                             mov     ecx, edi
    C1 E9 12                          shr     ecx, 12h
    23 C3                             and     eax, ebx
    23 CB                             and     ecx, ebx
    2B C8                             sub     ecx, eax
    C1 F9 03                          sar     ecx, 3
    8A 81 60 51 95 82                 mov     al, _MiSystemVaType[ecx]  // xref to .data

    Making sense of MiSystemVaType:

    Now that we've got the pointer to nt!_MiSystemVaType, what do we do with it? The first obvious thing is just to list everything out.

    Let's take a look at the first 0x10 bytes of the MiSystemVaType array. Each byte maps a logical address block of LARGE_PAGE_SIZE, beginning at ...
    Attached Thumbnails Attached Files
  14. IDC scripting a Win32.Virut variant - Part 2

    This post continues Part 1, which should be read first for reference.

    Some points of interest about the viral code itself:

    • There is a small RDTSC timing check at the start. If the difference between 2 RDTSC calls is greater than 0x100 then it's determined that you're in a VM or single step tracing the code (or have only 4K of memory maybe!). In that case the virus doesn't infect but instead returns to the default address of 0x40101D and only tries to connect to the irc server.

      Doing a little test I found that 2 RDTSC calls would return a difference of between 1000-1500 ticks under VMWare, but only 50 ticks under a real system. Not a sophisticated VM test, but it seems to work.

    • There is also apparently a Redpill type VM check which I found crashes under VMWare.

      :0040323A RedPill:      ; CODE XREF: Main+2
      :0040323A       push    eax
      :0040323B       sidt    qword ptr [esp-2]
      :00403240       pop     eax
      :00403241       mov     eax, [eax+6]    ; invalid pointer, crashes under VMWare
      :00403241                               ; buggy code?!
      :00403244       shl     eax, 10h
      :00403247       jns     short Force_RDTSC_test_to_fail
    • The virus is Win9x/Me compatible. If the OS is Win2K or greater it hooks NtCreateFile / NtOpenFile. If Win9x, it hooks VWIN32_Int21Dispatch and monitors for the MS-DOS LFN (long file name) service 0x716C, which is used for open/create. The Win9x related stuff is "old school" and has been documented before. If interested see:

      The VxDCall backdoor

    • The virus copies itself to the last section of a file it infects, but the initial seed value for the Xor decryption routine is different for every infected file (uses an RDTSC randomization), showing its polymorphic nature. After copying itself from running memory into the file, the main Decrypt function is called once again, but this time it's encrypting itself in the file, the XOR routine being reversible.

    • After determining the system offsets for the Nt calls it hooks, the virus creates a section, maps itself into it, then immediately continues execution from this high memory mapping address. All further execution is run from this memory mapped image. This makes it a little more difficult when live tracing and comparing addresses to the disassembly, but the jump to high memory makes a great breakpoint when you get deeper into the live analysis.

      .data:004035FE lea eax, dword_403606
      .data:00403604 jmp eax
      .data:00403606 ... ; this is now running from high mem

    • One interesting (though not original) thing the virus does is how it disables Windows File Protection (WFP) so it can infect any file in any directory without being subverted.

      Immediately after beginning execution in the high memory mapped section that I just mentioned, it calls NtAdjustPrivilegesToken with SeDebugPrivilege privilege so it is able to call CreateRemoteThread() in the Winlogon process.

      How to obtain a handle to any process with SeDebugPrivilege

      Using a CreateToolhelp32Snapshot/Process32Next loop, it scans for the 4th process returned, or Winlogon. Then it hooks the 4 Nt calls within the winlogon address context by overwriting the Service Id of the relevant Zw ntdll KiFastSystemCall with a detour to its own hook routine (which is mapped into winlogon memory space).

      Once this is done it calls CreateRemoteThread followed by a short Sleep routine to let the remote thread execute within winlogon context. After the Sleep nap, the CreateToolhelp32Snapshot loop continues and hooks the 4 Nt calls in every other active process.

      The aforementioned CreateRemoteThread winlogon thread does a number of things besides disabling WFP. It sets up the Win9x/Me VxDCall file hook if applicable, writes the irc sites IP address to the Windows hosts file, accesses the registry, creates some Events, creates a couple more threads, one of which maps out ntoskrnl and the KeServiceDescriptorTable, tries to connect to the internet, etc.

      WFP is disabled by patching in a call to ExitThread immediately after a NtWaitForMultipleObjects call in an sfc.os.dll function called SfcWatchProtectedDirectoriesWorkerThread. The function name pretty much describes what it does, it's a worker thread which continually monitors for file changes from a protected dll list. After patching SfcWatchProtectedDirectoriesWorkerThread the virus calls SfcTerminateWatcherThread. (IDA + symbols is a wonderful thing )

      Here is what the function looks like in code:

      // The search pattern in sfc.os.dll
      :00403CE4          Pattern_SFC_OS_DLL:    ; DATA XREF: Disable_WFP+F
      :00403CE4 6A 01       push    1
      :00403CE6 6A 01       push    1
      :00403CE8 FF 33       push    dword ptr [ebx]
      :00403CEA FF 73 04    push    dword ptr [ebx+4]
      :00403CEA          ; -----------------------------------------------
                            // part of call ds:NtWaitForMultipleObjects
      :00403CED FF 15       dw 15FFh   
      :00403CEF Disable_WFP     proc near
      // EAX = base address of sfc.os.dll returned from GetModuleHandleA
      :00403CEF       test    eax, eax
      :00403CF1       jz      short locret_403CE3
      :00403CF3       push    0Bh
      :00403CF8       mov     edx, eax
      :00403CFA       pop     ebx
      :00403CFB       add     edx, [eax+IMAGE_DOS_HEADER.e_lfanew]
      :00403CFE       lea     esi, Pattern_SFC_OS_DLL
                              // SectionTable.PointerToRawData .text section
      :00403D04       mov     edi, [edx+10Ch]
                              // SectionTable.SizeOfRawData .text section
      :00403D0A       mov     ecx, [edx+108h]
      :00403D10       add     edi, eax
      :00403D12       sub     ecx, ebx
      :00403D14 Find_Pattern:           ; CODE XREF: Disable_WFP+2E
      :00403D14       pusha
      :00403D15       mov     ecx, ebx
      :00403D17       repe cmpsb
      :00403D19       popa
      :00403D1A       jz      short loc_403D21
      :00403D1C       inc     edi
      :00403D1D       loop    Find_Pattern
      :00403D1F       jmp     short locret_403CE3
      :00403D21 ; ----------------------------------------------------
      :00403D21 loc_403D21:             ; CODE XREF: Disable_WFP+2B
      :00403D21       add     edi, 0Fh
      :00403D24       push    edi
      :00403D25       mov     edx, esp
      :00403D27       push    ebx
      :00403D28       mov     ecx, esp
      :00403D2A       push    eax
      :00403D2B       push    esp             ; OldProtect
      :00403D2C       push    40h             ; Protect
      :00403D2E       push    ecx             ; RegionSize
      :00403D2F       push    edx             ; BaseAddress
      :00403D30       push    0FFFFFFFFh      ; hProcess
      :00403D32       call    NtProtectVirtualMemory
      :00403D38       add     esp, 0Ch
      :00403D3B       mov     edx, ExitThread
      :00403D41       sub     edx, edi
      :00403D43       sub     edx, 7
      // Patch in ExitThread call immediately after
      // NtWaitForMultipleObjects in sfc.os function
      // SfcWatchProtectedDirectoriesWorkerThread
      // patch in push eax opcodes (6A00) + Call near, relative opcode (E8)
      :00403D46       mov     dword ptr [edi], 0E8006Ah  
      // patch in ExitThread displacement
      :00403D4C       mov     [edi+3], edx
      :00403D4F       retn
      :00403D4F Disable_WFP     endp ;
      Once I figured out what the code was doing I was able to do a search and found that the entire routine for disabling WFP was ripped from here:


    • And finally, and congratulations if you're still reading this, there is a mysterious Int 0x2C interrupt call at the start of the program. This call is the main reason this virus held my interest for so long and is ultimately the genesis of this article. I was hoping a full analysis of the program would point out its purpose. Alas, I'm still as clueless as when I started.

      Therefore I open up to speculation (or reason or knowledge), the true function of this Int2C call, if there is one, to you Gentle Reader (may Asimov forgive me).

      Here is the start of the code once again showing the important bits. I've tried to outline the "normal" path of infection by highlighting in Blue. Under any condition that I can see, Int2C will always return STATUS_NO_EVENT_PAIR, so that particular path of execution is fixed.

      The question is then. is this just quirky code to confuse us, or can an Int2C call have a real purpose in Ring3 under certain conditions?

      :00403200 start           proc near 
      :00403200                 cld
      :00403201                 call    Main
      :00403201 start           endp
      :0040321F popebp_ret:
      :0040321F                 pop     ebp
      :00403220                 retn
      :00403221 Force_RDTSC_test_to_fail:
      :00403221                 push    ebp
      :00403222                 mov     eax, 8000h
      :00403227                 xor     ecx, ecx
      :00403229                 jmp     short loc_403255
  15. Some Quick Insights Into Native .NET exe's (part 1 of?)

    So, what are natively compiled .NET exes? Well, to answer that question we have
    to go back to how the .NET runtime works.

    All your VB.NET and C# code is translated during compilation from the language
    in question to MSIL (Microsoft Intermediate Language). This is a sort of stack
    based assembler variant that, in combination with metadata present in the executable,
    can be translated back into high level code ( and C#). This is why tools
    such as reflector and dotDecompile exist on the .NET platform; the same effect
    is much harder to achieve with native code.

    Basically, the new possibilities for decompilation introduced in the .NET
    architecture have caused a lot of companies to shit themselves. Intellectual
    property (IP) is the lifeblood of the company. If someone can rip the idea and
    or source out of your product, and implement it in theirs, there is very little
    you can do to prevent them. This is becoming a major issue in the .NET dev circles
    (along with the fact that decompilation = easier cracking for malicous reverse
    engineers bent upon pirating goods to disrupt the global economy and plunge the
    world into deep recession).

    So, .NET devs are a lot more willing to invest time and money in securing their
    products. Frankly, given how shitty 99% of the "security" products on the market
    are, they're wasting their time.

    One of the security products that in my opinion falls into the "not well thought
    out" category is anything that boasts security through native code. Look at it this
    way: hackers have been cracking native code for how long? 2 decades? 3 decades?
    What makes you think that all of a sudden, in the grand year of 2008, they will
    start having problems hacking native code? Maybe it will be even EASIER for them
    because they no longer have to adapt to the foreign .NET architecture, but now
    simply have to load the exe into Olly and go at it the "old fashioned way".

    So, back to the question at hand. What are natively compiled .NET exes? Basically,
    they are exe's containing platform specific code that has been produced by the JIT
    instead of the aforementioned MSIL code. This makes it impossible to decompile the
    .NET code the old fashioned way (with Reflector).

    Producing .NET exes isn't really that simple. To natively compile a .NET exe into a
    native exe, you must use ngen.exe (comes with the SDK). Ngen is a native code
    generator provided by M$, and it's purpose is to increase performance. An application
    that demands performance might use Ngen to compile itself during installation.

    The newly produced native executables are not runnable. In fact, they are not even
    valid Win32 applications. They may be located in the Global Assembly Cache (GAC) of
    the local machine where Ngen was executed. If you do not know what the GAC is, read
    up on it here:

    Demystifying the .NET Global Assembly Cache
    By Jeremiah Talkar

    Now, I guess you're anxious to see the native exes I was just talking about. Desafortunadamente,
    it is not possible for you to access the GAC with Windows explorer right away. Thankfuly,
    a quick registry fix from the article quoted above will lets us browse the GAC from
    Windows Explorer. I quote:

    "If you want to disable the Assembly Cache Viewer and see the GAC in all its naked glory
    within Windows Explorer, you can set HKLM\Software\Microsoft\Fusion\DisableCacheViewer [DWORD] to 1."

    Simple, eh? Now, take any exe .NET exe (for example helloworld.exe) and execute Ngen upon it:

    C:\Windows\system32>cd C:\temp

    C:\temp>ngen HelloWorld.exe
    Microsoft (R) CLR Native Image Generator - Version 2.0.50727.1433
    Copyright (c) Microsoft Corporation. All rights reserved.
    Installing assembly C:\temp\HelloWorld.exe
    Compiling assembly C:\temp\HelloWorld.exe ...
    HelloWorld, Version=, Culture=neutral, PublicKeyToken=null <debug>

    Press any key to continue . . .

    There, we Ngen'd HelloWorld.exe. Now, whenever we execute HelloWorld.exe, the JIT will load
    the native HelloWorld.exe from the GAC and execute it, instead of compiling the IL in the
    HelloWorld.exe we are double clicking on. Like I said, this is intended to improve performance.

    To find the native compiled HelloWorld.exe on our hard drive, browse to

    This is different on each computer.

    You should see one file, and that is: As I mentioned before, it is this file
    that is loaded as a module when the JIT executes.

    As you can see by double clicking on, it is not a valid image. This means that
    you cannot distribute it. That is one of the downfalls of Ngen.exe. You must have a valid exe
    with MSIL in it to generate an Ngen image. You cannot simply distribute the Ngen'd image as it
    is invalid.

    Salamander .NET Protector changes all this. This is one of the protectors that takes a somewhat
    amusing approach towards solving the problem of invalid Ngen'd images. I took a quick look at it
    by downloading the Scribble Demo from their homepage:
    (no reversing involved, reversing is illegal you know :P )

    Just look at the file paths in the link above:

    \scribble-native\mdeployed\C\WINDOWS\assembly\NativeImages_v2.0.50727_32\Scribble\eccb67b11447c9488a7a35bab51a a59b

    It will become quite obvious that all its doing is
    emulating the GAC. It has its own GAC in there, with all the components scribble (native compiled)
    needs. When you run scribble.exe, it initializes the .NET Jit and points it towards its own GAC. .NET
    then grabs everything it needs from there (including native compiled scribble(, and executes it.

    Now that's just a hypothesis on how it works. Without real reversing I cannot verify my results.
    And since reversing it would be illegal, I guess I'll have to pass up the opportunity this time :P

    Now, how secure is salamander .net protector? Well, I guess compared to MSIL code native code is 10x more secure, but
    does that mean that its really SECURE? Not necessarily.

    First of all, there is a small bug in the protector where it makes it preserve the IL code from the original exe. Ntoskrnl
    described it in his article that he did on salamander .net protector. You can find it here:

    But lets just ignore the IL code in memory for now, and focus on attacking the native code. Remember that HelloWorld.exe from
    earlier in the chapter? Let's try Ngenning that, and then having some fun with it :>

    First off, we need both need to be looking at the same HelloWorld.exe. Here is the code that I used, just paste it into an
    empty project and compile. For button1 you can put any button, so long as it executes the code below
    BTW, for the purposes of this project I used express 2008

    Public Class Form1
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        End Sub
    End Class
    Simple piece of work, eh? Will just pop out a messagebox saying Greetings, and that's that. Compile it, run it, and then
    proceed to the next paragraph of this article.

    Ok now, first of all lets generate a valid native image for HelloWorld.exe. Just do:

    > ngen HelloWorld.exe

    Now go to the global assembly cache

    > cd C:\Windows\assembly\NativeImages_v2.0.50727_32\HelloWorld\355240658e5a51e36767993bef4ed510

    , find, and copy it to some temporary folder.

    Now do:

    > ngen uninstall HelloWorld

    I know this might not make sense to you, but just bear with me.

    Now, take Olly, and open the original HelloWorld.exe (the one which we execute ngen upon). Find the IL code in the hex view
    window (IL code is easy to recognize from a hex editor once you get used to looking at it; if you're having trouble finding
    it in the exe gets its RVA with CFF Explorer orjust search for 2A (2A is the bytecode for the IL_Ret instruction)). Here is
    how the beginning of the IL code looks for me from Olly:

    00E221C0  13 30 02 00 3B 00 00 00  0.;...
    00E221C8  1B 00 00 11 00 7E 0D 00  ...~..
    00E221D0  00 04 14 28 58 00 00 0A  .(X...
    00E221D8  0C 08 2C 20 72 0B 01 00  ., r.
    00E221E0  70 D0 09 00 00 02 28 25  pĐ...(%
    00E221E8  00 00 0A 6F 59 00 00 0A  ...oY...
    00E221F0  73 5A 00 00 0A 0B 07 80  sZ...€
    00E221F8  0D 00 00 04 00 7E 0D 00  ....~..
    00E22200  00 04 0A 2B 00 06 2A 00  ..+.*.

    end of IL code:

    (scroll down)

    00E22A10  00 00 04 02 7B 0C 00 00  ..{...
    00E22A18  04 14 FE 01 16 FE 01 0B  ţţ
    00E22A20  07 2C 0D 02
Page 2 of 5 FirstFirst 12345 LastLast