Ring3下的DLL注入(NtCreateThreadEx + LdrLoadDll方式实现,可以注入系统进程)
工具介绍及使用请移步:http://blog.csdn.net/sunflover454/article/details/50441014
本文首发在零日安全论坛:http://www.jmpoep.com/thread-833-1-1.html
使用NtCreateThreadEx + LdrLoadDll方式实现远程线程注入的特色在于比一般的远程线程注入稳定,可以注入系统进程,服务进程等。
核心源代码如下,完整源代码,请在文章末尾下载。
- //OD跟踪,发现最后调用的是NtCreateThreadEx,所以这里手动调用
- HANDLE Cx64Inject::MyCreateRemoteThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf)
- {
- HANDLE hThread = NULL;
- FARPROC pFunc = NULL;
- if( IsVistaOrLater())// Vista, 7, Server2008
- {
- pFunc = GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtCreateThreadEx");
- if( pFunc == NULL )
- {
- MyOutputDebugStringA("MyCreateRemoteThread() : GetProcAddress(\"NtCreateThreadEx\") 调用失败!错误代码: [%d]", GetLastError());
- return NULL;
- }
- ((_NtCreateThreadEx64)pFunc)(&hThread,0x1FFFFF,NULL,hProcess,pThreadProc,pRemoteBuf,FALSE,NULL,NULL,NULL,NULL);
- if( hThread == NULL )
- {
- MyOutputDebugStringA("MyCreateRemoteThread() : NtCreateThreadEx() 调用失败!错误代码: [%d]", GetLastError());
- return NULL;
- }
- }
- else// 2000, XP, Server2003
- {
- hThread = CreateRemoteThread(hProcess,NULL,0,pThreadProc,pRemoteBuf,0,NULL);
- if( hThread == NULL )
- {
- MyOutputDebugStringA("MyCreateRemoteThread() : CreateRemoteThread() 调用失败!错误代码: [%d]", GetLastError());
- return NULL;
- }
- }
- if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) )
- {
- MyOutputDebugStringA("MyCreateRemoteThread() : WaitForSingleObject() 调用失败!错误代码: [%d]", GetLastError());
- return NULL;
- }
- return hThread;
- }

//OD跟踪,发现最后调用的是NtCreateThreadEx,所以这里手动调用
HANDLE Cx64Inject::MyCreateRemoteThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf)
{
HANDLE hThread = NULL;
FARPROC pFunc = NULL;
if( IsVistaOrLater())// Vista, 7, Server2008
{
pFunc = GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtCreateThreadEx");
if( pFunc == NULL )
{
MyOutputDebugStringA("MyCreateRemoteThread() : GetProcAddress(\"NtCreateThreadEx\") 调用失败!错误代码: [%d]", GetLastError());
return NULL;
}
((_NtCreateThreadEx64)pFunc)(&hThread,0x1FFFFF,NULL,hProcess,pThreadProc,pRemoteBuf,FALSE,NULL,NULL,NULL,NULL);
if( hThread == NULL )
{
MyOutputDebugStringA("MyCreateRemoteThread() : NtCreateThreadEx() 调用失败!错误代码: [%d]", GetLastError());
return NULL;
}
}
else// 2000, XP, Server2003
{
hThread = CreateRemoteThread(hProcess,NULL,0,pThreadProc,pRemoteBuf,0,NULL);
if( hThread == NULL )
{
MyOutputDebugStringA("MyCreateRemoteThread() : CreateRemoteThread() 调用失败!错误代码: [%d]", GetLastError());
return NULL;
}
}
if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) )
{
MyOutputDebugStringA("MyCreateRemoteThread() : WaitForSingleObject() 调用失败!错误代码: [%d]", GetLastError());
return NULL;
}
return hThread;
}
- //在目标进程中创建线程并注入dll
- BOOL Cx64Inject::InjectDll(DWORD dwProcessId,LPCWSTR lpcwDllPath)
- {
- BOOL bRet = FALSE;
- HANDLE hProcess = NULL, hThread = NULL;
- LPVOID pCode = NULL;
- LPVOID pThreadData = NULL;
- __try
- {
- if(!EnableDebugPrivilege())
- {
- MyOutputDebugStringA("InjectDll() : EnableDebugPrivilege() 调用失败!错误代码: [%d]", GetLastError());
- return -1;
- }
- //打开目标进程;
- hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwProcessId);
- DWORD dwError = GetLastError();
- if (hProcess == NULL)
- __leave;
- //申请空间,把我们的代码和数据写入目标进程空间里;
- //写入数据;
- THREAD_DATA data;
- HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
- data.fnRtlInitUnicodeString = (pRtlInitUnicodeString)GetProcAddress(hNtdll,"RtlInitUnicodeString");
- data.fnLdrLoadDll = (pLdrLoadDll)GetProcAddress(hNtdll,"LdrLoadDll");
- memcpy(data.DllName, lpcwDllPath, (wcslen(lpcwDllPath) + 1)*sizeof(WCHAR));
- data.DllPath = NULL;
- data.Flags = 0;
- data.ModuleHandle = INVALID_HANDLE_VALUE;
- pThreadData = VirtualAllocEx(hProcess, NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
- if (pThreadData == NULL)
- __leave;
- BOOL bWriteOK = WriteProcessMemory(hProcess, pThreadData,&data,sizeof(data), NULL);
- if (!bWriteOK)
- __leave;
- MyOutputDebugStringA("pThreadData = 0x%p", pThreadData);
- //写入代码;
- DWORD SizeOfCode = (DWORD)ThreadProcEnd - (DWORD)ThreadProc;
- pCode = VirtualAllocEx(hProcess, NULL, SizeOfCode, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
- if (pCode == NULL)
- {
- MyOutputDebugStringA("InjectDll() : pCode = VirtualAllocEx() 调用失败!错误代码: [%d]", GetLastError());
- __leave;
- }
- bWriteOK = WriteProcessMemory(hProcess, pCode, (PVOID)ThreadProc, SizeOfCode, NULL);
- if (!bWriteOK)
- __leave;
- MyOutputDebugStringA("pCode = 0x%p", pCode);
- //创建远程线程,把ThreadProc作为线程起始函数,pThreadData作为参数;
- hThread = MyCreateRemoteThread(hProcess, (LPTHREAD_START_ROUTINE)pCode, pThreadData);
- if (hThread == NULL)
- __leave;
- //等待完成;
- WaitForSingleObject(hThread, INFINITE);
- bRet = TRUE;
- }
- __finally
- {
- if (pThreadData != NULL)
- VirtualFreeEx(hProcess, pThreadData, 0, MEM_RELEASE);
- if (pCode != NULL)
- VirtualFreeEx(hProcess, pCode, 0, MEM_RELEASE);
- if (hThread != NULL)
- CloseHandle(hThread);
- if (hProcess != NULL)
- CloseHandle(hProcess);
- }
- return bRet;
- }

//在目标进程中创建线程并注入dll
BOOL Cx64Inject::InjectDll(DWORD dwProcessId,LPCWSTR lpcwDllPath)
{
BOOL bRet = FALSE;
HANDLE hProcess = NULL, hThread = NULL;
LPVOID pCode = NULL;
LPVOID pThreadData = NULL;
__try
{
if(!EnableDebugPrivilege())
{
MyOutputDebugStringA("InjectDll() : EnableDebugPrivilege() 调用失败!错误代码: [%d]", GetLastError());
return -1;
}
//打开目标进程;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwProcessId);
DWORD dwError = GetLastError();
if (hProcess == NULL)
__leave;
//申请空间,把我们的代码和数据写入目标进程空间里;
//写入数据;
THREAD_DATA data;
HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
data.fnRtlInitUnicodeString = (pRtlInitUnicodeString)GetProcAddress(hNtdll,"RtlInitUnicodeString");
data.fnLdrLoadDll = (pLdrLoadDll)GetProcAddress(hNtdll,"LdrLoadDll");
memcpy(data.DllName, lpcwDllPath, (wcslen(lpcwDllPath) + 1)*sizeof(WCHAR));
data.DllPath = NULL;
data.Flags = 0;
data.ModuleHandle = INVALID_HANDLE_VALUE;
pThreadData = VirtualAllocEx(hProcess, NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (pThreadData == NULL)
__leave;
BOOL bWriteOK = WriteProcessMemory(hProcess, pThreadData,&data,sizeof(data), NULL);
if (!bWriteOK)
__leave;
MyOutputDebugStringA("pThreadData = 0x%p", pThreadData);
//写入代码;
DWORD SizeOfCode = (DWORD)ThreadProcEnd - (DWORD)ThreadProc;
pCode = VirtualAllocEx(hProcess, NULL, SizeOfCode, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (pCode == NULL)
{
MyOutputDebugStringA("InjectDll() : pCode = VirtualAllocEx() 调用失败!错误代码: [%d]", GetLastError());
__leave;
}
bWriteOK = WriteProcessMemory(hProcess, pCode, (PVOID)ThreadProc, SizeOfCode, NULL);
if (!bWriteOK)
__leave;
MyOutputDebugStringA("pCode = 0x%p", pCode);
//创建远程线程,把ThreadProc作为线程起始函数,pThreadData作为参数;
hThread = MyCreateRemoteThread(hProcess, (LPTHREAD_START_ROUTINE)pCode, pThreadData);
if (hThread == NULL)
__leave;
//等待完成;
WaitForSingleObject(hThread, INFINITE);
bRet = TRUE;
}
__finally
{
if (pThreadData != NULL)
VirtualFreeEx(hProcess, pThreadData, 0, MEM_RELEASE);
if (pCode != NULL)
VirtualFreeEx(hProcess, pCode, 0, MEM_RELEASE);
if (hThread != NULL)
CloseHandle(hThread);
if (hProcess != NULL)
CloseHandle(hProcess);
} return bRet;
}
以上是远程线程注入类的两个核心函数,下面是调用实例:
- Cx64Inject inject;
- if (inject.InjectDll(g_dwPID,g_szDllPath))
- {
- ::MessageBox(NULL,L"注入成功",L":)",MB_ICONINFORMATION);
- }
- else
- {
- ::MessageBox(NULL,L"注入失败!",L"失败",MB_ICONERROR);
- }

Cx64Inject inject;
if (inject.InjectDll(g_dwPID,g_szDllPath))
{
::MessageBox(NULL,L"注入成功",L":)",MB_ICONINFORMATION);
}
else
{
::MessageBox(NULL,L"注入失败!",L"失败",MB_ICONERROR);
}
封装成类了,使用起来很简单的。
有一点需要注意的是x64注入的意思是只能将64位dll注入64位进程。
x86注入的意思是32位dll注入32位进程。
源代码下载:
DLL注入工具x86Inject_v1.2完整源代码(VS2010)下载地址:http://download.csdn.net/detail/sunflover454/9385421
DLL注入工具x64Inject_v1.1完整源代码(VS2010)下载地址:http://download.csdn.net/detail/sunflover454/9385408
相关下载:
DLL注入工具成品(x86)下载地址:http://download.csdn.net/detail/sunflover454/9385346
DLL注入工具成品(x64)下载地址:http://download.csdn.net/detail/sunflover454/9385355
转载请注明出处,谢谢!
原帖地址:http://blog.csdn.net/sunflover454/article/details/50441146
jpg改rar
Ring3下的DLL注入(NtCreateThreadEx + LdrLoadDll方式实现,可以注入系统进程)的更多相关文章
- win7下将dll文件的打开方式改回系统默认
打开注册表,定位到HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.dll把除OpenWit ...
- 表达式SpEL方式的属性注入
-----------------------siwuxie095 表达式 SpEL 方式的属性注入 表达式 SpEL 方式的属性注入是 Spring 3.x 版本后提供的方式 1.编写一个普通类 B ...
- 命名空间p方式的属性注入
---------------------siwuxie095 命名空间 p 方式的属性注入 命名空间 p 方式的属性注入是 Spring 2.x 版本后提供的方式 1.编写一个普通类 Book.ja ...
- war包部署在tomcat下,使用windows service服务方式启动tomcat服务器,在包含调用dll的模块,报dll找不到问题的解决办法
问题描述: 开发了一个需要调用dll的java web程序,在idea开发环境下运行调试没问题,可以正常运行,在tomcat/bin下,运行批处理startup.bat,启动tomcat服务器,也可以 ...
- Spring依赖注入三种方式详解
在讲解Spring依赖注入之前的准备工作: 下载包含Spring的工具jar包的压缩包 解压缩下载下来的Spring压缩包文件 解压缩之后我们会看到libs文件夹下有许多jar包,而我们只需要其中的c ...
- dll的加载方式主要分为两大类,显式和隐式链接
之前简单写过如何创建lib和dll文件及简单的使用(http://blog.csdn.net/betabin/article/details/7239200).现在先再深入点写写dll的加载方式. d ...
- Ring3下干净的强行删除文件
在某公司实习完,再次回到寝室.还是在学校好. 实习期间的给我的任务就是为项目添加一个强行删除的模块. 背景是硬盘上存储空间不够时,需要删掉老的文件,如果这时后,老的文件被打开了,没有关掉,就无法删除. ...
- Spring的几种注入bean的方式
在Spring容器中为一个bean配置依赖注入有三种方式: · 使用属性的setter方法注入 这是最常用的方式: · 使用构造器注入: · 使用Filed注入(用于注解方式). 使用属性的se ...
- 深入Delphi下的DLL编程
深入Delphi下的DLL编程 作者:岑心 引 言 相信有些计算机知识的朋友都应该听说过“DLL”.尤其是那些使用过windows操作系统的人,都应该有过多次重装系统的“悲惨”经历——无论再怎样小心, ...
随机推荐
- Leetcode 39. Combination Sum
Given a set of candidate numbers (C) (without duplicates) and a target number (T), find all unique c ...
- npm 使用记录
在 Mint 下安装 pencil,折腾半天,发现它对 firefox 的支持,只到 46.0 .本来打算研究下怎么用 xulrunner 来跑 pencil 这个 web 应用,查看项目资源的时候, ...
- WKWebView与JS交互,UIWebView+JavascriptCore和JS交互
最近一直在做有关Swift和JavaScript交互的程序,所以有关UIWebView和WKWebView在使用上的差别在此总结下: UIWebView: (1)创建 var webView: UIW ...
- [bigdata] 使用Flume hdfs sink, hdfs文件未关闭的问题
现象: 执行mapreduce任务时失败 通过hadoop fsck -openforwrite命令查看发现有文件没有关闭. [root@com ~]# hadoop fsck -openforwri ...
- C#直接赋值和反射赋值(无GC)的性能比较
using System; using System.Reflection; using System.Diagnostics; using System.Runtime.InteropService ...
- codevs1021 玛丽卡
题目描述 Description 麦克找了个新女朋友,玛丽卡对他非常恼火并伺机报复. 因为她和他们不住在同一个城市,因此她开始准备她的长途旅行. 在这个国家中每两个城市之间最多只有一条路相通,并且我们 ...
- tomcat乱码原因--基本的编码问题
tomcat乱码原因:在学习servlet时候,经常会遇到中文乱码的问题,网上查只知道如何设置不乱码,其中的原理不是很明白.我认为明白其中的原理,乱码问题就很容易解决 tomcat乱码解决方法: po ...
- [Kerberos] User Ticket Management
Kerberos客户端常用命令包括 kinit, klist, kdestroy, and kpasswd,用户使用这些命令管理自己的 ticket. 此外,每台运行Kerberos的机器应该都配置/ ...
- 编译安装 Zend Opcache 缓存Opcache,加速 PHP
Optimizer+ 是 Zend 开发的闭源但可以免费使用的 PHP 优化加速组件,是第一个也是最快的 opcode 缓存工具.现在,Zend 科技公司将 Optimizer+ 在 PHP Lice ...
- jvm的内部体系结构浅析
转自:http://www.cnblogs.com/evan2012/archive/2012/05/09/2489417.html 1.jvm的内部体系结构浅析 2.jvm的几个运行时数据区域 3. ...