#malware #emulation #internals #x86 #shellcode #binary #pe

libscemu

x86 32/64位和系统内部模拟器,用于安全地模拟恶意软件和其他内容

241 个版本 (13 个破坏性更新)

新增 0.17.3 2024 年 8 月 21 日
0.16.7 2024 年 7 月 14 日
0.15.6 2024 年 3 月 27 日
0.14.1 2023 年 12 月 22 日
0.8.9 2022 年 11 月 11 日

#20模拟器

Download history 191/week @ 2024-05-05 5/week @ 2024-05-12 17/week @ 2024-05-19 139/week @ 2024-06-02 46/week @ 2024-06-09 12/week @ 2024-06-16 142/week @ 2024-06-23 6/week @ 2024-06-30 236/week @ 2024-07-14 1/week @ 2024-07-21 1/week @ 2024-07-28 502/week @ 2024-08-18

每月 503 次下载

MIT 许可证

2MB
37K SLoC

SCEMU 库

使用方法

从以下网址下载 maps32 或 maps64: https://github.com/sha0coder/scemu

解压缩到某个位置,例如 /tmp/,但不要使用 tmp。

创建 emu32 或 emu64,并设置 maps 文件夹非常重要。

use libscemu::emu32;


fn main() {
    let mut emu = emu32();
    emu.set_maps_folder("/tmp/maps32/");
    emu.init();

加载您的 shellcode 或 PE 二进制文件并运行模拟器。零参数表示无限模拟。

emu.load_code("shellcodes32/shikata.bin");
emu.set_verbose(2);
emu.run(None).unwrap(); 

或者,如果您更喜欢调用特定函数。

emu.load_code("samples/malware.exe");

let crypto_key_gen = 0x40112233;
let ret_addr = 0x40110000; // any place safe to return.

let param1 = 0x33;
let param2_out_buff = emu.alloc("buffer", 1024);

emu.maps.memset(param2_out_buff, 0, 1024); // non necesary, by default alloc create zeros.
emu.maps.write_spaced_bytes(param2_out_buff, 
        "DE CC 6C 83 CC F3 66 85 34"); // example of initialization.

// call function
emu.regs.set_eip(crypto_key_gen);
emu.stack_push32(param2_out_buff);
emu.stack_push32(param1);
emu.stack_push32(ret_addr);
emu.run(Some(ret_addr)).unwrap();   // emulate until arrive to ret_addr

// or simpler way:
let eax = emu.call32(crypto_key_gen, &[param1, param2_out_buff]).unwrap();

// this would be slower but more control
while emu.step() {
    ...
}

// check result
println!("return value: 0x{:x}", emu.regs.get_eax());
emu.maps.dump(param2_out_buff);

现在可以进行钩子操作。

use libscemu::emu32;

//need iced_x86 crate only for instruction hooks, to get the
//instruction object, so add `iced-x86 = "1.17.0"`
use iced_x86::{Instruction};  


fn trace_memory_read(emu:&mut libscemu::emu::Emu, ip_addr:u64, 
                     mem_addr:u64, sz:u8) {
    println!("0x{:x}: reading {} at 0x{:x}", ip_addr, sz, mem_addr);
    if mem_addr == 0x22dff0 {
        emu.stop();
    }
}

fn trace_memory_write(emu:&mut libscemu::emu::Emu, ip_addr:u64, 
                      mem_addr:u64, sz:u8, value:u128) -> u128 {
    println!("0x{:x}: writing {} '0x{:x}' at 0x{:x}", ip_addr, sz, 
             value, mem_addr);
    value   // I could change the value to write
}

fn trace_interrupt(emu:&mut libscemu::emu::Emu, ip_addr:u64, 
                   interrupt:u64) -> bool {
    println!("interrupt {} triggered at eip: 0x{:x}", interrupt, 
             ip_addr);
    true  // do handle interrupts
}   

fn trace_exceptions(emu:&mut libscemu::emu::Emu, ip_addr:u64) -> bool {
    println!("0x{:x} triggered an exception", ip_addr);
    true // do handle exceptions
}

fn trace_pre_instruction(emu:&mut libscemu::emu::Emu, ip_addr:u64, 
                         ins:&Instruction, sz:usize) {
}

fn trace_post_instruction(emu:&mut libscemu::emu::Emu, ip_addr:u64, 
                          ins:&Instruction, sz:usize, emu_ok:bool) {
}

fn trace_winapi_call(emu:&mut libscemu::emu::Emu, ip_addr:u64, api_addr:u64) -> bool {
    return true; // handle api calls
}

fn main() {
    let mut emu = emu32();
    emu.set_maps_folder("../scemu/maps32/"); // download the maps, ideally from scemu git.
    emu.init();

    emu.load_code("/home/sha0/src/scemu/shellcodes32/mars.exe");
    emu.hook.on_memory_read(trace_memory_read);
    emu.hook.on_memory_write(trace_memory_write);
    emu.hook.on_interrupt(trace_interrupt);
    emu.hook.on_exception(trace_exceptions);
    emu.hook.on_pre_instruction(trace_pre_instruction);
    emu.hook.on_post_instruction(trace_post_instruction);
    emu.hook.on_winapi_call(trace_winapi_call);
    emu.run(None).unwrap();
    println!("end!");
}

依赖项

~20–29MB
~466K SLoC