实现远程代码注入

原创 2016年08月28日 16:39:09

前面我写过DLL的注入代码(详见:DLL注入与卸载),但是也并非就一定要另外实现一个动态链接库再注入我们的所需操作。这次我们就直截了当一点,直接在目标进程中注入我们所需的代码来实现操控。

要在目标进程中完成一定的功能,当然需要调用相关的API函数了,只是这次我们要使用的API出现在不同的DLL中。Kernel32.dll文件在每个进程中的地址是相同的,但这并不代表其他DLL文件在每个进程中的地址也是一样的,我相信大家都懂得。由此,我们在目标进程中使用API时,就需要用到LoadLibrary()函数和GetProcAddress()函数动态调用每个用到的API。我们可以把将要用到的API函数和对应API所在的DLL封装到一个结构体,然后写入目标进程中。另外将需要远程执行的代码也写入目标进程的内存空间,最后就可以调用CreateRemoteThread()函数将先前的“伏笔”都调用起来了(*^-^*)

下面我们就实现一个让目标进程弹出提示框的程序。当然,该程序并没有什么实际效用,但是相信大家能够从中得到些许启发,嘻嘻。

首先,先热热身,做一些预备工作:

#define STRLEN 20
//自定义结构体用于数据写入
typedef struct _DATA
{
	DWORD dwLoadLibrary;
	DWORD dwGetProcAddress;
	DWORD dwGetModuleHandle;
	DWORD dwGetModuleFileName;

	char User32Dll[STRLEN];
	char MessageBox[STRLEN];
	char Str[STRLEN];
}DATA, *PDATA;

上述结构体中保存了LoadLibraryA()、GetProcAddress()、GetModuleHandle()、和GetModuleFileName()函数的地址。这四个函数都隶属于Kernel32.dll中,这意味着我们可以在注入之前获得(因为每个进程中的相应函数的地址都是一样的嘛)。User32Dll中保存“User32.dll”字符串,因为我们要用到MessageBoxA()函数,而该函数是User32.dll的导出函数。MessageBox中保存我们将以调用的函数名“MessageBoxA”,而Str中则保存着通过MessageBoxA()函数弹出的字符串。

对结构体进行相关初始化操作的函数如下:

void CMyDlg::InjectCode(DWORD dwPid)
{//此处需要进程id作为参数,取得的方法可参考DLL注入相关介绍,我就不再重复了
    //打开进程并获取进程句柄
    HANDLEhProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
 
    if(NULL== hProcess)
       return;
 
    DATAData = {0};
 
    //获取kernel32.dll中相关的导出函数
    Data.dwLoadLibrary= (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"),
                                              "LoadLibraryA");
    Data.dwGetProcAddress= (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"),
                                              "GetProcAddress");
    Data.dwGetModuleHandle= (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"),
                                              "GetModuleHandleA");
    Data.dwGetModuleFileName= (DWORD)GetProcAddress(GetModuleHandle("kernel32.dll"),
                                              "GetModuleFileNameA");
    //需要的其他dll和导出函数
    lstrcpy(Data.User32Dll,"user32.dll");
    lstrcpy(Data.MessageBox,"MessageBoxA");
    //提示字符串
    lstrcpy(Data.Str,"Code Inject !!!");
 
    //在目标进程中申请空间
    LPVOIDlpData = VirtualAllocEx(hProcess, NULL, sizeof(Data),
                     MEM_COMMIT,PAGE_EXECUTE_READWRITE);
    DWORDdwWriteNum = 0;
    WriteProcessMemory(hProcess,lpData, &Data,sizeof(Data), &dwWriteNum);
 
    //在目标进程空间中申请用于保存代码的长度
    WORDdwFunSize = 0x4000;
    LPVOIDlpCode = VirtualAllocEx(hProcess, NULL, dwFunSize,
                     MEM_COMMIT,PAGE_EXECUTE_READWRITE);
 
    WriteProcessMemory(hProcess,lpCode,&RemoteThreadProc,
                     dwFunSize,&dwWriteNum);
    HANDLEhThread = CreateRemoteThread(hProcess, NULL, 0,
                     (LPTHREAD_START_ROUTINE)lpCode,
                     lpData,0, NULL);
    WaitForSingleObject(hThread,INFINITE);
 
    CloseHandle(hThread);
    CloseHandle(hProcess);
}

以上代码对结构体的变量进行了初始化,并且将线程函数写入目标进程空间的内存中。用到的相关API在文章开始处提到的博客中都有介绍,我是一个重视代码重用的程序员,所以…

下面提供线程函数的实现参考:

DWORD WINAPI RemoteThreadProc(LPVOID lpParam)
{
	PDATA pData = (PDATA)lpParam;

	//定义API函数原型
	HMODULE (__stdcall *MyLoadLibrary)(LPCTSTR);
	FARPROC (__stdcall *MyGetProcAddress)(HMODULE, LPCSTR);
	HMODULE (__stdcall *MyGetModuleHandle)(LPCTSTR);
	int (__stdcall *MyMessageBox)(HWND, LPCTSTR, LPCTSTR, UINT);
	DWORD (__stdcall *MyGetModuleFileName)(HMODULE, LPTSTR, DWORD);

	//对各函数地址进行赋值
	MyLoadLibrary = (HMODULE (__stdcall *)(LPCTSTR))pData->dwLoadLibrary;
	MyGetProcAddress = (FARPROC (__stdcall *)(HMODULE, LPCSTR))pData->dwGetProcAddress;
	MyGetModuleHandle = (HMODULE (__stdcall *)(LPCTSTR))pData->dwGetModuleHandle;
	MyGetModuleFileName = (DWORD (__stdcall *)(HMODULE, LPTSTR, DWORD))pData->dwGetModuleFileName;

	//加载user32.dll
	HMODULE hModule = MyLoadLibrary(pData->User32Dll);
	//获得MessageBoxA的函数地址
	MyMessageBox = (int (__stdcall *)(HWND, LPCTSTR, LPCTSTR, UINT))
						MyGetProcAddress(hModule, pData->MessageBox);
	char szModuleFileName[MAX_PATH] = {0};
	MyGetModuleFileName(NULL, szModuleFileName, MAX_PATH);

	MyMessageBox(NULL, pData->Str, szModuleFileName, MB_OK);

	return 0;
}

主要的代码就是这样,编译链接并运行程序,启动一个目标进程作为注入靶子,然后填入相应的进程名进行注入。VC6中,如果是debug版本将会报错,但是使用release版本就可以啦。原因是VC6的默认编译器是debug版本,这样会加入很多调试信息。而某些调试信息并不存在于代码之中,而是在其他DLL模块内。这样当执行到调试相关的代码时会访问不存在的DLL模块中的代码,如是,就导致了错误的发生。

VC6转到release版本的方法:

vc右上角菜单栏或工具栏的空白处右键,选上Build项,使build工具栏可见,在Build工具栏上就可以选择工程的Debug或Release版本。

或者菜单栏Build->BatchBuild,在弹出的对话框中选择编译哪个版本,或者两个版本都编译。

好了,看一些运行后的效果吧。




相关的进程名可以通过任务管理器来获取哟。



版权声明:本文为博主原创文章,未经博主允许不得转载。

远程代码注入

除了通常的通过DLL注入来向其他进程插入代码,还有一种方法,就是直接想目标进程插入代码,此方法与前者相比之下有以下几个优点: 1、由于不用注入DLL,所以是目标进程占用的内存更小 2、由于没有注入...
  • qq_20977145
  • qq_20977145
  • 2016年06月29日 19:39
  • 491

远程线程注入的原理和实现方法

转载:http://blog.csdn.net/whatday/article/details/8975930 一、远程线程注入基本原理 远程线程注入——相信对Windows底层编程和系统安全熟悉...
  • heluan123132
  • heluan123132
  • 2015年06月08日 14:36
  • 5934

GetModuleHandle

获取已经载入进程空间的模块句柄。 函数声明: HMODULE WINAPI GetModuleHandle( _In_opt_ LPCTSTR lpModuleName ); 参数: LP...
  • huhaoxuan2010
  • huhaoxuan2010
  • 2017年09月13日 16:19
  • 93

代码注入之远程线程篇

引子           前些日子由于项目要求,在网上到处找资料,于无意中发现了 CodeProject 上的一篇很老的文章,文章标题为: Three Ways to Inject Your C...
  • qq1978366308
  • qq1978366308
  • 2016年04月10日 18:04
  • 1245

向其他进程注入代码的三种方法

转自:http://blog.sina.com.cn/s/blog_4ad042e50102e6a2.html 原版地址:http://www.codeproject.com/thr...
  • qq229596421
  • qq229596421
  • 2016年10月11日 20:24
  • 2513

windows-CODE注入(远程线程注入)

远程线程注入
  • u013761036
  • u013761036
  • 2016年08月14日 17:25
  • 2729

使用远程线程制作不死进程

远程线程指把当前进程部分代码注入到其他进程做为线程执行,虽然钩子程序能挂钩其他程序的消息,但钩子程序退出,注入的dll也就退出了,而远程线程不会 随着本地进程退出而结束。而且可以处理更多的事情,而不局...
  • mynote
  • mynote
  • 2008年01月28日 08:17
  • 482

向其他进程注入代码的三种方法

目录: ●导言 ●Windows 钩子(Hooks) ●CreateRemoteThread 和LoadLibrary 技术 ○进程间通讯 ●CreateRemoteThread 和 WritePro...
  • wzsy
  • wzsy
  • 2008年10月07日 16:47
  • 1555

向其他进程注入代码的三种方法

原版地址:http://www.codeproject.com/threads/winspy.asp?df=100&forumid=16291&select=1025152&msg=1025152下载...
  • iiprogram
  • iiprogram
  • 2006年01月13日 11:16
  • 1999

C++远程DLL注入

这是个很古老的DLL注入技术,采用的是创建远程线程的方式。将LdadLibraryA的函数地址当做线程的回调地址,线程参数采用待注入DLL的绝对路径值。这个参数我们得采用VirtualAllocEx和...
  • fzuim
  • fzuim
  • 2017年06月28日 16:53
  • 366
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:实现远程代码注入
举报原因:
原因补充:

(最多只允许输入30个字)