原文:http://www.pediy.com/kssd/index.html -- 病毒技术 -- 病毒知识 -- Anti Virus专题
搜索获得api函数地址的实现
我们的程序能正常的调用函数。那么这个动态链接库是如何输出函数来供我们的用户程序调用呢?它实际上是采用输出表结构来描述本dll需要导出哪些函数来供其他的程序调用,这样其他的用户程序才能正常的调用此动态链接库的输出函数.
导出表结构:
IMAGE_EXPORT_DIRECTORY struct
Characteristics DWORD ? ; 未使用,总是为0
TimeDateStamp DWORD ? ; 文件的产生时刻
MajorVersion WORD ? ; 未使用,总是为0
MinorVersion WORD ? ; 未使用,总是为0
nName DWORD ? ; 指向文件名的RVA
nBase DWORD ? ; 导出函数的起始序号
NumberOfFunctions DWORD ? ; 导出函数的总数
NumberOfNames DWORD ? ; 以名称导出的函数总数
AddressOfFunctions DWORD ? ; 指向导出函数地址表的RVA
AddressOfNames DWORD ? ; 指向函数名地址表的RVA
AddressOfNameOrdinals DWORD ? ; 指向函数名序号表的RVA
IMAGE_EXPORT_DIRECTORY ends
在这里说下AddressOfFunctions、AddressOfNames和AddressOfNameOrdinals这三个成员的对应关系,比如说我们通过名称搜索MessageBoxA函数的地址, AddressOfNames的值是一个RVA数组,每个RVA加上模块基址就是实际的函数名称字符串地址,如果说MessageBoxA这个字符串在这个数组的索引位置0处, 而AddressOfNames和AddressOfNameOrdinals是对应的,用”MessageBoxA“字符串在AddressOfNames中的索引在AddressOfNameOrdinals指向的函数名序号表中取值,取出的序号值再用在AddressOfFunctions中用来取值,取得的RVA加上模块基址就是MessageBoxA函数的地址了。
下面的代码用来测试获取MessageBoxA函数的地址并调用
.386
.model flat, stdcall
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
.const
szDllName db 'user32.dll', 0
szApiString db 'MessageBoxA', 0
szText db 'Get API Address Success!', 0
szCaption db 'Success', 0
.code
_GetApiAddress proc _hDllHandle, _lpApiString
push ebp
mov eax, _hDllHandle ; hModule
mov ecx, _lpApiString ; lpApiString
mov ebx, eax ; ebx = hModule
mov edi, ecx ; edi = lpAp