1 /*- 2 * Copyright (c) 2015 Kai Wang 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/param.h> 28 #include <assert.h> 29 #include <errno.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <time.h> 33 #include <unistd.h> 34 35 #include "_libpe.h" 36 37 ELFTC_VCSID("$Id: libpe_coff.c 3326 2016-01-16 17:46:17Z kaiwang27 $"); 38 39 int 40 libpe_parse_coff_header(PE *pe, char *hdr) 41 { 42 char tmp[128]; 43 PE_CoffHdr *ch; 44 PE_OptHdr *oh; 45 PE_DataDir *dd; 46 unsigned p, r, s; 47 int i; 48 49 if ((ch = malloc(sizeof(PE_CoffHdr))) == NULL) { 50 errno = ENOMEM; 51 return (-1); 52 } 53 54 PE_READ16(hdr, ch->ch_machine); 55 PE_READ16(hdr, ch->ch_nsec); 56 PE_READ32(hdr, ch->ch_timestamp); 57 PE_READ32(hdr, ch->ch_symptr); 58 PE_READ32(hdr, ch->ch_nsym); 59 PE_READ16(hdr, ch->ch_optsize); 60 PE_READ16(hdr, ch->ch_char); 61 62 pe->pe_ch = ch; 63 64 /* 65 * The Optional header is omitted for object files. 66 */ 67 if (ch->ch_optsize == 0) 68 return (libpe_parse_section_headers(pe)); 69 70 if ((oh = calloc(1, sizeof(PE_OptHdr))) == NULL) { 71 errno = ENOMEM; 72 return (-1); 73 } 74 pe->pe_oh = oh; 75 76 #define READ_OPT(n) \ 77 do { \ 78 /* \ 79 * Since the Optional Header size is variable, we must \ 80 * check if the requested read size will overrun the \ 81 * remaining header bytes. \ 82 */ \ 83 if (p + (n) > ch->ch_optsize) { \ 84 /* Consume the "extra" bytes */ \ 85 r = ch->ch_optsize - p; \ 86 if (read(pe->pe_fd, tmp, r) != (ssize_t) r) { \ 87 pe->pe_flags |= LIBPE_F_BAD_SEC_HEADER;\ 88 return (0); \ 89 } \ 90 return (libpe_parse_section_headers(pe)); \ 91 } \ 92 if (read(pe->pe_fd, tmp, (n)) != (ssize_t) (n)) { \ 93 pe->pe_flags |= LIBPE_F_BAD_OPT_HEADER; \ 94 return (0); \ 95 } \ 96 p += (n); \ 97 } while (0) 98 #define READ_OPT8(v) do { READ_OPT(1); (v) = *tmp; } while(0) 99 #define READ_OPT16(v) do { READ_OPT(2); (v) = le16dec(tmp); } while(0) 100 #define READ_OPT32(v) do { READ_OPT(4); (v) = le32dec(tmp); } while(0) 101 #define READ_OPT64(v) do { READ_OPT(8); (v) = le64dec(tmp); } while(0) 102 103 /* 104 * Read in the Optional header. Size of some fields are depending 105 * on the PE format specified by the oh_magic field. (PE32 or PE32+) 106 */ 107 108 p = 0; 109 READ_OPT16(oh->oh_magic); 110 if (oh->oh_magic == PE_FORMAT_32P) 111 pe->pe_obj = PE_O_PE32P; 112 READ_OPT8(oh->oh_ldvermajor); 113 READ_OPT8(oh->oh_ldverminor); 114 READ_OPT32(oh->oh_textsize); 115 READ_OPT32(oh->oh_datasize); 116 READ_OPT32(oh->oh_bsssize); 117 READ_OPT32(oh->oh_entry); 118 READ_OPT32(oh->oh_textbase); 119 if (oh->oh_magic != PE_FORMAT_32P) { 120 READ_OPT32(oh->oh_database); 121 READ_OPT32(oh->oh_imgbase); 122 } else 123 READ_OPT64(oh->oh_imgbase); 124 READ_OPT32(oh->oh_secalign); 125 READ_OPT32(oh->oh_filealign); 126 READ_OPT16(oh->oh_osvermajor); 127 READ_OPT16(oh->oh_osverminor); 128 READ_OPT16(oh->oh_imgvermajor); 129 READ_OPT16(oh->oh_imgverminor); 130 READ_OPT16(oh->oh_subvermajor); 131 READ_OPT16(oh->oh_subverminor); 132 READ_OPT32(oh->oh_win32ver); 133 READ_OPT32(oh->oh_imgsize); 134 READ_OPT32(oh->oh_hdrsize); 135 READ_OPT32(oh->oh_checksum); 136 READ_OPT16(oh->oh_subsystem); 137 READ_OPT16(oh->oh_dllchar); 138 if (oh->oh_magic != PE_FORMAT_32P) { 139 READ_OPT32(oh->oh_stacksizer); 140 READ_OPT32(oh->oh_stacksizec); 141 READ_OPT32(oh->oh_heapsizer); 142 READ_OPT32(oh->oh_heapsizec); 143 } else { 144 READ_OPT64(oh->oh_stacksizer); 145 READ_OPT64(oh->oh_stacksizec); 146 READ_OPT64(oh->oh_heapsizer); 147 READ_OPT64(oh->oh_heapsizec); 148 } 149 READ_OPT32(oh->oh_ldrflags); 150 READ_OPT32(oh->oh_ndatadir); 151 152 /* 153 * Read in the Data Directories. 154 */ 155 156 if (oh->oh_ndatadir > 0) { 157 if ((dd = calloc(1, sizeof(PE_DataDir))) == NULL) { 158 errno = ENOMEM; 159 return (-1); 160 } 161 pe->pe_dd = dd; 162 163 dd->dd_total = oh->oh_ndatadir < PE_DD_MAX ? oh->oh_ndatadir : 164 PE_DD_MAX; 165 166 for (i = 0; (uint32_t) i < dd->dd_total; i++) { 167 READ_OPT32(dd->dd_e[i].de_addr); 168 READ_OPT32(dd->dd_e[i].de_size); 169 } 170 } 171 172 /* Consume the remaining bytes in the Optional header, if any. */ 173 if (ch->ch_optsize > p) { 174 r = ch->ch_optsize - p; 175 for (; r > 0; r -= s) { 176 s = r > sizeof(tmp) ? sizeof(tmp) : r; 177 if (read(pe->pe_fd, tmp, s) != (ssize_t) s) { 178 pe->pe_flags |= LIBPE_F_BAD_SEC_HEADER; 179 return (0); 180 } 181 } 182 } 183 184 return (libpe_parse_section_headers(pe)); 185 } 186 187 off_t 188 libpe_write_pe_header(PE *pe, off_t off) 189 { 190 char tmp[4]; 191 192 if (pe->pe_cmd == PE_C_RDWR && 193 (pe->pe_flags & LIBPE_F_BAD_PE_HEADER) == 0) { 194 assert(pe->pe_dh != NULL); 195 off = lseek(pe->pe_fd, (off_t) pe->pe_dh->dh_lfanew + 4, 196 SEEK_SET); 197 return (off); 198 } 199 200 /* 201 * PE Header should to be aligned on 8-byte boundary according to 202 * the PE/COFF specification. 203 */ 204 if ((off = libpe_align(pe, off, 8)) < 0) 205 return (-1); 206 207 le32enc(tmp, PE_SIGNATURE); 208 if (write(pe->pe_fd, tmp, sizeof(tmp)) != (ssize_t) sizeof(tmp)) { 209 errno = EIO; 210 return (-1); 211 } 212 213 off += 4; 214 215 pe->pe_flags &= ~LIBPE_F_BAD_PE_HEADER; 216 217 /* Trigger rewrite for the following headers. */ 218 pe->pe_flags |= LIBPE_F_DIRTY_COFF_HEADER; 219 pe->pe_flags |= LIBPE_F_DIRTY_OPT_HEADER; 220 221 return (off); 222 } 223 224 off_t 225 libpe_write_coff_header(PE *pe, off_t off) 226 { 227 char tmp[128], *hdr; 228 PE_CoffHdr *ch; 229 PE_DataDir *dd; 230 PE_OptHdr *oh; 231 PE_Scn *ps; 232 PE_SecHdr *sh; 233 unsigned p; 234 uint32_t reloc_rva, reloc_sz; 235 int i, reloc; 236 237 reloc = 0; 238 reloc_rva = reloc_sz = 0; 239 240 if (pe->pe_cmd == PE_C_RDWR) { 241 assert((pe->pe_flags & LIBPE_F_SPECIAL_FILE) == 0); 242 243 if ((pe->pe_flags & LIBPE_F_DIRTY_COFF_HEADER) == 0 && 244 (pe->pe_flags & LIBPE_F_BAD_COFF_HEADER) == 0) { 245 if (lseek(pe->pe_fd, (off_t) sizeof(PE_CoffHdr), 246 SEEK_CUR) < 0) { 247 errno = EIO; 248 return (-1); 249 } 250 off += sizeof(PE_CoffHdr); 251 assert(pe->pe_ch != NULL); 252 ch = pe->pe_ch; 253 goto coff_done; 254 } 255 256 /* lseek(2) to the offset of the COFF header. */ 257 if (lseek(pe->pe_fd, off, SEEK_SET) < 0) { 258 errno = EIO; 259 return (-1); 260 } 261 } 262 263 if (pe->pe_ch == NULL) { 264 if ((ch = calloc(1, sizeof(PE_CoffHdr))) == NULL) { 265 errno = ENOMEM; 266 return (-1); 267 } 268 pe->pe_ch = ch; 269 270 /* 271 * Default value for ch_machine if not provided by the 272 * application. 273 */ 274 if (pe->pe_obj == PE_O_PE32P) 275 ch->ch_machine = IMAGE_FILE_MACHINE_AMD64; 276 else 277 ch->ch_machine = IMAGE_FILE_MACHINE_I386; 278 279 } else 280 ch = pe->pe_ch; 281 282 if (!ch->ch_timestamp) 283 ch->ch_timestamp = time(NULL); 284 285 if (pe->pe_obj == PE_O_PE32) { 286 if (!ch->ch_optsize) 287 ch->ch_optsize = PE_COFF_OPT_SIZE_32; 288 ch->ch_char |= IMAGE_FILE_EXECUTABLE_IMAGE | 289 IMAGE_FILE_32BIT_MACHINE; 290 } else if (pe->pe_obj == PE_O_PE32P) { 291 if (!ch->ch_optsize) 292 ch->ch_optsize = PE_COFF_OPT_SIZE_32P; 293 ch->ch_char |= IMAGE_FILE_EXECUTABLE_IMAGE | 294 IMAGE_FILE_LARGE_ADDRESS_AWARE; 295 } else 296 ch->ch_optsize = 0; 297 298 /* 299 * COFF line number is deprecated by the PE/COFF 300 * specification. COFF symbol table is deprecated 301 * for executables. 302 */ 303 ch->ch_char |= IMAGE_FILE_LINE_NUMS_STRIPPED; 304 if (pe->pe_obj == PE_O_PE32 || pe->pe_obj == PE_O_PE32P) 305 ch->ch_char |= IMAGE_FILE_LOCAL_SYMS_STRIPPED; 306 307 ch->ch_nsec = pe->pe_nscn; 308 309 STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) { 310 sh = &ps->ps_sh; 311 312 if (ps->ps_ndx == 0xFFFFFFFFU) { 313 ch->ch_symptr = sh->sh_rawptr; 314 ch->ch_nsym = pe->pe_nsym; 315 } 316 317 if (pe->pe_obj == PE_O_PE32 || pe->pe_obj == PE_O_PE32P) { 318 if (ps->ps_ndx == (0xFFFF0000 | PE_DD_BASERELOC) || 319 strncmp(sh->sh_name, ".reloc", strlen(".reloc")) == 320 0) { 321 reloc = 1; 322 reloc_rva = sh->sh_addr; 323 reloc_sz = sh->sh_virtsize; 324 } 325 } 326 } 327 328 if (!reloc) 329 ch->ch_char |= IMAGE_FILE_RELOCS_STRIPPED; 330 331 if (pe->pe_flags & LIBPE_F_BAD_OPT_HEADER) { 332 if (pe->pe_obj == PE_O_PE32) 333 ch->ch_optsize = PE_COFF_OPT_SIZE_32; 334 else if (pe->pe_obj == PE_O_PE32P) 335 ch->ch_optsize = PE_COFF_OPT_SIZE_32P; 336 else 337 ch->ch_optsize = 0; 338 } 339 340 /* 341 * Write the COFF header. 342 */ 343 hdr = tmp; 344 PE_WRITE16(hdr, ch->ch_machine); 345 PE_WRITE16(hdr, ch->ch_nsec); 346 PE_WRITE32(hdr, ch->ch_timestamp); 347 PE_WRITE32(hdr, ch->ch_symptr); 348 PE_WRITE32(hdr, ch->ch_nsym); 349 PE_WRITE16(hdr, ch->ch_optsize); 350 PE_WRITE16(hdr, ch->ch_char); 351 if (write(pe->pe_fd, tmp, sizeof(PE_CoffHdr)) != 352 (ssize_t) sizeof(PE_CoffHdr)) { 353 errno = EIO; 354 return (-1); 355 } 356 357 coff_done: 358 off += sizeof(PE_CoffHdr); 359 pe->pe_flags &= ~LIBPE_F_DIRTY_COFF_HEADER; 360 pe->pe_flags &= ~LIBPE_F_BAD_COFF_HEADER; 361 pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER; 362 363 if (ch->ch_optsize == 0) 364 return (off); 365 366 /* 367 * Write the Optional header. 368 */ 369 370 if (pe->pe_cmd == PE_C_RDWR) { 371 if ((pe->pe_flags & LIBPE_F_DIRTY_OPT_HEADER) == 0 && 372 (pe->pe_flags & LIBPE_F_BAD_OPT_HEADER) == 0) { 373 if (lseek(pe->pe_fd, (off_t) ch->ch_optsize, 374 SEEK_CUR) < 0) { 375 errno = EIO; 376 return (-1); 377 } 378 off += ch->ch_optsize; 379 return (off); 380 } 381 382 } 383 384 if (pe->pe_oh == NULL) { 385 if ((oh = calloc(1, sizeof(PE_OptHdr))) == NULL) { 386 errno = ENOMEM; 387 return (-1); 388 } 389 pe->pe_oh = oh; 390 } else 391 oh = pe->pe_oh; 392 393 if (pe->pe_obj == PE_O_PE32) 394 oh->oh_magic = PE_FORMAT_32; 395 else 396 oh->oh_magic = PE_FORMAT_32P; 397 398 /* 399 * LinkerVersion should not be less than 2.5, which will cause 400 * Windows to complain the executable is invalid in some case. 401 * By default we set LinkerVersion to 2.22 (binutils 2.22) 402 */ 403 if (!oh->oh_ldvermajor && !oh->oh_ldverminor) { 404 oh->oh_ldvermajor = 2; 405 oh->oh_ldverminor = 22; 406 } 407 408 /* 409 * The library always tries to write out all 16 data directories 410 * but the actual data dir written will depend on ch_optsize. 411 */ 412 oh->oh_ndatadir = PE_DD_MAX; 413 414 if (!oh->oh_filealign) 415 oh->oh_filealign = 0x200; 416 if (!oh->oh_secalign) 417 oh->oh_secalign = 0x1000; 418 oh->oh_hdrsize = roundup(off + ch->ch_optsize + pe->pe_nscn * 419 sizeof(PE_SecHdr), oh->oh_filealign); 420 oh->oh_imgsize = roundup(pe->pe_rvamax, oh->oh_secalign); 421 422 #define WRITE_OPT(n) \ 423 do { \ 424 /* \ 425 * Since the Optional Header size is variable, we must \ 426 * check if the requested write size will overrun the \ 427 * remaining header bytes. \ 428 */ \ 429 if (p + (n) > ch->ch_optsize) { \ 430 /* Pad the "extra" bytes */ \ 431 if (libpe_pad(pe, ch->ch_optsize - p) < 0) { \ 432 errno = EIO; \ 433 return (-1); \ 434 } \ 435 goto opt_done; \ 436 } \ 437 if (write(pe->pe_fd, tmp, (n)) != (ssize_t) (n)) { \ 438 errno = EIO; \ 439 return (-1); \ 440 } \ 441 p += (n); \ 442 } while (0) 443 #define WRITE_OPT8(v) do { *tmp = (v); WRITE_OPT(1); } while(0) 444 #define WRITE_OPT16(v) do { le16enc(tmp, (v)); WRITE_OPT(2); } while(0) 445 #define WRITE_OPT32(v) do { le32enc(tmp, (v)); WRITE_OPT(4); } while(0) 446 #define WRITE_OPT64(v) do { le64enc(tmp, (v)); WRITE_OPT(8); } while(0) 447 448 p = 0; 449 WRITE_OPT16(oh->oh_magic); 450 if (oh->oh_magic == PE_FORMAT_32P) 451 pe->pe_obj = PE_O_PE32P; 452 WRITE_OPT8(oh->oh_ldvermajor); 453 WRITE_OPT8(oh->oh_ldverminor); 454 WRITE_OPT32(oh->oh_textsize); 455 WRITE_OPT32(oh->oh_datasize); 456 WRITE_OPT32(oh->oh_bsssize); 457 WRITE_OPT32(oh->oh_entry); 458 WRITE_OPT32(oh->oh_textbase); 459 if (oh->oh_magic != PE_FORMAT_32P) { 460 WRITE_OPT32(oh->oh_database); 461 WRITE_OPT32(oh->oh_imgbase); 462 } else 463 WRITE_OPT64(oh->oh_imgbase); 464 WRITE_OPT32(oh->oh_secalign); 465 WRITE_OPT32(oh->oh_filealign); 466 WRITE_OPT16(oh->oh_osvermajor); 467 WRITE_OPT16(oh->oh_osverminor); 468 WRITE_OPT16(oh->oh_imgvermajor); 469 WRITE_OPT16(oh->oh_imgverminor); 470 WRITE_OPT16(oh->oh_subvermajor); 471 WRITE_OPT16(oh->oh_subverminor); 472 WRITE_OPT32(oh->oh_win32ver); 473 WRITE_OPT32(oh->oh_imgsize); 474 WRITE_OPT32(oh->oh_hdrsize); 475 WRITE_OPT32(oh->oh_checksum); 476 WRITE_OPT16(oh->oh_subsystem); 477 WRITE_OPT16(oh->oh_dllchar); 478 if (oh->oh_magic != PE_FORMAT_32P) { 479 WRITE_OPT32(oh->oh_stacksizer); 480 WRITE_OPT32(oh->oh_stacksizec); 481 WRITE_OPT32(oh->oh_heapsizer); 482 WRITE_OPT32(oh->oh_heapsizec); 483 } else { 484 WRITE_OPT64(oh->oh_stacksizer); 485 WRITE_OPT64(oh->oh_stacksizec); 486 WRITE_OPT64(oh->oh_heapsizer); 487 WRITE_OPT64(oh->oh_heapsizec); 488 } 489 WRITE_OPT32(oh->oh_ldrflags); 490 WRITE_OPT32(oh->oh_ndatadir); 491 492 /* 493 * Write the Data Directories. 494 */ 495 496 if (oh->oh_ndatadir > 0) { 497 if (pe->pe_dd == NULL) { 498 if ((dd = calloc(1, sizeof(PE_DataDir))) == NULL) { 499 errno = ENOMEM; 500 return (-1); 501 } 502 pe->pe_dd = dd; 503 dd->dd_total = PE_DD_MAX; 504 } else 505 dd = pe->pe_dd; 506 507 assert(oh->oh_ndatadir <= PE_DD_MAX); 508 509 if (reloc) { 510 dd->dd_e[PE_DD_BASERELOC].de_addr = reloc_rva; 511 dd->dd_e[PE_DD_BASERELOC].de_size = reloc_sz; 512 } 513 514 for (i = 0; (uint32_t) i < dd->dd_total; i++) { 515 WRITE_OPT32(dd->dd_e[i].de_addr); 516 WRITE_OPT32(dd->dd_e[i].de_size); 517 } 518 } 519 520 /* Pad the remaining bytes in the Optional header, if any. */ 521 if (ch->ch_optsize > p) { 522 if (libpe_pad(pe, ch->ch_optsize - p) < 0) { 523 errno = EIO; 524 return (-1); 525 } 526 } 527 528 opt_done: 529 off += ch->ch_optsize; 530 pe->pe_flags &= ~LIBPE_F_DIRTY_OPT_HEADER; 531 pe->pe_flags &= ~LIBPE_F_BAD_OPT_HEADER; 532 pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER; 533 534 return (off); 535 } 536