Dll注入方法之二

有了第一种方法,我们不难举一反三,由于原理是只需要我们的执行函数被写入到目标进程,所有相关的变量也在目标函数里,那么我们的函数就能被正确执行(前提是没有互相调用我们注入的函数,否则需要做地址处理。这也是为什么整个可执行文件注入时,要做很多重定位)。这里,我们进一步尝试,将LoadLibrary放在一个函数里,在同一个函数里,我们再调用一个MessageBox(这里只是一个测试,以后你可以调用任何你的函数,但必须要对地址进行处理)。

步骤一和步骤二:请参考Dll注入方法之一。

步骤三:书写需要被注入到目标进程的函数,这里我们先从最简单的naked函数开始,以汇编的形式注入。

#define PARAM_START 0x80000000
#define pfn_LoadLibraryA PARAM_START+1
#define pfn_MessageBoxA PARAM_START+2
#define szLibrary PARAM_START+3
#define szMsg PARAM_START+4
//定义上面这些唯一标识符,就像资源ID一样具有独特性,方便之后再缓冲中对地址进行修改
void __declspec(naked) YourFunction()
{
    __asm
    {
        push szLibrary
        mov eax, pfn_LoadLibraryA
        call eax //LoadLibraryA(szLibrary)
        push MB_OK
        push NULL
        push szMsg
        push NULL
        mov eax, pfn_MessageBoxA
        call eax //MessageBoxA(NULL,szMsg,NULL,MB_OK)
        retn //由于远程线程是创建的函数,所以需要构造返回指令让堆栈平衡
    }
}

步骤四:写一个函数代码段计算函数,为了计算YourFunction()这个函数的大小

	DWORD CodeSize(DWORD pfn_jmp)
	{
		byte *lpStartAddr;
		if (*(byte *)pfn_jmp==0xe9)
			lpStartAddr=(byte *)(*(DWORD *)(pfn_jmp+0x1)+pfn_jmp+0x5);
		else
			lpStartAddr=(byte *)pfn_jmp;//判断是否近跳还是远跳,至于为什么这样,各位要用ollydbg去看看,编译器在生成这些汇编代码时,是什么样的                              //由于篇幅有限,这里就不说反汇编基础了,自己去补充
		byte *StartCode=lpStartAddr;//处理jmp这条指令后得到的函数地址
		while (*lpStartAddr!=0xc3) //计算以retn指令结尾的函数
		{
			if (*lpStartAddr==0xc2 && *(lpStartAddr+1)==0x4)//由于默认只传入一个参数,并判断是否以ret4指令结尾的函数
			{
				lpStartAddr+=2;
				break;
			}
			lpStartAddr++;
		}
		return (DWORD)(lpStartAddr+1-StartCode);//返回函数字节大小
	}

步骤五:写一个YourFunction函数的执行代码复制到缓存区的函数

	byte *BufferCode(DWORD pfn_jmp)
	{
		codeSize=CodeSize(pfn_jmp);//步骤四的函数
		bufferCode=(byte *)malloc(codeSize);//为缓存区分配大小
		assert(bufferCode!=NULL);
		byte *lpStartAddr;
		if (*(byte *)pfn_jmp==0xe9)
			lpStartAddr=(byte *)(*(DWORD *)(pfn_jmp+0x1)+pfn_jmp+0x5);
		else
			lpStartAddr=(byte *)pfn_jmp;
		RtlCopyMemory(bufferCode,lpStartAddr,codeSize);
		//由于是nacked函数,所以不用对堆栈平衡进行处理,但第三种dll注入方法必须处理!
		return bufferCode;
	}

步骤六:注入代码

	BOOL ReplaceParamAddr(byte *buffer,DWORD dwOld,DWORD dwNew)
	{//这个函数是通过在buffer这个缓冲区搜索特征码,然后替换成新的数据(为了对地址进行调整)
		for (DWORD i=0;i<codeSize;i++)
		{
			if (*(DWORD *)&buffer[i]==dwOld)
			{
				*(DWORD *)&buffer[i]=dwNew;
				return TRUE;
			}
		}
		return FALSE;
	}

开始我们的注入代码

	BOOL InjectDll()
	{
		BOOL iRet=-1;
		HANDLE hRemoteProcess=OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_OPERATION|PROCESS_VM_WRITE,
			FALSE,GetProcessID(szInjectedExeFileName));//打开目标进程
		assert(hRemoteProcess!=INVALID_HANDLE_VALUE);
		BufferCode((DWORD)YourFunction);//步骤五的函数
		ReplaceParamAddr(bufferCode,pfn_LoadLibraryA,(DWORD)LoadLibraryA);//步骤六的函数,将唯一标识符替换为真实地址
		ReplaceParamAddr(bufferCode,pfn_MessageBoxA,(DWORD)MessageBoxA);
		//写入字符串到目标进程
		const char *szParameter="This is a Parameter!";
		PVOID lpString=VirtualAllocEx(hRemoteProcess,NULL,strlen(szDll)+strlen(szParameter)+2,
			MEM_COMMIT,	PAGE_READWRITE);
		assert(lpString!=NULL);
		WriteProcessMemory(hRemoteProcess,lpString,(LPVOID)szDll,strlen(szDll)+1,NULL);
		WriteProcessMemory(hRemoteProcess,(LPVOID)((DWORD)lpString+strlen(szDll)+1),
			(LPVOID)szParameter, strlen(szParameter)+1,NULL);
		ReplaceParamAddr(bufferCode,szLibrary,(DWORD)lpString);//同理,替换为字符串在目标进程中的地址
		ReplaceParamAddr(bufferCode,szMsg,(DWORD)lpString+strlen(szDll)+1);
		//写入执行代码到目标进程
		PVOID lpBaseAddr=VirtualAllocEx(hRemoteProcess,NULL,codeSize,MEM_COMMIT,
			PAGE_EXECUTE_READWRITE);
		assert(lpBaseAddr!=NULL);
		iRet=WriteProcessMemory(hRemoteProcess,lpBaseAddr,(LPVOID)bufferCode,codeSize,NULL);
		assert(iRet!=0);
		CreateRemoteThread(hRemoteProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)lpBaseAddr,
			0, NULL, NULL);
		return iRet;
	}

xp下测试效果图(win10同样测试通过,理由和”Dll注入方法之一“一样,注意字符串问题)  

按下确定后,会继续再弹出一个窗口

时间: 2024-10-11 21:05:55

Dll注入方法之二的相关文章

Dll注入方法-钩子

HHOOK SetWindowsHookEx(int idHook,HOOKPROC lpfn, HINSTANCE hMod, DWORD dwThreadId); idHook: 钩子类型lpfn:钩子过程的指针 ,也即拦截到指定系统消息后的预处理过程,定义在DLL中hMod:应用程序实例的句柄 如果是全局钩子, hInstance是DLL句柄(DllMain中给的模块地址.就是包含HookProc的动态库加载地址.否则给0就可以了,即勾自己.dwThreadId:要安装钩子的线程ID ,指

反射式DLL注入--方法

使用RWX权限打开目标进程,并为该DLL分配足够大的内存. 将DLL复制到分配的内存空间. 计算DLL中用于执行反射加载的导出的内存偏移量. 调用CreateRemoteThread(或类似的未公开的API函数RtlCreateUserThread)在远程进程中开始执行,使用反射加载函数的偏移地址作为入口点. 反射加载函数使用适当的CPU寄存器查找目标进程的进程环境块(PEB),并使用它查找内存中的地址kernel32.dll以及任何其他所需的库. 解析的KERNEL32出口目录中找到所需的AP

Windows系统的dll注入

声明:这篇博客原为本人在CSDN上发布的,但是CSDN这个网站违背了本人的分享和开源精神,另外CSDN的广告满天飞.审核重重(所有的下载必须使用CSDN下载,而下载需要积分,这严重违背本人的无私分享精神.开源精神.),即使审核通过也会不定时进行重新审核,CSDN的这些操作严重影响了本人的博客管理.因此,本着无私分享精神.开源精神.轻松使用原则,本人摒弃了CSDN,并将博文重新编辑并发布在博客园网站上,而原博文作删除处理! 一.什么是dll注入 在Windows操作系统中,运行的每一个进程都生活在

经典的就要转载:另类DLL注入法

转自:http://blog.csdn.net/onevs1/article/details/5692680 输入法注入[转帖] 百度搜来的.论述比较详细,不过我还没搞懂!就原文贴一下了! ----------------------------------------------------------------------------------------------以下是原文 Ring3下注入DLL的另类方法,能过杀软和游戏NP(源码)       注入DLL是做全局钩子或者拦截类软件

[转]Dll注入经典方法完整版

Pnig0s1992:算是复习了,最经典的教科书式的Dll注入. 总结一下基本的注入过程,分注入和卸载 注入Dll: 1,OpenProcess获得要注入进程的句柄 2,VirtualAllocEx在远程进程中开辟出一段内存,长度为strlen(dllname)+1; 3,WriteProcessMemory将Dll的名字写入第二步开辟出的内存中. 4,CreateRemoteThread将LoadLibraryA作为线程函数,参数为Dll的名称,创建新线程 5,CloseHandle关闭线程句

&lt;ReversingEngineering&gt;关于windows32位系统下的dll注入技术经验汇

上个学期把自己闷在图书馆一直在看关于逆向工程技术方面的书,从入门到初级,现在也敢说自己一条腿已经迈进了这片知识的大门里,因为该博客刚开通先将一些经验记录下来,也是留给自己一方面做个参照. <逆向工程核心原理>((韩)李承远 )<Reversing:逆向工程揭密(电子工业出版社)><黑客反汇编揭密>((俄)卡巴斯基 ) dll注入技术是一门逆向工程中非常基础非常初步的技术,也是打开大门的钥匙,逆向破解的前提条件.API勾取 ,Rootkit进程隐藏都需要dll注入为先决条

反病毒攻防研究第010篇:DLL注入(中)——DLL注入与卸载器的编写

一.前言 我在上一篇文章中所讨论的DLL利用方法,对于DLL文件本身来说是十分被动的,它需要等待程序的调用才可以发挥作用.而这次我打算主动出击,编写DLL注入与卸载器,这样就可以主动地对进程进行注入的操作了,从而更好地模拟现实中恶意代码的行为. 二.DLL注入的原理 如果想让DLL文件强制注入某个进程,那么就需要通过创建远程线程来实现.这里需要注意的是,所谓的"远程线程",并不是跨计算机的,而是跨进程的.举例来说,进程A在进程B中创建一个线程,这就叫做远程线程.从根本上说,DLL注入技

反病毒攻防研究第011篇:DLL注入(下)——无DLL的注入

一.前言 一般来说,想要将自己编写的程序注入到其它进程中,是必须要使用DLL文件的,这种方法已经在上一篇文章中讨论过了.但是事实上,可以不依赖于DLL文件来实现注入的.只不过这种方法不具有通用性,没有DLL注入那样灵活,因为它需要把代码写入"注入程序"中,一旦想要注入的内容发生了变化,就需要重写整个"注入程序".而不像DLL注入那样,只要修改DLL程序即可.即便如此,无DLL进行注入的方式,也是一种值得讨论的方法. 二.无DLL注入的基本原理 在注入与卸载方面,无论

反病毒攻防研究第009篇:DLL注入(上)——DLL文件的编写

一.前言 我之前所编写的用于模拟计算机病毒的对话框程序都是exe文件,所以运行时必将会产生一个进程,产生进程就非常容易被发现.而为了不被发现,可以选择将对话框程序创建为DLL文件.这种文件会加载到已有进程的地址空间中,这样就不会再次创建出进程,隐蔽性相对较好,DLL注入也是恶意程序总会使用的手段.这次我带算用几篇文章的篇幅来论述DLL注入的问题,而这篇文章就首先来讨论一下如何把我之前的对话框程序改写为DLL文件. 二.编写对话框DLL程序 这里我依旧使用VC++6.0,创建一个简单的Win32