; ; program: ordexample.asm ; author: Eddy L O Jansson / DFR Research & Engineering ; updated: 1999-08-10 03:05 ; ========================================================================= ; ; This code demonstrates how you can lookup a functions address thru it's ; ordinal value so that you can call undocumented functions which often ; have no name and thus cannot be declared, imported and called in the ; normal way. ; ; This code was developed and tested under Win'98 only, but it should ; work on all versions of Win'9x and under NT also. What we do is to ; walk thru the MZ and PE-header of kernel32.dll, until we reach the ; _IMAGE_EXPORT_DIRECTORY structure. This structure is then used to ; look up the correct function address by means of the export table. ; ; ; Send questions and comments to srm_dfr@hotmail.com ; http://hem2.passagen.se/eddy1/reveng/ ; ; Assembled using TASM v5.0: ; tasm32 -ml -m5 -q ordexamp.asm ; tlink32 -Tpe -aa -x -c ordexamp ,,, import32 ; .386p .model flat, stdcall EXTRN GetModuleHandleA:PROC EXTRN MessageBoxA:PROC EXTRN ExitProcess:PROC .CONST sTitle db 'Call by ordinal demonstration',0 sMessage db 'bpx MessageBoxExA ;-)',0 sKernel32 db 'KERNEL32',0 .DATA kernelbase dd ? ; don't change these around, we rely on this structure. exp_ord_base dd ? ;exp_func_count dd ? exp_func_tbl dd ? ;exp_ord_tbl dd ? .CODE START: push 30h push offset sTitle push offset sMessage push 0 call MessageBoxA ; ; This part of the code setup structures for the retrieval ; of function entrypoints by means of function ordinals. ; ; Note about the decommented code: this code is here in case ; someone wants to develop this further to make it search ; the ordinal table, instead of going for the function address table ; directly. I am myself unaware on how one would do that, the ordinal ; table just makes no sense, not for kernel32.dll anyway. ; push offset sKernel32 call GetModuleHandleA ; get kernel base address mov kernelbase,eax mov ebx,eax ; setup workspace mov ecx,eax ; -""- add eax,dword ptr[eax+03Ch] ; eax = pestart add ebx,dword ptr[eax+078h] ; ebx = image_export_directory mov edi,offset exp_ord_base mov eax,dword ptr[ebx+010h] ; base ordinal stosd ;mov eax,dword ptr[ebx+014h] ; number of function exported ;stosd mov eax,dword ptr[ebx+01Ch] ; function address table add eax,ecx stosd ;add ecx,dword ptr[ebx+024h] ; function ordinal table ;mov eax,ecx ;stosd ; ; Then when you want to look up a functions address, you simply do this. ; mov eax,25h ; kernel32!ord_25 = GetProcAddress16 sub eax,exp_ord_base ; fix up (normally 'dec eax') mov ecx,exp_func_tbl mov edi,dword ptr[ecx+eax*4] ; retrive address from table add edi,kernelbase ; ; Now the functions address is in edi, and you can call it. ; If you trace the code, do a 'u edi' in softice here, and you will ; see that you got the correct address. ; ; call edi nop nop exit: push 0 call ExitProcess END START