Can anyone tell me what did the GetProcAddress return? I mean the returned value in EAX means what? It really point to what?
Posted on 2004-12-02 02:22:21 by microstar_top
The address of the function you wanted to get.
Posted on 2004-12-02 04:19:32 by roticv
this is why i read the manual :lol:

taken from:

MSDN - GetProcAddress

Return Values

If the function succeeds, the return value is the address of the exported function or variable.

If the function fails, the return value is NULL. To get extended error information, call GetLastError.

Posted on 2004-12-02 05:54:14 by enodev

Welcome to the forum.

Here is a simple example for you. The application loads user32.dll and gets the address of MessageBoxA

.model flat,stdcall
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
includelib \masm32\lib\kernel32.lib

user32 db 'user32.dll',0
msgbox db 'MessageBoxA',0
caption db 'GetProcAddress example',0

invoke LoadLibrary,ADDR user32
push eax
invoke GetProcAddress,eax,ADDR msgbox
push MB_OK
push OFFSET msgbox
push OFFSET msgbox
push 0
call eax
pop eax
invoke FreeLibrary,eax
invoke ExitProcess,0

END start
Posted on 2004-12-02 12:46:07 by Vortex
under 9x, due to inconsistencies, GetProcAddress sometimes returns a thunk in the kernel of that particular API - something definitely to watch out for.
Posted on 2004-12-02 16:23:50 by Drocon
Thanks for all of your reply,easpecially Vortex's excellent sample. If I want to inject some code into other process's address space, should I relocate all the calls to these APIs? what should I do. That's the reason why I want to know the secret of GetProcAddress. What did the return value means, if I want to inject API's call into other process's space, how should i modify such codes to ensure they can perform properly?
I'm sorry for my English!
Thanks again for all of yours reply!
Posted on 2004-12-03 07:59:15 by microstar_top
Ok as I understand you wanna insert your code in another process, but
you have some troubles with implementing that... Well there are 2 tehniques that I'm aware of ->>>
First is to code your own win32 shellcode (includes locating kernel32.dll base and writing your own GetProcAddress) and use CreateProcess with SUSPENDED flag, inject code, ResumeThread =)
Second is more simple and it consist of DLL injecting...

2nd tehnique is much better b/c you don't have to play with troubles that come with real shellcode coding... it's boring in Windows, and more fun in Unix =) My smallest execve shellcode for Linux and aslo *BSD systems was 21 bytes, but at windows... huh toooo large =) I hate that =)

Ok DLL ijecting is simple tehnique which consist of injecting your dll in another process memory space...
1. find right process
2. OpenProcess
3. use VirtualAllocEx to alloacte memory for dll name
4. use WriteProcessMemory to write dll name at allocated memory
5. Find LoadLibraryA address
6. CreateRemoteThread
7. DLL is injected...
8. Havefun =)

e =)you can find these codes at http://nonenone.cjb.net/example.zip
Posted on 2004-12-03 10:34:50 by c0mrad

Here is a simulation of GetProcAddress

Thanks to Axial for his code:

; ebp holds a delta offset
szGetProcAddress db "GetProcAddress",0
GPASIZE = $ - szGetProcAddress
ApiCounter dd 0

GetGetProcAddressAddress proc
and dword ptr [ebp + ApiCounter],0
mov edi,dword ptr [eax+3Ch] ; kernel PE hdr
add edi,eax ; add image base
assume edi:ptr IMAGE_NT_HEADERS
mov edi,[edi].OptionalHeader.DataDirectory.VirtualAddress
add edi,eax
mov ecx,[edi].NumberOfNames
mov esi,[edi].AddressOfNames

add esi,eax
xchg eax,ebx

add eax,ebx

push ecx
push edi
push esi

pop ecx
lea edi,[ebp+szGetProcAddress]
mov esi,eax
repz cmpsb

pop esi
pop edi

jecxz GPA_found

inc dword ptr [ebp + ApiCounter]

pop ecx
dec ecx
jnz MatchLp

xor eax, eax ; error


mov esi,[edi].AddressOfNameOrdinals
pop ecx

mov ecx,dword ptr [ebp + ApiCounter]
shl ecx,1
add esi,ecx
add esi,ebx
xor eax,eax
shl eax,2

add eax,[edi].AddressOfFunctions
mov esi,eax
add esi,ebx
add eax,ebx

assume edi :nothing

GetGetProcAddressAddress endp
Posted on 2004-12-03 12:40:26 by Vortex
Posted on 2004-12-04 00:16:05 by microstar_top
no problem man =)
Posted on 2004-12-04 07:18:48 by c0mrad
Vortex, what happens if you run that GPA on NT and there's a forwarded export? :)
Posted on 2004-12-04 08:11:04 by f0dder
under 9x, due to inconsistencies, GetProcAddress sometimes returns a thunk in the kernel of that particular API - something definitely to watch out for.

Hi :)
What do you mean by a thunk? When does this happen exactly? :?:
Posted on 2004-12-04 11:40:58 by QvasiModo
Vortex, what happens if you run that GPA on NT and there's a forwarded export? :)

The solution is very easy, you will fix it if something is going wrong :)
Posted on 2004-12-05 04:12:44 by Vortex
After reading Vorex's post, I've thought a lot . Under Windows NT, GetProcAddress actually return the start address of the specified function. Because dlls in different process may be mapped in different regtion, so we must scan the export data directory to get the real start address. But I found the system dlls such as kernel32,user32 ,the system will always map them into the same address space in the higher memory region. So I wrote a demo to inject code into notepad process in a lazy way . The code run properly under Windows 2000.
I'm a freshman in Assembly language and system functions. If something was wrong with the code, tell me . Or you know other more efficient way, just tell me. Thanks.

.model flat,stdcall
option casemap:none

include windows.inc
include kernel32.inc
includelib kernel32.lib
include user32.inc
includelib user32.lib

lpMessageBox dd ?
lpGetModuleHandle dd ?
dwProcessId dd ?
hProcess dd ?
hKernel dd ?
hUser dd ?
hNotepad dd ?
lpBeginAddress dd ?

szClassName db 'Notepad',0
szKernel db 'kernel32.dll',0
szUser db 'user32.dll',0
szMessageBoxA db 'MessageBoxA',0
szGetModule db 'GetModuleHandleA',0
include injected.asm
;Get handle of kernel32
invoke GetModuleHandle,offset szKernel
mov hKernel,eax
;Get handle of user32
invoke GetModuleHandle,offset szUser
mov hUser,eax
invoke GetProcAddress,eax,offset szMessageBoxA
mov lpMessageBox,eax

invoke GetProcAddress,hKernel,offset szGetModule
mov lpGetModuleHandle,eax

; Find window(Notepad)
invoke FindWindow,offset szClassName,NULL
mov hNotepad,eax
invoke GetWindowThreadProcessId,eax,offset dwProcessId

; Open notepad process and get process handle
invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,dwProcessId
mov hProcess,eax
mov lpBeginAddress,eax
invoke WriteProcessMemory,hProcess,eax,offset REMOTE_CODE_START,REMOTE_CODE_LEN,NULL
invoke WriteProcessMemory,hProcess,lpBeginAddress,offset lpMessageBox,sizeof dword * 2,NULL

mov eax,lpBeginAddress
add eax,offset remote - offset REMOTE_CODE_START

invoke CreateRemoteThread,hProcess,NULL,0,eax,NULL,0,NULL

; close thread handle
invoke CloseHandle,eax

; close process handle
invoke CloseHandle,hProcess

invoke ExitProcess,NULL
end Start

REMOTE_CODE_START equ this byte
lpMessageBoxRemote dd ?
lpGetModule dd ?
hInstance dd ?

szCaption db 'Remote',0
szContent db 'The code executed now is injected by another process!',0

remote proc uses esi ebx edi lParam
local @hModule

call @f
;ebx is the offset between original address and new address
pop ebx
sub ebx,offset @b

push NULL
lea esi,lpGetModule
add esi,ebx
call dword ptr [esi]
lea esi,hInstance
add esi,ebx
; mov [ebx + offset hInstance],eax
mov esi,eax

push MB_OK
lea esi,offset szCaption
add esi,ebx
push esi
lea esi,offset szContent
add esi,ebx
push esi
lea esi,offset hInstance
add esi,ebx
push [esi]
lea esi,lpMessageBoxRemote
add esi,ebx
call dword ptr [esi]
remote endp

REMOTE_CODE_END equ this byte

Have Fun! :lol:
Posted on 2004-12-05 09:28:01 by microstar_top
include injected.asm

Is looks like that this file is missing, am I wrong?
Posted on 2004-12-05 10:15:29 by Vortex
It could be also usefull to check how LSD solved fork()-ing under windows =) Very nice tehnique and it also has a nice explanation of suspend/resume thread and managing thread context... very easy to understand...

http://lsd-pl.net and look for Windows assembly components
Posted on 2004-12-05 14:58:30 by c0mrad
The Code from REMOTE_CODE_START to the end is the content of injected.asm. I forgot to write down the file's name.
Posted on 2004-12-05 20:04:17 by microstar_top
Ok probably didn't tell you that GetProcAddress is capable of finding APIs by ordinal :

invoke GetProcAddress, handle, 238

where 238 is ordinal in ntdll.dll for NtQueryInformationProcess at WinXP SP1 =)
So complete engine for rewriting GetProcAddress if you wanna hook it and see when is it used... A really didn't know that this API is called so many times during DLL initialisation... So here is complete code on rewriteing GetProcAddress

GetProcAddr PROC USES esi edi ebx ecx edx bHandle:DWORD, pApi:DWORD
;Install our Structured Exception Handler

push bHandle
pop handle

;If handle == 0 we are looking for current module from PEB
;According to IDAs output of GetProcAddress ->>> BasepMapModuleHandle ->>>
; if handle is equal to 0, then get image-base from PEB
cmp handle, 0
jnz @F
mov eax, FS:[30h]
mov eax, [eax+8] ;<---- get Image Base
mov handle, eax
;<---- Locate EXPORT_TABLE!!!!!!
mov edi, handle
add edi, dword ptr[edi+3ch]
mov ebx, [edi].OptionalHeader.DataDirectory[0].VirtualAddress
add ebx, handle


;Is it ordinal??
mov ecx, 0FFFFh
mov edx, pApi
cmp edx, ecx
jbe @ordinal

;<--- get api len!!!!!
xor eax, eax
mov edi, pApi
mov ecx, 100h
repnz scasb
sub edi, pApi
mov ecx, edi

mov edx, [ebx].AddressOfNames
add edx, handle

xor eax, eax ;<----- eax is counter!!!
mov esi, [edx]
add esi, handle
mov edi, pApi
push ecx ;<----- save API_len
repe cmpsb
jz @find_ordinal
pop ecx
add edx, 4
inc eax
cmp eax, [ebx].NumberOfNames
jbe @find_name
mov eax, 0
jmp @ExitProc

;<--------in eax is Ordinal index * 2 to find right address
mov esi, [ebx].AddressOfNameOrdinals
add esi, handle
xor edx, edx
mov dx, word ptr[esi+eax*2]
;<---- edx has ordinal number
;<----- Now Find API address
mov esi, [ebx].AddressOfFunctions
add esi, handle
xor eax, eax
mov eax, dword ptr[esi+edx*4]
add eax, handle ;<---------API address

add esp, 4
GetProcAddr ENDP
Posted on 2004-12-06 19:04:48 by c0mrad
Why use something that is slower than regular GetProcAddress that doesn't handle forwarded exports either?
Posted on 2004-12-07 08:26:28 by f0dder
Just for fun, somebody asked about GetProcAddress so here is complete code on how to rewrite it =)
For educational urpose only =)
Posted on 2004-12-07 10:26:31 by c0mrad