巧用函数返回地址获取导出函数的直接调用模块
程序员文章站
2022-06-17 22:55:05
...
目的: 实现调用DLL中检测调用来源模块
描述:开发三方接口时经常会遇到模块校验,常见做法有如下几种
1. 在接口中开放参数,专门用于校验
2. 在接口DLL中校验调用模块
本文主要介绍第2种的实现方法
实现原理:
假设有函数 Add(a+b);
从C/C++角度看,貌似没有办法在Add函数中知道是谁调用了它.
从汇编角度看,在Add函数调用流程如下;
1. push 参数b
2. push 参数a
3. Call 函数Add , 在Call的时会将Add函数下一行代码地址做为返回地址,压栈
4. 到达Add函数的代码位置开始堆栈平衡操作,其中EBP寄存器会记录栈底的指针
5. 开始Add函数的执行
方法:
1.在第4步堆栈平衡操作中,EBP存储的是栈底的指针,
2.在第3步call调用时会将调用Add函数的下一条指令地址压栈,
3.如果能获取此地址,那么根据VirtualQuery查询到的指针基址,
4.此基址就是调用函数的模块句柄(HOMDULE),
5.使用GetModuleFileName可以获取模块的路径.
6.根据模块路径,我们可以检查模块的名称,
7.根据模块路径,可以获取版权,数字签名等信息做为校验的依据.
int c Add(int a ,int b)
{
//获取调用模块名称sart
PVOID pAddress = NULL;
PVOID tmpEAX = NULL;
_asm{
MOV tmpEAX , eax
mov eax , [ebp+4]
MOV pAddress ,eax
mov eax , tmpEAX
}
MEMORY_BASIC_INFORMATION mbi;
HMODULE hModule = NULL;
TCHAR buffer[1024] = {0};
if (::VirtualQuery(pAddress,&mbi,sizeof(mbi)) != 0)
{
hModule = (HMODULE)mbi.AllocationBase;
GetModuleFileName(hModule,buffer,1024);
}
//获取调用模块名称end
return a+b;
}
上一篇: 炒鸡爪要过冷水吗