Calling the Windows API in Assembly Language
by
Qark [VLAD]
If you didn't read the windows document in VLAD#4 or don't
know anything about lowlevel windows structures, then turn
back now!
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Although I designed this document with a view to virus writing,
I've never seen any information like this anywhere, so it
could just as easily be used as a general low-level windows text.
Feel free to use it as such.
I worked out the 'procedure ordinal number listing' by using
a diskeditor to increase the 'procedure ordinal number' in the
disk file, and seeing which API was produced by viewing the file
with a disassembler. This took many hours. I only did it for
the KERNEL functions because they are the only ones that are useful
for viruses. If you require pretty windows and scroll bars then
change the 'index into the module reference table' to refer to GDI
or USER and work out the 'procedure ordinal numbers' for yourself.
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
To work out the parameters to enter into the API, you will need
an API listing. These are normally of phone book proportions
and I'm not about to type one out, so grab one from your local
library. If you can, check to make sure that the book you are
thinking of choosing lists the selector functions such as
'AllocCStoDSAlias'. These functions are considered obselete
by Windows 3.1, but they are still there, and should be listed!
All parameters passed into an API are done using the stack.
The values shown in the API listing need to be PUSH'ed in order.
Any return data will be passed back in AX if it is a word, and
DX:AX if a dword. (I might be wrong about this, but it has worked
so far!)
For example, my 'Windows API Bible' (which doesnt list the selector
API functions) says to call "_lopen", which opens a file the same
as int 21 AH=3dh, do this:
Syntax: int _lopen (LPSTR lppathname, int ireadwrite);
Returns: int, file handle, or -1 if error.
Let's analyse the syntax.
The 'int' at the start means the return value will be an integer,
which is a word, and thus passed in AX. If it had said 'LONG' then
we'd know it was passing back in DX:AX.
LPSTR is a pointer to an asciiz string (the book tells us this) so
push the segment, and then offset of the filename to be opened.
'ireadwrite' is the openmode, so based on experience, 2 will be the
word pushed to open in read/write mode.
Now here is the full fileopen API all written up, including
relocation entry and call:
...
push ds ;ds:dx=filename
push dx
mov ax,2 ;open in read/write mode
push ax
apicall:
db 9ah ;Call Far Ptr
dw 0ffffh ;Windows needs these.
dw 0
mov bx,ax ;file handle into BX
...
The relocation item is setout like so:
db 3 ;32 bit pointer
db 1 ;Import Ordinal
dw offset apicall + 1 ;Offset of api entry
dw 1 ;Index into module reference table
;of KERNAL.
dw 55h ;Indicate '_lopen' API call.
;This is the 'procedure ordinal
;number'
In the relocation I have assumed that the kernal is the first
thing in the module reference table. Don't assume this. In a virus
you will have to search for it.
I got the '55h' by checking the table below. The 'procedure ordinal
number' indicates which API the relocation is talking about.
If you changed the '55h' to a '56h' it would be a '_lwrite' API
call instead. Check below to see why.
When in doubt, ask me about it.
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Procedure Ordinal Number Listing for KERNAL functions.
'*' indicates a handy function.
If the procedure 'doesnt exist' theres a chance it may be an
undocumented API.
01h - FatalExit
02h - ExitKernal
03h - GetVersion
04h - LocalInit
05h - LocalAlloc
06h - LocalRealloc
07h - LocalFree
08h - LocalLock
09h - LocalUnlock
0ah - LocalSize
0bh - LocalHandle
0ch - LocalFlags
0dh - LocalCompact
0eh - LocalNotify
0fh - GlobalAlloc
10h - GlobalRealloc
11h - GlobalFree
12h - GlobalLock
13h - GlobalUnlock
14h - GlobalSize
15h - GlobalHandle
16h - GlobalFlags
17h - LockSegment *
18h - UnlockSegment
19h - GlobalCompact
1ah - GlobalFreeAll
1bh - ??? Doesnt exist ???
1ch - GlobalMasterHandle
1dh - Yield
1eh - WaitEvent
1fh - PostEvent
20h - SetPriority
21h - LockCurrentTask
22h - SetTaskQueue
23h - GetTaskQueue
24h - GetCurrentTask
25h - GetCurrentPDB
26h - SetTaskSignalProc
27h - ??? Doesnt exist ???
28h - ??? Doesnt exist ???
29h - EnableDos
2ah - DisableDos
2bh - ??? Doesnt exist ???
2ch - ??? Doesnt exist ???
2dh - LoadModule
2eh - FreeModule
2fh - GetModuleHandle
30h - GetModuleUsage
31h - GetModuleFileName
32h - GetProcAddress
33h - MakeProcInstance
34h - FreeProcInstance
35h - CallProcInstance
36h - GetInstaceData
37h - Catch
38h - Throw
39h - GetProfileInt
3ah - GetProfileString
3bh - WriteProfileString
3ch - FindResource
3dh - LoadResource
3eh - LockResource
3fh - FreeResource
40h - AccessResource
41h - SizeofResource
42h - AllocResource
43h - SetResourceHandler
44h - InitAtomTable
45h - FindAtom
46h - AddAtom
47h - DeleteAtom
48h - GetAtomName
49h - GetAtomHandle
4ah - OpenFile
4bh - OpenPathName
4ch - DeletePathName
4dh - Reserved1
4eh - Reserved2
4fh - Reserved3
50h - Reserved4
51h - _lclose *
52h - _lread *
53h - _lcreat *
54h - _llseek *
55h - _lopen *
56h - _lwrite *
57h - Reserved5
58h - lstrcpy
59h - lstrcat
5ah - lstrlen
5bh - InitTask
5ch - GetTempDrive
5dh - GetCodeHandle
5eh - DefineHandleTable
5fh - LoadLibrary
60h - FreeLibrary
61h - GetTempFileName
62h - GetLastDiskChange
63h - GetLPErrMode
64h - ValidateCodeSegments
65h - NoHookDosCall
66h - Dos3Call *
67h - NetBIOSCall
68h - GetCodeInfo
69h - GetExeVersion
6ah - SetSwapAreaSize
6bh - SetErrorMode
6ch - SwitchStackTo
6dh - SwitchStackBack
6eh - PatchCodeHandle
6fh - GlobalWire
70h - GlobalUnwire
71h - __AHShift
72h - __AHinCR
73h - OutputDebugString
74h - InitLib
75h - OldYield
76h - GetTaskQueueDS
77h - GetTaskQueueES
78h - UndefDynLink
79h - LocalShrink
7ah - IsTaskLocked
7bh - KbDrSt
7ch - EnableKernal
7dh - DisableKernal
7eh - MemoryFreed
7fh - GetPrivateProfileInt
80h - GetPrivateProfileString
81h - WritePrivateProfileString
82h - FileCDR
83h - GetDosEnvironment
84h - GetWinFlags
85h - GetExePtr
86h - GetWindowsDirectory
87h - GetSystemDirectory
88h - GetDriveType
89h - FatalAppExit
8ah - GetHeapSpaces
8bh - Dosignal
8ch - SetSigHandler
8dh - InitTask1
8eh - ??? Doesnt exist ???
8fh - ??? Doesnt exist ???
90h - ??? Doesnt exist ???
91h - ??? Doesnt exist ???
92h - ??? Doesnt exist ???
93h - ??? Doesnt exist ???
94h - ??? Doesnt exist ???
95h - ??? Doesnt exist ???
96h - Directed Yield
97h - WinOldApCall
98h - GetNumTasks
99h - ??? Doesnt exist ???
9ah - ??? Doesnt exist ???
9bh - GetTaskDS
9ch - LimitEMSPages
9dh - GetCurPID
9fh - GlobalHandleNoRip
0a0h - EMSCopy
0a1h - LocalCountFree
0a2h - LocalHeapSize
0a3h - GlobalLRUOldest
0a4h - GlobalLRUNewest
0a5h - A20Proc
0a6h - WinExec
0a7h - GetExpWinVer
0a8h - DirectResAlloc
0a9h - GetFreeSpace
0aah - AllocCStoDSAlias *
0abh - AllocDStoCSAlias *
0ach - AllocAlias *
0adh - __ROMBIOS
0aeh - __a000h
0afh - AllocSelector *
0b0h - FreeSelector *
0b1h - PrestoChangoSelector *
0b2h - __winflags
0b3h - __d000h
0b4h - LongPtrAdd
0b5h - __b000h
0b6h - __b800h
0b7h - __0000h
0b8h - GlobalDosAlloc *
0b9h - GlobalDosFree *
0bah - GetSelectorBase *
0bbh - SetSelectorBase *
0bch - GetSelectorLimit *
0bdh - SetSelectorLimit *
0beh - __e000h
0bfh - GlobalPageLock
0c0h - GlobalPageUnlock
0c1h - __0040h
0c2h - __f000h
0c3h - __c000h
0c4h - SelectorAccessRights *
0c5h - GlobalFix
0c6h - GlobalUnfix
0c7h - SetHandleCount
0c8h - ValidateFreeSpaces
0c9h - ReplaceInst
0cah - RegisterPtrAce
0cbh - DebugBreak
0cch - SwapRecording
0cdh - CvwBreak
0ceh - AllocSelectorArray
0cfh - IsDBCSLeadByte
0d0h - ??? Doesnt exist ???
0d1h - ??? Doesnt exist ???
0e0h - ??? Doesnt exist ???
0f0h - ??? Doesnt exist ???
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
- VLAD #5 INDEX -