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 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 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 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 asm(code, addr=0x0): ks = Ks(KS_ARCH_ARM, KS_MODE_ARM) encoding, count = ks.asm(code, addr=addr) return encoding
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
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 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]))
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))
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]))
// 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: # Initialize emulator in ARM mode mu = Uc(UC_ARCH_ARM, UC_MODE_ARM)
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 new_section.sh_size = len(new_section.data) new_section.sh_addralign = 16 new_section.sh_type = 0x1 # PROGBITS