Initial Commit
This commit is contained in:
commit
3a99de7642
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
.vscode
|
||||
build
|
||||
CMakeLists.txt.user
|
||||
*.autosave
|
13
CMakeLists.txt
Normal file
13
CMakeLists.txt
Normal 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
21
LICENSE
Normal 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
6
src/elf.h
Normal 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
2
src/elf_32.c
Normal file
@ -0,0 +1,2 @@
|
||||
#define CustomElfW(x) Elf32_##x
|
||||
#include "elf_common.c"
|
2
src/elf_64.c
Normal file
2
src/elf_64.c
Normal file
@ -0,0 +1,2 @@
|
||||
#define CustomElfW(x) Elf64_##x
|
||||
#include "elf_common.c"
|
39
src/elf_common.c
Normal file
39
src/elf_common.c
Normal 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
16
src/log.h
Normal 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
113
src/main.c
Normal 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);
|
||||
}
|
Reference in New Issue
Block a user