// File: /workspace/github_c_makefile_star2_O0/mikeakohn[P]print_pe/build/../src/print_pe.c
// Function: main
int main(int argc, char *argv[])
{
  FILE *in,*out;
  struct dos_header_t dos_header;
  struct file_header_t file_header;
  struct optional_header_t optional_header;
  struct section_header_t section_header;
  uint8_t signature[4];
  char filename[64];
  char pe_filename[1024];
  struct funct_t funct;
  int dump = 0;
  int address_size = 4;
  int t, len;

  printf("\nprint_pe (January 15, 2023) - The DLL, EXE, OCX Analyzer\n");
  printf("Copyright 2005-2022 - Michael Kohn  http://www.mikekohn.net/\n\n");

  if (argc < 2)
  {
    printf(
       "Usage: print_pe [ options ] <input file>\n"
       "       -modify <function> <new return value>  (modify function)\n"
       "       -dump                                  (dump binary sections)\n"
       "\n");
    exit(0);
  }

  filename[0] = 0;
  funct.funct_name[0] = 0;
  funct.funct_ptr = 0;
  funct.file_offset = 0;

  for (t = 1; t < argc; t++)
  {
    if (strcasecmp(argv[t], "-modify") == 0)
    {
      strcpy(funct.funct_name, argv[++t]);
      funct.funct_retvalue = atoi(argv[++t]);
    }
      else
    if (strcasecmp(argv[t], "-dump") == 0)
    {
      dump = 1;
    }
      else
    {
      strcpy(pe_filename, argv[t]);
    }
  }

  in = fopen(pe_filename, "rb");

  if (in == 0)
  {
    printf("Cannot open file %s for reading.\n\n", argv[1]);
    exit(0);
  }

  memset(&optional_header, 0, sizeof(optional_header));

  read_dos_header(in, &dos_header);
  print_dos_header(&dos_header);

  len = dos_header.e_lfanew - ftell(in);

  if (dump == 1)
  {
    out = fopen("dos_code.bin", "wb");

    if (out != NULL)
    {
      for (t = 0; t < len; t++) { putc(getc(in), out); }
      fclose(out);
    }
  }

  if (dos_header.e_lfanew == 0)
  {
    printf("This is a DOS program.\n");
    fclose(in);
    exit(0);
  }

  fseek(in, dos_header.e_lfanew, SEEK_SET);

  read_chars_bin(in, signature, 4);

  if (signature[0] != 'P' || signature[1] != 'E' ||
      signature[2] != 0   || signature[3] != 0)
  {
    printf("This file is not a Microsoft PE format file\n\n");
    fclose(in);
    exit(0);
  }

  printf("Signature: PE00\n\n");

  file_header_read(&file_header, in);
  file_header_print(&file_header);

  if (file_header.SizeOfOptionalHeader != 0)
  {
    const int length = file_header.SizeOfOptionalHeader;

    optional_header_read(&optional_header, in, length);
    optional_header_print(&optional_header);
  }

  if (optional_header.Magic == 0x20b) { address_size = 8; }

  for (t = 0; t < file_header.NumberOfSections; t++)
  {
    section_header_read(&section_header, in);
    section_header_print(&section_header, t);

    if (strncmp(section_header.name, ".text", 5) == 0)
    {
      funct.file_offset = section_header.VirtualAddress - section_header.PointerToRawData;

      //struct _clr_header clr_header;
      //read_clr_header(in, &clr_header, 0x200);
      //print_clr_header(&clr_header);
    }

    if ((section_header.Characteristics & 0x20) != 0)
    {
      if (dump == 1)
      {
        sprintf(filename, "win_code_%d.bin", t);

        rip_binary(
          in,
          filename,
          section_header.PointerToRawData,
          section_header.SizeOfRawData);
      }

      vb_info_print(in, &optional_header, &section_header);
    }
      else
    if (strcmp(section_header.name, ".rsrc") == 0)
    {
      parse_resource_dir(in, &section_header, 0, 0, 0, dump);
    }

    const uint32_t virtual_start = section_header.VirtualAddress;
    const uint32_t virtual_end =
      section_header.VirtualAddress +
      section_header.SizeOfRawData;;

    // Print imports
    if (optional_header.directory_entry[1].size != 0)
    {
      if (optional_header.directory_entry[1].virtual_address >= virtual_start &&
          optional_header.directory_entry[1].virtual_address < virtual_end)
      {
        imports_print(
          in,
          optional_header.directory_entry[1].virtual_address,
          optional_header.directory_entry[1].size,
          address_size,
          &section_header);
      }
    }

    // Print exports
    if (optional_header.directory_entry[0].size != 0)
    {
      if (optional_header.directory_entry[0].virtual_address >= virtual_start &&
          optional_header.directory_entry[0].virtual_address < virtual_end)
      {
        exports_print(
          in,
          optional_header.directory_entry[0].virtual_address,
          optional_header.directory_entry[0].size,
          &section_header,
          &funct);
      }
    }

    // Debug section
    if (optional_header.directory_entry[6].size!= 0)
    {
      if (optional_header.directory_entry[6].virtual_address >= virtual_start &&
          optional_header.directory_entry[6].virtual_address < virtual_end)
      {
#if 0
        debug_section_print(
          in,
          optional_header.directory_entry[6].virtual_address,
          optional_header.directory_entry[6].size,
          &section_header);
#endif
        debug_directory_print(
          in,
          optional_header.directory_entry[6].virtual_address,
          optional_header.directory_entry[6].size,
          &section_header);
      }
    }

    // COM Desc section
    if (optional_header.directory_entry[14].size != 0)
    {
      if (optional_header.directory_entry[14].virtual_address >= virtual_start &&
          optional_header.directory_entry[14].virtual_address < virtual_end)
      {

        int is_dot_net = imports_find(
          in,
          optional_header.directory_entry[1].virtual_address,
          optional_header.directory_entry[1].size,
          address_size,
          &section_header,
          "_CorExeMain");

        if (is_dot_net == 1)
        {
          printf("---------------------------------------------\n");
          printf("COM Descriptor\n");
          printf("---------------------------------------------\n");

          hex_dump(
            in,
            optional_header.directory_entry[14].virtual_address,
            optional_header.directory_entry[14].size,
            &section_header);

          struct _clr_header clr_header;

          read_clr_header(
            in,
            &clr_header,
            optional_header.directory_entry[14].virtual_address,
            optional_header.directory_entry[14].size,
            &section_header);

          print_clr_header(&clr_header);
        }
      }
    }
  }

  fclose(in);

  if (funct.funct_name[0] != 0)
  {
    if (funct.funct_ptr == 0)
    {
      printf("Function %s not found in file.\n", funct.funct_name);
    }
      else
    if (funct.file_offset == 0)
    {
      printf("Function %s is found in file, but couldn't find the .text section.\nThis is a bug in print_pe probably.\n", funct.funct_name);
    }
      else
    {
      funct.funct_ptr = funct.funct_ptr - funct.file_offset;
      printf("Function %s found at %ld in file.\n\n", funct.funct_name, funct.funct_ptr);

      printf("This is experimental and will modify your file.\nDo you really want to change this function to { return %d; } (y/n) ", funct.funct_retvalue);

      t = getchar();

      if (t == 'y')
      {
        FILE *out = fopen(pe_filename, "rb+");
        fseek(out, funct.funct_ptr, SEEK_SET);
        putc(0xb8, out);
        putc((funct.funct_retvalue & 255), out);
        putc(((funct.funct_retvalue >> 8) & 255), out);
        putc(((funct.funct_retvalue >> 16) & 255), out);
        putc(((funct.funct_retvalue >> 24) & 255), out);
        putc(0xc3, out);
        fclose(out);
        printf("Modified!\n");
      }
        else
      {
        printf("Cancelled!\n");
      }
    }
  }

  return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xa80, %rsp            # imm = 0xA80
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl $0x0, -0xa0c(%rbp)
movl $0x4, -0xa10(%rbp)
leaq 0x6d70(%rip), %rdi      # 0xa004
movb $0x0, %al
callq 0x3080
leaq 0x6d9d(%rip), %rdi      # 0xa03f
movb $0x0, %al
callq 0x3080
cmpl $0x2, -0x8(%rbp)
jge 0x32c4
leaq 0x6dc8(%rip), %rdi      # 0xa07e
movb $0x0, %al
callq 0x3080
xorl %edi, %edi
callq 0x3140
movb $0x0, -0x1f0(%rbp)
movb $0x0, -0xa08(%rbp)
movq $0x0, -0x600(%rbp)
movq $0x0, -0x5f8(%rbp)
movl $0x1, -0xa14(%rbp)
movl -0xa14(%rbp), %eax
cmpl -0x8(%rbp), %eax
jge 0x33cd
movq -0x10(%rbp), %rax
movslq -0xa14(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq 0x6e17(%rip), %rsi      # 0xa12e
callq 0x3030
cmpl $0x0, %eax
jne 0x336e
leaq -0xa08(%rbp), %rdi
movq -0x10(%rbp), %rax
movl -0xa14(%rbp), %ecx
addl $0x1, %ecx
movl %ecx, -0xa14(%rbp)
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rsi
callq 0x3050
movq -0x10(%rbp), %rax
movl -0xa14(%rbp), %ecx
addl $0x1, %ecx
movl %ecx, -0xa14(%rbp)
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rdi
callq 0x3120
movl %eax, -0x608(%rbp)
jmp 0x33b7
movq -0x10(%rbp), %rax
movslq -0xa14(%rbp), %rcx
movq (%rax,%rcx,8), %rdi
leaq 0x6db2(%rip), %rsi      # 0xa136
callq 0x3030
cmpl $0x0, %eax
jne 0x339a
movl $0x1, -0xa0c(%rbp)
jmp 0x33b5
leaq -0x5f0(%rbp), %rdi
movq -0x10(%rbp), %rax
movslq -0xa14(%rbp), %rcx
movq (%rax,%rcx,8), %rsi
callq 0x3050
jmp 0x33b7
jmp 0x33b9
movl -0xa14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa14(%rbp)
jmp 0x32f2
leaq -0x5f0(%rbp), %rdi
leaq 0x6d61(%rip), %rsi      # 0xa13c
callq 0x3110
movq %rax, -0x18(%rbp)
cmpq $0x0, -0x18(%rbp)
jne 0x3408
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rsi
leaq 0x6d45(%rip), %rdi      # 0xa13f
movb $0x0, %al
callq 0x3080
xorl %edi, %edi
callq 0x3140
leaq -0x178(%rbp), %rdi
xorl %esi, %esi
movl $0x100, %edx            # imm = 0x100
callq 0x30a0
movq -0x18(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0x51c0
leaq -0x60(%rbp), %rdi
callq 0x5360
movslq -0x24(%rbp), %rax
movq %rax, -0xa78(%rbp)
movq -0x18(%rbp), %rdi
callq 0x30e0
movq %rax, %rcx
movq -0xa78(%rbp), %rax
subq %rcx, %rax
movl %eax, -0xa18(%rbp)
cmpl $0x1, -0xa0c(%rbp)
jne 0x34c7
leaq 0x6cfa(%rip), %rdi      # 0xa162
leaq 0x6d00(%rip), %rsi      # 0xa16f
callq 0x3110
movq %rax, -0x20(%rbp)
cmpq $0x0, -0x20(%rbp)
je 0x34c5
movl $0x0, -0xa14(%rbp)
movl -0xa14(%rbp), %eax
cmpl -0xa18(%rbp), %eax
jge 0x34bc
movq -0x18(%rbp), %rdi
callq 0x3150
movl %eax, %edi
movq -0x20(%rbp), %rsi
callq 0x30c0
movl -0xa14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa14(%rbp)
jmp 0x3489
movq -0x20(%rbp), %rdi
callq 0x3060
jmp 0x34c7
cmpl $0x0, -0x24(%rbp)
jne 0x34eb
leaq 0x6c9e(%rip), %rdi      # 0xa172
movb $0x0, %al
callq 0x3080
movq -0x18(%rbp), %rdi
callq 0x3060
xorl %edi, %edi
callq 0x3140
movq -0x18(%rbp), %rdi
movslq -0x24(%rbp), %rsi
xorl %edx, %edx
callq 0x3100
movq -0x18(%rbp), %rdi
leaq -0x1a8(%rbp), %rsi
movl $0x4, %edx
callq 0x6140
movzbl -0x1a8(%rbp), %eax
cmpl $0x50, %eax
jne 0x353f
movzbl -0x1a7(%rbp), %eax
cmpl $0x45, %eax
jne 0x353f
movzbl -0x1a6(%rbp), %eax
cmpl $0x0, %eax
jne 0x353f
movzbl -0x1a5(%rbp), %eax
cmpl $0x0, %eax
je 0x355d
leaq 0x6c44(%rip), %rdi      # 0xa18a
movb $0x0, %al
callq 0x3080
movq -0x18(%rbp), %rdi
callq 0x3060
xorl %edi, %edi
callq 0x3140
leaq 0x6c54(%rip), %rdi      # 0xa1b8
movb $0x0, %al
callq 0x3080
movq -0x18(%rbp), %rsi
leaq -0x74(%rbp), %rdi
callq 0x5890
leaq -0x74(%rbp), %rdi
callq 0x5930
movzwl -0x64(%rbp), %eax
cmpl $0x0, %eax
je 0x35b6
movzwl -0x64(%rbp), %eax
movl %eax, -0xa1c(%rbp)
movq -0x18(%rbp), %rsi
movl -0xa1c(%rbp), %edx
leaq -0x178(%rbp), %rdi
callq 0x6840
leaq -0x178(%rbp), %rdi
callq 0x6bd0
movzwl -0x178(%rbp), %eax
cmpl $0x20b, %eax            # imm = 0x20B
jne 0x35ce
movl $0x8, -0xa10(%rbp)
movl $0x0, -0xa14(%rbp)
movl -0xa14(%rbp), %eax
movzwl -0x72(%rbp), %ecx
cmpl %ecx, %eax
jge 0x38cb
movq -0x18(%rbp), %rsi
leaq -0x1a4(%rbp), %rdi
callq 0x86f0
movl -0xa14(%rbp), %esi
leaq -0x1a4(%rbp), %rdi
callq 0x87d0
leaq -0x1a4(%rbp), %rdi
leaq 0x6bb0(%rip), %rsi      # 0xa1ca
movl $0x5, %edx
callq 0x3040
cmpl $0x0, %eax
jne 0x363e
movl -0x194(%rbp), %eax
subl -0x18c(%rbp), %eax
movl %eax, %eax
movq %rax, -0x5f8(%rbp)
movl -0x17c(%rbp), %eax
andl $0x20, %eax
cmpl $0x0, %eax
je 0x36a5
cmpl $0x1, -0xa0c(%rbp)
jne 0x368c
leaq -0x1f0(%rbp), %rdi
movl -0xa14(%rbp), %edx
leaq 0x6b67(%rip), %rsi      # 0xa1d0
movb $0x0, %al
callq 0x3130
movq -0x18(%rbp), %rdi
leaq -0x1f0(%rbp), %rsi
movl -0x18c(%rbp), %edx
movl -0x190(%rbp), %ecx
callq 0x7250
movq -0x18(%rbp), %rdi
leaq -0x178(%rbp), %rsi
leaq -0x1a4(%rbp), %rdx
callq 0x8900
jmp 0x36df
leaq -0x1a4(%rbp), %rdi
leaq 0x6b2d(%rip), %rsi      # 0xa1e0
callq 0x30b0
cmpl $0x0, %eax
jne 0x36dd
movq -0x18(%rbp), %rdi
movl -0xa0c(%rbp), %r9d
leaq -0x1a4(%rbp), %rsi
xorl %r8d, %r8d
movl %r8d, %edx
movl %r8d, %ecx
callq 0x7bb0
jmp 0x36df
movl -0x194(%rbp), %eax
movl %eax, -0xa20(%rbp)
movl -0x194(%rbp), %eax
addl -0x190(%rbp), %eax
movl %eax, -0xa24(%rbp)
cmpl $0x0, -0xf0(%rbp)
je 0x3746
movl -0xf4(%rbp), %eax
cmpl -0xa20(%rbp), %eax
jb 0x3744
movl -0xf4(%rbp), %eax
cmpl -0xa24(%rbp), %eax
jae 0x3744
movq -0x18(%rbp), %rdi
movl -0xf4(%rbp), %esi
movl -0xf0(%rbp), %edx
movl -0xa10(%rbp), %ecx
leaq -0x1a4(%rbp), %r8
callq 0x63d0
jmp 0x3746
cmpl $0x0, -0xf8(%rbp)
je 0x3790
movl -0xfc(%rbp), %eax
cmpl -0xa20(%rbp), %eax
jb 0x378e
movl -0xfc(%rbp), %eax
cmpl -0xa24(%rbp), %eax
jae 0x378e
movq -0x18(%rbp), %rdi
movl -0xfc(%rbp), %esi
movl -0xf8(%rbp), %edx
leaq -0x1a4(%rbp), %rcx
leaq -0xa08(%rbp), %r8
callq 0x5530
jmp 0x3790
cmpl $0x0, -0xc8(%rbp)
je 0x37d3
movl -0xcc(%rbp), %eax
cmpl -0xa20(%rbp), %eax
jb 0x37d1
movl -0xcc(%rbp), %eax
cmpl -0xa24(%rbp), %eax
jae 0x37d1
movq -0x18(%rbp), %rdi
movl -0xcc(%rbp), %esi
movl -0xc8(%rbp), %edx
leaq -0x1a4(%rbp), %rcx
callq 0x4520
jmp 0x37d3
cmpl $0x0, -0x88(%rbp)
je 0x38b5
movl -0x8c(%rbp), %eax
cmpl -0xa20(%rbp), %eax
jb 0x38b3
movl -0x8c(%rbp), %eax
cmpl -0xa24(%rbp), %eax
jae 0x38b3
movq -0x18(%rbp), %rdi
movl -0xf4(%rbp), %esi
movl -0xf0(%rbp), %edx
movl -0xa10(%rbp), %ecx
leaq -0x1a4(%rbp), %r8
leaq 0x69be(%rip), %r9       # 0xa1e6
callq 0x66a0
movl %eax, -0xa28(%rbp)
cmpl $0x1, -0xa28(%rbp)
jne 0x38b1
leaq 0x69af(%rip), %rdi      # 0xa1f2
movb $0x0, %al
callq 0x3080
leaq 0x69d0(%rip), %rdi      # 0xa221
movb $0x0, %al
callq 0x3080
leaq 0x6993(%rip), %rdi      # 0xa1f2
movb $0x0, %al
callq 0x3080
movq -0x18(%rbp), %rdi
movl -0x8c(%rbp), %esi
movl -0x88(%rbp), %edx
leaq -0x1a4(%rbp), %rcx
callq 0x73d0
movq -0x18(%rbp), %rdi
movl -0x8c(%rbp), %edx
movl -0x88(%rbp), %ecx
leaq -0xa68(%rbp), %rsi
leaq -0x1a4(%rbp), %r8
callq 0x3bd0
leaq -0xa68(%rbp), %rdi
callq 0x3d80
jmp 0x38b3
jmp 0x38b5
jmp 0x38b7
movl -0xa14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0xa14(%rbp)
jmp 0x35d8
movq -0x18(%rbp), %rdi
callq 0x3060
movsbl -0xa08(%rbp), %eax
cmpl $0x0, %eax
je 0x3a73
cmpq $0x0, -0x600(%rbp)
jne 0x3908
leaq -0xa08(%rbp), %rsi
leaq 0x6935(%rip), %rdi      # 0xa231
movb $0x0, %al
callq 0x3080
jmp 0x3a71
cmpq $0x0, -0x5f8(%rbp)
jne 0x392c
leaq -0xa08(%rbp), %rsi
leaq 0x6931(%rip), %rdi      # 0xa251
movb $0x0, %al
callq 0x3080
jmp 0x3a6f
movq -0x600(%rbp), %rax
subq -0x5f8(%rbp), %rax
movq %rax, -0x600(%rbp)
leaq -0xa08(%rbp), %rsi
movq -0x600(%rbp), %rdx
leaq 0x6963(%rip), %rdi      # 0xa2b9
movb $0x0, %al
callq 0x3080
movl -0x608(%rbp), %esi
leaq 0x6973(%rip), %rdi      # 0xa2dd
movb $0x0, %al
callq 0x3080
callq 0x30d0
movl %eax, -0xa14(%rbp)
cmpl $0x79, -0xa14(%rbp)
jne 0x3a5f
leaq -0x5f0(%rbp), %rdi
leaq 0x69ba(%rip), %rsi      # 0xa351
callq 0x3110
movq %rax, -0xa70(%rbp)
movq -0xa70(%rbp), %rdi
movq -0x600(%rbp), %rsi
xorl %edx, %edx
callq 0x3100
movq -0xa70(%rbp), %rsi
movl $0xb8, %edi
callq 0x30c0
movl -0x608(%rbp), %edi
andl $0xff, %edi
movq -0xa70(%rbp), %rsi
callq 0x30c0
movl -0x608(%rbp), %edi
shrl $0x8, %edi
andl $0xff, %edi
movq -0xa70(%rbp), %rsi
callq 0x30c0
movl -0x608(%rbp), %edi
shrl $0x10, %edi
andl $0xff, %edi
movq -0xa70(%rbp), %rsi
callq 0x30c0
movl -0x608(%rbp), %edi
shrl $0x18, %edi
andl $0xff, %edi
movq -0xa70(%rbp), %rsi
callq 0x30c0
movq -0xa70(%rbp), %rsi
movl $0xc3, %edi
callq 0x30c0
movq -0xa70(%rbp), %rdi
callq 0x3060
leaq 0x68ff(%rip), %rdi      # 0xa355
movb $0x0, %al
callq 0x3080
jmp 0x3a6d
leaq 0x68fa(%rip), %rdi      # 0xa360
movb $0x0, %al
callq 0x3080
jmp 0x3a6f
jmp 0x3a71
jmp 0x3a73
xorl %eax, %eax
addq $0xa80, %rsp            # imm = 0xA80
popq %rbp
retq
nop