flat assembler
Message board for the users of flat assembler.

Index > Windows > GetThreadContext API - Weird things ...

Author
Thread Post new topic Reply to topic
smoke



Joined: 16 Jan 2006
Posts: 42
smoke 13 Nov 2006, 21:15
Okay , im figuring this out for like 2 weeks now and i cant make it working ...when i get context from a process i just dont get the right things (or maybe i do but they're kinda too weird to be true ... like if i try to get the EIP register i get some weird location in kernel32.dll ...)
so i was hoping if you can tell me what im doing wrong (as you can see im writing a generic unpacker for UPX Razz)
Here's the code:
Code:
format PE Console 4.0
entry start

include 'win32a.inc'

struc CONTEXT
{ 
.xcontextflags          dd      -1
.xdr0                   dd      ?
.xdr1                   dd      ?
.xdr2                   dd      ?
.xdr3                   dd      ?
.xdr6                   dd      ?
.xdr7                   dd      ?
.xfpu_controlword       dd      ?
.xcpu_statusword        dd      ?
.xfpu_tagword           dd      ?
.xfpu_erroroffset       dd      ?
.xfpu_errorselector     dd      ?
.xfpu_dataoffset        dd      ?
.xfpu_dataselector      dd      ?
.xfpu_registerarea      rb      80
.xfpu_cr0npxstate       dd      ?
.xgs                    dd      ?
.xfs                    dd      ?
.xes                    dd      ?
.xds                    dd      ?
.xedi                   dd      ?
.xesi                   dd      ?
.xebx                   dd      ?
.xedx                   dd      ?
.xecx                   dd      ?
.xeax                   dd      ?
.xebp                   dd      ?
.xeip                   dd      ?
.xcs                    dd      ?
.xeflags                dd      ?
.xesp                   dd      ?
.xss                    dd      ?

}

section '.text' readable executable

  start:

        invoke    printf,_format,_title

        call      Initialize

        invoke    printf,_format,_select

        invoke    GetOpenFileName,ofn
        cmp       al,0
        je        nofile

        invoke    CreateProcess,ofnBuffer,NULL,NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS + CREATE_SUSPENDED,\
                  NULL,NULL,startupinfo,processinfo

        test      eax,eax
        je        _failed

 ;      mov       [mycontext],100087
        mov       [mycontext.xcontextflags], 00010000h+1+2+4+8+10h


        invoke    GetThreadContext,[processinfo.hThread],mycontext

        mov       eax,[mycontext.xeip]

   exit:
        invoke    ExitProcess,0DEADh
        retn

 nofile:
        invoke    printf,_format,_nofile

        invoke    printf,_format,_line

        invoke    Sleep,2500
        jmp       exit

_failed:
        invoke    printf,_format,_pfailed

        invoke    printf,_format,_line

        invoke    Sleep,2500
        jmp       exit

Initialize:

        mov       [ofn.lStructSize],sizeof.OPENFILENAME
        mov       [ofn.lpstrFilter],ofnTxtFilter
        mov       [ofn.lpstrFile],ofnBuffer
        mov       [ofn.nMaxFile],512
        mov       [ofn.Flags],OFN_FILEMUSTEXIST + OFN_PATHMUSTEXIST + OFN_LONGNAMES +\
                  OFN_EXPLORER + OFN_HIDEREADONLY
        retn

section '.data' readable writable


ofn               OPENFILENAME
startupinfo       STARTUPINFO
processinfo       PROCESS_INFORMATION

mycontext      CONTEXT
;mycontext         CONTEXT

ofnBuffer         rb     128h
ofnTxtFilter      db     'UPX Packed Executable Files',0,'*.exe',0,0

_title            db     "[smoke'z generic UPX unpacker]",13,10
_shit             db     "-",13,10,0
_select           db     "[]--[Openfile initialized and executed!]",13,10,0
_nofile           db     "[]--[No file selected!]",13,10,0
_line             db     "-",13,10
_exiting          db     "[]--[Exiting now...]",13,10,0
_pfailed          db     "[]--[Failed to create process]",13,10,0
_format           db     "%s",0
_format1          db     "%d",0                              

section '.idata' import data readable writable



  library kernel32,                 'kernel32.DLL',\
          crtdll,                   'crtdll.DLL',\
          comdlg32,                 'comdlg32.dll'

  import  kernel32,\
          GetModuleHandle,          'GetModuleHandleA',\
          CreateProcess,            'CreateProcessA',\
          OpenProcess,              'OpenProcess',\
          GetThreadContext,         'GetThreadContext',\
          CloseHandle,              'CloseHandle',\
          ReadProcessMemory,        'ReadProcessMemory',\
          Sleep,                    'Sleep',\
          ExitProcess,              'ExitProcess'

  import  crtdll,\
          printf,                   'printf'

  import comdlg32,\
          GetOpenFileName,          'GetOpenFileNameA'  

    
Post 13 Nov 2006, 21:15
View user's profile Send private message Reply with quote
okasvi



Joined: 18 Aug 2005
Posts: 382
Location: Finland
okasvi 14 Nov 2006, 01:02
I changed your code to bit more to my liking to see if I can make it work, and here's working version:

Code:
format PE GUI

struc OPENFILENAME
{
        .lStructSize            rd 1
        .hwndOwner              rd 1
        .hInstance              rd 1
        .lpstrFilter            rd 1
        .lpstrCustomFilter      rd 1
        .nMaxCustFilter         rd 1
        .nFilterIndex           rd 1
        .lpstrFile              rd 1
        .nMaxFile               rd 1
        .lpstrFileTitle         rd 1
        .nMaxFileTitle          rd 1
        .lpstrInitialDir        rd 1
        .lpstrTitle             rd 1
        .Flags                  rd 1
        .nFileOffset            rw 1
        .nFileExtension         rw 1
        .lpstrDefExt            rd 1
        .lCustData              rd 1
        .lpfnHook               rd 1
        .lpTemplateName         rd 1
}

struc STARTUPINFO
{
  .cb                   rd 1
  .lpReserved           rd 1
  .lpDesktop            rd 1
  .lpTitle              rd 1
  .dwX                  rd 1
  .dwY                  rd 1
  .dwXSize              rd 1
  .dwYSize              rd 1
  .dwXCountChars        rd 1
  .dwYCountChars        rd 1
  .dwFillAttribute      rd 1
  .dwFlags              rd 1
  .wShowWindow          rw 1
  .cbReserved2          rw 1
  .lpReserved2          rd 1
  .hStdInput            rd 1
  .hStdOutput           rd 1
  .hStdError            rd 1
}

struc PROCESS_INFORMATION
{
  .hProcess     rd      1
  .hThread      rd      1
  .dwProcessId  rd      1
  .dwThreadId   rd      1
}

CONTEXT_X86         = 0x00010000
CONTEXT86_CONTROL   = (CONTEXT_X86 or 0x0001) ;/* SS:SP, CS:IP, FLAGS, BP */
CONTEXT86_INTEGER   = (CONTEXT_X86 or 0x0002) ;/* AX, BX, CX, DX, SI, DI */
CONTEXT86_SEGMENTS  = (CONTEXT_X86 or 0x0004) ;/* DS, ES, FS, GS */
CONTEXT86_FULL      = (CONTEXT86_CONTROL or CONTEXT86_INTEGER or CONTEXT86_SEGMENTS)
CONTEXT_FULL        = CONTEXT86_FULL

SIZE_OF_80387_REGISTERS equ 80

struc FLOATING_SAVE_AREA
{
    .ControlWord        rd      1
    .StatusWord         rd      1
    .TagWord            rd      1
    .ErrorOffset        rd      1
    .ErrorSelector      rd      1
    .DataOffset         rd      1
    .DataSelector       rd      1
    .RegisterArea       rb      SIZE_OF_80387_REGISTERS
    .Cr0NpxState        rd      1
}

MAXIMUM_SUPPORTED_EXTENSION equ 512

struc CONTEXT
{
    .ContextFlags       dd -1

    .Dr0        rd      1                                       
    .Dr1        rd      1
    .Dr2        rd      1
    .Dr3        rd      1
    .Dr6        rd      1
    .Dr7        rd      1

    .FloatSave.ControlWord        rd      1
    .FloatSave.StatusWord         rd      1
    .FloatSave.TagWord            rd      1
    .FloatSave.ErrorOffset        rd      1
    .FloatSave.ErrorSelector      rd      1
    .FloatSave.DataOffset         rd      1
    .FloatSave.DataSelector       rd      1
    .FloatSave.RegisterArea       rb      80 ;SIZE_OF_80387_REGISTERS
    .FloatSave.Cr0NpxState        rd      1

    .SegGs      rd      1
    .SegFs      rd      1
    .SegEs      rd      1
    .SegDs      rd      1

    .Edi        rd      1
    .Esi        rd      1
    .Ebx        rd      1
    .Edx        rd      1
    .Ecx        rd      1
    .Eax        rd      1

    .Ebp        rd      1
    .Eip        rd      1
    .SegCs      rd      1
    .EFlags     rd      1
    .Esp        rd      1
    .SegSs      rd      1

    .ExtendedRegisters  rb      MAXIMUM_SUPPORTED_EXTENSION
}
section '.text' readable executable
entry $

                mov     [ofn.lStructSize], OPENFILENAME_SIZE
                mov     [ofn.lpstrFilter], ofnTxtFilter
                mov     [ofn.lpstrFile], ofnBuffer
                mov     [ofn.nMaxFile], 512
                mov     [ofn.Flags], 2627588

                push    ofn
                call    [GetOpenFileName]
                test    eax, eax
                jz      err

                push    pinfo
                push    sinfo
                push    0 0
                push    0 ; 4=CREATE_SUSPENDED, NORMAL_PRIORITY_CLASS is set by default, so null param works here
                push    0 0 0 0
                push    ofnBuffer
                call    [CreateProcess]
                test    eax, eax
                jz      err


                push    5000
                call    [Sleep]

                push    [pinfo.hThread]
                call    [SuspendThread]
                cmp     eax, -1
                jz      err

                mov     [context.ContextFlags], 00010000h+1+2+4+8+10h  ;CONTEXT_FULL

                push    context
                push    [pinfo.hThread]
                call    [GetThreadContext]

                mov     eax, [context.Eip]
                push    eax
                push    _format1
                push    buf
                call    [wsprintf]

                push    0
                push    _title
                push    buf
                push    0
                call    [MessageBox]

                jmp     exit
err:
                push    0
                push    _title
                push    _err
                push    0
                call    [MessageBox]
exit:
                push    0
                call    [ExitProcess]
                retn

section '.data' readable writable
context         CONTEXT

ofnTxtFilter    db 'UPX Packed Executable Files',0,'*.exe',0,0
_title          db 'bleh',0
_format         db '%s',0
_format1        db '%x',0
_err            db 'Error, Failed.',0
buf             rb      512
ofn             OPENFILENAME
OPENFILENAME_SIZE = $ - ofn
pinfo           PROCESS_INFORMATION
sinfo           STARTUPINFO
ofnBuffer         rb     1024



section '.idata' readable writable
;____________________________________________________________________
        ;IAT
        ;____________________________________________________________
        krnl32:
                CreateProcess           dd      RVA _CreateProcess
                ExitProcess             dd      RVA _ExitProcess
                GetThreadContext        dd      RVA _GetThreadContext
                Sleep                   dd      RVA _Sleep
                SuspendThread           dd      RVA _SuspendThread
                                        dw      0
                _CreateProcess          db      0,0,'CreateProcessA',0
        _krnl32                         db      'kernel32'
                _ExitProcess            db      0,0,'ExitProcess'
                _GetThreadContext       db      0,0,'GetThreadContext'
                _Sleep                  db      0,0,'Sleep'
                _SuspendThread          db      0,0,'SuspendThread',0
        ;____________________________________________________________
        user32:
                MessageBox      dd      RVA _MessageBox
                wsprintf        dd      RVA _wsprintf
                                dw      0
                _MessageBox     db      0,0,'MessageBoxA',0
        _user32                 db      'user32'
                _wsprintf       db      0,0,'wsprintfA',0
        ;____________________________________________________________
        comd32:
                GetOpenFileName         dd      RVA _GetOpenFileName
                                        dw      0
                _GetOpenFileName        db      0,0,'GetOpenFileNameA',0
        _comd32                         db      'comdlg32'
        ;____________________________________________________________
data import
        dd      0,0,0, RVA _krnl32, RVA krnl32
        dd      0,0,0, RVA _user32, RVA user32
        dd      0,0,0, RVA _comd32, RVA comd32
        dd      0,0,0,0,0
end data
;____________________________________________________________________    


and here is what I tested it with:
Code:
include 'win32ax.inc'
start:
lool:
mov     eax, 1
mov     ebx, 2
mov     esi, 2
mov     edi, 3
jmp     lool
push    0
call    [ExitProcess]
.end start    



btw. incase you use CREATE_SUSPEND and get the thread context, eip will most likely be within kernel32.dll because the app hasnt initialized completely yet Wink hence I added sleep for few secs and suspended it after that...

_________________
When We Ride On Our Enemies
support reverse smileys |:
Post 14 Nov 2006, 01:02
View user's profile Send private message MSN Messenger Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 14 Nov 2006, 01:42
And if the program is not CPU intensive is very probable that EIP points to some blocking code (Sleep, GetMessage, synchronization functions, etc).
Post 14 Nov 2006, 01:42
View user's profile Send private message Reply with quote
smoke



Joined: 16 Jan 2006
Posts: 42
smoke 14 Nov 2006, 13:53
hmm thanks guys but .. okasvi , the problem is that i need to get the EP of the file so i can do byte scann after that .. and if i use your code i cant find out the EP of the opened thread (because its already running) ..
Post 14 Nov 2006, 13:53
View user's profile Send private message Reply with quote
LocoDelAssembly
Your code has a bug


Joined: 06 May 2005
Posts: 4624
Location: Argentina
LocoDelAssembly 14 Nov 2006, 14:51
Have you already tried http://msdn2.microsoft.com/en-us/library/ms679358.aspx ? and then loking at LOADED_IMAGE > IMAGE_NT_HEADERS > IMAGE_OPTIONAL_HEADER > AddressOfEntryPoint ?

Note that maybe is easier to access the EXE by your self instead of all this mess. Decide by yourself which solution is better.

Regards
Post 14 Nov 2006, 14:51
View user's profile Send private message Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 14 Nov 2006, 14:55
There's basically two things you can do. Both of them involves reading the PE header and getting the entrypoint.

The first method then is to run the process in debug mode, insert a 0xCC at entrypoint, and catching the debug message.

The other involves overwriting some more bytes at EIP with some inter-process communication code, and thus removing the need for running that app in debug mode.
Post 14 Nov 2006, 14:55
View user's profile Send private message Visit poster's website Reply with quote
smoke



Joined: 16 Jan 2006
Posts: 42
smoke 14 Nov 2006, 16:25
f0dder, well i need to findout the EP first .. and then i'll be able to do something .. so what guys do you suggest ? i thought there's some other option (like getting it with some apis or something) than reading it from a file (reading it from a file is kinda weird)
Post 14 Nov 2006, 16:25
View user's profile Send private message Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 14 Nov 2006, 23:26
smoke wrote:
f0dder, well i need to findout the EP first .. and then i'll be able to do something .. so what guys do you suggest ? i thought there's some other option (like getting it with some apis or something) than reading it from a file (reading it from a file is kinda weird)


I was referring to the (decompressor code) EP as set in the PE header - which is where you want to trace from, instead of the SUSPENDED entry in kernel32...

_________________
Image - carpe noctem
Post 14 Nov 2006, 23:26
View user's profile Send private message Visit poster's website Reply with quote
smoke



Joined: 16 Jan 2006
Posts: 42
smoke 16 Nov 2006, 13:34
okay i got the code which retrieves the entry point for me Smile
this is how i did it:
Code:
        invoke    CreateFile,ofnBuffer,GENERIC_READ,NULL,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL
        cmp       eax,INVALID_HANDLE_VALUE
        je        OpenErr
        mov       [hTarget],eax
        invoke    CreateFileMapping,eax,NULL,PAGE_READONLY,NULL,NULL,NULL
        mov       [hMapping],eax
        invoke    MapViewOfFile,eax,FILE_MAP_READ,NULL,NULL,NULL
        mov       [pMapping],eax
        add       ax, word [eax+3Ch]
        mov       [PELoc],eax
        mov       ebx, dword [eax+28h]
        mov       eax,[PELoc]
        add       ebx, dword [eax+34h]
        mov       eax,ebx

        invoke    wsprintf,entrypoint,_format2,eax
        invoke    printf,_format,EPMSG
    


and now when i have this i was thinking of running the file in suspended mode and then writing EB FE to the entrypoint Razz
Post 16 Nov 2006, 13:34
View user's profile Send private message Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 16 Nov 2006, 15:17
You can also have a look at how I do it in my XCOM patch loaders - it's a bit tricky, but pretty flexible Smile - http://f0dder.reteam.org/dl/xcom_bugfix091.zip
Post 16 Nov 2006, 15:17
View user's profile Send private message Visit poster's website Reply with quote
smoke



Joined: 16 Jan 2006
Posts: 42
smoke 16 Nov 2006, 21:47
yes , finaly i got it working like it should! Smile
here's the whole (almost hehe) code :
Code:
        invoke    CreateFile,ofnBuffer,GENERIC_READ,NULL,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL
        cmp       eax,INVALID_HANDLE_VALUE
        je        OpenErr
        mov       [hTarget],eax
        invoke    CreateFileMapping,eax,NULL,PAGE_READONLY,NULL,NULL,NULL
        mov       [hMapping],eax
        invoke    MapViewOfFile,eax,FILE_MAP_READ,NULL,NULL,NULL
        mov       [pMapping],eax
        add       ax, word [eax+3Ch]
        mov       [PELoc],eax
        mov       ebx, dword [eax+28h]
        mov       eax,[PELoc]
        add       ebx, dword [eax+34h]
        mov       eax,ebx

        mov       dword [entrypoint2],eax

        invoke    wsprintf,entrypoint,_format2,eax
        mov       [entrypoint+6], 0Dh
        invoke    printf,_format,EPMSG

     ;   mov       ebx,eax

; --------------------------------------------------------
        invoke    CloseHandle,dword[hTarget]


        invoke    CreateProcess,ofnBuffer,NULL,NULL,NULL,FALSE,NORMAL_PRIORITY_CLASS + CREATE_SUSPENDED,\
                  NULL,NULL,startupinfo,processinfo

        test      eax,eax
        je        _failed

        mov       eax,dword [entrypoint2]

        invoke    ReadProcessMemory,[processinfo.hProcess],eax,backupdata,breaksize,NULL

        mov       eax,dword [entrypoint2]
        invoke    WriteProcessMemory,[processinfo.hProcess],eax,breakpoint,breaksize,NULL

        invoke    ResumeThread,[processinfo.hThread]
        invoke    Sleep,250
        invoke    SuspendThread,[processinfo.hThread]


        mov       [mycontext.xcontextflags], 00010000h+1+2+4+8+10h
        invoke    GetThreadContext,[processinfo.hThread],mycontext

        mov       eax,[mycontext.xeip]
        mov       ebx,dword [entrypoint2]
        cmp       eax, ebx
        je        _success
    
Post 16 Nov 2006, 21:47
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.