def load_pe_binary(self, pe): "load the program into virtual memory (populate the mmap dict)" p = Task(pe, cpu) p.OS = self # create text and data segments according to elf header: for s in pe.sections: ms = pe.loadsegment(s, pe.Opt.SectionAlignment) if ms != None: vaddr, data = ms.popitem() p.state.mmap.write(vaddr, data) # init task state: p.state[cpu.rip] = cpu.cst(pe.Opt.AddressOfEntryPoint, 64) p.state[cpu.rbp] = cpu.cst(0, 64) p.state[cpu.rax] = cpu.cst(0, 64) p.state[cpu.rbx] = cpu.cst(0, 64) p.state[cpu.rcx] = cpu.cst(0, 64) p.state[cpu.rdx] = cpu.cst(0, 64) p.state[cpu.rsi] = cpu.cst(0, 64) p.state[cpu.rdi] = cpu.cst(0, 64) # create the stack space: if self.ASLR: p.state.mmap.newzone(p.cpu.rsp) else: ssz = pe.Opt.SizeOfStackReserve stack_base = 0x00007fffffffffff & ~(self.PAGESIZE - 1) stack_size = pe.Opt.SizeOfStackReserve p.state.mmap.write(stack_base - stack_size, b'\0' * stack_size) p.state[cpu.esp] = cpu.cst(stack_base, 64) # create the dynamic segments: if len(pe.functions) > 0: self.load_pe_iat(p) # start task: self.tasks.append(p) return p
def load_macho_binary(self, bprm): "load the program into virtual memory (populate the mmap dict)" p = Task(bprm, cpu) p.OS = self do_stack = False interp = None # do load commands: for s in bprm.cmds: if s.cmd == LC_LOAD_DYLINKER: interp = s.offset elif s.cmd == LC_SEGMENT_64: if s.segname.startswith(b"__PAGEZERO\0"): continue data = bprm.readsegment(s).ljust(s.vmsize, b"\0") p.state.mmap.write(s.vmaddr, data) elif s.cmd in (LC_THREAD, LC_UNIXTHREAD): if s.flavor == x86_THREAD_STATE64: for f in s.state.fields: r = getattr(cpu, f.name) p.state[r] = cpu.cst(s.state[f.name], r.size) bprm.__entry = p.state[cpu.rip] if s.cmd == LC_UNIXTHREAD: do_stack = True stack_size = 2 * self.PAGESIZE elif s.cmd == LC_MAIN: entry = bprm.entrypoints[0] p.state[cpu.rip] = cpu.cst(entry, 64) bprm.__entry = p.state[cpu.rip] if s.stacksize: do_stack = True stack_size = s.stacksize # create the stack space: if do_stack: if self.ASLR: p.state.mmap.newzone(p.cpu.rsp) p.state[cpu.rsp] = cpu.rsp else: stack_base = 0x00007FFFFFFFFFFF & ~(self.PAGESIZE - 1) p.state.mmap.write(stack_base - stack_size, b"\0" * stack_size) p.state[cpu.rsp] = cpu.cst(stack_base, 64) # create the dynamic segments: if bprm.dynamic and interp: self.load_macho_interp(p, interp) # return task: self.tasks.append(p) return p
def test_decoder_025(): c = codecs.decode('4c69f1020000f0', 'hex') i = cpu.disassemble(c) assert i.mnemonic == 'IMUL' assert i.operands[0].ref == 'r14' assert i.operands[1].ref == 'rcx' assert i.operands[2].size == 64 assert i.operands[2] == cpu.cst(0xf0000002, 32).signextend(64)
def initenv(self): from amoco.cas.mapper import mapper m = mapper() for k, v in ((cpu.rip, cpu.cst(self.bin.entrypoints[0], 64)), (cpu.rbp, cpu.cst(0, 64)), (cpu.rax, cpu.cst(0, 64)), (cpu.rbx, cpu.cst(0, 64)), (cpu.rcx, cpu.cst(0, 64)), (cpu.rdx, cpu.cst(0, 64)), (cpu.rsi, cpu.cst(0, 64)), (cpu.rdi, cpu.cst(0, 64))): m[k] = v return m
def test_decoder_026(): c = b'\x66\x41\xc7\x84\x55\x11\x11\x11\x11\x22\x22' i = cpu.disassemble(c) assert i.mnemonic == 'MOV' assert i.operands[0]._is_mem assert i.operands[0].size == 16 assert i.operands[0].a.base == cpu.r13 + (cpu.rdx * 2) assert i.operands[0].a.disp == 0x11111111 assert i.operands[1] == cpu.cst(0x2222, 16)
def seqhelper(self, seq): for i in seq: # some basic hints: if i.mnemonic.startswith('RET'): i.misc[tag.FUNC_END] = 1 continue elif i.mnemonic in ('PUSH', 'ENTER'): i.misc[tag.FUNC_STACK] = 1 if i.operands and i.operands[0] is cpu.rbp: i.misc[tag.FUNC_START] = 1 continue elif i.mnemonic in ('POP', 'LEAVE'): i.misc[tag.FUNC_UNSTACK] = 1 if i.operands and i.operands[0] is cpu.rbp: i.misc[tag.FUNC_END] = 1 continue # provide hints of absolute location from relative offset: elif i.mnemonic in ('CALL', 'JMP', 'Jcc'): if i.mnemonic == 'CALL': i.misc[tag.FUNC_CALL] = 1 i.misc['retto'] = i.address + i.length else: i.misc[tag.FUNC_GOTO] = 1 if i.mnemonic == 'Jcc': i.misc['cond'] = i.cond if (i.address is not None) and i.operands[0]._is_cst: v = i.address + i.operands[0].signextend(64) + i.length x = self.check_sym(v) if x is not None: v = x i.misc['to'] = v if i.misc[tag.FUNC_CALL] and i.misc['retto'] == v: # this looks like a fake call i.misc[tag.FUNC_CALL] = -1 continue # check operands (globals & .got calls): for op in i.operands: if op._is_mem: if op.a.base is cpu.rbp: if op.a.disp < 0: i.misc[tag.FUNC_ARG] = 1 else: i.misc[tag.FUNC_VAR] = 1 elif op.a.base is cpu.rip and (i.address is not None): v = cpu.cst( 0, op.a.base.size) + i.address + i.length + op.a.disp x = self.check_sym(v) if x is not None: v = x op.a.base = v op.a.disp = 0 i.misc['rip_rel'] = v elif op.a.base._is_cst: x = self.check_sym(op.a.base) if x is not None: op.a.base = x elif op._is_cst: x = self.check_sym(op) i.misc['imm_ref'] = x return seq
def initenv(self): from amoco.cas.mapper import mapper m = mapper() for k,v in ((cpu.rip, cpu.cst(self.bin.entrypoints[0],64)), (cpu.rbp, cpu.cst(0,64)), (cpu.rax, cpu.cst(0,64)), (cpu.rbx, cpu.cst(0,64)), (cpu.rcx, cpu.cst(0,64)), (cpu.rdx, cpu.cst(0,64)), (cpu.rsi, cpu.cst(0,64)), (cpu.rdi, cpu.cst(0,64))): m[k] = v return m
def load_elf_binary(self, bprm): "load the program into virtual memory (populate the mmap dict)" p = Task(bprm, cpu) p.OS = self # create text and data segments according to elf header: for s in bprm.Phdr: if s.p_type == PT_INTERP: interp = bprm.readsegment(s).strip(b"\0") elif s.p_type == PT_LOAD: ms = bprm.loadsegment(s, self.PAGESIZE) if ms != None: vaddr, data = ms.popitem() p.state.mmap.write(vaddr, data) elif s.p_type == PT_GNU_STACK: # executable_stack = s.p_flags & PF_X pass # init task state: p.state[cpu.rip] = cpu.cst(p.bin.entrypoints[0], 64) p.state[cpu.rbp] = cpu.cst(0, 64) p.state[cpu.rax] = cpu.cst(0, 64) p.state[cpu.rbx] = cpu.cst(0, 64) p.state[cpu.rcx] = cpu.cst(0, 64) p.state[cpu.rdx] = cpu.cst(0, 64) p.state[cpu.rsi] = cpu.cst(0, 64) p.state[cpu.rdi] = cpu.cst(0, 64) p.state[cpu.r8] = cpu.cst(0, 64) p.state[cpu.r9] = cpu.cst(0, 64) p.state[cpu.r10] = cpu.cst(0, 64) p.state[cpu.r11] = cpu.cst(0, 64) p.state[cpu.r12] = cpu.cst(0, 64) p.state[cpu.r13] = cpu.cst(0, 64) p.state[cpu.r14] = cpu.cst(0, 64) p.state[cpu.r15] = cpu.cst(0, 64) p.state[cpu.rflags] = cpu.cst(0, 64) # create the stack space: if self.ASLR: p.state.mmap.newzone(p.cpu.rsp) else: stack_base = 0x00007FFFFFFFFFFF & ~(self.PAGESIZE - 1) stack_size = 2 * self.PAGESIZE p.state.mmap.write(stack_base - stack_size, b"\0" * stack_size) p.state[cpu.rsp] = cpu.cst(stack_base, 64) # create the dynamic segments: if bprm.dynamic and interp: self.load_elf_interp(p, interp) # return task: self.tasks.append(p) return p
def use_x64(self): from amoco.arch.x64 import cpu_x64 self.cpu = cpu_x64 self.state[cpu_x64.rip] = cpu_x64.cst(0,32)