[Pwnable] [LINE CTF 2021] Query Firewall

image.png

image.png

2021 LINE CTF에 출제됐었던 문제다.

난이도는 9레벨, 풀이 인원은 총 3명으로 난이도가 매우 높다..

그래도 눈에 보였으니 한번 풀어보고 싶어졌다.

image.png

분석 가능한 파일은 이렇게 존재한다.

data.db에는 아무런 내용이 없고, client와 firewall.sqlext 바이너리를 분석하는 문제 같다.

image.png

RELRO를 제외한 모든 보안이 다 걸려있다고 볼 수 있다.

바로 IDA로 분석 이어가보겠다.

image.png

이게 도대체 무슨 끔찍한 오버뷰야…

main() 함수부터 살펴보겠다.

image.png

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  char v4; // [rsp+3h] [rbp-13Dh]
  int v5; // [rsp+4h] [rbp-13Ch] BYREF
  int v6; // [rsp+8h] [rbp-138h] BYREF
  int i; // [rsp+Ch] [rbp-134h]
  int v8; // [rsp+10h] [rbp-130h]
  int v9; // [rsp+14h] [rbp-12Ch]
  __int64 v10; // [rsp+18h] [rbp-128h] BYREF
  const char *v11; // [rsp+20h] [rbp-120h] BYREF
  void *buf; // [rsp+28h] [rbp-118h]
  char s[264]; // [rsp+30h] [rbp-110h] BYREF
  unsigned __int64 v14; // [rsp+138h] [rbp-8h]

  v14 = __readfsqword(0x28u);
  signal(14, handler);
  alarm(0x1Eu);
  v11 = 0;
  v4 = 1;
  setvbuf(stdin, 0, 2, 0);
  setvbuf(stdout, 0, 2, 0);
  if ( (unsigned int)sqlite3_open("data.db", &v10) )
  {
    puts("Cannot open database...");
    exit(0);
  }
  v8 = sqlite3_load_extension(v10, "./firewall.sqlext", 0, &v11);
  if ( v8 )
  {
    printf("SQL Error: %s\\n", v11);
    sqlite3_free(v11);
    exit(0);
  }
  buf = malloc(0x68u);
  while ( v4 )
  {
    puts("\\n[ Menu ]");
    puts("1. show version");
    puts("2. run query");
    puts("3. show blocked query");
    puts("4. remove blocked query");
    puts("5. exit");
    printf("> ");
    __isoc99_scanf("%d", &v5);
    switch ( v5 )
    {
      case 1:
        strcpy(s, "select sqlite_version();");
        v8 = sqlite3_exec(v10, s, sub_D10, 0, &v11);
        if ( v8 )
          goto LABEL_21;
        break;
      case 2:
        printf("query> ");
        v9 = read(0, buf, 0x60u);
        *((_BYTE *)buf + v9) = 0;
        for ( i = 0; i <= 95; ++i )
        {
          if ( *((_BYTE *)buf + i) == 34 )
          {
            puts("double quotes is not allow.");
            exit(0);
          }
        }
        sprintf(s, "select block(\\"%s\\");", (const char *)buf);
        v8 = sqlite3_exec(v10, s, sub_D10, 0, &v11);
        if ( v8 )
          goto LABEL_21;
        printf("query didn't blocked...\\n[+] now execute it: %s\\n", (const char *)buf);
        v8 = sqlite3_exec(v10, buf, sub_D10, 0, &v11);
        if ( v8 )
          goto LABEL_21;
        break;
      case 3:
        printf("query index> ");
        __isoc99_scanf("%d", &v6);
        sprintf(s, "select block_log(%d);", v6);
        v8 = sqlite3_exec(v10, s, sub_D10, 0, &v11);
        if ( v8 )
          goto LABEL_21;
        break;
      case 4:
        v8 = sqlite3_exec(v10, "select block_remove();", sub_D10, 0, &v11);
        if ( v8 )
        {
LABEL_21:
          printf("SQL Error: %s\\n", v11);
          sqlite3_free(v11);
        }
        break;
      case 5:
        v4 = 0;
        break;
      default:
        continue;
    }
  }
  sqlite3_close(v10);
  free(buf);
  return 0;
}

함수 개요