The main difference between DOS and Windozy coding, is that you don't have
Interrupts to use anymore. Windozy tells the low-level programmer to ****
off, you now have to *LINK* the functions you want, no more "Do this now!"
oh no, you have to *ASK* the ****ing OS to let you do it. Let's face it,
it's a pile of shit, but none-the-less, we have to get used to it!
The closest you could get to DOS in Win32 ASM is by hitting the VxD Calls
this is okay, apart from the fact the calls are quite undocumented (but you
can find the information about) and I've noticed some debugger's won't
debug any program which does not import ANY API's! SUCKS!
So, how the hell do we use these API's? First we have to let our compiler
and linker know what API functions we want... So in your ASM module, you
would require some code such as...
Code:
Extrn <API Name>:PROC
The API name *IS* Case Sensitive!!!! eg. ExitProcess <> EXITPROCESS
So for example, to include the ExitProcess function into your ASM prog. you
will need the following line
Code:
Extrn ExitProcess:PROC
So, you've learnt how to define your API's! So, now you want to be able to
use them! Well, that's easy!
For this example, we'll use GetProcAddress, as it has parameters, a return
value, and the two params are of diffent types...
From your API source --
Code:
FARPROC GetProcAddress (
HMODULE hModule // Handle to DLL Module
LPCSTR lpProcName // Address of function
);
So what are all those words? Let's snap it down
Code:
FARPROC - The type of return value, in this case it is a DWORD
containing the address of the Procedure!
HMODULE - A *VALUE*, which is the handle to the DLL!
LPCSTR - A *POINTER* to an ASCIIZ string!
So in code, you call, with your parameters, and the output value is
returned to you in EAX.
Fine, but what about calling with the parameters? Well, depending on which
compiler your using, the syntax is slightly different, although there is a
global way.
Code:
MASM has a function called INVOKE
INVOKE <API Name>,<Param 1>,<Param 2>.....<Param n>
TASM has an extended call
CALL <API Name>,<Param 1>,<Param 2>.....<Param n>
Global coding method
PUSH <Param n>
: :
PUSH <Param 2>
PUSH <Param 1>
CALL <API Name>
So, lets test out the API..
.386
.model flat
Extrn GetProcAddress:PROC
Kern equ 0BFF70000h ;<- Win9x Kernel handle
.data
xIt db 'ExitProcess',0
.code
start: push offset xIt ;<- Push POINTER of xIt
push Kern ;<- Kern Module handle
call GetProcAddress ;<- Call API
push eax ;<- EAX holds address of ExitProcess
ret ;<- Exit Program! :)
end start
From what you've read, this means all API's has to be linked. However, you
can't have them linked to a virus, unless you're a spawning virus or
companion! So that's why we have GetProcAddress! If you can get access to
this function, you can use it to get the address' of the API you need, and
call them. If you don't expect to return (eg. ExitProcess) then you can
code like in the example above where you push the address (EAX) and
"Return", otherwise you need to CALL it!
Code:
.386
.model flat
Extrn GetProcAddress:PROC
Kern equ 0BFF70000h ;<- Win9x Kernel handle
.data
Usr db 'USER32',0
GetMod db 'GetModuleHandleA',0
xIt db 'ExitProcess',0
.code
start: push offset GetMod ;<- Push POINTER to GetModHand
push Kern ;<- Kern Module handle
call GetProcAddress :<- Call API
xchg edi,eax ;<- Put API address into EDI
; DWORD GetModuleHandleA(LPCSTR lpModuleName);
push offset Usr ;<- Pointer to USER32 ASCIIZ string
call [edi] ;<- Call API address
;Here, EAX = Handle of User32, EDI = Address of GetModuleHandleA
push offset xIt ;<- Push POINTER of xIt
push Kern ;<- Kern Module handle
call GetProcAddress ;<- Call API
push eax ;<- EAX holds address of ExitProcess
ret ;<- Exit Program! :)
end start
By Rat Heart /ASM