DCTF 2021 - Bell

Read number and run throught known function

Description

Blaise's friends like triangles too! nc dctf-chall-bell.westeurope.azurecontainer.io 5311

Preface

The function gives us a number and then waits for multiple inputs.

Overview

Loading the file into ghidra we can take a look at what happens.

undefined8 main(void)
{
  int iVar1;
  uint uVar2;
  time_t tVar3;

  tVar3 = time((time_t *)0x0);
  srand((uint)tVar3);
  iVar1 = rand();
  uVar2 = iVar1 % 5 + 8;
  printf("%d\n",(ulong)uVar2);
  process((ulong)uVar2);
  return 0;
}
undefined8 process(uint param_1)
{
  long lVar1;
  bool bVar2;
  long lVar3;
  long in_FS_OFFSET;
  uint local_24;
  long local_20;

  lVar1 = *(long *)(in_FS_OFFSET + 0x28);
  bVar2 = true;
  local_24 = 1;
  while ((int)local_24 <= (int)param_1) {
    lVar3 = triangle((ulong)param_1,(ulong)local_24,(ulong)local_24);
    __isoc99_scanf();
    if (lVar3 != local_20) {
      bVar2 = false;
    }
    local_24 = local_24 + 1;
  }
  if (bVar2) {
    system("cat flag.txt");
  }
  else {
    puts("Better luck next time.");
  }
  if (lVar1 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return 0;
}
long triangle(uint param_1,int param_2)
{
  long lVar1;
  long lVar2;

  if ((int)param_1 < param_2) {
    lVar1 = 0;
  }
  else {
    if ((param_1 == 1) && (param_2 == 1)) {
      lVar1 = 1;
    }
    else {
      if (param_2 == 1) {
        lVar1 = triangle((ulong)(param_1 - 1),(ulong)(param_1 - 1),(ulong)(param_1 - 1));
      }
      else {
        lVar2 = triangle((ulong)param_1,(ulong)(param_2 - 1U),(ulong)(param_2 - 1U));
        lVar1 = triangle((ulong)(param_1 - 1),(ulong)(param_2 - 1U),(ulong)(param_2 - 1U));
        lVar1 = lVar1 + lVar2;
      }
    }
  }
  return lVar1;
}

From this I could see, I can win, if I just run the same operations and print my solutions. So I rewrote the triangle function in Python3 and integrated a read of the random number. My final script was:

#!/usr/bin/env python3
from pwn import *

context.arch = 'amd64'
context.kernel = 'amd64'
#context.log_level = "DEBUG"
context.log_level = "INFO"

def triangle(a,b):
    if a < b:
        return 0
    else:
        if a == 1 and b == 1:
            return 1
        else:
            if b == 1:
                return triangle(a-1,a-1)
            else:
                return triangle(a,b-1) + triangle(a-1,b-1)

p = remote("dctf-chall-bell.westeurope.azurecontainer.io", 5311)

random = int(p.readuntil('\n')[:-1].decode('ASCII'))
print(random)

for i in range(1,(random)+1):
    p.sendline(str(triangle(random,i)))

p.interactive()

Running this gives the flag.

dctf{f1rst_step_t0wards_b3ll_l4bs}


Navigation