工具介绍及使用请移步:http://blog.csdn.net/sunflover454/article/details/50441014

本文首发在零日安全论坛:http://www.jmpoep.com/thread-833-1-1.html

使用NtCreateThreadEx + LdrLoadDll方式实现远程线程注入的特色在于比一般的远程线程注入稳定,可以注入系统进程,服务进程等。

核心源代码如下,完整源代码,请在文章末尾下载。

  1. //OD跟踪,发现最后调用的是NtCreateThreadEx,所以这里手动调用
  2. HANDLE Cx64Inject::MyCreateRemoteThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf)
  3. {
  4. HANDLE hThread = NULL;
  5. FARPROC pFunc = NULL;
  6. if( IsVistaOrLater())// Vista, 7, Server2008
  7. {
  8. pFunc = GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtCreateThreadEx");
  9. if( pFunc == NULL )
  10. {
  11. MyOutputDebugStringA("MyCreateRemoteThread() : GetProcAddress(\"NtCreateThreadEx\") 调用失败!错误代码: [%d]", GetLastError());
  12. return NULL;
  13. }
  14. ((_NtCreateThreadEx64)pFunc)(&hThread,0x1FFFFF,NULL,hProcess,pThreadProc,pRemoteBuf,FALSE,NULL,NULL,NULL,NULL);
  15. if( hThread == NULL )
  16. {
  17. MyOutputDebugStringA("MyCreateRemoteThread() : NtCreateThreadEx() 调用失败!错误代码: [%d]", GetLastError());
  18. return NULL;
  19. }
  20. }
  21. else// 2000, XP, Server2003
  22. {
  23. hThread = CreateRemoteThread(hProcess,NULL,0,pThreadProc,pRemoteBuf,0,NULL);
  24. if( hThread == NULL )
  25. {
  26. MyOutputDebugStringA("MyCreateRemoteThread() : CreateRemoteThread() 调用失败!错误代码: [%d]", GetLastError());
  27. return NULL;
  28. }
  29. }
  30. if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) )
  31. {
  32. MyOutputDebugStringA("MyCreateRemoteThread() : WaitForSingleObject() 调用失败!错误代码: [%d]", GetLastError());
  33. return NULL;
  34. }
  35. return hThread;
  36. }
//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;
}
  1. //在目标进程中创建线程并注入dll
  2. BOOL Cx64Inject::InjectDll(DWORD dwProcessId,LPCWSTR lpcwDllPath)
  3. {
  4. BOOL bRet = FALSE;
  5. HANDLE hProcess = NULL, hThread = NULL;
  6. LPVOID pCode = NULL;
  7. LPVOID pThreadData = NULL;
  8. __try
  9. {
  10. if(!EnableDebugPrivilege())
  11. {
  12. MyOutputDebugStringA("InjectDll() : EnableDebugPrivilege() 调用失败!错误代码: [%d]", GetLastError());
  13. return -1;
  14. }
  15. //打开目标进程;
  16. hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, dwProcessId);
  17. DWORD dwError = GetLastError();
  18. if (hProcess == NULL)
  19. __leave;
  20. //申请空间,把我们的代码和数据写入目标进程空间里;
  21. //写入数据;
  22. THREAD_DATA data;
  23. HMODULE hNtdll = GetModuleHandleW(L"ntdll.dll");
  24. data.fnRtlInitUnicodeString = (pRtlInitUnicodeString)GetProcAddress(hNtdll,"RtlInitUnicodeString");
  25. data.fnLdrLoadDll = (pLdrLoadDll)GetProcAddress(hNtdll,"LdrLoadDll");
  26. memcpy(data.DllName, lpcwDllPath, (wcslen(lpcwDllPath) + 1)*sizeof(WCHAR));
  27. data.DllPath = NULL;
  28. data.Flags = 0;
  29. data.ModuleHandle = INVALID_HANDLE_VALUE;
  30. pThreadData = VirtualAllocEx(hProcess, NULL, 4096, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
  31. if (pThreadData == NULL)
  32. __leave;
  33. BOOL bWriteOK = WriteProcessMemory(hProcess, pThreadData,&data,sizeof(data), NULL);
  34. if (!bWriteOK)
  35. __leave;
  36. MyOutputDebugStringA("pThreadData = 0x%p", pThreadData);
  37. //写入代码;
  38. DWORD SizeOfCode = (DWORD)ThreadProcEnd - (DWORD)ThreadProc;
  39. pCode = VirtualAllocEx(hProcess, NULL, SizeOfCode, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
  40. if (pCode == NULL)
  41. {
  42. MyOutputDebugStringA("InjectDll() : pCode = VirtualAllocEx() 调用失败!错误代码: [%d]", GetLastError());
  43. __leave;
  44. }
  45. bWriteOK = WriteProcessMemory(hProcess, pCode, (PVOID)ThreadProc, SizeOfCode, NULL);
  46. if (!bWriteOK)
  47. __leave;
  48. MyOutputDebugStringA("pCode = 0x%p", pCode);
  49. //创建远程线程,把ThreadProc作为线程起始函数,pThreadData作为参数;
  50. hThread = MyCreateRemoteThread(hProcess, (LPTHREAD_START_ROUTINE)pCode, pThreadData);
  51. if (hThread == NULL)
  52. __leave;
  53. //等待完成;
  54. WaitForSingleObject(hThread, INFINITE);
  55. bRet = TRUE;
  56. }
  57. __finally
  58. {
  59. if (pThreadData != NULL)
  60. VirtualFreeEx(hProcess, pThreadData, 0, MEM_RELEASE);
  61. if (pCode != NULL)
  62. VirtualFreeEx(hProcess, pCode, 0, MEM_RELEASE);
  63. if (hThread != NULL)
  64. CloseHandle(hThread);
  65. if (hProcess != NULL)
  66. CloseHandle(hProcess);
  67. }
  68. return bRet;
  69. }
//在目标进程中创建线程并注入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;
}

以上是远程线程注入类的两个核心函数,下面是调用实例:

  1. Cx64Inject inject;
  2. if (inject.InjectDll(g_dwPID,g_szDllPath))
  3. {
  4. ::MessageBox(NULL,L"注入成功",L":)",MB_ICONINFORMATION);
  5. }
  6. else
  7. {
  8. ::MessageBox(NULL,L"注入失败!",L"失败",MB_ICONERROR);
  9. }
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方式实现,可以注入系统进程)的更多相关文章

  1. win7下将dll文件的打开方式改回系统默认

    打开注册表,定位到HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.dll把除OpenWit ...

  2. 表达式SpEL方式的属性注入

    -----------------------siwuxie095 表达式 SpEL 方式的属性注入 表达式 SpEL 方式的属性注入是 Spring 3.x 版本后提供的方式 1.编写一个普通类 B ...

  3. 命名空间p方式的属性注入

    ---------------------siwuxie095 命名空间 p 方式的属性注入 命名空间 p 方式的属性注入是 Spring 2.x 版本后提供的方式 1.编写一个普通类 Book.ja ...

  4. war包部署在tomcat下,使用windows service服务方式启动tomcat服务器,在包含调用dll的模块,报dll找不到问题的解决办法

    问题描述: 开发了一个需要调用dll的java web程序,在idea开发环境下运行调试没问题,可以正常运行,在tomcat/bin下,运行批处理startup.bat,启动tomcat服务器,也可以 ...

  5. Spring依赖注入三种方式详解

    在讲解Spring依赖注入之前的准备工作: 下载包含Spring的工具jar包的压缩包 解压缩下载下来的Spring压缩包文件 解压缩之后我们会看到libs文件夹下有许多jar包,而我们只需要其中的c ...

  6. dll的加载方式主要分为两大类,显式和隐式链接

    之前简单写过如何创建lib和dll文件及简单的使用(http://blog.csdn.net/betabin/article/details/7239200).现在先再深入点写写dll的加载方式. d ...

  7. Ring3下干净的强行删除文件

    在某公司实习完,再次回到寝室.还是在学校好. 实习期间的给我的任务就是为项目添加一个强行删除的模块. 背景是硬盘上存储空间不够时,需要删掉老的文件,如果这时后,老的文件被打开了,没有关掉,就无法删除. ...

  8. Spring的几种注入bean的方式

    在Spring容器中为一个bean配置依赖注入有三种方式: · 使用属性的setter方法注入  这是最常用的方式: · 使用构造器注入: · 使用Filed注入(用于注解方式).   使用属性的se ...

  9. 深入Delphi下的DLL编程

    深入Delphi下的DLL编程 作者:岑心 引 言 相信有些计算机知识的朋友都应该听说过“DLL”.尤其是那些使用过windows操作系统的人,都应该有过多次重装系统的“悲惨”经历——无论再怎样小心, ...

随机推荐

  1. rsync数据同步备份

    一.rsync简介 (1)rsync是什么? rsync是一款开源的.快速的.多功能的.可实现全量及增量的本地或远程数据同步备份的优秀工具. (2)rsync作用比较 远程拷贝:有点类似ssh的scp ...

  2. PHP 文件管理

    主页面: <?php session_start(); $filename=""; if(!empty($_SESSION["lujing"])) { $ ...

  3. jQuery-3~4章

    jQuery-3~5章 JQuery003-JQuery中的DOM操作 jQuery中的DOM操作: 1.查找节点 A.查找元素节点 B. 查找属性节点 var s1 = $("ul li: ...

  4. 谷歌地图地理解析和反解析geocode.geocoder详解

    地址解析就是将地址(如:贵州省贵阳市)转换为地理坐标(如经度:106.71,纬度:26.57)的过程. 地理反解析和上面的过程相反是将地理坐标(如纬度:26.57,经度:106.71)转换为地址(中国 ...

  5. IOS热更新-JSPatch实现原理+Patch现场恢复

    关于HotfixPatch 在IOS开发领域,由于Apple严格的审核标准和低效率,IOS应用的发版速度极慢,稍微大型的app发版基本上都在一个月以上,所以代码热更新(HotfixPatch)对于IO ...

  6. PHP读写大“二进制”文件,不必申请很大内存(fopen、fread、fwrite、fclose)

    <?php /** * 读写大二进制文件,不必申请很大内存 * 只有读取到内容才创建文件 * 保证目录可写 * * @param string $srcPath 源文件路径 * @param s ...

  7. synchronized在jvm底层是如何实现的

    目前在Java中存在两种锁机制:synchronized和Lock,Lock接口及其实现类是JDK5增加的内容,其作者是大名鼎鼎的并发专家Doug Lea.本文并不比较synchronized与Loc ...

  8. 为Tcl编写C的扩展库

    Tcl是一个比较简洁的脚本语言,官方地址 http://www.tcl.tk. tcl脚本加载C实现的动态库非常方便. 1. 为Tcl编写一个用C实现的扩展函数. #include <stdio ...

  9. java基础 作业(一)

    题目: 跳水比赛,8个评委打分.运动员的成绩是8个成绩去掉一个最高分,去掉一个最低分,剩下的6个分数 的平均分就是最后 得分.使用以为数组实现打分功能 .请把打分最高的评委和最低的评委找出来. 解析: ...

  10. BZOJ1562——[NOI2009]变换序列

    1.题意:题意有些难理解 2.分析:我们发现如果要求判断是否合法的话就so easy了,二分图匹配即可,但是我们发现要求输出字典序最小的,那么我们在匈牙利的时候就倒着枚举,另外邻接表中的边一定要排好序 ...