summaryrefslogtreecommitdiff
path: root/usr.sbin/crunchgen/elf_hide.c
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2008-08-22 15:18:56 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2008-08-22 15:18:56 +0000
commitf58dd4fe87fead2d644fc1341d7731fe34c75b13 (patch)
tree0e1c8bda49466845ec92f92ade36dd92d2239379 /usr.sbin/crunchgen/elf_hide.c
parentc1a84c1c712d13ee22082743780139fe2a4855f5 (diff)
Merge crunchgen & crunchhide (using name checking), and move to usr.sbin
next step is to not install it as two programs, but be even more clever
Diffstat (limited to 'usr.sbin/crunchgen/elf_hide.c')
-rw-r--r--usr.sbin/crunchgen/elf_hide.c474
1 files changed, 474 insertions, 0 deletions
diff --git a/usr.sbin/crunchgen/elf_hide.c b/usr.sbin/crunchgen/elf_hide.c
new file mode 100644
index 00000000000..b52a7757b07
--- /dev/null
+++ b/usr.sbin/crunchgen/elf_hide.c
@@ -0,0 +1,474 @@
+/* $OpenBSD: elf_hide.c,v 1.1 2008/08/22 15:18:55 deraadt Exp $ */
+
+/*
+ * Copyright (c) 1997 Dale Rahn.
+ * All rights reserved.
+ *
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/exec.h>
+#ifdef _NLIST_DO_ELF
+#include <sys/exec_elf.h>
+
+void load_strtab(Elf_Ehdr * pehdr, char *pexe);
+void dump_strtab();
+char *get_str(int indx);
+
+void load_symtab(Elf_Ehdr * pehdr, char *pexe);
+void dump_symtab();
+
+void load_shstr_tab(Elf_Ehdr * pehdr, char *pexe);
+char *get_shstr(int indx);
+void fprint_shstr(FILE * channel, int indx);
+
+void hide_sym();
+void reorder_syms(Elf_Ehdr * ehdr, Elf_Shdr * symsect,
+ Elf_Sym * symtab, int symtabsize, int symtabsecnum);
+typedef long Symmap;
+void renum_reloc_syms(Elf_Ehdr * ehdr, Symmap * symmap,
+ int symtabsecnum);
+
+
+char *pexe;
+
+void
+elf_hide(int pfile, char *p)
+{
+ Elf_Ehdr *pehdr;
+#ifdef DEBUG
+ Elf_Shdr *pshdr;
+ Elf_Phdr *pphdr;
+ int i;
+#endif
+ struct stat sb;
+
+ pexe = p;
+ pehdr = (Elf_Ehdr *) pexe;
+
+#ifdef DEBUG
+ printf("elf header\n");
+ printf("e_type %x\n", pehdr->e_type);
+ printf("e_machine %x\n", pehdr->e_machine);
+ printf("e_version %x\n", pehdr->e_version);
+ printf("e_entry %x\n", pehdr->e_entry);
+ printf("e_phoff %x\n", pehdr->e_phoff);
+ printf("e_shoff %x\n", pehdr->e_shoff);
+ printf("e_flags %x\n", pehdr->e_flags);
+ printf("e_ehsize %x\n", pehdr->e_ehsize);
+ printf("e_phentsize %x\n", pehdr->e_phentsize);
+ printf("e_phnum %x\n", pehdr->e_phnum);
+ printf("e_shentsize %x\n", pehdr->e_shentsize);
+ printf("e_shnum %x\n", pehdr->e_shnum);
+ printf("e_shstrndx %x\n", pehdr->e_shstrndx);
+#endif
+
+ load_shstr_tab(pehdr, pexe);
+#ifdef DEBUG
+ for (i = 0; i < pehdr->e_shnum; i++) {
+ pshdr = (Elf_Phdr *) (pexe + pehdr->e_shoff +
+ (i * pehdr->e_shentsize));
+
+ printf("section header %d\n", i);
+ printf("sh_name %x ", pshdr->sh_name);
+ fprint_shstr(stdout, pshdr->sh_name);
+ printf("\n");
+ printf("sh_type %x\n", pshdr->sh_type);
+ printf("sh_flags %x\n", pshdr->sh_flags);
+ printf("sh_addr %x\n", pshdr->sh_addr);
+ printf("sh_offset %x\n", pshdr->sh_offset);
+ printf("sh_size %x\n", pshdr->sh_size);
+ printf("sh_link %x\n", pshdr->sh_link);
+ printf("sh_info %x\n", pshdr->sh_info);
+ printf("sh_addralign %x\n", pshdr->sh_addralign);
+ printf("sh_entsize %x\n", pshdr->sh_entsize);
+ }
+#endif /* DEBUG */
+
+#ifdef DEBUG
+ for (i = 0; i < pehdr->e_phnum; i++) {
+ pshdr = (Elf_Phdr *) (pexe + pehdr->e_phoff +
+ (i * pehdr->e_phentsize));
+
+ printf("program header %d\n", i);
+ printf("p_type %x\n", pphdr->p_type);
+ printf("p_offset %x\n", pphdr->p_offset);
+ printf("p_vaddr %x\n", pphdr->p_vaddr);
+ printf("p_paddr %x\n", pphdr->p_paddr);
+ printf("p_filesz %x\n", pphdr->p_filesz);
+ printf("p_memsz %x\n", pphdr->p_memsz);
+ printf("p_flags %x\n", pphdr->p_flags);
+ printf("p_align %x\n", pphdr->p_align);
+ }
+#endif /* DEBUG */
+#if 0
+ for (i = 0; i < pehdr->e_shnum; i++) {
+ pshdr = (Elf_Phdr *) (pexe + pehdr->e_shoff +
+ (i * pehdr->e_shentsize));
+ if (strcmp(".strtab", get_shstr(pshdr->sh_name)) == 0)
+ break;
+ }
+ fprint_shstr(stdout, pshdr->sh_name);
+ printf("\n");
+#endif
+
+ load_strtab(pehdr, pexe);
+ load_symtab(pehdr, pexe);
+
+ munmap(pexe, sb.st_size);
+ close(pfile);
+}
+char *shstrtab;
+
+void
+load_shstr_tab(Elf_Ehdr * pehdr, char *pexe)
+{
+ Elf_Shdr *pshdr;
+ shstrtab = NULL;
+ if (pehdr->e_shstrndx == 0)
+ return;
+ pshdr = (Elf_Shdr *) (pexe + pehdr->e_shoff +
+ (pehdr->e_shstrndx * pehdr->e_shentsize));
+
+ shstrtab = (char *) (pexe + pshdr->sh_offset);
+}
+
+void
+fprint_shstr(FILE * channel, int indx)
+{
+ if (shstrtab != NULL)
+ fprintf(channel, "\"%s\"", &(shstrtab[indx]));
+}
+
+char *
+get_shstr(int indx)
+{
+ return &(shstrtab[indx]);
+}
+
+void
+load_symtab(Elf_Ehdr * pehdr, char *pexe)
+{
+ Elf_Sym *symtab;
+ Elf_Shdr *symsect;
+ int symtabsize;
+ Elf_Shdr *psymshdr;
+ Elf_Shdr *pshdr;
+#ifdef DEBUG
+ char *shname;
+#endif
+ int i;
+
+ symtab = NULL;
+ for (i = 0; i < pehdr->e_shnum; i++) {
+ pshdr = (Elf_Shdr *) (pexe + pehdr->e_shoff +
+ (i * pehdr->e_shentsize));
+ if (SHT_REL != pshdr->sh_type && SHT_RELA != pshdr->sh_type)
+ continue;
+ psymshdr = (Elf_Shdr *) (pexe + pehdr->e_shoff +
+ (pshdr->sh_link * pehdr->e_shentsize));
+#ifdef DEBUG
+ fprint_shstr(stdout, pshdr->sh_name);
+ printf("\n");
+#endif
+ symtab = (Elf_Sym *) (pexe + psymshdr->sh_offset);
+ symsect = psymshdr;
+ symtabsize = psymshdr->sh_size;
+
+#ifdef DEBUG
+ dump_symtab(symsect, symtab, symtabsize);
+#endif
+ hide_sym(pehdr, symsect, symtab, symtabsize, pshdr->sh_link);
+ }
+
+}
+
+void
+dump_symtab(Elf_Shdr * symsect, Elf_Sym * symtab, int symtabsize)
+{
+ int i;
+ Elf_Sym *psymtab;
+
+ for (i = 0; i < (symtabsize / sizeof(Elf_Sym)); i++) {
+ psymtab = &(symtab[i]);
+ if ((psymtab->st_info & 0xf0) == 0x10 &&
+ (psymtab->st_shndx != SHN_UNDEF)) {
+ printf("symbol %d:\n", i);
+ printf("st_name %x \"%s\"\n", psymtab->st_name,
+ get_str(psymtab->st_name));
+ printf("st_value %x\n", psymtab->st_value);
+ printf("st_size %x\n", psymtab->st_size);
+ printf("st_info %x\n", psymtab->st_info);
+ printf("st_other %x\n", psymtab->st_other);
+ printf("st_shndx %x\n", psymtab->st_shndx);
+ }
+ }
+}
+
+char *strtab;
+int strtabsize;
+void
+load_strtab(Elf_Ehdr * pehdr, char *pexe)
+{
+ Elf_Shdr *pshdr = NULL;
+ char *shname;
+ int i;
+ strtab = NULL;
+ for (i = 0; i < pehdr->e_shnum; i++) {
+ pshdr = (Elf_Shdr *) (pexe + pehdr->e_shoff +
+ (i * pehdr->e_shentsize));
+
+ shname = get_shstr(pshdr->sh_name);
+ if (strcmp(".strtab", shname) == 0)
+ break;
+ }
+#ifdef DEBUG
+ fprint_shstr(stdout, pshdr->sh_name);
+ printf("\n");
+#endif
+
+ strtab = (char *) (pexe + pshdr->sh_offset);
+
+ strtabsize = pshdr->sh_size;
+
+#ifdef DEBUG
+ dump_strtab();
+#endif
+}
+
+void
+dump_strtab()
+{
+ int index;
+ char *pstr;
+ char *pnstr;
+ int i = 0;
+ index = 0;
+ pstr = strtab;
+ while (index < strtabsize) {
+ printf("string %x: \"%s\"\n", i, pstr);
+ pnstr = pstr + strlen(pstr) + 1;
+ index = pnstr - strtab;
+ pstr = pnstr;
+ i++;
+ }
+
+}
+
+void
+fprint_str(FILE * channel, int indx)
+{
+ if (strtab != NULL)
+ fprintf(channel, "\"%s\"", &(strtab[indx]));
+}
+
+char *
+get_str(int indx)
+{
+ return &(strtab[indx]);
+}
+
+int in_keep_list(char *symbol);
+
+void
+hide_sym(Elf_Ehdr * ehdr, Elf_Shdr * symsect,
+ Elf_Sym * symtab, int symtabsize, int symtabsecnum)
+{
+ int i;
+ unsigned char info;
+ Elf_Sym *psymtab;
+
+#ifdef __mips__
+ u_int32_t f = arc4random();
+#endif
+
+ for (i = 0; i < (symtabsize / sizeof(Elf_Sym)); i++) {
+ psymtab = &(symtab[i]);
+ if ((psymtab->st_info & 0xf0) == 0x10 &&
+ (psymtab->st_shndx != SHN_UNDEF)) {
+ if (in_keep_list(get_str(psymtab->st_name)))
+ continue;
+#ifdef DEBUG
+ printf("symbol %d:\n", i);
+ printf("st_name %x \"%s\"\n", psymtab->st_name,
+ get_str(psymtab->st_name));
+ printf("st_info %x\n", psymtab->st_info);
+#endif
+#ifndef __mips__
+ info = psymtab->st_info;
+ info = info & 0xf;
+ psymtab->st_info = info;
+#else
+ /*
+ * XXX This is a small ugly hack to be able to use
+ * XXX chrunchide with MIPS.
+ * XXX Because MIPS needs global symbols to stay
+ * XXX global (has to do with GOT), we mess around
+ * XXX with the symbol names instead. For most uses
+ * XXX this will be no problem, symbols are stripped
+ * XXX anyway. However, if many one character
+ * XXX symbols exist, names may clash.
+ */
+ {
+ char *p;
+ u_int32_t n, z;
+
+ z = f++;
+ p = get_str(psymtab->st_name);
+ n = strlen(p);
+ if (n > 4)
+ n = 4;
+ while (n--) {
+ p[n] = z;
+ z >>= 8;
+ while (p[n] == 0)
+ p[n] += arc4random();
+ }
+ }
+
+#endif
+#ifdef DEBUG
+ printf("st_info %x\n", psymtab->st_info);
+#endif
+ }
+ }
+ reorder_syms(ehdr, symsect, symtab, symtabsize, symtabsecnum);
+}
+
+void
+reorder_syms(Elf_Ehdr * ehdr, Elf_Shdr * symsect,
+ Elf_Sym * symtab, int symtabsize, int symtabsecnum)
+{
+ int i;
+ int nsyms;
+ int cursym;
+ Elf_Sym *tmpsymtab;
+ Symmap *symmap;
+
+
+ nsyms = symtabsize / sizeof(Elf_Sym);
+
+ tmpsymtab = (Elf_Sym *) calloc(1, symtabsize);
+ symmap = (Symmap *) calloc(nsyms, sizeof(Symmap));
+ if (!tmpsymtab || !symmap)
+ errx(5, "calloc: %s", strerror(ENOMEM));
+
+ bcopy(symtab, tmpsymtab, symtabsize);
+
+ cursym = 1;
+ for (i = 1; i < nsyms; i++) {
+ if ((tmpsymtab[i].st_info & 0xf0) == 0x00) {
+#ifdef DEBUG
+ printf("copying l o%d n%d <%s>\n", i, cursym,
+ get_str(tmpsymtab[i].st_name));
+#endif
+ bcopy(&(tmpsymtab[i]), &(symtab[cursym]),
+ sizeof(Elf_Sym));
+ symmap[i] = cursym;
+ cursym++;
+ }
+ }
+ symsect->sh_info = cursym;
+ for (i = 1; i < nsyms; i++) {
+ if ((tmpsymtab[i].st_info & 0xf0) != 0x00) {
+#ifdef DEBUG
+ printf("copying nl o%d n%d <%s>\n", i, cursym,
+ get_str(tmpsymtab[i].st_name));
+#endif
+ bcopy(&(tmpsymtab[i]), &(symtab[cursym]),
+ sizeof(Elf_Sym));
+ symmap[i] = cursym;
+ cursym++;
+ }
+ }
+ if (cursym != nsyms) {
+ printf("miscounted symbols somewhere c %d n %d \n",
+ cursym, nsyms);
+ exit(5);
+ }
+ renum_reloc_syms(ehdr, symmap, symtabsecnum);
+ free(tmpsymtab);
+ free(symmap);
+}
+
+void
+renum_reloc_syms(Elf_Ehdr * ehdr, Symmap * symmap, int symtabsecnum)
+{
+ Elf_Shdr *pshdr;
+ int i, j;
+ int num_reloc;
+ Elf_Rel *prel;
+ Elf_RelA *prela;
+ int symnum;
+
+ for (i = 0; i < ehdr->e_shnum; i++) {
+ pshdr = (Elf_Shdr *) (pexe + ehdr->e_shoff +
+ (i * ehdr->e_shentsize));
+ if ((pshdr->sh_type == SHT_RELA) &&
+ pshdr->sh_link == symtabsecnum) {
+
+#ifdef DEBUG
+ printf("section %d has rela relocations in symtab\n", i);
+#endif
+ prela = (Elf_RelA *) (pexe + pshdr->sh_offset);
+ num_reloc = pshdr->sh_size / sizeof(Elf_RelA);
+ for (j = 0; j < num_reloc; j++) {
+ symnum = ELF_R_SYM(prela[j].r_info);
+#ifdef DEBUG
+ printf("sym num o %d n %d\n", symnum,
+ symmap[symnum]);
+#endif
+ prela[j].r_info = ELF_R_INFO(symmap[symnum],
+ ELF_R_TYPE(prela[j].r_info));
+ }
+ }
+ if ((pshdr->sh_type == SHT_REL) &&
+ pshdr->sh_link == symtabsecnum) {
+#ifdef DEBUG
+ printf("section %d has rel relocations in symtab\n", i);
+#endif
+ prel = (Elf_Rel *) (pexe + pshdr->sh_offset);
+ num_reloc = pshdr->sh_size / sizeof(Elf_Rel);
+ for (j = 0; j < num_reloc; j++) {
+ symnum = ELF_R_SYM(prel[j].r_info);
+#ifdef DEBUG
+ printf("sym num o %d n %d\n", symnum,
+ symmap[symnum]);
+#endif
+ prel[j].r_info = ELF_R_INFO(symmap[symnum],
+ ELF_R_TYPE(prel[j].r_info));
+ }
+ }
+ }
+
+}
+#endif /* _NLIST_DO_ELF */