// File: /workspace/github_c_makefile_star2_O1/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
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa38, %rsp            # imm = 0xA38
movq %rsi, %r15
movl %edi, %ebp
leaq 0x4f1b(%rip), %rdi      # 0x8194
callq 0x3060
leaq 0x4f49(%rip), %rdi      # 0x81ce
callq 0x3060
cmpl $0x1, %ebp
jle 0x381a
xorl %eax, %eax
movb %al, 0x150(%rsp)
leaq 0x218(%rsp), %rcx
movl $0x0, 0x8(%rsp)
movb %al, (%rcx)
xorps %xmm0, %xmm0
movups %xmm0, 0x408(%rcx)
movl $0x1, %r14d
leaq 0x4d3f(%rip), %r12      # 0x8004
movslq %r14d, %r13
movq (%r15,%r13,8), %rbx
movq %rbx, %rdi
movq %r12, %rsi
callq 0x3040
testl %eax, %eax
je 0x3300
movq %rbx, %rdi
leaq 0x4d27(%rip), %rsi      # 0x800c
callq 0x3040
testl %eax, %eax
je 0x3329
leaq 0x630(%rsp), %rdi
movq %rbx, %rsi
callq 0x3050
jmp 0x3331
movq 0x8(%r15,%r13,8), %rsi
leaq 0x218(%rsp), %rdi
callq 0x3050
leal 0x2(%r13), %r14d
movq 0x10(%r15,%r13,8), %rdi
callq 0x3120
movl %eax, 0x618(%rsp)
jmp 0x3331
movl $0x1, 0x8(%rsp)
incl %r14d
cmpl %ebp, %r14d
jl 0x32c5
leaq 0x4cd2(%rip), %rsi      # 0x8012
leaq 0x630(%rsp), %rdi
callq 0x3110
testq %rax, %rax
je 0x3828
movq %rax, %r14
leaq 0x50(%rsp), %rdi
movl $0x100, %edx            # imm = 0x100
xorl %esi, %esi
callq 0x30b0
leaq 0x198(%rsp), %rbx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x4728
movq %rbx, %rdi
callq 0x4825
movl 0x3c(%rbx), %ebp
movq %r14, %rdi
callq 0x30f0
cmpl $0x1, 0x8(%rsp)
jne 0x33da
movq %rax, %r15
leaq 0x4c97(%rip), %rdi      # 0x8038
leaq 0x4c9d(%rip), %rsi      # 0x8045
callq 0x3110
testq %rax, %rax
je 0x33da
movq %rax, %rbx
subl %r15d, %ebp
testl %ebp, %ebp
jle 0x33d2
movq %r14, %rdi
callq 0x3150
movl %eax, %edi
movq %rbx, %rsi
callq 0x30d0
decl %ebp
jne 0x33bc
movq %rbx, %rdi
callq 0x3070
movslq 0x1d4(%rsp), %rsi
testq %rsi, %rsi
je 0x383c
movq %r14, %rdi
xorl %edx, %edx
callq 0x3100
leaq 0xc(%rsp), %rbx
movq %r14, %rdi
movq %rbx, %rsi
movl $0x4, %edx
callq 0x5276
cmpb $0x50, (%rbx)
jne 0x3845
cmpb $0x45, 0xd(%rsp)
jne 0x3845
cmpb $0x0, 0xe(%rsp)
jne 0x3845
cmpb $0x0, 0xf(%rsp)
jne 0x3845
leaq 0x4dd1(%rip), %rdi      # 0x820c
callq 0x3060
leaq 0x3c(%rsp), %rbx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x4c68
movq %rbx, %rdi
callq 0x4ccc
movzwl 0x10(%rbx), %edx
testl %edx, %edx
je 0x3478
leaq 0x50(%rsp), %rbx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x57f8
movq %rbx, %rdi
callq 0x5a48
xorl %eax, %eax
cmpw $0x20b, 0x50(%rsp)      # imm = 0x20B
sete %cl
cmpw $0x0, 0x3e(%rsp)
je 0x36c8
movb %cl, %al
leal 0x4(,%rax,4), %ebp
leaq 0x10(%rsp), %r15
xorl %r12d, %r12d
movq %r15, %rdi
movq %r14, %rsi
callq 0x6dd4
movq %r15, %rdi
movl %r12d, %esi
callq 0x6e6a
movl 0x10(%rsp), %eax
movl $0x7865742e, %ecx       # imm = 0x7865742E
xorl %ecx, %eax
movzbl 0x14(%rsp), %ecx
xorl $0x74, %ecx
orl %eax, %ecx
jne 0x34de
movl 0x20(%rsp), %eax
subl 0x28(%rsp), %eax
movq %rax, 0x628(%rsp)
testb $0x20, 0x38(%rsp)
jne 0x3515
movl 0x10(%rsp), %eax
movl $0x7273722e, %ecx       # imm = 0x7273722E
xorl %ecx, %eax
movzwl 0x14(%rsp), %ecx
xorl $0x63, %ecx
orl %eax, %ecx
jne 0x355b
movq %r14, %rdi
movq %r15, %rsi
xorl %edx, %edx
xorl %ecx, %ecx
xorl %r8d, %r8d
movl 0x8(%rsp), %r9d
callq 0x674d
jmp 0x355b
cmpl $0x1, 0x8(%rsp)
jne 0x354b
leaq 0x150(%rsp), %rbx
movq %rbx, %rdi
leaq 0x4b20(%rip), %rsi      # 0x804e
movl %r12d, %edx
xorl %eax, %eax
callq 0x3130
movl 0x24(%rsp), %ecx
movl 0x28(%rsp), %edx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x5e74
movq %r14, %rdi
leaq 0x50(%rsp), %rsi
movq %r15, %rdx
callq 0x6f58
movl 0x20(%rsp), %ebx
movl 0x24(%rsp), %r13d
addl %ebx, %r13d
movl 0xd8(%rsp), %edx
testl %edx, %edx
je 0x3598
movl 0xd4(%rsp), %esi
cmpl %ebx, %esi
setae %al
cmpl %r13d, %esi
setb %cl
andb %al, %cl
cmpb $0x1, %cl
jne 0x3598
movq %r14, %rdi
movl %ebp, %ecx
movq %r15, %r8
callq 0x5478
movl 0xd0(%rsp), %edx
testl %edx, %edx
je 0x35cf
movl 0xcc(%rsp), %esi
cmpl %ebx, %esi
setae %al
cmpl %r13d, %esi
setb %cl
andb %al, %cl
cmpb $0x1, %cl
jne 0x35cf
movq %r14, %rdi
movq %r15, %rcx
leaq 0x218(%rsp), %r8
callq 0x499c
movl 0x100(%rsp), %edx
testl %edx, %edx
je 0x35fe
movl 0xfc(%rsp), %esi
cmpl %ebx, %esi
setae %al
cmpl %r13d, %esi
setb %cl
andb %al, %cl
cmpb $0x1, %cl
jne 0x35fe
movq %r14, %rdi
movq %r15, %rcx
callq 0x3fb8
cmpl $0x0, 0x140(%rsp)
je 0x36b7
movl 0x13c(%rsp), %eax
cmpl %ebx, %eax
setae %cl
cmpl %r13d, %eax
setb %al
andb %cl, %al
cmpb $0x1, %al
jne 0x36b7
movl 0xd4(%rsp), %esi
movl 0xd8(%rsp), %edx
movq %r14, %rdi
movl %ebp, %ecx
movq %r15, %r8
leaq 0x4a1f(%rip), %r9       # 0x8064
callq 0x56a8
cmpl $0x1, %eax
jne 0x36b7
leaq 0x4beb(%rip), %rbx      # 0x8241
movq %rbx, %rdi
callq 0x3060
leaq 0x4bcd(%rip), %rdi      # 0x8232
callq 0x3060
movq %rbx, %rdi
callq 0x3060
movl 0x13c(%rsp), %esi
movl 0x140(%rsp), %edx
movq %r14, %rdi
movq %r15, %rcx
callq 0x5fac
movl 0x13c(%rsp), %edx
movl 0x140(%rsp), %ecx
movq %r14, %rdi
leaq 0x1d8(%rsp), %rbx
movq %rbx, %rsi
movq %r15, %r8
callq 0x3908
movq %rbx, %rdi
callq 0x3a1b
incl %r12d
movzwl 0x3e(%rsp), %eax
cmpl %eax, %r12d
jb 0x34a1
movq %r14, %rdi
callq 0x3070
cmpb $0x0, 0x218(%rsp)
je 0x3806
movq 0x620(%rsp), %rdx
testq %rdx, %rdx
je 0x37d9
movq 0x628(%rsp), %rax
testq %rax, %rax
je 0x37e2
subq %rax, %rdx
leaq 0x218(%rsp), %rbx
movq %rdx, 0x408(%rbx)
leaq 0x49df(%rip), %rdi      # 0x80f8
movq %rbx, %rsi
xorl %eax, %eax
callq 0x3090
movl 0x400(%rbx), %esi
leaq 0x49ec(%rip), %rdi      # 0x811c
xorl %eax, %eax
callq 0x3090
callq 0x30e0
cmpl $0x79, %eax
jne 0x37fa
leaq 0x4a44(%rip), %rsi      # 0x8190
leaq 0x630(%rsp), %rdi
callq 0x3110
movq %rax, %rbx
movq 0x620(%rsp), %rsi
movq %rax, %rdi
xorl %edx, %edx
callq 0x3100
movl $0xb8, %edi
movq %rbx, %rsi
callq 0x30d0
movzbl 0x618(%rsp), %edi
movq %rbx, %rsi
callq 0x30d0
movzbl 0x619(%rsp), %edi
movq %rbx, %rsi
callq 0x30d0
movzbl 0x61a(%rsp), %edi
movq %rbx, %rsi
callq 0x30d0
movzbl 0x61b(%rsp), %edi
movq %rbx, %rsi
callq 0x30d0
movl $0xc3, %edi
movq %rbx, %rsi
callq 0x30d0
movq %rbx, %rdi
callq 0x3070
leaq 0x4a51(%rip), %rdi      # 0x8228
jmp 0x3801
leaq 0x4890(%rip), %rdi      # 0x8070
jmp 0x37e9
leaq 0x48a7(%rip), %rdi      # 0x8090
leaq 0x218(%rsp), %rsi
xorl %eax, %eax
callq 0x3090
jmp 0x3806
leaq 0x4a1c(%rip), %rdi      # 0x821d
callq 0x3060
xorl %eax, %eax
addq $0xa38, %rsp            # imm = 0xA38
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x4a92(%rip), %rdi      # 0x82b3
callq 0x3060
jmp 0x3859
movq 0x8(%r15), %rsi
leaq 0x47e2(%rip), %rdi      # 0x8015
xorl %eax, %eax
callq 0x3090
jmp 0x3859
leaq 0x4a59(%rip), %rdi      # 0x829c
jmp 0x384c
leaq 0x4a23(%rip), %rdi      # 0x826f
callq 0x3060
movq %r14, %rdi
callq 0x3070
xorl %edi, %edi
callq 0x3140