diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 8da2c64..57b49a0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -16,7 +16,7 @@ jobs: run: cmake -B build - name: Build and link objects - run: cmake --build build --config Release + run: cmake --build build windows_latest_build_cmake_msvc: runs-on: windows-latest @@ -42,4 +42,4 @@ jobs: run: cmake -B build - name: Build and link objects - run: cmake --build build --config Release + run: cmake --build build diff --git a/.gitignore b/.gitignore index 85046e6..e6babd0 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,7 @@ venv env bin build +docker-build # Exclude Compiled Files *.a diff --git a/CMakeLists.txt b/CMakeLists.txt index 666db1c..affb433 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,76 +1,12 @@ -cmake_minimum_required( VERSION 3.22 ) +cmake_minimum_required( VERSION 3.14 FATAL_ERROR ) -project( omega-zero CXX ) - -set( CMAKE_CXX_STANDARD_REQUIRED ON ) -set( CMAKE_CXX_STANDARD 20 ) +set( CMAKE_C_STANDARD_REQUIRED ON ) +set( CMAKE_C_STANDARD 99 ) set( CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin ) -set( INCLUDE_DIR ${CMAKE_SOURCE_DIR}/include ) -include_directories( ${PROJECT_NAME} ${INCLUDE_DIR} ) - -set( SOURCE_DIR ${CMAKE_SOURCE_DIR}/src ) -set( SOURCES - # CXX Sources - ${SOURCE_DIR}/elf.cpp - ${SOURCE_DIR}/filetypes.cpp - ${SOURCE_DIR}/main.cpp - ${SOURCE_DIR}/parser.cpp - ${SOURCE_DIR}/pe32.cpp - ${SOURCE_DIR}/util.cpp - # CXX Headers - ${INCLUDE_DIR}/elf.hpp - ${INCLUDE_DIR}/filetypes.hpp - ${INCLUDE_DIR}/parser.hpp - ${INCLUDE_DIR}/pe32.hpp - ${INCLUDE_DIR}/util.hpp -) - -add_executable( ${PROJECT_NAME} ${SOURCES} ) -set_target_properties( - ${PROJECT_NAME} - PROPERTIES - PREFIX vpr- -) - -target_compile_options( - ${PROJECT_NAME} - PRIVATE $<$:/W4> - $<$:/O2> - $<$:/DNDEBUG> - $<$:-Ofast> - $<$:-Wall> - $<$:-Wextra> - $<$:-Werror> - $<$:-Wshadow> - $<$:-Wpedantic> - $<$:-Wconversion> - $<$:-ffunction-sections> - $<$:-ffast-math> - $<$:-funroll-loops> - $<$:-fPIE> - $<$:-Ofast> - $<$:-Wall> - $<$:-Wextra> - $<$:-Werror> - $<$:-Wshadow> - $<$:-Wpedantic> - $<$:-Wconversion> - $<$:-ffunction-sections> - $<$:-ffast-math> - $<$:-funroll-loops> - $<$:-fPIE> -) - -target_link_options( - ${PROJECT_NAME} - PRIVATE $<$:/MANIFEST:NO> - $<$:-s> - $<$:-s> -) +project( omega-zero + VERSION 1.1.0 + LANGUAGES C ) -install( - TARGETS ${PROJECT_NAME} - DESTINATION ${CMAKE_INSTALL_PREFIX}/bin -) +add_subdirectory( omega-zero ) diff --git a/Dockerfile b/Dockerfile index ef9dc81..1472b58 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,47 +1,26 @@ # Creator: VPR # Created: January 27th, 2022 -# Updated: March 11th, 2022 +# Updated: March 14th, 2025 -FROM ubuntu:20.04 +FROM ubuntu:22.04 # Set env to avoid user input interruption during installation -ENV TZ=America/Chicago +ENV TZ=Etc/UTC RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone # Install deps RUN apt-get update -y -RUN apt-get install -y --no-install-recommends sudo \ - zsh \ - zsh-autosuggestions \ - git \ - curl \ - wget \ - vim \ - tree \ - tmux \ - zip \ - unzip \ - pkg-config \ - m4 \ - libtool \ - automake \ - gnutls-bin \ - make \ - build-essential \ - gcc \ - gcc-multilib \ - g++-multilib \ - mingw-w64 \ - mingw-w64-common \ - mingw-w64-i686-dev \ - mingw-w64-x86-64-dev \ - gdb \ - cscope - -# Change login shell to zsh -RUN chsh -s /bin/zsh $(whoami) +RUN apt-get install -y --no-install-recommends \ +cmake \ +build-essential \ +gcc \ +gcc-multilib \ +g++-multilib \ +mingw-w64 \ +mingw-w64-common \ +mingw-w64-i686-dev \ +mingw-w64-x86-64-dev # Create omega-zero user && working directory -RUN mkdir -p /home/oz ENV HOME=/home/root -WORKDIR /home/oz/omega-zero +WORKDIR /opt/omega-zero diff --git a/README.md b/README.md index 4cf2663..6d3a0e0 100644 --- a/README.md +++ b/README.md @@ -14,15 +14,14 @@ This project aims to provide a tool for the stripping of the section-header information of 32/64 bit ELF and PE32 executables. -## Docker Environment +## Building with a Docker Environment ``` # Download repo git clone https://github.com/0xvpr/vpr-omega-zero cd vpr-omega-zero -# Create docker image +# Create docker image and build with cmake chmod +x docker-build.sh && ./docker-build.sh -chmod +x docker-start.sh && ./docker-start.sh ``` ## Build instructions @@ -48,7 +47,7 @@ cmake.exe --build build vpr-omega-zero path/to/executable [ path/to/other/executable ] ``` -## Testing (Needs improvement) +## Testing TODO ```bash # chmod +x compare.sh && ./compare.sh # deprecated ``` diff --git a/compile_flags.txt b/compile_flags.txt index d029dec..ba20890 100644 --- a/compile_flags.txt +++ b/compile_flags.txt @@ -1,4 +1,5 @@ --std=c++2a +--target=x86_64-pc-linux-gnu +-std=c99 -Iinclude -Wall -Wextra diff --git a/docker-build.sh b/docker-build.sh index 8b5567b..ff7e21b 100644 --- a/docker-build.sh +++ b/docker-build.sh @@ -1,16 +1,22 @@ -#!/bin/sh +#!/bin/bash -# Creator: VPR -# Created: March 11th, 2022 -# Updated: March 11th, 2022 +# Created by: VPR +# Created: March 11th, 2022 + +# Updated by: VPR +# Updated: March 15th, 2025 set -e pipefail set -e errexit set -e nounset set -e xtrace +ROOT_DIR="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" + DOCKER_FILE="Dockerfile" DOCKER_IMAGE="omega-zero-dev" +USER_MOD="$(id -u):$(id -g)" -# Builds docker image using root Dockerfile -docker build -f "${__docker_file}" -t "${DOCKER_IMAGE}" . +# Builds docker image using root Dockerfile and runs cmake for installation +[[ $(docker image ls -a | grep omega-zero-dev) ]] || docker build -f "${DOCKER_FILE}" -t "${DOCKER_IMAGE}" . +docker run -u ${USER_MOD} -itv ${ROOT_DIR}:/opt/omega-zero "${DOCKER_IMAGE}" /bin/bash -c "cmake -B docker-build && cmake --build docker-build" diff --git a/docker-start.sh b/docker-start.sh deleted file mode 100644 index 29a8120..0000000 --- a/docker-start.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -# Creator: VPR -# Created: March 11th, 2022 -# Updated: March 11th, 2022 - -DOCKER_IMAGE="omega-zero-dev" - -docker run -itv ${PWD}:/home/oz/omega-zero "${DOCKER_IMAGE}" diff --git a/include/elf.hpp b/include/elf.hpp deleted file mode 100644 index 57f72e1..0000000 --- a/include/elf.hpp +++ /dev/null @@ -1,68 +0,0 @@ -#ifndef ELF_HEADER -#define ELF_HEADER - -#include - -// Structs -namespace elf { - - typedef struct _ElfHeader32 { - unsigned char e_magic[16]; - uint16_t e_type; - uint16_t e_machine; - uint32_t e_version; - uint32_t e_entry; - uint32_t e_phoff; - uint32_t e_shoff; - uint32_t e_flags; - uint16_t e_ehsize; - uint16_t e_phentsize; - uint16_t e_phnum; - uint16_t e_shentsize; - uint16_t e_shnum; - uint16_t e_shstrndx; - } ElfHeader32; - - typedef struct _ElfHeader64 { - unsigned char e_magic[16]; - uint16_t e_type; - uint16_t e_machine; - uint32_t e_version; - uint64_t e_entry; - uint64_t e_phoff; - uint64_t e_shoff; - uint32_t e_flags; - uint16_t e_ehsize; - uint16_t e_phentsize; - uint16_t e_phnum; - uint16_t e_shentsize; - uint16_t e_shnum; - uint16_t e_shstrndx; - } ElfHeader64; - -} // namespace elf - -// Functions -namespace elf { - - /** - * Perform scraping of 32 bit ELF binary. - * - * @param filename - * @return success - **/ - [[nodiscard]] - bool ProcessElf32(char*); - - /** - * Perform scraping of 64 bit ELF binary. - * - * @param filename - * @return success - **/ - [[nodiscard]] - bool ProcessElf64(char*); - -} // namespace elf - -#endif // ELF_HEADER diff --git a/include/filetypes.hpp b/include/filetypes.hpp deleted file mode 100644 index 0440842..0000000 --- a/include/filetypes.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef FILETYPES_HEADER -#define FILETYPES_HEADER - -#include -#include - -namespace filetypes { - - enum T : uint16_t { - unsupported, // 0 - pe_x86, // 1 - pe_x86_64, // 2 - elf_x86, // 3 - elf_x86_64 // 4 - }; - - /** - * Determine which executable format the file is compliant with. - * - * @param header - * @return - **/ - [[nodiscard]] uint16_t DetermineFiletype(std::ifstream&); - -} // namespace filetypes - -#endif // FILETYPES_HEADER diff --git a/include/parser.hpp b/include/parser.hpp deleted file mode 100644 index 4bfc41e..0000000 --- a/include/parser.hpp +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef PARSER_HEADER -#define PARSER_HEADER - -#include -#include - -typedef std::vector file_arr_t; - -namespace parser { - - class CommandLine; - -} // namespace parser - -class parser::CommandLine { -private: - const uint32_t operations; - const file_arr_t filenames; -public: - CommandLine() = delete; - CommandLine(const CommandLine& other) = delete; - CommandLine(int argc, char** argv); - ~CommandLine(); -public: - uint32_t Operations() const; - const file_arr_t Filenames() const; -}; - -#endif // PARSER_HEADER diff --git a/include/pe32.hpp b/include/pe32.hpp deleted file mode 100644 index 9577df1..0000000 --- a/include/pe32.hpp +++ /dev/null @@ -1,128 +0,0 @@ -#ifndef PE_32_HEADER -#define PE_32_HEADER - -#include - -// Structs -namespace pe32 { - - typedef struct _MsDosStub { - uint16_t mMagic; - unsigned char bits[126]; - } MsDosStub; - - typedef struct _Pe32Header { - uint32_t mMagic; // PE\0\0 or 0x00004550 - uint16_t mMachine; - uint16_t mNumberOfSections; - uint32_t mTimeDateStamp; - uint32_t mPointerToSymbolTable; - uint32_t mNumberOfSymbols; - uint16_t mSizeOfOptionalHeader; - uint16_t mCharacteristics; - } Pe32Header; - - typedef struct _Pe32OptionalHeader { - uint16_t mMagic; // 0x010b - PE32, 0x020b - PE32+ (64 bit) - uint8_t mMajorLinkerVersion; - uint8_t mMinorLinkerVersion; - uint32_t mSizeOfCode; - uint32_t mSizeOfInitializedData; - uint32_t mSizeOfUninitializedData; - uint32_t mAddressOfEntryPoint; - uint32_t mBaseOfCode; - uint32_t mBaseOfData; - uint32_t mImageBase; - uint32_t mSectionAlignment; - uint32_t mFileAlignment; - uint16_t mMajorOperatingSystemVersion; - uint16_t mMinorOperatingSystemVersion; - uint16_t mMajorImageVersion; - uint16_t mMinorImageVersion; - uint16_t mMajorSubsystemVersion; - uint16_t mMinorSubsystemVersion; - uint32_t mWin32VersionValue; - uint32_t mSizeOfImage; - uint32_t mSizeOfHeaders; - uint32_t mCheckSum; - uint16_t mSubsystem; - uint16_t mDllCharacteristics; - uint32_t mSizeOfStackReserve; - uint32_t mSizeOfStackCommit; - uint32_t mSizeOfHeapReserve; - uint32_t mSizeOfHeapCommit; - uint32_t mLoaderFlags; - uint32_t mNumberOfRvaAndSizes; - } Pe32OptionalHeader; - - typedef struct _Pe32PlusOptionalHeader { - uint16_t mMagic; // 0x010b - PE32, 0x020b - PE32+ (64 bit) - uint8_t mMajorLinkerVersion; - uint8_t mMinorLinkerVersion; - uint32_t mSizeOfCode; - uint32_t mSizeOfInitializedData; - uint32_t mSizeOfUninitializedData; - uint32_t mAddressOfEntryPoint; - uint32_t mBaseOfCode; - uint64_t mImageBase; - uint32_t mSectionAlignment; - uint32_t mFileAlignment; - uint16_t mMajorOperatingSystemVersion; - uint16_t mMinorOperatingSystemVersion; - uint16_t mMajorImageVersion; - uint16_t mMinorImageVersion; - uint16_t mMajorSubsystemVersion; - uint16_t mMinorSubsystemVersion; - uint32_t mWin32VersionValue; - uint32_t mSizeOfImage; - uint32_t mSizeOfHeaders; - uint32_t mCheckSum; - uint16_t mSubsystem; - uint16_t mDllCharacteristics; - uint64_t mSizeOfStackReserve; - uint64_t mSizeOfStackCommit; - uint64_t mSizeOfHeapReserve; - uint64_t mSizeOfHeapCommit; - uint32_t mLoaderFlags; - uint32_t mNumberOfRvaAndSizes; - } Pe32PlusOptionalHeader; - - typedef struct _Pe32SectionHeader { - char mName[8]; - uint32_t mVirtualSize; - uint32_t mVirtualAddress; - uint32_t mSizeOfRawData; - uint32_t mPointerToRawData; - uint32_t mPointerToRelocations; - uint32_t mPointerToLinenumbers; - uint16_t mNumberOfRelocations; - uint16_t mNumberOfLinenumbers; - uint32_t mCharacteristics; - } Pe32SectionHeader; - -} // namespace pe32 - -// Functions -namespace pe32 { - - /** - * Perform scraping of 32 bit PE32 binary. - * - * @param filename - * @return success - **/ - [[nodiscard]] - bool ProcessPe32(char*); - - /** - * Perform scraping of 64 bit PE32+ binary. - * - * @param filename - * @return success - **/ - [[nodiscard]] - bool ProcessPe64(char*); - -} // namespace pe32 - -#endif // PE_32_HEADER diff --git a/omega-zero/CMakeLists.txt b/omega-zero/CMakeLists.txt new file mode 100644 index 0000000..5fab165 --- /dev/null +++ b/omega-zero/CMakeLists.txt @@ -0,0 +1,59 @@ +add_executable( + ${PROJECT_NAME} + main.c + elf.c + filetypes.c + pe32.c + util.c ) + +set_target_properties( + ${PROJECT_NAME} + PROPERTIES + PREFIX vpr- +) + +add_compile_definitions( + VERSION_MAJOR=${PROJECT_VERSION_MAJOR} + VERSION_MINOR=${PROJECT_VERSION_MINOR} + VERSION_PATCH=${PROJECT_VERSION_PATCH} +) + +target_compile_options( + ${PROJECT_NAME} + PRIVATE $<$:/W4> + $<$:/O2> + $<$:/DNDEBUG> + $<$:-Ofast> + $<$:-Wall> + $<$:-Wextra> + $<$:-Werror> + $<$:-Wshadow> + $<$:-Wpedantic> + $<$:-Wconversion> + $<$:-ffunction-sections> + $<$:-ffast-math> + $<$:-funroll-loops> + $<$:-fPIE> + $<$:-Ofast> + $<$:-Wall> + $<$:-Wextra> + $<$:-Werror> + $<$:-Wshadow> + $<$:-Wpedantic> + $<$:-Wconversion> + $<$:-ffunction-sections> + $<$:-ffast-math> + $<$:-funroll-loops> + $<$:-fPIE> +) + +target_link_options( + ${PROJECT_NAME} + PRIVATE $<$:/MANIFEST:NO> + $<$:-s> + $<$:-s> +) + +install( + TARGETS ${PROJECT_NAME} + DESTINATION ${CMAKE_INSTALL_PREFIX}/bin ) diff --git a/omega-zero/elf.c b/omega-zero/elf.c new file mode 100644 index 0000000..f703019 --- /dev/null +++ b/omega-zero/elf.c @@ -0,0 +1,132 @@ +#include "elf.h" + +#include "filetypes.h" + +#include +#include + +typedef union { + ElfHeader32 header32; + ElfHeader64 header64; +} header_union; + +bool process_elf(const char* restrict filename, flags_ptr_t flags, enum filetype_t arch) +{ + assert((arch == elf_x86) || (arch == elf_x86_64)); + + if ( !(flags->zero_all || flags->zero_headers) ) + { + fprintf(stderr, "No processing for '%s' to be completed.\n", filename); + return 0; + } + + FILE* fp = 0; + header_union header = { 0 }; + size_t header_size = + ((arch == elf_x86) * sizeof(ElfHeader32)) + + ((arch == elf_x86_64) * sizeof(ElfHeader64)); + + // Open target file + if ( !(fp = fopen(filename, "rb+")) ) + { + fprintf(stderr, "Failed to open '%s' for reading.\n", filename); + return false; + } + + // Get header information + fseek(fp, 0, SEEK_SET); + size_t bytes_read = fread((unsigned char *)&header, header_size, 1, fp); + if (bytes_read != 1) + { + fprintf(stderr, "Failed to read bytes for elf header.\n"); + fclose(fp); + return false; + } + + if (arch == elf_x86) // 32 bit + { + // If file has a zeroed value, skip the file + if ((header.header32.e_shentsize * header.header32.e_shnum) == 0) { + fprintf(stderr, "'%s' has a invalid section header entry size and/or section header number.\n" + "Skipping '%s'.\n", filename, filename); + fclose(fp); + return false; + } + + // Calculate total size + size_t shsize = header.header32.e_shentsize * header.header32.e_shnum; + unsigned char* null_bytes = (unsigned char *)calloc(1, sizeof(unsigned char) * shsize); + if (!null_bytes) + { + fprintf(stderr, "Failed to allocate null-bytes.\n"); + fclose(fp); + return false; + } + + // Overwrite total bytes + fseek(fp, (long)header.header32.e_shoff, SEEK_SET); + if ( fwrite(null_bytes, (unsigned long)(shsize), 1, fp) != 1 ) + { + free(null_bytes); + fprintf(stderr, "Failed to overwrite section-header.\n"); + fclose(fp); + return false; + } + free(null_bytes); + + // Set offsets for e_shoff, e_shentsize, e_shnum, and e_shstrndx + header.header32.e_shoff = 0; + header.header32.e_shentsize = 0; + header.header32.e_shnum = 0; + header.header32.e_shstrndx = 0; + } + else // 64 bit + { + // If file has a zeroed value, skip the file + if ((header.header64.e_shentsize * header.header64.e_shnum) == 0) { + fprintf(stderr, "'%s' has a invalid section header entry size and/or section header number.\n" + "Skipping '%s'.\n", filename, filename); + fclose(fp); + return false; + } + + // Calculate total size + size_t shsize = header.header64.e_shentsize * header.header64.e_shnum; + unsigned char* null_bytes = (unsigned char *)calloc(1, sizeof(unsigned char) * shsize); + if (!null_bytes) + { + fprintf(stderr, "Failed to allocate null-bytes.\n"); + fclose(fp); + return false; + } + + // Overwrite total bytes + fseek(fp, (long)header.header64.e_shoff, SEEK_SET); + if ( fwrite(null_bytes, (unsigned long)(shsize), 1, fp) != 1 ) + { + free(null_bytes); + fprintf(stderr, "Failed to overwrite section-header.\n"); + fclose(fp); + return false; + } + free(null_bytes); + + // Set offsets for e_shoff, e_shentsize, e_shnum, and e_shstrndx + header.header64.e_shoff = 0; + header.header64.e_shentsize = 0; + header.header64.e_shnum = 0; + header.header64.e_shstrndx = 0; + } + + // Write the bytes out + fseek(fp, 0, SEEK_SET); + if ( fwrite((char *)&header, header_size, 1, fp) != 1 ) + { + fprintf(stderr, "Failed to overwrite header.\n"); + fclose(fp); + return false; + } + + fclose(fp); + return true; +} diff --git a/omega-zero/elf.h b/omega-zero/elf.h new file mode 100644 index 0000000..328ccd6 --- /dev/null +++ b/omega-zero/elf.h @@ -0,0 +1,62 @@ +#ifndef ELF_HEADER +#define ELF_HEADER + +#include +#include + +#include "filetypes.h" +#include "flags.h" + +// +// Structs +// + +typedef struct _ElfHeader32 { + uint8_t e_magic[16]; + uint16_t e_type; + uint16_t e_machine; + uint32_t e_version; + uint32_t e_entry; + uint32_t e_phoff; + uint32_t e_shoff; + uint32_t e_flags; + uint16_t e_ehsize; + uint16_t e_phentsize; + uint16_t e_phnum; + uint16_t e_shentsize; + uint16_t e_shnum; + uint16_t e_shstrndx; +} ElfHeader32; + +typedef struct _ElfHeader64 { + uint8_t e_magic[16]; + uint16_t e_type; + uint16_t e_machine; + uint32_t e_version; + uint64_t e_entry; + uint64_t e_phoff; + uint64_t e_shoff; + uint32_t e_flags; + uint16_t e_ehsize; + uint16_t e_phentsize; + uint16_t e_phnum; + uint16_t e_shentsize; + uint16_t e_shnum; + uint16_t e_shstrndx; +} ElfHeader64; + +// +// Functions +// + +/** + * Perform processing of a 32/64 bit ELF binary. + * + * @param filename + * @param flags + * @param arch + * @return success +**/ +bool process_elf(const char* restrict filename, flags_ptr_t flags, enum filetype_t arch); + +#endif // ELF_HEADER diff --git a/omega-zero/filetypes.c b/omega-zero/filetypes.c new file mode 100644 index 0000000..71721e8 --- /dev/null +++ b/omega-zero/filetypes.c @@ -0,0 +1,72 @@ +#include "filetypes.h" +#include "pe32.h" + +static +uint16_t determine_pe32_architecture(FILE* fp) +{ + char header[sizeof(MsDosStub) + sizeof(Pe32Header) + sizeof(Pe32OptionalHeader)] = { 0 }; + + fseek(fp, 0, SEEK_SET); + if ( fread(header, sizeof(header), 1, fp) != 1 ) + { + return unsupported; + } + + if (header[0] != 'M' || header[1] != 'Z') + { + return unsupported; + } + + Pe32OptionalHeader* optional_header = + (Pe32OptionalHeader *)(header + sizeof(MsDosStub) + sizeof(Pe32Header)); + switch (optional_header->mMagic >> 9) + { + case 0: { return pe_x86; } + case 1: { return pe_x86_64; } + default: { break; } + } + + return unsupported; + +} + +static +enum filetype_t determine_elf_architecture(FILE* fp) +{ + char header[8] = {0}; + + fseek(fp, 0, SEEK_SET); + if ( fread(header, sizeof(header), 1, fp) != 1 ) + { + return unsupported; + } + + if (header[0] != 0x7F || header[1] != 'E' || header[2] != 'L' || header[3] != 'F') { + return unsupported; + } + + switch (header[4]) + { + case 1: { return elf_x86; } + case 2: { return elf_x86_64; } + default: { break; } + } + + return unsupported; + +} + +enum filetype_t determine_filetype(const char * restrict filename) { + + FILE* fp = 0; + if ( !(fp = fopen(filename, "rb")) ) + { + return unsupported; + } + + uint32_t architecture = 0; + architecture = determine_pe32_architecture(fp) + determine_elf_architecture(fp); + fclose(fp); + + return architecture; +} diff --git a/omega-zero/filetypes.h b/omega-zero/filetypes.h new file mode 100644 index 0000000..f7b0e2d --- /dev/null +++ b/omega-zero/filetypes.h @@ -0,0 +1,23 @@ +#ifndef FILETYPES_HEADER +#define FILETYPES_HEADER + +#include +#include + +enum filetype_t { + unsupported = 0, // 0 + pe_x86, // 1 + pe_x86_64, // 2 + elf_x86, // 3 + elf_x86_64 // 4 +}; + +/** + * Determine which executable format the file is compliant with. + * + * @param header + * @return +**/ +enum filetype_t determine_filetype(const char * restrict); + +#endif // FILETYPES_HEADER diff --git a/omega-zero/flags.h b/omega-zero/flags.h new file mode 100644 index 0000000..c225562 --- /dev/null +++ b/omega-zero/flags.h @@ -0,0 +1,13 @@ +#ifndef FLAGS_HEADER +#define FLAGS_HEADER + +#include + +typedef struct _flags { + bool zero_all:1; + bool zero_headers:1; + bool zero_section_headers:1; + bool zero_optional_headers:1; +} flags_t, *flags_ptr_t; + +#endif // FLAGS_HEADER diff --git a/omega-zero/main.c b/omega-zero/main.c new file mode 100644 index 0000000..25661b9 --- /dev/null +++ b/omega-zero/main.c @@ -0,0 +1,156 @@ +/** + * Project: vpr-omega-zero + * + * Created by: VPR + * Created: March 9th, 2022 + * + * Updated by: March 9th, 2022 + * Updated: March 15th, 2025 + * + * Description: Inspired by yellobytes's 'zeroSection2.py' + * https://github.com/yellowbyte/reverse-engineering-playground/tree/master/file_format_hacks + * + * Omega Zero aims to provide a tool for the stripping of the + * section-header information of x86 and x86_64 ELF and PE32 binaries. + * + * License: MIT +**/ + +#include "filetypes.h" +#include "util.h" +#include "pe32.h" +#include "elf.h" + +#include +#include + +static const char* filenames[4096]; +static size_t n_filenames; +static flags_t flags = { .zero_all = 1 }; + +int main(int argc, char** argv) +{ + if (argc < 2) + { + __usage_error(argv[0], "insufficient arguments"); + } + + for (int i = 1; i < argc; ++i) + { + if (argv[i][0] == '-' && argv[i][1]) + { + for (int j = 1; argv[i][j]; ++j) + { + switch (argv[i][j]) + { + case 'H': flags.zero_headers = 1; break; + case 'o': flags.zero_optional_headers = 1; break; + case 's': flags.zero_section_headers = 1; break; + case 'a': flags.zero_all = 1; break; + case 'h': __usage_error(argv[0], "display help"); break; + case '-': + { + if (strncmp((argv[i]+j), "-help", sizeof("-help")) == 0) + { + __usage_error(argv[0], "display help"); + } + else if (strncmp((argv[i]+j), "-headers", sizeof("-headers")) == 0) + { + flags.zero_headers = 1; + } + else if (strncmp((argv[i]+j), "-optional-headers", sizeof("-optional-headers")) == 0) + { + flags.zero_headers = 1; + } + else if (strncmp((argv[i]+j), "-section-headers", sizeof("-section-headers")) == 0) + { + flags.zero_headers = 1; + } + else if (strncmp((argv[i]+j), "-all", sizeof("-all")) == 0) + { + flags.zero_headers = 1; + } + break; + } + default: fprintf(stderr, "unknown option: %c\n", argv[i][j]); break; + } + } + } + else + { + filenames[n_filenames] = argv[i]; + ++n_filenames; + } + } + + // Default to zero_all if none are set + if ( !(flags.zero_headers | flags.zero_section_headers | flags.zero_optional_headers) ) + { + flags.zero_all = 1; + } + + if (!n_filenames) + { + __usage_error(argv[0], "no files supplied"); + } + + for (size_t i = 0; i < n_filenames; ++i) + { + const char* const filename = filenames[i]; + fprintf(stderr, "Processing '%s'...\n", filename); + + FILE* fp = 0; + if ( !(fp = fopen(filename, "rb")) ) + { + fprintf(stderr, "Failed to open '%s'.\n", filename); + fprintf(stdout, "Skipping '%s'...\n", filename); + continue; + } + fclose(fp); + + bool bSuccess = false; + enum filetype_t filetype = determine_filetype(filename); + switch (filetype) + { + case unsupported: + { + fprintf(stderr, "Filetype not supported.\n"); + fprintf(stdout, "Skipping '%s'...\n", filename); + continue; + } + case pe_x86: + { + fputs("PE32 detected\n", stdout); + bSuccess = process_pe32(filename, &flags, pe_x86); + break; + } + case pe_x86_64: + { + fputs("PE32+(x86_64) detected\n", stdout); + bSuccess = process_pe32(filename, &flags, pe_x86_64); + break; + } + case elf_x86: + { + fputs("ELF x86 detected\n", stdout); + bSuccess = process_elf(filename, &flags, elf_x86); + break; + } + case elf_x86_64: + { + fputs("ELF x86_64 detected\n", stdout); + bSuccess = process_elf(filename, &flags, elf_x86_64); + break; + } + } + + if (bSuccess) { + fprintf(stdout, "'%s' was successfully processed.\n", filename); + } else { + fprintf(stdout, "Failed to process '%s'.\n", filename); + } + + } + + return 0; +} diff --git a/omega-zero/pe32.c b/omega-zero/pe32.c new file mode 100644 index 0000000..95be2ca --- /dev/null +++ b/omega-zero/pe32.c @@ -0,0 +1,211 @@ +#include "pe32.h" + +#include "filetypes.h" + +#include +#include +#include + +typedef union { + Pe32OptionalHeader header32; + Pe32PlusOptionalHeader header64; +} pe32_union_t; + +bool process_pe32( const char* restrict filename, + const flags_ptr_t flags, + enum filetype_t arch ) +{ + assert((arch == pe_x86) || (arch == pe_x86_64)); + + if ( !( flags->zero_all || + flags->zero_headers || + flags->zero_section_headers || + flags->zero_optional_headers ) ) + { + fprintf(stderr, "No processing for '%s' to be completed.\n", filename); + return 0; + } + + Pe32Header header = { 0 }; + pe32_union_t optional_header_u; + size_t optional_header_size = + ((arch == pe_x86)*sizeof(Pe32OptionalHeader)) + // 32 bit + ((arch == pe_x86_64)*sizeof(Pe32PlusOptionalHeader)); // 64 bit + + FILE* fp = 0; + if ( !(fp = fopen(filename, "rb+")) ) + { + fprintf(stderr, "Failed to open '%s' for reading.\n", filename); + return false; + } + + bool zero_headers = flags->zero_all || flags->zero_headers; + if (zero_headers) + { + // Get PE32 header + fseek(fp, sizeof(MsDosStub), SEEK_SET); + if ( ( fread((char *)&header, sizeof(header), 1, fp)) != 1) + { + fprintf(stderr, "Failed to read header of '%s'.\n", filename); + fclose(fp); + return false; + } + + // + // Clear header + // + + //header.mMagic = 0; // NOPE + //header.mMachine = 0; // NOPE + header.mTimeDateStamp = 0; // OK + //header.mNumberOfSymbols = 0; // NOPE + //header.mCharacteristics = 0; // NOPE + //header.mNumberOfSections = 0; // MAYBE - if mNumberOfSections is saved before clearing + //header.mSizeOfOptionalHeader = 0; // NOPE + header.mPointerToSymbolTable = 0; // OK + + // Set PE32 header + fseek(fp, sizeof(MsDosStub), SEEK_SET); + if ( fwrite((char *)&header, sizeof(header), 1, fp) != 1 ) + { + fprintf(stderr, "Failed to write header of '%s'.\n", filename); + fclose(fp); + return false; + } + } + + bool zero_optional_headers = flags->zero_all || flags->zero_optional_headers; + if (zero_optional_headers) + { + // Get optional header + fseek(fp, sizeof(MsDosStub) + sizeof(Pe32Header), SEEK_SET); + if ( fread((char *)&optional_header_u, optional_header_size, 1, fp) != 1) + { + fprintf(stderr, "Failed to read optional header of '%s'.\n", filename); + fclose(fp); + return false; + } + + // Clear Optional Header + if (arch == pe_x86) // 32 bit + { + //optional_header_u.header32.mMagic = 0; // NOPE + optional_header_u.header32.mMajorLinkerVersion = 0; // OK + optional_header_u.header32.mMinorLinkerVersion = 0; // OK + optional_header_u.header32.mSizeOfCode = 0; // OK + optional_header_u.header32.mSizeOfInitializedData = 0; // OK + optional_header_u.header32.mSizeOfUninitializedData = 0; // OK + //optional_header_u.header32.mAddressOfEntryPoint = 0; // NOPE + optional_header_u.header32.mBaseOfCode = 0; // OK + optional_header_u.header32.mBaseOfData = 0; // OK + //optional_header_u.header32.mImageBase = 0; // FUCK NO + //optional_header_u.header32.mSectionAlignment = 0; // NOPE + //optional_header_u.header32.mFileAlignment = 0; // NO + optional_header_u.header32.mMajorOperatingSystemVersion = 0; // OK + optional_header_u.header32.mMinorOperatingSystemVersion = 0; // OK + optional_header_u.header32.mMajorImageVersion = 0; // OK + optional_header_u.header32.mMinorImageVersion = 0; // OK + //optional_header_u.header32.mMajorSubsystemVersion = 0; // needs specific value + optional_header_u.header32.mMinorSubsystemVersion = 0; // OK + //optional_header_u.header32.mWin32VersionValue = 0; // OK but probably not + //optional_header_u.header32.mSizeOfImage = 0; // NOPE + //optional_header_u.header32.mSizeOfHeaders = 0; // NOPE + optional_header_u.header32.mCheckSum = 0; // OK + //optional_header_u.header32.mSubsystem = 0; // nah + //optional_header_u.header32.mDllCharacteristics = 0; // hmmmm... maybe but probably not + optional_header_u.header32.mSizeOfStackReserve = 0; // OK + optional_header_u.header32.mSizeOfStackCommit = 0; // OK + optional_header_u.header32.mSizeOfHeapReserve = 0; // OK + optional_header_u.header32.mSizeOfHeapCommit = 0; // OK + optional_header_u.header32.mLoaderFlags = 0; // OK but probably not + //optional_header_u.header32.mNumberOfRvaAndSizes = 0; // Absolutely the fuck not + } + else // 64 bit + { + //optional_header_u.header32.mMagic = 0; // NOPE + optional_header_u.header64.mMajorLinkerVersion = 0; // OK + optional_header_u.header64.mMinorLinkerVersion = 0; // OK + optional_header_u.header64.mSizeOfCode = 0; // OK + optional_header_u.header64.mSizeOfInitializedData = 0; // OK + optional_header_u.header64.mSizeOfUninitializedData = 0; // OK + //optional_header_u.header64.mAddressOfEntryPoint = 0; // NOPE + optional_header_u.header64.mBaseOfCode = 0; // OK + //optional_header_u.header64.mImageBase = 0; // FUCK NO + //optional_header_u.header64.mSectionAlignment = 0; // NOPE + //optional_header_u.header64.mFileAlignment = 0; // NO + optional_header_u.header64.mMajorOperatingSystemVersion = 0; // OK + optional_header_u.header64.mMinorOperatingSystemVersion = 0; // OK + optional_header_u.header64.mMajorImageVersion = 0; // OK + optional_header_u.header64.mMinorImageVersion = 0; // OK + //optional_header_u.header64.mMajorSubsystemVersion = 0; // needs specific value + optional_header_u.header64.mMinorSubsystemVersion = 0; // OK + //optional_header_u.header64.mWin32VersionValue = 0; // OK but probably not + //optional_header_u.header64.mSizeOfImage = 0; // NOPE + //optional_header_u.header64.mSizeOfHeaders = 0; // NOPE + optional_header_u.header64.mCheckSum = 0; // OK + //optional_header_u.header64.mSubsystem = 0; // nah + //optional_header_u.header64.mDllCharacteristics = 0; // hmmmm... maybe but probably not + optional_header_u.header64.mSizeOfStackReserve = 0; // OK + optional_header_u.header64.mSizeOfStackCommit = 0; // OK + optional_header_u.header64.mSizeOfHeapReserve = 0; // OK + optional_header_u.header64.mSizeOfHeapCommit = 0; // OK + optional_header_u.header64.mLoaderFlags = 0; // OK but probably not + //optional_header_u.header32.mNumberOfRvaAndSizes = 0; // Absolutely the fuck not + } + + // Set optional header + fseek(fp, sizeof(MsDosStub) + sizeof(Pe32Header), SEEK_SET); + if ( fwrite((char *)&optional_header_u, optional_header_size, 1, fp) != 1 ) + { + fprintf(stderr, "Failed to write header of '%s'.\n", filename); + fclose(fp); + return false; + } + } + + // + // Zero out each section header + // + + bool zero_section_headers = flags->zero_all || flags->zero_section_headers; + if (zero_section_headers) + { + for (unsigned i = 0; i < header.mNumberOfSections; i++) { + Pe32SectionHeader section_header = { 0 }; + // Get section header + long offset = (long)(sizeof(MsDosStub) + sizeof(Pe32Header) + + header.mSizeOfOptionalHeader + i * sizeof(Pe32SectionHeader)); + fseek(fp, offset, SEEK_SET); + if ( fread((char *)§ion_header, sizeof(section_header), 1, fp) != 1 ) + { + fprintf(stderr, "Failed to read section header of '%s'.\n", filename); + fclose(fp); + return false; + } + + // Clear entries of section header + memset(section_header.mName, 0, 8); // yes....? + //section_header.mVirtualSize = 0; // NOPE + //section_header.mVirtualAddress = 0; // NOPE + //section_header.mSizeOfRawData = 0; // NOPE + //section_header.mPointerToRawData = 0; // NOPE + //section_header.mPointerToRelocations = 0; // maybe + //section_header.mPointerToLinenumbers = 0; // maybe + //section_header.mNumberOfRelocations = 0; // maybe + //section_header.mNumberOfLinenumbers = 0; // maybe + //section_header.mCharacteristics = 0; // NOPE + + // Set section header + fseek(fp, offset, SEEK_SET); + if ( fwrite((char *)§ion_header, sizeof(section_header), 1, fp) != 1) + { + fprintf(stderr, "Failed to write section header: '%s' of '%s'.\n", section_header.mName, filename); + fclose(fp); + return false; + } + } + } + + fclose(fp); + return true; +} diff --git a/omega-zero/pe32.h b/omega-zero/pe32.h new file mode 100644 index 0000000..9b5f319 --- /dev/null +++ b/omega-zero/pe32.h @@ -0,0 +1,113 @@ +#ifndef PE_32_HEADER +#define PE_32_HEADER + +#include +#include + +#include "filetypes.h" +#include "flags.h" + +// Structs +typedef struct _MsDosStub { + uint16_t mMagic; + uint8_t bits[126]; +} MsDosStub; + +typedef struct _Pe32Header { + uint32_t mMagic; // PE\0\0 or 0x00004550 + uint16_t mMachine; + uint16_t mNumberOfSections; + uint32_t mTimeDateStamp; + uint32_t mPointerToSymbolTable; + uint32_t mNumberOfSymbols; + uint16_t mSizeOfOptionalHeader; + uint16_t mCharacteristics; +} Pe32Header; + +typedef struct _Pe32OptionalHeader { + uint16_t mMagic; // 0x010b - PE32, 0x020b - PE32+ (64 bit) + uint8_t mMajorLinkerVersion; + uint8_t mMinorLinkerVersion; + uint32_t mSizeOfCode; + uint32_t mSizeOfInitializedData; + uint32_t mSizeOfUninitializedData; + uint32_t mAddressOfEntryPoint; + uint32_t mBaseOfCode; + uint32_t mBaseOfData; + uint32_t mImageBase; + uint32_t mSectionAlignment; + uint32_t mFileAlignment; + uint16_t mMajorOperatingSystemVersion; + uint16_t mMinorOperatingSystemVersion; + uint16_t mMajorImageVersion; + uint16_t mMinorImageVersion; + uint16_t mMajorSubsystemVersion; + uint16_t mMinorSubsystemVersion; + uint32_t mWin32VersionValue; + uint32_t mSizeOfImage; + uint32_t mSizeOfHeaders; + uint32_t mCheckSum; + uint16_t mSubsystem; + uint16_t mDllCharacteristics; + uint32_t mSizeOfStackReserve; + uint32_t mSizeOfStackCommit; + uint32_t mSizeOfHeapReserve; + uint32_t mSizeOfHeapCommit; + uint32_t mLoaderFlags; + uint32_t mNumberOfRvaAndSizes; +} Pe32OptionalHeader; + +typedef struct _Pe32PlusOptionalHeader { + uint16_t mMagic; // 0x010b - PE32, 0x020b - PE32+ (64 bit) + uint8_t mMajorLinkerVersion; + uint8_t mMinorLinkerVersion; + uint32_t mSizeOfCode; + uint32_t mSizeOfInitializedData; + uint32_t mSizeOfUninitializedData; + uint32_t mAddressOfEntryPoint; + uint32_t mBaseOfCode; + uint64_t mImageBase; + uint32_t mSectionAlignment; + uint32_t mFileAlignment; + uint16_t mMajorOperatingSystemVersion; + uint16_t mMinorOperatingSystemVersion; + uint16_t mMajorImageVersion; + uint16_t mMinorImageVersion; + uint16_t mMajorSubsystemVersion; + uint16_t mMinorSubsystemVersion; + uint32_t mWin32VersionValue; + uint32_t mSizeOfImage; + uint32_t mSizeOfHeaders; + uint32_t mCheckSum; + uint16_t mSubsystem; + uint16_t mDllCharacteristics; + uint64_t mSizeOfStackReserve; + uint64_t mSizeOfStackCommit; + uint64_t mSizeOfHeapReserve; + uint64_t mSizeOfHeapCommit; + uint32_t mLoaderFlags; + uint32_t mNumberOfRvaAndSizes; +} Pe32PlusOptionalHeader; + +typedef struct _Pe32SectionHeader { + int8_t mName[8]; + uint32_t mVirtualSize; + uint32_t mVirtualAddress; + uint32_t mSizeOfRawData; + uint32_t mPointerToRawData; + uint32_t mPointerToRelocations; + uint32_t mPointerToLinenumbers; + uint16_t mNumberOfRelocations; + uint16_t mNumberOfLinenumbers; + uint32_t mCharacteristics; +} Pe32SectionHeader; + +/** + * Perform processesing of a 32/64 bit PE32 binary. + * + * @param filename + * @return success +**/ +bool process_pe32(const char* restrict filename, const flags_ptr_t flags, enum filetype_t arch); + +#endif // PE_32_HEADER diff --git a/omega-zero/util.c b/omega-zero/util.c new file mode 100644 index 0000000..de92ba4 --- /dev/null +++ b/omega-zero/util.c @@ -0,0 +1,47 @@ +#include "util.h" + +#include "version.h" + +#include +#include + +void __usage_error(const char* restrict argv_0, const char* restrict error_message) +{ + fprintf(stderr, + "Error message: %s.\n" + "\n" + "Usage:\n" + " %s [] \n" + "\n" + "Optional arguments:\n" + " -a, Enable all flags. (default option)\n" + " --all\n" + " -o, Zero all optional headers.\n" + " --optional-headers\n" + " -s, Zero all section headers.\n" + " --section-headers\n" + " -H Zero all headers.\n" + " -headers\n" + " -h, Display help.\n" + " --help\n" + "\n" + "Examples:\n" + " %s path/to/executable\n" + " %s -sH path/to/executable\n" + "\n" + "Version:\n" + " %d.%d.%d\n" + "\n" + "Author:\n" + " VPR\n", + error_message, + argv_0, + argv_0, + argv_0, + VERSION_MAJOR, + VERSION_MINOR, + VERSION_PATCH + ); + + exit(1); +} diff --git a/include/util.hpp b/omega-zero/util.h similarity index 50% rename from include/util.hpp rename to omega-zero/util.h index f015865..c75631c 100644 --- a/include/util.hpp +++ b/omega-zero/util.h @@ -1,13 +1,9 @@ #ifndef UTIL_HEADER #define UTIL_HEADER -#include - /** * Usage error - * **/ -[[noreturn]] -void __usage_error(char* argv, int error_code); +void __usage_error(const char* restrict argv, const char* restrict error_message); #endif // UTIL_HEADER diff --git a/omega-zero/version.h b/omega-zero/version.h new file mode 100644 index 0000000..76fbda3 --- /dev/null +++ b/omega-zero/version.h @@ -0,0 +1,16 @@ +#ifndef VERSION_HEADER +#define VERSION_HEADER + +#ifndef VERSION_MAJOR +#define VERSION_MAJOR 1 +#endif // VERSION_MAJOR + +#ifndef VERSION_MINOR +#define VERSION_MINOR 0 +#endif // VERSION_MINOR + +#ifndef VERSION_PATCH +#define VERSION_PATCH 0 +#endif // VERSION_PATCH + +#endif // VERSION_HEADER diff --git a/src/elf.cpp b/src/elf.cpp deleted file mode 100644 index 99443f8..0000000 --- a/src/elf.cpp +++ /dev/null @@ -1,140 +0,0 @@ -#include "elf.hpp" - -#include "filetypes.hpp" - -#include -#include -#include - -using elf::ElfHeader32; -using elf::ElfHeader64; - -[[nodiscard]] -bool elf::ProcessElf32(char* filename) { - - std::fstream fs; - ElfHeader32 header; - - // Open target file - fs.open(filename, std::ios::binary | std::ios::in | std::ios::out); - if (!fs.is_open()) { - std::cerr << "Failed to open '" << filename << "' for reading." << std::endl; - return false; - } - - // Get header information - fs.seekg(0, std::ios::beg); - fs.read((char *)&header, sizeof(header)); - if (fs.fail()) { - std::cerr << "Failed to read bytes for elf header." << std::endl; - fs.close(); - return false; - } - - // If file has a zeroed value, skip the file - if ((header.e_shentsize * header.e_shnum) == 0) { - std::cerr << "'" << filename << "' has a invalid section header entry size and/or section header number.\n" - << "Skipping '" << filename << "'.\n"; - fs.close(); - return false; - } - - // Calculate total size - size_t shsize = header.e_shentsize * header.e_shnum; - auto null_bytes = new char[shsize]; - memset(null_bytes, 0, shsize); - - // Overwrite total bytes - fs.seekg(header.e_shoff, std::ios::beg); - fs.write(null_bytes, static_cast(shsize)); - if (fs.fail()) { - delete[] null_bytes; - std::cerr << "Failed to overwrite section-header." << std::endl; - fs.close(); - return false; - } - delete[] null_bytes; - - // Set offsets for e_shoff, e_shentsize, e_shnum, and e_shstrndx - header.e_shoff = 0; - header.e_shentsize = 0; - header.e_shnum = 0; - header.e_shstrndx = 0; - - // Write the bytes out - fs.seekg(0, std::ios::beg); - fs.write((char *)&header, sizeof(header)); - if (fs.fail()) { - std::cerr << "Failed to overwrite header." << std::endl; - fs.close(); - return false; - } - - fs.close(); - return true; -} - -[[nodiscard]] -bool elf::ProcessElf64(char* filename) { - - std::fstream fs; - ElfHeader64 header; - - // Open target file - fs.open(filename, std::ios::binary | std::ios::in | std::ios::out); - if (!fs.is_open()) { - std::cerr << "Failed to open '" << filename << "' for reading." << std::endl; - return false; - } - - // Get header information - fs.seekg(0, std::ios::beg); - fs.read((char *)&header, sizeof(header)); - if (fs.fail()) { - std::cerr << "Failed to read bytes for elf header." << std::endl; - fs.close(); - return false; - } - - // If file has a zeroed value, skip the file - if ((header.e_shentsize * header.e_shnum) == 0) { - std::cerr << "'" << filename << "' has a invalid section header entry size and/or section header number.\n" - << "Skipping '" << filename << "'.\n"; - fs.close(); - return false; - } - - // Calculate total size - size_t shsize = header.e_shentsize * header.e_shnum; - auto null_bytes = new char[shsize]; - memset(null_bytes, 0, shsize); - - // Overwrite total bytes - fs.seekg(static_cast(header.e_shoff), std::ios::beg); - fs.write(null_bytes, static_cast(shsize)); - if (fs.fail()) { - delete[] null_bytes; - std::cerr << "Failed to overwrite section-header." << std::endl; - fs.close(); - return false; - } - delete[] null_bytes; - - // Set offsets for e_shoff, e_shentsize, e_shnum, and e_shstrndx - header.e_shoff = 0; - header.e_shentsize = 0; - header.e_shnum = 0; - header.e_shstrndx = 0; - - // Write the bytes out - fs.seekg(0, std::ios::beg); - fs.write((char *)&header, sizeof(header)); - if (fs.fail()) { - std::cerr << "Failed to overwrite header." << std::endl; - fs.close(); - return false; - } - - fs.close(); - return true; -} diff --git a/src/filetypes.cpp b/src/filetypes.cpp deleted file mode 100644 index 9c05009..0000000 --- a/src/filetypes.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "filetypes.hpp" -#include "pe32.hpp" - -#include - -[[nodiscard]] -static uint16_t DeterminePe32Architecture(std::ifstream& ifs) { - - using pe32::Pe32OptionalHeader; - using pe32::Pe32Header; - using pe32::MsDosStub; - - const size_t size = sizeof(MsDosStub) + - sizeof(Pe32Header) + sizeof(Pe32OptionalHeader); - char header[size]{0}; - - ifs.seekg(0, std::ios::beg); - ifs.read(header, sizeof(header)); - - if (header[0] != 'M' || header[1] != 'Z') { - return filetypes::unsupported; - } - - auto optional_header = (pe32::Pe32OptionalHeader *)(header + - sizeof(MsDosStub) + sizeof(Pe32Header)); - switch (optional_header->mMagic >> 9) { - case 0: { return filetypes::pe_x86; } - case 1: { return filetypes::pe_x86_64; } - default: { break; } - } - - return filetypes::unsupported; - -} - -[[nodiscard]] -static uint16_t DetermineElfArchitecture(std::ifstream& ifs) { - - char header[8]{0}; - ifs.seekg(0, std::ios::beg); - ifs.read(header, sizeof(header)); - - if (header[0] != 0x7F || header[1] != 'E' || header[2] != 'L' || header[3] != 'F') { - return filetypes::unsupported; - } - - switch (header[4]) { - case 1: { return filetypes::elf_x86; } - case 2: { return filetypes::elf_x86_64; } - default: { break; } - } - - return filetypes::unsupported; - -} - -[[nodiscard]] -uint16_t filetypes::DetermineFiletype(std::ifstream& ifs) { - - uint16_t architecture = 0; - - if (ifs.good()) { - architecture = static_cast(DeterminePe32Architecture(ifs) + DetermineElfArchitecture(ifs)); - } - - ifs.close(); - return architecture; -} diff --git a/src/main.cpp b/src/main.cpp deleted file mode 100644 index 05e4c6c..0000000 --- a/src/main.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/** - * Project: vpr-omega-zero - * - * Creator: VPR - * Created: March 9th, 2022 - * Updated: March 11th, 2022 - * - * Description: - * Inspired by yellobytes's 'zeroSection2.py' - * https://github.com/yellowbyte/reverse-engineering-playground/tree/master/file_format_hacks - * - * Omega Zero aims to provide a tool for the stripping of the - * section-header information of x86 and x86_64 ELF and PE32 binaries. -**/ - -#include "filetypes.hpp" // namespace filetypes -#include "parser.hpp" // namespace parser -#include "util.hpp" // __usage_error -#include "pe32.hpp" // namespace pe32 -#include "elf.hpp" // namespace elf - -#include -#include -#include - -#define ERR_NO_ARGS (int)0xFFFFFFFF - -int main(int argc, char** argv) { - - if (argc < 2) { - __usage_error(argv[0], ERR_NO_ARGS); - } - - auto cl = parser::CommandLine(argc, argv); - for (const auto& filename : cl.Filenames()) { - - std::cout << "Processing '" << filename << "'..." << std::endl; - - if (!std::filesystem::exists(filename)) { - std::cerr << "'" << filename << "' does not exist." << std::endl; - std::cout << "Skipping '" << filename << "'...\n" << std::endl; - continue; - } else if (!std::filesystem::is_regular_file(filename) || std::filesystem::is_directory(filename)) { - std::cerr << "'" << filename << "' is not a regular file." << std::endl; - std::cout << "Skipping '" << filename << "'...\n" << std::endl; - continue; - } - - std::ifstream ifs(filename); - if (!ifs.is_open()) { - std::cerr << "Failed to open '" << filename << "'.\n" << std::endl; - std::cout << "Skipping '" << filename << "'...\n" << std::endl; - continue; - } - - bool bSuccess = false; - auto raw_filename = const_cast(filename.c_str()); - auto filetype = filetypes::DetermineFiletype(ifs); - switch (filetype) - { - case filetypes::unsupported: - { - std::cerr << "Filetype not supported." << " " << filetype << std::endl; - std::cout << "Skipping '" << filename << "'...\n" << std::endl; - continue; - } - case filetypes::pe_x86: - { - std::cout << "PE32 detected\n"; - bSuccess = pe32::ProcessPe32(raw_filename); - break; - } - case filetypes::pe_x86_64: - { - std::cout << "PE32+(x86_64) detected\n"; - bSuccess = pe32::ProcessPe64(raw_filename); - break; - } - case filetypes::elf_x86: - { - std::cout << "ELF x86 detected\n"; - bSuccess = elf::ProcessElf32(raw_filename); - break; - } - case filetypes::elf_x86_64: - { - std::cout << "ELF x86_64 detected\n"; - bSuccess = elf::ProcessElf64(raw_filename); - break; - } - } - - if (bSuccess) { - std::cout << "'" << filename << "' successfully processed.\n" << std::endl; - } else { - std::cout << "failed to process'" << filename << "'.\n" << std::endl; - } - - } - - return 0; - -} diff --git a/src/parser.cpp b/src/parser.cpp deleted file mode 100644 index 02904b4..0000000 --- a/src/parser.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include "parser.hpp" - -static -file_arr_t SetFilenames(int argc, char** argv) { - - if (argc < 2) { - return { }; - } - - std::string program_name(argv[0]); - - std::vector arguments; - for (int i = 1; i < argc; i++) { - std::string argument(argv[i]); - - if (argument == program_name) { - continue; - } else if (argument[0] == '-') { - continue; - } - - arguments.push_back(argument); - } - - return arguments; - -} - -static -uint32_t SetOperations(int argc, char** argv) { - (void)argc; - (void)argv; - return 0; -} - -parser::CommandLine::CommandLine(int argc, char** argv) - : operations(SetOperations(argc, argv)) - , filenames(SetFilenames(argc, argv)) -{ -} - -parser::CommandLine::~CommandLine() -{ -} - -uint32_t parser::CommandLine::Operations() const { return operations; } -const std::vector parser::CommandLine::Filenames() const { return filenames; } - -//parser::CommandLine::GetOperations(int argc, char** argv); diff --git a/src/pe32.cpp b/src/pe32.cpp deleted file mode 100644 index eecedbf..0000000 --- a/src/pe32.cpp +++ /dev/null @@ -1,268 +0,0 @@ -#include "pe32.hpp" - -#include -#include -#include - -[[nodiscard]] -bool pe32::ProcessPe32(char* filename) { - - Pe32Header header; - Pe32OptionalHeader optional_header; - - // Open target file - std::fstream fs(filename, std::ios::binary | std::ios::in | std::ios::out); - if (!fs.is_open()) { - std::cerr << "Failed to open '" << filename << "' for reading." << std::endl; - return false; - } - - // Get PE32 header - fs.seekg(sizeof(MsDosStub), std::ios::beg); - fs.read((char *)&header, sizeof(header)); - if (fs.fail()) { - std::cerr << "Failed to read header of '" << filename << "'." << std::endl; - fs.close(); - return false; - } - - // Get optional header - fs.seekg(sizeof(MsDosStub) + sizeof(Pe32Header), std::ios::beg); - fs.read((char *)&optional_header, sizeof(optional_header)); - if (fs.fail()) { - std::cerr << "Failed to read optional header of '" << filename << "'." << std::endl; - fs.close(); - return false; - } - - /* Clear header */ - //header.mMagic = 0; // NOPE - //header.mMachine = 0; // NOPE - header.mTimeDateStamp = 0; // OK - //header.mNumberOfSymbols = 0; // NOPE - //header.mCharacteristics = 0; // NOPE - //header.mNumberOfSections = 0; // NOPE - //header.mSizeOfOptionalHeader = 0; // NOPE - header.mPointerToSymbolTable = 0; // OK - - /* Clear Optional Header */ - //optional_header.mMagic = 0; // NOPE - optional_header.mMajorLinkerVersion = 0; // OK - optional_header.mMinorLinkerVersion = 0; // OK - optional_header.mSizeOfCode = 0; // OK - optional_header.mSizeOfInitializedData = 0; // OK - optional_header.mSizeOfUninitializedData = 0; // OK - //optional_header.mAddressOfEntryPoint = 0; // NOPE - optional_header.mBaseOfCode = 0; // OK - optional_header.mBaseOfData = 0; // OK - //optional_header.mImageBase = 0; // FUCK NO - //optional_header.mSectionAlignment = 0; // NOPE - //optional_header.mFileAlignment = 0; // NO - optional_header.mMajorOperatingSystemVersion = 0; // OK - optional_header.mMinorOperatingSystemVersion = 0; // OK - optional_header.mMajorImageVersion = 0; // OK - optional_header.mMinorImageVersion = 0; // OK - //optional_header.mMajorSubsystemVersion = 0; // needs specific value - optional_header.mMinorSubsystemVersion = 0; // OK - //optional_header.mWin32VersionValue = 0; // OK but probably not - //optional_header.mSizeOfImage = 0; // NOPE - //optional_header.mSizeOfHeaders = 0; // NOPE - optional_header.mCheckSum = 0; // OK - //optional_header.mSubsystem = 0; // nah - //optional_header.mDllCharacteristics = 0; // hmmmm... maybe but probably not - optional_header.mSizeOfStackReserve = 0; // OK - optional_header.mSizeOfStackCommit = 0; // OK - optional_header.mSizeOfHeapReserve = 0; // OK - optional_header.mSizeOfHeapCommit = 0; // OK - optional_header.mLoaderFlags = 0; // OK but probably not - //optional_header.mNumberOfRvaAndSizes = 0; // Absolutely the fuck not - - // Set PE32 header - fs.seekg(sizeof(MsDosStub), std::ios::beg); - fs.write((char *)&header, sizeof(header)); - if (fs.fail()) { - std::cerr << "Failed to write header of '" << filename << "'." << std::endl; - fs.close(); - return false; - } - - // Set optional header - fs.seekg(sizeof(MsDosStub) + sizeof(Pe32Header), std::ios::beg); - fs.write((char *)&optional_header, sizeof(optional_header)); - if (fs.fail()) { - std::cerr << "Failed to write header of '" << filename << "'." << std::endl; - fs.close(); - return false; - } - - // Zero out each section header - for (unsigned i = 0; i < header.mNumberOfSections; i++) { - Pe32SectionHeader section_header; - long offset = sizeof(MsDosStub) + sizeof(Pe32Header) + - header.mSizeOfOptionalHeader + i * sizeof(Pe32SectionHeader); - - // Get section header - fs.seekg(offset, std::ios::beg); - fs.read((char *)§ion_header, sizeof(section_header)); - if (fs.fail()) { - std::cerr << "Failed to read section header of '" << filename << "'." << std::endl; - fs.close(); - return false; - } - - // Clear entries of section header - memset(section_header.mName, 0, 8); // yes....? - //section_header.mVirtualSize = 0; // NOPE - //section_header.mVirtualAddress = 0; // NOPE - //section_header.mSizeOfRawData = 0; // NOPE - //section_header.mPointerToRawData = 0; // NOPE - //section_header.mPointerToRelocations = 0; // maybe - //section_header.mPointerToLinenumbers = 0; // maybe - //section_header.mNumberOfRelocations = 0; // maybe - //section_header.mNumberOfLinenumbers = 0; // maybe - //section_header.mCharacteristics = 0; // NOPE - - // Set section headers - fs.seekg(offset, std::ios::beg); - fs.write((char *)§ion_header, sizeof(section_header)); - if (fs.fail()) { - std::cerr << "Failed to write section header: '" << section_header.mName << "' of '" << filename << "'." << std::endl; - fs.close(); - return false; - } - } - - fs.close(); - return true; -} - -[[nodiscard]] -bool pe32::ProcessPe64(char* filename) { - - Pe32Header header; - Pe32PlusOptionalHeader optional_header; - - // Open target file - std::fstream fs(filename, std::ios::binary | std::ios::in | std::ios::out); - if (!fs.is_open()) { - std::cerr << "Failed to open '" << filename << "' for reading." << std::endl; - return false; - } - - // Get PE32 header - fs.seekg(sizeof(MsDosStub), std::ios::beg); - fs.read((char *)&header, sizeof(header)); - if (fs.fail()) { - std::cerr << "Failed to read header of '" << filename << "'." << std::endl; - fs.close(); - return false; - } - - // Get optional header - fs.seekg(sizeof(MsDosStub) + sizeof(Pe32Header), std::ios::beg); - fs.read((char *)&optional_header, sizeof(optional_header)); - if (fs.fail()) { - std::cerr << "Failed to read optional header of '" << filename << "'." << std::endl; - fs.close(); - return false; - } - - /* Clear header */ - //header.mMagic = 0; // NOPE - //header.mMachine = 0; // NOPE - header.mTimeDateStamp = 0; // OK - //header.mNumberOfSymbols = 0; // NOPE - //header.mCharacteristics = 0; // NOPE - //header.mNumberOfSections = 0; // NOPE - //header.mSizeOfOptionalHeader = 0; // NOPE - header.mPointerToSymbolTable = 0; // OK - - /* Clear Optional Header */ - //optional_header.mMagic = 0; // NOPE - optional_header.mMajorLinkerVersion = 0; // OK - optional_header.mMinorLinkerVersion = 0; // OK - optional_header.mSizeOfCode = 0; // OK - optional_header.mSizeOfInitializedData = 0; // OK - optional_header.mSizeOfUninitializedData = 0; // OK - //optional_header.mAddressOfEntryPoint = 0; // NOPE - optional_header.mBaseOfCode = 0; // OK - //optional_header.mImageBase = 0; // FUCK NO - //optional_header.mSectionAlignment = 0; // NOPE - //optional_header.mFileAlignment = 0; // NOOOOOOPE - optional_header.mMajorOperatingSystemVersion = 0; // OK - optional_header.mMinorOperatingSystemVersion = 0; // OK - optional_header.mMajorImageVersion = 0; // OK - optional_header.mMinorImageVersion = 0; // OK - //optional_header.mMajorSubsystemVersion = 0; // needs specific value - //optional_header.mMinorSubsystemVersion = 0; // Sometimes OK so probably not - //optional_header.mWin32VersionValue = 0; // OK but probably not - //optional_header.mSizeOfImage = 0; // NOPE - //optional_header.mSizeOfHeaders = 0; // NOPE - optional_header.mCheckSum = 0; // OK probably not good to change - //optional_header.mSubsystem = 0; // nah - //optional_header.mDllCharacteristics = 0; // hmmmm... maybe but probably not - optional_header.mSizeOfStackReserve = 0; // OK - optional_header.mSizeOfStackCommit = 0; // OK - optional_header.mSizeOfHeapReserve = 0; // OK - optional_header.mSizeOfHeapCommit = 0; // OK - optional_header.mLoaderFlags = 0; // OK but probably not - //optional_header.mNumberOfRvaAndSizes = 0; // Absolutely the fuck not - - // Set PE32 header - fs.seekg(sizeof(MsDosStub), std::ios::beg); - fs.write((char *)&header, sizeof(header)); - if (fs.fail()) { - std::cerr << "Failed to write header of '" << filename << "'." << std::endl; - fs.close(); - return false; - } - - // Set optional header - fs.seekg(sizeof(MsDosStub) + sizeof(Pe32Header), std::ios::beg); - fs.write((char *)&optional_header, sizeof(optional_header)); - if (fs.fail()) { - std::cerr << "Failed to write header of '" << filename << "'." << std::endl; - fs.close(); - return false; - } - - // Zero out each section header - for (unsigned i = 0; i < header.mNumberOfSections; i++) { - Pe32SectionHeader section_header; - long offset = sizeof(MsDosStub) + sizeof(Pe32Header) + - header.mSizeOfOptionalHeader + i * sizeof(Pe32SectionHeader); - - // Get section header - fs.seekg(offset, std::ios::beg); - fs.read((char *)§ion_header, sizeof(section_header)); - if (fs.fail()) { - std::cerr << "Failed to read section header of '" << filename << "'." << std::endl; - fs.close(); - return false; - } - - // Clear entries of section header - memset(section_header.mName, 0, 8); // yes....? - //section_header.mVirtualSize = 0; // NOPE - //section_header.mVirtualAddress = 0; // NOPE - //section_header.mSizeOfRawData = 0; // NOPE - //section_header.mPointerToRawData = 0; // NOPE - //section_header.mPointerToRelocations = 0; // maybe - //section_header.mPointerToLinenumbers = 0; // maybe - //section_header.mNumberOfRelocations = 0; // maybe - //section_header.mNumberOfLinenumbers = 0; // maybe - //section_header.mCharacteristics = 0; // NOPE - - // Set section headers - fs.seekg(offset, std::ios::beg); - fs.write((char *)§ion_header, sizeof(section_header)); - if (fs.fail()) { - std::cerr << "Failed to write section header: '" << section_header.mName << "' of '" << filename << "'." << std::endl; - fs.close(); - return false; - } - } - - fs.close(); - return true; -} diff --git a/src/util.cpp b/src/util.cpp deleted file mode 100644 index 00f8157..0000000 --- a/src/util.cpp +++ /dev/null @@ -1,16 +0,0 @@ -#include "util.hpp" - -void __usage_error(char* argv_0, int error_code) { - std::cerr << "Usage error " << error_code << ": " << [&error_code]() -> std::string { - switch (error_code) { - case -1: { return "no arguments supplied."; } - default: { return "unknown error."; } - } - }() << "\n" - << "\n" - << "example usage:\n" - << " " << argv_0 << " path/to/executable" - << std::endl; - - exit(error_code); -}