[Cyber Jawara Quals 2017] Zero Day Market (75 Poin)

Masalah

Diberikan berkas zero_day_market dan layanan yang tersedia pada nc cj2k17.ctf.idsirtii.or.id 21337.

Penyelesaian

Pengumpulan Informasi

Kami memeriksa jenis berkas dan keamanan yang ada didalamnya dengan file dan checksec.

$ file zero_day_market 
zero_day_market: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=77e3afe31565bf7337bb81bf51e65dab7d12ac93, not stripped

$ checksec zero_day_market 
[*] '/.../zero_day_market'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled

Berdasarkan informasi diatas, keamanan binary diaktifkan semua dan arsitektur yang digunakan adalah Linux 64 bit.

Alur Program Program menampilkan menu untuk membeli dan menjual exploit dengan harga yang bisa diatur sendiri dengan saldo awal 10 BTC.

$ ./zero_day_market 
== WELCOME TO CYBER JAWARA ZERO DAY MARKET ==

Your Money: 10 BTC

1) Buy
2) Sell
3) Exit
Your choice: 1

- ZERO DAY LIST -
[1] Chrome Exploit | 100 BTC
[2] Safari Exploit | 100 BTC
[3] Windows 10 Exploit | 150 BTC
[4] Git Exploit | 5 BTC
[5] Jenkins Exploit | 5 BTC
[6] Flag | 99999999 BTC
Choose Number: 4
Buy Git Exploit with 5 BTC

Your Money: 5 BTC

1) Buy
2) Sell
3) Exit
Your choice: 2

- YOUR INVENTORY -
[1] Git Exploit
Choose Number: 1
Price: 5
Sold! You get 5 BTC

Your Money: 10 BTC

1) Buy
2) Sell
3) Exit
Your choice: 3

Tujuan utama pada program ini adalah membeli Flag melalui opsi 6, namun harganya terlampau mahal.

Dekompilasi Kami melakukan dekompilasi untuk memahami alur program lebih jelas lagi. Terdapat fungsi main yang berisi struktur awal program.

// local variable allocation has failed, the output may be wrong!
int __cdecl main(int argc, const char **argv, const char **envp)
{
  init(*(_QWORD *)&argc, argv, envp);
  load_flag();
  market();
  return 0;
}

Program menginisiasi Flag yang disimpan pada opsi 6, dan fungsi market berisi alur jual-beli exploit.

int load_flag()
{
  FILE *stream; // ST08_8@1

  stream = fopen("flag.txt", "r");
  fread(flag, 1uLL, 0x2AuLL, stream);
  return fclose(stream);
}

Pada fungsi market, menu utama ditampilkan.

__int64 market()
{
  char v0; // ST07_1@2
  char v1; // ST06_1@6
  char v2; // ST07_1@6
  char v3; // ST06_1@21
  char v4; // ST07_1@21
  char v5; // ST07_1@25
  char v7; // [sp+6h] [bp-BAh]@2
  unsigned int v8; // [sp+8h] [bp-B8h]@25
  unsigned int v9; // [sp+Ch] [bp-B4h]@1
  int i; // [sp+10h] [bp-B0h]@3
  int v11; // [sp+14h] [bp-ACh]@14
  int j; // [sp+18h] [bp-A8h]@29
  int v13; // [sp+1Ch] [bp-A4h]@6
  int v14; // [sp+20h] [bp-A0h]@1
  int v15; // [sp+24h] [bp-9Ch]@1
  int v16; // [sp+28h] [bp-98h]@1
  int v17; // [sp+2Ch] [bp-94h]@1
  int v18; // [sp+30h] [bp-90h]@1
  int v19; // [sp+34h] [bp-8Ch]@1
  int v20; // [sp+40h] [bp-80h]@1
  int v21; // [sp+44h] [bp-7Ch]@1
  int v22; // [sp+48h] [bp-78h]@1
  int v23; // [sp+4Ch] [bp-74h]@1
  int v24; // [sp+50h] [bp-70h]@1
  int v25; // [sp+54h] [bp-6Ch]@1
  int v26; // [sp+60h] [bp-60h]@1
  int v27; // [sp+64h] [bp-5Ch]@1
  int v28; // [sp+68h] [bp-58h]@1
  int v29; // [sp+6Ch] [bp-54h]@1
  int v30; // [sp+70h] [bp-50h]@1
  int v31; // [sp+74h] [bp-4Ch]@1
  const char *v32; // [sp+80h] [bp-40h]@1
  const char *v33; // [sp+88h] [bp-38h]@1
  const char *v34; // [sp+90h] [bp-30h]@1
  const char *v35; // [sp+98h] [bp-28h]@1
  const char *v36; // [sp+A0h] [bp-20h]@1
  const char *v37; // [sp+A8h] [bp-18h]@1
  __int64 v38; // [sp+B8h] [bp-8h]@1

  v38 = *MK_FP(__FS__, 40LL);
  v14 = 0;
  v15 = 0;
  v16 = 0;
  v17 = 0;
  v18 = 0;
  v19 = 0;
  v20 = 0;
  v21 = 0;
  v22 = 0;
  v23 = 0;
  v24 = 0;
  v25 = 0;
  v26 = 100;
  v27 = 100;
  v28 = 150;
  v29 = 5;
  v30 = 5;
  v31 = 99999999;
  v32 = "Chrome Exploit";
  v33 = "Safari Exploit";
  v34 = "Windows 10 Exploit";
  v35 = "Git Exploit";
  v36 = "Jenkins Exploit";
  v37 = "Flag";
  puts("== WELCOME TO CYBER JAWARA ZERO DAY MARKET ==");
  v9 = 10;
  while ( 1 )
  {
    while ( 1 )
    {
      puts(&byte_106E);
      printf("Your Money: %u BTC\n", v9);
      puts(&byte_106E);
      puts("1) Buy");
      puts("2) Sell");
      puts("3) Exit");
      printf("Your choice: ");
      v7 = getchar();
      v0 = getchar();
      if ( v7 != 49 )
        break;
      puts(&byte_106E);
      puts("- ZERO DAY LIST -");
      for ( i = 0; i <= 5; ++i )
        printf("[%d] %s | %d BTC\n", (unsigned int)(i + 1), (&v32)[8 * i], (unsigned int)*(&v26 + i));
      printf("Choose Number: ");
      v1 = getchar();
      v2 = getchar();
      v13 = v1 - 49;
      if ( v13 >= 0 && v13 <= 5 )
      {
        if ( *(&v26 + v13) <= v9 )
        {
          printf("Buy %s with %d BTC\n", (&v32)[8 * v13], (unsigned int)*(&v26 + v13));
          v9 -= *(&v26 + v13);
          ++*(&v14 + v13);
          if ( v13 == 5 )
            puts(flag);
        }
        else
        {
          puts("Not Enough Money!");
        }
      }
      else
      {
        puts("Invalid Number");
      }
    }
    if ( v7 != 50 )
      break;
    puts(&byte_106E);
    puts("- YOUR INVENTORY -");
    v11 = 0;
    for ( i = 0; i <= 5; ++i )
    {
      if ( *(&v14 + i) )
      {
        printf("[%d] %s\n", (unsigned int)(v11 + 1), (&v32)[8 * i]);
        *(&v20 + v11++) = i;
      }
    }
    if ( v11 )
    {
      printf("Choose Number: ");
      v3 = getchar();
      v4 = getchar();
      v13 = v3 - 48;
      if ( v13 > 0 && v13 <= v11 )
      {
        if ( *(&v20 + --v13) )
        {
          printf("Price: ");
          _isoc99_scanf("%d", &v8);
          v5 = getchar();
          v11 = *(&v20 + v13);
          if ( *(&v26 + v11) >= (signed int)v8 )
          {
            printf("Sold! You get %d BTC\n", v8);
            v9 += v8;
            --*(&v14 + v11);
          }
          else
          {
            printf(
              "No one want to buy! %s price in the market is %d BTC\n",
              (&v32)[8 * v11],
              (unsigned int)*(&v26 + v11));
          }
        }
        else
        {
          puts("Invalid Number");
        }
        for ( j = 0; j <= 5; ++j )
          *(&v20 + j) = 0;
      }
      else
      {
        puts("Invalid Number");
      }
    }
    else
    {
      puts("You have nothing");
    }
  }
  return *MK_FP(__FS__, 40LL) ^ v38;
}

Identifikasi Kelemahan

Berdasarkan informasi diatas, terdapat kelemahan Integer Overflow. Tepatnya pada fungsi market pada bagian struktur kondisonal penjualan exploit disebabkan oleh cast ke tipe data Signed Int.

if ( *(&v20 + --v13) )
        {
          printf("Price: ");
          _isoc99_scanf("%d", &v8);
          v5 = getchar();
          v11 = *(&v20 + v13);
          if ( *(&v26 + v11) >= (signed int)v8 )
          {
            printf("Sold! You get %d BTC\n", v8);
            v9 += v8;
            --*(&v14 + v11);
          }
          else
          {
            printf(
              "No one want to buy! %s price in the market is %d BTC\n",
              (&v32)[8 * v11],
              (unsigned int)*(&v26 + v11));
          }
        }

Jika penjualan dilakukan dengan memasukkan input sebesar -2147483647 maka saldo yang didapat bertambah sebesar 2147483647 BTC.

Eksploitasi

nc cj2k17.ctf.idsirtii.or.id 21337
== WELCOME TO CYBER JAWARA ZERO DAY MARKET ==

Your Money: 10 BTC

1) Buy
2) Sell
3) Exit
Your choice: 1

- ZERO DAY LIST -
[1] Chrome Exploit | 100 BTC
[2] Safari Exploit | 100 BTC
[3] Windows 10 Exploit | 150 BTC
[4] Git Exploit | 5 BTC
[5] Jenkins Exploit | 5 BTC
[6] Flag | 99999999 BTC
Choose Number: 5
Buy Jenkins Exploit with 5 BTC

Your Money: 5 BTC

1) Buy
2) Sell
3) Exit
Your choice: 2

- YOUR INVENTORY -
[1] Jenkins Exploit
Choose Number: 1
Price: -2147483647
Sold! You get -2147483647 BTC

Your Money: 2147483654 BTC

1) Buy
2) Sell
3) Exit
Your choice: 1

- ZERO DAY LIST -
[1] Chrome Exploit | 100 BTC
[2] Safari Exploit | 100 BTC
[3] Windows 10 Exploit | 150 BTC
[4] Git Exploit | 5 BTC
[5] Jenkins Exploit | 5 BTC
[6] Flag | 99999999 BTC
Choose Number: 6
Buy Flag with 99999999 BTC
CJ2017{y0_d4w6_buy_zero_day_with_zero_day}

Your Money: 2047483655 BTC

1) Buy
2) Sell
3) Exit
Your choice:

Flag yang didapat adalah CJ2017{y0_d4w6_buy_zero_day_with_zero_day}.

results matching ""

    No results matching ""