You Cant C Me

HackTheBox Reversing Challenge

You Cant C Me adalah soal CTF kategori Reversing dengan tingkat kesulitan Easy. Soal ini dibuat oleh MinatoTW dan telah dirilis pada 13 April 2021.

Berikut adalah deskripsi dari tantangan ini:

Can you see me?

Introduction

Setelah mengesktrak archive soal, saya menemukan satu file bernama auth.

➜ ls -lah
total 28K
drwxrwxr-x 3 kali kali 4.0K Mar  5 05:06 .
drwxrwxr-x 5 kali kali 4.0K Mar  5 05:03 ..
-rwxr-xr-x 1 kali kali  15K Dec  1  2020 auth

➜ file auth 
auth: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, stripped

File ini merupakan executable Linux berformat ELF 64-bit LSB PIE. Selain itu, file ini telah di-strip sehingga nama fungsi tidak tersimpan.

Ketika menjalankan program ini, saya mencoba menginput "test" dan hasilnya program memberikan respons:

I said, you can't c me!

Penggunaan perintah strings tidak menemukan hal yang menarik. Terdapat string "this_is_the_password", ketika saya mencoba menginputkannya, program tetap memberikan respons yang sama (gagal).

➜ strings auth 

..<SNIPPED>..
Welcome!
I said, you can't c me!
HTB{%s}
this_is_the_password
m^&&fi
Uo&kUZ'ZUYUc)
;*3$"
..<SNIPPED>..

Proof of Concept

1. Analisis dinamis dengan ltrace

Untuk mendapatkan string yang valid, saya melakukan pengujian dinamis menggunakan ltrace. Dengan alat ini, saya dapat melihat fungsi-fugnsi yang dipanggil ketika program berjalan.

➜ ltrace ./auth
printf("Welcome!\n"Welcome!
)                                                                                                 = 9
malloc(21)                                                                                                           = 0x229cc6b0
fgets(test
"test\n", 21, 0x7f17c8dcc8e0)                                                                                  = 0x229cc6b0
strcmp("wh00ps!_y0u_d1d_c_m3", "test\n")                                                                             = 3
printf("I said, you can't c me!\n"I said, you can't c me!
)                                                                                  = 24
+++ exited (status 0) +++

Terlihat bahwa program melakukan validasi input dengan menggunakan fungsi strcmp, yang membandingkan input pengguna dengan string "wh00ps!_y0u_d1d_c_m3". Ketika saya menginputkan string tersebut, program akan menampilkan flag.

➜ ./auth                     
Welcome!
wh00ps!_y0u_d1d_c_m3
HTB{wh00ps!_y0u_d1d_c_m3}

2. Analisis statik dengan decompiler

Karena program telah di-strip, saya harus melihat setiap fungsi untuk menentukan mana yang merupakan fungsi utama. Setelah melihat-lihat, saya menemukan fungsi FUN_00401160(void) yang memiliki string "I said, you can't c me!".

undefined4 FUN_00401160(void)

{
  int iVar1;
  undefined8 local_48;
  undefined8 local_40;
  undefined4 local_38;
  char *local_30;
  undefined8 local_28;
  undefined8 local_20;
  undefined4 local_18;
  undefined local_14;
  int local_10;
  undefined4 local_c;
  
  local_c = 0;
  local_10 = 0;
  printf("Welcome!\n");
  local_28._0_1_ = 't';
  local_28._1_1_ = 'h';
  local_28._2_1_ = 'i';
  local_28._3_1_ = 's';
  local_28._4_1_ = '_';
  local_28._5_1_ = 'i';
  local_28._6_1_ = 's';
  local_28._7_1_ = '_';
  local_20._0_1_ = 't';
  local_20._1_1_ = 'h';
  local_20._2_1_ = 'e';
  local_20._3_1_ = '_';
  local_20._4_1_ = 'p';
  local_20._5_1_ = 'a';
  local_20._6_1_ = 's';
  local_20._7_1_ = 's';
  local_18 = 0x64726f77;
  local_14 = 0;
  local_30 = (char *)malloc(0x15);
  local_48 = 0x5517696626265e6d;
  local_40 = 0x555a275a556b266f;
  local_38 = 0x29635559;
  for (local_10 = 0; local_10 < 0x14; local_10 = local_10 + 1) {
    *(char *)((long)&local_28 + (long)local_10) = *(char *)((long)&local_48 + (long)local_10) + '\n'
    ;
  }
  fgets(local_30,0x15,stdin);
  iVar1 = strcmp((char *)&local_28,local_30);
  if (iVar1 == 0) {
    printf("HTB{%s}\n",local_30);
  }
  else {
    printf("I said, you can\'t c me!\n");
  }
  return local_c;
}

Untuk mempermudah analisis, saya mengubah beberapa nama variabel sehingga terlihat seperti berikut:


undefined4 FUN_00401160(void)

{
  int isInputValid;
  undefined8 encrypted;
  undefined8 local_40;
  undefined4 local_38;
  char *input;
  undefined8 decrypted;
  undefined8 local_20;
  undefined4 local_18;
  undefined local_14;
  int i;
  undefined4 local_c;
  
  local_c = 0;
  i = 0;
  printf("Welcome!\n");
  decrypted._0_1_ = 't';
  decrypted._1_1_ = 'h';
  decrypted._2_1_ = 'i';
  decrypted._3_1_ = 's';
  decrypted._4_1_ = '_';
  decrypted._5_1_ = 'i';
  decrypted._6_1_ = 's';
  decrypted._7_1_ = '_';
  local_20._0_1_ = 't';
  local_20._1_1_ = 'h';
  local_20._2_1_ = 'e';
  local_20._3_1_ = '_';
  local_20._4_1_ = 'p';
  local_20._5_1_ = 'a';
  local_20._6_1_ = 's';
  local_20._7_1_ = 's';
  local_18 = 0x64726f77;
  local_14 = 0;
  input = (char *)malloc(21);
  encrypted = 0x5517696626265e6d;
  encrypted2 = 0x555a275a556b266f;
  encrypted3 = 0x29635559;
  for (i = 0; i < 20; i = i + 1) {
    *(char *)((long)&decrypted + (long)i) = *(char *)((long)&encrypted + (long)i) + '\n';
  }
  fgets(input,21,stdin);
  isInputValid = strcmp((char *)&decrypted,input);
  if (isInputValid == 0) {
    printf("HTB{%s}\n",input);
  }
  else {
    printf("I said, you can\'t c me!\n");
  }
  return local_c;
}

Dari sini, saya dapat menyimpulkan bahwa terdapat string terenkripsi, yaitu:

  • 0x5517696626265e6d

  • 0x555a275a556b266f

  • 0x29635559

Untuk mendapatkan hasil dekripsi, kita harus menambahkan nilai \n (nilai ASCII 10) ke setiap karakter.

Dari hasil analisis ini, saya mencoba merekode program tersebut menggunakan bahasa C sehingga terlihat seperti berikut:

#include <stdio.h>
#include <string.h>

int main() {

  // set variable
  int isInputValid;
  char input[21];
  char decrypted[20];
  char encrypted[20] = {0x6d, 0x5e, 0x26, 0x26, 0x66, 0x69, 0x17, 0x55,  // 0x5517696626265e6d
                       0x6f, 0x26, 0x6b, 0x55, 0x5a, 0x27, 0x5a, 0x55,   // 0x555a275a556b266f
                       0x59, 0x55, 0x63, 0x29 };                         // 0x29635559 

  for (int i = 0; i < 20; i = i + 1) {
    decrypted[i] = encrypted[i] + '\n';
  }

  printf("decrypted: %s\n", decrypted); // for debugs

  printf("Welcome!\n");
  fgets(input, sizeof(input), stdin);

  isInputValid = strcmp(decrypted, input);

  if (isInputValid == 0) {
    printf("HTB{%s}", decrypted);
  } else {
    printf("I said, you can\'t c me!\n");
  }
  
  return 0;
}

Hasilnya:

➜ gcc main.c -o main; sleep 2 ; ./main
decrypted: wh00ps!_y0u_d1d_c_m3
Welcome!
wh00ps!_y0u_d1d_c_m3
HTB{wh00ps!_y0u_d1d_c_m3}

Last updated