Skip to content

[HTB Challenges] Writeup CTF: Baby RE

Strcmp? Ez
Strcmp? Ez

Baby RE adalah tantangan CTF kategori Reversing dengan tingkat kesulitan easy dari HTB Challenges. Tantangan ini dibuat oleh Xh4H dan telah dirilis pada 26 Oktober 2019.

Berikut adalah deskripsi dari tantangan ini:

Show us your basic skills! (P.S. There are 4 ways to solve this, are you willing to try them all?)

Pendahuluan

Setelah mengesktrak archive tantangan, saya menemukan satu file bernama baby.

Terminal
ls -lah
total 36K
drwxrwxr-x 3 kali kali 4.0K Mar 1 03:48 .
drwxrwxr-x 4 kali kali 4.0K Mar 1 03:36 ..
-rw-rw-r-- 1 kali kali 17K Oct 13 2019 baby
file baby
baby: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=25adc53b89f781335a27bf1b81f5c4cb74581022, for GNU/Linux 3.2.0, not stripped

File ini merupakan ELF 64-bit LSB pie executable yang merupakan file executable Linux.

Ketika saya menjalankan program ini, saya diminta untuk menginputkan key. Jika saya menginputkan sembarang teks, misalnya “test”, program akan menampilkan pesan “Try again later” lalu berhenti. Hal ini menunjukkan bahwa program hanya menerima key yang valid.

Terminal
chmod +x baby
./baby
Insert key:
test
Try again later.

Proof of Concept

Pada deskripsi tantangan disebutkan bahwa terdapat empat cara untuk menyelesaikan tantangan ini. Namun, saya hanya menemukan tiga cara, sebagaimana yang tercantum pada walkthrough resmi, yaitu:

  1. Menggunakan strings
  2. Analisis dinamis menggunakan ltrace
  3. Menggunakan decompiler

1. Menggunakan strings

Tantangan ini meminta saya untuk mendapatkan key yang valid agar bisa mendapatkan flag.

Langkah sederhana yang bisa saya lakukan adalah menggunakan strings untuk menampilkan semua string yang ada di dalam file executable tersebut.

Baca lebih lanjut tentang strings di sini.

Terminal
strings baby
/lib64/ld-linux-x86-64.so.2
mgUa
libc.so.6
puts
stdin
fgets
__cxa_finalize
strcmp
__libc_start_main
GLIBC_2.2.5
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
u/UH
HTB{B4BYH
_R3V_TH4H
TS_Ef
[]A\A]A^A_
Dont run `strings` on this challenge, that is not the way!!!!
Insert key:
abcde122313
Try again later.
;*3$"
GCC: (Debian 9.2.1-8) 9.2.1 20190909
crtstuff.c
deregister_tm_clones

Hasilnya, saya menemukan beberapa string yang menarik pada file baby, seperti:

  1. Terdapat potongan flag di sini:
HTB{B4BYH
_R3V_TH4H
TS_Ef
  1. Terdapat string “abcde122313” di antara “Insert Key” dan “Try again later”. Saya menduga ini adalah key yang dikomparasikan dengan inputan pengguna. Jika inputan salah, program akan menampilkan pesan “Try again later”.

Dari hasil analisis ini, saya mencoba menginputkan “abcde122313” sebagai key, dan hasilnya program menampilkan flag.

Terminal
./baby
Insert key:
abcde122313
HTB{B4BY_R3V_TH4TS_EZ}

2. Analisis dinamis menggunakan ltrace

Pada saat membuat program, ketika kita ingin melakukan perbandingan inputan biasanya menggunakan pengkondisian seperti if atau switch.

Sebagian besar file executable di Linux menggunakan libc (C Library) karena library ini menyediakan fungsi dasar (API) untuk berinteraksi dengan kernel dan sistem operasi.

Dalam bahasa C, terdapat fungsi strcmp() dan strncmp() untuk membandingkan dua string.

Untuk mengetahui apakah program tersebut memanggil shared library (seperti libc), saya mencoba menggunakan ltrace.

Baca lebih lanjut tentang ltrace di sini.

Terminal
ltrace ./baby
puts("Insert key: "Insert key:
) = 13
fgets(test
"test\n", 20, 0x7f3358e1a8e0) = 0x7ffe6545af20
strcmp("test\n", "abcde122313\n") = 13
puts("Try again later."Try again later.
) = 17
+++ exited (status 0) +++

Ketika saya menginputkan “test”, ltrace mendeteksi bahwa program melakukan pemanggilan fungsi berikut:

strcmp("test\n", "abcde122313\n")

Program ini membandingkan inputan pengguna dengan “abcde122313”, yang di mana ini adalah key yang valid untuk mendapatkan flag.

3. Analisis statik menggunakan decompiler

Dekompilasi program baby menggunakan Ghidra menghasilkan fungsi main() seperti berikut:

undefined8 main(void)
{
int iVar1;
undefined8 local_48;
undefined8 local_40;
undefined4 local_38;
undefined2 local_34;
char local_28 [24];
char *local_10;
local_10 = "Dont run `strings` on this challenge, that is not the way!!!!";
puts("Insert key: ");
fgets(local_28,0x14,stdin);
iVar1 = strcmp(local_28,"abcde122313\n");
if (iVar1 == 0) {
local_48 = 0x594234427b425448;
local_40 = 0x3448545f5633525f;
local_38 = 0x455f5354;
local_34 = 0x7d5a;
puts((char *)&local_48);
}
else {
puts("Try again later.");
}
return 0;
}

Baca lebih lanjut tentang Ghidra di sini.

Dari sini sebenarnya kita sudah mengetahui jawabannya, terdapat perbandingan inputan pengguna dan valid key pada baris kode ke-15.

Analisis Kode

Meskipun saya sudah mendapatkan jawaban dari tantangan ini, saya ingin menganalisis hasil dekompilasi tersebut lebih dalam untuk mempelajarinya secara lebih detail.

  1. Identifikasi fungsi main()
undefined8 main(void)
{
return 0;
}
return 0;
  1. Deklarasi variabel
int iVar1;
undefined8 local_48;
undefined8 local_40;
undefined4 local_38;
undefined2 local_34;
char local_28 [24];
char *local_10;

Mari kita identifikasi masing-masing variabel:

VariabelTipe DataFungsi
iVar1intMenyimpan hasil dari strcmp().
local_48, local_40, local_38, local_34undefined8, undefined4, undefined2Berisi flag dalam hex.
local_28char arrayMenyimpan input dari pengguna.
local_10char *Menyimpan string yang tidak pernah ditampilkan (tersembunyi).
  1. String tersembunyi
local_10 = "Dont run `strings` on this challenge, that is not the way!!!!";
  1. Meminta pengguna untuk menginputkan key
puts("Insert key: ");
fgets(local_28,0x14,stdin);
  1. Membandingkan input pengguna dengan key
iVar1 = strcmp(local_28,"abcde122313\n");
  1. Jika input benar, flag ditampilkan
if (iVar1 == 0) {
local_48 = 0x594234427b425448; // "YB4B{BTH" ➜ "HTB{B4BY"
local_40 = 0x3448545f5633525f; // "4HT_VER_" ➜ "_REV_TH4"
local_38 = 0x455f5354; // "E_ST" ➜ "TS_E"
local_34 = 0x7d5a; // "}Z" ➜ "Z}"
puts((char *)&local_48);
}
HexadecimalASCII (Terbalik)ASCII (Setelah Dibalik)
0x594234427b425448"YB4B{BTH""HTB{B4BY"
0x3448545f5633525f"4HT_VER_""_REV_TH4"
0x455f5354"E_ST""TS_E"
0x7d5a"}Z""Z}"
# Contoh pembacaan Little Endian untuk 0x594234427b425448
48 'H'
54 'T'
42 'B'
7b '{'
42 'B'
34 '4'
42 'B'
59 'Y'

Berikut adalah jika pseudocode tersebut ditulis ulang ke dalam kode C yang lebih readable:

if (strcmp(user_input, "abcde122313\n") == 0) {
char flag[] = "HTB{B4BY_REV_TH4TS_EZ}";
puts(flag);
}

Penutup

Itulah cara menyelesaikan tantangan Baby RE dari HTB Challenges dengan menggunakan teknik analisis statik dan dinamis. Semoga bermanfaat!


[HTB Challenges] Writeup CTF: You Cant You C Me
Apa itu Secure Software Development Life Cycle (SSDLC)?