def set_execstack(self, enabled: bool) -> bool: """ 开启或关闭execstack(只支持ELF) :param enabled: 是否开启execstack :return: """ for seg in self.ldr.binary.segments: # 查找GNU_STACK类型的segment if seg.type == lief.ELF.SEGMENT_TYPES.GNU_STACK: # dump ph_data,并修改flags old_ph_data = self._dump_segment(seg) if enabled: seg.flags = lief.ELF.SEGMENT_FLAGS(7) # rwx else: seg.flags = lief.ELF.SEGMENT_FLAGS(6) # rw- new_ph_data = self._dump_segment(seg) # 更新ph_data if not self._update_segment(old_ph_data, new_ph_data): log.fail("Modify segment failed") return False if enabled: log.success("Set execstack -> enabled") else: log.success("Set execstack -> disabled") return True log.fail("Can't find GNU_STACK segment") return False
def add_asm(self, asm: str, label: str = None) -> int: try: target_vaddr = self._add_asm(asm) except AddException as ex: log.fail(ex) return 0 if not target_vaddr: log.fail("Add asm @ {} failed".format(hex(target_vaddr))) return 0 self._label(target_vaddr, label) log.success("Add asm @ {}".format(hex(target_vaddr))) return target_vaddr
def patch_asm(self, vaddr: int, asm: str, label: str = None) -> bool: byte_code, inst_cnt = self._asm(asm, vaddr) if not inst_cnt: return False try: self._patch_byte(vaddr, byte_code) except PatchException as ex: log.fail(ex) return False self._label(vaddr, label) log.success("Patch {} asm @ {}".format(hex(inst_cnt), hex(vaddr))) return True
def patch_byte(self, vaddr: int, byte: str or bytes or bytearray, label: str = None) -> bool: try: self._patch_byte(vaddr, byte) except PatchException as ex: log.fail(ex) return False self._label(vaddr, label) log.success("Patch {} bytes @ {}".format(hex(len(byte)), hex(vaddr))) return True
def _asm(self, asm: str, vma: int) -> (bytes, int): """ 将汇编代码转换为机器码 :param asm: 汇编代码 :param vma: 虚拟地址 :return: (机器码,机器码长度) """ try: asm_formatted = asm.format(**self.symbols) except KeyError as ex: log.fail("Can't find symbol {}".format(ex)) return bytes(), 0 return self.ldr.ks.asm(asm_formatted, vma, True)
def add_c(self, c_code: str, label: str = None) -> int: try: compiled_bytes = self._call_scc(c_code) target_vaddr = self._add_byte(compiled_bytes) except SccException as ex: log.fail(ex) return 0 except AddException as ex: log.fail(ex) return 0 self._label(target_vaddr, label) log.success("Add c_code @ {}".format(hex(target_vaddr))) return target_vaddr
def add_segment(self, addr: int = 0, length: int = 0x1000, prot: int = 7) -> int: """ 新增一个段 :param addr: 虚拟地址,默认为0表示自动计算 :param length: 长度,默认0x1000 :param prot: 保护权限,默认rwx :return: 成功则返回申请的地址,失败返回0 """ if addr & 0xfff: log.fail("address {} is not page aligned".format(hex(addr))) return 0 return self._add_segment(addr, length, prot)
def add_byte(self, byte: str or bytes or bytearray, label: str = None) -> int: try: target_vaddr = self._add_byte(byte) except AddException as ex: log.fail(ex) return 0 if not target_vaddr: log.fail("Add {} bytes @ {} failed".format(hex(len(byte)), hex(target_vaddr))) return 0 self._label(target_vaddr, label) log.success("Add {} bytes @ {}".format(hex(len(byte)), hex(target_vaddr))) return target_vaddr
def set_norelro(self) -> bool: """ 取消ELF的relro :return: """ for seg in self.ldr.binary.segments: if seg.type == lief.ELF.SEGMENT_TYPES.GNU_RELRO: old_ph_data = self._dump_segment(seg) seg.type = lief.ELF.SEGMENT_TYPES.NULL new_ph_data = self._dump_segment(seg) if not self._update_segment(old_ph_data, new_ph_data): log.fail("Modify segment failed") return False log.success("Set norelro -> enabled") return True log.fail("Can't find GNU_RELRO segment") return False
def hook_asm(self, vaddr: int, asm: str, label: str = None) -> bool: """ 在指定地址插入asm作为hook代码 :param vaddr: 虚拟地址 :param asm: 汇编代码 :param label: 此hook的名字,后续在asm中可以以{name}的方式引用这个hook的地址 :return: """ if self.ldr.arch in [Arch.I386, Arch.AMD64]: if self._hook_asm_intel(vaddr, asm): self._label(vaddr, label) log.success("Hook @ {}".format(hex(vaddr))) return True else: log.fail("Hook @ {} failed".format(hex(vaddr))) return False else: raise TODOException("Only support hook i386 & amd64 for now")
def patch_c(self, vaddr: int, c_code: str, label: str = None) -> bool: try: compiled_bytes = self._call_scc(c_code) except SccException as ex: log.fail(ex) return False if not compiled_bytes: log.fail("call scc to generate binary code failed") return False try: self._patch_byte(vaddr, compiled_bytes) except PatchException as ex: log.fail(ex) return False self._label(vaddr, label) log.success("Patch c code @ {}".format(hex(vaddr))) return True
def label(self, vaddr: int, label_name: str) -> bool: if self._label(vaddr, label_name): log.success("name {} with {}".format(hex(vaddr), label_name)) return True log.fail("name {} with {} failed".format(hex(vaddr), label_name)) return False