1 /* $OpenBSD: elf_hide.c,v 1.11 2017/10/29 08:45:53 mpi 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
33 #include <elf.h>
34 #include <err.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <unistd.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include "mangle.h"
42
43 extern int elf_mangle;
44
45 void load_strtab(Elf_Ehdr * pehdr, char *pexe);
46 void dump_strtab(void);
47 char *get_str(int indx);
48
49 void load_symtab(Elf_Ehdr * pehdr, char *pexe);
50 void dump_symtab(Elf_Shdr * symsect, Elf_Sym * symtab, int symtabsize);
51 void fprint_str(FILE * channel, int indx);
52
53 void load_shstr_tab(Elf_Ehdr * pehdr, char *pexe);
54 char *get_shstr(int indx);
55 void fprint_shstr(FILE * channel, int indx);
56
57 void hide_sym(Elf_Ehdr * ehdr, Elf_Shdr * symsect,
58 Elf_Sym * symtab, int symtabsize, int symtabsecnum);
59 void reorder_syms(Elf_Ehdr * ehdr, Elf_Shdr * symsect,
60 Elf_Sym * symtab, int symtabsize, int symtabsecnum);
61 typedef long Symmap;
62 void renum_reloc_syms(Elf_Ehdr * ehdr, Symmap * symmap,
63 int symtabsecnum);
64 void elf_hide(int pfile, char *p);
65
66
67 char *pexe;
68
69 void
elf_hide(int pfile,char * p)70 elf_hide(int pfile, char *p)
71 {
72 Elf_Ehdr *pehdr;
73 #ifdef DEBUG
74 Elf_Shdr *pshdr;
75 Elf_Phdr *pphdr;
76 int i;
77 #endif
78
79 pexe = p;
80 pehdr = (Elf_Ehdr *) pexe;
81
82 #ifdef DEBUG
83 printf("elf header\n");
84 printf("e_type %x\n", pehdr->e_type);
85 printf("e_machine %x\n", pehdr->e_machine);
86 printf("e_version %x\n", pehdr->e_version);
87 printf("e_entry %x\n", pehdr->e_entry);
88 printf("e_phoff %x\n", pehdr->e_phoff);
89 printf("e_shoff %x\n", pehdr->e_shoff);
90 printf("e_flags %x\n", pehdr->e_flags);
91 printf("e_ehsize %x\n", pehdr->e_ehsize);
92 printf("e_phentsize %x\n", pehdr->e_phentsize);
93 printf("e_phnum %x\n", pehdr->e_phnum);
94 printf("e_shentsize %x\n", pehdr->e_shentsize);
95 printf("e_shnum %x\n", pehdr->e_shnum);
96 printf("e_shstrndx %x\n", pehdr->e_shstrndx);
97 #endif
98
99 load_shstr_tab(pehdr, pexe);
100 #ifdef DEBUG
101 for (i = 0; i < pehdr->e_shnum; i++) {
102 pshdr = (Elf_Phdr *) (pexe + pehdr->e_shoff +
103 (i * pehdr->e_shentsize));
104
105 printf("section header %d\n", i);
106 printf("sh_name %x ", pshdr->sh_name);
107 fprint_shstr(stdout, pshdr->sh_name);
108 printf("\n");
109 printf("sh_type %x\n", pshdr->sh_type);
110 printf("sh_flags %x\n", pshdr->sh_flags);
111 printf("sh_addr %x\n", pshdr->sh_addr);
112 printf("sh_offset %x\n", pshdr->sh_offset);
113 printf("sh_size %x\n", pshdr->sh_size);
114 printf("sh_link %x\n", pshdr->sh_link);
115 printf("sh_info %x\n", pshdr->sh_info);
116 printf("sh_addralign %x\n", pshdr->sh_addralign);
117 printf("sh_entsize %x\n", pshdr->sh_entsize);
118 }
119 #endif /* DEBUG */
120
121 #ifdef DEBUG
122 for (i = 0; i < pehdr->e_phnum; i++) {
123 pshdr = (Elf_Phdr *) (pexe + pehdr->e_phoff +
124 (i * pehdr->e_phentsize));
125
126 printf("program header %d\n", i);
127 printf("p_type %x\n", pphdr->p_type);
128 printf("p_offset %x\n", pphdr->p_offset);
129 printf("p_vaddr %x\n", pphdr->p_vaddr);
130 printf("p_paddr %x\n", pphdr->p_paddr);
131 printf("p_filesz %x\n", pphdr->p_filesz);
132 printf("p_memsz %x\n", pphdr->p_memsz);
133 printf("p_flags %x\n", pphdr->p_flags);
134 printf("p_align %x\n", pphdr->p_align);
135 }
136 #endif /* DEBUG */
137 #if 0
138 for (i = 0; i < pehdr->e_shnum; i++) {
139 pshdr = (Elf_Phdr *) (pexe + pehdr->e_shoff +
140 (i * pehdr->e_shentsize));
141 if (strcmp(".strtab", get_shstr(pshdr->sh_name)) == 0)
142 break;
143 }
144 fprint_shstr(stdout, pshdr->sh_name);
145 printf("\n");
146 #endif
147
148 load_strtab(pehdr, pexe);
149 load_symtab(pehdr, pexe);
150 close(pfile);
151 }
152 char *shstrtab;
153
154 void
load_shstr_tab(Elf_Ehdr * pehdr,char * pexe)155 load_shstr_tab(Elf_Ehdr * pehdr, char *pexe)
156 {
157 Elf_Shdr *pshdr;
158 shstrtab = NULL;
159 if (pehdr->e_shstrndx == 0)
160 return;
161 pshdr = (Elf_Shdr *) (pexe + pehdr->e_shoff +
162 (pehdr->e_shstrndx * pehdr->e_shentsize));
163
164 shstrtab = (char *) (pexe + pshdr->sh_offset);
165 }
166
167 void
fprint_shstr(FILE * channel,int indx)168 fprint_shstr(FILE * channel, int indx)
169 {
170 if (shstrtab != NULL)
171 fprintf(channel, "\"%s\"", &(shstrtab[indx]));
172 }
173
174 char *
get_shstr(int indx)175 get_shstr(int indx)
176 {
177 return &(shstrtab[indx]);
178 }
179
180 void
load_symtab(Elf_Ehdr * pehdr,char * pexe)181 load_symtab(Elf_Ehdr * pehdr, char *pexe)
182 {
183 Elf_Sym *symtab;
184 Elf_Shdr *symsect;
185 int symtabsize;
186 Elf_Shdr *psymshdr;
187 Elf_Shdr *pshdr;
188 #ifdef DEBUG
189 char *shname;
190 #endif
191 int i;
192
193 symtab = NULL;
194 for (i = 0; i < pehdr->e_shnum; i++) {
195 pshdr = (Elf_Shdr *) (pexe + pehdr->e_shoff +
196 (i * pehdr->e_shentsize));
197 if (SHT_REL != pshdr->sh_type && SHT_RELA != pshdr->sh_type)
198 continue;
199 psymshdr = (Elf_Shdr *) (pexe + pehdr->e_shoff +
200 (pshdr->sh_link * pehdr->e_shentsize));
201 #ifdef DEBUG
202 fprint_shstr(stdout, pshdr->sh_name);
203 printf("\n");
204 #endif
205 symtab = (Elf_Sym *) (pexe + psymshdr->sh_offset);
206 symsect = psymshdr;
207 symtabsize = psymshdr->sh_size;
208
209 #ifdef DEBUG
210 dump_symtab(symsect, symtab, symtabsize);
211 #endif
212 hide_sym(pehdr, symsect, symtab, symtabsize, pshdr->sh_link);
213 }
214
215 }
216
217 void
dump_symtab(Elf_Shdr * symsect,Elf_Sym * symtab,int symtabsize)218 dump_symtab(Elf_Shdr * symsect, Elf_Sym * symtab, int symtabsize)
219 {
220 int i;
221 Elf_Sym *psymtab;
222
223 for (i = 0; i < (symtabsize / sizeof(Elf_Sym)); i++) {
224 psymtab = &(symtab[i]);
225 if ((psymtab->st_info & 0xf0) == 0x10 &&
226 (psymtab->st_shndx != SHN_UNDEF)) {
227 printf("symbol %d:\n", i);
228 printf("st_name %x \"%s\"\n", psymtab->st_name,
229 get_str(psymtab->st_name));
230 printf("st_value %llx\n", (unsigned long long)psymtab->st_value);
231 printf("st_size %llx\n", (unsigned long long)psymtab->st_size);
232 printf("st_info %x\n", psymtab->st_info);
233 printf("st_other %x\n", psymtab->st_other);
234 printf("st_shndx %x\n", psymtab->st_shndx);
235 }
236 }
237 }
238
239 char *strtab;
240 int strtabsize;
241 void
load_strtab(Elf_Ehdr * pehdr,char * pexe)242 load_strtab(Elf_Ehdr * pehdr, char *pexe)
243 {
244 Elf_Shdr *pshdr = NULL;
245 char *shname;
246 int i;
247 strtab = NULL;
248 for (i = 0; i < pehdr->e_shnum; i++) {
249 pshdr = (Elf_Shdr *) (pexe + pehdr->e_shoff +
250 (i * pehdr->e_shentsize));
251
252 shname = get_shstr(pshdr->sh_name);
253 if (strcmp(".strtab", shname) == 0)
254 break;
255 }
256 #ifdef DEBUG
257 fprint_shstr(stdout, pshdr->sh_name);
258 printf("\n");
259 #endif
260
261 strtab = (char *) (pexe + pshdr->sh_offset);
262
263 strtabsize = pshdr->sh_size;
264
265 #ifdef DEBUG
266 dump_strtab();
267 #endif
268 }
269
270 void
dump_strtab()271 dump_strtab()
272 {
273 int index;
274 char *pstr;
275 char *pnstr;
276 int i = 0;
277 index = 0;
278 pstr = strtab;
279 while (index < strtabsize) {
280 printf("string %x: \"%s\"\n", i, pstr);
281 pnstr = pstr + strlen(pstr) + 1;
282 index = pnstr - strtab;
283 pstr = pnstr;
284 i++;
285 }
286
287 }
288
289 void
fprint_str(FILE * channel,int indx)290 fprint_str(FILE * channel, int indx)
291 {
292 if (strtab != NULL)
293 fprintf(channel, "\"%s\"", &(strtab[indx]));
294 }
295
296 char *
get_str(int indx)297 get_str(int indx)
298 {
299 return &(strtab[indx]);
300 }
301
302 int in_keep_list(char *symbol);
303
304 void
hide_sym(Elf_Ehdr * ehdr,Elf_Shdr * symsect,Elf_Sym * symtab,int symtabsize,int symtabsecnum)305 hide_sym(Elf_Ehdr * ehdr, Elf_Shdr * symsect,
306 Elf_Sym * symtab, int symtabsize, int symtabsecnum)
307 {
308 int i;
309 unsigned char info;
310 Elf_Sym *psymtab;
311
312 for (i = 0; i < (symtabsize / sizeof(Elf_Sym)); i++) {
313 psymtab = &(symtab[i]);
314 if ((psymtab->st_info & 0xf0) == 0x10 &&
315 (psymtab->st_shndx != SHN_UNDEF)) {
316 if (in_keep_list(get_str(psymtab->st_name)))
317 continue;
318 #ifdef DEBUG
319 printf("symbol %d:\n", i);
320 printf("st_name %x \"%s\"\n", psymtab->st_name,
321 get_str(psymtab->st_name));
322 printf("st_info %x\n", psymtab->st_info);
323 #endif
324 if (!elf_mangle) {
325 info = psymtab->st_info;
326 info = info & 0xf;
327 psymtab->st_info = info;
328 } else {
329 mangle_str(get_str(psymtab->st_name));
330 }
331 #ifdef DEBUG
332 printf("st_info %x\n", psymtab->st_info);
333 #endif
334 }
335 }
336 reorder_syms(ehdr, symsect, symtab, symtabsize, symtabsecnum);
337 }
338
339 void
reorder_syms(Elf_Ehdr * ehdr,Elf_Shdr * symsect,Elf_Sym * symtab,int symtabsize,int symtabsecnum)340 reorder_syms(Elf_Ehdr * ehdr, Elf_Shdr * symsect,
341 Elf_Sym * symtab, int symtabsize, int symtabsecnum)
342 {
343 int i;
344 int nsyms;
345 int cursym;
346 Elf_Sym *tmpsymtab;
347 Symmap *symmap;
348
349
350 nsyms = symtabsize / sizeof(Elf_Sym);
351
352 tmpsymtab = calloc(1, symtabsize);
353 symmap = calloc(nsyms, sizeof(Symmap));
354 if (!tmpsymtab || !symmap)
355 errc(5, ENOMEM, "calloc");
356
357 bcopy(symtab, tmpsymtab, symtabsize);
358
359 cursym = 1;
360 for (i = 1; i < nsyms; i++) {
361 if ((tmpsymtab[i].st_info & 0xf0) == 0x00) {
362 #ifdef DEBUG
363 printf("copying l o%d n%d <%s>\n", i, cursym,
364 get_str(tmpsymtab[i].st_name));
365 #endif
366 bcopy(&(tmpsymtab[i]), &(symtab[cursym]),
367 sizeof(Elf_Sym));
368 symmap[i] = cursym;
369 cursym++;
370 }
371 }
372 symsect->sh_info = cursym;
373 for (i = 1; i < nsyms; i++) {
374 if ((tmpsymtab[i].st_info & 0xf0) != 0x00) {
375 #ifdef DEBUG
376 printf("copying nl o%d n%d <%s>\n", i, cursym,
377 get_str(tmpsymtab[i].st_name));
378 #endif
379 bcopy(&(tmpsymtab[i]), &(symtab[cursym]),
380 sizeof(Elf_Sym));
381 symmap[i] = cursym;
382 cursym++;
383 }
384 }
385 if (cursym != nsyms) {
386 printf("miscounted symbols somewhere c %d n %d \n",
387 cursym, nsyms);
388 exit(5);
389 }
390 renum_reloc_syms(ehdr, symmap, symtabsecnum);
391 free(tmpsymtab);
392 free(symmap);
393 }
394
395 void
renum_reloc_syms(Elf_Ehdr * ehdr,Symmap * symmap,int symtabsecnum)396 renum_reloc_syms(Elf_Ehdr * ehdr, Symmap * symmap, int symtabsecnum)
397 {
398 Elf_Shdr *pshdr;
399 int i, j;
400 int num_reloc;
401 Elf_Rel *prel;
402 Elf_RelA *prela;
403 int symnum;
404
405 for (i = 0; i < ehdr->e_shnum; i++) {
406 pshdr = (Elf_Shdr *) (pexe + ehdr->e_shoff +
407 (i * ehdr->e_shentsize));
408 if ((pshdr->sh_type == SHT_RELA) &&
409 pshdr->sh_link == symtabsecnum) {
410
411 #ifdef DEBUG
412 printf("section %d has rela relocations in symtab\n", i);
413 #endif
414 prela = (Elf_RelA *) (pexe + pshdr->sh_offset);
415 num_reloc = pshdr->sh_size / sizeof(Elf_RelA);
416 for (j = 0; j < num_reloc; j++) {
417 symnum = ELF_R_SYM(prela[j].r_info);
418 #ifdef DEBUG
419 printf("sym num o %d n %d\n", symnum,
420 symmap[symnum]);
421 #endif
422 prela[j].r_info = ELF_R_INFO(symmap[symnum],
423 ELF_R_TYPE(prela[j].r_info));
424 }
425 }
426 if ((pshdr->sh_type == SHT_REL) &&
427 pshdr->sh_link == symtabsecnum) {
428 #ifdef DEBUG
429 printf("section %d has rel relocations in symtab\n", i);
430 #endif
431 prel = (Elf_Rel *) (pexe + pshdr->sh_offset);
432 num_reloc = pshdr->sh_size / sizeof(Elf_Rel);
433 for (j = 0; j < num_reloc; j++) {
434 symnum = ELF_R_SYM(prel[j].r_info);
435 #ifdef DEBUG
436 printf("sym num o %d n %d\n", symnum,
437 symmap[symnum]);
438 #endif
439 prel[j].r_info = ELF_R_INFO(symmap[symnum],
440 ELF_R_TYPE(prel[j].r_info));
441 }
442 }
443 }
444
445 }
446