def assemble(insn_list): ks = Ks(KS_ARCH_X86, KS_MODE_64) iarray, cnt = ks.asm("\n".join(insn_list)) code = "" for i in iarray: code += chr(i) return code
def runTest(self): ks = Ks(KS_ARCH_PPC, KS_MODE_PPC32 + KS_MODE_BIG_ENDIAN) encoding, count = ks.asm(self.asm, 0xc0000000) expected_encoding = [ 56, 128, 0, 1, 56, 132, 0, 1, 72, 0, 191, 249, 56, 128, 0, 1, 56, 165, 0, 1, 72, 0, 191, 249 ] self.assertEqual(encoding, expected_encoding)
def runTest(self): ks = Ks(KS_ARCH_ARM, KS_MODE_ARM) encoding, count = ks.asm(self.asm, 0xc0000000) expected_encoding = [ 48, 0, 160, 227, 91, 172, 33, 235, 16, 0, 0, 230, 65, 0, 160, 227, 84, 172, 33, 235 ] self.assertEqual(encoding, expected_encoding)
def __init__(self, emu, base_addr, size): self._emu = emu self._keystone = Ks(KS_ARCH_ARM, KS_MODE_THUMB) self._size = size self._current_id = 0xFF00 self._hooks = dict() self._hook_magic = base_addr self._hook_start = base_addr + 4 self._hook_current = self._hook_start self._emu.mu.hook_add(UC_HOOK_CODE, self._hook, None, self._hook_start, self._hook_start + size)
def run(uc, inp): try: ks = Ks(KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN) bytecode, _ = ks.asm(inp) uc.mem_write(BASE_ADR, bytes(bytecode)) uc.emu_start(BASE_ADR, BASE_ADR + 4, 0, 1) except KsError as ke: print(ke) except UcError as ue: print(ue) except: print("Assemler error")
def assembler(arch: QL_ARCH, endianess: QL_ENDIAN) -> Ks: """Instantiate an assembler object for a specified architecture. Args: arch: architecture type endianess: architecture endianess Returns: an assembler object """ endian = { QL_ENDIAN.EL: KS_MODE_LITTLE_ENDIAN, QL_ENDIAN.EB: KS_MODE_BIG_ENDIAN }[endianess] asm_map = { QL_ARCH.ARM: (KS_ARCH_ARM, KS_MODE_ARM), QL_ARCH.ARM64: (KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN), QL_ARCH.ARM_THUMB: (KS_ARCH_ARM, KS_MODE_THUMB), QL_ARCH.MIPS: (KS_ARCH_MIPS, KS_MODE_MIPS32 + endian), QL_ARCH.A8086: (KS_ARCH_X86, KS_MODE_16), QL_ARCH.X86: (KS_ARCH_X86, KS_MODE_32), QL_ARCH.X8664: (KS_ARCH_X86, KS_MODE_64) } if arch in asm_map: return Ks(*asm_map[arch]) raise NotImplementedError
def assembler(self) -> Ks: endian = { QL_ENDIAN.EL: KS_MODE_LITTLE_ENDIAN, QL_ENDIAN.EB: KS_MODE_BIG_ENDIAN }[self.endian] return Ks(KS_ARCH_MIPS, KS_MODE_MIPS32 + endian)
def assembler(arch: QL_ARCH, endianess: QL_ENDIAN, is_thumb: bool) -> Ks: """Instantiate an assembler object for a specified architecture. Args: arch: architecture type endianess: architecture endianess is_thumb: thumb mode for ARM (ignored otherwise) Returns: an assembler object """ endian = { QL_ENDIAN.EL : KS_MODE_LITTLE_ENDIAN, QL_ENDIAN.EB : KS_MODE_BIG_ENDIAN }[endianess] thumb = KS_MODE_THUMB if is_thumb else 0 asm_map = { QL_ARCH.ARM : (KS_ARCH_ARM, KS_MODE_ARM + endian + thumb), QL_ARCH.ARM64 : (KS_ARCH_ARM64, KS_MODE_ARM), QL_ARCH.MIPS : (KS_ARCH_MIPS, KS_MODE_MIPS32 + endian), QL_ARCH.A8086 : (KS_ARCH_X86, KS_MODE_16), QL_ARCH.X86 : (KS_ARCH_X86, KS_MODE_32), QL_ARCH.X8664 : (KS_ARCH_X86, KS_MODE_64), QL_ARCH.PPC : (KS_ARCH_PPC, KS_MODE_PPC32 + KS_MODE_BIG_ENDIAN) } if arch in asm_map: return Ks(*asm_map[arch]) raise NotImplementedError
def ql_create_assembler(archtype: QL_ARCH, archendian: QL_ENDIAN, reg_cpsr=None) -> Ks: if archtype == QL_ARCH.X86: ks = Ks(KS_ARCH_X86, KS_MODE_32) elif archtype == QL_ARCH.X8664: ks = Ks(KS_ARCH_X86, KS_MODE_64) elif archtype == QL_ARCH.ARM: mode = KS_MODE_THUMB if reg_cpsr & __reg_cpsr_v[ archendian] else KS_MODE_ARM ks = Ks(KS_ARCH_ARM, mode) # FIXME: should be: mode + __ks_endian[archendian] elif archtype == QL_ARCH.ARM_THUMB: ks = Ks(KS_ARCH_ARM, KS_MODE_THUMB) elif archtype == QL_ARCH.ARM64: ks = Ks(KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN) elif archtype == QL_ARCH.MIPS: ks = Ks(KS_ARCH_MIPS, KS_MODE_MIPS32 + __ks_endian[archendian]) elif archtype == QL_ARCH.A8086: ks = Ks(KS_ARCH_X86, KS_MODE_16) elif archtype == QL_ARCH.EVM: raise NotImplementedError('evm') else: raise QlErrorArch(f'{archtype:d}') return ks
def assemble(self, code, thumb=True): """ Assemble code using Keystone and write it at the current position. Args: code (:obj:`str`): the code to assemble thumb (:obj:`bool`): True if Thumb, False otherwise Returns: :obj:`int`: the number of bytes written """ from keystone import Ks, KS_ARCH_ARM, KS_MODE_ARM, KS_MODE_THUMB ks = Ks(KS_ARCH_ARM, KS_MODE_THUMB if thumb else KS_MODE_ARM) addr = self._ptr.value bs, size = ks.asm(code, addr) self.write(bytes(bytearray(bs))) return len(bs)
def create_assembler(self) -> Ks: if self._asm is None: endian = { QL_ENDIAN.EL: KS_MODE_LITTLE_ENDIAN, QL_ENDIAN.EB: KS_MODE_BIG_ENDIAN }[self.ql.archendian] self._asm = Ks(KS_ARCH_MIPS, KS_MODE_MIPS32 + endian) return self._asm
def assembler(self) -> Ks: # note: we do not cache the assembler instance; rather we refresh it # each time to make sure current endianess and thumb mode are taken into # account mode = KS_MODE_ARM if self.endian == QL_ENDIAN.EB: mode += KS_MODE_BIG_ENDIAN if self.is_thumb: mode += KS_MODE_THUMB return Ks(KS_ARCH_ARM, mode)
def sample_elf(request): with tempfile.NamedTemporaryFile(suffix='.elf', delete=False) as f: e = ElfBuilder() e.set_endianity('>') e.set_machine(elf_consts.EM_ARM) # add a segment text_address = 0x1234 ks = Ks(KS_ARCH_ARM, KS_MODE_ARM | KS_MODE_BIG_ENDIAN) text_buffer = ks.asm( ''' ret_1: mov r0, #1 bx lr eloop: b eloop data: .word 0x11223344 .word 0x55667788 .code 32 main: push {r4-r7, lr} bl 0x1234-8 ldr r0, =data bl 0x1234-8 pop {r4-r7, pc} ''', text_address)[0] text_buffer = bytearray(text_buffer) e.add_segment(text_address, text_buffer, elf_consts.PF_R | elf_consts.PF_W | elf_consts.PF_X) e.add_code_section('.text', text_address, len(text_buffer)) f.write(e.build()) yield f
def create_assembler(self) -> Ks: # note: we do not cache the assembler instance; rather we refresh it # each time to make sure thumb mode is taken into account if self.ql.archtype == QL_ARCH.ARM: # FIXME: mode should take endianess into account mode = KS_MODE_THUMB if self.__is_thumb() else KS_MODE_ARM elif self.ql.archtype == QL_ARCH.ARM_THUMB: mode = KS_MODE_THUMB else: raise QlErrorArch(f'unexpected arch type {self.ql.archtype}') return Ks(KS_ARCH_ARM, mode)
def create_assembler(self) -> Ks: if self._asm is None: self._asm = Ks(KS_ARCH_ARM64, KS_MODE_LITTLE_ENDIAN) return self._asm
class Hooker: """ :type emu androidemu.emulator.Emulator """ def __init__(self, emu, base_addr, size): self._emu = emu self._keystone = Ks(KS_ARCH_ARM, KS_MODE_THUMB) self._size = size self._current_id = 0xFF00 self._hooks = dict() self._hook_magic = base_addr self._hook_start = base_addr + 4 self._hook_current = self._hook_start self._emu.mu.hook_add(UC_HOOK_CODE, self._hook, None, self._hook_start, self._hook_start + size) def _get_next_id(self): idx = self._current_id self._current_id += 1 return idx def write_function(self, func): # Get the hook id. hook_id = self._get_next_id() hook_addr = self._hook_current # Create the ARM assembly code. # Make sure to update STACK_OFFSET if you change the PUSH/POP. asm = "PUSH {R4,LR}\n" \ "MOV R4, #" + hex(hook_id) + "\n" \ "MOV R4, R4\n" \ "POP {R4,PC}" asm_bytes_list, asm_count = self._keystone.asm( bytes(asm, encoding='ascii')) if asm_count != 4: raise ValueError("Expected asm_count to be 4 instead of %u." % asm_count) # Write assembly code to the emulator. self._emu.mu.mem_write(hook_addr, bytes(asm_bytes_list)) # Save results. self._hook_current += len(asm_bytes_list) self._hooks[hook_id] = func return hook_addr def write_function_table(self, table): if not isinstance(table, dict): raise ValueError("Expected a dictionary for the function table.") index_max = int(max(table, key=int)) + 1 # First, we write every function and store its result address. hook_map = dict() for index, func in table.items(): hook_map[index] = self.write_function(func) # Then we write the function table. table_bytes = b"" table_address = self._hook_current for index in range(0, index_max): address = hook_map[index] if index in hook_map else 0 table_bytes += int(address + 1).to_bytes( 4, byteorder='little') # + 1 because THUMB. self._emu.mu.mem_write(table_address, table_bytes) self._hook_current += len(table_bytes) # Then we write the a pointer to the table. ptr_address = self._hook_current self._emu.mu.mem_write(ptr_address, table_address.to_bytes(4, byteorder='little')) self._hook_current += 4 return ptr_address, table_address def _hook(self, mu, address, size, user_data): # Check if instruction is "MOV R4, R4" if size != 2 or self._emu.mu.mem_read(address, size) != b"\x24\x46": return # Find hook. hook_id = self._emu.mu.reg_read(UC_ARM_REG_R4) hook_func = self._hooks[hook_id] # Call hook. try: hook_func(self._emu) except: # Make sure we catch exceptions inside hooks and stop emulation. mu.emu_stop() raise
# extend a segment to map this new section in RWX memory # update the entrypoint to jmp to the shellcode ## e = ELF(argv[1]) new_section = Elf64_Shdr_ST() # creating our shellcode (exit(14);) asm = """ mov rax, 0x3c mov rdi, 14 syscall """ ks = Ks(KS_ARCH_X86, KS_MODE_64) ks.syntax = KS_OPT_SYNTAX_NASM shellcode = ks.asm(asm)[0] shellcode = (c_char * len(shellcode)).from_buffer(bytearray(shellcode)).raw # we can modify the .text section to jmp to the sc but we will directly modified the entrypoint # stub = ks.asm("jmp 0x3308")[0] # stub = (c_char * len(stub)).from_buffer(bytearray(stub)).raw # e.get_section_by_name(".text").data = stub new_section.data = shellcode new_section.sh_name = 1 # choose a random name # right after the last sh there is the sht table so it offset will be the addr of the new section new_section.sh_offset = e.Elf64_Ehdr.e_shoff # nice if it would be filled automatically by save
from capstone import Cs, CS_ARCH_X86, CS_MODE_32 from keystone import Ks, KS_ARCH_X86, KS_MODE_32 _asm = Ks(KS_ARCH_X86, KS_MODE_32) class Disasassembler: def __init__(self, offset=0): self._disas = Cs(CS_ARCH_X86, CS_MODE_32) self.offset = offset def disasm(self, opcodes): return self._disas.disasm(opcodes, self.offset) def asm(code): opcodes_list = _asm.asm(code)[0] return "".join(map(chr, opcodes_list))
def runTest(self): ks = Ks(KS_ARCH_PPC, KS_MODE_PPC32 + KS_MODE_BIG_ENDIAN) encoding, count = ks.asm(self.asm, 0xc0000000) expected_encoding = [56, 128, 0, 1, 56, 132, 0, 1, 72, 0, 191, 249, 56, 128, 0, 1, 56, 165, 0, 1, 72, 0, 191, 249] self.assertEqual(encoding, expected_encoding)
def runTest(self): ks = Ks(KS_ARCH_ARM, KS_MODE_ARM) encoding, count = ks.asm(self.asm, 0xc0000000) expected_encoding = [48, 0, 160, 227, 91, 172, 33, 235, 16, 0, 0, 230, 65, 0, 160, 227, 84, 172, 33, 235] self.assertEqual(encoding, expected_encoding)
from keystone import Ks, KS_ARCH_ARM, KS_MODE_ARM asm = Ks(KS_ARCH_ARM, KS_MODE_ARM) code = '''mov r0, #0x37; sub r1, r2, r3''' asm_code = asm.asm(code) print(asm_code) print(bytes(asm_code[0]))
def create_assembler(self) -> Ks: return Ks(KS_ARCH_ARM, KS_MODE_ARM + KS_MODE_THUMB)
ARM_CODE = """ // n is r0, we will pass it from python, ans is r1 mov r1, 1 // ans = 1 loop: cmp r0, 0 // while n >= 0: mulgt r1, r1, r0 // ans *= n subgt r0, r0, 1 // n = n - 1 bgt loop // // answer is in r1 """ print("Assembling the ARM code") try: # initialize the keystone object with the ARM architecture ks = Ks(KS_ARCH_ARM, KS_MODE_ARM) # Assemble the ARM code ARM_BYTECODE, _ = ks.asm(ARM_CODE) # convert the array of integers into bytes ARM_BYTECODE = bytes(ARM_BYTECODE) print(f"Code successfully assembled (length = {len(ARM_BYTECODE)})") print("ARM bytecode:", ARM_BYTECODE) except KsError as e: print("Keystone Error: %s" % e) exit(1) # memory address where emulation starts ADDRESS = 0x1000000 print("Emulating the ARM code") try:
import unittest import struct from functools import wraps from manticore.core.cpu.arm import Armv7Cpu as Cpu, Mask, Interruption from manticore.core.memory import Memory32 from capstone.arm import * from keystone import Ks, KS_ARCH_ARM, KS_MODE_ARM ks = Ks(KS_ARCH_ARM, KS_MODE_ARM) import logging logger = logging.getLogger("ARM_TESTS") def assemble(asm): ords = ks.asm(asm)[0] if not ords: raise Exception('bad assembly: {}'.format(asm)) return ''.join(map(chr, ords)) class Armv7CpuTest(unittest.TestCase): def setUp(self): self.c = Cpu(Memory32()) self.rf = self.c.regfile self._setupStack() def _setupStack(self):
from roppylib.util.misc import tobytes from roppylib.log import getLogger from roppylib.context import context from keystone import Ks, KS_ARCH_X86, KS_MODE_32, KS_MODE_64 from capstone import Cs, CS_ARCH_X86, CS_MODE_32, CS_MODE_64 log = getLogger(__name__) cmd = { 'i386': { "disasm": Cs(CS_ARCH_X86, CS_MODE_32), "asm": Ks(KS_ARCH_X86, KS_MODE_32) }, 'amd64': { "disasm": Cs(CS_ARCH_X86, CS_MODE_64), "asm": Ks(KS_ARCH_X86, KS_MODE_64) } } def asm(s, arch=None): """ Assemble a string of opcode of given architecture Example: >>> from roppy import * >>> sc = ''' ... xor eax,eax ... push eax ... push 0x68732f2f ... push 0x6e69622f ... mov ebx,esp
def asm(code, addr=0x0): ks = Ks(KS_ARCH_ARM, KS_MODE_ARM) encoding, count = ks.asm(code, addr=addr) return encoding
def assembler(self) -> Ks: return Ks(KS_ARCH_ARM64, KS_MODE_ARM)
import binascii from keystone import Ks, KS_ARCH_ARM, KS_MODE_ARM ks = Ks(KS_ARCH_ARM, KS_MODE_ARM) assembly_text = \ """ sub sp, sp, #8 push {sp, lr} bl #0xc6ab8 ldr lr, [sp, #4] add sp, sp, #8 pop {r2, r3} bx lr """ for i in range(100): output = ks.asm(assembly_text, 0x902c4, as_bytes=True) # print("{}: {}: {}".format(i, assembly_text, output)) output_2 = ks.asm("b #0", 0x4, as_bytes=True) # print("{}: {}: {}".format(i, "b #0", output_2))
def create_assembler(self) -> Ks: if not self._asm: self._asm = Ks(KS_ARCH_X86, KS_MODE_32) return self._asm
def assemble(code, entry_point): ks = Ks(KS_ARCH_X86, KS_MODE_32) asm = "%s JMP offset_%s; %s" % (_init(), entry_point, code) # print asm.replace("; ", "\n").replace(";", "\n") return "".join(map(chr, ks.asm(asm)[0]))
def assembler(self) -> Ks: return Ks(KS_ARCH_X86, KS_MODE_32)
import os import struct from capstone import CS_MODE_THUMB, CS_MODE_ARM from functools import wraps from keystone import Ks, KS_ARCH_ARM, KS_MODE_ARM, KS_MODE_THUMB from unicorn import UC_QUERY_MODE, UC_MODE_THUMB from manticore.native.cpu.abstractcpu import ConcretizeRegister from manticore.native.cpu.arm import Armv7Cpu as Cpu, Mask, Interruption from manticore.core.smtlib import ConstraintSet from manticore.native.state import State from manticore.native.memory import ConcretizeMemory, Memory32 from manticore.platforms import linux from manticore.utils.fallback_emulator import UnicornEmulator ks = Ks(KS_ARCH_ARM, KS_MODE_ARM) ks_thumb = Ks(KS_ARCH_ARM, KS_MODE_THUMB) import logging logger = logging.getLogger("ARM_TESTS") __doc__ = ''' Test the Unicorn emulation stub. Armv7UnicornInstructions includes all semantics from ARM tests to ensure that they match. UnicornConcretization tests to make sure symbolic values get properly concretized. ''' def assemble(asm, mode=CS_MODE_ARM): if CS_MODE_ARM == mode: