红队技巧分享:看看二进制漏洞研究与免杀相结合

红队技巧分享:看看二进制漏洞研究与免杀相结合

原创 老鑫安全 老鑫安全 2025-03-29 12:25

之前在一篇文章里提到过使用编码兼容性问题来绕过一些命令执行的检测。Windows编码是个很大的攻击面,用在免杀方面其实有点大材小用,一个非常棒的资料参考:
https://blog.orange.tw/posts/2025-01-worstfit-unveiling-hidden-transformers-in-windows-ansi/

红队技巧分享:躲避现代检测系统的命令执行

本篇文章将采取和上次差不多的命令执行例子来讲解另外一个攻击面,分享的是利用一些“老牌函数”自身逻辑缺陷来绕过 AV/Edr的技巧。主要是思路,希望读者有所收获并能举一反三

以导出凭据为例

rundll32 comsvcs.dll MiniDump %LSASS_PID% dump.bin full 

毫无疑问EDR 和 AV 工具能够检测这种攻击,这得益于它们全面并写的非常棒的规则集,专门用于此类操作。就像下面的 Splunk 规则一样。

| tstats `security_content_summariesonly` count min(_time) as firstTime max(_time) as lastTime from datamodel=Endpoint.Processes where `process_rundll32` Processes.process=*comsvcs.dll* Processes.process IN ("*MiniDump*") by Processes.user Processes.parent_process_name Processes.process_name Processes.original_file_name Processes.process Processes.dest | `drop_dm_object_name(Processes)` | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` | `dump_lsass_via_comsvcs_dll_filter`

可以看到,该规则检查一个进程是否使用“comsvcs.dll
”与“MiniDump
”参数。所以,开始逗智逗勇。使用导出函数的序号而不是其名称。

rundll32 comsvcs.dll '#24' %LSASS_PID% dump.bin full

但对于安全产品来说,无非也就是这样就好了

Processes.process IN ("*MiniDump*","*#24*") 

所以如果是用这种思路去考虑绕过拦截那将是无止境的。混淆命令也没什么用,安全产品在识别这种命令执行的攻击方法方面已经强大且熟练,AST 层面上进行反混淆,可以参考QAX的论文《Invoke-Deobfuscation: AST-Based and Semantics-Preserving Deobfuscation for PowerShell Scripts》

所以让我们来看另外一种方法

rundll32 comsvcs.dll,#-9999999999999999999999999999999976 %LSASS_PID% dump.bin full 

这里给的导出函数序号是一个非常大的负数,相信有点计算机基础的都能预感到这可能会发生整数溢出。

so,让我们打开IDA看看rundll32是怎么处理的

可以看到 rundll32
 使用wtoi
 函数将 ASCII 序号转换为整数值,然后再通过GetProcAddress
函数使用这个函数序号来获取函数地址。

将参数 “-9999999999999999999999999999999976”
 传递给函数 “wtoi”
,当调用 “wtoi”
 时,它返回值 24 (0x18)

wtoi具体做了什么?让我们更进一步,逆向位于 “msvcrt.dll”
 中的 “wtoi”

在 “wtoi” 函数中,可以看到它首先通过比较 ASCII 编号的第一个字符来判断数字是负数还是正数。

之后,“wtoi”函数开始逐个字符地将 ASCII 数字转换为整数。

它从最左边的字符串数字中读取一个字符,然后将其转换为十进制值,对它进行一些数学运算,并重复此操作,直到达到字符串的末尾,以创建最终的整数。

x64dbg调试对照

执行循环转换过程,在每一步中,结果都保存在 RDI 寄存器中。当到达负数的最后三位数字时,当前RDI寄存器的最小32位是0xFFFFFFFF,由于符号位的原因,它表示为-1,由于wtoi”函数旨在将输入字符串转换为有符号的 4 字节整数值。所以结果始终都是 4 个字节,这里已经溢出了。

继续执行剩下的“7”和“6”

最终得到二进制补码形式的0xFFFFFFE8
。转换为10进制,这个数字等于“ -24 ”。然后我们传的参数前面是带有负号的,“-999999999999999999999999999999999976
 ”。因此,负负得正,wtoi
函数会在最终计算中准确地对结果取反

-(-24): +24

更多姿势知识星球:

图片

相关课程: