尝试根据字符频度检测Powershell混淆
在我以前的文章中,曾经描述过使用ObfuscatedEmpire来自动化C2通道中的PowerShell混淆,以逃避杀毒软件的签名,在那篇文章中,我也提到了其他人提出的用于检测恶意PowerShell脚本的技术。该技术最初由微软的李•霍尔姆斯(Lee Holmes)提出的,是为了搜寻混淆发生的一些线索。
例如,Invoke-Obfuscation使用的令牌混淆技巧是将撇号,即将`插入到函数名称和其他登录凭据中。Invoke-Empire可能会成为iN`v`OK`e-`eM`p`IR`e,不过这些功能在PowerShell中的作用和Invoke-Empire是类似的,但会破坏与文字字符串“Invoke-Empire”匹配的杀软签名。但是,我真的希望脚本中的一半字符是由撇号组成吗? Lee早在2015年11月就对这一类型的检测方法进行过介绍。不过,在这篇文章中,我将主要参考他最近的一篇文章,该文为我们提供了一些非常棒的PowerShell功能,并利用Measure-CharacterFrequency和Measure-VectorSimilarity实现一些模糊检测技术。
本文基本上只是我重现Lee在他这篇文章中的一些检测技术,其中就包括一个可用于检测模糊化脚本的封装脚本。
这个脚本便是Invoke-ObfuscationDetection,主要的作用就是用作函数的封装器,可用于操作基于字符分析的混淆检测功能。Invoke-ObfuscationDetection会把PowerShell脚本定义为“正常”字符分布的基线,通过计算给定的PowerShell脚本的字符分布,定义给定脚本必须满足的字符分布的向量相似度,然后根据返回的布尔值是True或False来判断脚本是否被模糊化。
Invoke-ObfuscationDetection会返回一个“IsObfuscated”这样的布尔结果,给定一个包含脚本的字符串:
PS> Invoke-ObfuscationDetection -Script 'iN`v`OK`e-`eM`p`IR`e'
Obfuscated
----------
True
Invoke-ObfuscationDetection还接受包含脚本的文件名作为输入的-ScriptPath参数:
PS /opt/ObfuscatedEmpire/data/obfuscated_module_source/> Get-ChildItem -Recurse -Include *.ps1 | Invoke-ObfuscationDetection | % { $_.Obfuscated } | Group-Object
Count Name Group
----- ---- -----
72 True {True, True, True, True...}
2 False {False, False}
该命令显示Invoke-Obfuscation的TokenAll1命令混淆的Empire模块上的Invoke-ObfuscationDetection的结果,我还可以通过Invoke-ObfuscationDetection(启用ScriptBlock日志记录)来提供ScriptBlock日志:
PS> Get-WinEvent -FilterHashtable @{ProviderName="Microsoft-Windows-PowerShell"; Id = 4104} | % { [PSCustomObject] @{ ScriptName = $_.Properties[3].Value; Script = $_.Properties[2].Value } } | Invoke-ObfuscationDetection | Select -First 2
Name Obfuscated
---- ----------
2980cef2-ed31-4146-870a-a395b2d3debf True
431be04f-98a5-47cf-8e47-e565ccf6e520 False
在讨论Invoke-ObfuscationDetection的有效性之前,我认为有必要解释一下测试方法, Invoke-ObfuscationDetection在实现时,其最大的挑战便是要确定什么才能构成“正常”的PowerShell脚本。可以通过下载poshcode.org上的每个脚本,删除Windows Defender中有意混淆的脚本和识别为恶意软件的脚本(总共5552个脚本),并使用Measure-CharacterFrequency功能得到平均字符分布。
接下来的挑战便是确定平均字符分布时可接受的差异,因为并不是每个脚本都完全符合平均字符分布。虽然我会使用Measure-VectorSimilarity函数来测量每个脚本与平均字符分布的差异,但我如何决定哪些差异是能接受的,哪些是不能接受的?通过测试,我发现还是使用多年来的经验比较靠谱。我对5552个脚本中的一半进行了测试(以避免过度拟合),发现有一半会通过我提供的Measure-CharacterFrequency来确定平均字符分布。
检测的有效性验证
现在开启杀软环境,当我将一个模糊化的脚本提供给Invoke-ObfuscationDetection时,会发生假阴性错误,但是它没有被检测为混淆。当我向Invoke-ObfuscationDetection提供一个没有模糊化的脚本时,会发生假阳性错误,但它被检测为混淆。
在这样的情况下,确定假阳性或假阴性率发生的概率便非常重要,为此利用我多年的测试经验,我在测试过的脚本中确定了一些相似性较高的混淆脚本,以便把假阳性和假阴性的概率降到最低。我会对测试的脚本使用Invoke-Obfuscation的TokenAll1命令进行混淆,而将未混淆的那一半脚本提交给Invoke-ObfuscationDetection以确定假阳性发生的概率,然后我会将这些脚本提交到Invoke-ObfuscationDetection以确定假阴性发生的概率。
下图中,X轴代表相似度要求,Y轴代表发生的概率。
在我以前的文章中,曾经描述过使用ObfuscatedEmpire来自动化C2通道中的PowerShell混淆,以逃避杀毒软件的签名,在那篇文章中,我也提到了其他人提出的用于检测恶意PowerShell脚本的技术。该技术最初由微软的李•霍尔姆斯(Lee Holmes)提出的,是为了搜寻混淆发生的一些线索。
例如,Invoke-Obfuscation使用的令牌混淆技巧是将撇号,即将`插入到函数名称和其他登录凭据中。Invoke-Empire可能会成为iN`v`OK`e-`eM`p`IR`e,不过这些功能在PowerShell中的作用和Invoke-Empire是类似的,但会破坏与文字字符串“Invoke-Empire”匹配的杀软签名。但是,我真的希望脚本中的一半字符是由撇号组成吗? Lee早在2015年11月就对这一类型的检测方法进行过介绍。不过,在这篇文章中,我将主要参考他最近的一篇文章,该文为我们提供了一些非常棒的PowerShell功能,并利用Measure-CharacterFrequency和Measure-VectorSimilarity实现一些模糊检测技术。
本文基本上只是我重现Lee在他这篇文章中的一些检测技术,其中就包括一个可用于检测模糊化脚本的封装脚本。
这个脚本便是Invoke-ObfuscationDetection,主要的作用就是用作函数的封装器,可用于操作基于字符分析的混淆检测功能。Invoke-ObfuscationDetection会把PowerShell脚本定义为“正常”字符分布的基线,通过计算给定的PowerShell脚本的字符分布,定义给定脚本必须满足的字符分布的向量相似度,然后根据返回的布尔值是True或False来判断脚本是否被模糊化。
Invoke-ObfuscationDetection会返回一个“IsObfuscated”这样的布尔结果,给定一个包含脚本的字符串:
PS> Invoke-ObfuscationDetection -Script 'iN`v`OK`e-`eM`p`IR`e'
Obfuscated
----------
True
Invoke-ObfuscationDetection还接受包含脚本的文件名作为输入的-ScriptPath参数:
PS /opt/ObfuscatedEmpire/data/obfuscated_module_source/> Get-ChildItem -Recurse -Include *.ps1 | Invoke-ObfuscationDetection | % { $_.Obfuscated } | Group-Object
Count Name Group
----- ---- -----
72 True {True, True, True, True...}
2 False {False, False} 无奈人生安全网
该命令显示Invoke-Obfuscation的TokenAll1命令混淆的Empire模块上的Invoke-ObfuscationDetection的结果,我还可以通过Invoke-ObfuscationDetection(启用ScriptBlock日志记录)来提供ScriptBlock日志:
PS> Get-WinEvent -FilterHashtable @{ProviderName="Microsoft-Windows-PowerShell"; Id = 4104} | % { [PSCustomObject] @{ ScriptName = $_.Properties[3].Value; Script = $_.Properties[2].Value } } | Invoke-ObfuscationDetection | Select -First 2
Name Obfuscated
---- ----------
2980cef2-ed31-4146-870a-a395b2d3debf True
431be04f-98a5-47cf-8e47-e565ccf6e520 False
内容来自无奈安全网
在讨论Invoke-ObfuscationDetection的有效性之前,我认为有必要解释一下测试方法, Invoke-ObfuscationDetection在实现时,其最大的挑战便是要确定什么才能构成“正常”的PowerShell脚本。可以通过下载poshcode.org上的每个脚本,删除Windows Defender中有意混淆的脚本和识别为恶意软件的脚本(总共5552个脚本),并使用Measure-CharacterFrequency功能得到平均字符分布。
接下来的挑战便是确定平均字符分布时可接受的差异,因为并不是每个脚本都完全符合平均字符分布。虽然我会使用Measure-VectorSimilarity函数来测量每个脚本与平均字符分布的差异,但我如何决定哪些差异是能接受的,哪些是不能接受的?通过测试,我发现还是使用多年来的经验比较靠谱。我对5552个脚本中的一半进行了测试(以避免过度拟合),发现有一半会通过我提供的Measure-CharacterFrequency来确定平均字符分布。
检测的有效性验证
现在开启杀软环境,当我将一个模糊化的脚本提供给Invoke-ObfuscationDetection时,会发生假阴性错误,但是它没有被检测为混淆。当我向Invoke-ObfuscationDetection提供一个没有模糊化的脚本时,会发生假阳性错误,但它被检测为混淆。
在这样的情况下,确定假阳性或假阴性率发生的概率便非常重要,为此利用我多年的测试经验,我在测试过的脚本中确定了一些相似性较高的混淆脚本,以便把假阳性和假阴性的概率降到最低。我会对测试的脚本使用Invoke-Obfuscation的TokenAll1命令进行混淆,而将未混淆的那一半脚本提交给Invoke-ObfuscationDetection以确定假阳性发生的概率,然后我会将这些脚本提交到Invoke-ObfuscationDetection以确定假阴性发生的概率。
www.wnhack.com
下图中,X轴代表相似度要求,Y轴代表发生的概率。