flat assembler
Message board for the users of flat assembler.

Index > Windows > stuck at export address table.

Author
Thread Post new topic Reply to topic
Overflowz



Joined: 03 Sep 2010
Posts: 1046
Overflowz
Well, hi there. I'm trying to implement GetProcAddress procedure with fasm, but I stuck at getting address of functions via this formula:
Code:
func_addr = base + AddressOfFunctions[NumberOfNames - index_of_function_name]    

but the problem is that, with this formula, I'm getting wrong results.
here's currently exported function info on my system:
Code:
ordinal     function rva     name ordinal    name rva      name
246         11222            245             C63D2         GetProcAddress
33E         1499F            33D             C7663         LoadLibraryA    

also, NumberOfNames == NumberOfFunctions.

GetProcAddress function address is returned fine, but instead of LoadLibraryA, it returns LoadLibraryExA (ord = 33F, name ord = 33E)
what am I missing?

Code:
; gets procedure address
; edx = function name hash
; ecx = library base address
; returns function address in eax
get_proc_address:
    mov ebx, ecx               ; ebx = kernel32 base
    mov esi, ebx               ; esi = kernel32 base
    add esi, [esi + 0x3C]      ; esi = PE
    mov esi, [esi + 0x78]      ; esi = RVA to export directory
    add esi, ebx               ; esi = VA to export directory
    mov ecx, [esi + 0x18]      ; ecx = NumberOfNames
    mov eax, [esi + 0x1C]      ; eax = RVA to AddressOfFunctions
    mov esi, [esi + 0x20]      ; esi = RVA to AddressOfNames
    add eax, ebx               ; eax = VA to AddressOfFunctions
    add esi, ebx               ; esi = VA to AddressOfNames
    
    mov edi, eax               ; edi = AddressOfFunctions

    ; start counter
@@:
    add edi, 4;shl edi, 2             ; increase AddressOfFunctions offset by 4
    lodsd             ; function name RVA
    add eax, ebx      ; function name VA
    call ror13        ; simple hashing function, returns result in eax
    cmp eax, edx      ; compare hashes
    jz @f
    loop @b
@@:

    mov eax, [edi]        ; get function address RVA
    add eax, ebx          ; get function address VA
    
    ret    


Regards.

EDIT: instead of shl edi, 2 replaced add edi, 4. (I was testing things and it was wrong code, but problem still the same.)
Post 07 Jan 2015, 18:41
View user's profile Send private message Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc
Overflowz
Quote:
but the problem is that, with this formula, I'm getting wrong results.

The formula doesn't make any sense. Fortunately, you're also not using it.
Code:
...
mov edi, eax               ; edi = AddressOfFunctions
...    

This is not what you need. You should follow the array of name ordinals (in fact it's an array of indexes: to obtain an ordinal you'd also add the ordinal base) rather than the array of function RVAs. When you find the corresponding ordinal, use it as an index into the array of function RVAs.

_________________
Faith is a superposition of knowledge and fallacy
Post 07 Jan 2015, 20:30
View user's profile Send private message Reply with quote
Overflowz



Joined: 03 Sep 2010
Posts: 1046
Overflowz
l_inc
hi, so name ordinals are the indexes of AddressOfFunctions? I mean, when I'll get pointer of name ordinal, should I add it to AddressOfFunctions address and get the actual pointer of function address?

Regards.
Post 08 Jan 2015, 11:36
View user's profile Send private message Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc
Overflowz
Quote:
hi, so name ordinals are the indexes of AddressOfFunctions?

Yes. Indexes into the array.
Quote:
when I'll get pointer of name ordinal

You should dereference it to get the two-byte ordinal (index)*. Then you should multiply the index by 4 to get an offset into the AddressOfFunctions array. Then you add the offset to AddressOfFunctions to get a pointer to an RVA of a function. Then you dereference it to get the RVA. And then you add the module base address to get a pointer to the function.

*I hope, you say what you mean here. A pointer to a name ordinal is not a pointer to the name ordinal table, but to a value inside the table.

_________________
Faith is a superposition of knowledge and fallacy
Post 08 Jan 2015, 17:57
View user's profile Send private message Reply with quote
Overflowz



Joined: 03 Sep 2010
Posts: 1046
Overflowz
l_inc
Thanks, worked like a charm Wink
anyone who wants the code, it's here:
Code:
get_proc_address:
    mov ebx, ecx                           ; ebx = library base
    mov esi, ebx                           ; esi = library base
    add esi, [esi + 0x3C]                  ; esi = PE\0\0
    mov esi, [esi + 0x78]                  ; esi = RVA to export directory
    add esi, ebx                           ; esi = VA to export directory
    push esi                               ; save export directory into the stack
    mov ecx, [esi + 0x18]                  ; ecx = NumberOfNames
    mov edi, [esi + 0x24]                  ; edi = RVA to AddressOfNameOrdinals
    mov esi, [esi + 0x20]                  ; esi = RVA to AddressOfNames
    add edi, ebx                           ; edi = VA to AddressOfNameOrdinals
    add esi, ebx                           ; esi = VA to AddressOfNames

    ; start counter
@@:
    lodsd                                  ; load function name RVA into eax
    add eax, ebx                           ; function name VA
    call ror13                             ; get function name hash
    cmp eax, edx                           ; compare hashes
    jz @f                                  ; are they equal?
    add edi, 2                             ; increase AddressOfNameOrdinals offset by 2 (each ordinal is 2 bytes long)
    loop @b                                ; if not, loop again
@@:
    movzx edi, word [edi]                  ; edi = name ordinal
    pop eax                                ; restore export directory into the eax
    mov eax, [eax + 0x1C]                  ; eax = RVA AddressOfFunctions
    add eax, ebx                           ; eax = VA AddressOfFunctions
    mov eax, [eax + edi * 4]               ; eax = RVA function address
    add eax, ebx                           ; eax = VA function address

    ret    

WARNING: not using error checking.
Post 08 Jan 2015, 20:02
View user's profile Send private message Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc
Overflowz
This won't work for forwarded export. I.e., it's possible that instead of a function address, you'll get a pointer to a string similar to "ntdll.RtlHeapAlloc" or "winmm.#2" that is located inside of the export directory. In this case you should perform the address resolving process in the specified dll.

P.S. I have a couple of macros that allow to build a compact import_by_hash table and a code that resolves that table correctly (very compact: about 200 bytes), but the code is a bit suboptimal with respect to performance. I didn't have enough time to improve on that and this way bring those to a state worthy publishing.

_________________
Faith is a superposition of knowledge and fallacy
Post 08 Jan 2015, 20:16
View user's profile Send private message Reply with quote
Overflowz



Joined: 03 Sep 2010
Posts: 1046
Overflowz
l_inc
I know about forwarded exports, I'm just playing around with this and functions that I'm currently using are not export forwarded, but thanks anyway for the tip Wink
Post 09 Jan 2015, 12:54
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-2020, Tomasz Grysztar. Also on GitHub, YouTube, Twitter.

Website powered by rwasa.