flat assembler
Message board for the users of flat assembler.

Index > Projects and Ideas > hash importer

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
hidden



Joined: 14 Feb 2007
Posts: 49
hidden 02 Mar 2007, 20:18
I wasn't sure? where to post it, to the "windows" or to the "macros", because it relative to both, so I post it to the "Projects and Ideas" Smile

It's a procedure, that find functions in the modules by hashes of the names, and generates jmp table with relative jumps to the imported functions.

I could be used in windows applications, dll modules, kernel-mode modules and another PE export compatible files as well.

It's absolutely relative, no need reloc section for drivers and dll's, also it saves memory in big import tables.

Code:
format PE GUI 4.0
entry start

include 'win32w.inc'

AntiDebug equ ; It's more difficult to debug, then jumps goes not to the begin of the function. But any way OllyDbg doesn't show it as usual.

macro rol32 op1, op2
 { match =dword v, op1 \{ v = ((v shl op2) or (v shr (32 - op2))) and $FFFFFFFF \}
   match =word v,  op1 \{ v = ((v shl op2) or (v shr (32 - op2))) and $FFFFFFFF \}
   match =byte v,  op1 \{ v = ((v shl op2) or (v shr (32 - op2))) and $FFFFFFFF \} }

macro iprc [proc, name]
 { forward
    if used proc | impanyway eq
     if name eqtype ''
      local ch
      local hash
      local length
      virtual at 0
       db name
       length = $
       hash = 0
       repeat length
        load ch byte from length-%
        rol32 dword hash, 5
        hash = hash xor (ch and 11111b)
       end repeat
      end virtual
      label proc dword
      db length ; Length, if $ff then load lib, if $fe then end, if $fd then by id
      dd hash
     else
      db $fd
      dd name+1
     end if
    end if }

macro iprcex [proc]
 { forward
    if used proc | proc eq LoadLibraryA | impanyway eq
      local ch
      local hash
      local length
      virtual at 0
       db `proc#''
       length = $
       hash = 0
       repeat length
        load ch byte from length-%
        hash = ((hash shl 5) or (hash shr (32 - 5))) and $FFFFFFFF ; hash = hash rol 5
        hash = hash xor (ch and 11111b)
       end repeat
      end virtual
      virtual at $
       proc dd ?
      end virtual
      db length ; Length, if $ff then load lib, if $fe then end, if $fd then by id
      dd hash
    end if }

macro hip [proc, len, hash]
 { forward
    if used proc | proc eq LoadLibraryA | impanyway eq
     proc db len
          dd hash
    end if }

macro imod [module, str]
 { forward
    db $fe
    module dd module#.str - $
    module#.text equ str }

macro istr [module]
 { forward
    module#.str db module#.text, 0 }

macro endi ierrproc
 { db $ff }

struct IED
 Characteristics        dd ? ;This field appears to be unused and is always set to 0.
 TimeDateStamp          dd ? ;The time/date stamp indicating when this file was created.
 Version                dd ? ;These fields appear to be unused and are set to 0.
 Name                   dd ? ;The RVA of an ASCIIZ string with the name of this DLL.
 Base                   dd ? ;The starting ordinal number for exported functions. For example, if the file exports functions with ordinal values of 10, 11, and 12, this field contains 10. To obtain the exported ordinal for a function, you need to add this value to the appropriate element of the AddressOfNameOrdinals array.
 NumberOfFunctions      dd ? ;The number of elements in the AddressOfFunctions array. This value is also the number of functions exported by this module. Theoretically, this value could be different than the NumberOfNames field (next), but actually they're always the same.
 NumberOfNames          dd ? ;The number of elements in the AddressOfNames array. This value seems always to be identical to the NumberOfFunctions field, and so is the number of exported functions.
 AddressOfFunctions     dd ? ;This field is an RVA and points to an array of function addresses. The function addresses are the entry points (RVAs) for each exported function in this module.
 AddressOfNames         dd ? ;This field is an RVA and points to an array of string pointers. The strings are the names of the exported functions in this module.
 AddressOfNameOrdinals  dd ? ;This field is an RVA and points to an array of WORDs. The WORDs are the export ordinals of all the exported functions in this module. However, don't forget to add in the starting ordinal number specified in the Base field.
ends

; ZF - Error, ax - Error code

AX_WRONG_MODULE_HANDLE  equ 'MZ'
AX_WRONG_PE_SECTION     equ 'PE'
AX_WRONG_EXPORT_SECTION equ 'WE'
AX_NO_EXPORT_SECTION    equ 'NE'
AX_FUNCTION_NOT_FOUND   equ 'NF'

MAX_MOD_MODULE_NAME_LEN = 260

proc ProcIdByHash, base, hash, len
        ;local   img_size dd ?
        local   exp_addr dd ?
        local   exp_end dd ?
        xchg    edi, [base]
        push    ebx ecx edx esi

        mov     ax, 'MZ'
        cmp     [edi], ax
        jnz     .default_error

        mov     edx, [edi+$3C] ; OffSet to PE Header

        mov     ax, 'PE'
        cmp     [edi+edx], ax
        jnz     .default_error

        ;mov     eax, [edi+edx+$50] ; Image size
        ;mov     [img_size], eax

        mov     ebx, [edi+edx+$78] ; Offset to Export section
        mov     eax, [edi+edx+$7C] ; Size of Export section
        add     eax, ebx

        cmp     al, sizeof.IED ; Is export table presents
        jb      .noexport
        test    ebx, ebx ; Is export table presents
        jz      .noexport
        cmp     eax, [edi+edx+$50] ; Is end of export table in image
        ja      .err_wrong_export
        cmp     ebx, [edi+edx+$50] ; Is export table in image
        ja      .err_wrong_export

        mov     [exp_end], eax
        mov     [exp_addr], ebx

        mov     ecx, [edi+ebx+IED.NumberOfNames]
        mov     ebx, [edi+ebx+IED.AddressOfNames]

        test    ecx, ecx ; Any name
        jz      .noexport
        test    ebx, ebx
        jz      .noexport
        cmp     ebx, [exp_end]
        ja      .err_wrong_export
        lea     eax, [ebx+ecx*4]
        cmp     eax, [exp_end] ; Is last name in export table
        ja      .err_wrong_export

        lea     ebx, [edi+ebx-4]

  .next_export_item:
        mov     esi, [ebx+ecx*4]
        cmp     esi, [exp_end]
        ja      .err_wrong_export

        movsx   eax, byte[len]
        add     eax, esi
        cmp     eax, [exp_end]
        ja      .wrng_length
        cmp     byte[eax+edi], 0
        jne     .wrng_length

        add     esi, edi
        mov     edx, [hash]

  @@:   lodsb
        test    al, al
        jz      @f
        and     al, 11111b
        xor     dl, al ; Hashing
        ror     edx, 5
        jmp     @b

  @@:   test    edx, edx
        jz      .hash_found

  .wrng_length:
        loop    .next_export_item

        mov     ax, 'NF'
        jmp     .default_error

  .hash_found:
        mov     ebx, [exp_addr]
        lea     eax, [ebx+IED.AddressOfNameOrdinals]
        cmp     eax, [exp_end]
        ja      .err_wrong_export
        mov     eax, [edi+eax]
        cmp     eax, [exp_end]
        ja      .err_wrong_export
        lea     eax, [eax+ecx*2-2]
        cmp     eax, [exp_end]
        ja      .err_wrong_export
        movzx   eax, word[eax+edi]
        ;add     eax, edi
        ;movzx   eax, word[eax+ecx*2-2]
        add     eax, [edi+ebx+IED.Base]

        test    eax, eax

  .end: pop     esi edx ecx ebx
        mov     edi, [base]
        ret

  .err_wrong_export:
        mov     ax, 'WE'

  .default_error:
        xor     ebx, ebx
        jmp     .end

  .noexport:
        mov     ax, 'NE'
        jmp     .default_error
endp

proc ProcAddrById, base, id
        local   exp_end dd ?
        xchg    edi, [base]
        push    ebx edx ecx esi

        mov     ecx, [edi+$3C] ; OffSet to PE Header

        mov     ebx, [edi+ecx+$78] ; Offset to Export section
        mov     eax, [edi+ecx+$7C]
        cmp     ebx, [edi+ecx+$50]
        ja      .err_wrong_export
        add     eax, ebx
        mov     [exp_end], eax
        mov     esi, [edi+ebx+IED.AddressOfFunctions]
        mov     eax, [id]
        sub     eax, [edi+ebx+IED.Base]

        lea     eax, [esi+eax*4]
        cmp     eax, [exp_end]
        ja      .err_wrong_export

        mov     esi, [edi+eax] ; RVA of function
        lea     eax, [esi+edi]

        cmp     esi, [edi+$50] ; Is this proc in image
        ja      .err_wrong_export

        cmp     esi, ebx
        jb      .proc_found
        cmp     esi, [exp_end]
        ja      .proc_found

  ; If you don't need Forwarded Export Support you can comment next block
        stdcall GetForwardedProcId, eax
        stdcall ProcAddrById, edi, eax
        jmp     .end
  ; End of block

  .err_wrong_export:
        xor     ebx, ebx
        mov     ax, 'WE'
        jmp     .end

  .proc_found:
        test    eax, eax

  .end:
        pop     esi ecx edx ebx
        mov     edi, [base]
        ret
endp

proc GetForwardedProcId, str
        mov     esi, [str]

        mov     ecx, MAX_MOD_MODULE_NAME_LEN
        sub     esp, ecx

        mov     edx, esp

        mov     ebx, esi
  .next_simbol:
        lodsb

        cmp     al, '.'
        jne     @f
        mov     ebx, esi
@@:
        mov     [edx], al
        inc     edx

        or      al, al
        jz      @f

        loop    .next_simbol
@@:
        cmp     ebx, [str]
        jz      .GetProc

        lea     eax, [esp+ebx]
        sub     eax, [str]
        mov     byte[eax-1], 0
        stdcall LoadLibraryA, esp
        mov     edi, eax

.GetProc:
        add     esp, MAX_MOD_MODULE_NAME_LEN

        mov     esi, ebx
        neg     ebx

        xor     edx, edx

@@:     lodsb
        or      al, al
        jz      @f
        and     al, 11111b
        xor     dl, al
        ror     edx, 5
        jmp     @b
@@:
        lea     ebx, [ebx+esi-1]

        lea     ecx, [ebx*5]
        rol     edx, cl

        stdcall ProcIdByHash, edi, edx, ebx

        ret
endp

proc GetKernel
        xor     eax, eax
        mov     eax, [fs:eax+30h]
        test    eax, eax
        js      ngk
        mov     eax, [eax+0Ch]
        mov     esi, [eax+1Ch]
        lodsd
        mov     eax, [eax+8]
        jmp     egk
ngk:    mov     eax, [eax+34h]
        add     eax, 7Ch
        mov     eax, [eax+3Ch]
egk:    ret
endp

proc BaseByAddr, addr
        mov     eax, [addr]

        xor     ax, ax
  @@:   cmp     word[eax], 'MZ'
        jz      @f
        sub     eax, $10000
        jmp     @b
  @@:   ret
endp

proc importer, kernel, imports, loadlib, errproc
        xchg    esi, [imports]
        xchg    edi, [kernel]

  .loop:lodsb
        cmp     al, $fd
        ja      .more
        je      .byid
        mov     ah, al

        or      edi, edi
        jz      .xxx

        stdcall ProcIdByHash, edi, [esi], [esi-1]
        jnz     @f
        cmp     ax, 'NF'
        jnz     .endi
        mov     eax, [errproc]
        test    eax, eax
        jnz     .stor
        mov     ax, 'NF'
        jmp     .endi
  @@:
  .gbi: stdcall ProcAddrById, edi, eax
        jnz     @f
        mov     eax, [errproc]
        test    eax, eax
        mov     ax, 'WE'
        jnz     @f
        jmp     .endi
  @@:

  .stor:if      AntiDebug eq
         cmp     word[eax], $FF8B
         jnz     @f
         add     eax, 2
  @@:   end     if
         sub     eax, 4

  @@:   sub     eax, esi
        mov     byte[esi-1], $E9
        mov     dword[esi], eax
  .xxx: lodsd
        jmp     .loop

  .byid:mov     eax, [esi]
        jmp     .gbi

  .more:cmp     al, $fe
        ja      .endi
        lodsd

        lea     eax, [eax+esi-4]
        invoke  loadlib, eax
        mov     edi, eax
        mov     [esi-4], eax

        jmp     .loop

  .endi:mov     edi, [kernel]
        mov     esi, [imports]
        ret
endp

proc ImportErrProc
        stdcall MessageBoxA, 0, wfmsg, wferr, MB_ICONERROR
        ret
endp

myi:
  iprc LoadLibraryA, 'LoadLibraryA',\
    AddVectoredExceptionHandler,'AddVectoredExceptionHandler',\
    ExitProcess,'ExitProcess'
  imod user, 'user32'
  iprcex MessageBoxA,\ ; iprcex if a simbol equal to the name
    WrongFunc
  endi

 xxx = AddVectoredExceptionHandler

start:
        stdcall BaseByAddr, [esp]
        ;stdcall GetKernel
        stdcall importer, eax, myi, LoadLibraryA, ImportErrProc
        jz      Error
        stdcall WrongFunc ; Example of wrong function

        stdcall MessageBoxA, 0, txt, txt, 0

exit:   stdcall ExitProcess, 0
        ret

Error:  mov     word[wferr], ax
        stdcall MessageBoxA, 0, wferr, wferr, 0
        jmp     exit

txt             db "It works",0
wferr           db '   Error',0
wfmsg           db "You'r trying to call wrong function, if it has any arguments then process needs to be restarted.",0
        istr    user    


I thick somebody may find it useful Smile

And some more, macro emulation of rol, rol sometimes very useful

[+] Support forwarding functions. (If anything wrong with it please let me know)
[+] If something wrong with module or export tables and errproc = 0 it return error codes, otherwise it call errproc instead of undefined function.

Remark:
1) LoadLibraryA should be imported or declared before using "imod" or Forwarding functions, better if it is first this to do.
2) Import table should be in writable executable section, but "istr" can be in read only section.

Updates:
Added passing needed functions by arguments of importer.


Description: The same code, that listed.
Download
Filename: 111.ASM
Filesize: 9.63 KB
Downloaded: 882 Time(s)


_________________
Image Lang: (eng|рус)


Last edited by hidden on 08 Mar 2007, 20:31; edited 6 times in total
Post 02 Mar 2007, 20:18
View user's profile Send private message Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 04 Mar 2007, 12:24
Have you done extensive collision testing of this?
Post 04 Mar 2007, 12:24
View user's profile Send private message Visit poster's website Reply with quote
hidden



Joined: 14 Feb 2007
Posts: 49
hidden 04 Mar 2007, 19:22
Quote:
Have you done extensive collision testing of this?

Heshes isn't case sensitive, it uses only first 5 bits of the symbol nomber, and understend 0 as p, 1 as q, 2 as r and so on.
Hashes will be 100% different if name not longer then 6 ascii simbols, it is theoretically, but practically I didn't find any api function with same hash, but to be sure I added also length of the name.

It works just fine for me.
Post 04 Mar 2007, 19:22
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 04 Mar 2007, 19:33
hidden: that means it doesn't work good enough. You must somehow ensure case when two functions have same hash.

By the way, it is pretty possible to have first 6 chars of 2 different functions same, because many names are prefixed with abbreviation of brand the provide, sometimes just the has abbreviation has 6 chars Smile


Last edited by vid on 04 Mar 2007, 19:37; edited 1 time in total
Post 04 Mar 2007, 19:33
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
okasvi



Joined: 18 Aug 2005
Posts: 382
Location: Finland
okasvi 04 Mar 2007, 19:34
Nice macros&procedures Smile


edit:
Quote:
By the way, it is pretty possible to have first 6 chars of 2 different functions same, because all names are prefixed with abbreviation of brand the provide, sometimes just the has abbreviation has 6 chars


crc32 should be enough.
Post 04 Mar 2007, 19:34
View user's profile Send private message MSN Messenger Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 04 Mar 2007, 19:39
okasvi: still it's not really the best way to leave door open for bugs that may appear long time ago
Post 04 Mar 2007, 19:39
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 04 Mar 2007, 19:44
You should at least check the hashing scheme on all exports of all DLLs in %windir%\system32 - any collision == use another hash algo.
Post 04 Mar 2007, 19:44
View user's profile Send private message Visit poster's website Reply with quote
okasvi



Joined: 18 Aug 2005
Posts: 382
Location: Finland
okasvi 04 Mar 2007, 20:01
Btw. does this support forwarded exports? If it doesnt it should be noted in first post.
My personal getprocaddr with hashing doesnt, and I first ran into some problems while figuring why it doesnt work on some apis but since I'm the only user of it, it doesnt matter.
Post 04 Mar 2007, 20:01
View user's profile Send private message MSN Messenger Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 04 Mar 2007, 20:05
Not only do you need to support forwarded exports to be able to handle just about any real program running on NT, you also need to handle data exports if you want to support anything linked against dynamic MSVCRT.
Post 04 Mar 2007, 20:05
View user's profile Send private message Visit poster's website Reply with quote
hidden



Joined: 14 Feb 2007
Posts: 49
hidden 04 Mar 2007, 22:59
No, it doesn't support forwarded exports, I don't see an easy way to recognize, is it offset to the function or name to another exports and even if I recognize, I'll have to import that item, and this function would be 3 times bigger. Isn't it more easy to check that function forwarded or not, before using it?

It will make jumps to the data variables, so you will ether need to decompile jumps or use ProcIdByHash, ProcAddrById functions separately, to get adders to the variable.

Quote:
By the way, it is pretty possible to have first 6 chars of 2 different functions same, because many names are prefixed with abbreviation of brand the provide, sometimes just the has abbreviation has 6 chars Smile
chars that after char 6 will be XORed by previous chars.
CreateDialogIndirect & CreateDialogIndirectParam will have different hashes also it checks sizes.

Quote:
use another hash algo
I use this algo because it needs only dword/hash

Algo:
Code:
01100-01111-00001-00100-01100-01001-00 xor 010-10010-00001-10010-11001-00001-0000
  L     o     a     d     L     i       b        r     a     r     y     A
    


And then XOR this 2 dwords, it's hash of "LoadLibraryA"


Last edited by hidden on 04 Mar 2007, 23:04; edited 1 time in total
Post 04 Mar 2007, 22:59
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 04 Mar 2007, 23:02
You still missed the most important part:
Quote:
that means it doesn't work good enough. You must somehow ensure case when two functions have same hash.
Post 04 Mar 2007, 23:02
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 04 Mar 2007, 23:14
A data export can be recognized by checking if export RVA is inside a section with PE_SCN_CNT_INITIALIZED_DATA - at least that seems to work, I haven't checked how NT itself handles it.

And forwarded functions could change with a service pack, not to mention that some forwarded functions are useful. I detect a forward by checking if the export RVA lies within PE_DIRENT_EXPORT.rva and PE_DIRENT_EXPORT.size bytes forward - again, dunno how NT itself handles it.
Post 04 Mar 2007, 23:14
View user's profile Send private message Visit poster's website Reply with quote
hidden



Joined: 14 Feb 2007
Posts: 49
hidden 05 Mar 2007, 06:13
Here is some more macros&function - Exception handler, I didn't tested it enough, but it works.

Code:
macro SetHandler
{ push TryHandler
  push dword[fs:0]
  mov [fs:0], esp
  push __EXCEPT
  push ebp }

macro UnsetHandler
{ pop dword[fs:0]
  add esp, 4 }

macro try
{ __TRY equ
  local ..endt
  __ENDT equ ..endt
  local ..except
  __EXCEPT equ ..except
  SetHandler }

macro except
{ add esp, 8
  UnsetHandler
  jmp __ENDT
  __EXCEPT:
  UnsetHandler
  restore __TRY
  __TRY equ , }

macro endt
{ if __TRY eq
    add esp, 8
    __EXCEPT:
    UnsetHandler
  end if
  __ENDT:
  restore __EXCEPT
  restore __ENDT
  restore __TRY }

macro TryProc
{ proc TryHandler, ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext
    push esi edi ebx
    mov esi, [EstablisherFrame]
    mov edi, [ContextRecord]
    mov ebx, esi
    sub esi, 8
    add edi, $B4
    movsd ; ebp
    lodsd
    xchg [edi], eax
    ;movsd ; eip
    mov [edi+12], ebx ; esp
    mov [edi-8], eax ; esp

    pop ebx edi esi
    xor eax, eax
    ret
  endp }

if noinit eq
else
  TryProc
end if    

Quote:
You must somehow ensure case when two functions have same hash.

Quote:
You should at least check the hashing scheme on all exports of all DLLs in %windir%\system32 - any collision == use another hash algo.

And my try to check collisions:
Code:
format PE GUI 4.0
entry start

include 'win32a.inc'
include 'P:\fasm\asm\tests\utils.inc'

MAX_PATH = 260

struct WIN32_FIND_DATA
  dwFileAttributes      dd ?
  ftCreationTime        dq ?
  ftLastAccessTime      dq ?
  ftLastWriteTime       dq ?
  nFileSizeHigh         dd ?
  nFileSizeLow          dd ?
  dwReserved            dq ?
  cFileName             rb MAX_PATH
  cAlternateFileName    rb 14
ends

myi:
  iprcex LoadLibraryA, VirtualAlloc
  iprcex ExitProcess, LoadLibraryExA, FreeLibrary, FindFirstFileA, FindNextFileA
  imod user, 'user32'
  iprcex MessageBoxA
  endi
  istr user

  start:
        stdcall GetKernel
        stdcall importer, eax, myi

        stdcall VirtualAlloc, 0, $10000, MEM_COMMIT, PAGE_READWRITE
        mov     [buf], eax

        stdcall FindFirstFileA, mask, ffd
        mov     [hfind], eax
.loop:
  try
        mov     edi, [buf]
        stdcall LoadLibraryExA, ffd.cFileName, 0, LOAD_LIBRARY_AS_DATAFILE
        cmp     eax, 1
        jb      @f
        xor     si, si
        xchg    si, ax
        mov     ebp, eax

        call    HashAllNames ; base - ebp

        call    CompareHashes
@@:
  endt
        jz      Found

        stdcall FreeLibrary,  ebp

.next:  stdcall FindNextFileA, [hfind], ffd
        test    eax, eax
        jnz     .loop

        stdcall MessageBoxA, 0, sNothingFound, sNothingFound, 0

@@:     stdcall ExitProcess,-1

 Found:
        stdcall MessageBoxA, 0, sFoundCollision, sFoundCollision, 0
        jmp     @b

proc CompareHashes
        xor     edx, edx
@@:     inc     edx
        lea     edi, [edx*4]
        add     edi, [buf]
        mov     ecx, [count]
        sub     ecx, edx
        jecxz   @f
        mov     eax, [edi-4]
        repne   scasd
        jne     @b
        ret
@@:     cmp     cl, 1 ; unset ZF
        ret
endp

proc HashAllNames
        pushad

        cmp     word[ebp], 'MZ'
        jne     .wrong
        mov     eax, [ebp+$3C] ; OffSet to PE Header
        cmp     word[ebp+eax], 'PE'
        jne     .wrong
        mov     ebx, [ebp+eax+$78] ; Offset to Export section
        test    ebx, ebx
        jz      .wrong
        add     eax, ebp

        test    si, si
        jz      .running
        xor     edx, edx
@@:     mov     ecx, [eax+edx+$100] ; Virtual Size of the first section
        add     ecx, [eax+edx+$104] ; Virtual Address of the first section
        cmp     ebx, ecx
        jb      @f
        add     edx, $28
        jmp     @b
@@:     sub     ebp, [eax+edx+$104] ; Section offset in the file
        add     ebp, [eax+edx+$10C] ; Virtual Address of the first section
.running:

        mov     ecx, [ebp+ebx+IED.NumberOfNames]
        test    ecx, ecx
        jz      .wrong
        mov     ebx, [ebp+ebx+IED.AddressOfNames]
        test    ebx, ebx
        jz      .wrong
        add     ebx, ebp

        mov     [count], ecx

.loop:  mov     esi, [ebx]
        add     esi, ebp

        mov     edx, esi
        sub     edx, ebp
        and     edx, $7FFFFFFF
        cmp     edx, 10*1024*1024
        ja      .wrong

        xor     edx, edx
@@:     lodsb
        or      al, al
        jz      @f
        and     al, 11111b
        xor     dl, al
        ror     edx, 5
        jmp     @b
@@:
        mov     [edi], edx
        add     edi, 4

        add     ebx, 4
        dec     ecx
        jnz     .loop

.wrong:
        popad
        ret
endp

sFoundCollision db 'Collision has been found',0
sNothingFound   db 'Collision not found',0

mask            db 'C:\windows\system32\*.dll',0

count           dd ?
buf             dd ?
hfind           dd ?
ffd             WIN32_FIND_DATA    

Result: Collision not found
Post 05 Mar 2007, 06:13
View user's profile Send private message Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 05 Mar 2007, 13:59
Good Smile

_________________
Image - carpe noctem
Post 05 Mar 2007, 13:59
View user's profile Send private message Visit poster's website Reply with quote
hidden



Joined: 14 Feb 2007
Posts: 49
hidden 05 Mar 2007, 16:33
Quote:
how NT itself handles it.
I've reversed ntdll.LdrGetProcedureAddress and found out that forwarding functions can be done only to the ntdll, so if something forwarding somewhere, it forwarding to the ntdll.
If you put "Hardware Access Break Point" at the last "L" on the "NTDLL.RtlAddVectoredExceptionHandler" and try to call GetProcAddress(kernel, 'AddVectoredExceptionHandler'), you will stop at the algo that checks it.
Post 05 Mar 2007, 16:33
View user's profile Send private message Reply with quote
f0dder



Joined: 19 Feb 2004
Posts: 3175
Location: Denmark
f0dder 05 Mar 2007, 23:32
can be done only to NTDLL, or is only done to NTDLL? I haven't seen any other redirects, but it would be silly if there was an arbitrary restriction like that?
Post 05 Mar 2007, 23:32
View user's profile Send private message Visit poster's website Reply with quote
hidden



Joined: 14 Feb 2007
Posts: 49
hidden 06 Mar 2007, 00:49
Quote:
can be done only to NTDLL, or is only done to NTDLL?
Right, "is", I have read some MSDN, I will check what can I do with forwarding...

_________________
Image Lang: (eng|рус)
Post 06 Mar 2007, 00:49
View user's profile Send private message Reply with quote
hidden



Joined: 14 Feb 2007
Posts: 49
hidden 06 Mar 2007, 03:23
I added Support forwarding functions, it needs tests and it can be easily disabled by commenting little block. Smile

Also I converted "Collisions Checker" to API extractor Smile
Code:
format PE GUI 4.0
entry start

include 'win32a.inc'
include 'P:\fasm\asm\tests\utils.inc' ; - hash importer

FILE_WRITE_DATA = 2

myi:
  iprcex AddVectoredExceptionHandler, LoadLibraryA, VirtualAlloc
  iprcex ExitProcess, LoadLibraryExA, FreeLibrary, CreateFileA, WriteFile, CloseHandle
  imod _user, 'user32'
  iprcex MessageBoxA
  endi
  istr _user

kernel          db 'kernel32',0
kernel_txt      db 'kernel32.inc',0
user            db 'user32',0
user_txt        db 'user32.inc',0
gdi             db 'gdi32',0
gdi_txt         db 'gdi32.inc',0
shell           db 'shell32',0
shell_txt       db 'shell32.inc',0
shlwapi         db 'shlwapi',0
shlwapi_txt     db 'shlwapi.inc',0
advapi          db 'advapi32',0
advapi_txt      db 'advapi32.inc',0

  start:
        stdcall GetKernel
        stdcall importer, eax, myi

        stdcall VirtualAlloc, 0, $10000, MEM_COMMIT, PAGE_READWRITE
        mov     [buf], eax

        mov     esi, kernel
        mov     edi, kernel_txt
        call    GetModImports

        mov     esi, user
        mov     edi, user_txt
        call    GetModImports

        mov     esi, gdi
        mov     edi, gdi_txt
        call    GetModImports

        mov     esi, shell
        mov     edi, shell_txt
        call    GetModImports

        mov     esi, shlwapi
        mov     edi, shlwapi_txt
        call    GetModImports

        mov     esi, advapi
        mov     edi, advapi_txt
        call    GetModImports


        stdcall MessageBoxA, 0, sDone, sDone, 0

@@:     stdcall ExitProcess, -1

 .err:  stdcall MessageBoxA, 0, sError, sError, 0
        jmp     @b

proc GetModImports
        stdcall LoadLibraryExA, esi, 0, LOAD_LIBRARY_AS_DATAFILE
        cmp     eax, 1
        jb      @f
        mov     ebp, eax
        call    HashAllNames ; base - ebp
@@:     stdcall FreeLibrary,  ebp
        stdcall CreateFileA, edi, FILE_WRITE_DATA, FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0
        push    eax
        stdcall WriteFile, eax, [buf], [count], esp, 0
        stdcall CloseHandle
        ret
endp

proc HashAllNames
        pushad

        xor     si, si
        xchg    si, bp

        cmp     word[ebp], 'MZ'
        jne     .wrong
        mov     eax, [ebp+$3C] ; OffSet to PE Header
        cmp     word[ebp+eax], 'PE'
        jne     .wrong
        mov     ebx, [ebp+eax+$78] ; Offset to Export section
        test    ebx, ebx
        jz      .wrong
        add     eax, ebp

        test    si, si
        jz      .running
        xor     edx, edx
@@:     mov     ecx, [eax+edx+$100] ; Virtual Size of the first section
        add     ecx, [eax+edx+$104] ; Virtual Address of the first section
        cmp     ebx, ecx
        jb      @f
        add     edx, $28
        jmp     @b
@@:     sub     ebp, [eax+edx+$104] ; Section offset in the file
        add     ebp, [eax+edx+$10C] ; Virtual Address of the first section
.running:

        mov     edx, [ebp+ebx+IED.NumberOfNames]
        test    edx, edx
        jz      .wrong
        mov     ebx, [ebp+ebx+IED.AddressOfNames]
        test    ebx, ebx
        jz      .wrong
        add     ebx, ebp

        mov     edi, [buf]

.loop:  mov     esi, [ebx]
        add     esi, ebp

        mov     ecx, esi
        sub     ecx, ebp
        and     ecx, $7FFFFFFF
        cmp     ecx, 10*1024*1024
        ja      .wrong

        mov     eax, 'hip '
        stosd

        xor     ecx, ecx
@@:     lodsb
        or      al, al
        jz      @f
        stosb
        and     al, 11111b
        xor     cl, al
        ror     ecx, 5
        jmp     @b
@@:
        sub     esi, ebp
        sub     esi, [ebx] ; esi - length
        lea     eax, [esi-1]

        mov     esi, ecx
        lea     ecx, [eax*5]
        rol     esi, cl
        mov     ecx, esi

        call    db2str
        shl     eax, 16
        mov     ax, ',$'
        stosd

        rol     ecx, 8
        xor     ah, ah
        mov     al, cl
        call    db2str
        shl     eax, 16
        mov     ax, ',$'
        stosd

        rol     ecx, 16
        xor     ah, ah
        mov     al, cl
        call    db2str
        shl     eax, 16

        xor     ah, ah
        mov     al, ch
        call    db2str
        stosd

        mov     eax, $0A0D0000

        rol     ecx, 8
        xor     ah, ah
        mov     al, cl
        call    db2str
        stosd

        add     ebx, 4
        dec     edx
        jnz     .loop

        sub     edi, [buf]
        mov     [count], edi

.wrong:
        popad
        ret
endp

proc db2str ; ax - input/output
        ror     ax, 4
        shr     ah, 4
        add     ax, ('0' shl 8) + '0'
        cmp     al, '9'
        jna     @f
        add     al, 'A' - '9' - 1
@@:     cmp     ah, '9'
        jna     @f
        add     ah, 'A' - '9' - 1
@@:     ret
endp

sError          db 'Some Error',0
sDone           db 'Done',0

count           dd ?
buf             dd ?    

Than you can use importer like this:
Code:
format PE GUI 4.0
entry start

include 'win32a.inc'
include 'P:\fasm\asm\tests\utils.inc'

myi:
  include 'kernel32.inc'
  imod user, 'user32'
  include 'user32.inc'
  endi
  istr user

start:
        stdcall GetKernel
        stdcall importer, eax, myi

        stdcall MessageBoxA, 0, sWorks, sWorks, 0

        stdcall ExitProcess, -1

 sWorks         db 'It works!!!',0    
Post 06 Mar 2007, 03:23
View user's profile Send private message Reply with quote
Vasilev Vjacheslav



Joined: 11 Aug 2004
Posts: 392
Vasilev Vjacheslav 06 Mar 2007, 14:43
hidden, why you don't create one simple archive which contains you work attached to the first post?
Post 06 Mar 2007, 14:43
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 06 Mar 2007, 14:59
hidden: so, if once there will be some collision, how will your app beheave?
Post 06 Mar 2007, 14:59
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  
Goto page 1, 2  Next

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