Skip to content

Commit

Permalink
move arch info into seperate component, rename x86 archs
Browse files Browse the repository at this point in the history
  • Loading branch information
DennyDai committed Feb 28, 2024
1 parent 9075aaa commit d26942e
Show file tree
Hide file tree
Showing 39 changed files with 175 additions and 106 deletions.
Empty file.
6 changes: 6 additions & 0 deletions src/patcherex2/components/archinfo/aarch64.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class Aarch64Info:
nop_bytes = b"\x1f\x20\x03\xd5"
nop_size = 4
jmp_asm = "b {dst}"
jmp_size = 4
call_asm = "bl {dst}"
6 changes: 6 additions & 0 deletions src/patcherex2/components/archinfo/amd64.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class Amd64Info:
nop_bytes = b"\x90"
nop_size = 1
jmp_asm = "jmp {dst}"
jmp_size = 6
call_asm = "call {dst}"
6 changes: 6 additions & 0 deletions src/patcherex2/components/archinfo/arm.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class ArmInfo:
nop_bytes = b"\x00\xF0\x20\xE3" # TODO: thumb
nop_size = 4
jmp_asm = "b {dst}"
jmp_size = 4
call_asm = "bl {dst}"
7 changes: 7 additions & 0 deletions src/patcherex2/components/archinfo/mips.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class MipsInfo:
nop_bytes = b"\x00\x00\x00\x00"
nop_size = 4
jmp_asm = "j {dst}"
# NOTE: keystone will always add nop for branch delay slot, so include it in size
jmp_size = 8
call_asm = "jal {dst}"
7 changes: 7 additions & 0 deletions src/patcherex2/components/archinfo/mips64.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class Mips64Info:
nop_bytes = b"\x00\x00\x00\x00"
nop_size = 4
jmp_asm = "j {dst}"
# NOTE: keystone will always add nop for branch delay slot, so include it in size
jmp_size = 8
call_asm = "jal {dst}"
6 changes: 6 additions & 0 deletions src/patcherex2/components/archinfo/ppc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class PpcInfo:
nop_bytes = b"\x60\x00\x00\x00"
nop_size = 4
jmp_asm = "b {dst}"
jmp_size = 4
call_asm = "bl {dst}"
6 changes: 6 additions & 0 deletions src/patcherex2/components/archinfo/ppc64.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class Ppc64Info:
nop_bytes = b"\x60\x00\x00\x00"
nop_size = 4
jmp_asm = "b {dst}"
jmp_size = 4
call_asm = "bl {dst}"
6 changes: 6 additions & 0 deletions src/patcherex2/components/archinfo/ppc_vle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class PpcVleInfo:
nop_bytes = b"\x01\x00\x00\x00"
nop_size = 4
jmp_asm = "b {dst}"
jmp_size = 4
call_asm = "bl {dst}"
6 changes: 6 additions & 0 deletions src/patcherex2/components/archinfo/sparc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class SparcInfo:
nop_bytes = b"\x01\x00\x00\x00"
nop_size = 4
jmp_asm = "b {dst}\nnop" # nop due to delay slot
jmp_size = 8
call_asm = "call {dst}"
6 changes: 6 additions & 0 deletions src/patcherex2/components/archinfo/x86.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class X86Info:
nop_bytes = b"\x90"
nop_size = 1
jmp_asm = "jmp {dst}"
jmp_size = 5
call_asm = "call {dst}"
6 changes: 3 additions & 3 deletions src/patcherex2/components/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def insert_trampoline_code(
+ "\n"
+ moved_instrs
+ "\n"
+ self.p.target.JMP_ASM.format(dst=hex(addr + moved_instrs_len))
+ self.p.archinfo.jmp_asm.format(dst=hex(addr + moved_instrs_len))
)
trampoline_size = (
len(
Expand Down Expand Up @@ -84,7 +84,7 @@ def insert_trampoline_code(
)
self.p.binfmt_tool.update_binary_content(file_addr, trampoline_bytes)
jmp_to_trampoline = self.p.assembler.assemble(
self.p.target.JMP_ASM.format(dst=hex(mem_addr)),
self.p.archinfo.jmp_asm.format(dst=hex(mem_addr)),
addr,
is_thumb=self.p.binary_analyzer.is_thumb(addr),
)
Expand All @@ -97,7 +97,7 @@ def get_instrs_to_be_moved(
) -> Optional[str]:
basic_block = self.p.binary_analyzer.get_basic_block(addr)
idx = basic_block["instruction_addrs"].index(addr)
end = addr + self.p.target.JMP_SIZE
end = addr + self.p.archinfo.jmp_size
instrs = b""

for insn_addr in basic_block["instruction_addrs"][idx:] + [basic_block["end"]]:
Expand Down
1 change: 1 addition & 0 deletions src/patcherex2/patcherex.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def __init__(
"allocation_manager",
"binfmt_tool",
"utils",
"archinfo",
]
for component in components:
setattr(
Expand Down
6 changes: 4 additions & 2 deletions src/patcherex2/patches/function_patches.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def apply(self, p) -> None:
else:
mem_addr = self.detour_pos
file_addr = p.binary_analyzer.mem_addr_to_file_offset(mem_addr)
jmp_instr = p.target.JMP_ASM.format(dst=hex(mem_addr))
jmp_instr = p.archinfo.jmp_asm.format(dst=hex(mem_addr))
jmp_bytes = p.assembler.assemble(
jmp_instr,
func["addr"],
Expand Down Expand Up @@ -100,7 +100,9 @@ def apply(self, p) -> None:
ifp.apply(p)
instrs = self.prefunc if self.prefunc else ""
instrs += "\n"
instrs += p.target.CALL_ASM.format(dst=f"{{__patcherex_{hex(self.addr)}}}")
instrs += p.archinfo.call_asm.format(
dst=f"{{__patcherex_{hex(self.addr)}}}"
)
instrs += "\n"
instrs += self.postfunc if self.postfunc else ""
p.utils.insert_trampoline_code(
Expand Down
8 changes: 4 additions & 4 deletions src/patcherex2/patches/instruction_patches.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,10 @@ def __init__(
def apply(self, p):
if self.num_bytes is None:
raise NotImplementedError()
if self.num_bytes and self.num_bytes % p.target.NOP_SIZE != 0:
if self.num_bytes and self.num_bytes % p.archinfo.nop_size != 0:
raise Exception(
f"Cannot remove {self.num_bytes} bytes, must be a multiple of {p.target.NOP_SIZE}"
f"Cannot remove {self.num_bytes} bytes, must be a multiple of {p.archinfo.nop_size}"
)
num_nops = self.num_bytes // p.target.NOP_SIZE
num_nops = self.num_bytes // p.archinfo.nop_size
offset = p.binary_analyzer.mem_addr_to_file_offset(self.addr)
p.binfmt_tool.update_binary_content(offset, p.target.NOP_BYTES * num_nops)
p.binfmt_tool.update_binary_content(offset, p.archinfo.nop_bytes * num_nops)
12 changes: 6 additions & 6 deletions src/patcherex2/targets/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from .elf_arm_linux import ElfArmLinux
from .elf_arm_linux_recomp import ElfArmLinuxRecomp
from .elf_arm_mimxrt1052 import ElfArmMimxrt1052
from .elf_i386_linux import ElfI386Linux
from .elf_x86_linux import ElfX86Linux
from .elf_leon3_bare import ElfLeon3Bare
from .elf_mips64_linux import ElfMips64Linux
from .elf_mips64el_linux import ElfMips64elLinux
Expand All @@ -11,8 +11,8 @@
from .elf_ppc64_linux import ElfPpc64Linux
from .elf_ppc64le_linux import ElfPpc64leLinux
from .elf_ppc_linux import ElfPpcLinux
from .elf_x86_64_linux import ElfX8664Linux
from .elf_x86_64_linux_recomp import ElfX8664LinuxRecomp
from .elf_amd64_linux import ElfAmd64Linux
from .elf_amd64_linux_recomp import ElfAmd64LinuxRecomp
from .ihex_ppc_bare import IHexPPCBare
from .target import Target

Expand All @@ -21,7 +21,7 @@
"ElfArmLinux",
"ElfArmLinuxRecomp",
"ElfArmMimxrt1052",
"ElfI386Linux",
"ElfX86Linux",
"ElfLeon3Bare",
"ElfMips64Linux",
"ElfMips64elLinux",
Expand All @@ -30,8 +30,8 @@
"ElfPpc64Linux",
"ElfPpc64leLinux",
"ElfPpcLinux",
"ElfX8664Linux",
"ElfX8664LinuxRecomp",
"ElfAmd64Linux",
"ElfAmd64LinuxRecomp",
"IHexPPCBare",
"Target",
]
12 changes: 7 additions & 5 deletions src/patcherex2/targets/elf_aarch64_linux.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,11 @@
from ..components.compilers.clang import Clang
from ..components.disassemblers.capstone import Capstone, capstone
from ..components.utils.utils import Utils
from ..components.archinfo.aarch64 import Aarch64Info
from .target import Target


class ElfAArch64Linux(Target):
NOP_BYTES = b"\x1f\x20\x03\xd5"
NOP_SIZE = 4
JMP_ASM = "b {dst}"
JMP_SIZE = 4

@staticmethod
def detect_target(binary_path):
with open(binary_path, "rb") as f:
Expand Down Expand Up @@ -67,3 +63,9 @@ def get_utils(self, utils):
if utils == "default":
return Utils(self.p, self.binary_path)
raise NotImplementedError()

def get_archinfo(self, archinfo):
archinfo = archinfo or "default"
if archinfo == "default":
return Aarch64Info()
raise NotImplementedError()
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,11 @@
from ..components.compilers.clang import Clang
from ..components.disassemblers.capstone import Capstone, capstone
from ..components.utils.utils import Utils
from ..components.archinfo.amd64 import Amd64Info
from .target import Target


class ElfX8664Linux(Target):
NOP_BYTES = b"\x90"
NOP_SIZE = 1
JMP_ASM = "jmp {dst}"
JMP_SIZE = 6
CALL_ASM = "call {dst}"

class ElfAmd64Linux(Target):
@staticmethod
def detect_target(binary_path):
with open(binary_path, "rb") as f:
Expand Down Expand Up @@ -73,3 +68,9 @@ def get_utils(self, utils):
if utils == "default":
return Utils(self.p, self.binary_path)
raise NotImplementedError()

def get_archinfo(self, archinfo):
archinfo = archinfo or "default"
if archinfo == "default":
return Amd64Info()
raise NotImplementedError()
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from ..components.binary_analyzers.angr import Angr
from ..components.compilers.llvm_recomp import LLVMRecomp
from .elf_x86_64_linux import ElfX8664Linux
from .elf_amd64_linux import ElfAmd64Linux


class ElfX8664LinuxRecomp(ElfX8664Linux):
class ElfAmd64LinuxRecomp(ElfAmd64Linux):
@staticmethod
def detect_target(binary_path):
return False
Expand Down
13 changes: 7 additions & 6 deletions src/patcherex2/targets/elf_arm_linux.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,11 @@
from ..components.compilers.clang_arm import ClangArm
from ..components.disassemblers.capstone_arm import CapstoneArm
from ..components.utils.utils import Utils
from ..components.archinfo.arm import ArmInfo
from .target import Target


class ElfArmLinux(Target):
NOP_BYTES = b"\x00\xF0\x20\xE3" # TODO: thumb
NOP_SIZE = 4
JMP_ASM = "b {dst}"
JMP_SIZE = 4
CALL_ASM = "bl {dst}"

@staticmethod
def detect_target(binary_path):
with open(binary_path, "rb") as f:
Expand Down Expand Up @@ -66,3 +61,9 @@ def get_utils(self, utils):
if utils == "default":
return Utils(self.p, self.binary_path)
raise NotImplementedError()

def get_archinfo(self, archinfo):
archinfo = archinfo or "default"
if archinfo == "default":
return ArmInfo()
raise NotImplementedError()
13 changes: 7 additions & 6 deletions src/patcherex2/targets/elf_leon3_bare.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from ..components.compilers.bcc import Bcc as BccCompiler
from ..components.disassemblers.capstone import Capstone, capstone
from ..components.utils.utils import Utils
from ..components.archinfo.sparc import SparcInfo
from .target import Target

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -45,12 +46,6 @@ def _init_memory_analysis(self):


class ElfLeon3Bare(Target):
NOP_BYTES = b"\x01\x00\x00\x00"
NOP_SIZE = 4
JMP_ASM = "b {dst}\nnop" # nop due to delay slot
JMP_SIZE = 8
CALL_ASM = "call {dst}"

@staticmethod
def detect_target(binary_path):
with open(binary_path, "rb") as f:
Expand Down Expand Up @@ -109,3 +104,9 @@ def get_utils(self, utils):
if utils == "default":
return Utils(self.p, self.binary_path)
raise NotImplementedError()

def get_archinfo(self, archinfo):
archinfo = archinfo or "default"
if archinfo == "default":
return SparcInfo()
raise NotImplementedError()
14 changes: 7 additions & 7 deletions src/patcherex2/targets/elf_mips64_linux.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,11 @@
from ..components.compilers.clang import Clang
from ..components.disassemblers.capstone import Capstone, capstone
from ..components.utils.utils import Utils
from ..components.archinfo.mips64 import Mips64Info
from .target import Target


class ElfMips64Linux(Target):
NOP_BYTES = b"\x00\x00\x00\x00"
NOP_SIZE = 4
JMP_ASM = "j {dst}"
# NOTE: keystone will always add nop for branch delay slot, so include it in size
JMP_SIZE = 8
CALL_ASM = "jal {dst}"

@staticmethod
def detect_target(binary_path):
with open(binary_path, "rb") as f:
Expand Down Expand Up @@ -74,3 +68,9 @@ def get_utils(self, utils):
if utils == "default":
return Utils(self.p, self.binary_path)
raise NotImplementedError()

def get_archinfo(self, archinfo):
archinfo = archinfo or "default"
if archinfo == "default":
return Mips64Info()
raise NotImplementedError()
14 changes: 7 additions & 7 deletions src/patcherex2/targets/elf_mips64el_linux.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,11 @@
from ..components.compilers.clang import Clang
from ..components.disassemblers.capstone import Capstone, capstone
from ..components.utils.utils import Utils
from ..components.archinfo.mips64 import Mips64Info
from .target import Target


class ElfMips64elLinux(Target):
NOP_BYTES = b"\x00\x00\x00\x00"
NOP_SIZE = 4
JMP_ASM = "j {dst}"
# NOTE: keystone will always add nop for branch delay slot, so include it in size
JMP_SIZE = 8
CALL_ASM = "jal {dst}"

@staticmethod
def detect_target(binary_path):
with open(binary_path, "rb") as f:
Expand Down Expand Up @@ -74,3 +68,9 @@ def get_utils(self, utils):
if utils == "default":
return Utils(self.p, self.binary_path)
raise NotImplementedError()

def get_archinfo(self, archinfo):
archinfo = archinfo or "default"
if archinfo == "default":
return Mips64Info()
raise NotImplementedError()
14 changes: 7 additions & 7 deletions src/patcherex2/targets/elf_mips_linux.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,11 @@
from ..components.compilers.clang import Clang
from ..components.disassemblers.capstone import Capstone, capstone
from ..components.utils.utils import Utils
from ..components.archinfo.mips import MipsInfo
from .target import Target


class ElfMipsLinux(Target):
NOP_BYTES = b"\x00\x00\x00\x00"
NOP_SIZE = 4
JMP_ASM = "j {dst}"
# NOTE: keystone will always add nop for branch delay slot, so include it in size
JMP_SIZE = 8
CALL_ASM = "jal {dst}"

@staticmethod
def detect_target(binary_path):
with open(binary_path, "rb") as f:
Expand Down Expand Up @@ -74,3 +68,9 @@ def get_utils(self, utils):
if utils == "default":
return Utils(self.p, self.binary_path)
raise NotImplementedError()

def get_archinfo(self, archinfo):
archinfo = archinfo or "default"
if archinfo == "default":
return MipsInfo()
raise NotImplementedError()
Loading

0 comments on commit d26942e

Please sign in to comment.