Exemplo n.º 1
0
Arquivo: pe.c Projeto: HarryR/sanos
static int pe_write(struct pe_info *pe) {
  int i;
  int fd;
  FILE *op;
  FILE *stubfile;
  char *stub;
  int stub_size;
  DWORD file_offset, r;
  Section *s;

  if (pe->stub) {
    stubfile = fopen(pe->stub, "rb");
    if (stubfile == NULL) {
      error_noabort("could not read '%s': %s", pe->stub, strerror(errno));
      return 1;
    }
    fseek(stubfile, 0, SEEK_END);
    stub_size = ftell(stubfile);
    fseek(stubfile, 0, SEEK_SET);
    if (stub_size < sizeof(IMAGE_DOS_HEADER)) {
      error_noabort("invalid stub (%d bytes): %s", stub_size, pe->stub);
      return 1;
    }
    stub = tcc_malloc(stub_size);
    if (fread(stub, 1, stub_size, stubfile) != stub_size) {
      error_noabort("error reading stub '%s': %s", pe->stub, strerror(errno));
      return 1;
    }
    fclose(stubfile);
  } else {
    stub_size = DOSSTUB_SIZE + sizeof(IMAGE_DOS_HEADER);
    stub = tcc_malloc(stub_size);
    memcpy(stub, &pe_doshdr, sizeof(IMAGE_DOS_HEADER));
    memcpy(stub + sizeof(IMAGE_DOS_HEADER), pe_dosstub, DOSSTUB_SIZE);
  }
  ((PIMAGE_DOS_HEADER) stub)->e_lfanew = stub_size;

  fd = open(pe->filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0777);
  if (fd < 0) {
    error_noabort("could not write '%s': %s", pe->filename, strerror(errno));
    return 1;
  }
  op = fdopen(fd, "wb");

  pe->sizeofheaders = 
    pe_file_align(pe,
      stub_size +
      sizeof(DWORD) + 
      sizeof(IMAGE_FILE_HEADER) +
      sizeof(IMAGE_OPTIONAL_HEADER) +
      pe->sec_count * sizeof (IMAGE_SECTION_HEADER));

  file_offset = pe->sizeofheaders;
  pe_fpad(op, file_offset, 0);

  if (verbose == 2) {
    printf("------------------------------------\n  virt   file   size  ord section" "\n");
  }

  for (i = 0; i < pe->sec_count; ++i) {
    struct section_info *si = pe->sec_info + i;
    const char *sh_name = si->name;
    unsigned long addr = si->sh_addr - pe->imagebase;
    unsigned long size = si->sh_size;
    IMAGE_SECTION_HEADER *psh = &si->ish;

    if (verbose == 2) {
      printf("%6lx %6lx %6lx %4d %s\n", addr, file_offset, size, si->ord, sh_name);
    }

    switch (si->cls) {
      case sec_text:
        pe_opthdr.BaseOfCode = addr;
        pe_opthdr.SizeOfCode += size;
        pe_opthdr.AddressOfEntryPoint = ((Elf32_Sym *) symtab_section->data)[pe->start_sym_index].st_value - pe->imagebase;
        break;

      case sec_data:
        pe_opthdr.BaseOfData = addr;
        pe_opthdr.SizeOfInitializedData += size;
        break;

      case sec_bss:
        pe_opthdr.SizeOfUninitializedData += size;
        break;

      case sec_reloc:
        pe_set_datadir(IMAGE_DIRECTORY_ENTRY_BASERELOC, addr, size);
        break;

      case sec_rsrc:
        pe_set_datadir(IMAGE_DIRECTORY_ENTRY_RESOURCE, addr, size);
        break;

      case sec_stab:
        break;
    }

    if (pe->thunk == pe->s1->sections[si->ord]) {
      if (pe->imp_size) {
        pe_set_datadir(IMAGE_DIRECTORY_ENTRY_IMPORT, pe->imp_offs + addr, pe->imp_size);
        pe_set_datadir(IMAGE_DIRECTORY_ENTRY_IAT, pe->iat_offs + addr, pe->iat_size);
      }
      if (pe->exp_size) {
        pe_set_datadir(IMAGE_DIRECTORY_ENTRY_EXPORT, pe->exp_offs + addr, pe->exp_size);
      }
    }

    strcpy((char *) psh->Name, sh_name);
    psh->Characteristics = pe_sec_flags[si->cls];
    psh->VirtualAddress = addr;
    psh->Misc.VirtualSize = size;
    pe_opthdr.SizeOfImage = umax(pe_virtual_align(size + addr), pe_opthdr.SizeOfImage); 

    if (si->sh_size) {
      psh->PointerToRawData = r = file_offset;
      for (s = si->first; s; s = s->next) {
        if (s->sh_type != SHT_NOBITS) {
          file_offset = align(file_offset, s->sh_addralign);
          pe_fpad(op, file_offset, si->cls == sec_text ? 0x90 : 0x00);
          fwrite(s->data, 1, s->data_offset, op);
          file_offset += s->data_offset;
        }
      }
      file_offset = pe_file_align(pe, file_offset);
      psh->SizeOfRawData = file_offset - r;
      pe_fpad(op, file_offset, 0);
    }
  }

  pe_filehdr.TimeDateStamp = time(NULL);
  pe_filehdr.NumberOfSections = pe->sec_count;
  pe_filehdr.Characteristics = do_debug ? 0x0102 : 0x030E;
  pe_opthdr.SizeOfHeaders = pe->sizeofheaders;
  pe_opthdr.ImageBase = pe->imagebase;
  pe_opthdr.FileAlignment = pe->filealign;
  if (pe->type == PE_DLL) {
    pe_filehdr.Characteristics = do_debug ? 0x2102 : 0x230E;
  } else if (pe->type != PE_GUI) {
    pe_opthdr.Subsystem = 3;
  }
  if (!pe->reloc) pe_filehdr.Characteristics |= 1;
  if (pe->s1->noshare) pe_filehdr.Characteristics |= 0x4000;

  fseek(op, 0, SEEK_SET);
  fwrite(stub,  1, stub_size, op);
  fwrite(&pe_ntsig,  1, sizeof pe_ntsig, op);
  fwrite(&pe_filehdr,  1, sizeof pe_filehdr, op);
  fwrite(&pe_opthdr,  1, sizeof pe_opthdr, op);
  for (i = 0; i < pe->sec_count; ++i) {
    fwrite(&pe->sec_info[i].ish, 1, sizeof(IMAGE_SECTION_HEADER), op);
  }
  fclose(op);

  if (verbose == 2) {
    printf("------------------------------------\n");
  }
  if (verbose) {
    printf("<- %s (%lu bytes)\n", pe->filename, file_offset);
  }

  tcc_free(stub);
  return 0;
}
Exemplo n.º 2
0
/*----------------------------------------------------------------------------*/
ST_FN int pe_write(struct pe_info *pe)
{
    int i;
    FILE *op;
    DWORD file_offset, r;

    op = fopen(pe->filename, "wb");
    if (NULL == op) {
        error_noabort("could not write '%s': %s", pe->filename, strerror(errno));
        return 1;
    }

    pe->sizeofheaders = pe_file_align(
        sizeof pe_header
        + pe->sec_count * sizeof (IMAGE_SECTION_HEADER)
        );

    file_offset = pe->sizeofheaders;
    pe_fpad(op, file_offset);

    if (2 == pe->s1->verbose)
        printf("-------------------------------"
               "\n  virt   file   size  section" "\n");

    for (i = 0; i < pe->sec_count; ++i) {
        struct section_info *si = pe->sec_info + i;
        const char *sh_name = si->name;
        unsigned long addr = si->sh_addr - pe->imagebase;
        unsigned long size = si->sh_size;
        IMAGE_SECTION_HEADER *psh = &si->ish;

        if (2 == pe->s1->verbose)
            printf("%6lx %6lx %6lx  %s\n",
                addr, file_offset, size, sh_name);

        switch (si->cls) {
            case sec_text:
                pe_header.opthdr.BaseOfCode = addr;
                pe_header.opthdr.AddressOfEntryPoint = addr + pe->start_addr;
                break;

            case sec_data:
                pe_header.opthdr.BaseOfData = addr;
                break;

            case sec_bss:
                break;

            case sec_reloc:
                pe_set_datadir(IMAGE_DIRECTORY_ENTRY_BASERELOC, addr, size);
                break;

            case sec_rsrc:
                pe_set_datadir(IMAGE_DIRECTORY_ENTRY_RESOURCE, addr, size);
                break;

            case sec_stab:
                break;
        }

        if (pe->thunk == pe->s1->sections[si->ord]) {
            if (pe->imp_size) {
                pe_set_datadir(IMAGE_DIRECTORY_ENTRY_IMPORT,
                    pe->imp_offs + addr, pe->imp_size);
                pe_set_datadir(IMAGE_DIRECTORY_ENTRY_IAT,
                    pe->iat_offs + addr, pe->iat_size);
            }
            if (pe->exp_size) {
                pe_set_datadir(IMAGE_DIRECTORY_ENTRY_EXPORT,
                    pe->exp_offs + addr, pe->exp_size);
            }
        }

        strcpy((char*)psh->Name, sh_name);

        psh->Characteristics = pe_sec_flags[si->cls];
        psh->VirtualAddress = addr;
        psh->Misc.VirtualSize = size;
        pe_header.opthdr.SizeOfImage =
            umax(pe_virtual_align(size + addr), pe_header.opthdr.SizeOfImage); 

        if (si->data_size) {
            psh->PointerToRawData = r = file_offset;
            fwrite(si->data, 1, si->data_size, op);
            file_offset = pe_file_align(file_offset + si->data_size);
            psh->SizeOfRawData = file_offset - r;
            pe_fpad(op, file_offset);
        }
    }

    // pe_header.filehdr.TimeDateStamp = time(NULL);
    pe_header.filehdr.NumberOfSections = pe->sec_count;
    pe_header.opthdr.SizeOfHeaders = pe->sizeofheaders;
    pe_header.opthdr.ImageBase = pe->imagebase;
    if (PE_DLL == pe->type)
        pe_header.filehdr.Characteristics = 0x230E;
    else if (PE_GUI != pe->type)
        pe_header.opthdr.Subsystem = 3;

    fseek(op, SEEK_SET, 0);
    fwrite(&pe_header,  1, sizeof pe_header, op);
    for (i = 0; i < pe->sec_count; ++i)
        fwrite(&pe->sec_info[i].ish, 1, sizeof(IMAGE_SECTION_HEADER), op);
    fclose (op);

    if (2 == pe->s1->verbose)
        printf("-------------------------------\n");
    if (pe->s1->verbose)
        printf("<- %s (%lu bytes)\n", pe->filename, file_offset);

    return 0;
}