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}