Introduction
Welcome to official MWEMU documentation, you can do scrolling down or using the direct links that are on the left.
Github repo: https://github.com/sha0coder/mwemu

What is MWEMU?
MWEMU is a hardware emulator and Windows process simulator written in pure Rust from scratch, It was created by @sha0coder and It's open source. The contributors of this software have improved the quality of the project a lot, check to know them.
The implemented hardware is x86/x64, unlike other emulators also implemt some parts of the OS (mainly windows) because asm code soon or later is going to do system calls (WinAPI, linux syscalls, etc).
It resulted extremely useful for malware deobfuscation, but this don't replace reversing, I't needed a previous reversing to prepare well the emulation initial state, and emulate only small group of functions, like decryption, keygen etc. In some specific cases mwemu can do full-emulation, wihth simple packers, encoded shellcodes, etc.
The emulation and simulation is implemented from scratch, but the awesome Rust library iced-x86 is used to the translation from a bunch of bytes to instruction objects. I implemented more than 300 x86 instructions, flags, exceptions, some loaders PE32/PE64/ELF64/shellcode32/shellcode64 and many other stuff.
MWEMU is blazing fast and also is memory-safe thanks to the Rust magic compiler.
The 3 ways of using MWEMU
1. The first way is commandline, see commandline for more details, this is for trying full-emulation.
2. Second way is creating python scripts with pymwemu module, can be installed with pip or git.
pypi: https://pypi.org/project/pymwemu/
If you need features or bug-fixes implemented recently use the git, will need to compile the full project and then the python bindings with maturin, more details in this section pymwemu instalation
3. Third way is using the rust crate published in crates.io https://crates.io/crates/libmwemu from a rust application.
Architectures
You can run MWEMU from Windows, Linux and Mac (x86 and also m1)
But only can be emulated x86 code (32bits and 64bits) mainly for Windows, there is linux shellcode support even syscalls are implemented but regarding ELF only 64bits, only static compiled and quite basic support for now, but no problem with shellcodes.
libc can be emulated well despite it is plenty of ymm instructions, but the linker cannot be emulated totally so far, my plan is fully emulating the linker, in this case I don't need to implement the hole linking process (.got and .plt creation etc)
A bit of internals
For now, just a basic overview of the internals.

In the past I named the project SCEMU, and was stored in 3 separated repos for mwemu (the commandline) pymwemu (pyhon module) and (libmwemu) the engine where all is implemented and also it's the Rust Crate module on crates.io.
Then it was renamed to MWEMU, because SCEMU is more specific to shellcode and because it's an italian bad word.
So, now it's one repo with a crates/ folder with the 3 crates.
The tests are implemented on crates/libmwemu/src/tests/ and are described lately.
Most of files were splitted in small files.
~/s/mwemu ❯❯❯ ls crates/libmwemu/src/ main ⬆ ✱
banzai.rs emu/ kuser_shared.rs syscall/
breakpoint.rs emu_context.rs lib.rs tests/
colors.rs engine/ macros.rs thread_context.rs
config.rs err.rs maps/ threading.rs
console.rs exception.rs ntapi/ tools/
constants.rs exception_type.rs pe/ tracing.rs
context/ flags.rs peb/ utils.rs
crit_state.rs fpu/ regs64.rs winapi/
definitions.rs fpu.rs script.rs
eflags.rs global_locks.rs serialization/
elf/ hooks.rs structures/
emu/ contains emu methods and sub-bojects that are involved in the emulation itself.
In engine/ there are the implementation of all the instructions.
winapi/ contains the WinAPI implemntations divided in winapi32/ and winapi64/
there are other thigngs like contants.rs structures/ etc.
Test System
For triggering locally use make tests this downloads some binaries and launch the test system cargo test
Don't use --release, always is more convinient do the tests without aplying the optimizations, that could ignore some type of errors. Actually the github CI is configured to do cargo test and also cargo test --release to check both modes.
Every git push or pull-request will trigger the CI in gibhut to perform all the tests in Linux, Windows and Mac. In in the case of PR is mandatory, in the case of a git push is only informative.
PR also triggers a coverate analysis of the tests, which is currently only 32%

Project Contributtors
There are also other people that suggested intereting ideas and optimizations.
Regarding wit00 it's a github glitch for git pushing having a bad configuration in git config. (the bug was reported to github)
I'm @sha0coder and I created this software to empower my reversing engineering works, and I'm sharing this because I think it's useful for some cases.
Some graphs:https://github.com/sha0coder/mwemu/graphs/contributors
Videos and pics
radare2 integration on mwemu - r2con2025
my youtube channel, there are some demos
License
Actually there are several licenses, the source code is GPLv3, but the crates.io rust module and pypi python module are MIT for having less restrictions in distributing software using libmwemu or pymwemu.
https://github.com/sha0coder/mwemu/blob/main/LICENSE
Don't hesitate in contact me for creating technologies based of this software.
email: sha0 at badchecksum dot net
MWEMU commandline tool
The commandline is a quick way of using mwemu, and there are many features like register/memory/call/string tracing or capturing emulation moments.
If the packer is simple probably can be full-emulated using the commandline tool, but if you need more control use pymwemu and for total control libmwemu.
MWEMU Installation
1. First you need to install Rust and Cargo, and the best way is using rustup.
For instance in linux or mac:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
In the default setup binaries are in ~/.cargo/bin/ but you need to add this to the path, ideally on last section of the path.
export PATH="$PATH:/home/username/.cargo/bin/"
The installer says how to put in the bashrc or other shells rc.
2. Then there are 2 options to install this
-
Install from crates.io (is more convininent second option)
Shell cargo install mwemu -
The recommended way is cloning the github repo and compile from it, with Cargo it's simple.
Shell git clone https://github.com/sha0coder/mwemu.git cargo build --release make tests
--help
Use help option for viewing the commandline options, note that the before the "--" there are cargo flags and after the "--" are the parameters of the program, in this case mwemu commandline.
~/s/mwemu ❯❯❯ cargo run --release -- --help Finished `release` profile [optimized] target(s) in 0.06s
Running `target/release/mwemu --help`
MWEMU emulator for malware 0.7.12
@sha0coder
USAGE:
mwemu [FLAGS] [OPTIONS]
FLAGS:
-6, --64bits enable 64bits architecture emulation
--banzai skip unimplemented instructions, and keep up emulating what can be emulated
--call enable call tracer
--entropy display changes in the entropy
--flags trace the flags hex value in every instruction.
-F, --fpu trace the fpu states.
-h, --handle handle Ctrl+C to spawn console
--help Prints help information
-l, --loops show loop interations, it is slow.
--multithread enable multithread emulation
-n, --nocolors print without colors for redirecting to a file >out
-p, --stack_trace trace stack on push/pop
-t, --test test mode
-m, --trace_memory trace all the memory accesses read and write.
-r, --trace_registers print the register values in every step.
--version Prints version information
-v, --verbose -vv for view the assembly, -v only messages, without verbose only see the api calls and
goes faster
OPTIONS:
-A, --args
Full Emulation
Main options are:
-6 for 64bits mode (otherwise would be 32bits)
-f for selecting file path.
-vv for vieweing the emulated assembler. (emulation is faster with no verbosity, in this case only shows the api calls)
❯❯❯ cargo run --release -- -6 -f test/elf64lin_cpu_arithmetics1.bin -vv

Capturing a moment
MWEMU displays always the number of emulated instructions, and this is a unique identificator of a moment.
The moment 1 is the first assembly instruction, if you add the flag -c 1 the emulator will stop before emulating instruction 1
~/s/mwemu ❯❯❯ cargo run --release -- -6 -f test/elf64lin_cpu_arithmetics1.bin -vv -c 1 main ⬆ ✱
Finished `release` profile [optimized] target(s) in 0.07s
Running `target/release/mwemu -6 -f test/elf64lin_cpu_arithmetics1.bin -vv -c 1`
static elf64 detected.
Entry point pointing to .text 0x401000
-------
1 0x401000: inc al
--- console ---
=>
The instruction 1 will not be colored, this means that that instruction is going to be emulated in next step.
This spawns the console in that emulator state, and you can press enters to emulate steps or "h" command for viewing options.
If verbose mode is not set, only WinAPI, syscalls etc will be displayed, but there will be also a number that represent the emulated instructions until that state.
There is the option of stopping the emulator at specific address with uppercase "-C addr" but note that the address can be triggered multiple times and is not an unique identificator like the -c moment
Verbosity
There are 4 verbosity levels:
0: Don't use any -v for minimum verbosity, only WinAPI calls and syscalls will be printed.
1: Use -v for viewing also some messages like, polymorfic code detected etc.
2: Use -vv for viewing also the assembly code, mwemu will print every assembly instruction, this makes slower the emulation.2: Use -vv for viewing also the assembly code, mwemu will print every assembly instruction, this makes slower the emulation.
3: Use -vvv for also viewing every "rep" interaction, in instruction with rep prefix like "rep movzx" will print one line for every step of the rep loop.
Use -V or --verbose_at for enabling verbose mode at specific point.
The verbose mode is automatically enabled 100 instructions previous to the configured -c moment to stop.
Logging
It's possible to redirect the output to a file, ie:
❯❯❯ cargo run --release -- -6 -f test/elf64lin_cpu_arithmetics1.bin -vv -c 1 > /tmp/log
But note that colors are terminal escape bytes and will be logged making parsing more difficult, if you do cat /tmp/log you will see the colors but if you use an editor you will see those bytes
It is more convinient using --log option for a clean logs.
❯❯❯ cargo run --release -- -6 -f test/elf64lin_cpu_arithmetics1.bin -vv -c 1 --log /tmp/log
Initialize registers
There are some cases like emulating dlls or chunk of code that needs some initial values in the registers.
The commandline tool allows to set registers using those options:
--mxcsr <MXCSR> set mxcsr register
--r10 <R10> set r10 register
--r11 <R11> set r11 register
--r12 <R12> set r12 register
--r13 <R13> set r13 register
--r14 <R14> set r14 register
--r15 <R15> set r15 register
--r8 <R8> set r8 register
--r9 <R9> set r9 register
--rax <RAX> set rax register
--rbp <RBP> set rbp register
--rbx <RBX> set rbx register
--rcx <RCX> set rcx register
--rdi <RDI> set rdi register
--rdx <RDX> set rdx register
--rflags <RFLAGS> set rflags register
--rip <RIP> set rip register
--rsi <RSI> set rsi register
--rsp <RSP> set rsp register
But note that colors are terminal escape bytes and will be logged making parsing more difficult, if you do cat /tmp/log you will see the colors but if you use an editor you will see those bytes
It is more convinient using --log option for a clean logs.
❯❯❯ cargo run --release -- -6 -f test/elf64lin_cpu_arithmetics1.bin -c 1 --rax 0x123 --rbx 0x1337
Finished `release` profile [optimized] target(s) in 0.08s
Running `target/release/mwemu -6 -f test/elf64lin_cpu_arithmetics1.bin -c 1 --rax 0x123 --rbx 0x1337`
static elf64 detected.
Entry point pointing to .text 0x401000
--- console ---
=>r rax
rax: 0x123 291
=>r rbx
rbx: 0x1337 4919
Trace Registers
Use option -R <registers to trace> to trace some registers
❯❯❯ cargo run --release -- -6 -f test/elf64lin_cpu_arithmetics1.bin -vv -R rax,rsp
...
57 0x4010a2: rcr al,1
58 rax: 0x82f61001 2197164033
58 rsp: 0x7fffffffe270
58 0x4010a4: rcr ax,1
59 rax: 0x82f60800 2197161984
59 rsp: 0x7fffffffe270
59 0x4010a7: rcr eax,1
60 rax: 0xc17b0400 3246064640
60 rsp: 0x7fffffffe270
60 0x4010a9: rcr rax,1
61 rax: 0x60bd8200 1623032320
61 rsp: 0x7fffffffe270
61 0x4010ac: rcr al,cl
62 rax: 0x60bd8200 1623032320
62 rsp: 0x7fffffffe270
62 0x4010ae: rcr ax,cl
63 rax: 0x60bd8200 1623032320
63 rsp: 0x7fffffffe270
63 0x4010b1: rcr eax,cl
64 rax: 0x60bd8200 1623032320
64 rsp: 0x7fffffffe270
64 0x4010b3: rcr rax,cl
65 rax: 0x60bd8200 1623032320
65 rsp: 0x7fffffffe270
65 0x4010b6: mov eax,90909090h ; 0x90909090
66 rax: 0x90909090 2425393296
66 rsp: 0x7fffffffe270
66 0x4010bb: mov edx,90909090h ; 0x90909090
67 rax: 0x90909090 2425393296
67 rsp: 0x7fffffffe270
67 0x4010c0: mov ecx,0 ; 0x0
68 rax: 0x90909090 2425393296
68 rsp: 0x7fffffffe270
68 0x4010c5: shrd eax,edx,cl
69 rax: 0x90909090 2425393296
69 rsp: 0x7fffffffe270
69 0x4010c8: ret ; ret-addr: 0x0 ret-value: 0x90909090
You can trace one or multiple registers at same time with -R option but with no spaces between registers.