Commit 90a53d8f authored by PoroCYon's avatar PoroCYon
Browse files

initial

parents
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
CFLAGS += -std=gnu11 #-Wall
noelfver: noelfver.c
clean:
@-rm -vf noelfver
# noelfver
Removes versioning information offsets from the PT_DYNAMIC phdr (segment)
from ELF files. Does ***NOT*** remove the actual versioning information (use
`objcopy -R .gnu.version -R .gnu.version_r` for that). Don't use this unless
you know what you are doing.
## If something breaks
It's entirely your fault. No warranty implied etc. etc. etc. I wrote this in
half an hour, so what do you expect?
## License
[WTFPL 2.0](/LICENSE)
/*
* Copyright (c) 2019 PoroCYon
* This work is free. You can redistribute it and/or modify it under the
* terms of the Do What The Fuck You Want To Public License, Version 2,
* as published by Sam Hocevar. See the LICENSE file for more details.
*/
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <elf.h>
static void print_help(char* arg0) {
printf(
"%s: remove symbol versioning information from the DYNAMIC segment of an ELF\n"
"file. Does NOT remove the sections containing the actual versioning\n"
"information, use something like `objcopy -R .gnu.version -R .gnu.version_r`\n"
"to remove those.\n"
"\n"
"Usage:\n"
"\t%s -h|--help\n"
"\t\tPrint this text.\n"
"\n"
"\t%s input.elf > output.elf\n"
"\t\tPatch the input.elf file, output will be written to stdout.\n"
"\t\tIf stdout is a TTY, this text will be displayed as well.\n"
, arg0, arg0, arg0);
}
static const int dyn_forbidden[] = {
DT_VERSYM ,
DT_VERDEF ,
DT_VERDEFNUM ,
DT_VERNEED ,
DT_VERNEEDNUM,
};
#define lengthof(x) (sizeof(x)/sizeof(*x))
// ¯\_(ツ)_/¯
#define PATCHUP_NAME patch_up_elf64
#include "patchup.h"
#undef PATCHUP_NAME
#define PATCHUP_NAME patch_up_elf32
#define Elf64_Ehdr Elf32_Ehdr
#define Elf64_Phdr Elf32_Phdr
#define Elf64_Dyn Elf32_Dyn
#include "patchup.h"
#undef Elf64_Dyn
#undef Elf64_Phdr
#undef Elf64_Ehdr
#undef PATCHUP_NAME
int main(int argc, char* argv[]) {
if (argc < 2 || !strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")
|| isatty(STDOUT_FILENO)) {
print_help(argv[0]);
return isatty(STDOUT_FILENO) ? 1 : 0;
}
int fd = open(argv[1], O_RDONLY);
if (fd < 0) {
dprintf(STDERR_FILENO, "Can't open input file '%s'.\n", argv[1]);
return 1;
}
struct stat st;
if (fstat(fd, &st) < 0) {
dprintf(STDERR_FILENO, "Can't stat file '%s'.\n", argv[1]);
close(fd);
return 1;
}
void* mem = malloc((size_t)st.st_size);
if (read(fd, mem, (size_t)st.st_size) != st.st_size) {
dprintf(STDERR_FILENO, "Can't read from file '%s'.\n", argv[1]);
free(mem);
close(fd);
return 1;
}
close(fd);
int rv = 0;
bool is32bit;
// try to emulate 'bugs' in the kernel a little -- on x86es, it only looks
// at e_machine, never at EI_CLASS.
if (((Elf32_Ehdr*)mem)->e_machine == EM_386) {
is32bit = true;
} else if (((Elf64_Ehdr*)mem)->e_machine == EM_X86_64) {
is32bit = false;
} else {
is32bit = ((uint8_t*)mem)[EI_CLASS] < ELFCLASS64;
}
int res = (is32bit ?
patch_up_elf32((Elf32_Ehdr*)mem) :
patch_up_elf64((Elf64_Ehdr*)mem));
if (res) {
rv = res;
goto ERR;
}
write(STDOUT_FILENO, mem, (size_t)st.st_size);
ERR:
free(mem);
return rv;
}
/*
* Copyright (c) 2019 PoroCYon
* This work is free. You can redistribute it and/or modify it under the
* terms of the Do What The Fuck You Want To Public License, Version 2,
* as published by Sam Hocevar. See the LICENSE file for more details.
*/
static int PATCHUP_NAME(Elf64_Ehdr* elf) {
for (size_t i = 0; i < elf->e_phnum; ++i) {
Elf64_Phdr* phdr = (Elf64_Phdr*)(
(uint8_t*)elf + elf->e_phoff + i * elf->e_phentsize);
if (phdr->p_type != PT_DYNAMIC) {
continue;
}
Elf64_Dyn* dynbase = (Elf64_Dyn*)((uint8_t*)elf + phdr->p_offset);
for (size_t j = 0; ; ++j) {
Elf64_Dyn* dyn = &dynbase[j];
if (dyn->d_tag == DT_NULL) break;
for (size_t k = 0; k < lengthof(dyn_forbidden); ++k) {
if (dyn->d_tag == dyn_forbidden[k]) {
if (dynbase[j+1].d_tag == DT_NULL) {
dyn->d_tag = DT_NULL;
} else {
// TODO: instead of replacing it with a placeholder
// value, move the following entries up, and overwrite
// the end with zeros.
dyn->d_tag = DT_DEBUG; // placeholder value
}
dyn->d_un.d_val = 0;
}
}
}
}
return 0;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment