Baby RE
HackTheBox Reversing Challenge
Baby RE adalah soal CTF kategori Reversing dengan tingkat kesulitan Easy. Soal 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?)
Introduction
Setelah mengesktrak archive soal, saya menemukan satu file bernama baby
.
➜ 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.
➜ chmod +x baby
➜ ./baby
Insert key:
test
Try again later.
Proof of Concept
Pada deskripsi soal dinyatakan bahwa ada empat cara untuk menyelesaikan soal ini. Namun, saya hanya akan membahas tiga cara, sesuai dengan walkthough resmi yang juga hanya mencakup tiga metode, yaitu:
Menggunakan
strings
.Melakukan analisis dinamis menggunakan
ltrace
.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 mencoba menemukan key pada file biner.
➜ 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:
Terdapat potongan flag di sini:
HTB{B4BYH
_R3V_TH4H
TS_Ef
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.
➜ ./baby
Insert key:
abcde122313
HTB{B4BY_R3V_TH4TS_EZ}
2. Analisis dinamis dengan ltrace
Berdasarkan pengalaman saya, umumnya perbandingan input yang valid atau tidak menggunakan pengkondisian seperti if
. Pada program yang ditulis dalam bahasa C, fungsi untuk membandingkan string adalah strcmp()
.
Untuk mengetahui apakah program menggunakan fungsi strcmp()
, saya mencoba menjalankan perintah ltrace
.
Saya mencoba menjalankan ltrace
pada program baby
:
➜ 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")
Kode ini membandingkan input pengguna dengan "abcde122313", yang ternyata adalah key yang valid untuk mendapatkan flag.
3. Analisis statik dengan decompiler
Dekompilasi 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;
}
Dari sini, sebenarnya kita sudah mengetahui jawabannya. Perbandingan antara inputan dan key terdapat pada baris kode berikut:
iVar1 = strcmp(local_28,"abcde122313\n");
Analisis Kode
Meskipun saya sudah mendapatkan jawaban dari tantangan ini, saya ingin menganalisis hasil dekompilasi tersebut lebih dalam untuk mempelajarinya secara lebih detail.
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:
iVar1
int
Variabel untuk menyimpan hasil dari strcmp()
.
local_48
, local_40
, local_38
, local_34
undefined8
, undefined4
, undefined2
Berisi bagian dari flag.
local_28
char array
Variabel untuk menyimpan input dari pengguna.
local_10
char *
Menyimpan string yang tidak pernah ditampilkan (tersembunyi).
Membandingkan input pengguna dengan key
iVar1 = strcmp(local_28,"abcde122313\n");
Fungsi
strcmp()
membandingkan input pengguna dengan"abcde122313\n"
. Jika cocok, nilai yang akan dikembalikan bernilai 0.Hasil perbandingan tersebut akan disimpan dalam variabel
iVar1
.
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);
}
if (iVar1 == 0)
Jika variabel
iVar1
bernilai 0, maka flag akan ditampilkan.
Penjelasan flag:
Flag dipecah menjadi 4 bagian, setiap bagian memiliki kapasitas maksimal 8 byte.
Hal ini terjadi karena arsitektur CPU 64-bit (x86-64) lebih efisien membaca data dalam unit 64-bit (8 byte).
Little Endian (dibalik)
CPU x86-64 menggunakan Little Endian, sehingga data hex yang tersimpan di memori harus dibalik agar terbaca dengan benar.
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);
}
Last updated