如何获取NtReadVirtualMemory函数原始地址最好有代码啊能帮我解决问题我在追加300分如题 谢谢了

如何获取NtReadVirtualMemory函数原始地址最好有代码啊能帮我解决问题我在追加300分如题 谢谢了,第1张

这种问题你在问问上问不会有很好的结果的,我简单给你说说思路和原理 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内存浪费

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/12155267.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-21
下一篇 2023-05-21

发表评论

登录后才能评论

评论列表(0条)

保存