include ROPGadget
This commit is contained in:
12
ROPgadget/ropgadget/loaders/__init__.py
Normal file
12
ROPgadget/ropgadget/loaders/__init__.py
Normal 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
|
350
ROPgadget/ropgadget/loaders/elf.py
Normal file
350
ROPgadget/ropgadget/loaders/elf.py
Normal 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"
|
211
ROPgadget/ropgadget/loaders/macho.py
Normal file
211
ROPgadget/ropgadget/loaders/macho.py
Normal 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"
|
233
ROPgadget/ropgadget/loaders/pe.py
Normal file
233
ROPgadget/ropgadget/loaders/pe.py
Normal 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"
|
72
ROPgadget/ropgadget/loaders/raw.py
Normal file
72
ROPgadget/ropgadget/loaders/raw.py
Normal 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"
|
107
ROPgadget/ropgadget/loaders/universal.py
Normal file
107
ROPgadget/ropgadget/loaders/universal.py
Normal 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
|
Reference in New Issue
Block a user