17 comments

[ 1.6 ms ] story [ 35.6 ms ] thread
I was just looking at Unicorn last week because it's used by unipacker to do automated unpacking of binaries. I built a "toolbox" for gpt-5.5 to do semi-automated malware and exploit reverse engineering and unipacker is sometimes useful for that purpose.
uh.. what is a cpu emulator? or what can I do with it? I am kind of having hard time comprehend this.
(comment deleted)
"Based on Qemu 5, we built Unicorn2 from scratch"

What?

> Based on Qemu 5, we built Unicorn2 from scratch, […] still maintaining backward compatibility with the current version, […] we also added 2 highly-demanded architectures in PowerPC & RISCV.

Qemu supports RV and PPC!

And that is not what “from scratch” means!

I think they re-implemented Unicorn on a newer version of QEMU 5, rather than trying to port their old modifications over. Unicorn apparently did not support RV and PPC in the older version.
For anyone who isn't familiar with Unicorn, it doesn't emulate any specific whole-system, it's a library/framework for emulation of just the CPU. You are responsible for hooking up the whole "rest of the world" to the emulated CPU, for whatever you might need. This includes things like emulating peripherals, syscalls, binary loading, etc.

You usually use it to build your own emulator or other analysis tool, often for reverse engineering.

Somewhat relatedly, is there something halfway between QEMU and Unicorn? That is, a full VM in a library, with debugging capabilities. I'd like to be able to configure a VM, save the execution at a specific point, modify memory, run, and stop when some condition is hit (e.g. a memory address is read, or executed). For years I've had this idea of running the Jamella editor in multiple threads to crack Diablo II item seeds.
Maybe kinda sorta https://github.com/momo5502/sogen? It can even virtualize Modern Warfare 2 these days.
Also interesting, but like Qiling it simulates the kernel. That seems weird to me, that two projects would independently converge on the same solution. Is it that hard to emulate both rings, or is it that it makes useful analysis more difficult?
Maybe some KVM patching to use SLAT for breakpoints/watchpoints would fit your bill? Not sure.
I’m using it a lot in AI-driven reverse-engineering (old DOS games), agents love it (usually Python harness)
The problem is that it's not sustainable - QEMU improved so much since the moment of fork and updating the QEMU code in Unicorn is always done manually. It is especially important for architectures that evolve quickly - ARM64, RISC-V, x86. Meanwhile, QEMU now has the notion of TCG plugins[1] that can read/write registers and memory, which is enough for most cases. You can see many examples of the plugins in contrib/plugins[2] directory of the mainline QEMU - a good starting point.

[1] https://www.qemu.org/docs/master/devel/tcg-plugins.html

[2] https://gitlab.com/qemu-project/qemu/-/tree/master/contrib/p...

This looks useful for a lot of instrumentation use cases, but less so for building custom emulators, if I'm understanding it correctly.
This is actually the whole reason I wrote the patches that allow you to read and write memory and registers. I work on fuzzing, and fuzzing tools are a fragmented ecosystem of QEMU forks and patches that are outdated the moment they are published. Even PANDA from MIT LL which has great support struggled to keep their patches rebased and compatible with QEMU's actually-pretty-fast releases. Upstream or bust, it's really not that hard, it just takes a little persistence (and with LLMs learning git email is easy)!
Codex just walked me through my first experience with unicorn the other day, emulating / stubbing out subsystems from a Pioneer CDJ-3000 to help understand its music catalog database format and network protocol.

It felt like science fiction watching Codex write unicorn to host binaries and reverse engineer them.