// File: DimitriFourny[P]uaf_replacer/main.cc
// Function: main
int main(int argc, char* argv[]) {
  if (argc < 2) {
    printf("Usage: %s <json_path> [object_size]\n", argv[0]);
    printf("       %s <json_path> <min_size> <max_size>\n", argv[0]);
    return 1;
  }

  std::string filepath = argv[1];
  bool search_exact_size = false;
  unsigned int target_object_size = 0;
  bool search_range_size = false;
  unsigned int min_size = 0, max_size = 0;
  if (argc == 3) {
    search_exact_size = true;
    target_object_size = std::stoul(argv[2], nullptr, 0);
  } else if (argc > 3) {
    search_range_size = true;
    min_size = std::stoul(argv[2], nullptr, 0);
    max_size = std::stoul(argv[3], nullptr, 0);
  }

  printf("Mapping the file...");
  fflush(stdout);
  size_t filesize = 0;
  char* memfile = map_file(filepath, filesize);
  if (!memfile) {
    return 2;
  }
  memfile[filesize] = 0;
  printf("done\n");

  printf("Mapping the JSON...");
  fflush(stdout);
  rapidjson::Document document;
  document.Parse(memfile);
  if (document.HasParseError()) {
    printf("parsing error\n");
    printf("Error: %s (%zd)\n", GetParseError_En(document.GetParseError()), 
      document.GetErrorOffset());
    free(memfile);
    return 3;
  }
  printf("done\n");
  free(memfile);

  if (search_exact_size) {
    printf("Searching objects of size 0x%x bytes...\n", target_object_size);
  } else if (search_range_size) {
    printf("Searching objects in the range [0x%x, 0x%x] bytes...\n", 
      min_size, max_size);
  }
  printf("\n--------------------\n");

  size_t nb_found = 0;
  for (rapidjson::Value::ConstMemberIterator itr = document.MemberBegin(); 
       itr != document.MemberEnd(); ++itr) {
    if (!itr->value.HasMember("name") || !itr->value.HasMember("type")
        || !itr->value.HasMember("size")) {
      continue; 
    }

    if (search_exact_size) {
      if (itr->value["size"].GetUint() != target_object_size) {
        continue;
      }
    } else if (search_range_size) {
      if (itr->value["size"].GetUint() < min_size ||
          itr->value["size"].GetUint() > max_size) {
        continue;
      }
    }

    printf("%s %s (0x%x bytes)\n", itr->value["type"].GetString(), 
      itr->value["name"].GetString(), itr->value["size"].GetUint());
    nb_found++;
    
    if (itr->value.HasMember("members")) {
      dump_members(document, itr->value, itr->value["members"], 0, 0);
    }
    printf("--------------------\n");
  }

  printf("\n%zu objects found\n", nb_found);
  return 0;
}

// Assembly:
subq $0x2e8, %rsp            # imm = 0x2E8
movl $0x0, 0x2e4(%rsp)
movl %edi, 0x2e0(%rsp)
movq %rsi, 0x2d8(%rsp)
cmpl $0x2, 0x2e0(%rsp)
jge 0x3cfd
movq 0x2d8(%rsp), %rax
movq (%rax), %rsi
leaq 0xa46b(%rip), %rdi      # 0xe138
movb $0x0, %al
callq 0x2050
movq 0x2d8(%rsp), %rax
movq (%rax), %rsi
leaq 0xa477(%rip), %rdi      # 0xe15d
movb $0x0, %al
callq 0x2050
movl $0x1, 0x2e4(%rsp)
jmp 0x47aa
movq 0x2d8(%rsp), %rax
movq 0x8(%rax), %rax
movq %rax, 0x168(%rsp)
leaq 0x2b7(%rsp), %rdi
movq %rdi, 0x170(%rsp)
callq 0x2350
movq 0x168(%rsp), %rsi
movq 0x170(%rsp), %rdx
leaq 0x2b8(%rsp), %rdi
callq 0x6b90
jmp 0x3d45
leaq 0x2b7(%rsp), %rdi
callq 0x2210
movb $0x0, 0x2a3(%rsp)
movl $0x0, 0x29c(%rsp)
movb $0x0, 0x29b(%rsp)
movl $0x0, 0x294(%rsp)
movl $0x0, 0x290(%rsp)
cmpl $0x3, 0x2e0(%rsp)
jne 0x3e99
movb $0x1, 0x2a3(%rsp)
movq 0x2d8(%rsp), %rax
movq 0x10(%rax), %rax
movq %rax, 0x158(%rsp)
leaq 0x26f(%rsp), %rdi
movq %rdi, 0x160(%rsp)
callq 0x2350
movq 0x158(%rsp), %rsi
movq 0x160(%rsp), %rdx
leaq 0x270(%rsp), %rdi
callq 0x6b90
jmp 0x3de1
xorl %edx, %edx
movl %edx, %esi
leaq 0x270(%rsp), %rdi
callq 0x7030
movq %rax, 0x150(%rsp)
jmp 0x3dfc
movq 0x150(%rsp), %rax
movl %eax, 0x29c(%rsp)
leaq 0x270(%rsp), %rdi
callq 0x2130
leaq 0x26f(%rsp), %rdi
callq 0x2210
jmp 0x4060
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a8(%rsp)
movl %eax, 0x2a4(%rsp)
leaq 0x2b7(%rsp), %rdi
callq 0x2210
jmp 0x47b9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a8(%rsp)
movl %eax, 0x2a4(%rsp)
jmp 0x3e87
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a8(%rsp)
movl %eax, 0x2a4(%rsp)
leaq 0x270(%rsp), %rdi
callq 0x2130
leaq 0x26f(%rsp), %rdi
callq 0x2210
jmp 0x479b
cmpl $0x3, 0x2e0(%rsp)
jle 0x405e
movb $0x1, 0x29b(%rsp)
movq 0x2d8(%rsp), %rax
movq 0x10(%rax), %rax
movq %rax, 0x140(%rsp)
leaq 0x247(%rsp), %rdi
movq %rdi, 0x148(%rsp)
callq 0x2350
movq 0x140(%rsp), %rsi
movq 0x148(%rsp), %rdx
leaq 0x248(%rsp), %rdi
callq 0x6b90
jmp 0x3ef7
xorl %edx, %edx
movl %edx, %esi
leaq 0x248(%rsp), %rdi
callq 0x7030
movq %rax, 0x138(%rsp)
jmp 0x3f12
movq 0x138(%rsp), %rax
movl %eax, 0x294(%rsp)
leaq 0x248(%rsp), %rdi
callq 0x2130
leaq 0x247(%rsp), %rdi
callq 0x2210
movq 0x2d8(%rsp), %rax
movq 0x18(%rax), %rax
movq %rax, 0x128(%rsp)
leaq 0x21f(%rsp), %rdi
movq %rdi, 0x130(%rsp)
callq 0x2350
movq 0x128(%rsp), %rsi
movq 0x130(%rsp), %rdx
leaq 0x220(%rsp), %rdi
callq 0x6b90
jmp 0x3f83
xorl %edx, %edx
movl %edx, %esi
leaq 0x220(%rsp), %rdi
callq 0x7030
movq %rax, 0x120(%rsp)
jmp 0x3f9e
movq 0x120(%rsp), %rax
movl %eax, 0x290(%rsp)
leaq 0x220(%rsp), %rdi
callq 0x2130
leaq 0x21f(%rsp), %rdi
callq 0x2210
jmp 0x405e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a8(%rsp)
movl %eax, 0x2a4(%rsp)
jmp 0x4003
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a8(%rsp)
movl %eax, 0x2a4(%rsp)
leaq 0x248(%rsp), %rdi
callq 0x2130
leaq 0x247(%rsp), %rdi
callq 0x2210
jmp 0x479b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a8(%rsp)
movl %eax, 0x2a4(%rsp)
jmp 0x404c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a8(%rsp)
movl %eax, 0x2a4(%rsp)
leaq 0x220(%rsp), %rdi
callq 0x2130
leaq 0x21f(%rsp), %rdi
callq 0x2210
jmp 0x479b
jmp 0x4060
leaq 0xa123(%rip), %rdi      # 0xe18a
xorl %eax, %eax
callq 0x2050
jmp 0x4070
movq 0x11f41(%rip), %rax     # 0x15fb8
movq (%rax), %rdi
callq 0x2260
jmp 0x4081
movq $0x0, 0x210(%rsp)
leaq 0x2b8(%rsp), %rdi
leaq 0x210(%rsp), %rsi
callq 0x24f0
movq %rax, 0x118(%rsp)
jmp 0x40ac
movq 0x118(%rsp), %rax
movq %rax, 0x208(%rsp)
cmpq $0x0, 0x208(%rsp)
jne 0x40fb
movl $0x2, 0x2e4(%rsp)
movl $0x1, 0x204(%rsp)
jmp 0x478c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a8(%rsp)
movl %eax, 0x2a4(%rsp)
jmp 0x479b
movq 0x208(%rsp), %rax
movq 0x210(%rsp), %rcx
movb $0x0, (%rax,%rcx)
leaq 0xa088(%rip), %rdi      # 0xe19e
xorl %eax, %eax
callq 0x2050
jmp 0x411f
leaq 0xa07e(%rip), %rdi      # 0xe1a4
xorl %eax, %eax
callq 0x2050
jmp 0x412f
movq 0x11e82(%rip), %rax     # 0x15fb8
movq (%rax), %rdi
callq 0x2260
jmp 0x4140
xorl %eax, %eax
movl %eax, %ecx
leaq 0x1a0(%rsp), %rdi
movl $0x400, %edx            # imm = 0x400
movq %rcx, %rsi
callq 0x7080
jmp 0x415b
movq 0x208(%rsp), %rsi
leaq 0x1a0(%rsp), %rdi
callq 0x7190
jmp 0x4172
leaq 0x1a0(%rsp), %rdi
callq 0x71c0
movb %al, 0x117(%rsp)
jmp 0x4188
movb 0x117(%rsp), %al
testb $0x1, %al
jne 0x4198
jmp 0x4259
leaq 0xa019(%rip), %rdi      # 0xe1b8
xorl %eax, %eax
callq 0x2050
jmp 0x41a8
leaq 0x1a0(%rsp), %rdi
callq 0x7340
movl %eax, 0x110(%rsp)
jmp 0x41be
movl 0x110(%rsp), %edi
callq 0x71e0
movq %rax, 0x108(%rsp)
jmp 0x41d4
leaq 0x1a0(%rsp), %rdi
callq 0x7360
movq %rax, 0x100(%rsp)
jmp 0x41eb
movq 0x100(%rsp), %rdx
movq 0x108(%rsp), %rsi
leaq 0x9fc5(%rip), %rdi      # 0xe1c7
xorl %eax, %eax
callq 0x2050
jmp 0x420b
movq 0x208(%rsp), %rdi
callq 0x2280
movl $0x3, 0x2e4(%rsp)
movl $0x1, 0x204(%rsp)
jmp 0x477f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a8(%rsp)
movl %eax, 0x2a4(%rsp)
leaq 0x1a0(%rsp), %rdi
callq 0x74e0
jmp 0x479b
leaq 0x9f3e(%rip), %rdi      # 0xe19e
xorl %eax, %eax
callq 0x2050
jmp 0x4269
movq 0x208(%rsp), %rdi
callq 0x2280
testb $0x1, 0x2a3(%rsp)
je 0x4299
movl 0x29c(%rsp), %esi
leaq 0x9f4a(%rip), %rdi      # 0xe1d8
xorl %eax, %eax
callq 0x2050
jmp 0x4297
jmp 0x42c5
testb $0x1, 0x29b(%rsp)
je 0x42c3
movl 0x294(%rsp), %esi
movl 0x290(%rsp), %edx
leaq 0x9f49(%rip), %rdi      # 0xe201
xorl %eax, %eax
callq 0x2050
jmp 0x42c1
jmp 0x42c3
jmp 0x42c5
leaq 0x9f6b(%rip), %rdi      # 0xe237
xorl %eax, %eax
callq 0x2050
jmp 0x42d5
movq $0x0, 0x198(%rsp)
leaq 0x188(%rsp), %rdi
leaq 0x1a0(%rsp), %rsi
callq 0x7380
jmp 0x42f8
leaq 0x190(%rsp), %rdi
leaq 0x188(%rsp), %rsi
callq 0x73f0
jmp 0x430f
jmp 0x4311
leaq 0x178(%rsp), %rdi
leaq 0x1a0(%rsp), %rsi
callq 0x7430
jmp 0x4328
leaq 0x180(%rsp), %rdi
leaq 0x178(%rsp), %rsi
callq 0x73f0
jmp 0x433f
movq 0x180(%rsp), %rsi
leaq 0x190(%rsp), %rdi
callq 0x7410
movb %al, 0xff(%rsp)
jmp 0x435d
movb 0xff(%rsp), %al
testb $0x1, %al
jne 0x436d
jmp 0x4751
leaq 0x190(%rsp), %rdi
callq 0x74b0
movq %rax, 0xf0(%rsp)
jmp 0x4384
movq 0xf0(%rsp), %rdi
addq $0x10, %rdi
leaq 0x9d22(%rip), %rsi      # 0xe0b9
callq 0x6c50
movb %al, 0xef(%rsp)
jmp 0x43a5
movb 0xef(%rsp), %al
testb $0x1, %al
jne 0x43b5
jmp 0x443f
leaq 0x190(%rsp), %rdi
callq 0x74b0
movq %rax, 0xe0(%rsp)
jmp 0x43cc
movq 0xe0(%rsp), %rdi
addq $0x10, %rdi
leaq 0x9cdf(%rip), %rsi      # 0xe0be
callq 0x6c50
movb %al, 0xdf(%rsp)
jmp 0x43ed
movb 0xdf(%rsp), %al
testb $0x1, %al
jne 0x43fa
jmp 0x443f
leaq 0x190(%rsp), %rdi
callq 0x74b0
movq %rax, 0xd0(%rsp)
jmp 0x4411
movq 0xd0(%rsp), %rdi
addq $0x10, %rdi
leaq 0xa89a(%rip), %rsi      # 0xecbe
callq 0x6c50
movb %al, 0xcf(%rsp)
jmp 0x4432
movb 0xcf(%rsp), %al
testb $0x1, %al
jne 0x4444
jmp 0x443f
jmp 0x473d
testb $0x1, 0x2a3(%rsp)
je 0x44b7
leaq 0x190(%rsp), %rdi
callq 0x74b0
movq %rax, 0xc0(%rsp)
jmp 0x4465
movq 0xc0(%rsp), %rdi
addq $0x10, %rdi
leaq 0xa846(%rip), %rsi      # 0xecbe
callq 0x6ca0
movq %rax, 0xb8(%rsp)
jmp 0x4487
movq 0xb8(%rsp), %rdi
callq 0x6fe0
movl %eax, 0xb4(%rsp)
jmp 0x449d
movl 0xb4(%rsp), %eax
cmpl 0x29c(%rsp), %eax
je 0x44b2
jmp 0x473d
jmp 0x458c
testb $0x1, 0x29b(%rsp)
je 0x458a
leaq 0x190(%rsp), %rdi
callq 0x74b0
movq %rax, 0xa8(%rsp)
jmp 0x44dc
movq 0xa8(%rsp), %rdi
addq $0x10, %rdi
leaq 0xa7cf(%rip), %rsi      # 0xecbe
callq 0x6ca0
movq %rax, 0xa0(%rsp)
jmp 0x44fe
movq 0xa0(%rsp), %rdi
callq 0x6fe0
movl %eax, 0x9c(%rsp)
jmp 0x4514
movl 0x9c(%rsp), %eax
cmpl 0x294(%rsp), %eax
jb 0x4583
leaq 0x190(%rsp), %rdi
callq 0x74b0
movq %rax, 0x90(%rsp)
jmp 0x453b
movq 0x90(%rsp), %rdi
addq $0x10, %rdi
leaq 0xa770(%rip), %rsi      # 0xecbe
callq 0x6ca0
movq %rax, 0x88(%rsp)
jmp 0x455d
movq 0x88(%rsp), %rdi
callq 0x6fe0
movl %eax, 0x84(%rsp)
jmp 0x4573
movl 0x84(%rsp), %eax
cmpl 0x290(%rsp), %eax
jbe 0x4588
jmp 0x473d
jmp 0x458a
jmp 0x458c
leaq 0x190(%rsp), %rdi
callq 0x74b0
movq %rax, 0x78(%rsp)
jmp 0x45a0
movq 0x78(%rsp), %rdi
addq $0x10, %rdi
leaq 0x9b0e(%rip), %rsi      # 0xe0be
callq 0x6ca0
movq %rax, 0x70(%rsp)
jmp 0x45bc
movq 0x70(%rsp), %rdi
callq 0x6cd0
movq %rax, 0x68(%rsp)
jmp 0x45cd
leaq 0x190(%rsp), %rdi
callq 0x74b0
movq %rax, 0x60(%rsp)
jmp 0x45e1
movq 0x60(%rsp), %rdi
addq $0x10, %rdi
leaq 0x9ac8(%rip), %rsi      # 0xe0b9
callq 0x6ca0
movq %rax, 0x58(%rsp)
jmp 0x45fd
movq 0x58(%rsp), %rdi
callq 0x6cd0
movq %rax, 0x50(%rsp)
jmp 0x460e
leaq 0x190(%rsp), %rdi
callq 0x74b0
movq %rax, 0x48(%rsp)
jmp 0x4622
movq 0x48(%rsp), %rdi
addq $0x10, %rdi
leaq 0xa68c(%rip), %rsi      # 0xecbe
callq 0x6ca0
movq %rax, 0x40(%rsp)
jmp 0x463e
movq 0x40(%rsp), %rdi
callq 0x6fe0
movl %eax, 0x3c(%rsp)
jmp 0x464e
movl 0x3c(%rsp), %ecx
movq 0x50(%rsp), %rdx
movq 0x68(%rsp), %rsi
leaq 0x9beb(%rip), %rdi      # 0xe24e
xorl %eax, %eax
callq 0x2050
jmp 0x466c
movq 0x198(%rsp), %rax
incq %rax
movq %rax, 0x198(%rsp)
leaq 0x190(%rsp), %rdi
callq 0x74b0
movq %rax, 0x30(%rsp)
jmp 0x4693
movq 0x30(%rsp), %rdi
addq $0x10, %rdi
leaq 0x9a6a(%rip), %rsi      # 0xe10d
callq 0x6c50
movb %al, 0x2f(%rsp)
jmp 0x46ae
movb 0x2f(%rsp), %al
testb $0x1, %al
jne 0x46b8
jmp 0x472b
leaq 0x190(%rsp), %rdi
callq 0x74b0
movq %rax, 0x20(%rsp)
jmp 0x46cc
movq 0x20(%rsp), %rax
addq $0x10, %rax
movq %rax, 0x10(%rsp)
leaq 0x190(%rsp), %rdi
callq 0x74b0
movq %rax, 0x18(%rsp)
jmp 0x46ee
movq 0x18(%rsp), %rdi
addq $0x10, %rdi
leaq 0x9a0f(%rip), %rsi      # 0xe10d
callq 0x6ca0
movq %rax, 0x8(%rsp)
jmp 0x470a
movq 0x8(%rsp), %rdx
movq 0x10(%rsp), %rsi
xorl %r8d, %r8d
movl %r8d, %ecx
leaq 0x1a0(%rsp), %rdi
callq 0x3390
jmp 0x4729
jmp 0x472b
leaq 0x9b06(%rip), %rdi      # 0xe238
xorl %eax, %eax
callq 0x2050
jmp 0x473b
jmp 0x473d
leaq 0x190(%rsp), %rdi
callq 0x74c0
jmp 0x474c
jmp 0x4311
movq 0x198(%rsp), %rsi
leaq 0x9b02(%rip), %rdi      # 0xe262
xorl %eax, %eax
callq 0x2050
jmp 0x4769
movl $0x0, 0x2e4(%rsp)
movl $0x1, 0x204(%rsp)
leaq 0x1a0(%rsp), %rdi
callq 0x74e0
leaq 0x2b8(%rsp), %rdi
callq 0x2130
jmp 0x47aa
leaq 0x2b8(%rsp), %rdi
callq 0x2130
jmp 0x47b9
movl 0x2e4(%rsp), %eax
addq $0x2e8, %rsp            # imm = 0x2E8
retq
movq 0x2a8(%rsp), %rdi
callq 0x2340
nopw %cs:(%rax,%rax)