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 ??? ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ