Customizing the GetProcAddress

    <-- x64lab Multilanguage Enhanced Ide
    Copyright (c) 2009-2011, Marc Rainer Kranz
    All rights reserved. -->
            MPL 1.1 License


Here my 64 bit customized GetProcAddress. It uses a divide-and-conquer strategy (better spelled as "decrease-and-conquer") to find the API.

At the moment it doesnt resolve forwarded references (i do not plan to implement such feature, nor i would). It executes at O(log2N) time,

where N represents the number of functions; it means that for a 1237-functions library, like the kernel32.dll, it executes max. 10 comparisons, plus some overhead of few comparisons to match exactly names like CreateFi-leA and CreateFi-leW
(because the key-needle is actually 8 bytes only).

Usage is like the standard GetProcAddress, but you dont need to adjust
stack for the call

mov rdx,szApiName (ansi string, example "CreateFileA")
mov rcx,hModule   (obtained from GetModuleHandle)
call .get_api


.get_api:
    ;--- in RCX BaseAddress
    ;--- in RDX apiname
    ;--- RET RAX (0,valid function address)
    push rbp
    push rbx
    push rdi
    push rsi
    push r12
    push r13
    push 0

    test rcx,rcx
    jz .err_get_api
    mov rbx,rcx
    test rdx,rdx
    jz .err_get_api
    mov rsi,rdx
   
    mov eax,[rbx+3Ch]   
;--- PE header
    test eax,eax
    jz .err_get_api
    add rax,rbx          ;--- Add the modules base address
    mov ebp,[rax+88h]    ;--- export tables RVA
    test ebp,ebp         ;--- is EAT ?
    jz .err_get_api
    add rbp,rbx          ;--- ok EAT

    mov ecx,[rbp+14h]    ;--- NumberOfFunctions
    test ecx,ecx
    jz .err_get_api
    mov edx,[rbp+20h]   
    add rdx,rbx          ;--- AddressOfNames

    mov r11,[rsi]
    bswap r11
    mov r12,rsi

.get_apiA:
    lodsb
    test al,al
    jnz .get_apiA
    mov rax,r12
    sub rax,rsi
    neg rax
    mov rsi,r12

    xor r10,r10   ;--- RX
    mov r9,rcx    ;--- LX
    mov r12,rax   ;--- len api

    mov ecx,eax
    sub eax,8
    sbb eax,eax
    and ecx,eax
    shl ecx,3
    xor eax,eax
    dec cl
    inc eax
    ror rax,1
    sar rax,cl
    and r11,rax
    xor ecx,ecx
    xchg r13,rax    ;--- mask
    jmp .get_apiLX

.get_apiRX:
    test r10,r10
    jle .err_get_api
    add rcx,r9
    shr r10,1
    mov r9,r10
    adc r9,1

.get_apiLX:
    ;--- in RCX OFFS
    ;--- in R9  LX
    ;--- in R10 RX
    mov eax,ecx
    add rax,r9
    dec eax
    shl eax,2
    add rax,rdx
    mov edi,[rax]
    add rdi,rbx
    mov rax,[rdi]
    bswap rax
    and rax,r13
    cmp r11,rax
    ja .get_apiRX
    jz .get_apiB
    shr r9,1
    jz .err_get_api
    mov r10,r9
    adc r9,0
    dec r10
    jmp .get_apiLX

.get_apiB:
    add r9,rcx
    add r9,r10
    test r9,r9
    jle .err_get_api
    inc r9
    mov r8,rsi

.get_apiC:
    dec r9
    jz  .err_get_api
    mov rcx,r12
    mov rsi,r8
    mov edi,[rdx+r9*4-4]
    add rdi,rbx
    repe cmpsb
    jnz .get_apiC
    test ecx,ecx
    jnz .get_apiC

    mov esi,[rdx+r9*4-4]
    add rsi,rbx
    mov edx,[rbp+1Ch]    ;--- AddressOfFunctions
    add rdx,rbx
    mov eax,[rdx+r9*4-4]
    mov [rsp],rax
    add [rsp],rbx

.err_get_api:
    pop rax
    pop r13
    pop r12
    pop rsi
    pop rdi
    pop rbx
    pop rbp
    ret 0