// File: /workspace/github_c_makefile_star2_O2/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 0x4f0b(%rip), %rdi      # 0x8194
callq 0x3060
leaq 0x4f39(%rip), %rdi      # 0x81ce
callq 0x3060
cmpl $0x1, %ebp
jle 0x380a
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)
pushq $0x1
popq %r14
leaq 0x4d31(%rip), %r12      # 0x8004
cmpl %ebp, %r14d
jge 0x3348
movslq %r14d, %r13
movq (%r15,%r13,8), %rbx
movq %rbx, %rdi
movq %r12, %rsi
callq 0x3040
testl %eax, %eax
je 0x3313
movq %rbx, %rdi
leaq 0x4d14(%rip), %rsi      # 0x800c
callq 0x3040
testl %eax, %eax
je 0x333c
leaq 0x630(%rsp), %rdi
movq %rbx, %rsi
callq 0x3050
jmp 0x3343
movq 0x8(%r15,%r13,8), %rsi
leaq 0x218(%rsp), %rdi
callq 0x3050
addl $0x2, %r14d
movq 0x10(%r15,%r13,8), %rdi
callq 0x3130
movl %eax, 0x618(%rsp)
jmp 0x3343
pushq $0x1
popq %rax
movl %eax, 0x8(%rsp)
incl %r14d
jmp 0x32d3
leaq 0x4cc3(%rip), %rsi      # 0x8012
leaq 0x630(%rsp), %rdi
callq 0x3120
testq %rax, %rax
je 0x3818
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 0x46a0
movq %rbx, %rdi
callq 0x4799
movl 0x3c(%rbx), %ebp
movq %r14, %rdi
callq 0x30f0
cmpl $0x1, 0x8(%rsp)
jne 0x33f2
movq %rax, %r15
leaq 0x4c88(%rip), %rdi      # 0x8038
leaq 0x4c8e(%rip), %rsi      # 0x8045
callq 0x3120
testq %rax, %rax
je 0x33f2
movq %rax, %rbx
subl %r15d, %ebp
xorl %r15d, %r15d
testl %ebp, %ebp
cmovgl %ebp, %r15d
subl $0x1, %r15d
jb 0x33ea
movq %r14, %rdi
callq 0x3160
movl %eax, %edi
movq %rbx, %rsi
callq 0x30d0
jmp 0x33d0
movq %rbx, %rdi
callq 0x3070
movslq 0x1d4(%rsp), %rsi
testq %rsi, %rsi
je 0x382c
movq %r14, %rdi
xorl %edx, %edx
callq 0x3110
leaq 0xc(%rsp), %rbx
pushq $0x4
popq %rdx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x51d0
cmpl $0x4550, (%rbx)         # imm = 0x4550
jne 0x3835
leaq 0x4dd9(%rip), %rdi      # 0x820c
callq 0x3060
leaq 0x3c(%rsp), %rbx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x4be0
movq %rbx, %rdi
callq 0x4c44
movzwl 0x10(%rbx), %edx
testl %edx, %edx
je 0x3470
leaq 0x50(%rsp), %rbx
movq %rbx, %rdi
movq %r14, %rsi
callq 0x56b4
movq %rbx, %rdi
callq 0x58fa
xorl %eax, %eax
leaq 0x50(%rsp), %rcx
cmpw $0x20b, (%rcx)          # imm = 0x20B
sete %al
leal 0x4(,%rax,4), %ebp
leaq 0x10(%rsp), %r12
xorl %r13d, %r13d
movzwl 0x3e(%rsp), %eax
cmpl %eax, %r13d
jae 0x36b8
movq %r12, %rdi
movq %r14, %rsi
callq 0x6b9c
movq %r12, %rdi
movl %r13d, %esi
callq 0x6c2c
movq %r12, %rdi
leaq 0x4b8c(%rip), %rsi      # 0x8048
pushq $0x5
popq %rdx
callq 0x3100
testl %eax, %eax
jne 0x34d8
movl 0x20(%rsp), %eax
subl 0x28(%rsp), %eax
movq %rax, 0x628(%rsp)
testb $0x20, 0x38(%rsp)
jne 0x350e
movq %r12, %rdi
leaq 0x4b75(%rip), %rsi      # 0x805e
pushq $0x6
popq %rdx
callq 0x3100
testl %eax, %eax
jne 0x3554
movq %r14, %rdi
movq %r12, %rsi
xorl %edx, %edx
xorl %ecx, %ecx
xorl %r8d, %r8d
movl 0x8(%rsp), %r9d
callq 0x6524
jmp 0x3554
cmpl $0x1, 0x8(%rsp)
jne 0x3544
leaq 0x150(%rsp), %rbx
movq %rbx, %rdi
leaq 0x4b27(%rip), %rsi      # 0x804e
movl %r13d, %edx
xorl %eax, %eax
callq 0x3140
movl 0x24(%rsp), %ecx
movl 0x28(%rsp), %edx
movq %r14, %rdi
movq %rbx, %rsi
callq 0x5d40
movq %r14, %rdi
leaq 0x50(%rsp), %rsi
movq %r12, %rdx
callq 0x6d18
movl 0x20(%rsp), %r15d
movl 0x24(%rsp), %ebx
addl %r15d, %ebx
movl 0xd8(%rsp), %edx
testl %edx, %edx
je 0x3591
movl 0xd4(%rsp), %esi
cmpl %r15d, %esi
setae %al
cmpl %ebx, %esi
setb %cl
andb %al, %cl
cmpb $0x1, %cl
jne 0x3591
movq %r14, %rdi
movl %ebp, %ecx
movq %r12, %r8
callq 0x5398
movl 0xd0(%rsp), %edx
testl %edx, %edx
je 0x35c8
movl 0xcc(%rsp), %esi
cmpl %r15d, %esi
setae %al
cmpl %ebx, %esi
setb %cl
andb %al, %cl
cmpb $0x1, %cl
jne 0x35c8
movq %r14, %rdi
movq %r12, %rcx
leaq 0x218(%rsp), %r8
callq 0x490c
movl 0x100(%rsp), %edx
testl %edx, %edx
je 0x35f7
movl 0xfc(%rsp), %esi
cmpl %r15d, %esi
setae %al
cmpl %ebx, %esi
setb %cl
andb %al, %cl
cmpb $0x1, %cl
jne 0x35f7
movq %r14, %rdi
movq %r12, %rcx
callq 0x3fb8
cmpl $0x0, 0x140(%rsp)
je 0x36b0
movl 0x13c(%rsp), %eax
cmpl %r15d, %eax
setae %cl
cmpl %ebx, %eax
setb %al
andb %cl, %al
cmpb $0x1, %al
jne 0x36b0
movl 0xd4(%rsp), %esi
movl 0xd8(%rsp), %edx
movq %r14, %rdi
movl %ebp, %ecx
movq %r12, %r8
leaq 0x4a26(%rip), %r9       # 0x8064
callq 0x559c
cmpl $0x1, %eax
jne 0x36b0
leaq 0x4bf2(%rip), %rbx      # 0x8241
movq %rbx, %rdi
callq 0x3060
leaq 0x4bd4(%rip), %rdi      # 0x8232
callq 0x3060
movq %rbx, %rdi
callq 0x3060
movl 0x13c(%rsp), %esi
movl 0x140(%rsp), %edx
movq %r14, %rdi
movq %r12, %rcx
callq 0x5e80
movl 0x13c(%rsp), %edx
movl 0x140(%rsp), %ecx
movq %r14, %rdi
leaq 0x1d8(%rsp), %rbx
movq %rbx, %rsi
movq %r12, %r8
callq 0x38f3
movq %rbx, %rdi
callq 0x3a06
incl %r13d
jmp 0x348e
movq %r14, %rdi
callq 0x3070
cmpb $0x0, 0x218(%rsp)
je 0x37f6
movq 0x620(%rsp), %rdx
testq %rdx, %rdx
je 0x37c9
movq 0x628(%rsp), %rax
testq %rax, %rax
je 0x37d2
subq %rax, %rdx
leaq 0x218(%rsp), %rbx
movq %rdx, 0x408(%rbx)
leaq 0x49ef(%rip), %rdi      # 0x80f8
movq %rbx, %rsi
xorl %eax, %eax
callq 0x3090
movl 0x400(%rbx), %esi
leaq 0x49fc(%rip), %rdi      # 0x811c
xorl %eax, %eax
callq 0x3090
callq 0x30e0
cmpl $0x79, %eax
jne 0x37ea
leaq 0x4a54(%rip), %rsi      # 0x8190
leaq 0x630(%rsp), %rdi
callq 0x3120
movq %rax, %rbx
movq 0x620(%rsp), %rsi
movq %rax, %rdi
xorl %edx, %edx
callq 0x3110
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 0x4a61(%rip), %rdi      # 0x8228
jmp 0x37f1
leaq 0x48a0(%rip), %rdi      # 0x8070
jmp 0x37d9
leaq 0x48b7(%rip), %rdi      # 0x8090
leaq 0x218(%rsp), %rsi
xorl %eax, %eax
callq 0x3090
jmp 0x37f6
leaq 0x4a2c(%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 0x4aa2(%rip), %rdi      # 0x82b3
callq 0x3060
jmp 0x3849
movq 0x8(%r15), %rsi
leaq 0x47f2(%rip), %rdi      # 0x8015
xorl %eax, %eax
callq 0x3090
jmp 0x3849
leaq 0x4a69(%rip), %rdi      # 0x829c
jmp 0x383c
leaq 0x4a33(%rip), %rdi      # 0x826f
callq 0x3060
movq %r14, %rdi
callq 0x3070
xorl %edi, %edi
callq 0x3150