├── src ├── Entitlements.cpp ├── SymbolTableEntry32.cpp ├── SymbolTableEntry64.cpp ├── Segment.cpp ├── SymbolTableHeader.cpp ├── Section.cpp ├── Section32.cpp ├── Section64.cpp ├── LibraryInfo.cpp ├── StringTable.cpp ├── Segment64.cpp ├── Segment32.cpp ├── SimpleLoadCommands.cpp ├── MachHeader.cpp ├── DynamicSymbolTable.cpp ├── FileUtils.cpp ├── SymbolTableEntry.cpp ├── Blobs.cpp ├── FileReader.cpp └── MachO.cpp ├── .gitignore ├── include ├── SymbolTableEntry32.hpp ├── SymbolTableEntry64.hpp ├── Entitlements.hpp ├── Section32.hpp ├── Section64.hpp ├── Segment64.hpp ├── Segment32.hpp ├── SymbolTableHeader.hpp ├── StringTable.hpp ├── FileUtils.hpp ├── MachHeader.hpp ├── Segment.hpp ├── LibraryInfo.hpp ├── SimpleLoadCommands.hpp ├── Section.hpp ├── Blobs.hpp ├── FileReader.hpp ├── pugiconfig.hpp ├── SymbolTableEntry.hpp ├── DynamicSymbolTable.hpp ├── MachO.hpp └── pugixml.hpp ├── .travis.yml ├── LICENSE ├── README.md ├── Makefile └── poc └── poc.cpp /src/Entitlements.cpp: -------------------------------------------------------------------------------- 1 | #include "Entitlements.hpp" 2 | 3 | Entitlements::Entitlements() 4 | { 5 | } 6 | 7 | Entitlements::Entitlements(std::string xml_str) 8 | { 9 | xml = xml_str; 10 | } 11 | 12 | std::string Entitlements::getXml() 13 | { 14 | return xml; 15 | } 16 | 17 | -------------------------------------------------------------------------------- /src/SymbolTableEntry32.cpp: -------------------------------------------------------------------------------- 1 | #include "SymbolTableEntry32.hpp" 2 | 3 | 4 | SymbolTableEntry32::SymbolTableEntry32(FILE *file, char *strings) : SymbolTableEntry(file, strings) 5 | { 6 | FileUtils::readUint32(file, &value); 7 | } 8 | 9 | uint64_t SymbolTableEntry32::getValue() 10 | { 11 | return value; 12 | } 13 | -------------------------------------------------------------------------------- /src/SymbolTableEntry64.cpp: -------------------------------------------------------------------------------- 1 | #include "SymbolTableEntry64.hpp" 2 | 3 | 4 | SymbolTableEntry64::SymbolTableEntry64(FILE *file, char *strings) : SymbolTableEntry(file, strings) 5 | { 6 | FileUtils::readUint64(file, &value); 7 | } 8 | 9 | uint64_t SymbolTableEntry64::getValue() 10 | { 11 | return value; 12 | } 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | *.smod 19 | 20 | # Compiled Static libraries 21 | *.lai 22 | *.la 23 | *.a 24 | *.lib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | -------------------------------------------------------------------------------- /include/SymbolTableEntry32.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __SYMBOLTABLENTRY32_HPP 2 | #define __SYMBOLTABLENTRY32_HPP 3 | 4 | #include "SymbolTableEntry.hpp" 5 | 6 | /*specfic entry for 32 bit*/ 7 | class SymbolTableEntry32: public SymbolTableEntry 8 | { 9 | private: 10 | uint32_t value; 11 | 12 | public: 13 | SymbolTableEntry32(FILE *file, char *strins); 14 | virtual uint64_t getValue(); 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /include/SymbolTableEntry64.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __SYMBOLTABLENTRY64_HPP 2 | #define __SYMBOLTABLENTRY64_HPP 3 | 4 | #include "SymbolTableEntry.hpp" 5 | 6 | /*specific entry for 64 bit*/ 7 | class SymbolTableEntry64: public SymbolTableEntry 8 | { 9 | private: 10 | uint64_t value; 11 | 12 | public: 13 | SymbolTableEntry64(FILE *file, char *strings); 14 | virtual uint64_t getValue(); 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /include/Entitlements.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __ENTITLEMENTS_HPP 2 | #define __ENTITLEMENTS_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "FileUtils.hpp" 9 | 10 | #define ENTITLEMENTS_VALUE 0x5 11 | 12 | class Entitlements 13 | { 14 | private: 15 | std::string xml; 16 | public: 17 | Entitlements(); 18 | Entitlements(std::string xml_str); 19 | std::string getXml(); 20 | 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/Section32.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __SECTION_32_HPP 2 | #define __SECTION_32_HPP 3 | 4 | #include 5 | #include "Section.hpp" 6 | 7 | /*class for section for 32 bit architecture*/ 8 | class Section32: public Section 9 | { 10 | 11 | /*specific fields*/ 12 | private: 13 | uint32_t virtualAddress; 14 | uint32_t size; 15 | 16 | public: 17 | Section32(FILE *file); 18 | virtual uint64_t getVirtualAddress(); 19 | virtual uint64_t getSize(); 20 | virtual uint32_t getReserved3(); 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /include/Section64.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __SECTION_64_HPP 2 | #define __SECTION_64_HPP 3 | 4 | #include 5 | #include "Section.hpp" 6 | 7 | /*class for section for 32 bit architecture*/ 8 | class Section64: public Section 9 | { 10 | 11 | /*specific fields*/ 12 | private: 13 | uint64_t virtualAddress; 14 | uint64_t size; 15 | uint32_t reserved3; 16 | 17 | public: 18 | Section64(FILE *file); 19 | virtual uint64_t getVirtualAddress(); 20 | virtual uint64_t getSize(); 21 | virtual uint32_t getReserved3(); 22 | }; 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /include/Segment64.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __SEGEMENT64_HPP 2 | #define __SEGEMENT64_HPP 3 | 4 | #include "Segment.hpp" 5 | #include 6 | 7 | /*class for the load segment command for 64 bit architecture*/ 8 | class Segment64: public Segment 9 | { 10 | /*specific fields*/ 11 | private: 12 | uint64_t virtualAddress; 13 | uint64_t virtualSize; 14 | uint64_t fileOffset; 15 | uint64_t fileSize; 16 | 17 | public: 18 | Segment64(FILE *f); 19 | virtual uint64_t getVirtualAddress(); 20 | virtual uint64_t getVirtualSize(); 21 | virtual uint64_t getFileOffset(); 22 | virtual uint64_t getFileSize(); 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /include/Segment32.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __SEGEMENT32_HPP 2 | #define __SEGEMENT32_HPP 3 | 4 | #include "Segment.hpp" 5 | #include 6 | 7 | /*class for the load segment command for 32 bit architecture*/ 8 | class Segment32: public Segment 9 | { 10 | /*specific fields*/ 11 | private: 12 | uint32_t virtualAddress; 13 | uint32_t virtualSize; 14 | uint32_t fileOffset; 15 | uint32_t fileSize; 16 | 17 | public: 18 | Segment32(FILE *f); 19 | virtual uint64_t getVirtualAddress(); 20 | virtual uint64_t getVirtualSize(); 21 | virtual uint64_t getFileOffset(); 22 | virtual uint64_t getFileSize(); 23 | 24 | 25 | }; 26 | #endif 27 | -------------------------------------------------------------------------------- /include/SymbolTableHeader.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __SYMBOLTABLEHEADER_HPP 2 | #define __SYMBOLTABLEHEADER_HPP 3 | 4 | #include 5 | #include 6 | #include "FileUtils.hpp" 7 | 8 | /*information about the symbol and string tables*/ 9 | class SymbolTableHeader 10 | { 11 | private: 12 | uint32_t tableOffset; 13 | uint32_t numberSymbols; 14 | uint32_t stringTableOffset; 15 | uint32_t stringTableSize; 16 | 17 | public: 18 | SymbolTableHeader(FILE *file); 19 | SymbolTableHeader(); 20 | uint32_t getTableOffset(); 21 | uint32_t getNumberofSymbols(); 22 | uint32_t getStringTableOffset(); 23 | uint32_t getStringTableSize(); 24 | }; 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/Segment.cpp: -------------------------------------------------------------------------------- 1 | #include "Segment.hpp" 2 | 3 | char * Segment::getName() 4 | { 5 | return name; 6 | } 7 | uint32_t Segment::getMaxProtection() 8 | { 9 | return maxProtection; 10 | } 11 | 12 | uint32_t Segment::getInitProtection() 13 | { 14 | return initProtection; 15 | } 16 | 17 | uint32_t Segment::getNumberSections() 18 | { 19 | return numberSections; 20 | } 21 | 22 | uint32_t Segment::getFlags() 23 | { 24 | return flags; 25 | } 26 | 27 | std::vector
Segment::getSections() 28 | { 29 | return sections; 30 | } 31 | Segment::~Segment() 32 | { 33 | uint32_t index; 34 | for(index = 0; index < sections.size(); index++) 35 | delete sections[index]; 36 | } 37 | -------------------------------------------------------------------------------- /include/StringTable.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __STRINGTABLE_HPP 2 | #define __STRINGTABLE_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "SymbolTableHeader.hpp" 10 | #include "FileUtils.hpp" 11 | 12 | /*string table referenced by the symbol table*/ 13 | class StringTable 14 | { 15 | private: 16 | char *raw; 17 | uint32_t numberOfStrings; 18 | std::vector table; 19 | 20 | public: 21 | StringTable(FILE *file, SymbolTableHeader tableHeader); 22 | StringTable(); 23 | 24 | char *getRaw(); 25 | char *get(uint32_t index); 26 | uint32_t getNumberOfStrings(); 27 | 28 | ~StringTable(); 29 | 30 | 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | os: 4 | - osx 5 | - linux 6 | 7 | dist: 8 | - trusty 9 | 10 | compiler: 11 | - gcc 12 | 13 | addons: 14 | apt: 15 | sources: 16 | packages: 17 | 18 | branches: 19 | only: 20 | - master 21 | 22 | before_install: 23 | - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update; brew install capstone; export DYLD_LIBRARY_PATH=/usr/local/opt/capstone/lib/:$DYLD_LIBRARY_PATH; fi 24 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then wget http://cz.archive.ubuntu.com/ubuntu/pool/universe/c/capstone/libcapstone3_3.0.4-0.2_amd64.deb; sudo dpkg -i libcapstone3_3.0.4-0.2_amd64.deb; fi 25 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then wget http://cz.archive.ubuntu.com/ubuntu/pool/universe/c/capstone/libcapstone-dev_3.0.4-0.2_amd64.deb; sudo dpkg -i libcapstone-dev_3.0.4-0.2_amd64.deb; fi 26 | 27 | script: 28 | - make 29 | -------------------------------------------------------------------------------- /include/FileUtils.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __FILE_UTILS_HPP 2 | #define __FILE_UTILS_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | class FileUtils 9 | { 10 | private: 11 | static bool isSwap; 12 | static uint32_t swapUint32(uint32_t value); 13 | static uint64_t swapUint64(uint64_t value); 14 | static uint16_t swapUint16(uint16_t value); 15 | static void swapBytes(char *buff, int size); 16 | public: 17 | static void readUint32(FILE *file, uint32_t * buff); 18 | static void readNetworkUint32(FILE *file, uint32_t * buff); 19 | static void readUint64(FILE *file, uint64_t * buff); 20 | static void readUint8(FILE *file, uint8_t * buff); 21 | static void readUint16(FILE *file, uint16_t * buff); 22 | static void readBytes(FILE *file, char * buff, int nr); 23 | static void setSwap(); 24 | }; 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/SymbolTableHeader.cpp: -------------------------------------------------------------------------------- 1 | #include "SymbolTableHeader.hpp" 2 | 3 | SymbolTableHeader::SymbolTableHeader(FILE *file) 4 | { 5 | uint32_t cmdSize; 6 | 7 | FileUtils::readUint32(file, &cmdSize); 8 | 9 | FileUtils::readUint32(file, &tableOffset); 10 | 11 | FileUtils::readUint32(file, &numberSymbols); 12 | 13 | FileUtils::readUint32(file, &stringTableOffset); 14 | 15 | FileUtils::readUint32(file, &stringTableSize); 16 | } 17 | 18 | SymbolTableHeader::SymbolTableHeader() 19 | { 20 | 21 | } 22 | uint32_t SymbolTableHeader::getTableOffset() 23 | { 24 | return tableOffset; 25 | } 26 | 27 | uint32_t SymbolTableHeader::getNumberofSymbols() 28 | { 29 | return numberSymbols; 30 | } 31 | 32 | uint32_t SymbolTableHeader::getStringTableOffset() 33 | { 34 | return stringTableOffset; 35 | } 36 | 37 | uint32_t SymbolTableHeader::getStringTableSize() 38 | { 39 | return stringTableSize; 40 | } 41 | -------------------------------------------------------------------------------- /src/Section.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "Section.hpp" 4 | 5 | char * Section::getSectionName() 6 | { 7 | return sectionName; 8 | } 9 | 10 | char * Section::getSegmentName() 11 | { 12 | return segmentName; 13 | } 14 | 15 | uint32_t Section::getOffset() 16 | { 17 | return offset; 18 | } 19 | 20 | uint32_t Section::getAlign() 21 | { 22 | return align; 23 | } 24 | 25 | uint32_t Section::getRelocationOffset() 26 | { 27 | return relocationsOffset; 28 | } 29 | 30 | uint32_t Section::getNumberRelocations() 31 | { 32 | return numberRelocations; 33 | } 34 | uint32_t Section::getFlags() 35 | { 36 | return flags; 37 | } 38 | 39 | uint32_t Section::getReserved1() 40 | { 41 | return reserved1; 42 | } 43 | 44 | uint32_t Section::getReserved2() 45 | { 46 | return reserved2; 47 | } 48 | 49 | uint32_t Section::getType() 50 | { 51 | return (flags & SECTION_TYPE); 52 | } 53 | Section::~Section() 54 | { 55 | } 56 | -------------------------------------------------------------------------------- /src/Section32.cpp: -------------------------------------------------------------------------------- 1 | #include "Section32.hpp" 2 | #include "FileUtils.hpp" 3 | 4 | Section32::Section32(FILE *file) 5 | { 6 | 7 | FileUtils::readBytes(file, sectionName, 16); 8 | 9 | FileUtils::readBytes(file, segmentName, 16); 10 | 11 | FileUtils::readUint32(file, &virtualAddress); 12 | 13 | FileUtils::readUint32(file, &size); 14 | 15 | FileUtils::readUint32(file, &offset); 16 | 17 | FileUtils::readUint32(file, &align); 18 | 19 | FileUtils::readUint32(file, &relocationsOffset); 20 | 21 | FileUtils::readUint32(file, &numberRelocations); 22 | 23 | FileUtils::readUint32(file, &flags); 24 | 25 | FileUtils::readUint32(file, &reserved1); 26 | 27 | FileUtils::readUint32(file, &reserved2); 28 | } 29 | 30 | uint64_t Section32::getVirtualAddress() 31 | { 32 | return virtualAddress; 33 | } 34 | 35 | uint64_t Section32::getSize() 36 | { 37 | return size; 38 | } 39 | 40 | uint32_t Section32::getReserved3() 41 | { 42 | return 0; 43 | } 44 | -------------------------------------------------------------------------------- /include/MachHeader.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __MACHHEADER_HPP 2 | #define __MACHHEADER_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #define MAGIC_32 0xFEEDFACE 9 | #define MAGIC_64 0xFEEDFACF 10 | #define CIGAM_32 0xCEFAEDFE 11 | #define CIGAM_64 0xCFFAEDFE 12 | 13 | class MachHeader 14 | { 15 | private: 16 | bool is_32; 17 | uint32_t magic; 18 | uint32_t cpuType; 19 | uint32_t cpuSubType; 20 | uint32_t fileType; 21 | uint32_t numberCmds; 22 | uint32_t sizeOfCmds; 23 | uint32_t flags; 24 | uint32_t reserved; 25 | 26 | public: 27 | MachHeader(FILE *file); 28 | MachHeader(); 29 | /****getter****/ 30 | bool getIs32(); 31 | uint32_t getMagic(); 32 | uint32_t getCpuType(); 33 | uint32_t getCpuSubType(); 34 | uint32_t getFileType(); 35 | uint32_t getNumberCmds(); 36 | uint32_t getSizeOfCmds(); 37 | uint32_t getFlags(); 38 | uint32_t getReserved(); 39 | 40 | }; 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/Section64.cpp: -------------------------------------------------------------------------------- 1 | #include "Section64.hpp" 2 | #include "FileUtils.hpp" 3 | 4 | Section64::Section64(FILE *file) 5 | { 6 | FileUtils::readBytes(file, sectionName, 16); 7 | 8 | FileUtils::readBytes(file, segmentName, 16); 9 | 10 | FileUtils::readUint64(file, &virtualAddress); 11 | 12 | FileUtils::readUint64(file, &size); 13 | 14 | FileUtils::readUint32(file, &offset); 15 | 16 | FileUtils::readUint32(file, &align); 17 | 18 | FileUtils::readUint32(file, &relocationsOffset); 19 | 20 | FileUtils::readUint32(file, &numberRelocations); 21 | 22 | FileUtils::readUint32(file, &flags); 23 | 24 | FileUtils::readUint32(file, &reserved1); 25 | 26 | FileUtils::readUint32(file, &reserved2); 27 | 28 | FileUtils::readUint32(file, &reserved3); 29 | } 30 | 31 | uint64_t Section64::getVirtualAddress() 32 | { 33 | return virtualAddress; 34 | } 35 | 36 | uint64_t Section64::getSize() 37 | { 38 | return size; 39 | } 40 | 41 | uint32_t Section64::getReserved3() 42 | { 43 | return reserved3; 44 | } 45 | -------------------------------------------------------------------------------- /include/Segment.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __SEGEMENT_HPP 2 | #define __SEGEMENT_HPP 3 | 4 | #include 5 | #include 6 | #include "Section.hpp" 7 | 8 | /*generic class for SegmentLoad Command which the user will use*/ 9 | /*this class is needed to abstract the architecture 32 bit 64 bit*/ 10 | class Segment 11 | { 12 | 13 | /*common fields*/ 14 | protected: 15 | char name[16]; 16 | uint32_t maxProtection; 17 | uint32_t initProtection; 18 | uint32_t numberSections; 19 | uint32_t flags; 20 | std::vector
sections; 21 | 22 | /*unified interface for both 32 bit and 64 bit*/ 23 | public: 24 | char *getName(); 25 | virtual uint64_t getVirtualAddress() = 0; 26 | virtual uint64_t getVirtualSize() = 0; 27 | virtual uint64_t getFileOffset() = 0; 28 | virtual uint64_t getFileSize() = 0; 29 | uint32_t getMaxProtection(); 30 | uint32_t getInitProtection(); 31 | uint32_t getNumberSections(); 32 | uint32_t getFlags(); 33 | std::vector
getSections(); 34 | 35 | virtual ~Segment(); 36 | }; 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Alexandros Dimos, Liviu Gheorghe 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /include/LibraryInfo.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __LIBRARYINFO_HPP 2 | #define __LIBRARYINFO_HPP 3 | 4 | #include 5 | #include 6 | #include "FileUtils.hpp" 7 | 8 | /*Dynamicly linked shared libraries are identified by two things. The 9 | * pathname (the name of the library as found for execution), and the 10 | * compatibility version number. The pathname must match and the compatibility 11 | * number in the user of the library must be greater than or equal to the 12 | * library being used. The time stamp is used to record the time a library was 13 | * built and copied into user so it can be use to determined if the library used 14 | * at runtime is exactly the same as used to built the program. 15 | */ 16 | 17 | class LibraryInfo 18 | { 19 | private: 20 | uint32_t timestamp; 21 | uint32_t currentVersion; 22 | uint32_t compatibilityVersion; 23 | char *name; 24 | 25 | public: 26 | 27 | LibraryInfo(FILE * file); 28 | uint32_t getTimestamp(); 29 | uint32_t getCurrentVersion(); 30 | uint32_t getCompatibilityVersion(); 31 | char * getName(); 32 | 33 | ~LibraryInfo(); 34 | 35 | }; 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/LibraryInfo.cpp: -------------------------------------------------------------------------------- 1 | #include "LibraryInfo.hpp" 2 | 3 | LibraryInfo::LibraryInfo(FILE *file) 4 | { 5 | uint32_t cmdSize, nameOffset; 6 | uint64_t cmdOffset; 7 | 8 | cmdOffset = ftell(file) - sizeof(uint32_t); 9 | 10 | FileUtils::readUint32(file, &cmdSize); 11 | 12 | FileUtils::readUint32(file, &nameOffset); 13 | 14 | FileUtils::readUint32(file, ×tamp); 15 | 16 | FileUtils::readUint32(file, ¤tVersion); 17 | 18 | FileUtils::readUint32(file, &compatibilityVersion); 19 | 20 | fseek(file, cmdOffset + nameOffset, SEEK_SET); 21 | name = new char[cmdSize - nameOffset]; 22 | FileUtils::readBytes(file, name, cmdSize - nameOffset); 23 | 24 | } 25 | 26 | uint32_t LibraryInfo::getTimestamp() 27 | { 28 | return timestamp; 29 | } 30 | 31 | uint32_t LibraryInfo::getCurrentVersion() 32 | { 33 | return currentVersion; 34 | } 35 | 36 | uint32_t LibraryInfo::getCompatibilityVersion() 37 | { 38 | return compatibilityVersion; 39 | } 40 | 41 | char *LibraryInfo::getName() 42 | { 43 | return name; 44 | } 45 | 46 | LibraryInfo::~LibraryInfo() 47 | { 48 | delete name; 49 | } 50 | -------------------------------------------------------------------------------- /src/StringTable.cpp: -------------------------------------------------------------------------------- 1 | #include "StringTable.hpp" 2 | 3 | StringTable::StringTable(FILE *file, SymbolTableHeader tableHeader) 4 | { 5 | uint32_t tableSize, dataIndex; 6 | 7 | fseek(file, tableHeader.getStringTableOffset(), SEEK_SET); 8 | 9 | tableSize = tableHeader.getStringTableSize(); 10 | raw = new char[tableSize]; 11 | 12 | FileUtils::readBytes(file, raw, tableSize); 13 | 14 | /*index the table*/ 15 | dataIndex = 0; 16 | while(dataIndex < tableSize) { 17 | table.push_back(&raw[dataIndex]); 18 | dataIndex += strlen(&raw[dataIndex]) + 1; 19 | } 20 | 21 | numberOfStrings = table.size(); 22 | 23 | } 24 | 25 | StringTable::StringTable() 26 | { 27 | 28 | } 29 | 30 | char *StringTable::getRaw() 31 | { 32 | return raw; 33 | } 34 | 35 | char *StringTable::get(uint32_t index) 36 | { 37 | if(index < table.size()) 38 | return table[index]; 39 | 40 | return NULL; 41 | } 42 | 43 | uint32_t StringTable::getNumberOfStrings() 44 | { 45 | return numberOfStrings; 46 | } 47 | 48 | StringTable::~StringTable() 49 | { 50 | delete raw; 51 | } 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # open-source-machlib 2 | 3 | [![Build Status](https://travis-ci.org/Redridge/open-source-machlib.svg?branch=master)](https://travis-ci.org/Redridge/open-source-machlib) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) 4 | # 5 | 6 | The goal of this project is to create an open source equivalent of machlib: a library for inspecting Apple binary format files, particularly the iOS kernelcache. It will provide features to list library calls, system calls, kernel extensions, segments and sections and others. It will be a library that could then be used as a back-end for other tools. 7 | 8 | 9 | ### Installing 10 | 11 | Downloading the necessary dependecies. 12 | 13 | ``` 14 | make prepare 15 | ``` 16 | Building the sources, generating the library and a sample application. 17 | The library and the sample application will be located inside the bin directory 18 | 19 | ``` 20 | make 21 | ``` 22 | Changing the LIBRARY PATH. 23 | 24 | Linux 25 | 26 | ``` 27 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/bin 28 | ``` 29 | Macos 30 | 31 | ``` 32 | export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:/path/to/bin 33 | ``` 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /src/Segment64.cpp: -------------------------------------------------------------------------------- 1 | #include "FileUtils.hpp" 2 | #include "Segment64.hpp" 3 | #include "Section64.hpp" 4 | 5 | Segment64::Segment64(FILE *file) 6 | { 7 | uint32_t cmdSize, index; 8 | 9 | FileUtils::readUint32(file, &cmdSize); 10 | 11 | FileUtils::readBytes(file, name, 16); 12 | 13 | FileUtils::readUint64(file, &virtualAddress); 14 | 15 | FileUtils::readUint64(file, &virtualSize); 16 | 17 | FileUtils::readUint64(file, &fileOffset); 18 | 19 | FileUtils::readUint64(file, &fileSize); 20 | 21 | FileUtils::readUint32(file, &maxProtection); 22 | 23 | FileUtils::readUint32(file, &initProtection); 24 | 25 | FileUtils::readUint32(file, &numberSections); 26 | 27 | FileUtils::readUint32(file, &flags); 28 | 29 | /*parse sections*/ 30 | for(index = 0; index < numberSections; index++) { 31 | sections.push_back(new Section64(file)); 32 | } 33 | 34 | } 35 | 36 | uint64_t Segment64::getVirtualAddress() 37 | { 38 | return virtualAddress; 39 | } 40 | 41 | uint64_t Segment64::getVirtualSize() 42 | { 43 | return virtualSize; 44 | } 45 | 46 | uint64_t Segment64::getFileOffset() 47 | { 48 | return fileOffset; 49 | } 50 | 51 | uint64_t Segment64::getFileSize() 52 | { 53 | return fileSize; 54 | } 55 | -------------------------------------------------------------------------------- /src/Segment32.cpp: -------------------------------------------------------------------------------- 1 | #include "FileUtils.hpp" 2 | #include "Segment32.hpp" 3 | #include "Section32.hpp" 4 | 5 | Segment32::Segment32(FILE *file) 6 | { 7 | uint32_t cmdSize, index; 8 | 9 | FileUtils::readUint32(file, &cmdSize); 10 | 11 | FileUtils::readBytes(file, name, 16); 12 | 13 | FileUtils::readUint32(file, &virtualAddress); 14 | 15 | FileUtils::readUint32(file, &virtualSize); 16 | 17 | FileUtils::readUint32(file, &fileOffset); 18 | 19 | FileUtils::readUint32(file, &fileSize); 20 | 21 | FileUtils::readUint32(file, &maxProtection); 22 | 23 | FileUtils::readUint32(file, &initProtection); 24 | 25 | FileUtils::readUint32(file, &numberSections); 26 | 27 | FileUtils::readUint32(file, &flags); 28 | 29 | /*parse sections*/ 30 | for(index = 0; index < numberSections; index++) { 31 | sections.push_back(new Section32(file)); 32 | } 33 | 34 | 35 | } 36 | 37 | uint64_t Segment32::getVirtualAddress() 38 | { 39 | return virtualAddress; 40 | } 41 | 42 | uint64_t Segment32::getVirtualSize() 43 | { 44 | return virtualSize; 45 | } 46 | 47 | uint64_t Segment32::getFileOffset() 48 | { 49 | return fileOffset; 50 | } 51 | 52 | uint64_t Segment32::getFileSize() 53 | { 54 | return fileSize; 55 | } 56 | -------------------------------------------------------------------------------- /include/SimpleLoadCommands.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __LOADSIMPLECOMMANDS_HPP 2 | #define __LOADSIMPLECOMMANDS_HPP 3 | 4 | #include 5 | #include 6 | #include "FileUtils.hpp" 7 | 8 | class LoadDyLinkerCmd 9 | { 10 | private: 11 | uint32_t nameOffset; 12 | char * linkerName; 13 | 14 | public: 15 | LoadDyLinkerCmd(FILE *file); 16 | uint32_t getNameOffset(); 17 | char *getLinkerName(); 18 | 19 | ~LoadDyLinkerCmd(); 20 | 21 | }; 22 | 23 | /*It is used for main executables to specify the location (file offset) 24 | * of main(). If -stack_size was used at link time, the stacksize 25 | * field will contain the stack size need for the main thread. 26 | */ 27 | class LoadMainCmd { 28 | 29 | private: 30 | uint64_t entryOffset; 31 | uint64_t stackSize; 32 | 33 | public: 34 | LoadMainCmd(FILE *file); 35 | LoadMainCmd(); 36 | uint64_t getEntryOffset(); 37 | uint64_t getStackSize(); 38 | }; 39 | 40 | 41 | /*It's used by tools that need to symbolicate addresses in crash logs, 42 | samples, spindumps, etc. to determine 43 | if a given address falls inside a function*/ 44 | class LinkEditCmd { 45 | 46 | private: 47 | uint32_t dataOffset; 48 | uint32_t dataSize; 49 | 50 | public: 51 | LinkEditCmd(FILE *file); 52 | LinkEditCmd(); 53 | uint32_t getDataOffset(); 54 | uint32_t getDataSize(); 55 | 56 | }; 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC := g++ -Wall 2 | SRCDIR := src 3 | BUILDDIR := build 4 | TARGET := bin/libopenmach.so 5 | LIBDIR := bin 6 | 7 | SRCEXT := cpp 8 | SOURCES := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT)) 9 | OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.o)) 10 | CFLAGS := -g -fpic 11 | LIB := -lcapstone 12 | INC := -I include 13 | OS := $(shell uname) 14 | 15 | 16 | build: $(TARGET) bin/poc 17 | 18 | $(TARGET): $(OBJECTS) 19 | @mkdir -p $(LIBDIR) 20 | @echo " $(CC) $^ -o $(TARGET) $(LIB)"; $(CC) $^ -shared -o $(TARGET) $(LIB) 21 | 22 | $(BUILDDIR)/%.o: $(SRCDIR)/%.$(SRCEXT) 23 | @mkdir -p $(BUILDDIR) 24 | @echo " $(CC) $(CFLAGS) $(INC) -c -o $@ $<"; $(CC) $(CFLAGS) $(INC) -c -o $@ $< 25 | 26 | prepare: 27 | ifeq ($(OS), Darwin) 28 | @echo "installing dependencies for MACOS" 29 | @brew install capstone 30 | @export DYLD_LIBRARY_PATH=/usr/local/opt/capstone/lib/:$DYLD_LIBRARY_PATH 31 | else 32 | @echo "installing dependencies for Linux" 33 | @wget http://cz.archive.ubuntu.com/ubuntu/pool/universe/c/capstone/libcapstone3_3.0.4-0.2_amd64.deb 34 | @sudo dpkg -i libcapstone3_3.0.4-0.2_amd64.deb 35 | @wget http://cz.archive.ubuntu.com/ubuntu/pool/universe/c/capstone/libcapstone-dev_3.0.4-0.2_amd64.deb 36 | @sudo dpkg -i libcapstone-dev_3.0.4-0.2_amd64.deb 37 | endif 38 | 39 | clean: 40 | @echo " $(RM) -r $(BUILDDIR) $(TARGET) bin/poc"; $(RM) -r $(BUILDDIR) $(TARGET) bin/poc 41 | 42 | bin/poc: poc/poc.cpp 43 | @echo " $(CC) -L$(LIBDIR) -o $@ $< -lopenmach $(INC)"; $(CC) -L$(LIBDIR) -o $@ $< -lopenmach $(INC) 44 | 45 | .PHONY: clean 46 | 47 | -------------------------------------------------------------------------------- /include/Section.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __SECTION_HPP 2 | #define __SECTION_HPP 3 | 4 | 5 | #include 6 | 7 | /* 256 section types */ 8 | #define SECTION_TYPE 0x000000ff 9 | /* 24 section attributes */ 10 | #define SECTION_ATTRIBUTES 0xffffff00 11 | 12 | /* section with only non-lazy symbol pointers */ 13 | #define S_NON_LAZY_SYMBOL_POINTER 0x6 14 | 15 | /* section with only lazy symbol pointers*/ 16 | #define S_LAZY_SYMBOL_POINTERS 0x7 17 | 18 | /* section with only symbol stubs, byte size of stub in 19 | the reserved2 field */ 20 | #define S_SYMBOL_STUBS 0x8 21 | 22 | /*generic class for Sections which the user will use*/ 23 | /*this class is needed to abstract the architecture 32 bit 64 bit*/ 24 | class Section 25 | { 26 | 27 | /*common fields*/ 28 | protected: 29 | char sectionName[16]; 30 | char segmentName[16]; 31 | uint32_t offset; 32 | uint32_t align; 33 | uint32_t relocationsOffset; 34 | uint32_t numberRelocations; 35 | uint32_t flags; 36 | uint32_t reserved1; 37 | uint32_t reserved2; 38 | 39 | /*unified interface for both 32 bit and 64 bit*/ 40 | public: 41 | char *getSectionName(); 42 | char *getSegmentName(); 43 | virtual uint64_t getVirtualAddress() = 0; 44 | virtual uint64_t getSize() = 0; 45 | uint32_t getOffset(); 46 | uint32_t getAlign(); 47 | uint32_t getRelocationOffset(); 48 | uint32_t getNumberRelocations(); 49 | uint32_t getFlags(); 50 | uint32_t getReserved1(); 51 | uint32_t getReserved2(); 52 | virtual uint32_t getReserved3() = 0; 53 | uint32_t getType(); 54 | 55 | virtual ~Section(); 56 | }; 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /include/Blobs.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __BLOBS_HPP 2 | #define __BLOBS_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "FileUtils.hpp" 9 | #include "SimpleLoadCommands.hpp" 10 | 11 | #define CSMAGIC_EMBEDDED_SIGNATURE 0xFADE0CC0 12 | #define CSMAGIC_DIRECTORY_BLOB 0xFADE0C02 13 | 14 | #define CODE_DIRECTORY_BLOB 0x0 15 | 16 | struct subblob { 17 | uint32_t type; 18 | uint32_t offset; 19 | }; 20 | 21 | class SuperBlob 22 | { 23 | private: 24 | uint32_t length; 25 | uint32_t numBlobs; 26 | std::vector subblobs; 27 | public: 28 | SuperBlob(FILE *file, LinkEditCmd sigCmd); 29 | SuperBlob(); 30 | uint32_t getLength(); 31 | uint32_t getNumBlobs(); 32 | std::vector getSubBlobs(); 33 | 34 | 35 | }; 36 | 37 | class CodeDirectoryBlob 38 | { 39 | private: 40 | uint32_t length; 41 | uint32_t version; 42 | uint32_t flags; 43 | uint32_t hashOffset; 44 | uint32_t identOffset; 45 | uint32_t nSpecialSlots; 46 | uint32_t nCodeSlots; 47 | uint32_t codeLimit; 48 | uint8_t hashSize; 49 | uint8_t hashType; 50 | uint8_t platform; 51 | uint8_t pageSize; 52 | uint32_t spare2; 53 | uint32_t scatterOffset; 54 | uint32_t teamOffset; 55 | std::vector hashes; 56 | public: 57 | CodeDirectoryBlob(FILE *file, LinkEditCmd sigCmd, SuperBlob sb); 58 | CodeDirectoryBlob(); 59 | uint32_t getLength(); 60 | uint32_t getVersion(); 61 | uint32_t getFlags(); 62 | uint32_t getHashOffset(); 63 | uint32_t getIdentOffset(); 64 | uint32_t getNSpecialSlots(); 65 | uint32_t getNCodeSlots(); 66 | uint32_t getCodeLimit(); 67 | uint8_t getHashSize(); 68 | uint8_t getHashType(); 69 | uint8_t getPlatform(); 70 | uint8_t getPageSize(); 71 | uint32_t getSpare2(); 72 | uint32_t getScatterOffset(); 73 | uint32_t getTeamOffset(); 74 | std::vector getHashes(); 75 | 76 | }; 77 | 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /src/SimpleLoadCommands.cpp: -------------------------------------------------------------------------------- 1 | #include "SimpleLoadCommands.hpp" 2 | 3 | LoadDyLinkerCmd::LoadDyLinkerCmd(FILE *file) 4 | { 5 | uint32_t cmdSize; 6 | uint64_t cmdOffset; 7 | 8 | cmdOffset = ftell(file) - sizeof(uint32_t); 9 | 10 | FileUtils::readUint32(file, &cmdSize); 11 | 12 | FileUtils::readUint32(file, &nameOffset); 13 | 14 | fseek(file, cmdOffset + nameOffset, SEEK_SET); 15 | linkerName = new char[cmdSize - nameOffset]; 16 | FileUtils::readBytes(file, linkerName, cmdSize - nameOffset); 17 | 18 | } 19 | 20 | uint32_t LoadDyLinkerCmd::getNameOffset() 21 | { 22 | return nameOffset; 23 | } 24 | 25 | char * LoadDyLinkerCmd::getLinkerName() 26 | { 27 | return linkerName; 28 | } 29 | 30 | LoadDyLinkerCmd::~LoadDyLinkerCmd() 31 | { 32 | delete linkerName; 33 | } 34 | 35 | 36 | LoadMainCmd::LoadMainCmd(FILE *file) 37 | { 38 | uint32_t cmdSize; 39 | 40 | FileUtils::readUint32(file, &cmdSize); 41 | 42 | FileUtils::readUint64(file, &entryOffset); 43 | 44 | FileUtils::readUint64(file, &stackSize); 45 | } 46 | 47 | LoadMainCmd::LoadMainCmd() 48 | { 49 | 50 | } 51 | 52 | uint64_t LoadMainCmd::getEntryOffset() 53 | { 54 | return entryOffset; 55 | } 56 | 57 | uint64_t LoadMainCmd::getStackSize() 58 | { 59 | return stackSize; 60 | } 61 | 62 | 63 | LinkEditCmd::LinkEditCmd() 64 | { 65 | dataOffset = 0; 66 | dataSize = 0; 67 | } 68 | 69 | LinkEditCmd::LinkEditCmd(FILE *file) 70 | { 71 | uint32_t cmdSize; 72 | 73 | FileUtils::readUint32(file, &cmdSize); 74 | 75 | FileUtils::readUint32(file, &dataOffset); 76 | 77 | FileUtils::readUint32(file, &dataSize); 78 | } 79 | 80 | uint32_t LinkEditCmd::getDataOffset() 81 | { 82 | return dataOffset; 83 | } 84 | 85 | uint32_t LinkEditCmd::getDataSize() 86 | { 87 | return dataSize; 88 | } 89 | -------------------------------------------------------------------------------- /src/MachHeader.cpp: -------------------------------------------------------------------------------- 1 | #include "MachHeader.hpp" 2 | #include "FileUtils.hpp" 3 | 4 | MachHeader::MachHeader(FILE *file) 5 | { 6 | FileUtils::readUint32(file, &magic); 7 | 8 | if(magic != MAGIC_32 && magic != MAGIC_64 && 9 | magic != CIGAM_32 && magic != CIGAM_64) { 10 | throw std::runtime_error("File probably not MachO"); 11 | } 12 | 13 | if(magic == MAGIC_32 || magic == CIGAM_32) 14 | is_32 = true; 15 | else 16 | is_32 = false; 17 | 18 | if(magic == CIGAM_32 || magic == CIGAM_64) 19 | FileUtils::setSwap(); 20 | 21 | FileUtils::readUint32(file, &cpuType); 22 | FileUtils::readUint32(file, &cpuSubType); 23 | FileUtils::readUint32(file, &fileType); 24 | FileUtils::readUint32(file, &numberCmds); 25 | FileUtils::readUint32(file, &sizeOfCmds); 26 | FileUtils::readUint32(file, &flags); 27 | 28 | if(!is_32) 29 | FileUtils::readUint32(file, &reserved); 30 | 31 | } 32 | 33 | MachHeader::MachHeader() 34 | { 35 | 36 | } 37 | 38 | bool MachHeader::getIs32() 39 | { 40 | return is_32; 41 | } 42 | 43 | uint32_t MachHeader::getMagic() 44 | { 45 | return magic; 46 | } 47 | 48 | uint32_t MachHeader::getCpuType() 49 | { 50 | return cpuType; 51 | } 52 | 53 | uint32_t MachHeader::getCpuSubType() 54 | { 55 | return cpuSubType; 56 | } 57 | 58 | uint32_t MachHeader::getFileType() 59 | { 60 | return fileType; 61 | } 62 | 63 | uint32_t MachHeader::getNumberCmds() 64 | { 65 | return numberCmds; 66 | } 67 | 68 | uint32_t MachHeader::getSizeOfCmds() 69 | { 70 | return sizeOfCmds; 71 | } 72 | 73 | uint32_t MachHeader::getFlags() 74 | { 75 | return flags; 76 | } 77 | 78 | uint32_t MachHeader::getReserved() 79 | { 80 | if(!is_32) 81 | return reserved; 82 | 83 | //TODO - throws exception when not 32 bit 84 | return -1; 85 | } 86 | -------------------------------------------------------------------------------- /include/FileReader.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __FILEREADER_HPP 2 | #define __FILEREADER_HPP 3 | 4 | #include 5 | #include "MachO.hpp" 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #define CPU_ARCH_ABI64 0x1000000 12 | 13 | #define CPU_TYPE_I386 7 14 | #define CPU_TYPE_X86_64 (CPU_TYPE_I386 | CPU_ARCH_ABI64) 15 | 16 | 17 | #define CPU_TYPE_ARM 12 18 | #define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64) 19 | 20 | 21 | 22 | struct myComp { 23 | bool operator()(const char *a, const char *b) const { 24 | return std::strcmp(a, b) < 0; 25 | } 26 | }; 27 | 28 | class FileReader 29 | { 30 | private: 31 | 32 | MachO *binary; 33 | FILE *file; 34 | /*maps for functions offset and names*/ 35 | std::map functionStartsMap; 36 | std::map functionNamesMap; 37 | std::vector functionsOffset; 38 | /*capstone variables*/ 39 | cs_arch capstoneArchOption; 40 | cs_mode capstoneModeOption; 41 | csh capstoneHandle; 42 | 43 | static std::map capstoneArch; 44 | static std::mapmakeCapstoneArch(); 45 | 46 | /*helper functions*/ 47 | void DisassembleAll(uint64_t fileOffset, uint64_t size); 48 | 49 | void Disassemble(uint64_t fileOffset, uint64_t codeSize); 50 | 51 | void Disassemblex86(const uint8_t **code, 52 | uint64_t size, uint64_t startAddress, bool print); 53 | 54 | void DisassembleARM(const uint8_t **code, 55 | uint64_t size, uint64_t startAddress); 56 | 57 | bool getFunctionBoundaries(uint64_t offset, uint64_t *begin, 58 | uint64_t *end); 59 | 60 | cs_mode getCapstoneMode(uint64_t fileOffset); 61 | uint64_t getNextOffset(uint64_t currentOffset); 62 | 63 | 64 | public: 65 | FileReader(MachO *binary); 66 | void Disassemble(); 67 | void Disassemble(char *functionName); 68 | void Disassemble(uint64_t fileOffset); 69 | char * dumpSection(char * segmentName, char *sectionName, uint64_t *size); 70 | char * dumpBytes(uint64_t offset, uint64_t size); 71 | 72 | ~FileReader(); 73 | }; 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /src/DynamicSymbolTable.cpp: -------------------------------------------------------------------------------- 1 | #include "DynamicSymbolTable.hpp" 2 | 3 | DynamicSymbolTableHeader::DynamicSymbolTableHeader(FILE *file) 4 | { 5 | uint32_t cmdSize; 6 | 7 | FileUtils::readUint32(file, &cmdSize); 8 | 9 | FileUtils::readUint32(file, &indexLocalSym); 10 | FileUtils::readUint32(file, &numberLocalSym); 11 | 12 | FileUtils::readUint32(file, &indexExtDefSym); 13 | FileUtils::readUint32(file, &numberExtDefSym); 14 | 15 | FileUtils::readUint32(file, &indexUndefSym); 16 | FileUtils::readUint32(file, &numberUndefSym); 17 | 18 | FileUtils::readUint32(file, &tocOff); 19 | FileUtils::readUint32(file, &numberTocEntries); 20 | 21 | FileUtils::readUint32(file, &modTabOff); 22 | FileUtils::readUint32(file, &numberModTabEntries); 23 | 24 | FileUtils::readUint32(file, &extRefSymOff); 25 | FileUtils::readUint32(file, &numberExtRefSyms); 26 | 27 | FileUtils::readUint32(file, &tableOffset); 28 | FileUtils::readUint32(file, &numberEntries); 29 | 30 | FileUtils::readUint32(file, &extRelOff); 31 | FileUtils::readUint32(file, &numberExtRel); 32 | 33 | FileUtils::readUint32(file, &locRelOff); 34 | FileUtils::readUint32(file, &numberLocRel); 35 | } 36 | 37 | DynamicSymbolTableHeader::DynamicSymbolTableHeader() 38 | { 39 | 40 | } 41 | uint32_t DynamicSymbolTableHeader::getTableOffset() 42 | { 43 | return tableOffset; 44 | } 45 | 46 | uint32_t DynamicSymbolTableHeader::getNumberEntries() 47 | { 48 | return numberEntries; 49 | } 50 | 51 | DynamicSymbolTableEntry::DynamicSymbolTableEntry(uint32_t index, 52 | uint64_t indirectAddress, char *name, Section *section) 53 | { 54 | this->index = index; 55 | this->indirectAddress = indirectAddress; 56 | this->name = new char[strlen(name)+ 1]; 57 | strcpy(this->name, name); 58 | this->section = section; 59 | } 60 | 61 | uint32_t DynamicSymbolTableEntry::getIndex() 62 | { 63 | return index; 64 | } 65 | 66 | uint64_t DynamicSymbolTableEntry::getIndirectAdress() 67 | { 68 | return indirectAddress; 69 | } 70 | 71 | char * DynamicSymbolTableEntry::getName() 72 | { 73 | return name; 74 | } 75 | Section *DynamicSymbolTableEntry::getSection() 76 | { 77 | return section; 78 | } 79 | DynamicSymbolTableEntry::~DynamicSymbolTableEntry() 80 | { 81 | delete name; 82 | } 83 | -------------------------------------------------------------------------------- /include/pugiconfig.hpp: -------------------------------------------------------------------------------- 1 | /** 2 | * pugixml parser - version 1.8 3 | * -------------------------------------------------------- 4 | * Copyright (C) 2006-2016, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) 5 | * Report bugs and download new versions at http://pugixml.org/ 6 | * 7 | * This library is distributed under the MIT License. See notice at the end 8 | * of this file. 9 | * 10 | * This work is based on the pugxml parser, which is: 11 | * Copyright (C) 2003, by Kristen Wegner (kristen@tima.net) 12 | */ 13 | 14 | #ifndef HEADER_PUGICONFIG_HPP 15 | #define HEADER_PUGICONFIG_HPP 16 | 17 | // Uncomment this to enable wchar_t mode 18 | // #define PUGIXML_WCHAR_MODE 19 | 20 | // Uncomment this to enable compact mode 21 | // #define PUGIXML_COMPACT 22 | 23 | // Uncomment this to disable XPath 24 | // #define PUGIXML_NO_XPATH 25 | 26 | // Uncomment this to disable STL 27 | // #define PUGIXML_NO_STL 28 | 29 | // Uncomment this to disable exceptions 30 | // #define PUGIXML_NO_EXCEPTIONS 31 | 32 | // Set this to control attributes for public classes/functions, i.e.: 33 | // #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL 34 | // #define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL 35 | // #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall 36 | // In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead 37 | 38 | // Tune these constants to adjust memory-related behavior 39 | // #define PUGIXML_MEMORY_PAGE_SIZE 32768 40 | // #define PUGIXML_MEMORY_OUTPUT_STACK 10240 41 | // #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096 42 | 43 | // Uncomment this to switch to header-only version 44 | // #define PUGIXML_HEADER_ONLY 45 | 46 | // Uncomment this to enable long long support 47 | // #define PUGIXML_HAS_LONG_LONG 48 | 49 | #endif 50 | 51 | /** 52 | * Copyright (c) 2006-2016 Arseny Kapoulkine 53 | * 54 | * Permission is hereby granted, free of charge, to any person 55 | * obtaining a copy of this software and associated documentation 56 | * files (the "Software"), to deal in the Software without 57 | * restriction, including without limitation the rights to use, 58 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 59 | * copies of the Software, and to permit persons to whom the 60 | * Software is furnished to do so, subject to the following 61 | * conditions: 62 | * 63 | * The above copyright notice and this permission notice shall be 64 | * included in all copies or substantial portions of the Software. 65 | * 66 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 67 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 68 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 69 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 70 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 71 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 72 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 73 | * OTHER DEALINGS IN THE SOFTWARE. 74 | */ 75 | -------------------------------------------------------------------------------- /src/FileUtils.cpp: -------------------------------------------------------------------------------- 1 | #include "FileUtils.hpp" 2 | 3 | bool FileUtils::isSwap = false; 4 | 5 | void FileUtils::readUint32(FILE *file, uint32_t *buff) 6 | { 7 | uint32_t rc; 8 | 9 | rc = fread(buff, sizeof(uint32_t), 1, file); 10 | if (rc != 1) 11 | throw std::runtime_error("File Read32 Fail"); 12 | if (isSwap) 13 | *buff = swapUint32(*buff); 14 | } 15 | 16 | void FileUtils::readNetworkUint32(FILE *file, uint32_t *buff) 17 | { 18 | uint32_t rc; 19 | uint32_t buf; 20 | 21 | rc = fread(&buf, sizeof(uint32_t), 1, file); 22 | if (rc != 1) 23 | throw std::runtime_error("File ReadNetwork32 Fail"); 24 | *buff = ntohl(buf); 25 | } 26 | 27 | 28 | void FileUtils::readUint64(FILE *file, uint64_t *buff) 29 | { 30 | uint32_t rc; 31 | 32 | rc = fread(buff, sizeof(uint64_t), 1, file); 33 | if (rc != 1) 34 | throw std::runtime_error("File Read64 Fail"); 35 | if (isSwap) 36 | *buff = swapUint64(*buff); 37 | } 38 | 39 | void FileUtils::readUint8(FILE *file, uint8_t *buff) 40 | { 41 | uint32_t rc; 42 | 43 | rc = fread(buff, sizeof(uint8_t), 1, file); 44 | if (rc != 1) 45 | throw std::runtime_error("File Read8 Fail"); 46 | 47 | } 48 | 49 | void FileUtils::readUint16(FILE *file, uint16_t *buff) 50 | { 51 | uint32_t rc; 52 | 53 | rc = fread(buff, sizeof(uint16_t), 1, file); 54 | if (rc != 1) 55 | throw std::runtime_error("File Read16 Fail"); 56 | 57 | if (isSwap) 58 | *buff = swapUint16(*buff); 59 | } 60 | 61 | void FileUtils::readBytes(FILE *file, char *buff, int nr) 62 | { 63 | uint32_t rc; 64 | 65 | rc = fread(buff, nr, 1, file); 66 | if (rc != 1) 67 | throw std::runtime_error("File ReadBytes Fail"); 68 | if (isSwap) 69 | swapBytes(buff, nr); 70 | 71 | } 72 | 73 | void FileUtils::setSwap() 74 | { 75 | isSwap = true; 76 | } 77 | 78 | uint32_t FileUtils::swapUint32(uint32_t value) 79 | { 80 | uint32_t Byte0 = value & 0x000000FF; 81 | uint32_t Byte1 = value & 0x0000FF00; 82 | uint32_t Byte2 = value & 0x00FF0000; 83 | uint32_t Byte3 = value & 0xFF000000; 84 | return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24); 85 | } 86 | 87 | uint64_t FileUtils::swapUint64(uint64_t value) 88 | { 89 | uint64_t Hi = swapUint32(uint32_t(value)); 90 | uint32_t Lo = swapUint32(uint32_t(value >> 32)); 91 | return (Hi << 32) | Lo; 92 | } 93 | 94 | uint16_t FileUtils::swapUint16(uint16_t value) 95 | { 96 | uint16_t Hi = value << 8; 97 | uint16_t Lo = value >> 8; 98 | return Hi | Lo; 99 | } 100 | 101 | void FileUtils::swapBytes(char *buff, int size) 102 | { 103 | uint32_t index; 104 | uint8_t temp; 105 | 106 | for (index = 0; index < size / 2; index++) { 107 | temp = buff[index]; 108 | buff[index] = buff[size - index - 1]; 109 | buff[size = index - 1] = temp; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/SymbolTableEntry.cpp: -------------------------------------------------------------------------------- 1 | #include "SymbolTableEntry.hpp" 2 | 3 | SymbolTableEntry::SymbolTableEntry(FILE *file, char *strings) 4 | { 5 | FileUtils::readUint32(file, &stringTableIndex); 6 | 7 | FileUtils::readUint8(file, &type); 8 | 9 | FileUtils::readUint8(file, §ionIndex); 10 | 11 | FileUtils::readUint16(file, &description); 12 | 13 | /*get the name from string table*/ 14 | name = new char[strlen(&strings[stringTableIndex]) + 1]; 15 | 16 | strcpy(name, &strings[stringTableIndex]); 17 | 18 | } 19 | 20 | SymbolTableEntry::SymbolTableEntry() 21 | { 22 | 23 | } 24 | 25 | uint32_t SymbolTableEntry::getStringTableIndex() 26 | { 27 | return stringTableIndex; 28 | } 29 | 30 | uint8_t SymbolTableEntry::getType() 31 | { 32 | return type; 33 | } 34 | 35 | uint8_t SymbolTableEntry::getSectionIndex() 36 | { 37 | return sectionIndex; 38 | } 39 | 40 | uint16_t SymbolTableEntry::getDescription() 41 | { 42 | return description; 43 | } 44 | 45 | char *SymbolTableEntry::getName() 46 | { 47 | return name; 48 | } 49 | 50 | SymbolTableEntry::~SymbolTableEntry() 51 | { 52 | delete name; 53 | } 54 | 55 | bool SymbolTableEntry::isDebug() 56 | { 57 | return (type & STAB_MASK); 58 | } 59 | 60 | bool SymbolTableEntry::isPrivateExternal() 61 | { 62 | return (type & PEXT_MASK); 63 | } 64 | 65 | bool SymbolTableEntry::isExternal() 66 | { 67 | return (type & EXT_MASK); 68 | } 69 | 70 | bool SymbolTableEntry::isUndefined() 71 | { 72 | return ((type & TYPE_MASK) == UNDEFINED); 73 | } 74 | 75 | bool SymbolTableEntry::isAbsolute() 76 | { 77 | return ((type & TYPE_MASK) == ABSOLUTE); 78 | } 79 | 80 | bool SymbolTableEntry::isDefinedInSection() 81 | { 82 | return ((type & TYPE_MASK) == DEFINED_IN_SECT); 83 | } 84 | 85 | bool SymbolTableEntry::isPrebound() 86 | { 87 | return ((type & TYPE_MASK) == PREBOUND); 88 | } 89 | 90 | bool SymbolTableEntry::isIndirect() 91 | { 92 | return ((type & TYPE_MASK) == INDIRECT); 93 | } 94 | 95 | bool SymbolTableEntry::isReferenceUndefinedNonLazy() 96 | { 97 | if(isUndefined()) { 98 | return ((description & REFERENCE_MASK) == REFERENCE_FLAG_UNDEFINED_NON_LAZY); 99 | } 100 | 101 | return false; 102 | } 103 | 104 | bool SymbolTableEntry::isReferenceUndefinedLazy() 105 | { 106 | if(isUndefined()) { 107 | return ((description & REFERENCE_MASK) == REFERENCE_FLAG_UNDEFINED_LAZY); 108 | } 109 | 110 | return false; 111 | } 112 | 113 | bool SymbolTableEntry::isReferenceDefined() 114 | { 115 | if(isUndefined()) { 116 | return ((description & REFERENCE_MASK) == REFERENCE_FLAG_DEFINED); 117 | } 118 | 119 | return false; 120 | } 121 | 122 | bool SymbolTableEntry::isReferencePrivateDefined() 123 | { 124 | if(isUndefined()) { 125 | return ((description & REFERENCE_MASK) == REFERENCE_FLAG_PRIVATE_DEFINED); 126 | } 127 | 128 | return false; 129 | } 130 | 131 | bool SymbolTableEntry::isReferencePrivateUndefinedNonLazy() 132 | { 133 | if(isUndefined()) { 134 | return ((description & REFERENCE_MASK) == REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY); 135 | } 136 | 137 | return false; 138 | } 139 | 140 | bool SymbolTableEntry::isReferencePrivateUndefinedLazy() 141 | { 142 | if(isUndefined()) { 143 | return ((description & REFERENCE_MASK) == REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY); 144 | } 145 | 146 | return false; 147 | } 148 | 149 | bool SymbolTableEntry::isReferenceDynamically() 150 | { 151 | if(isUndefined()) { 152 | return ((description & REFERENCE_MASK) == REFERENCED_DYNAMICALLY); 153 | } 154 | 155 | return false; 156 | } 157 | 158 | uint8_t SymbolTableEntry::getLibraryOrdinal() 159 | { 160 | if(isUndefined()) 161 | return ((description >> 8) & 0xFF); 162 | else 163 | return -1; 164 | } 165 | 166 | bool SymbolTableEntry::isWeakReferenced() 167 | { 168 | return (description & WEAK_REF_MASK); 169 | } 170 | 171 | bool SymbolTableEntry::isWeakDefined() 172 | { 173 | return (description & WEAK_DEF_MASK); 174 | } 175 | 176 | bool SymbolTableEntry::isRefToWeakSymbol() 177 | { 178 | return (description & REF_TO_WEAK_MASK); 179 | } 180 | 181 | bool SymbolTableEntry::isSymbolResolver() 182 | { 183 | return (description & SYMBOL_RESOLVER_MASK); 184 | } 185 | 186 | bool SymbolTableEntry::isArmThumb() 187 | { 188 | return (description & ARM_THUMB_MASK); 189 | } 190 | -------------------------------------------------------------------------------- /src/Blobs.cpp: -------------------------------------------------------------------------------- 1 | #include "Blobs.hpp" 2 | 3 | SuperBlob::SuperBlob() 4 | { 5 | } 6 | 7 | SuperBlob::SuperBlob(FILE *file, LinkEditCmd sigCmd) 8 | { 9 | struct subblob sb; 10 | uint32_t buf; 11 | uint32_t offset = sigCmd.getDataOffset(); 12 | 13 | fseek(file, offset, SEEK_SET); 14 | FileUtils::readNetworkUint32(file, &buf); 15 | if (buf != CSMAGIC_EMBEDDED_SIGNATURE) { 16 | throw std::runtime_error("Signature not valid."); 17 | } 18 | 19 | FileUtils::readNetworkUint32(file, &length); 20 | FileUtils::readNetworkUint32(file, &numBlobs); 21 | 22 | for (unsigned int i = 0; i < numBlobs; i++) { 23 | FileUtils::readNetworkUint32(file, &sb.type); 24 | FileUtils::readNetworkUint32(file, &sb.offset); 25 | subblobs.push_back(sb); 26 | } 27 | 28 | } 29 | 30 | uint32_t SuperBlob::getLength() 31 | { 32 | return length; 33 | } 34 | 35 | uint32_t SuperBlob::getNumBlobs() 36 | { 37 | return numBlobs; 38 | } 39 | 40 | std::vector SuperBlob::getSubBlobs() 41 | { 42 | return subblobs; 43 | } 44 | 45 | CodeDirectoryBlob::CodeDirectoryBlob() 46 | { 47 | } 48 | 49 | CodeDirectoryBlob::CodeDirectoryBlob(FILE *file, LinkEditCmd sigCmd, 50 | SuperBlob sb) 51 | { 52 | char *buf; 53 | uint32_t magic; 54 | uint32_t sbOffset = sigCmd.getDataOffset(); 55 | uint32_t cdbOffset = 0; 56 | std::vector sbs = sb.getSubBlobs(); 57 | 58 | for (unsigned int i = 0; i < sbs.size(); i++) { 59 | if (sbs[i].type == CODE_DIRECTORY_BLOB) { 60 | cdbOffset = sbs[i].offset; 61 | break; 62 | } 63 | } 64 | 65 | fseek(file, sbOffset + cdbOffset, SEEK_SET); 66 | FileUtils::readNetworkUint32(file, &magic); 67 | if (magic != CSMAGIC_DIRECTORY_BLOB) { 68 | throw std::runtime_error("Code Directory Blob wrong magic"); 69 | } 70 | 71 | /* Read metadata */ 72 | FileUtils::readNetworkUint32(file, &length); 73 | FileUtils::readNetworkUint32(file, &version); 74 | FileUtils::readNetworkUint32(file, &flags); 75 | FileUtils::readNetworkUint32(file, &hashOffset); 76 | FileUtils::readNetworkUint32(file, &identOffset); 77 | FileUtils::readNetworkUint32(file, &nSpecialSlots); 78 | FileUtils::readNetworkUint32(file, &nCodeSlots); 79 | FileUtils::readNetworkUint32(file, &codeLimit); 80 | FileUtils::readUint8(file, &hashSize); 81 | FileUtils::readUint8(file, &hashType); 82 | FileUtils::readUint8(file, &platform); 83 | FileUtils::readUint8(file, &pageSize); 84 | FileUtils::readNetworkUint32(file, &spare2); 85 | FileUtils::readNetworkUint32(file, &scatterOffset); 86 | FileUtils::readNetworkUint32(file, &teamOffset); 87 | 88 | /* Read hashes */ 89 | uint32_t hashesStart = sbOffset + cdbOffset + hashOffset - hashSize * nSpecialSlots; 90 | fseek(file, hashesStart, SEEK_SET); 91 | buf = (char*) malloc(hashSize * (nSpecialSlots + nCodeSlots)); 92 | for (uint32_t i = 0; i < nSpecialSlots; i++) { 93 | char *cur_buf = buf + i * hashSize; 94 | FileUtils::readBytes(file, cur_buf, hashSize); 95 | hashes.push_back(cur_buf); 96 | } 97 | 98 | for (uint32_t i = 0; i < nCodeSlots; i++) { 99 | char *cur_buf = buf + i * hashSize + nSpecialSlots * hashSize; 100 | FileUtils::readBytes(file, cur_buf, hashSize); 101 | hashes.push_back(cur_buf); 102 | } 103 | 104 | } 105 | 106 | uint32_t CodeDirectoryBlob::getLength() 107 | { 108 | return length; 109 | } 110 | 111 | uint32_t CodeDirectoryBlob::getVersion() 112 | { 113 | return version; 114 | } 115 | 116 | uint32_t CodeDirectoryBlob::getFlags() 117 | { 118 | return flags; 119 | } 120 | 121 | uint32_t CodeDirectoryBlob::getHashOffset() 122 | { 123 | return hashOffset; 124 | } 125 | 126 | uint32_t CodeDirectoryBlob::getIdentOffset() 127 | { 128 | return identOffset; 129 | } 130 | 131 | uint32_t CodeDirectoryBlob::getNSpecialSlots() 132 | { 133 | return nSpecialSlots; 134 | } 135 | 136 | uint32_t CodeDirectoryBlob::getNCodeSlots() 137 | { 138 | return nCodeSlots; 139 | } 140 | 141 | uint32_t CodeDirectoryBlob::getCodeLimit() 142 | { 143 | return codeLimit; 144 | } 145 | 146 | uint8_t CodeDirectoryBlob::getHashSize() 147 | { 148 | return hashSize; 149 | } 150 | 151 | uint8_t CodeDirectoryBlob::getHashType() 152 | { 153 | return hashType; 154 | } 155 | 156 | uint8_t CodeDirectoryBlob::getPlatform() 157 | { 158 | return platform; 159 | } 160 | 161 | uint8_t CodeDirectoryBlob::getPageSize() 162 | { 163 | return pageSize; 164 | } 165 | 166 | uint32_t CodeDirectoryBlob::getSpare2() 167 | { 168 | return spare2; 169 | } 170 | 171 | uint32_t CodeDirectoryBlob::getScatterOffset() 172 | { 173 | return scatterOffset; 174 | } 175 | 176 | uint32_t CodeDirectoryBlob::getTeamOffset() 177 | { 178 | return teamOffset; 179 | } 180 | 181 | std::vector 182 | CodeDirectoryBlob::getHashes() 183 | { 184 | return hashes; 185 | } 186 | 187 | 188 | -------------------------------------------------------------------------------- /include/SymbolTableEntry.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __SYMBOLTABLENTRY_HPP 2 | #define __SYMBOLTABLENTRY_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include "FileUtils.hpp" 8 | 9 | /*masks for type bits*/ 10 | #define STAB_MASK 0xe0 /* if any of these bits set, a symbolic debugging entry */ 11 | #define PEXT_MASK 0x10 /* private external symbol bit */ 12 | #define TYPE_MASK 0x0e /* mask for the N_TYPE bits */ 13 | #define EXT_MASK 0x01 /* external symbol bit, set for external symbols */ 14 | 15 | /*values for N_TYPE*/ 16 | #define UNDEFINED 0x0 /* undefined */ 17 | #define ABSOLUTE 0x2 /* absolute */ 18 | #define DEFINED_IN_SECT 0xe /* defined in section number sectionIndex */ 19 | #define PREBOUND 0xc /* prebound undefined (defined in a dylib) */ 20 | #define INDIRECT 0xa /* indirect */ 21 | 22 | /*mask for the description field in case of undefined symbols*/ 23 | #define REFERENCE_MASK 0xf 24 | 25 | /*type of references*/ 26 | #define REFERENCE_FLAG_UNDEFINED_NON_LAZY 0 27 | #define REFERENCE_FLAG_UNDEFINED_LAZY 1 28 | #define REFERENCE_FLAG_DEFINED 2 29 | #define REFERENCE_FLAG_PRIVATE_DEFINED 3 30 | #define REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY 4 31 | #define REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY 5 32 | 33 | 34 | /* 35 | * To simplify stripping of objects that use are used with the dynamic link 36 | * editor, the static link editor marks the symbols defined an object that are 37 | * referenced by a dynamicly bound object (dynamic shared libraries, bundles). 38 | * With this marking strip knows not to strip these symbols. 39 | */ 40 | #define REFERENCED_DYNAMICALLY 0x0010 41 | 42 | /* 43 | * The N_WEAK_REF bit of the n_desc field indicates to the dynamic linker that 44 | * the undefined symbol is allowed to be missing and is to have the address of 45 | * zero when missing. 46 | */ 47 | #define WEAK_REF_MASK 0x0040 /* symbol is weak referenced */ 48 | 49 | /* 50 | * The N_WEAK_DEF bit of the n_desc field indicates to the static and dynamic 51 | * linkers that the symbol definition is weak, allowing a non-weak symbol to 52 | * also be used which causes the weak definition to be discared. Currently this 53 | * is only supported for symbols in coalesed sections. 54 | */ 55 | #define WEAK_DEF_MASK 0x0080 /* coalesed symbol is a weak definition */ 56 | 57 | /* 58 | * The N_REF_TO_WEAK bit of the n_desc field indicates to the dynamic linker 59 | * that the undefined symbol should be resolved using flat namespace searching. 60 | */ 61 | #define REF_TO_WEAK_MASK 0x0080 /* reference to a weak symbol */ 62 | 63 | /* 64 | * The N_SYMBOL_RESOLVER bit of the n_desc field indicates that the 65 | * that the function is actually a resolver function and should 66 | * be called to get the address of the real function to use. 67 | * This bit is only available in .o files (MH_OBJECT filetype) 68 | */ 69 | #define SYMBOL_RESOLVER_MASK 0x0100 70 | 71 | 72 | #define ARM_THUMB_MASK 0x0008 73 | 74 | /*class for an entry in the symbol table independent of 32bit or 64bit architecture*/ 75 | class SymbolTableEntry 76 | { 77 | protected: 78 | uint32_t stringTableIndex; 79 | uint8_t type; 80 | uint8_t sectionIndex; 81 | uint16_t description; 82 | char *name; 83 | 84 | public: 85 | SymbolTableEntry(FILE *file, char *strings); 86 | SymbolTableEntry(); 87 | uint32_t getStringTableIndex(); 88 | uint8_t getType(); 89 | uint8_t getSectionIndex(); 90 | uint16_t getDescription(); 91 | char *getName(); 92 | virtual uint64_t getValue() = 0; 93 | 94 | /*queries of the type field*/ 95 | bool isDebug(); 96 | bool isPrivateExternal(); 97 | bool isExternal(); 98 | bool isUndefined(); 99 | bool isAbsolute(); 100 | bool isDefinedInSection(); 101 | bool isPrebound(); 102 | bool isIndirect(); 103 | 104 | /*queries of the description field*/ 105 | bool isReferenceUndefinedNonLazy(); 106 | bool isReferenceUndefinedLazy(); 107 | bool isReferenceDefined(); 108 | bool isReferencePrivateDefined(); 109 | bool isReferencePrivateUndefinedNonLazy(); 110 | bool isReferencePrivateUndefinedLazy(); 111 | bool isReferenceDynamically(); 112 | 113 | uint8_t getLibraryOrdinal(); 114 | bool isWeakReferenced(); 115 | bool isWeakDefined(); 116 | bool isRefToWeakSymbol(); 117 | bool isSymbolResolver(); 118 | 119 | bool isArmThumb(); 120 | 121 | virtual ~SymbolTableEntry(); 122 | 123 | }; 124 | 125 | 126 | #endif 127 | -------------------------------------------------------------------------------- /include/DynamicSymbolTable.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __DYNAMICSYMBOLTABLE_HPP 2 | #define __DYNAMICSYMBOLTABLE_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include "FileUtils.hpp" 8 | #include "Section.hpp" 9 | 10 | /* An indirect symbol table entry is simply a 32bit index into the symbol table 11 | * to the symbol that the pointer or stub is refering to. Unless it is for a 12 | * non-lazy symbol pointer section for a defined symbol which strip(1) as 13 | * removed. In which case it has the value INDIRECT_SYMBOL_LOCAL. If the 14 | * symbol was also absolute INDIRECT_SYMBOL_ABS is or'ed with that. 15 | */ 16 | #define INDIRECT_SYMBOL_LOCAL 0x80000000 17 | #define INDIRECT_SYMBOL_ABS 0x40000000 18 | 19 | 20 | /*most of the fields are for now unused*/ 21 | class DynamicSymbolTableHeader { 22 | private: 23 | /* index to local symbols */ 24 | uint32_t indexLocalSym; 25 | /* number of local symbols */ 26 | uint32_t numberLocalSym; 27 | 28 | /* index to externally defined symbols */ 29 | uint32_t indexExtDefSym; 30 | /* number of externally defined symbols */ 31 | uint32_t numberExtDefSym; 32 | 33 | /* index to undefined symbols */ 34 | uint32_t indexUndefSym; 35 | /* number of undefined symbols */ 36 | uint32_t numberUndefSym; 37 | 38 | /* 39 | * For the dynamic binding process to find which module a symbol 40 | * is defined in, the table of contents is used (analogous to the ranlib 41 | * structure in an archive) which maps defined external symbols to modules 42 | * they are defined in. This exists only in a dynamically linked shared 43 | * library file. 44 | */ 45 | 46 | /* file offset to table of contents */ 47 | uint32_t tocOff; 48 | /* number of entries in table of contents */ 49 | uint32_t numberTocEntries; 50 | 51 | /* 52 | * To support dynamic binding of "modules" (whole object files) the symbol 53 | * table must reflect the modules that the file was created from. This is 54 | * done by having a module table that has indexes and counts into the merged 55 | * tables for each module. The module structure that these two entries 56 | * refer to is described below. This exists only in a dynamically linked 57 | * shared library file. 58 | */ 59 | 60 | /* file offset to module table */ 61 | uint32_t modTabOff; 62 | /* number of module table entries */ 63 | uint32_t numberModTabEntries; 64 | 65 | /* 66 | * To support dynamic module binding the module structure for each module 67 | * indicates the external references (defined and undefined) each module 68 | * makes. For each module there is an offset and a count into the 69 | * reference symbol table for the symbols that the module references. 70 | * This exists only in a dynamically linked shared library file. For 71 | * executable and object modules the defined external symbols and the 72 | * undefined external symbols indicates the external references. 73 | */ 74 | 75 | /* offset to referenced symbol table */ 76 | uint32_t extRefSymOff; 77 | /* number of referenced symbol table entries */ 78 | uint32_t numberExtRefSyms; 79 | 80 | /* file offset to the indirect symbol table */ 81 | uint32_t tableOffset; 82 | /* number of indirect symbol table entries */ 83 | uint32_t numberEntries; 84 | 85 | /* offset to external relocation entries */ 86 | uint32_t extRelOff; 87 | /* number of external relocation entries */ 88 | uint32_t numberExtRel; 89 | 90 | /* 91 | * All the local relocation entries are grouped together (they are not 92 | * grouped by their module since they are only used if the object is moved 93 | * from it staticly link edited address). 94 | */ 95 | 96 | /* offset to local relocation entries */ 97 | uint32_t locRelOff; 98 | /* number of local relocation entries */ 99 | uint32_t numberLocRel; 100 | 101 | public: 102 | DynamicSymbolTableHeader(); 103 | DynamicSymbolTableHeader(FILE *file); 104 | uint32_t getTableOffset(); 105 | uint32_t getNumberEntries(); 106 | 107 | }; 108 | 109 | /*an indirect symbol is represented by its index in the symbol table*/ 110 | /*it's indirect address name and the section in which is defined*/ 111 | class DynamicSymbolTableEntry 112 | { 113 | private: 114 | uint32_t index; 115 | uint64_t indirectAddress; 116 | char *name; 117 | Section *section; 118 | 119 | public: 120 | DynamicSymbolTableEntry(uint32_t index, uint64_t indirectAddress, 121 | char *name, Section *section); 122 | uint32_t getIndex(); 123 | uint64_t getIndirectAdress(); 124 | char *getName(); 125 | Section *getSection(); 126 | 127 | ~DynamicSymbolTableEntry(); 128 | }; 129 | 130 | #endif 131 | -------------------------------------------------------------------------------- /include/MachO.hpp: -------------------------------------------------------------------------------- 1 | #ifndef __MACHO_HPP 2 | #define __MACHO_HPP 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include "FileUtils.hpp" 11 | #include "MachHeader.hpp" 12 | #include "Section.hpp" 13 | #include "Segment.hpp" 14 | #include "Section32.hpp" 15 | #include "Segment32.hpp" 16 | #include "Section64.hpp" 17 | #include "Segment64.hpp" 18 | #include "SymbolTableHeader.hpp" 19 | #include "StringTable.hpp" 20 | #include "SymbolTableEntry.hpp" 21 | #include "SymbolTableEntry32.hpp" 22 | #include "SymbolTableEntry64.hpp" 23 | #include "SimpleLoadCommands.hpp" 24 | #include "LibraryInfo.hpp" 25 | #include "DynamicSymbolTable.hpp" 26 | #include "Blobs.hpp" 27 | #include "Entitlements.hpp" 28 | 29 | 30 | #define LC_SEGMENT32 0x01 31 | #define LC_SEGMENT64 0x19 32 | #define LC_SYMTAB 0x02 33 | #define LC_LOAD_DYLINKER 0x0E 34 | 35 | #define LC_UUID 0x1B 36 | #define UUID_SIZE 16 37 | 38 | #define LC_REQ_DYLD 0x80000000 39 | #define LC_MAIN (0x28|LC_REQ_DYLD) 40 | 41 | #define LC_LOAD_DYLIB 0x0C 42 | 43 | #define LC_FUNCTION_STARTS 0x26 44 | 45 | #define LC_DYSYMTAB 0x0B 46 | 47 | #define LC_CODE_SIGNATURE 0x1D 48 | 49 | #define NAMEPREFIX "func_" 50 | 51 | struct myKextComp { 52 | bool operator()(char *a, char *b) const { 53 | return std::strcmp(a, b) < 0; 54 | } 55 | }; 56 | 57 | /*high level class*/ 58 | /*entry point of the library*/ 59 | class MachO 60 | { 61 | private: 62 | char *fileName; 63 | FILE *file; 64 | 65 | MachHeader header; 66 | 67 | std::vector segments; 68 | 69 | SymbolTableHeader symbolTableHeader; 70 | bool symbolTableHeaderPresent; 71 | 72 | DynamicSymbolTableHeader dynamicSymbolTableHeader; 73 | 74 | /*flags to avoid recomputing*/ 75 | bool stringTableComputed; 76 | bool symbolTableComputed; 77 | 78 | /*the string table*/ 79 | StringTable *stringTable; 80 | 81 | /*entries in the symbol table*/ 82 | std::vector symbolTable; 83 | std::map symbolsFileOffset; 84 | 85 | /*the dynamic symbol table*/ 86 | std::vector dynamicSymbolTable; 87 | bool DynamicSymbolTableComputed; 88 | 89 | 90 | /*dinmaic linker load command*/ 91 | LoadDyLinkerCmd *loadDyLinkerCmd; 92 | 93 | /*entry point command*/ 94 | LoadMainCmd loadMainCmd; 95 | bool loadMainCmdPresent; 96 | 97 | /*the uuid is a 128-bit unique random number that*/ 98 | /*identifies an object produced by the static link editor*/ 99 | uint8_t uuid[UUID_SIZE]; 100 | 101 | /*Dynamicly linked shared libraries*/ 102 | std::vector dynamicLibraries; 103 | 104 | /*information about where to find the table that includes 105 | the start of the functions*/ 106 | LinkEditCmd functionStartsCmd; 107 | bool functionStartsCmdPresent; 108 | 109 | std::map functionsOffset; 110 | bool functionsOffsetComputed; 111 | 112 | std::vector > kextsInfo; 113 | bool kextsInfoComputed; 114 | std::map kextsHeader; 115 | 116 | void computeSymbolsFileOffset(); 117 | char *getFunctionName(uint64_t functionFileOffset); 118 | 119 | /* information about where to find signature */ 120 | LinkEditCmd codeSignatureCmd; 121 | bool codeSignatureCmdPresent; 122 | 123 | /* superblob */ 124 | SuperBlob superblob; 125 | bool isSuperBlobFetched; 126 | 127 | /* code directory blob */ 128 | CodeDirectoryBlob codeDirectoryBlob; 129 | bool isCodeDirectoryBlobFetched; 130 | 131 | /* entitlements */ 132 | Entitlements entitlements; 133 | bool isEntitlementsFetched; 134 | 135 | public: 136 | MachO(char *fileName); 137 | 138 | char *getFileName(); 139 | 140 | 141 | MachHeader getHeader(); 142 | 143 | std::vector getSegments(); 144 | 145 | Segment *getSegmentByName(char *name); 146 | Section *getSectionByIndex(uint32_t index); 147 | Section *getSectionByName(char * segmentName, char *sectionName); 148 | 149 | SymbolTableHeader getSymbolTableHeader(); 150 | 151 | StringTable *getStringTable(); 152 | 153 | std::vector getSymbolTable(); 154 | uint64_t getSymbolFileOffset(SymbolTableEntry *symbol); 155 | 156 | std::vector getDynamicSymbolTable(); 157 | 158 | LoadDyLinkerCmd *getLoadDyLinkerCmd(); 159 | 160 | uint8_t *getUUID(); 161 | 162 | LoadMainCmd getLoadMainCmd(); 163 | 164 | std::vector getDynamicLibrariesInfo(); 165 | std::vector listDynamicLibraries(); 166 | 167 | LinkEditCmd getFunctionStartsCmd(); 168 | 169 | std::map getFunctionsOffset(); 170 | 171 | std::vector > getKextsInfo(); 172 | 173 | std::vector > getKextByProperty(char * key, char * value); 174 | 175 | std::map getKextByBundleId(char * bundleId); 176 | 177 | uint64_t getVirtToFile(uint64_t virtualAddress); 178 | 179 | void dumpKext(char * bundleId, char *fileName); 180 | 181 | LinkEditCmd getCodeSignatureCmd(); 182 | SuperBlob getSuperBlob(); 183 | CodeDirectoryBlob getCodeDirectoryBlob(); 184 | Entitlements getEntitlements(); 185 | 186 | ~MachO(); 187 | }; 188 | 189 | 190 | #endif 191 | -------------------------------------------------------------------------------- /poc/poc.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "MachO.hpp" 6 | #include "FileReader.hpp" 7 | 8 | 9 | void print_header(MachHeader header) 10 | { 11 | if (header.getMagic() == MAGIC_32) 12 | printf("MACH-O 32\n"); 13 | else 14 | printf("MACH-O 64\n"); 15 | 16 | printf("cputype:%d\n subtype:%x\nfiletype:%x\nncmds:%d\nsize:%d\nflags:%x\n", header.getCpuType(), 17 | header.getCpuSubType(), header.getFileType(), header.getNumberCmds(), header.getSizeOfCmds(), header.getFlags()); 18 | 19 | if (header.getMagic() == MAGIC_64) 20 | printf("reserved:%x\n", header.getReserved()); 21 | } 22 | void print_section(Section *section) 23 | { 24 | printf("Segment name: %s\nSection name %s\n", 25 | section->getSegmentName(), section->getSectionName()); 26 | 27 | printf("virtual address: %llu\nsize: %llu\n", 28 | section->getVirtualAddress(), section->getSize()); 29 | 30 | printf("offset: %x\nnumber of relocations: %d\nalign: %d\n" , 31 | section->getOffset(), section->getNumberRelocations(), section->getAlign()); 32 | 33 | printf("relocation offset: %d\nflags: %u\n", 34 | section->getRelocationOffset(), section->getFlags()); 35 | 36 | printf("reserved1: %d\nreserved2: %d\n", 37 | section->getReserved1(), section->getReserved2()); 38 | } 39 | 40 | void print_segment(Segment *segment) 41 | { 42 | printf("Segment Name: %s\n", segment->getName()); 43 | 44 | printf("virtual address: %lld\nvirtual size: %lld\n", 45 | segment->getVirtualAddress(), segment->getVirtualSize()); 46 | 47 | printf("file offset: %llx\nfile size: %lld\n", 48 | segment->getFileOffset(), segment->getFileSize() ); 49 | 50 | printf("init prot: 0x%x\nmax prot: %x\n", 51 | segment->getInitProtection(), segment->getMaxProtection()); 52 | 53 | printf("flags: %x\nnumber of sections: %d\n", 54 | segment->getFlags(), segment->getNumberSections()); 55 | 56 | std::vector
sections = segment->getSections(); 57 | for(uint32_t i = 0; i < segment->getNumberSections(); i++) 58 | print_section(sections[i]); 59 | } 60 | 61 | void print_symbol_header(SymbolTableHeader header) 62 | { 63 | printf("tableOffset: %u\nnumber symbols: %u\n", 64 | header.getTableOffset(), header.getNumberofSymbols()); 65 | 66 | printf("string table offset: %u\nstring table size: %u\n", 67 | header.getStringTableOffset(), header.getStringTableSize()); 68 | } 69 | 70 | void print_symbol(SymbolTableEntry *entry) 71 | { 72 | printf("string table index: %u\n", entry->getStringTableIndex()); 73 | 74 | printf("symbol name: %s\n", entry->getName()); 75 | 76 | printf("type: 0x%x Debug:%d PrivateExternal:%d External:%d\nUndefined:%d Absolute: %d DefinSection: %d Prebound:%d Indirect %d\n", 77 | entry->getType(), entry->isDebug(), entry->isPrivateExternal(), entry->isExternal(), 78 | entry->isUndefined(), entry->isAbsolute(), entry->isDefinedInSection(), 79 | entry->isPrebound(), entry->isIndirect()); 80 | 81 | printf("section index: %u\n", entry->getSectionIndex()); 82 | 83 | printf("description: %u\n", entry->getDescription()); 84 | if(entry->isUndefined()) 85 | printf("library ordinal: %d\n", entry->getLibraryOrdinal()); 86 | 87 | printf("value: 0x%llx\n", entry->getValue()); 88 | } 89 | void print_lib(LibraryInfo * lib) 90 | { 91 | printf("version:%u\n name: %s\n", lib->getCurrentVersion(), lib->getName()); 92 | 93 | printf("timestamp: %u\n Comp: %u\n", lib->getTimestamp(), lib->getCompatibilityVersion()); 94 | } 95 | /*listing of segments and sections*/ 96 | int main(int argc, char *argv[]) 97 | { 98 | 99 | // int option; 100 | 101 | if (argc != 3) { 102 | printf("Usage: %s