😈
ReverseMe
  • Introduction
  • References
  • ReverseMe
    • Introduction
      • What is Reverse Engineering?
      • Legality of Reverse Engineering
      • Reverse Engineering Communities
  • Programming Language
    • C
      • Basic
        • Pointer
        • Casting
      • Reference
        • stdio.h
          • fclose()
          • fopen()
          • fseek()
          • ftell()
          • fgetc()
          • fgets()
          • fread()
          • fprintf()
          • fwrite()
          • printf()
          • putchar()
          • puts()
          • sprintf()
          • snprintf()
        • stdlib.h
          • malloc()
          • calloc()
          • realloc()
          • free()
          • rand()
          • srand()
        • string.h
          • strcat()
          • strncat()
          • strcmp()
          • strncmp()
          • strcpy()
          • strncpy()
        • time.h
          • time()
  • Reversing Fundamentals
    • Stripped and Unstripped
  • Tools
    • file
    • strings
    • ltrace
    • ghidra
  • CTF Writeups
    • HackTheBox Challenges
      • Baby RE
      • You Cant C Me
  • ABOUT ME
    • Mail
    • LinkedIn
    • GitHub
Powered by GitBook
On this page
  • Introduction
  • Proof of Concept
  • 1. Menggunakan strings
  • 2. Analisis dinamis dengan ltrace
  • 3. Analisis statik dengan decompiler
  1. CTF Writeups
  2. HackTheBox Challenges

Baby RE

HackTheBox Reversing Challenge

PreviousHackTheBox ChallengesNextYou Cant C Me

Last updated 2 months ago

adalah soal CTF kategori Reversing dengan tingkat kesulitan Easy. Soal ini dibuat oleh 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:

  1. Menggunakan strings.

  2. Melakukan 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 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:

  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.

➜ ./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.

1

Identifikasi fungsi main()

undefined8 main(void)

{
  
  return 0;
}
  • Fungsi ini tidak menerima argument (void).

  • Tipe data undefined8 seharusnya adalah int, seperti yang dapat dilihat pada baris pengembalian nilai:

return 0;
2

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:

Variabel
Tipe Data
Fungsi

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).

3

String tersembunyi

local_10 = "Dont run `strings` on this challenge, that is not the way!!!!";
  • Menyimpan string ke dalam variabel local_10 dan tidak pernah ditampilkan.

  • Ini menjadi petunjuk kepada pengguna untuk tidak menggunakan strings dalam menyelesaikan tantangan.

4

Meminta pengguna untuk menginputkan key

puts("Insert key: ");
fgets(local_28,0x14,stdin);
5

Membandingkan input pengguna dengan key

iVar1 = strcmp(local_28,"abcde122313\n");
  • Hasil perbandingan tersebut akan disimpan dalam variabel iVar1.

6

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.

Hexadecimal
ASCII (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);
}

Baca lebih lanjut tentang strings .

Baca lebih lanjut tentang ltrace .

Baca lebih lanjut tentang strcmp() .

Baca lebih lanjut tentang Ghidra .

akan menampilkan string ke layar.

akan menyimpan input pengguna ke dalam variabel local_28 dengan maksimal 20 karakter (0x14).

Fungsi membandingkan input pengguna dengan "abcde122313\n". Jika cocok, nilai yang akan dikembalikan bernilai 0.

Baby RE
Xh4H
di sini
di sini
di sini
di sini
puts()
fgets()
strcmp()