sha0coder
libscemu
Rust

SCEMU The crates.io lib, x86 cpu and systems emulator focused mainly for anti-malware

Last updated Jan 10, 2026
47
Stars
7
Forks
5
Issues
0
Stars/day
Attention Score
7
Language breakdown
Rust 100.0%
โ–ธ Files click to expand
README

SCEMU the lib

This repo has been archived, now libscemu, pyscemu and scemu become 1 repo: https://github.com/sha0coder/mwemu

Usage

Download the maps32 or maps64 from: https://github.com/sha0coder/scemu

In the example it's on /tmp/ but dont use tmp.

Create an emu32 or emu64 and it's important to set the maps folder.

use libscemu::emu32;

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

Load your shellcode or PE binary and run the emulator. None parameter means emulate for-ever.

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

Or if you prefer call specific function.

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

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

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

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

// call function emu.regs.seteip(cryptokey_gen); emu.stackpush32(param2out_buff); emu.stack_push32(param1); emu.stackpush32(retaddr); emu.run(Some(retaddr)).unwrap(); // emulate until arrive to retaddr

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

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

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

Now it's possible to do hooks on libscemu but not on pyscemu.

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 tracememoryread(emu:&mut libscemu::emu::Emu, ip_addr:u64, mem_addr:u64, sz:u8) { log::info!("0x{:x}: reading {} at 0x{:x}", ipaddr, sz, memaddr); if mem_addr == 0x22dff0 { emu.stop(); } }

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

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

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

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

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

fn tracewinapicall(emu:&mut libscemu::emu::Emu, ipaddr:u64, apiaddr:u64) -> bool { return true; // handle api calls }

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

emu.load_code("/home/sha0/src/scemu/shellcodes32/mars.exe"); emu.hook.onmemoryread(tracememoryread); emu.hook.onmemorywrite(tracememorywrite); emu.hook.oninterrupt(traceinterrupt); emu.hook.onexception(traceexceptions); emu.hook.onpreinstruction(tracepreinstruction); emu.hook.onpostinstruction(tracepostinstruction); emu.hook.onwinapicall(tracewinapicall); emu.run(None).unwrap(); log::info!("end!"); }

๐Ÿ”— More in this category

ยฉ 2026 GitRepoTrend ยท sha0coder/libscemu ยท Updated daily from GitHub