include ROPGadget

This commit is contained in:
Liam Dalgarno
2020-11-25 15:38:46 +00:00
parent 688bb5a1be
commit 5f8099dde0
48 changed files with 3325 additions and 0 deletions

View File

@ -0,0 +1,12 @@
## -*- coding: utf-8 -*-
##
## Jonathan Salwan - 2014-05-12 - ROPgadget tool
##
## http://twitter.com/JonathanSalwan
## http://shell-storm.org/project/ROPgadget/
##
import ropgadget.loaders.elf
import ropgadget.loaders.macho
import ropgadget.loaders.pe
import ropgadget.loaders.raw

View File

@ -0,0 +1,350 @@
## -*- coding: utf-8 -*-
##
## Jonathan Salwan - 2014-05-12 - ROPgadget tool
##
## http://twitter.com/JonathanSalwan
## http://shell-storm.org/project/ROPgadget/
##
from capstone import *
from ctypes import *
from struct import unpack
class ELFFlags(object):
ELFCLASS32 = 0x01
ELFCLASS64 = 0x02
EI_CLASS = 0x04
EI_DATA = 0x05
ELFDATA2LSB = 0x01
ELFDATA2MSB = 0x02
EM_386 = 0x03
EM_X86_64 = 0x3e
EM_ARM = 0x28
EM_MIPS = 0x08
EM_SPARCv8p = 0x12
EM_PowerPC = 0x14
EM_ARM64 = 0xb7
class Elf32_Ehdr_LSB(LittleEndianStructure):
_fields_ = [
("e_ident", c_ubyte * 16),
("e_type", c_ushort),
("e_machine", c_ushort),
("e_version", c_uint),
("e_entry", c_uint),
("e_phoff", c_uint),
("e_shoff", c_uint),
("e_flags", c_uint),
("e_ehsize", c_ushort),
("e_phentsize", c_ushort),
("e_phnum", c_ushort),
("e_shentsize", c_ushort),
("e_shnum", c_ushort),
("e_shstrndx", c_ushort)
]
class Elf64_Ehdr_LSB(LittleEndianStructure):
_fields_ = [
("e_ident", c_ubyte * 16),
("e_type", c_ushort),
("e_machine", c_ushort),
("e_version", c_uint),
("e_entry", c_ulonglong),
("e_phoff", c_ulonglong),
("e_shoff", c_ulonglong),
("e_flags", c_uint),
("e_ehsize", c_ushort),
("e_phentsize", c_ushort),
("e_phnum", c_ushort),
("e_shentsize", c_ushort),
("e_shnum", c_ushort),
("e_shstrndx", c_ushort)
]
class Elf32_Phdr_LSB(LittleEndianStructure):
_fields_ = [
("p_type", c_uint),
("p_offset", c_uint),
("p_vaddr", c_uint),
("p_paddr", c_uint),
("p_filesz", c_uint),
("p_memsz", c_uint),
("p_flags", c_uint),
("p_align", c_uint)
]
class Elf64_Phdr_LSB(LittleEndianStructure):
_fields_ = [
("p_type", c_uint),
("p_flags", c_uint),
("p_offset", c_ulonglong),
("p_vaddr", c_ulonglong),
("p_paddr", c_ulonglong),
("p_filesz", c_ulonglong),
("p_memsz", c_ulonglong),
("p_align", c_ulonglong)
]
class Elf32_Shdr_LSB(LittleEndianStructure):
_fields_ = [
("sh_name", c_uint),
("sh_type", c_uint),
("sh_flags", c_uint),
("sh_addr", c_uint),
("sh_offset", c_uint),
("sh_size", c_uint),
("sh_link", c_uint),
("sh_info", c_uint),
("sh_addralign", c_uint),
("sh_entsize", c_uint)
]
class Elf64_Shdr_LSB(LittleEndianStructure):
_fields_ = [
("sh_name", c_uint),
("sh_type", c_uint),
("sh_flags", c_ulonglong),
("sh_addr", c_ulonglong),
("sh_offset", c_ulonglong),
("sh_size", c_ulonglong),
("sh_link", c_uint),
("sh_info", c_uint),
("sh_addralign", c_ulonglong),
("sh_entsize", c_ulonglong)
]
class Elf32_Ehdr_MSB(BigEndianStructure):
_fields_ = [
("e_ident", c_ubyte * 16),
("e_type", c_ushort),
("e_machine", c_ushort),
("e_version", c_uint),
("e_entry", c_uint),
("e_phoff", c_uint),
("e_shoff", c_uint),
("e_flags", c_uint),
("e_ehsize", c_ushort),
("e_phentsize", c_ushort),
("e_phnum", c_ushort),
("e_shentsize", c_ushort),
("e_shnum", c_ushort),
("e_shstrndx", c_ushort)
]
class Elf64_Ehdr_MSB(BigEndianStructure):
_fields_ = [
("e_ident", c_ubyte * 16),
("e_type", c_ushort),
("e_machine", c_ushort),
("e_version", c_uint),
("e_entry", c_ulonglong),
("e_phoff", c_ulonglong),
("e_shoff", c_ulonglong),
("e_flags", c_uint),
("e_ehsize", c_ushort),
("e_phentsize", c_ushort),
("e_phnum", c_ushort),
("e_shentsize", c_ushort),
("e_shnum", c_ushort),
("e_shstrndx", c_ushort)
]
class Elf32_Phdr_MSB(BigEndianStructure):
_fields_ = [
("p_type", c_uint),
("p_offset", c_uint),
("p_vaddr", c_uint),
("p_paddr", c_uint),
("p_filesz", c_uint),
("p_memsz", c_uint),
("p_flags", c_uint),
("p_align", c_uint)
]
class Elf64_Phdr_MSB(BigEndianStructure):
_fields_ = [
("p_type", c_uint),
("p_flags", c_uint),
("p_offset", c_ulonglong),
("p_vaddr", c_ulonglong),
("p_paddr", c_ulonglong),
("p_filesz", c_ulonglong),
("p_memsz", c_ulonglong),
("p_align", c_ulonglong)
]
class Elf32_Shdr_MSB(BigEndianStructure):
_fields_ = [
("sh_name", c_uint),
("sh_type", c_uint),
("sh_flags", c_uint),
("sh_addr", c_uint),
("sh_offset", c_uint),
("sh_size", c_uint),
("sh_link", c_uint),
("sh_info", c_uint),
("sh_addralign", c_uint),
("sh_entsize", c_uint)
]
class Elf64_Shdr_MSB(BigEndianStructure):
_fields_ = [
("sh_name", c_uint),
("sh_type", c_uint),
("sh_flags", c_ulonglong),
("sh_addr", c_ulonglong),
("sh_offset", c_ulonglong),
("sh_size", c_ulonglong),
("sh_link", c_uint),
("sh_info", c_uint),
("sh_addralign", c_ulonglong),
("sh_entsize", c_ulonglong)
]
""" This class parses the ELF """
class ELF(object):
def __init__(self, binary):
self.__binary = bytearray(binary)
self.__ElfHeader = None
self.__shdr_l = []
self.__phdr_l = []
self.__setHeaderElf()
self.__setShdr()
self.__setPhdr()
""" Parse ELF header """
def __setHeaderElf(self):
e_ident = self.__binary[:15]
ei_class = e_ident[ELFFlags.EI_CLASS]
ei_data = e_ident[ELFFlags.EI_DATA]
if ei_class != ELFFlags.ELFCLASS32 and ei_class != ELFFlags.ELFCLASS64:
print("[Error] ELF.__setHeaderElf() - Bad Arch size")
return None
if ei_data != ELFFlags.ELFDATA2LSB and ei_data != ELFFlags.ELFDATA2MSB:
print("[Error] ELF.__setHeaderElf() - Bad architecture endian")
return None
if ei_class == ELFFlags.ELFCLASS32:
if ei_data == ELFFlags.ELFDATA2LSB: self.__ElfHeader = Elf32_Ehdr_LSB.from_buffer_copy(self.__binary)
elif ei_data == ELFFlags.ELFDATA2MSB: self.__ElfHeader = Elf32_Ehdr_MSB.from_buffer_copy(self.__binary)
elif ei_class == ELFFlags.ELFCLASS64:
if ei_data == ELFFlags.ELFDATA2LSB: self.__ElfHeader = Elf64_Ehdr_LSB.from_buffer_copy(self.__binary)
elif ei_data == ELFFlags.ELFDATA2MSB: self.__ElfHeader = Elf64_Ehdr_MSB.from_buffer_copy(self.__binary)
self.getArch() # Check if architecture is supported
""" Parse Section header """
def __setShdr(self):
shdr_num = self.__ElfHeader.e_shnum
base = self.__binary[self.__ElfHeader.e_shoff:]
shdr_l = []
e_ident = self.__binary[:15]
ei_data = e_ident[ELFFlags.EI_DATA]
for i in range(shdr_num):
if self.getArchMode() == CS_MODE_32:
if ei_data == ELFFlags.ELFDATA2LSB: shdr = Elf32_Shdr_LSB.from_buffer_copy(base)
elif ei_data == ELFFlags.ELFDATA2MSB: shdr = Elf32_Shdr_MSB.from_buffer_copy(base)
elif self.getArchMode() == CS_MODE_64:
if ei_data == ELFFlags.ELFDATA2LSB: shdr = Elf64_Shdr_LSB.from_buffer_copy(base)
elif ei_data == ELFFlags.ELFDATA2MSB: shdr = Elf64_Shdr_MSB.from_buffer_copy(base)
self.__shdr_l.append(shdr)
base = base[self.__ElfHeader.e_shentsize:]
# setup name from the strings table
if self.__ElfHeader.e_shstrndx != 0:
string_table = bytes(self.__binary[(self.__shdr_l[self.__ElfHeader.e_shstrndx].sh_offset):])
for i in range(shdr_num):
self.__shdr_l[i].str_name = string_table[self.__shdr_l[i].sh_name:].split(b'\x00')[0].decode('utf8')
""" Parse Program header """
def __setPhdr(self):
pdhr_num = self.__ElfHeader.e_phnum
base = self.__binary[self.__ElfHeader.e_phoff:]
phdr_l = []
e_ident = self.__binary[:15]
ei_data = e_ident[ELFFlags.EI_DATA]
for i in range(pdhr_num):
if self.getArchMode() == CS_MODE_32:
if ei_data == ELFFlags.ELFDATA2LSB: phdr = Elf32_Phdr_LSB.from_buffer_copy(base)
elif ei_data == ELFFlags.ELFDATA2MSB: phdr = Elf32_Phdr_MSB.from_buffer_copy(base)
elif self.getArchMode() == CS_MODE_64:
if ei_data == ELFFlags.ELFDATA2LSB: phdr = Elf64_Phdr_LSB.from_buffer_copy(base)
elif ei_data == ELFFlags.ELFDATA2MSB: phdr = Elf64_Phdr_MSB.from_buffer_copy(base)
self.__phdr_l.append(phdr)
base = base[self.__ElfHeader.e_phentsize:]
def getEntryPoint(self):
return self.__e_entry
def getExecSections(self):
ret = []
for segment in self.__phdr_l:
if segment.p_flags & 0x1:
ret += [{
"offset" : segment.p_offset,
"size" : segment.p_memsz,
"vaddr" : segment.p_vaddr,
"opcodes" : bytes(self.__binary[segment.p_offset:segment.p_offset+segment.p_memsz])
}]
return ret
def getDataSections(self):
ret = []
for section in self.__shdr_l:
if not (section.sh_flags & 0x4) and (section.sh_flags & 0x2):
ret += [{
"name" : section.str_name,
"offset" : section.sh_offset,
"size" : section.sh_size,
"vaddr" : section.sh_addr,
"opcodes" : bytes(self.__binary[section.sh_offset:section.sh_offset+section.sh_size])
}]
return ret
def getArch(self):
if self.__ElfHeader.e_machine == ELFFlags.EM_386 or self.__ElfHeader.e_machine == ELFFlags.EM_X86_64:
return CS_ARCH_X86
elif self.__ElfHeader.e_machine == ELFFlags.EM_ARM:
return CS_ARCH_ARM
elif self.__ElfHeader.e_machine == ELFFlags.EM_ARM64:
return CS_ARCH_ARM64
elif self.__ElfHeader.e_machine == ELFFlags.EM_MIPS:
return CS_ARCH_MIPS
elif self.__ElfHeader.e_machine == ELFFlags.EM_PowerPC:
return CS_ARCH_PPC
elif self.__ElfHeader.e_machine == ELFFlags.EM_SPARCv8p:
return CS_ARCH_SPARC
else:
print("[Error] ELF.getArch() - Architecture not supported")
return None
def getArchMode(self):
if self.__ElfHeader.e_ident[ELFFlags.EI_CLASS] == ELFFlags.ELFCLASS32:
return CS_MODE_32
elif self.__ElfHeader.e_ident[ELFFlags.EI_CLASS] == ELFFlags.ELFCLASS64:
return CS_MODE_64
else:
print("[Error] ELF.getArchMode() - Bad Arch size")
return None
def getEndian(self):
if self.__ElfHeader.e_ident[ELFFlags.EI_DATA] == ELFFlags.ELFDATA2LSB:
return 0
if self.__ElfHeader.e_ident[ELFFlags.EI_DATA] == ELFFlags.ELFDATA2MSB:
return CS_MODE_BIG_ENDIAN
print("[Error] ELF.getEndian() - Bad Endianness")
return None
def getFormat(self):
return "ELF"

View File

@ -0,0 +1,211 @@
## -*- coding: utf-8 -*-
##
## Jonathan Salwan - 2014-05-12 - ROPgadget tool
##
## http://twitter.com/JonathanSalwan
## http://shell-storm.org/project/ROPgadget/
##
from capstone import *
from ctypes import *
class MACH_HEADER(Structure):
_fields_ = [
("magic", c_uint),
("cputype", c_uint),
("cpusubtype", c_uint),
("filetype", c_uint),
("ncmds", c_uint),
("sizeofcmds", c_uint),
("flags", c_uint)
]
class LOAD_COMMAND(Structure):
_fields_ = [
("cmd", c_uint),
("cmdsize", c_uint)
]
class SEGMENT_COMMAND(Structure):
_fields_ = [
("cmd", c_uint),
("cmdsize", c_uint),
("segname", c_ubyte * 16),
("vmaddr", c_uint),
("vmsize", c_uint),
("fileoff", c_uint),
("filesize", c_uint),
("maxprot", c_uint),
("initprot", c_uint),
("nsects", c_uint),
("flags", c_uint)
]
class SEGMENT_COMMAND64(Structure):
_fields_ = [
("cmd", c_uint),
("cmdsize", c_uint),
("segname", c_ubyte * 16),
("vmaddr", c_ulonglong),
("vmsize", c_ulonglong),
("fileoff", c_ulonglong),
("filesize", c_ulonglong),
("maxprot", c_uint),
("initprot", c_uint),
("nsects", c_uint),
("flags", c_uint)
]
class SECTION(Structure):
_fields_ = [
("sectname", c_ubyte * 16),
("segname", c_ubyte * 16),
("addr", c_uint),
("size", c_uint),
("offset", c_uint),
("align", c_uint),
("reloff", c_uint),
("nreloc", c_uint),
("flags", c_uint),
("reserved1", c_uint),
("reserved2", c_uint)
]
class SECTION64(Structure):
_fields_ = [
("sectname", c_ubyte * 16),
("segname", c_ubyte * 16),
("addr", c_ulonglong),
("size", c_ulonglong),
("offset", c_uint),
("align", c_uint),
("reloff", c_uint),
("nreloc", c_uint),
("flags", c_uint),
("reserved1", c_uint),
("reserved2", c_uint)
]
class MACHOFlags(object):
CPU_TYPE_I386 = 0x7
CPU_TYPE_X86_64 = (CPU_TYPE_I386 | 0x1000000)
CPU_TYPE_MIPS = 0x8
CPU_TYPE_ARM = 12
CPU_TYPE_ARM64 = (CPU_TYPE_ARM | 0x1000000)
CPU_TYPE_SPARC = 14
CPU_TYPE_POWERPC = 18
CPU_TYPE_POWERPC64 = (CPU_TYPE_POWERPC | 0x1000000)
LC_SEGMENT = 0x1
LC_SEGMENT_64 = 0x19
S_ATTR_SOME_INSTRUCTIONS = 0x00000400
S_ATTR_PURE_INSTRUCTIONS = 0x80000000
""" This class parses the Mach-O """
class MACHO(object):
def __init__(self, binary):
self.__binary = bytearray(binary)
self.__machHeader = None
self.__rawLoadCmd = None
self.__sections_l = []
self.__setHeader()
self.__setLoadCmd()
def __setHeader(self):
self.__machHeader = MACH_HEADER.from_buffer_copy(self.__binary)
if self.getArchMode() == CS_MODE_32:
self.__rawLoadCmd = self.__binary[28:28+self.__machHeader.sizeofcmds]
elif self.getArchMode() == CS_MODE_64:
self.__rawLoadCmd = self.__binary[32:32+self.__machHeader.sizeofcmds]
def __setLoadCmd(self):
base = self.__rawLoadCmd
for i in range(self.__machHeader.ncmds):
command = LOAD_COMMAND.from_buffer_copy(base)
if command.cmd == MACHOFlags.LC_SEGMENT:
segment = SEGMENT_COMMAND.from_buffer_copy(base)
self.__setSections(segment, base[56:], 32)
elif command.cmd == MACHOFlags.LC_SEGMENT_64:
segment = SEGMENT_COMMAND64.from_buffer_copy(base)
self.__setSections(segment, base[72:], 64)
base = base[command.cmdsize:]
def __setSections(self, segment, base, sizeHeader):
for i in range(segment.nsects):
if sizeHeader == 32:
section = SECTION.from_buffer_copy(base)
section.offset = segment.fileoff + section.addr - segment.vmaddr
base = base[68:]
self.__sections_l += [section]
elif sizeHeader == 64:
section = SECTION64.from_buffer_copy(base)
section.offset = segment.fileoff + section.addr - segment.vmaddr
base = base[80:]
self.__sections_l += [section]
def getEntryPoint(self):
for section in self.__sections_l:
if section.sectname[0:6] == "__text":
return section.addr
def getExecSections(self):
ret = []
for section in self.__sections_l:
if section.flags & MACHOFlags.S_ATTR_SOME_INSTRUCTIONS or section.flags & MACHOFlags.S_ATTR_PURE_INSTRUCTIONS:
ret += [{
"name" : section.sectname,
"offset" : section.offset,
"size" : section.size,
"vaddr" : section.addr,
"opcodes" : bytes(self.__binary[section.offset:section.offset+section.size])
}]
return ret
def getDataSections(self):
ret = []
for section in self.__sections_l:
if not section.flags & MACHOFlags.S_ATTR_SOME_INSTRUCTIONS and not section.flags & MACHOFlags.S_ATTR_PURE_INSTRUCTIONS:
ret += [{
"name" : section.sectname,
"offset" : section.offset,
"size" : section.size,
"vaddr" : section.addr,
"opcodes" : bytes(self.__binary[section.offset:section.offset+section.size])
}]
return ret
def getArch(self):
if self.__machHeader.cputype == MACHOFlags.CPU_TYPE_I386 or self.__machHeader.cputype == MACHOFlags.CPU_TYPE_X86_64:
return CS_ARCH_X86
if self.__machHeader.cputype == MACHOFlags.CPU_TYPE_ARM:
return CS_ARCH_ARM
if self.__machHeader.cputype == MACHOFlags.CPU_TYPE_ARM64:
return CS_ARCH_ARM64
if self.__machHeader.cputype == MACHOFlags.CPU_TYPE_MIPS:
return CS_ARCH_MIPS
else:
print("[Error] MACHO.getArch() - Architecture not supported")
return None
def getArchMode(self):
if self.__machHeader.magic == 0xfeedface:
return CS_MODE_32
elif self.__machHeader.magic == 0xfeedfacf:
return CS_MODE_64
else:
print("[Error] MACHO.getArchMode() - Bad Arch size")
return None
pass
def getEndian(self):
# TODO: Support other endianness
return 0
def getFormat(self):
return "Mach-O"

View File

@ -0,0 +1,233 @@
## -*- coding: utf-8 -*-
##
## Jonathan Salwan - 2014-05-12 - ROPgadget tool
##
## http://twitter.com/JonathanSalwan
## http://shell-storm.org/project/ROPgadget/
##
from capstone import *
from ctypes import *
from struct import unpack
from binascii import unhexlify
class PEFlags(object):
IMAGE_MACHINE_INTEL_386 = 0x014c
IMAGE_MACHINE_AMD_8664 = 0x8664
IMAGE_FILE_MACHINE_ARM = 0x1c0
IMAGE_FILE_MACHINE_ARMV7 = 0x1c4
IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b
IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b
IMAGE_SIZEOF_SHORT_NAME = 0x8
class IMAGE_FILE_HEADER(Structure):
_fields_ = [
("Magic", c_uint),
("Machine", c_ushort),
("NumberOfSections", c_ushort),
("TimeDateStamp", c_uint),
("PointerToSymbolTable", c_uint),
("NumberOfSymbols", c_uint),
("SizeOfOptionalHeader", c_ushort),
("Characteristics", c_ushort)
]
class IMAGE_OPTIONAL_HEADER(Structure):
_fields_ = [
("Magic", c_ushort),
("MajorLinkerVersion", c_ubyte),
("MinorLinkerVersion", c_ubyte),
("SizeOfCode", c_uint),
("SizeOfInitializedData", c_uint),
("SizeOfUninitializedData", c_uint),
("AddressOfEntryPoint", c_uint),
("BaseOfCode", c_uint),
("BaseOfData", c_uint),
("ImageBase", c_uint),
("SectionAlignment", c_uint),
("FileAlignment", c_uint),
("MajorOperatingSystemVersion", c_ushort),
("MinorOperatingSystemVersion", c_ushort),
("MajorImageVersion", c_ushort),
("MinorImageVersion", c_ushort),
("MajorSubsystemVersion", c_ushort),
("MinorSubsystemVersion", c_ushort),
("Win32VersionValue", c_uint),
("SizeOfImage", c_uint),
("SizeOfHeaders", c_uint),
("CheckSum", c_uint),
("Subsystem", c_ushort),
("DllCharacteristics", c_ushort),
("SizeOfStackReserve", c_uint),
("SizeOfStackCommit", c_uint),
("SizeOfHeapReserve", c_uint),
("SizeOfHeapCommit", c_uint),
("LoaderFlags", c_uint),
("NumberOfRvaAndSizes", c_uint)
]
class IMAGE_OPTIONAL_HEADER64(Structure):
_fields_ = [
("Magic", c_ushort),
("MajorLinkerVersion", c_ubyte),
("MinorLinkerVersion", c_ubyte),
("SizeOfCode", c_uint),
("SizeOfInitializedData", c_uint),
("SizeOfUninitializedData", c_uint),
("AddressOfEntryPoint", c_uint),
("BaseOfCode", c_uint),
("ImageBase", c_ulonglong),
("SectionAlignment", c_uint),
("FileAlignment", c_uint),
("MajorOperatingSystemVersion", c_ushort),
("MinorOperatingSystemVersion", c_ushort),
("MajorImageVersion", c_ushort),
("MinorImageVersion", c_ushort),
("MajorSubsystemVersion", c_ushort),
("MinorSubsystemVersion", c_ushort),
("Win32VersionValue", c_uint),
("SizeOfImage", c_uint),
("SizeOfHeaders", c_uint),
("CheckSum", c_uint),
("Subsystem", c_ushort),
("DllCharacteristics", c_ushort),
("SizeOfStackReserve", c_ulonglong),
("SizeOfStackCommit", c_ulonglong),
("SizeOfHeapReserve", c_ulonglong),
("SizeOfHeapCommit", c_ulonglong),
("LoaderFlags", c_uint),
("NumberOfRvaAndSizes", c_uint)
]
class IMAGE_NT_HEADERS(Structure):
_fields_ = [
("Signature", c_uint),
("FileHeader", IMAGE_FILE_HEADER),
("OptionalHeader", IMAGE_OPTIONAL_HEADER)
]
class IMAGE_NT_HEADERS64(Structure):
_fields_ = [
("Signature", c_uint),
("FileHeader", IMAGE_FILE_HEADER),
("OptionalHeader", IMAGE_OPTIONAL_HEADER64)
]
class IMAGE_SECTION_HEADER(Structure):
_fields_ = [
("Name", c_ubyte * PEFlags.IMAGE_SIZEOF_SHORT_NAME),
("PhysicalAddress", c_uint),
("VirtualAddress", c_uint),
("SizeOfRawData", c_uint),
("PointerToRawData", c_uint),
("PointerToRelocations", c_uint),
("PointerToLinenumbers", c_uint),
("NumberOfRelocations", c_ushort),
("NumberOfLinenumbers", c_ushort),
("Characteristics", c_uint)
]
""" This class parses the PE format """
class PE(object):
def __init__(self, binary):
self.__binary = bytearray(binary)
self.__PEOffset = 0x00000000
self.__IMAGE_FILE_HEADER = None
self.__IMAGE_OPTIONAL_HEADER = None
self.__sections_l = []
self.__getPEOffset()
self.__parsePEHeader()
self.__parseOptHeader()
self.__parseSections()
def __getPEOffset(self):
self.__PEOffset = unpack("<I", bytes(self.__binary[60:64]))[0]
if self.__binary[self.__PEOffset:self.__PEOffset+4] != unhexlify(b"50450000"):
print("[Error] PE.__getPEOffset() - Bad PE signature")
return None
def __parsePEHeader(self):
PEheader = self.__binary[self.__PEOffset:]
self.__IMAGE_FILE_HEADER = IMAGE_FILE_HEADER.from_buffer_copy(PEheader)
def __parseOptHeader(self):
PEoptHeader = self.__binary[self.__PEOffset+24:self.__PEOffset+24+self.__IMAGE_FILE_HEADER.SizeOfOptionalHeader]
if unpack("<H", bytes(PEoptHeader[0:2]))[0] == PEFlags.IMAGE_NT_OPTIONAL_HDR32_MAGIC:
self.__IMAGE_OPTIONAL_HEADER = IMAGE_OPTIONAL_HEADER.from_buffer_copy(PEoptHeader)
elif unpack("<H", bytes(PEoptHeader[0:2]))[0] == PEFlags.IMAGE_NT_OPTIONAL_HDR64_MAGIC:
self.__IMAGE_OPTIONAL_HEADER = IMAGE_OPTIONAL_HEADER64.from_buffer_copy(PEoptHeader)
else:
print("[Error] PE.__parseOptHeader - Bad size header")
return None
def __parseSections(self):
baseSections = self.__PEOffset+24+self.__IMAGE_FILE_HEADER.SizeOfOptionalHeader
sizeSections = self.__IMAGE_FILE_HEADER.NumberOfSections * sizeof(IMAGE_SECTION_HEADER)
base = self.__binary[baseSections:baseSections+sizeSections]
for i in range(self.__IMAGE_FILE_HEADER.NumberOfSections):
sec = IMAGE_SECTION_HEADER.from_buffer_copy(base)
base = base[sizeof(IMAGE_SECTION_HEADER):]
self.__sections_l += [sec]
return 0
def getEntryPoint(self):
return self.__IMAGE_OPTIONAL_HEADER.ImageBase + self.__IMAGE_OPTIONAL_HEADER.AddressOfEntryPoint
def getDataSections(self):
ret = []
for section in self.__sections_l:
if section.Characteristics & 0x80000000:
ret += [{
"name" : section.Name,
"offset" : section.PointerToRawData,
"size" : section.SizeOfRawData,
"vaddr" : section.VirtualAddress + self.__IMAGE_OPTIONAL_HEADER.ImageBase,
"opcodes" : bytes(self.__binary[section.PointerToRawData:section.PointerToRawData+section.SizeOfRawData])
}]
return ret
def getExecSections(self):
ret = []
for section in self.__sections_l:
if section.Characteristics & 0x20000000:
ret += [{
"name" : section.Name,
"offset" : section.PointerToRawData,
"size" : section.SizeOfRawData,
"vaddr" : section.VirtualAddress + self.__IMAGE_OPTIONAL_HEADER.ImageBase,
"opcodes" : bytes(self.__binary[section.PointerToRawData:section.PointerToRawData+section.SizeOfRawData])
}]
return ret
def getArch(self):
if self.__IMAGE_FILE_HEADER.Machine == PEFlags.IMAGE_MACHINE_INTEL_386 or self.__IMAGE_FILE_HEADER.Machine == PEFlags.IMAGE_MACHINE_AMD_8664:
return CS_ARCH_X86
if self.__IMAGE_FILE_HEADER.Machine == PEFlags.IMAGE_FILE_MACHINE_ARM or self.__IMAGE_FILE_HEADER.Machine == PEFlags.IMAGE_FILE_MACHINE_ARMV7:
return CS_ARCH_ARM
else:
print("[Error] PE.getArch() - Bad Arch")
return None
def getArchMode(self):
if self.__IMAGE_OPTIONAL_HEADER.Magic == PEFlags.IMAGE_NT_OPTIONAL_HDR32_MAGIC:
return CS_MODE_32
elif self.__IMAGE_OPTIONAL_HEADER.Magic == PEFlags.IMAGE_NT_OPTIONAL_HDR64_MAGIC:
return CS_MODE_64
else:
print("[Error] PE.getArch() - Bad arch size")
return None
def getEndian(self):
# PE is little-endian only
return 0
def getFormat(self):
return "PE"

View File

@ -0,0 +1,72 @@
## -*- coding: utf-8 -*-
##
## Jonathan Salwan - 2014-05-12
##
## http://shell-storm.org
## http://twitter.com/JonathanSalwan
##
from capstone import *
class Raw(object):
def __init__(self, binary, arch, mode, endian):
self.__binary = bytearray(binary)
self.__arch = arch
self.__mode = mode
self.__endian = endian
def getEntryPoint(self):
return 0x0
def getExecSections(self):
return [{"name": "raw", "offset": 0x0, "size": len(self.__binary), "vaddr": 0x0, "opcodes": bytes(self.__binary)}]
def getDataSections(self):
return []
def getArch(self):
arch = {
"x86": CS_ARCH_X86,
"arm": CS_ARCH_ARM,
"arm64": CS_ARCH_ARM64,
"sparc": CS_ARCH_SPARC,
"mips": CS_ARCH_MIPS,
"ppc": CS_ARCH_PPC
}
try:
ret = arch[self.__arch]
except:
print("[Error] Raw.getArch() - Architecture not supported. Only supported: x86 arm arm64 sparc mips ppc")
return None
return ret
def getArchMode(self):
mode = {
"32": CS_MODE_32,
"64": CS_MODE_64,
"arm": CS_MODE_ARM,
"thumb": CS_MODE_THUMB
}
try:
ret = mode[self.__mode]
except:
print("[Error] Raw.getArchMode() - Mode not supported. Only supported: 32 64 arm thumb")
return None
return ret
def getEndian(self):
if self.getArch() == CS_ARCH_X86:
return 0
endian ={
"little": 0,
"big": CS_MODE_BIG_ENDIAN
}
try:
ret = endian[self.__endian]
except:
print("[Error] Raw.getArchEndian() - Endianness not supported. Only supported: little big")
return None
return ret
def getFormat(self):
return "Raw"

View File

@ -0,0 +1,107 @@
## -*- coding: utf-8 -*-
##
## Christoffer Brodd-Reijer - 2014-07-20 - ROPgadget tool
##
## http://twitter.com/ephracis
## http://shell-storm.org/project/ROPgadget/
##
import sys
from capstone import *
from ctypes import *
from binascii import *
from ropgadget.loaders.macho import *
class FAT_HEADER(BigEndianStructure):
_fields_ = [
("magic", c_uint),
("nfat_arch", c_uint)
]
class FAT_ARC(BigEndianStructure):
_fields_ = [
("cputype", c_uint),
("cpusubtype", c_uint),
("offset", c_uint),
("size", c_uint),
("align", c_uint)
]
class MACHOFlags(object):
CPU_TYPE_I386 = 0x7
CPU_TYPE_X86_64 = (CPU_TYPE_I386 | 0x1000000)
CPU_TYPE_MIPS = 0x8
CPU_TYPE_ARM = 12
CPU_TYPE_SPARC = 14
CPU_TYPE_POWERPC = 18
CPU_TYPE_POWERPC64 = (CPU_TYPE_POWERPC | 0x1000000)
LC_SEGMENT = 0x1
LC_SEGMENT_64 = 0x19
S_ATTR_SOME_INSTRUCTIONS = 0x00000400
S_ATTR_PURE_INSTRUCTIONS = 0x80000000
""" This class parses the Universal binary """
class UNIVERSAL(object):
def __init__(self, binary):
self.__binary = bytearray(binary)
self.__machoBinaries = []
self.__fatHeader = None
self.__rawLoadCmd = None
self.__sections_l = []
self.__setHeader()
self.__setBinaries()
def __setHeader(self):
self.__fatHeader = FAT_HEADER.from_buffer_copy(self.__binary)
def __setBinaries(self):
offset = 8
for i in xrange(self.__fatHeader.nfat_arch):
header = FAT_ARC.from_buffer_copy(self.__binary[offset:])
rawBinary = self.__binary[header.offset:header.offset+header.size]
if rawBinary[:4] == unhexlify(b"cefaedfe") or rawBinary[:4] == unhexlify(b"cffaedfe"):
self.__machoBinaries.append(MACHO(rawBinary))
else:
print("[Error] Binary #"+str(i+1)+" in Universal binary has an unsupported format")
offset += sizeof(header)
def getExecSections(self):
ret = []
for binary in self.__machoBinaries:
ret += binary.getExecSections()
return ret
def getDataSections(self):
ret = []
for binary in self.__machoBinaries:
ret += binary.getDataSections()
return ret
def getFormat(self):
return "Universal"
# TODO: These three will just return whatever is in the first binary.
# Perhaps the rest of ROPgadget should support loading multiple binaries?
def getEntryPoint(self):
for binary in self.__machoBinaries:
return binary.getEntryPoint()
def getArch(self):
for binary in self.__machoBinaries:
return binary.getArch()
def getArchMode(self):
for binary in self.__machoBinaries:
return binary.getArchMode()
def getEndian(self):
for binary in self.__machoBinaries:
return binary.getEndian()
if sys.version_info.major == 3:
xrange = range