1 /* $OpenBSD: elf_hide.c,v 1.8 2014/05/20 01:25:24 guenther Exp $ */ 2 3 /* 4 * Copyright (c) 1997 Dale Rahn. 5 * All rights reserved. 6 * 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/types.h> 30 #include <sys/mman.h> 31 #include <sys/stat.h> 32 #include <err.h> 33 #include <errno.h> 34 #include <fcntl.h> 35 #include <unistd.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <sys/exec.h> 40 #include "mangle.h" 41 42 #ifdef _NLIST_DO_ELF 43 #include <sys/exec_elf.h> 44 45 extern int elf_mangle; 46 47 void load_strtab(Elf_Ehdr * pehdr, char *pexe); 48 void dump_strtab(void); 49 char *get_str(int indx); 50 51 void load_symtab(Elf_Ehdr * pehdr, char *pexe); 52 void dump_symtab(Elf_Shdr * symsect, Elf_Sym * symtab, int symtabsize); 53 void fprint_str(FILE * channel, int indx); 54 55 void load_shstr_tab(Elf_Ehdr * pehdr, char *pexe); 56 char *get_shstr(int indx); 57 void fprint_shstr(FILE * channel, int indx); 58 59 void hide_sym(Elf_Ehdr * ehdr, Elf_Shdr * symsect, 60 Elf_Sym * symtab, int symtabsize, int symtabsecnum); 61 void reorder_syms(Elf_Ehdr * ehdr, Elf_Shdr * symsect, 62 Elf_Sym * symtab, int symtabsize, int symtabsecnum); 63 typedef long Symmap; 64 void renum_reloc_syms(Elf_Ehdr * ehdr, Symmap * symmap, 65 int symtabsecnum); 66 void elf_hide(int pfile, char *p); 67 68 69 char *pexe; 70 71 void 72 elf_hide(int pfile, char *p) 73 { 74 Elf_Ehdr *pehdr; 75 #ifdef DEBUG 76 Elf_Shdr *pshdr; 77 Elf_Phdr *pphdr; 78 int i; 79 #endif 80 81 pexe = p; 82 pehdr = (Elf_Ehdr *) pexe; 83 84 #ifdef DEBUG 85 printf("elf header\n"); 86 printf("e_type %x\n", pehdr->e_type); 87 printf("e_machine %x\n", pehdr->e_machine); 88 printf("e_version %x\n", pehdr->e_version); 89 printf("e_entry %x\n", pehdr->e_entry); 90 printf("e_phoff %x\n", pehdr->e_phoff); 91 printf("e_shoff %x\n", pehdr->e_shoff); 92 printf("e_flags %x\n", pehdr->e_flags); 93 printf("e_ehsize %x\n", pehdr->e_ehsize); 94 printf("e_phentsize %x\n", pehdr->e_phentsize); 95 printf("e_phnum %x\n", pehdr->e_phnum); 96 printf("e_shentsize %x\n", pehdr->e_shentsize); 97 printf("e_shnum %x\n", pehdr->e_shnum); 98 printf("e_shstrndx %x\n", pehdr->e_shstrndx); 99 #endif 100 101 load_shstr_tab(pehdr, pexe); 102 #ifdef DEBUG 103 for (i = 0; i < pehdr->e_shnum; i++) { 104 pshdr = (Elf_Phdr *) (pexe + pehdr->e_shoff + 105 (i * pehdr->e_shentsize)); 106 107 printf("section header %d\n", i); 108 printf("sh_name %x ", pshdr->sh_name); 109 fprint_shstr(stdout, pshdr->sh_name); 110 printf("\n"); 111 printf("sh_type %x\n", pshdr->sh_type); 112 printf("sh_flags %x\n", pshdr->sh_flags); 113 printf("sh_addr %x\n", pshdr->sh_addr); 114 printf("sh_offset %x\n", pshdr->sh_offset); 115 printf("sh_size %x\n", pshdr->sh_size); 116 printf("sh_link %x\n", pshdr->sh_link); 117 printf("sh_info %x\n", pshdr->sh_info); 118 printf("sh_addralign %x\n", pshdr->sh_addralign); 119 printf("sh_entsize %x\n", pshdr->sh_entsize); 120 } 121 #endif /* DEBUG */ 122 123 #ifdef DEBUG 124 for (i = 0; i < pehdr->e_phnum; i++) { 125 pshdr = (Elf_Phdr *) (pexe + pehdr->e_phoff + 126 (i * pehdr->e_phentsize)); 127 128 printf("program header %d\n", i); 129 printf("p_type %x\n", pphdr->p_type); 130 printf("p_offset %x\n", pphdr->p_offset); 131 printf("p_vaddr %x\n", pphdr->p_vaddr); 132 printf("p_paddr %x\n", pphdr->p_paddr); 133 printf("p_filesz %x\n", pphdr->p_filesz); 134 printf("p_memsz %x\n", pphdr->p_memsz); 135 printf("p_flags %x\n", pphdr->p_flags); 136 printf("p_align %x\n", pphdr->p_align); 137 } 138 #endif /* DEBUG */ 139 #if 0 140 for (i = 0; i < pehdr->e_shnum; i++) { 141 pshdr = (Elf_Phdr *) (pexe + pehdr->e_shoff + 142 (i * pehdr->e_shentsize)); 143 if (strcmp(".strtab", get_shstr(pshdr->sh_name)) == 0) 144 break; 145 } 146 fprint_shstr(stdout, pshdr->sh_name); 147 printf("\n"); 148 #endif 149 150 load_strtab(pehdr, pexe); 151 load_symtab(pehdr, pexe); 152 close(pfile); 153 } 154 char *shstrtab; 155 156 void 157 load_shstr_tab(Elf_Ehdr * pehdr, char *pexe) 158 { 159 Elf_Shdr *pshdr; 160 shstrtab = NULL; 161 if (pehdr->e_shstrndx == 0) 162 return; 163 pshdr = (Elf_Shdr *) (pexe + pehdr->e_shoff + 164 (pehdr->e_shstrndx * pehdr->e_shentsize)); 165 166 shstrtab = (char *) (pexe + pshdr->sh_offset); 167 } 168 169 void 170 fprint_shstr(FILE * channel, int indx) 171 { 172 if (shstrtab != NULL) 173 fprintf(channel, "\"%s\"", &(shstrtab[indx])); 174 } 175 176 char * 177 get_shstr(int indx) 178 { 179 return &(shstrtab[indx]); 180 } 181 182 void 183 load_symtab(Elf_Ehdr * pehdr, char *pexe) 184 { 185 Elf_Sym *symtab; 186 Elf_Shdr *symsect; 187 int symtabsize; 188 Elf_Shdr *psymshdr; 189 Elf_Shdr *pshdr; 190 #ifdef DEBUG 191 char *shname; 192 #endif 193 int i; 194 195 symtab = NULL; 196 for (i = 0; i < pehdr->e_shnum; i++) { 197 pshdr = (Elf_Shdr *) (pexe + pehdr->e_shoff + 198 (i * pehdr->e_shentsize)); 199 if (SHT_REL != pshdr->sh_type && SHT_RELA != pshdr->sh_type) 200 continue; 201 psymshdr = (Elf_Shdr *) (pexe + pehdr->e_shoff + 202 (pshdr->sh_link * pehdr->e_shentsize)); 203 #ifdef DEBUG 204 fprint_shstr(stdout, pshdr->sh_name); 205 printf("\n"); 206 #endif 207 symtab = (Elf_Sym *) (pexe + psymshdr->sh_offset); 208 symsect = psymshdr; 209 symtabsize = psymshdr->sh_size; 210 211 #ifdef DEBUG 212 dump_symtab(symsect, symtab, symtabsize); 213 #endif 214 hide_sym(pehdr, symsect, symtab, symtabsize, pshdr->sh_link); 215 } 216 217 } 218 219 void 220 dump_symtab(Elf_Shdr * symsect, Elf_Sym * symtab, int symtabsize) 221 { 222 int i; 223 Elf_Sym *psymtab; 224 225 for (i = 0; i < (symtabsize / sizeof(Elf_Sym)); i++) { 226 psymtab = &(symtab[i]); 227 if ((psymtab->st_info & 0xf0) == 0x10 && 228 (psymtab->st_shndx != SHN_UNDEF)) { 229 printf("symbol %d:\n", i); 230 printf("st_name %x \"%s\"\n", psymtab->st_name, 231 get_str(psymtab->st_name)); 232 printf("st_value %llx\n", (unsigned long long)psymtab->st_value); 233 printf("st_size %llx\n", (unsigned long long)psymtab->st_size); 234 printf("st_info %x\n", psymtab->st_info); 235 printf("st_other %x\n", psymtab->st_other); 236 printf("st_shndx %x\n", psymtab->st_shndx); 237 } 238 } 239 } 240 241 char *strtab; 242 int strtabsize; 243 void 244 load_strtab(Elf_Ehdr * pehdr, char *pexe) 245 { 246 Elf_Shdr *pshdr = NULL; 247 char *shname; 248 int i; 249 strtab = NULL; 250 for (i = 0; i < pehdr->e_shnum; i++) { 251 pshdr = (Elf_Shdr *) (pexe + pehdr->e_shoff + 252 (i * pehdr->e_shentsize)); 253 254 shname = get_shstr(pshdr->sh_name); 255 if (strcmp(".strtab", shname) == 0) 256 break; 257 } 258 #ifdef DEBUG 259 fprint_shstr(stdout, pshdr->sh_name); 260 printf("\n"); 261 #endif 262 263 strtab = (char *) (pexe + pshdr->sh_offset); 264 265 strtabsize = pshdr->sh_size; 266 267 #ifdef DEBUG 268 dump_strtab(); 269 #endif 270 } 271 272 void 273 dump_strtab() 274 { 275 int index; 276 char *pstr; 277 char *pnstr; 278 int i = 0; 279 index = 0; 280 pstr = strtab; 281 while (index < strtabsize) { 282 printf("string %x: \"%s\"\n", i, pstr); 283 pnstr = pstr + strlen(pstr) + 1; 284 index = pnstr - strtab; 285 pstr = pnstr; 286 i++; 287 } 288 289 } 290 291 void 292 fprint_str(FILE * channel, int indx) 293 { 294 if (strtab != NULL) 295 fprintf(channel, "\"%s\"", &(strtab[indx])); 296 } 297 298 char * 299 get_str(int indx) 300 { 301 return &(strtab[indx]); 302 } 303 304 int in_keep_list(char *symbol); 305 306 void 307 hide_sym(Elf_Ehdr * ehdr, Elf_Shdr * symsect, 308 Elf_Sym * symtab, int symtabsize, int symtabsecnum) 309 { 310 int i; 311 unsigned char info; 312 Elf_Sym *psymtab; 313 314 for (i = 0; i < (symtabsize / sizeof(Elf_Sym)); i++) { 315 psymtab = &(symtab[i]); 316 if ((psymtab->st_info & 0xf0) == 0x10 && 317 (psymtab->st_shndx != SHN_UNDEF)) { 318 if (in_keep_list(get_str(psymtab->st_name))) 319 continue; 320 #ifdef DEBUG 321 printf("symbol %d:\n", i); 322 printf("st_name %x \"%s\"\n", psymtab->st_name, 323 get_str(psymtab->st_name)); 324 printf("st_info %x\n", psymtab->st_info); 325 #endif 326 if (!elf_mangle) { 327 info = psymtab->st_info; 328 info = info & 0xf; 329 psymtab->st_info = info; 330 } else { 331 mangle_str(get_str(psymtab->st_name)); 332 } 333 #ifdef DEBUG 334 printf("st_info %x\n", psymtab->st_info); 335 #endif 336 } 337 } 338 reorder_syms(ehdr, symsect, symtab, symtabsize, symtabsecnum); 339 } 340 341 void 342 reorder_syms(Elf_Ehdr * ehdr, Elf_Shdr * symsect, 343 Elf_Sym * symtab, int symtabsize, int symtabsecnum) 344 { 345 int i; 346 int nsyms; 347 int cursym; 348 Elf_Sym *tmpsymtab; 349 Symmap *symmap; 350 351 352 nsyms = symtabsize / sizeof(Elf_Sym); 353 354 tmpsymtab = (Elf_Sym *) calloc(1, symtabsize); 355 symmap = (Symmap *) calloc(nsyms, sizeof(Symmap)); 356 if (!tmpsymtab || !symmap) 357 errc(5, ENOMEM, "calloc"); 358 359 bcopy(symtab, tmpsymtab, symtabsize); 360 361 cursym = 1; 362 for (i = 1; i < nsyms; i++) { 363 if ((tmpsymtab[i].st_info & 0xf0) == 0x00) { 364 #ifdef DEBUG 365 printf("copying l o%d n%d <%s>\n", i, cursym, 366 get_str(tmpsymtab[i].st_name)); 367 #endif 368 bcopy(&(tmpsymtab[i]), &(symtab[cursym]), 369 sizeof(Elf_Sym)); 370 symmap[i] = cursym; 371 cursym++; 372 } 373 } 374 symsect->sh_info = cursym; 375 for (i = 1; i < nsyms; i++) { 376 if ((tmpsymtab[i].st_info & 0xf0) != 0x00) { 377 #ifdef DEBUG 378 printf("copying nl o%d n%d <%s>\n", i, cursym, 379 get_str(tmpsymtab[i].st_name)); 380 #endif 381 bcopy(&(tmpsymtab[i]), &(symtab[cursym]), 382 sizeof(Elf_Sym)); 383 symmap[i] = cursym; 384 cursym++; 385 } 386 } 387 if (cursym != nsyms) { 388 printf("miscounted symbols somewhere c %d n %d \n", 389 cursym, nsyms); 390 exit(5); 391 } 392 renum_reloc_syms(ehdr, symmap, symtabsecnum); 393 free(tmpsymtab); 394 free(symmap); 395 } 396 397 void 398 renum_reloc_syms(Elf_Ehdr * ehdr, Symmap * symmap, int symtabsecnum) 399 { 400 Elf_Shdr *pshdr; 401 int i, j; 402 int num_reloc; 403 Elf_Rel *prel; 404 Elf_RelA *prela; 405 int symnum; 406 407 for (i = 0; i < ehdr->e_shnum; i++) { 408 pshdr = (Elf_Shdr *) (pexe + ehdr->e_shoff + 409 (i * ehdr->e_shentsize)); 410 if ((pshdr->sh_type == SHT_RELA) && 411 pshdr->sh_link == symtabsecnum) { 412 413 #ifdef DEBUG 414 printf("section %d has rela relocations in symtab\n", i); 415 #endif 416 prela = (Elf_RelA *) (pexe + pshdr->sh_offset); 417 num_reloc = pshdr->sh_size / sizeof(Elf_RelA); 418 for (j = 0; j < num_reloc; j++) { 419 symnum = ELF_R_SYM(prela[j].r_info); 420 #ifdef DEBUG 421 printf("sym num o %d n %d\n", symnum, 422 symmap[symnum]); 423 #endif 424 prela[j].r_info = ELF_R_INFO(symmap[symnum], 425 ELF_R_TYPE(prela[j].r_info)); 426 } 427 } 428 if ((pshdr->sh_type == SHT_REL) && 429 pshdr->sh_link == symtabsecnum) { 430 #ifdef DEBUG 431 printf("section %d has rel relocations in symtab\n", i); 432 #endif 433 prel = (Elf_Rel *) (pexe + pshdr->sh_offset); 434 num_reloc = pshdr->sh_size / sizeof(Elf_Rel); 435 for (j = 0; j < num_reloc; j++) { 436 symnum = ELF_R_SYM(prel[j].r_info); 437 #ifdef DEBUG 438 printf("sym num o %d n %d\n", symnum, 439 symmap[symnum]); 440 #endif 441 prel[j].r_info = ELF_R_INFO(symmap[symnum], 442 ELF_R_TYPE(prel[j].r_info)); 443 } 444 } 445 } 446 447 } 448 #endif /* _NLIST_DO_ELF */ 449