这种问题你在问问上问不会有很好的结果的,我简单给你说说思路和原理 NtReadVirtualMemory这个函数在RING3下由NTDLLDLL导出,对应的系统服务函数地址保存在SSDT里。不知道你问的是应用层还是内核层,我分别和你说一下。 RING3下可以编写DLL注入每个进程,然后在每个进程内修改系统动态链接库的导出表,即IAT HOOK。要想得到原始函数地址,首先要打开磁盘上的NTDLLDLL文件,解析该文件的导出表(EAT),根据NTDLLDLL的内存基址以及磁盘文件里记录的RVA手动计算出NtReadVirtualMemory函数地址。 RING0下直接修改SSDT表即可挂钩NtReadVirtualMemory系统服务,要想获取SSDT里各例程的原始地址,同样需要自己解析磁盘文件(ntoskrnlexe)。关于SSDT HOOK的内容网上很多,我在看雪找到了一个不错的贴你可以参考下: http://bbspediycom/showthreadphpt=99970&highlight=SSDT+HOOK+%E6%81%A2%E5%A4%8D 很早以前用VB6写过一个ring3下检测EAT HOOK/IAT HOOK的程序,不过只在XP下测试过,而且现在很少人用VB6了,这份代码可能对你没有什么参考价值,如果有需要的话可以去我的博客找找代码naylon0ginrcom
vs的项目默认字符集是 Unicode 字符集,换成如下就可以了:
LoadLibrary(_T("actice_dlldll"));或者
LoadLibrary(L"actice_dlldll");
或者
LoadLibraryA("actice_dlldll");
windows的话,好像有个GetModuleFileName
这个我用过,我也记下来了
HMODULE hModule;
GetModuleHandleEx( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)(dll中任意一函数地址), &hModule );
TCHAR filename[MAX_PATH];
GetModuleFileName( hModule, filename, _countof(filename) );
如果缓冲区(filename)太小,还得重来
最后,filename就是dll自身所在路径。
在golang中加载dll并调用函数流程如下:
1加载dll动态库到内存 syscallLoadLibrary
2获取函数地址 syscallGetProcAddress
3执行系统调用,传入参数 syscallSyscall6
一个系统消息框函数的调用示例:
简单说:在put函数的定义处,首先得有一个student的对象,然后通过对象调用input,调用时实参的个数,类型和input函数中的形参个数,类型都要一致。
具体解释:
c++的成员函数根据其调用的不同,大致可以分为4类:内联成员函数,静态成员函数,虚成员函数和上述3种以外的普通成员函数。从本质来说类成员函数和全局函数在调用上并没有差别,非内联函数的在调用时,基本上都包括如下的过程:函数的参数入栈,eip指针值入栈,然后跳到函数体的地址,执行函数体对应的代码,执行完毕调整栈帧。下面就按照上述4个分类进行分析,先来说一下普通的成员函数:
普通的成员函数在被调用时有两大特征:
1 普通的成员函数是静态绑定的,
2 普通的成员函数调用时编译器隐式传入this指针的值。
通过代码分析一下:
#include <iostream>
using namespace std;
class Test
{
public:
void Print(int i);
};
void Test::Print(int i)
{
cout<<i<<endl;
}
int main()
{
Test p=new Test();
p->Print(2);
system("pause");
}
上面Print函数符合上面所说4类的中的普通成员,所谓的静态绑定实质是c++源代码编译时,编编译器在p->Print();处翻译成直接调用Test类中Print()的汇编代码,也就是编译期编译器就确定了被调函数的相对地址。而所谓的动态绑定实质是,源码在编译的时候,编译器不是翻译成直接调用Test类中Print()的汇编代码,而是翻译成一个查找虚表,得到到函数的相对地址的过程。
可以通过两种方式
1隐式链接(需要dll,lib,h)
2显式链接(需要dll,h)
方法1:隐式链接----需要lib,dll,h文件
隐式链接就是在程序开始执行时就将DLL文件加载到内存当中,而显示链接,是实时加载,程序需要的时候加载,不需要的时候,卸载。
这种方式需要DLL文件,以及相应的Lib文件和头文件。
只要没有在程序中显式链接的,都是隐式链接
Windows程序bin目录包含了可执行文件(exe)和动态链接库(dlll),lib目录包含了静态库。
步骤
第一步:将dll,lib,h文件放入对应的搜索路径
●其中动态库的搜索路径点击这里查看,记住最重要的两个
1、项目当前目录(cpp)目录
2、path环境变量中的目录
●静态库的搜索路径包括
1、项目当前目录cpp目录(项目和解决方案的Debug不行)(也不是解决方案目录)
2、VC设置中的库目录(Library Directories)
注:如果lib库不放到搜索路径中,也可以在程序中添加
#pragmacomment(lib,"D:/DLLTestlib")//若是相对路径,则为项目当前cpp目录
●头文件搜索路径包括
1、VC设置中的包含目录(Include Directories)
第二步:一定要在VC设置中的依赖项中添加你用到的库的名字
第一种(对应上面每种搜索路径1):针对数量较少的库
设置dll,lib搜索路径:直接将dll,lib,h放入项目当前目录下(即含有项目源文件cpp的目录)
设置h的搜索路径:VC设置中的包含目录(Include Directories)加入你的h路径
然后在链接->输入->附加依赖项中加入你要使用的静态库。
这里只添加静态库
就可以使用DLL中的函数了。
第二种(对应上面每种搜索路径2):针对数量比较多的库(Opencv)
如Opencv,OSG等开源库的配置
这种方式也是通常开源库的配置方式,如Opencv,OSG等
步骤如下
步骤1 添加DLL的目录
方法1:★将dll目录(通常为bin目录)放入环境变量Path中(需要重启),path是搜索动态库的目录
步骤2添加静态库lib库目录和头文件的目录
在工程中的VC++目录中添加静态库目录和头文件目录。
步骤3添加静态库
在链接->输入->附加依赖项中加入你要使用的静态库(当程序中调用时,会在上述配置的库目录中寻找这个库)。
这里只添加静态库,动态库的目录已放入环境变量中,系统会搜索这个路径的,自动加载dll
如RmwRoadBoundaryStraightLineDLLlib
然后,在程序中添加头文件 (在上述配置的头文件目录中寻找),就可以使用DLL中的函数了。
方法2:显式链接---需要DLL(不需要lib,h文件)
就是显式加载DLL库
注意:显示链接,导出DLL的时候,采用extern “C”的方式,而不采用_declspec(dllexport),因为 _declspec(dllexport)会有一个”名字改编”的问题(采用了_cdecl调用规约的C++编译方式)。
示例:
如库文件对应的头文件如下
#ifndef DLLTEST_H
#defineDLLTEST_H
//该宏完成在dll项目内部使用__declspec(dllexport)导出
//在dll项目外部使用时,用__declspec(dllimport)导入
//宏DLL_EXPORTS在cpp中定义
#ifdefDLL_EXPORTS
#defineDLL_EXPORTS extern"C"_declspec(dllexport)
#else
#define DLL_EXPORTS extern"C"_declspec(dllimport)
#endif
//函数声明
DLL_EXPORTSint Add(int a, int b);
DLL_EXPORTSint Sub(int a, int b);
DLL_EXPORTSint Divide(int a, int b);
#endif//DLLTEST_H
测试代码:
typedefint(Add)(int a, int b);
typedefint(Sub)(int a, int b);
HINSTANCE hDLL;
Add Add_;//函数指针
hDLL = LoadLibrary(_T("D:/DLLTestdll"));//加载动态链接库DLLTestdll文件;
Add_ = (Add)GetProcAddress(hDLL,"Add");
intresult = Add_(5, 8);
printf("5+8:%d\n",result);
FreeLibrary(hDLL);//卸载dll文件;
以下是采用__declspec(dllexport)方式导出,不推荐这种方式需要注意函数名的书写问题!
现在DLLTesth中有函数(采用__declspec(dllexport)方式导出)
#ifndef DLLTEST_H
#defineDLLTEST_H
//该宏完成在dll项目内部使用__declspec(dllexport)导出
//在dll项目外部使用时,用__declspec(dllimport)导入
//宏DLL_EXPORTS在cpp中定义
#ifdefDLL_EXPORTS
#defineDLL_EXPORTS __declspec(dllexport)
#else
#define DLL_EXPORTS __declspec(dllimport)
#endif
intDLL_EXPORTS Add(int a, int b);
intDLL_EXPORTS Sub(int a, int b);
intDLL_EXPORTS Divide(int a, int b);
#endif//DLLTEST_H
测试代码
typedefint(Add)(int a, int b);
typedefint(Sub)(int a, int b);
HINSTANCE hDLL;
Add Add_;//函数指针
//也可以采用hDLL =LoadLibrary(_T("D:/DLLTestdll"));
hDLL =LoadLibraryA(("D:/DLLTestdll"));//加载动态链接库DLLTestdll文件;
Add_ = (Add)GetProcAddress(hDLL,"Add@@YAHHH@Z");//!!!!获取函数地址
intresult = Add_(5, 8);
printf("5+8:%d\n",result);
FreeLibrary(hDLL);//卸载dll文件;
这里需要注意的是:GetProcAddress(hDLL,"函数名");中的函数名要是DLL中的函数名,这个函数名可以用PE Explorer软件查看
由于采用的是VC++处理函数名方式,所以
GetProcAddress(hDLL,"Add@@YAHHH@Z");// GetProcAddress(hDLL,"函数名");
而不是简单的“Add”,因为DLL中的函数名是结果VC++方式处理过的函数名
显示调用,最好采用extern “C”的方式导出DLL
所以采用隐式链接方式的时候,只加载需要的DLL,在附加依赖项中,只添加需要的DLL对于的lib,不要多加,否则会造成1加大程序启动时间 2内存浪费
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)