Give an overview of the current call stack.
This works best when a symbol table has been provided, which is currently only the case for ELF binaries.
Returns
Returns string
commit
commit(): any
This function should be returned from a hook to indicate the state should be kept and execution should continue.
Returns
Returns any
execute
execute(): Promise<void>
Execute all instructions until execution has stopped.
Execution might stop due to hooks stopping emulation via the stop() method, execution reaching the end of the code, or an error.
This is the same as calling step in a loop, but staying in WASM should be more efficient.
Create a new Axecutor from the bytes of an ELF binary.
This will load the .text section into memory and set the program counter to the entry point.
One thing to note is that you might want to set up the stack via init_stack_program_start before running the binary.
Register syscalls that the emulator should handle automatically.
The function takes variadic arguments, where each argument is a number of one of the supported Syscalls
Register a function to be called after a mnemonic is executed.
The function will be called with the Axecutor object and mnemonic as arguments.
The function may be sync or async and MUST return the result of one of the following functions:
instance.commit(): Continue execution, keep data
instance.stop(): Stop execution, keep data
instance.unchanged(): Continue execution, but discard data changed in the hook
You can register multiple functions for the same mnemonic, the order of execution is however not defined.
Register a function to be called before a mnemonic is executed.
The function will be called with the Axecutor object and mnemonic as arguments.
The function may be sync or async and MUST return the result of one of the following functions:
instance.commit(): Continue execution, keep data
instance.stop(): Stop execution, keep data
instance.unchanged(): Continue execution, but discard data changed in the hook
You can register multiple functions for the same mnemonic, the order of execution is however not defined.
Parameters
mnemonic: number
cb: Function
Returns void
init_stack
init_stack(length: bigint): bigint
Initializes the stack at a random location with the given length.
Initializes the stack with the given length, command-line arguments and environment variables according to the System V ABI.
This is useful for emulating ELF binaries.
Set the access permissions of the memory area with the given start address.
The access permissions are a bitmask of PROT_READ (1), PROT_WRITE (2), and PROT_EXEC (4).
A value of 0 means no access.
By default, all memory areas are initialized with PROT_READ | PROT_WRITE.
Reads an 128-bit value from an 128-bit wide register. Invalid registers lead to exceptions.
Returns
Parameters
reg: number
Returns bigint
reg_read_16
reg_read_16(reg: number): bigint
Reads a 16-bit value from a 16-bit wide register. Invalid registers lead to exceptions.
Returns
Parameters
reg: number
Returns bigint
reg_read_32
reg_read_32(reg: number): bigint
Reads a 32-bit value from a 32-bit wide register. Invalid registers lead to exceptions.
Returns
Parameters
reg: number
Returns bigint
reg_read_64
reg_read_64(reg: number): bigint
Reads a 64-bit value from a 64-bit wide register. Invalid registers lead to exceptions.
Returns
Parameters
reg: number
Returns bigint
reg_read_8
reg_read_8(reg: number): bigint
Reads an 8-bit value from a 8-bit wide register. Invalid registers lead to exceptions.
Returns
Parameters
reg: number
Returns bigint
reg_write_128
reg_write_128(reg: number, value: bigint): void
Writes an 128-bit value to an 128-bit wide register. Out-of-range values or invalid registers lead to exceptions.
Parameters
reg: number
value: bigint
Returns void
reg_write_16
reg_write_16(reg: number, value: bigint): void
Writes a 16-bit value to a 16-bit wide register. Out-of-range values or invalid registers lead to exceptions.
Parameters
reg: number
value: bigint
Returns void
reg_write_32
reg_write_32(reg: number, value: bigint): void
Writes a 32-bit value to a 32-bit wide register. Out-of-range values or invalid registers lead to exceptions.
Note that on x86-64 writes to 32-bit registers clear the upper 32 bits of the corresponding 64-bit register.
Parameters
reg: number
value: bigint
Returns void
reg_write_64
reg_write_64(reg: number, value: bigint): void
Writes a 64-bit value to a 64-bit wide register. Out-of-range values or invalid registers lead to exceptions.
Parameters
reg: number
value: bigint
Returns void
reg_write_8
reg_write_8(reg: number, value: bigint): void
Writes an 8-bit value to a 8-bit wide register. Out-of-range values or invalid registers lead to exceptions.
Parameters
reg: number
value: bigint
Returns void
resolve_symbol
resolve_symbol(addr: bigint): undefined | string
Get the symbol name for a given address. This only works if the ELF binary contains a symbol table.
If no symbol is found, None or undefined is returned.
Returns
Parameters
addr: bigint
Returns undefined | string
set_max_instructions
set_max_instructions(max: bigint): void
Sets an upper limit on the number of instructions that can be executed.
Parameters
max: bigint
Returns void
step
step(): Promise<boolean>
Execute the next instruction (including all registered hooks), returning if execution has stopped
Returns
Returns Promise<boolean>
stop
stop(): any
This function should be returned from a hook to indicate the state should be kept and execution should stop.
You can also call this function from ouside of a hook, it will however not stop any running hooks.
Returns
Returns any
toString
toString(): string
Returns a string representation of the Axecutor instance that can be useful for debugging
Returns
Returns string
trace
trace(): string
Generate a trace of the current execution state. This trace is a list of all executed jumps, calls and returns.
Conditional jumps that were not taken are not included in the trace.
This works best when a symbol table has been provided, which is currently only the case for ELF binaries.
Returns
Returns string
unchanged
unchanged(): any
This function should be returned from a hook to indicate the state should not be kept, but execution should continue.
Returns
Returns any
write_fs
write_fs(value: bigint): void
Writes a value to the FS segment register.
Parameters
value: bigint
Returns void
write_gs
write_gs(value: bigint): void
Writes a value to the GS segment register.
Parameters
value: bigint
Returns void
Constructors
constructor
new Axecutor(code: Uint8Array, code_start_addr: bigint, initial_rip: bigint): Axecutor
Creates a new Axecutor instance from the given x86-64 instruction bytes, writing the code to memory at code_start_addr and setting the initial RIP to initial_rip.
Axecutor is the main struct that is used for emulation.
It can be instantiated in JavaScript using one of the following methods:
let ax = new Axecutor(code: Uint8Array, code_start_addr: bigint, initial_rip: bigint)
let ax = Axecutor.fromBinary(elf_binary: Uint8Array)
.Afterwards, one can register hooks before/after instructions:
ax.hook_before_mnemonic(Mnemonic.Syscall, (axInstance: Axecutor) => {...});
ax.hook_after_mnemonic(Mnemonic.Syscall, (axInstance: Axecutor) => {...});