全新的恶意攻击技术已出现:针对日本用户的复杂多阶段PowerShell恶意脚本分析

luochicun Web安全 2019年3月29日发布
Favorite收藏

导语:在本文中,我将分析了一个针对日本用户的复杂多阶段PowerShell恶意脚本。

在本文中,我将分析了一个针对日本用户的复杂多阶段PowerShell恶意脚本。在本月的3月7日,网络安全公司InQuest在HybridAnalysis上发现了这个攻击示例,这个恶意软件样本是个全新的攻击样本,因为它利用了多阶段混淆、加密和隐写术来保护它的最终有效载荷不被检测到。截止发稿时,还没有任何杀毒软件能检测到这种攻击。

样本的详细信息如下:

· SHA256: 945a1276860fc4904ca23ed86b22e1782cd5761bc6c47f1cf331d9ae02cde0db

· Multi-AV: VirusTotal

· Sandbox: HyberidAnalysis

· 样本下载地址为:https://github.com/InQuest/malware-samples/tree/master/2019-03-PowerShell-Obfuscation-Encryption-Steganography

截至本文发表时,VirusTotal上的57个杀毒软件产品都没有检测到这个样本,具体原因你将在下文中看到。

在本文中,我将向你介绍这种恶意软件中经常使用的混淆技术。它特殊依赖于PowerShell中的字符串格式化运算符(-f)和转义字符(')来混淆它的最终有效载荷。Daniel BohannonInvoke-Obfuscation: PowerShell obFUsk8tion techniques & How To (Try) D""e ' tec ' th '+'em'中介绍了这些技术,并在他的Invoke-Obfuscation框架中实现了这些技术。

PowerShell中的基本字符串格式由-f运算符执行。点击这里,查看这个运算符的语法。

“带占位符的字符串”-f用逗号(,)字符分隔的字符串值列表,其中占位符以{Index,Alignment: format}的格式出现,其中Index是在-f运算符之后出现的字符串值列表中的索引。由于对齐和格式通常不用于混淆目的,所以我将它们忽略。如下示例:

考虑以下从主示例中选择的PowerShell语句:

"{2}{1}{0}" -f ']','te[','By'

应用-f运算符后,我可以得到'Byte[]' ('By'在索引2处,'te['在索引1处,']在索引0处)。

Grave字符(')用于转义PowerShell中具有特殊含义的字符,例如,如果要使用“in”放置“first”,你需要通过在字符串前面放置一个重要字符来转义此字符串中的双引号字符。为此,你需要先写入“place”。

在正常字符之前出现转义字符不会改变它们的含义,换句话说,它们就像不存在一样被忽略了。如下示例:

考虑从示例中提取的以下代码片段。

"lOAD`WiThPart`iAlN`AmE"

由于`W,`i和'A分别代表W,i和A,所以字符串等于lOADWiThPartiAlNAmE。

混淆或加密阶段的分析

此时,我将根据前面讨论的混淆技术,对混淆阶段逐一展开来分析。你还可以使用我创建的以下Python脚本,根据这些技术自动对编码的PowerShell脚本进行反混淆处理。

1.png

原始PowerShell脚本

上图就是描述了我们从HybridAnalysis中获得的原始PowerShell脚本,在第1行,特殊字符用于混淆“lOADWiThPartiAlNAmE”,然后使用字符串格式化混淆技术来混淆“System.Security”和“Out-Null”字符串。

为了对脚本进行反混淆,你可以利用我们开发的可以处理这两种特定技术的python脚本

python bash-deobfuscator.py -f obfuscated.powershell.script.ps1

下图显示了反混淆原始脚本第一阶段的结果:

2.png

在第二行中,Set-Alias(sa)cmdlet为“new-object”创建了一个新名称“DF”。

代码由两个函数组成(从第3行到第18行,从第19行到第21行)。第21行的字符串为:

${ZAE} = (&("get-culture"))."pAreNT"."nAmE"[0];

Get-Culture cmdlet会检索系统当前所在的区域,name字段基于RFC 4646。你可以在这个GitHub存储库中看到完整的语言代码,name字段的第一个字符被分配给了ZAE变量。

在第22行,通过传递两个参数来调用函数pLank。mIss会被设置为一个长加密字符串,colSs被设置为ZAE。然后将colSs作为第一个参数传递给Rfc2898DeriveBytes 类的构造函数,得到的对象用于在第10行和第11行创建两个密钥,即DcZ和DeFs,然后将这些密钥传递给在第4行创建的RijndaelManaged对象的CreateDecryptor(DcZ作为密钥,DeFs作为IV)方法。

简而言之,pLank函数使用由第二个参数构造的密钥解密第一个参数。第二个参数是一串小写英文字母(a-z)。通过逐个测试这些字符,我意识到当字符为 j. ja-JP时,解密是有意义的,因为 j. ja-JP是唯一以j. 开头的语言代码。因此,我可以说这个恶意软件针对的是当前文化设置为ja-JP的系统。所以,我有理由认为这些系统位于日本,所发现的示例是针对日本用户和系统的。

最后,在第25行执行解密代码。

要获得解密的脚本,我可以使用PowerShell ISE中的调试器,它默认情况下安装在Windows 10上。我还将第22行更改为${ZAE} ='j',并将第25行更改为其他内容,以防止恶意软件样本无意中执行,然后在第25行上放置断点,此gif文件显示了执行此操作的详细过程。

调试PowerShell代码以解密有效载荷

下图显示了我在解密和解压缩后在第25行上获得的脚本:

4.png

第2阶段解密后,所显示的有效载荷

在红色部分,GV是Get-Variable的别名,Get-Variable'* mDR *'与MaximumDriveCount变量匹配。“MaximumDriveCount”[3,11,2]是['i','e','x']并且应用-join运算符,我可以得到“iex”。

5.png

Get-Variable '*mDR*'语句的输出内容

执行剩余代码,会输出一个字符串。首先使用frOMbaSe64stRING函数解码长字符串,然后使用DEFlATeSTREam解压。最后,将结果转换为ASCII。我们可以使用PowerShell或PowerShell ISE运行这部分来删除这一阶段。你可以通过删除图4中的红色部分来实现,现在我应该能得到如下图所示的代码。

6.png

第3阶段的反混淆结果

这个阶段不依赖于定义的变量,而是依赖于环境变量来构造“iex”。在命令的其余部分中,这些数字用0x0c(12)进行xored,然后转换为字符,最后连接在一起形成一个字符串。注意,这部分非常耗时,然后使用iex执行得到的字符串。

7.png

第4阶段的反混淆结果

在这个阶段,构造一个字符串并通过管道连接到iex(红色部分)。$PSHome是一个指向PowerShell主目录的预定义变量。

要构造字符串,首先将每个数字(以二进制表示)转换为字符串,然后转换为Int16,再转换为字符。最后,将所有得到的字符连接在一起形成最终字符串。

8.png

第5阶段的反混淆结果

重申一下,红色部分是如何构建iex的过程。在这个脚本的其余部分中,format运算符用于构造一个字符串。然后使用replace函数(蓝色部分)将一些字符和子字符串替换为其他字符,得到的字符串如下图所示。

9.png

第6阶段的反混淆结果

此PowerShell脚本中使用了相同的技术,在对此阶段进行反混淆处理后,我们得到如下内容。

10.png

第7阶段的反混淆结果

我们可以再次使用我们的python脚本来反混淆字符串格式化技术(请注意该文件是ASCII格式,因此将python脚本中的编码从utf_16更改为utf_8)。我们还可以简化代码以更好地理解它的作用。

11.png

第8阶段的反混淆结果

在第44行,根据当前Windows的版本,调用v6B或v10A函数。第3行至第27行与第1至21行类似,添加的行数较少。如果Windows版本等于6,则调用v6B。此函数首先尝试从两个URL下载图像(如果第一个URL不可用,则尝试第二个URL)。如果图像的大小高于55555,则在第35到36行上提取嵌入图像中的字符串。

12.png

包含PowerShell代码的图像(隐写技术)

此示例中的隐写术提取函数与ursnif使用的技术非常相似(类似于https://twitter.com/DissectMalware/status/1057518886709612546)

13.png

隐写技术类似于ursnif使用的技术

然后,使用Nice函数对提取的代码进行解密和解压缩(第39行),生成的base-64编码字符串先被解码然后执行(第40行)。

https://i.postimg.cc/kn50Ph3h/6A.png?dl=1
https://i.imgur.com/wRli0qz.png

如果Windows版本不等于6,则调用函数v10A。首先,对base64编码的字符串进行解码,并通过[Reflection.Assembly] :: Load函数加载结果。基于这个函数,我们可以推断出数据是一个. net dll二进制文件,然后调用静态函数Stefan.gavbo.pf()。

14.png

嵌入式.NET DLL

此时pf函数会下载另一个图像,如下图所示。

15.png

pf函数下载的图像,它包含PowerShell代码

从v6B中的下载图像中提取的代码如下图所示:

16.PNG

从下载的图像中提取的PowerShell代码,返混淆后的结果如下:

17.PNG

对提取的PowerShell脚本进行第一轮反混淆处理后的结果

18.png

经过第二轮反混淆后提取的PowerShell脚本

19.png

经过第三轮反混淆后提取的PowerShell脚本

代码可以从以下一个url中下载另一个图像,然后提取、解压并执行嵌入的PowerShell代码。

https://images2.imgbox.com/25/39/dMnX3Y3Q_o.png
https://i.imgur.com/vwN9O7y.png

20.png

包含PowerShell代码的脚本下载的图像(隐写技术)

嵌入代码为:

21.png

从图像中提取的代码

22.png

嵌入的PE二进制文件

请注意,如果你要使用python脚本进行反混淆,请确保对第37行进行注释。

在图22的2415行,得到如下内容:

$NiSs=$Ni."LC`Id"; [email protected](($niss %4),2,($niss %6),4,($niss %7),($niss %9),($niss %11),($niss %12),10,($niss %100),(($niss %50)+10),(($niss %50)-10),(($niss %800)+9));[byte[]]$MjT=$null;$sPKk=""+$NiSs;.("{0}{1}"-f 'E','du') ${glOBaL:`M`G`GG} ([system.text.encoding]::"As`cIi"."gEtBy`TES"($sPKk)) ([ref]$MjT) $aCc;${glOBaL:`M`G`GG}=([System.Text.Encoding]::"Ut`F8"."g`e`TsTrinG"($MjT))

$Ni在第15行末尾分配($Ni=Get-Culture),当前文化的语言ID分配给$ NiS($ Ni.LCId)。 ja-JP的语言ID是1041。为了使代码有效,我们将其替换为以下的值。

$NiSs=1041; [email protected](($niss %4),2,($niss %6),4,($niss %7),($niss %9),($niss %11),($niss %12),10,($niss %100),(($niss %50)+10),(($niss %50)-10),(($niss %800)+9));[byte[]]$MjT=$null;$sPKk=""+$NiSs;.("{0}{1}"-f 'E','du') ${glOBaL:`M`G`GG} ([system.text.encoding]::"As`cIi"."gEtBy`TES"($sPKk)) ([ref]$MjT) $aCc;${glOBaL:`M`G`GG}=([System.Text.Encoding]::"Ut`F8"."g`e`TsTrinG"($MjT))

现在,我们可以调试代码并提取嵌入的PE文件。

本文翻译自:http://blog.inquest.net/blog/2019/03/09/Analyzing-Sophisticated-PowerShell-Targeting-Japan/如若转载,请注明原文地址: https://www.4hou.com/web/17070.html
点赞 1
  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论