Skip to content

Instantly share code, notes, and snippets.

@wumb0
Created November 29, 2020 18:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wumb0/da8fc7865da2489d3148b65d3baa54cd to your computer and use it in GitHub Desktop.
Save wumb0/da8fc7865da2489d3148b65d3baa54cd to your computer and use it in GitHub Desktop.
command line assembly emulator that allows you to quickly see the results of instructions
# requires keystone-engine, capstone, prompt_toolkit, and pygments
import keystone as ks
import unicorn as uc
import math
import sys
from pygments.lexers.asm import NasmLexer
from pygments.styles import get_style_by_name
from prompt_toolkit.shortcuts import prompt
from prompt_toolkit.lexers import PygmentsLexer
from prompt_toolkit.validation import Validator, ValidationError
from prompt_toolkit.styles.pygments import style_from_pygments_cls
k = ks.Ks(ks.KS_ARCH_X86, ks.KS_MODE_LITTLE_ENDIAN|ks.KS_MODE_64)
code_base = 0x1000
stack_base = 0x10000
class AsmVal(Validator):
def validate(self, doc):
if not doc.text:
raise ValidationError(message="Invalid input")
try:
k.asm(doc.text, code_base, True)
except:
raise ValidationError(message="Invalid assembly syntax")
def emulate(data):
asm = k.asm(data, code_base, True)
u = uc.Uc(uc.UC_ARCH_X86, uc.UC_MODE_LITTLE_ENDIAN|uc.UC_MODE_64)
u.mem_map(code_base, int(math.ceil(len(asm[0]) / float(0x1000))) * 0x1000)
u.mem_map(stack_base, 0x2000, uc.UC_PROT_READ | uc.UC_PROT_WRITE)
u.mem_write(code_base, asm[0])
u.reg_write(uc.x86_const.UC_X86_REG_RIP, code_base)
u.reg_write(uc.x86_const.UC_X86_REG_RSP, stack_base)
regs = ["RIP", "RAX", "RBX", "RCX", "RDX", "RSI", "RDI", "RSP", "RBP", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15"]
u.emu_start(0x1000, 0x1000 + len(asm[0]), count=asm[1])
for reg in regs:
print("{}:\t0x{:016x}".format(reg, u.reg_read(getattr(uc.x86_const, "UC_X86_REG_" + reg))))
print("FLAGS:")
ef = u.reg_read(uc.x86_const.UC_X86_REG_EFLAGS)
flags = {"CF": 0, "PF": 2, "AF": 4, "ZF": 6, "SF": 7, "TF": 8, "IF": 9, "DF": 10, "OF": 11}
for name, bit in flags.items():
print(f"\t{name}: {ef & (1 << bit) == (1 << bit)}")
if len(sys.argv) > 1:
data = open(sys.argv[1]).read()
emulate(data)
else:
data = ""
while 1:
try:
style = style_from_pygments_cls(get_style_by_name('colorful'))
data = prompt("Enter some assembly\n", multiline=True, validator=AsmVal(), lexer=PygmentsLexer(NasmLexer), default=data, style=style)
except KeyboardInterrupt:
break
emulate(data)
print()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment