Hi friends,
My tool scan.exe searches for API functions in the source codes and creates a listing of these functions. I created some macros to handlle this listing so that all the API functions can be called with the LoadLibrary & GetProcAddress methode.
Scan looks for API functions and puts them in an include file :
The source code looks like this :
The macro LOAD_LIBS :
- gets the handle of kernel32.dll , only one function ExitProcess is imported from kernel32.lib
?because executables without import section may not function on every version of Windows.
- looks for the adress of GetProcAddress
- finds the addresses of LoadLibrary & FreeLibrary
- loads the required DLLs ( except kernel32.dll )
- finds the adresses of API functions
Finally, FREE_LIBS unloads the DLLs except kernel32.dll
Notice that ExitProcess should be called with Invoke instead of invoke so that scan would not put ExitProcess to the list of API functions. ( scan is case-sensitive ) Only one API function prototype should exist to create a minimal import section :
The couple invoke2 / Invoke2 doesn't do parameter checking. There is also the cinvoke macro for C run-time functions.
If you want scan to by-pass a function, call it with Invoke or Invoke2 macro
To create the listing file :
...and you get sourcefile.imp
To get more informationa about my tool scan, have a look at :
http://vortex.masmcode.com
My tool scan.exe searches for API functions in the source codes and creates a listing of these functions. I created some macros to handlle this listing so that all the API functions can be called with the LoadLibrary & GetProcAddress methode.
Scan looks for API functions and puts them in an include file :
.data
impfuncs dd hkernel32
? ? ? ? db "GetModuleHandleA",0
? ? ? ? db 0
? ? ? ? dd huser32
? ? ? ? db "DialogBoxIndirectParamA",0
? ? ? ? db "EndDialog",0
? ? ? ? db "LoadIconA",0
? ? ? ? db "LoadMenuIndirectA",0
? ? ? ? db "MessageBoxA",0
? ? ? ? db "SendMessageA",0
? ? ? ? db "SetMenu",0
? ? ? ? db 0
? ? ? ? dd hgdi32
? ? ? ? db "CreateSolidBrush",0
? ? ? ? db "DeleteObject",0
? ? ? ? db 0
? ? ? ? dd 0
loadDLL db "user32.dll",0
? ? ? ? ? db "gdi32.dll",0
? ? ? ? ? db 0
.data?
ProcAddr EQU GetModuleHandle
? ? ? ? GetModuleHandle dd ?
? ? ? ? DialogBoxIndirectParam dd ?
? ? ? ? EndDialog dd ?
? ? ? ? LoadIcon dd ?
? ? ? ? LoadMenuIndirect dd ?
? ? ? ? MessageBox dd ?
? ? ? ? SendMessage dd ?
? ? ? ? SetMenu dd ?
? ? ? ? CreateSolidBrush dd ?
? ? ? ? DeleteObject dd ?
hModules EQU huser32
? ? ? ? huser32 dd ?
? ? ? ? hgdi32 dd ?
? ? ? ? hkernel32 dd ?
NumbOfModules EQU 2
The source code looks like this :
.
.
.code
start:
LOAD_LIBS
invoke2 GetModuleHandle, NULL
invoke2 DialogBoxIndirectParam,eax,ADDR Resource,NULL,ADDR DlgProc,NULL
FREE_LIBS
Invoke ExitProcess,eax
.
.
The macro LOAD_LIBS :
- gets the handle of kernel32.dll , only one function ExitProcess is imported from kernel32.lib
?because executables without import section may not function on every version of Windows.
- looks for the adress of GetProcAddress
- finds the addresses of LoadLibrary & FreeLibrary
- loads the required DLLs ( except kernel32.dll )
- finds the adresses of API functions
Finally, FREE_LIBS unloads the DLLs except kernel32.dll
Notice that ExitProcess should be called with Invoke instead of invoke so that scan would not put ExitProcess to the list of API functions. ( scan is case-sensitive ) Only one API function prototype should exist to create a minimal import section :
ExitProcess PROTO :DWORD
The couple invoke2 / Invoke2 doesn't do parameter checking. There is also the cinvoke macro for C run-time functions.
If you want scan to by-pass a function, call it with Invoke or Invoke2 macro
To create the listing file :
scan sourcefile.asm -m3
...and you get sourcefile.imp
To get more informationa about my tool scan, have a look at :
http://vortex.masmcode.com
...the question is, why would you do this?
Some users worked on creating executables without import section. As an academic interest on this topic, I tried to automate all the work.
As an academic interest, it can be fun... and there's a (very) few appliances where it can be useful, like when dealing with software protection. I wouldn't recommend anybody to adopt this kind of coding for generic use, though.
Especially not since manually coded GetProcAddresses are often fragile, and slower.
Especially not since manually coded GetProcAddresses are often fragile, and slower.
Yes, the technique can be usefull for software protection and you are free to modify the code to use the real GetProcAddress API function so that there will be no fragility.