Shellcode Emulator

Step x86 and x64 shellcode in a constrained browser emulator. Registers, flags, stack, memory, reversible writes and modelled API calls.

Advertisement

Watch shellcode run without letting it run

Static reading only gets you so far with position-independent code. Decoding stubs, GetPC tricks and API hashing all look like noise in a disassembler and become obvious the moment you can watch the registers change. This emulator models x86 and x64 execution in the browser, so you can step through a payload without giving it a real process to live in.

What is modelled

General-purpose registers and flags for both 32-bit and 64-bit modes, a stack, and private mapped memory that exists only inside the emulator. Every executed instruction appends to a trace with the state it produced, and writes are reversible, so you can step backward instead of restarting when you overshoot the interesting part.

Breakpoints pause before a chosen address. The memory view shows what the current instruction touched, which is how a decoder loop reveals itself: you watch the same buffer transform in place, byte by byte, until readable strings appear.

API and syscall attempts are modelled as events, not performed. When shellcode resolves and calls something, you see which call it attempted and with what arguments, and execution continues against a modelled return value. There is no filesystem, no process creation, no network, no clipboard and no credential access behind those calls.

Stop on unknown, never guess

The instruction subset for this release is documented, and it is a subset. When the emulator meets an instruction it does not implement, it stops and says so.

That behaviour is deliberate and worth understanding, because the alternative is much worse. An emulator that treats an unimplemented instruction as a no-op keeps running and produces a trace that looks complete and is quietly wrong. Every register value after that point is fiction. Stopping is the honest failure, even though it means some payloads will not run to completion here.

Additional architectures get added only when their decoder and state-transition suites meet the same bar, rather than shipping partial support that mislabels its own gaps.

Ceilings

Instruction count, memory, trace length, wall-clock time and output volume all have hard limits. Shellcode that loops forever hits the instruction ceiling and stops rather than freezing the tab. The limits are low enough to keep the browser responsive, which means a payload built around a long sleep or a large allocation will hit a ceiling before it finishes.

A workable approach to an unknown payload

Start at the entry point and step until the code stops looking linear. Most payloads open with a short GetPC sequence to learn their own address, then enter a decode loop. Set a breakpoint after the loop rather than stepping through every iteration, and read memory there: if the payload was encoded, the strings and the real instructions are visible at that point.

From there the modelled call events usually tell the story. A payload that resolves LoadLibraryA then WSAStartup then connect has announced itself before executing anything meaningful, and you have that sequence without a network stack ever existing.

Finding the real entry point

Carved shellcode does not always start at offset zero of the range you extracted. Padding, alignment bytes, a length prefix, or a few bytes of the surrounding structure often ride along, and starting execution one byte early produces a decode that goes nowhere.

When the first few instructions look like nonsense, try starting a byte or two later rather than concluding the payload is corrupt. Real entry points tend to announce themselves: a stack alignment, a push sequence, a call to the next instruction to recover the current address, or an immediate load followed by a loop counter. If stepping from a candidate offset produces a clean sequence that settles into a loop, that is almost certainly the start.

Encoding choices leave fingerprints too. Payloads built to survive string handling avoid null bytes, so a range with no zero bytes across a few hundred positions is usually deliberate rather than coincidental, and it suggests the author expected the payload to travel through something that treats a null as a terminator.

Where it fits

Shellcode usually arrives as bytes carved out of something larger. Extract the range in the Hex Editor, read it in the Machine Code Disassembler, then emulate it here when static reading stalls. Findings attach to the Binary Lab session, so the trace and the modelled calls land in the same evidence report as the rest of the analysis.

This is a browser model of a CPU, not a sandbox and not a substitute for a detonation environment. Use it to understand code, not to certify that code is safe.

Frequently Asked Questions

Does the emulator execute shellcode on my computer?+

No. It models supported instructions in TypeScript with a private Uint8Array memory space. It never invokes native code, a system call, an interrupt, or an operating-system API.

What happens at an unsupported instruction?+

The emulator stops with the exact address and opcode rather than guessing. It also stops at syscalls, interrupts, external control transfers, invalid memory, and the instruction limit.

Can it analyze a complete executable?+

It can extract and model a selected byte range or detected entry offset, but it does not load a full process image, dynamic linker, operating-system APIs, or every CPU instruction. Use the executable inspector first.

Related tools

This tool is provided for informational and educational purposes only. All processing happens in your browser — no data is sent to or stored on our servers. While we strive for accuracy, we make no warranties about the completeness or reliability of results. Results are based on the information you enter and do not constitute a security audit, a formal compliance assessment, or legal advice, and they do not establish that any system or organisation meets a given standard. Coverage of a framework may be partial — check what the tool states it assesses. For anything you intend to rely on, consult a qualified assessor.