- Timestamp:
- Jun 20, 2006, 10:24:47 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/sstrip.c
r1 r48 3 3 */ 4 4 5 /* #include "config_xor.h" */ 5 /* Modified for portability and 64bit/32bit elf executables, Rainer Wichmann */ 6 7 #include "config.h" 6 8 7 9 #include <stdio.h> … … 14 16 #if !defined(__ia64) && !defined(__ia64__) && !defined(__itanium__) && \ 15 17 !defined(__alpha) && !defined(__alpha__) && \ 16 (defined(__linux__) || defined(__FreeBSD__)) && \ 17 (defined(__i386__) || defined(__i386) || defined(i386)) 18 (defined(HAVE_ELF_H) || defined(HAVE_LINUX_ELF_H)) && \ 19 (defined(__linux__) || defined(__FreeBSD__)) && \ 20 (defined(__i386__) || defined(__i386) || defined(i386)) 18 21 19 22 /* || defined(__sun) || defined(__sun__) || defined(sun) */ 20 23 21 #if defined(__linux__) 24 25 #if defined(HAVE_ELF_H) 26 #include <elf.h> 27 #else 22 28 #include <linux/elf.h> 23 #else24 #include <elf.h>25 29 #endif 26 30 … … 30 34 #endif 31 35 32 #if ELF_CLASS == ELFCLASS32 33 #define Elf_Ehdr Elf32_Ehdr 34 #define Elf_Phdr Elf32_Phdr 35 #else 36 #define Elf_Ehdr Elf64_Ehdr 37 #define Elf_Phdr Elf64_Phdr 38 #endif 36 #ifndef ELFCLASS32 37 #define ELFCLASS32 1 /* 32-bit objects */ 38 #endif 39 #ifndef ELFCLASS64 40 #define ELFCLASS64 2 /* 64-bit objects */ 41 #endif 42 43 39 44 40 45 /* The name of the program. … … 65 70 * munging. 66 71 */ 67 static int readelfheader (int fd, Elf_Ehdr *ehdr)72 static int readelfheader_32(int fd, Elf32_Ehdr *ehdr) 68 73 { 69 74 errno = 0; … … 81 86 /* Compare the file's class and endianness with the program's. 82 87 */ 88 #ifdef ELF_DATA 83 89 if (ehdr->e_ident[EI_DATA] != ELF_DATA) 84 90 return err("ELF file has different endianness."); 85 if (ehdr->e_ident[EI_CLASS] != ELF_CLASS) 86 return err("ELF file has different word size."); 91 #endif 92 93 if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) 94 return FALSE; 87 95 88 96 /* Check the target architecture. 89 97 */ 98 #ifdef ELF_ARCH 90 99 if (ehdr->e_machine != ELF_ARCH) 91 100 return err("ELF file created for different architecture."); 101 #endif 92 102 93 103 /* Verify the sizes of the ELF header and the program segment 94 104 * header table entries. 95 105 */ 96 if (ehdr->e_ehsize != sizeof(Elf _Ehdr))106 if (ehdr->e_ehsize != sizeof(Elf32_Ehdr)) 97 107 return err("unrecognized ELF header size."); 98 if (ehdr->e_phentsize != sizeof(Elf _Phdr))108 if (ehdr->e_phentsize != sizeof(Elf32_Phdr)) 99 109 return err("unrecognized program segment header size."); 100 110 … … 107 117 } 108 118 119 static int readelfheader_64(int fd, Elf64_Ehdr *ehdr) 120 { 121 errno = 0; 122 123 if (lseek(fd, 0, SEEK_SET)) 124 return ferr("could not rewind file"); 125 126 if (read(fd, ehdr, sizeof *ehdr) != sizeof *ehdr) 127 return ferr("missing or incomplete ELF header."); 128 129 /* Check the ELF signature. 130 */ 131 if (!(ehdr->e_ident[EI_MAG0] == ELFMAG0 && 132 ehdr->e_ident[EI_MAG1] == ELFMAG1 && 133 ehdr->e_ident[EI_MAG2] == ELFMAG2 && 134 ehdr->e_ident[EI_MAG3] == ELFMAG3)) 135 return err("missing ELF signature."); 136 137 /* Compare the file's class and endianness with the program's. 138 */ 139 #ifdef ELF_DATA 140 if (ehdr->e_ident[EI_DATA] != ELF_DATA) 141 return err("ELF file has different endianness."); 142 #endif 143 144 if (ehdr->e_ident[EI_CLASS] != ELFCLASS64) 145 return err("ELF file has different word size."); 146 147 /* Check the target architecture. 148 */ 149 #ifdef ELF_ARCH 150 if (ehdr->e_machine != ELF_ARCH) 151 return err("ELF file created for different architecture."); 152 #endif 153 154 /* Verify the sizes of the ELF header and the program segment 155 * header table entries. 156 */ 157 if (ehdr->e_ehsize != sizeof(Elf64_Ehdr)) 158 return err("unrecognized ELF header size."); 159 if (ehdr->e_phentsize != sizeof(Elf64_Phdr)) 160 return err("unrecognized program segment header size."); 161 162 /* Finally, check the file type. 163 */ 164 if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) 165 return err("not an executable or shared-object library."); 166 167 return TRUE; 168 } 169 109 170 /* readphdrtable() loads the program segment header table into memory. 110 171 */ 111 static int readphdrtable(int fd, Elf_Ehdr const *ehdr, Elf_Phdr **phdrs) 172 static int readphdrtable_32(int fd, Elf32_Ehdr const *ehdr, Elf32_Phdr **phdrs) 173 { 174 size_t size; 175 176 if (!ehdr->e_phoff || !ehdr->e_phnum) 177 return err("ELF file has no program header table."); 178 179 size = ehdr->e_phnum * sizeof **phdrs; 180 if (!(*phdrs = malloc(size))) 181 return err("Out of memory!"); 182 183 errno = 0; 184 if (read(fd, *phdrs, size) != (ssize_t)size) 185 return ferr("missing or incomplete program segment header table."); 186 187 return TRUE; 188 } 189 190 static int readphdrtable_64(int fd, Elf64_Ehdr const *ehdr, Elf64_Phdr **phdrs) 112 191 { 113 192 size_t size; … … 132 211 * is executing, and thus can be safely discarded.) 133 212 */ 134 static int getmemorysize (Elf_Ehdr const *ehdr, Elf_Phdr const *phdrs,135 unsigned long *newsize)136 { 137 Elf _Phdr const *phdr;213 static int getmemorysize_32(Elf32_Ehdr const *ehdr, Elf32_Phdr const *phdrs, 214 unsigned long *newsize) 215 { 216 Elf32_Phdr const *phdr; 138 217 unsigned long size, n; 139 218 int i; 219 220 /* Start by setting the size to include the ELF header and the 221 * complete program segment header table. 222 */ 223 size = ehdr->e_phoff + ehdr->e_phnum * sizeof *phdrs; 224 if (size < sizeof *ehdr) 225 size = sizeof *ehdr; 226 227 /* Then keep extending the size to include whatever data the 228 * program segment header table references. 229 */ 230 for (i = 0, phdr = phdrs ; i < ehdr->e_phnum ; ++i, ++phdr) { 231 if (phdr->p_type != PT_NULL) { 232 n = phdr->p_offset + phdr->p_filesz; 233 if (n > size) 234 size = n; 235 } 236 } 237 238 *newsize = size; 239 return TRUE; 240 } 241 242 static int getmemorysize_64(Elf64_Ehdr const *ehdr, Elf64_Phdr const *phdrs, 243 unsigned long *newsize) 244 { 245 Elf64_Phdr const *phdr; 246 unsigned long size, n; 247 int i; 140 248 141 249 /* Start by setting the size to include the ELF header and the … … 196 304 * included truncated bytes at the end of the file. 197 305 */ 198 static int modifyheaders (Elf_Ehdr *ehdr, Elf_Phdr *phdrs,199 unsigned long newsize)200 { 201 Elf _Phdr *phdr;202 int 306 static int modifyheaders_32(Elf32_Ehdr *ehdr, Elf32_Phdr *phdrs, 307 unsigned long newsize) 308 { 309 Elf32_Phdr *phdr; 310 int i; 203 311 204 312 /* If the section header table is gone, then remove all references … … 228 336 } 229 337 338 static int modifyheaders_64(Elf64_Ehdr *ehdr, Elf64_Phdr *phdrs, 339 unsigned long newsize) 340 { 341 Elf64_Phdr *phdr; 342 int i; 343 344 /* If the section header table is gone, then remove all references 345 * to it in the ELF header. 346 */ 347 if (ehdr->e_shoff >= newsize) { 348 ehdr->e_shoff = 0; 349 ehdr->e_shnum = 0; 350 ehdr->e_shentsize = 0; 351 ehdr->e_shstrndx = 0; 352 } 353 354 /* The program adjusts the file size of any segment that was 355 * truncated. The case of a segment being completely stripped out 356 * is handled separately. 357 */ 358 for (i = 0, phdr = phdrs ; i < ehdr->e_phnum ; ++i, ++phdr) { 359 if (phdr->p_offset >= newsize) { 360 phdr->p_offset = newsize; 361 phdr->p_filesz = 0; 362 } else if (phdr->p_offset + phdr->p_filesz > newsize) { 363 phdr->p_filesz = newsize - phdr->p_offset; 364 } 365 } 366 367 return TRUE; 368 } 369 230 370 /* commitchanges() writes the new headers back to the original file 231 371 * and sets the file to its new size. 232 372 */ 233 static int commitchanges (int fd, Elf_Ehdr const *ehdr, Elf_Phdr *phdrs,234 unsigned long newsize)373 static int commitchanges_32(int fd, Elf32_Ehdr const *ehdr, Elf32_Phdr *phdrs, 374 unsigned long newsize) 235 375 { 236 376 size_t n; … … 275 415 } 276 416 417 static int commitchanges_64(int fd, Elf64_Ehdr const *ehdr, Elf64_Phdr *phdrs, 418 unsigned long newsize) 419 { 420 size_t n; 421 422 /* Save the changes to the ELF header, if any. 423 */ 424 if (lseek(fd, 0, SEEK_SET)) 425 return ferr("could not rewind file"); 426 errno = 0; 427 if (write(fd, ehdr, sizeof *ehdr) != sizeof *ehdr) 428 return err("could not modify file"); 429 430 /* Save the changes to the program segment header table, if any. 431 */ 432 if (lseek(fd, ehdr->e_phoff, SEEK_SET) == (off_t)-1) { 433 err("could not seek in file."); 434 goto warning; 435 } 436 n = ehdr->e_phnum * sizeof *phdrs; 437 if (write(fd, phdrs, n) != (ssize_t)n) { 438 err("could not write to file"); 439 goto warning; 440 } 441 442 /* Eleventh-hour sanity check: don't truncate before the end of 443 * the program segment header table. 444 */ 445 if (newsize < ehdr->e_phoff + n) 446 newsize = ehdr->e_phoff + n; 447 448 /* Chop off the end of the file. 449 */ 450 if (ftruncate(fd, newsize)) { 451 err("could not resize file"); 452 goto warning; 453 } 454 455 return TRUE; 456 457 warning: 458 return err("ELF file may have been corrupted!"); 459 } 460 277 461 /* main() loops over the cmdline arguments, leaving all the real work 278 462 * to the other functions. … … 281 465 { 282 466 int fd; 283 Elf_Ehdr ehdr; 284 Elf_Phdr *phdrs = NULL; 467 int is_32bit_elf; 468 Elf32_Ehdr ehdr32; 469 Elf32_Phdr *phdrs32 = NULL; 470 Elf64_Ehdr ehdr64; 471 Elf64_Phdr *phdrs64 = NULL; 285 472 unsigned long newsize; 286 473 char **arg; … … 308 495 } 309 496 310 if (!(readelfheader(fd, &ehdr) && 311 readphdrtable(fd, &ehdr, &phdrs) && 312 getmemorysize(&ehdr, phdrs, &newsize) && 313 truncatezeros(fd, &newsize) && 314 modifyheaders(&ehdr, phdrs, newsize) && 315 commitchanges(fd, &ehdr, phdrs, newsize))) 497 if (readelfheader_32(fd, &ehdr32)) { 498 is_32bit_elf = TRUE; 499 } 500 else if (readelfheader_64(fd, &ehdr64)) { 501 is_32bit_elf = FALSE; 502 } 503 else { 504 close(fd); 505 return EXIT_FAILURE; 506 } 507 508 if (is_32bit_elf) { 509 if (!(readphdrtable_32(fd, &ehdr32, &phdrs32) && 510 getmemorysize_32(&ehdr32, phdrs32, &newsize) && 511 truncatezeros(fd, &newsize) && 512 modifyheaders_32(&ehdr32, phdrs32, newsize) && 513 commitchanges_32(fd, &ehdr32, phdrs32, newsize))) 316 514 ++failures; 515 } 516 else { 517 if (!(readphdrtable_64(fd, &ehdr64, &phdrs64) && 518 getmemorysize_64(&ehdr64, phdrs64, &newsize) && 519 truncatezeros(fd, &newsize) && 520 modifyheaders_64(&ehdr64, phdrs64, newsize) && 521 commitchanges_64(fd, &ehdr64, phdrs64, newsize))) 522 ++failures; 523 } 317 524 318 525 close(fd);
Note:
See TracChangeset
for help on using the changeset viewer.