diff --git a/README.md b/README.md index e4dd286..0638a04 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,16 @@ # syms2elf -The plugin export the symbols (for the moment only functions) recognized by IDA Pro and radare2 to the ELF symbol table. This allows us to use the power of IDA/r2 in recognizing functions (analysis, FLIRT signatures, manual creation, renaming, etc), but not be limited to the exclusive use of this tools. +The plugin export the symbols (for the moment only functions) recognized by IDA Pro and radare2 (also works for rizin and cutter) to the ELF symbol table. This allows us to use the power of IDA/r2 in recognizing functions (analysis, FLIRT signatures, manual creation, renaming, etc), but not be limited to the exclusive use of this tools. Supports 32 and 64-bits file format. ## INSTALLATION * **IDA Pro**: Simply, copy `syms2elf.py` to the IDA's plugins folder. - * **radare2**: You can install via r2pm: `r2pm -i syms2elf` + * **radare2**: In radare2 environment, pass this command: `#!pipe python ./syms2elf.py ` + * **rizin** : In rizin environment, pass this command: `#!pipe python ./syms2elf.py ` + * If you are using radare2, make sure that you have install r2pipe. You can use this command: `pip3 install r2pipe` + * For rizin: `pip3 install rzpipe` @@ -15,22 +18,24 @@ Supports 32 and 64-bits file format. Based on a full-stripped ELF: -``` -$ file test1_x86_stripped -test1_x86_stripped: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, stripped +```$ file test_x86 +testfile_x86: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=7ee4206d91718e7b0bef16a7c03f8fa49c4a39e7, stripped ``` Rename some functions in IDA or r2, run `syms2elf` and select the output file. ![IDA output log](https://cloud.githubusercontent.com/assets/1675387/13477862/a02aa742-e0ce-11e5-835e-3a0992a3f171.png) -![r2_syms2elf](https://cloud.githubusercontent.com/assets/1675387/13831270/adddfae2-ebd2-11e5-8dcd-877c9c67faed.png) +![r2_syms2elf](https://user-images.githubusercontent.com/40752497/181514837-0fe5de8a-29db-4a67-a614-f10a773b5e1c.png) + +![cutter](https://user-images.githubusercontent.com/40752497/181536360-f725857c-1893-48c4-ac4a-96288a034b31.png) + After that: ``` -$ file test1_x86_unstripped -test1_x86_unstripped: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, not stripped +$ file test_x86_unstripped +test_x86_unstripped: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=7ee4206d91718e7b0bef16a7c03f8fa49c4a39e7, not stripped ``` Now, you can open it with others tools and analyzing in a more comfortable way. @@ -39,7 +44,10 @@ Now, you can open it with others tools and analyzing in a more comfortable way. * Daniel García (@danigargu) * Jesús Olmos (@sha0coder) - + * Ivan Stupnitskiy (@YanagiRu) -- plugin porting ## CONTACT Any comment or request will be highly appreciated :-) + +## AND ALSO +This modification (plugin porting to rizin & cutter) was started as a part of [Digital Security](https://github.com/DSecurity)'s Research Centre internship ["Summ3r of h4ck 2022"](https://dsec.ru/about/vacancies/#internship). diff --git a/syms2elf.py b/syms2elf.py index 0d420cc..d97a317 100644 --- a/syms2elf.py +++ b/syms2elf.py @@ -1,820 +1,983 @@ -#!/usr/bin/python -# -*- coding: utf-8 -*- -# -# sym2elf -# 28/11/2014 -# -# Daniel García -# Jesús Olmos -# -# ELF parser - based on the lib of ROPgadget tool by Jonathan Salwan -# http://shell-storm.org/project/ROPgadget/ -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# - -PLUG_NAME = "syms2elf" - -import os -import sys - -from ctypes import * -from struct import unpack - -USE_R2 = False -USE_IDA = False - -try: - import idaapi - USE_IDA = True -except: - if "radare2" in os.environ.get('PATH',''): - USE_R2 = True - else: - print("ERROR: The plugin must be run in IDA or radare2") - sys.exit(0) - -SHN_UNDEF = 0 -STB_GLOBAL_FUNC = 0x12 - -class SHTypes: - SHT_NULL = 0 - SHT_PROGBITS = 1 - SHT_SYMTAB = 2 - SHT_STRTAB = 3 - SHT_RELA = 4 - SHT_HASH = 5 - SHT_DYNAMIC = 6 - SHT_NOTE = 7 - SHT_NOBITS = 8 - SHT_REL = 9 - SHT_SHLIB = 10 - SHT_DYNSYM = 11 - SHT_NUM = 12 - SHT_LOPROC = 0x70000000 - SHT_HIPROC = 0x7fffffff - SHT_LOUSER = 0x80000000 - SHT_HIUSER = 0xffffffff - -class ELFFlags: - 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 SymFlags: - STB_LOCAL = 0 - STB_GLOBAL = 1 - STB_WEAK = 2 - STT_NOTYPE = 0 - STT_OBJECT = 1 - STT_FUNC = 2 - STT_SECTION = 3 - STT_FILE = 4 - STT_COMMON = 5 - STT_TLS = 6 - -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) - ] - -class Elf32_Sym_LSB(LittleEndianStructure): - _fields_ = [ - ("st_name", c_uint), - ("st_value", c_uint), - ("st_size", c_uint), - ("st_info", c_ubyte), - ("st_other", c_ubyte), - ("st_shndx", c_ushort) - ] - -class Elf64_Sym_LSB(LittleEndianStructure): - _fields_ = [ - ("st_name", c_uint), - ("st_info", c_ubyte), - ("st_other", c_ubyte), - ("st_shndx", c_ushort), - ("st_value", c_ulonglong), - ("st_size", c_ulonglong) - ] - -class Elf32_Sym_MSB(BigEndianStructure): - _fields_ = [ - ("st_name", c_uint), - ("st_value", c_uint), - ("st_size", c_uint), - ("st_info", c_ubyte), - ("st_other", c_ubyte), - ("st_shndx", c_ushort) - ] - -class Elf64_Sym_MSB(BigEndianStructure): - _fields_ = [ - ("st_name", c_uint), - ("st_info", c_ubyte), - ("st_other", c_ubyte), - ("st_shndx", c_ushort), - ("st_value", c_ulonglong), - ("st_size", c_ulonglong) - ] - - -""" This class parses the ELF """ -class ELF: - def __init__(self, binary): - self.binary = bytearray(binary) - self.ElfHeader = None - self.shdr_l = [] - self.phdr_l = [] - self.syms_l = [] - self.e_ident = self.binary[:15] - self.ei_data = unpack(" symtab.sh_offset: - self.cut_at_offset(strtab.sh_offset, strtab.sh_size) - self.cut_at_offset(symtab.sh_offset, symtab.sh_size) - else: - self.cut_at_offset(symtab.sh_offset, symtab.sh_size) - self.cut_at_offset(strtab.sh_offset, strtab.sh_size) - - self.binary = self.binary[0:sz_striped] - self.write(0, self.ElfHeader) - return True - - def get_symtab(self): - shstrtab = bytes(self.get_shstrtab_data()) - for sh in self.shdr_l: - sh_name = shstrtab[sh.sh_name:].split(b"\0")[0] - if sh.sh_type == SHTypes.SHT_SYMTAB and \ - (sh.sh_name == SHN_UNDEF or sh_name == ".symtab"): - return sh - return None - - def get_strtab(self): - shstrtab = bytes(self.get_shstrtab_data()) - for sh in self.shdr_l: - sh_name = shstrtab[sh.sh_name:].split(b"\0")[0] - if sh.sh_type == SHTypes.SHT_STRTAB and \ - (sh.sh_name == SHN_UNDEF or sh_name == ".strtab"): - return sh - return None - - def getArchMode(self): - if self.ElfHeader.e_ident[ELFFlags.EI_CLASS] == ELFFlags.ELFCLASS32: - return 32 - elif self.ElfHeader.e_ident[ELFFlags.EI_CLASS] == ELFFlags.ELFCLASS64: - return 64 - else: - log("[Error] ELF.getArchMode() - Bad Arch size") - return None - - """ Parse ELF header """ - def __setHeaderElf(self): - e_ident = self.binary[:15] - - ei_class = unpack(" - """, { - 'formChangeCb' : Form.FormChangeCb(self.OnFormChange), - 'txtFile' : Form.FileInput(save=True, swidth=50) - }) - - self.input_elf = ida_nalt.get_input_file_path() - - def OnFormChange(self, fid): - if fid == self.txtFile.id: - o_file = self.GetControlValue(self.txtFile) - - if os.path.exists(o_file): - s = "Output file already exists\n" \ - "The output file already exists. " \ - "Do you want to overwrite it?" - - if bool(ida_kernwin.ask_form(s, "1")): - os.remove(o_file) - else: - self.SetControlValue(self.txtFile, '') - return 1 - - def Show(self): - if not self.Compiled(): - self.Compile() - - if "ELF" in get_file_type_name(): - ok = self.Execute() - else: - warning("The input file is not a ELF") - ok = 0 - return ok - - class Syms2Elf_t(plugin_t): - flags = PLUGIN_UNL - comment = "" - help = "" - wanted_name = PLUG_NAME - wanted_hotkey = "" - - def init(self): - return PLUGIN_OK - - def run(self, arg=0): - f = Syms2Elf() - - if f.Show(): - symbols = get_ida_symbols() - output_file = f.txtFile.value - write_symbols(f.input_elf, output_file, symbols) - f.Free() - - def term(self): - pass - - def PLUGIN_ENTRY(): - return Syms2Elf_t() - -elif USE_R2: - - import r2pipe - r2p = r2pipe.open() - log = log_r2 - - if len(sys.argv) < 2: - log("Usage: $syms2elf ") - sys.exit(0) - - file_info = r2p.cmdj("ij").get("core") - - if file_info['format'].lower() in ('elf','elf64'): - symbols = get_r2_symbols() - write_symbols(file_info['file'], sys.argv[1], symbols) - else: - log("The input file is not a ELF") - - +#!/usr/bin/python +# -*- coding: utf-8 -*- +# +# sym2elf +# 28/11/2014 +# +# Daniel García +# Jesús Olmos +# +# ELF parser - based on the lib of ROPgadget tool by Jonathan Salwan +# http://shell-storm.org/project/ROPgadget/ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# Ported to rizin by Rukatonoshi +from PySide2.QtCore import Qt +from PySide2.QtWidgets import QHBoxLayout, QLabel, QWidget, QSizePolicy, QPushButton, QLineEdit + +PLUG_NAME = "syms2elf" + +import os +import sys +from ctypes import * +from struct import unpack + +USE_R2 = False +USE_IDA = False +USE_RIZIN = False +USE_CUTTER = False + +try: + import cutter + USE_CUTTER = True +except: + try: + import idaapi + USE_IDA = True + except: + if "radare2" in os.environ.get('PATH',''): + USE_R2 = True + elif "rizin" in os.environ.get('PATH',''): + USE_RIZIN = True + else: + print("ERROR: The plugin must be run in IDA, radare2, rizin or cutter") + sys.exit(0) + +SHN_UNDEF = 0 +STB_GLOBAL_FUNC = 0x12 + +class SHTypes: + SHT_NULL = 0 + SHT_PROGBITS = 1 + SHT_SYMTAB = 2 + SHT_STRTAB = 3 + SHT_RELA = 4 + SHT_HASH = 5 + SHT_DYNAMIC = 6 + SHT_NOTE = 7 + SHT_NOBITS = 8 + SHT_REL = 9 + SHT_SHLIB = 10 + SHT_DYNSYM = 11 + SHT_NUM = 12 + SHT_LOPROC = 0x70000000 + SHT_HIPROC = 0x7fffffff + SHT_LOUSER = 0x80000000 + SHT_HIUSER = 0xffffffff + +class ELFFlags: + 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 SymFlags: + STB_LOCAL = 0 + STB_GLOBAL = 1 + STB_WEAK = 2 + STT_NOTYPE = 0 + STT_OBJECT = 1 + STT_FUNC = 2 + STT_SECTION = 3 + STT_FILE = 4 + STT_COMMON = 5 + STT_TLS = 6 + +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) + ] + +class Elf32_Sym_LSB(LittleEndianStructure): + _fields_ = [ + ("st_name", c_uint), + ("st_value", c_uint), + ("st_size", c_uint), + ("st_info", c_ubyte), + ("st_other", c_ubyte), + ("st_shndx", c_ushort) + ] + +class Elf64_Sym_LSB(LittleEndianStructure): + _fields_ = [ + ("st_name", c_uint), + ("st_info", c_ubyte), + ("st_other", c_ubyte), + ("st_shndx", c_ushort), + ("st_value", c_ulonglong), + ("st_size", c_ulonglong) + ] + +class Elf32_Sym_MSB(BigEndianStructure): + _fields_ = [ + ("st_name", c_uint), + ("st_value", c_uint), + ("st_size", c_uint), + ("st_info", c_ubyte), + ("st_other", c_ubyte), + ("st_shndx", c_ushort) + ] + +class Elf64_Sym_MSB(BigEndianStructure): + _fields_ = [ + ("st_name", c_uint), + ("st_info", c_ubyte), + ("st_other", c_ubyte), + ("st_shndx", c_ushort), + ("st_value", c_ulonglong), + ("st_size", c_ulonglong) + ] + + +""" This class parses the ELF """ +class ELF: + def __init__(self, binary): + self.binary = bytearray(binary) + self.ElfHeader = None + self.shdr_l = [] + self.phdr_l = [] + self.syms_l = [] + self.e_ident = self.binary[:15] + self.ei_data = unpack(" symtab.sh_offset: + self.cut_at_offset(strtab.sh_offset, strtab.sh_size) + self.cut_at_offset(symtab.sh_offset, symtab.sh_size) + else: + self.cut_at_offset(symtab.sh_offset, symtab.sh_size) + self.cut_at_offset(strtab.sh_offset, strtab.sh_size) + + self.binary = self.binary[0:sz_striped] + self.write(0, self.ElfHeader) + return True + + def get_symtab(self): + shstrtab = bytes(self.get_shstrtab_data()) + for sh in self.shdr_l: + sh_name = shstrtab[sh.sh_name:].split(b"\0")[0] + if sh.sh_type == SHTypes.SHT_SYMTAB and \ + (sh.sh_name == SHN_UNDEF or sh_name == ".symtab"): + return sh + return None + + def get_strtab(self): + shstrtab = bytes(self.get_shstrtab_data()) + for sh in self.shdr_l: + sh_name = shstrtab[sh.sh_name:].split(b"\0")[0] + if sh.sh_type == SHTypes.SHT_STRTAB and \ + (sh.sh_name == SHN_UNDEF or sh_name == ".strtab"): + return sh + return None + + def getArchMode(self): + if self.ElfHeader.e_ident[ELFFlags.EI_CLASS] == ELFFlags.ELFCLASS32: + return 32 + elif self.ElfHeader.e_ident[ELFFlags.EI_CLASS] == ELFFlags.ELFCLASS64: + return 64 + else: + log("[Error] ELF.getArchMode() - Bad Arch size") + return None + + """ Parse ELF header """ + def __setHeaderElf(self): + e_ident = self.binary[:15] + + ei_class = unpack(" + """, { + 'formChangeCb' : Form.FormChangeCb(self.OnFormChange), + 'txtFile' : Form.FileInput(save=True, swidth=50) + }) + + self.input_elf = ida_nalt.get_input_file_path() + + def OnFormChange(self, fid): + if fid == self.txtFile.id: + o_file = self.GetControlValue(self.txtFile) + + if os.path.exists(o_file): + s = "Output file already exists\n" \ + "The output file already exists. " \ + "Do you want to overwrite it?" + + if bool(ida_kernwin.ask_form(s, "1")): + os.remove(o_file) + else: + self.SetControlValue(self.txtFile, '') + return 1 + + def Show(self): + if not self.Compiled(): + self.Compile() + + if "ELF" in get_file_type_name(): + ok = self.Execute() + else: + warning("The input file is not a ELF") + ok = 0 + return ok + + class Syms2Elf_t(plugin_t): + flags = PLUGIN_UNL + comment = "" + help = "" + wanted_name = PLUG_NAME + wanted_hotkey = "" + + def init(self): + return PLUGIN_OK + + def run(self, arg=0): + f = Syms2Elf() + + if f.Show(): + symbols = get_ida_symbols() + output_file = f.txtFile.value + write_symbols(f.input_elf, output_file, symbols) + f.Free() + + def term(self): + pass + + def PLUGIN_ENTRY(): + return Syms2Elf_t() + +elif USE_R2: + import r2pipe + r2p = r2pipe.open() + log = log_r2 + + if len(sys.argv) < 2: + log("Usage: #!pipe python ./syms2elf.py ") + sys.exit(0) + + file_info = r2p.cmdj("ij").get("core") + #print(file_info) + + if file_info['format'].lower() in ('elf','elf64'): + symbols = get_r2_symbols() + write_symbols(file_info['file'], sys.argv[1], symbols) + else: + log("The input file is not a ELF") + +elif USE_RIZIN: + import rzpipe + + rzp = rzpipe.open() + log = log_r2 + + if len(sys.argv) < 2: + log("Usage: #!pipe python ./syms2elf.py ") + sys.exit(0) + + file_info = rzp.cmdj("ij").get("core") + #print(file_info) + + if file_info['format'].lower() in ('elf','elf64'): + symbols = get_rizin_symbols() + write_symbols(file_info['file'], sys.argv[1], symbols) + else: + log("The input file is not a ELF") + sys.exit(0) + +elif USE_CUTTER: + class Syms2ElfWidget(cutter.CutterDockWidget): + def __init__(self, parent): + super(Syms2ElfWidget, self).__init__(parent) + self.setObjectName("WidgetForSyms2Elf") + self.setWindowTitle("syms2elf") + + content = QWidget() + self.setWidget(content) + + # Create layout and label + layout = QHBoxLayout(content) + + self.output_path = QLineEdit(content) + self.output_path.setPlaceholderText("Enter the filename") + self.output_path.setMinimumWidth(400) + layout.addWidget(self.output_path) + layout.setAlignment(self.output_path, Qt.AlignHCenter | Qt.AlignTrailing) + + button = QPushButton(content) + button.setText("Export") + button.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) + button.setMaximumHeight(50) + button.setMaximumWidth(200) + layout.addWidget(button) + layout.setAlignment(button, Qt.AlignHCenter | Qt.AlignLeading) + + button.clicked.connect(self.export_syms) + + self.show() + + def export_syms(self): + file_info = cutter.cmdj("ij").get("core") + #cutter.message("%s\n" % file_info) + file_name = self.output_path.text() + + if file_info['format'].lower() in ('elf','elf64'): + symbols = get_cutter_symbols() + #cutter.message("%s\n" % symbols) + path = get_path(file_info['file']) + file_name = path + file_name + #cutter.message("%s\n" % file_name) + write_symbols(file_info['file'], file_name, symbols) + else: + cutter.message("The input file is not an ELF!") + + + class CutterSyms2ElfPlugin(cutter.CutterPlugin): + name = "Syms2Elf Plugin" + description = "Export the symbols to the ELF symbol table." + version = "1.1" + author = "Rukatonoshi" + + # Override CutterPlugin methods + + def __init__(self): + super(CutterSyms2ElfPlugin, self).__init__() + + def setupPlugin(self): + pass + + def setupInterface(self, main): + # Dock widget + widget = Syms2ElfWidget(main) + main.addPluginDockWidget(widget) + + def terminate(self): # optional + cutter.message("CutterSyms2ElfPlugin shutting down") + + def create_cutter_plugin(): + return CutterSyms2ElfPlugin()