c加加中dll注入文件的易语言dll代码注入基本语法是什么,

C语言封装dll - CSDN博客
C语言封装dll
一、首先,使用vs2008创建windows32控制台程序,选择dll复选框,确定。
然后在stdafx.h头文件中声明导出函数,举例如下
__declspec(dllexport) int &add(int a ,int b);//add是函数名,可声明多个
__declspec(dllexport) int &sub(int a ,int b);
如果创建的是C++工程则需要在函数声明前加上extern &C&
变成: extern &C& __declspec(dllexport) int &add(int a ,int b);
extern &C& __declspec(dllexport) int &sub(int a ,int b);
接着在你创建的C文件中实现上述函数体,如下
int __declspec(dllexport) add(int a ,int b)
return a+b;
int __declspec(dllexport) sub(int a,int b)
return a-b;
这个是C++中,如果仅仅使用一个c文件实现dll,举例如下
#include &windows.h&
__declspec(dllexport) int &add(int a ,int b);
__declspec(dllexport) int &sub(int a ,int b);
BOOL APIENTRY DllMain( HMODULE hModule,
&DWORD &ul_reason_for_call,
&LPVOID lpReserved
switch (ul_reason_for_call)
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
return TRUE;
}//这段代码c++工程自动生成
__declspec(dllexport) int add(int a ,int b)
return a+b;
int __declspec(dllexport) sub(int a,int b)
return a-b;
二、C调用dll
在创建一个新的工程。把之前生成的dll文件拷贝入调用工程的debug文件夹下。如果想方便,就顺便把lib文件也拷贝到debug下,因为三要用。键入如下代码:
#include&stdio.h&
#include &windows.h&
int main()
typedef int (*ADD)(int ,int);//函数指针类型
HINSTANCE Hint = LoadLibrary(&adddll.dll&);//加载我们刚才生成的dll
ADD add = (ADD)GetProcAddress(Hint,&add&);//取得dll导出的add方法
printf(&%d&,add(3,4));
当提示错误error C2664: “LoadLibraryW”: 不能将参数 1 从“const char [13]”转换为“LPCWSTR” & &时,需要步骤三。
三、C调用lib,
把上述工程生成的lib文件拷入建立的工程下,然后在代码中加入如下语句
#pragma comment(lib,&adddllcpp.lib&)
extern int add(int ,int);//没有加这句而只加上面这句(或在工程设置里加上DLL.lib)会链接错误
extern int sub(int ,int);
注意:工程属性字符集必须改成“使用多字节字符集”。
本文已收录于以下专栏:
相关文章推荐
DLL也就是动态链接库,使用DLL编程的好处大家应当都知道了吧,可是怎么样来作呢,今天我就来说说。首先,你要确定你要导出那些个函数,然后你就在你要导出的函数名前加上下面一句话:
// 输出函数的...
一直在做linux编程,突然要移植到windows,摸索了好久,记录下,分三篇来记录:
1.用vs2010将C做成dll
2.c#做界面后,如何调用C语言函数/dll
3.c#程序的打包...
一、DLL的创建
创建项目: Win32->Win32项目,名称:MyDLL
选择DLL (D) ->完成.
1、新建头文件testdll.h
testdll.h代码如下:
在合作开发时,C#时常需要调用C++DLL,当传递参数时时常遇到问题,尤其是传递和返回字符串是,现总结一下,分享给大家:
VC++中主要字符串类型为:LPSTR,LPCSTR, LPCTSTR,...
如果熟悉windows的用户就会发现windows下有很多dll文件,但很多人不知道这些文件究竟是用来干什么的,为什么要做成dll文件。现在我就windows下的systems文件夹下的user32....
vs创建dll的过程:
DLL的空项目创建完成后,建立dll的头文件,代码如下:
#ifdef _myFirstDLL_H_
_myFirstDLL_H_
身为学渣,总是学完就忘,所以写下来方便自己以后查看,也是为其他小白提供一点思路。
参考的资料:http://blog.csdn.net/u/article/details/4130...
1.怎么封装自己的dll;
a.打开visual studio - 文件 - 新建 - 项目- 类库 - 名称MyTestDll;
b.右键Class1.cs - 修改为 TestDll.
...
他的最新文章
讲师:董岩
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)【图文】C基本语法_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
&&C基本语法
大小:794.50KB
登录百度文库,专享文档复制特权,财富值每天免费拿!
你可能喜欢在C++中嵌入汇编实现DLL注入
标 题:在C++中嵌入汇编实现DLL注入
作 者:stormxp
时 间:<font color="#11-02-21 23:24:59 链 接:
实现DLL注入的方法已经很多了,也都比较成熟,用的最多的方法是通过远程线程进行线程注入,然后导入Dll文件。远程线程里有两个关键技术需要解决,一个是全局变量和字符串的存取问题,另一个是地址重定位问题。如果用汇编来实现这两个问题是很简单的,但在高级语言中就显得有点笨拙了。以前有一篇用C++来实现这个技术的文章,但那篇文章用了一个变通的方法,即用局部变量来代替全局变量,在建立远程线程的时候把变量传给远程线程。这个方法可以说达到了一箭双雕的目的,因为局部变量是存在于堆栈中的,不存在绝对地址的调用问题,对局部变量的访问也就不存在地址重定位问题。但回头想想,那个方法还是没有能够突破C++的这些限制。笔者在参考了罗云彬的《windows环境下32位汇编语言程序设计》中线程隐藏那一章节后,提出了在C++中实现远程线程的方法。因为本文涉及到很多汇编方面的知识,所以我相信本文的意义不仅仅是提出一种DLL注入的方法,更重要的是对编程能力的训练和对加深对操作系统底层的理解。
&&高级语言的编译过程
&&C++中的变量分为以下几个情况:全局变量,字符串和局部变量。对于变量我们在用C++编程中定义了直接调用就可以,从来不用考虑这些变量在生成的二进制文件装入内存后是怎么样存储的,但在进行远程线程的操作时这些都是必须考虑的。实际上在编译时,编译器对变量和代码有着不同的处理,全局变量和字符串被放在了数据段中,局部变量存放于堆栈中,代码位于代码段中,而数据段,堆栈区,代码段在内存中是独立存放的,它们的地址并不连续。在编译时对全局变量和字符串的存取被修改为对绝对地址的调用,这个绝对地址是编译时确定的,在程序运行时由操作系统负责在该地址处分配内存并进行初始化。而编译器对局部变量的处理是将其修改为对堆栈的操作,这样局部变量的地址实际上依赖于栈寄存器,栈寄存器不同,其绝对地址也不同。
&&另外,高级语言中调用函数时,编译器作的处理如下:&
1.将需要传递的参数反向压入堆栈;
2.用call语句调用函数地址,执行该函数;
3.&&函数执行完成后恢复堆栈的平衡;
在上面三步的第二步中又可以分为几个小步:
1.&&把本句call指令的下一指令地址压入堆栈;
2.&&转到函数地址执行;
3.&&当遇到ret之类的返指令时从栈中弹出返回地址;
4.&&转到弹出的地址(也就是call语句的下句指令)继续执行。
现在在拿LoadLibrary来举个例子,该函数是windows中的一个API,位于Kernel32.dll中,其默认装载地址为7C801D7B。因为Kernel32.dll是常驻内存的,所以在一般情况下内存中的这个地址就是LoadLibrary的入口地址,但这不是绝对的。在C++中要调用这个函数我们可以这样写:
&&&&LoadLibrary(”Dll.dll”);&&&&&&
在汇编中就得这样写了:
&&&&Push&&&字符串”DLL.dll”在内存中的地址,通常这个地址位于数据区
&&&&Call&&&&LoadLibrary的入口地址,如7C801D7B
因为Windows中的API皆为标准调用约定,所以恢复堆栈的工作就由被调用的函数完成了。当然在C++中自定义的函数一般为C调用约定,如果调用自己写的函数你就要考虑恢复堆栈的问题了。最后说明一点,在汇编中调用API的返回值一般会放在寄存器eax中,所以要检测函数是否调用成功只要检测eax的值就可以了。
&&高级语言中远程线程遇到的问题
&&首先我们来回想一下远程线程的实现过程:
&&1.在程序中的某个地方写出远程线程代码;
2.用WriteProcessMemory将上步写的远程线程代码复制到目标进程;
3.用CreateRemoteThread建立远程线程,并使其运行。
现在仔细分析一下,不妨假设本进程为进程A,要注入的宿主进程为进程B。第一步中所写的远程线程代码位于A中,此时用到的全局变量和字符串在编译时生成的绝对地址是按进程A确定的,这些地址位于进程A的数据区,第二步复制代码时,我们把代码区的数据完整的复制到了进程B中,而数据区并没有被复制。被复制过来的代码要运行时同样要访问那些全局变量和字符串的绝对地址,在进程B中那个地址可能已经被其它进程占用,也可能是一些随机的数据,这样会造成访问出错。在汇编语言中可以在代码区中申请变量空间,在复制代码时这些变量也相应被复制过去,这样就不存在数据区绝对地址访问的问题。但C++中是不允许在代码区中申请变量空间的,所以如何让变量随代码一起被复制是第一个需要解决的问题。
其二,假如我们己经在代码区中成功的存放了变量。但编译器在编译时把对这个变量的存取修改为绝对地址的存取,这个地址同样是位于进程A中的。在进程B中申请内存空间时,这个空间的地址是不确定的,这样代码被复制到进程B中后对这个地址的存取还是会出错,其原理和上面是一样的。所以这就需要我们对这些变量进行地址重定位。
远程线程代码的实现
因为我们的目的就是要把自己的DLL文件导入到目标进程中,所以远程线程的代码相对来说比较简单,就是调用LoadLibrary,也就是上面举的例子中的代码。我们要在代码中保存的变量有两个,一个是LoadLibrary的地址(虽说这个地址基本上是固定的,但为了保险起见我们还是动态获取,并将其保存,否则就不需要这个变量了),另一个是保存DLL文件名的字符串。为了在写远程线程代码时,在代码区中为这两个变量分配内存,我们可以用空指令给这两个变量占位,复制到进程B中后再把它修改为真正的值。如:API的地址占四个字节,汇编中一个空指令nop占一个字节,所以我们就用四个nop来为其“申请”空间;我们的DLL文件名为”Dll.dll”,占七个字节,考虑到字符要以0作为结尾标记,共占8个字节,所以我们用8个nop来“申请”空间。
下一个问题是解决地址重定位问题,这个技术在病毒,木马等诸多方面有着广泛的应用,当然这个技术并不是由笔者实现,笔者也是通过学习得到的,在这里也简要介绍一下实现的原理。
先看下面这段代码:
1&&&&&&call&&&&relocal
2&&&&relocal:
3&&&&&&pop&&&&ebx
4&&&&&&sub&&&&ebx&,&offset&relocal
现在细细分析一下。第一句话执行时首先会把第三句运行时的地址(注意是运行时的地址,不是绝对地址,这个地址在进程A中与在进程B中是不一样的)压入堆栈,然后执行第三句,而第三句又把该地址弹出到寄存器ebx。第四句的offset&relocal,它在编译时被编译器修改为进程A中第三句的绝对地址,如果现在该段代码运行于进程B中,第四句相减执行完后ebx并不是0,而是这段代码在进程A中的地址偏移与在进程B中地址偏移之差!得到这个差值后,在进程B中每当访问含有绝对地址的变量时只要加上这个差值就可以得到正确地址。
好了,关键技术实现后远程线程的代码如下:
REMOTE_THREAD_BEGIN:&&&&&&//远程线程代码开始标记
&&&&//*******给LoadLibrary函数地址占位*******
LoadLibraryAddr:
&&&&//*******给FreeLibrary函数地址占位*******
FreeLibraryAddr:
&&&&//*******给动态链接库名占位*******
LibraryName:
&&&&//*******代码开始的真正位置*******
REMOTE_THREAD_CODE:
&&&&//*******实现地址重定位,ebx保存差值*******
&&&&call&&&&relocal
&&&&pop&&&&ebx
&&&&sub&&&&ebx&,&offset&relocal
&&&&//*******1.调用LoadLibrary*******
&&&&//*******1.1.压入LoadLibrary参数(动态链接库名)*******
&&&&mov&&&&eax&,&ebx&&&&&&&&&&
&&&&add&&&&eax&,&offset&LibraryName&&//变量地址加上ebx,实现地址重定位
&&&&push&&&&eax
&&&&//*******1.2.调用LoadLibrary*******
&&&&mov&&&&eax&,&ebx
&&&&add&&&&eax&,&offset&LoadLibraryAddr&&&&//同样实现地址重定位
&&&&mov&&&&eax&,&[eax]&&&&//从变量中取出LoadLibrary的地址
&&&&call&&&&eax
&&&&//*******1.3.检测是否成功,如果失败了就直接返回,防止程序异常*******
&&&&or&&&&eax&,&eax
&&&&jnz&&&&NEXT1&&&&&&//执行成功,跳转到位NEXT1继续执行
&&&&//&*******2.释放动态链接库*******
&&&&//&*******2.1.压入FreeLibrary参数*******
&&&&push&&&&eax
&&&&//&*******2.2.调用FreeLibrary*******
&&&&mov&&&&eax&,&ebx
&&&&add&&&&eax&,&offset&FreeLibraryAddr&&&&//地址重定位
&&&&mov&&&&eax&,&[eax]&&&&//从变量中取出FreeLibrary的地址
&&&&call&&&&eax
REMOTE_THREAD_END:
因为DLL文件在第一次被导入时会自动执行DllMain中的代码,所以我们把DLL中自己写的代码放在这个函数中,这样只要DLL文件被导入就可以执行代码了;如果不这样,我们还必须去获取DLL文件中的函数地址,那样会加大工作量,当然如果你不怕麻烦也可以去试试。
主程序的实现
其实远程线程代码实现后,本节的技术含量就相对低得多了。本段代码主要实现以下几个功能:
1.&&在宿主进程中申请代码空间;
2.&&把远程线程的代码复制到宿主进程中;
3.&&修正远程线程变量的值;
4.&&创建远程线程,使远程代码执行。
关键代码如下:
//*******1.&在宿主进程中申请代码空间*******
//*******1.1.&通过进程ID打开进程句柄,并获得进程句柄*******
&&HANDLE&&hSelectedProcH&&&&//保存宿主进程句柄
&&hSelectedProcHandle&=&OpenProcess(PROCESS_ALL_ACCESS&,&FALSE&,&
nSelectedThreadId);&&//进程ID的获取方法,完整的源代码中有介绍,这里就不介绍了
//*******1.2.得到远程线程代码长度,目的是得到要申请的空间的大小******
&&int&&&nRemoteThreadCodeL&&&&&&//保存代码长度
&&&&&&mov&&&&eax&,&offset&REMOTE_THREAD_END
&&&&&&mov&&&&ebx&,&offset&REMOTE_THREAD_BEGIN
&&&&&&sub&&&&eax&,&ebx&&&&//用代码结尾偏移减去开始的偏移,得到代码长度
&&&&&&mov&&&&nRemoteThreadCodeLength&,&eax
//*******1.3.在宿主进程中申请空间*******
&&LPVOID&&&pRemoteThreadA&&&&//保存申请空间的基址
&&pRemoteThreadAddr&=&VirtualAllocEx(hSelectedProcHandle&,&NULL&,&nRemoteThreadCodeLength&,&MEM_COMMIT,PAGE_EXECUTE_READWRITE);
//*******2.把远程线程的代码复制到宿主进程*******
//*******2.1.得到本进程中远程线程代码的起始地址*******
&&LPVOID&&pRemoteThreadCodeB&&//指向本进程中远程线程代码的起始位置
&&DWORD&&nWritenNum&,&&nS&&&&//临时变量
&&_asm&mov&&eax&,&offset&REMOTE_THREAD_BEGIN
&&_asm&mov&&pRemoteThreadCodeBuf&,&eax&&
//*******2.2.向宿主进程中复制代码*******
&&nSuccess&=&WriteProcessMemory(hSelectedProcHandle&,&pRemoteThreadAddr&,&pRemoteThreadCodeBuf&,&nRemoteThreadCodeLength&,&&nWritenNum);
//&*******3.修正远程线程中变量的值*******
//&*******3.1.首先获取两个关键函数的地址*******
&&HMODULE&hKernel32;
&&hKernel32&=&LoadLibrary(&Kernel32.dll&);
&&LPVOID&pLoadLibrary&,&pFreeL
&&pLoadLibrary&=&(LPVOID)GetProcAddress(hKernel32&,&&LoadLibraryA&);
&&pFreeLibrary&=&(LPVOID)GetProcAddress(hKernel32&,&&FreeLibrary&);
//&*******3.2.修正代码*******
&&PBYTE&pRemoteAddrM&&&&//在远程线程地址上移动的指针
&&pRemoteAddrMove&=&(PBYTE)pRemoteThreadA
//&*******3.2.1.修正LoadLibrary地址*******
&&nSuccess&=&WriteProcessMemory(hSelectedProcHandle&,&
&&&&pRemoteAddrMove&,&
&&&&&pLoadLibrary&,
&&&&&nWritenNum);
//*******3.2.2.修正FreeLibrary地址*******
&&pRemoteAddrMove&+=4;&&&&//定位到保存FreeLibrary的变量
&&nSuccess&=&WriteProcessMemory(hSelectedProcHandle&,
&&&&pRemoteAddrMove&,&
&&&&&pFreeLibrary&,
&&&&&nWritenNum);
//*******3.2.3.修正动态链接库名*******
&&char&szDllName[8]&=&{&Dll.dll&};&&&&//注意这里必须是8个字符,
//并且必须与你的DLL文件名相同
&&pRemoteAddrMove&+=4;
&&nSuccess&=&WriteProcessMemory(hSelectedProcHandle&,&
&&&&&&pRemoteAddrMove&,&
&&&&&&szDllName&,
&&&&&&8&,&
&&&&&&&nWritenNum);
&&//*******4.创建远程线程,使远程代码执行*******
&&//*******4.1.把指针移动到远程线程代码开始处*******
&&pRemoteAddrMove&+=8;
&&HANDLE&hRemoteThreadH&&&&//远程线程句柄
&&//&*******4.2.定义远程线程函数类型*******
&&typedef&unsigned&long&(WINAPI&*stRemoteThreadProc)(LPVOID);
&&stRemoteThreadProc&pRemoteThreadP
&&//&*******4.3.把入口地址赋给声明的函数*******
&&pRemoteThreadProc&=&(stRemoteThreadProc)pRemoteAddrM
&&//*******4.4.创建远程线程*******
&&hRemoteThreadHandle&=&CreateRemoteThread(hSelectedProcHandle&,&NULL&,&0&,&
&&&&pRemoteThreadProc&,&0&,&0&,&NULL);
&&因为本模块主要是调用一些API,这些API去查下资料就可以知道其用法,所以这里就不做详细介绍了。所附源代码为一个基于对话框的MFC程序,里面还有一个获取当前系统进程的模块,这里就不介绍其实现过程了。另外还附带一个简单的DLL工程作为测试。在运行程序时一定要把DLL文件放到系统搜索路径中,否则会因找不到DLL文件而失败。
至此所有功能模块已经介绍完毕,总体来说,这个方法实现了我们的预期功能,它的不足之处是实现起来比较繁琐,但从学习的角度来说不失为一个好方法。若文中有说的不到之处,还请各位高手们批评指正。
&&&&&&&&&文章为原创,发于黑防10年7期上,不知能不能加精,想要个邀请码。上传的附件
标 题:答复
作 者:wlksl
时 间:<font color="#11-02-22 10:50:07
&&为什么要嵌入汇编呢?用汇编并没有变的简单。个人觉得用c&还是很方便的!
//获得想要注入代码的进程的句柄
hProcess&=&OpenProcess(PROCESS_ALL_ACCESS,&FALSE,&dwProcessID);
if&(hProcess&==&NULL)
//计算DLL路径名需要的字节数
cch&=&1&+&strlen(szModuleName);
//在远程线程中为路径名分配空间
pszLibFileRemote&=&(PSTR)VirtualAllocEx(hProcess,&NULL,&cch,&MEM_COMMIT,&PAGE_READWRITE);
if&(pszLibFileRemote&==&NULL)
//将DLL的路径名复制到远程进程的内存空间
if&(!WriteProcessMemory(hProcess,&(PVOID)pszLibFileRemote,&(PVOID)szLibName,&cch,&NULL))
//获得LoadLibraryA在Kernel32.dll中的真正地址
pfnThreadRoutine&=&(PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT(&Kernel32&)),&&LoadLibraryA&);
if&(pfnThreadRoutine&==&NULL)
//创建远程线程,并通过远程线程调用用户的DLL文件
hThread&=&CreateRemoteThread(hProcess,&NULL,&0,&pfnThreadRoutine,&(LPVOID)pszLibFileRemote,&0,&NULL);
if&(hThread&==&NULL)}

我要回帖

更多关于 远程线程注入dll 代码 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信