Confusion with how Win32 API calls work in assembly

孤人 提交于 2020-05-13 06:46:50

问题


I don't know how to ask this better but why does this:

call ExitProcess

do the same as this?:

mov eax, ExitProcess
mov eax, [eax]
call eax

I would think that these would be equivalent:

call ExitProcess


mov eax, ExitProcess
call eax

回答1:


When importing the code from a DLL, the symbol ExitProcess isn't actually the address of the code that exits your process (it's the address of the address). So, in that case, you have to dereference it to get the actual code address.

That means that you must use:

call [ExitProcess]

to call it.

For example, there's some code at this location containing the following:

;; Note how we use 'AllocConsole' as if it was a variable. 'AllocConsole', to 
;; NASM, means the address of the AllocConsole "variable" ; but since the 
;; pointer to the AllocConsole() Win32 API function is stored in that 
;; variable, we need to call the address from that variable. 
;; So it's "call the code at the address: whatever's at the address
;; AllocConsole" . 
call [AllocConsole] 

However, importing the DLL directly in user code is not the only way to get at the function. I'll explain why you're seeing both ways below.

The "normal" means of calling a DLL function is to mark it extern then import it from the DLL:

extern ExitProcess
import ExitProcess kernel32.dll
:
call [ExitProcess]

Because that sets up the symbol to be an indirect reference to the code, you need to call it indirectly.

After some searching, it appears there is code in the wild that uses the naked form:

call ExitProcess

From what I can tell, this all seems to use the alink linker, which links with the win32.lib library file. It's possible that this library provides the stub for calling the actual DLL code, something like:

import ExitProcessActual kernel32.dll ExitProcess
global ExitProcess

ExitProcess:
    jmp [ExitProcessActual]

In nasm, this would import the address of ExitProcess from the DLL and call it ExitProcessActual, keeping in mind that this address is an indirect reference to the code, not the address of the code itself.

It would then export the ExitProcess entry point (the one in this LIB file, not the one in the DLL) so that others could use it.

Then someone could simply write:

extern ExitProcess
:
call ExitProcess

to exit the process - the library would jump to the actual DLL code.


In fact, with a little more research, this is exactly what's happening. From the alink.txt file which comes with the alink download:

A sample import library for Win32 is included as win32.lib. All named exports in Kernel32, User32, GDI32, Shell32, ADVAPI32, version, winmm, lz32, commdlg and commctl are included.

Use:

alink -oPE file[.obj] win32.lib

to include it or specify

INCLUDELIB "win32"

in your source file.

This consists of a series of entries for import redirection - call MessageBoxA, and it jumps to [__imp_MessageBoxA], which is in the import table.

Thus calls to imports will run faster if call [__imp_importName] is used instead of call importName.

See test.asm, my sample program, which calls up a message box both ways:

includelib "win32.lib"
extrn MessageBoxA:near
extrn __imp_MessageBoxA:dword

codeseg

start:
push 0 ; OK button
push offset title1
push offset string1
push 0
call MessageBoxA

push 0 ; OK button
push offset title1
push offset string2
push 0
call large [large __imp_MessageBoxA]

(__imp_MessageBoxA is the symbol imported from the DLL, equivalent to my ExitProcessActual above).



来源:https://stackoverflow.com/questions/11731816/confusion-with-how-win32-api-calls-work-in-assembly

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!