Initial Commit

This commit is contained in:
TheBrokenRail 2022-03-22 19:13:25 -04:00
commit 3a99de7642
9 changed files with 216 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
.vscode
build
CMakeLists.txt.user
*.autosave

13
CMakeLists.txt Normal file
View File

@ -0,0 +1,13 @@
cmake_minimum_required(VERSION 3.13.0)
# Project
project(elf-padder)
# Warnings
add_compile_options(-Wall -Wextra -Werror -Wpointer-arith -Wshadow -Wnull-dereference)
add_link_options(-Wl,--no-undefined)
add_definitions(-D_GNU_SOURCE)
set(CMAKE_C_STANDARD 99)
# Build
add_executable(elf-padder src/main.c src/elf_32.c src/elf_64.c)

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 TheBrokenRail
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

6
src/elf.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
#include <stddef.h>
void Elf32_pad(unsigned char *out, size_t padding);
void Elf64_pad(unsigned char *out, size_t padding);

2
src/elf_32.c Normal file
View File

@ -0,0 +1,2 @@
#define CustomElfW(x) Elf32_##x
#include "elf_common.c"

2
src/elf_64.c Normal file
View File

@ -0,0 +1,2 @@
#define CustomElfW(x) Elf64_##x
#include "elf_common.c"

39
src/elf_common.c Normal file
View File

@ -0,0 +1,39 @@
#ifndef CustomElfW
#include <link.h>
#define CustomElfW(x) ElfW(x)
#endif
#include <elf.h>
#include "log.h"
#include "elf.h"
// Fix ELF Pointers
void CustomElfW(pad)(unsigned char *out, size_t padding) {
// Get ELF Header
CustomElfW(Ehdr) *elf_header = (CustomElfW(Ehdr) *) out;
// Fix ELF Program Header Offset
if (elf_header->e_phoff != 0) {
elf_header->e_phoff += padding;
// Fix ELF Program Headers
CustomElfW(Phdr) *elf_program_headers = (CustomElfW(Phdr) *) (out + elf_header->e_phoff);
int elf_program_header_count = elf_header->e_phnum;
for (int i = 0; i < elf_program_header_count; i++) {
elf_program_headers[i].p_offset += padding;
}
}
// Fix ELF Section Header
if (elf_header->e_shoff != 0) {
elf_header->e_shoff += padding;
// Fix ELF Section Headers
CustomElfW(Shdr) *elf_section_headers = (CustomElfW(Shdr) *) (out + elf_header->e_shoff);
int elf_section_header_count = elf_header->e_shnum;
for (int i = 0; i < elf_section_header_count; i++) {
elf_section_headers[i].sh_offset += padding;
}
}
}

16
src/log.h Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#include <stdio.h>
#include <stdlib.h>
// Logging
#define INFO(format, ...) { fprintf(stderr, "[INFO]: " format "\n", __VA_ARGS__); }
#define ERR(format, ...) { fprintf(stderr, "[ERR]: (%s:%i): " format "\n", __FILE__, __LINE__, __VA_ARGS__); exit(EXIT_FAILURE); }
// Check Memory Allocation
#define ALLOC_CHECK(obj) \
{ \
if (obj == NULL) { \
ERR("%s", "Memory Allocation Failed"); \
} \
}

113
src/main.c Normal file
View File

@ -0,0 +1,113 @@
#include <stdio.h>
#include <sys/mman.h>
#include <string.h>
#include <unistd.h>
#include <elf.h>
#include "log.h"
#include "elf.h"
// Pad ELF File
static void *elf_pad(const char *target, size_t padding, size_t *out_size) {
// File Data
FILE *file_obj = NULL;
unsigned char *file_map = NULL;
long int file_size = 0;
// Return
unsigned char *out = NULL;
// Code
{
// Load Main Binary
file_obj = fopen(target, "rb");
// Verify Binary
if (!file_obj) {
ERR("Unable To Open: %s", target);
}
// Get File Size
fseek(file_obj, 0L, SEEK_END);
file_size = ftell(file_obj);
fseek(file_obj, 0L, SEEK_SET);
// Map File To Pointer
file_map = (unsigned char *) mmap(0, file_size, PROT_READ, MAP_PRIVATE, fileno(file_obj), 0);
// Check ELF Magic
if (file_map[EI_MAG0] != ELFMAG0 || file_map[EI_MAG1] != ELFMAG1 || file_map[EI_MAG2] != ELFMAG2 || file_map[EI_MAG3] != ELFMAG3) {
ERR("Not An ELF File: %s", target);
}
int is_64bit = file_map[EI_CLASS] != ELFCLASS32;
if (file_map[EI_DATA] != ELFDATA2LSB) {
ERR("ELF File Isn't Little-Endian: %s", target);
}
// Allocate New File
*out_size = file_size + padding;
out = malloc(*out_size);
ALLOC_CHECK(out);
// Copy Header
size_t header_size = is_64bit ? sizeof (Elf64_Ehdr) : sizeof (Elf32_Ehdr);
memcpy(out, file_map, header_size);
// Copy Everything Else
memcpy(out + header_size + padding, file_map + header_size, file_size - header_size);
// Zero Padding
memset(out + header_size, 0, padding);
// Fix Pointers
if (is_64bit) {
Elf64_pad(out, padding);
} else {
Elf32_pad(out, padding);
}
}
// Unmap And Close File
if (file_map != NULL) {
munmap(file_map, file_size);
}
if (file_obj != NULL) {
fclose(file_obj);
}
// Return
return out;
}
// Main
int main(int argc, char *argv[]) {
if (argc != 3) {
ERR("%s", "Invalid Arguments");
}
// Arguments
size_t padding = 0;
if (sscanf(argv[1], "%zu", &padding) != 1) {
ERR("%s", "Unable To Parse Padding Number");
}
char *target = argv[2];
// Align Padding To Page Boundary
{
long page_size = sysconf(_SC_PAGESIZE);
size_t old_padding = padding;
padding = (padding / page_size) * page_size;
if ((old_padding % page_size) != 0) {
padding += page_size;
}
}
INFO("Aligning Padding To Page Boundary: %zu", padding);
// Pad
size_t out_size = 0;
void *out = elf_pad(target, padding, &out_size);
// Print
fwrite(out, 1, out_size, stdout);
// Free
free(out);
}