def do_x(self, args): """Dump memory at a specific address. Usage: x [/n] [{FORMAT}] LOCATION Options: n integer, how many items should be displayed Format: Either 'byte', 'int' (32bit) or 'str' (zero-terminated string) Location: address (decimal or hexadecimal form) or a $-prefixed register name (use the register's value as the destination address)""" try: x_regex = re.compile(r"(?:/(\d*) )?(?:{(byte|int|str)} )?(.+)") result = x_regex.findall(args) if not result: print("Error parsing command") return n, t, addr = result[0] n = int(n, 0) if n else 1 t = t or "int" if "$" in addr: alias = addr[1:] addr = get_reg_values(self.engine.uc)[alias] else: alias = "" addr = int(addr, 0) self.print_mem(addr, n, t, alias) except Exception as e: print(f"Error parsing command: {e}")
def print_regs(self, args=None): reg_values = get_reg_values(self.engine.uc) if not args: regs = reg_values.keys() else: regs = map(lambda r: r.lower(), args) for reg in regs: print(f"{reg.upper()} = 0x{reg_values[reg]:02x}")
def do_valset(self, args): """Set memory at a specific address to a custom value Usage: valset [{FORMAT}] OPERATION LOCATION Format: either 'byte', 'int' (32bit) or 'str' (zero-terminated string) Operation: modifies the old value instead of overwriting it (anything else than '=' is disregarded in str mode!) either = (set), += (add to), *= (multiply with) or /= (divide by) Location: address (decimal or hexadecimal form) for memory writing, or a $-prefixed register name to write an integer to this specific register ('byte' and 'str' not supported for register mode!)""" regs = { "eax": UC_X86_REG_EAX, "ebx": UC_X86_REG_EBX, "ecx": UC_X86_REG_ECX, "edx": UC_X86_REG_EDX, "eip": UC_X86_REG_EIP, "esp": UC_X86_REG_ESP, "efl": UC_X86_REG_EFLAGS, "edi": UC_X86_REG_EDI, "esi": UC_X86_REG_ESI, "ebp": UC_X86_REG_EBP } set_regs_regex = re.compile( rf"\$({'|'.join(regs.keys())}) ([+\-*/]?=) (.+)") result = set_regs_regex.findall(args) if result: reg, op, value = result[0] try: value = int(value, 0) old_value = get_reg_values(self.engine.uc)[reg] if op == "+=": value += old_value elif op == "-=": value -= old_value elif op == "*=": value *= old_value elif op == "/=": value = old_value // value self.engine.uc.reg_write(regs[reg], value) except Exception as e: print(f"Error: {e}") return set_regex = re.compile(r"(?:{(byte|int|str)} )?(.+) ([+\-*/]?=) (.+)") result = set_regex.findall(args) if not result: print("Error parsing command") else: try: t, addr, op, value = result[0] t = t or "int" addr = int(addr, 0) types = {"byte": ("B", 1), "int": ("<I", 4), "str": ("", 0)} fmt, size = types[t] if fmt: value = int(value, 0) old_value, = struct.unpack( fmt, self.engine.uc.mem_read(addr, size)) if op == "+=": value += old_value elif op == "-=": value -= old_value elif op == "*=": value *= old_value elif op == "/=": value = old_value // value to_write = struct.pack(fmt, value) else: to_write = (value + "\x00").encode() self.engine.uc.mem_write(addr, to_write) except Exception as e: print(f"Error: {e}")