Tags: rev 

Rating:

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.

```C
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;
}
```

```C
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;
}
```

```C
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:

```Python
#!/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}```

Original writeup (https://w0y.at/writeup/2021/05/17/dctf-2021-bell.html).