Skip to content
Home » ELF C++ 0 protection — Rootme Writeup

ELF C++ 0 protection — Rootme Writeup

  • Writeup

Dalam artikel ini, saya akan membahas cara menyelesaikan challenge “ELF C++ 0 Protection” di platform Root-Me, dengan nilai 10 poin. Tantangan ini meminta kita untuk menemukan password validasi dari sebuah file binary.

Analisis Awal

Pertama, mari kita download dan periksa file binary yang diberikan (ch25.bin):

/ROOTME/ ls ch25.bin
ch25.bin

/ROOTME/ ./ch25.bin
usage : ./ch25.bin password

/ROOTME/ ./ch25.bin acak
Password incorrect.

Ketika dijalankan tanpa argumen, program menampilkan cara penggunaannya. Ketika diberi password yang salah, program hanya menampilkan “Password incorrect.”

Decompiling dengan Ghidra

Untuk memahami program lebih baik, saya akan menganalisisnya menggunakan decompiler Ghidra. Mencari referensi “Password incorrect”, saya menemukan fungsi main:

undefined4 main(int param_1,undefined4 *param_2)
{
  char *pcVar1;
  bool bVar2;
  ostream *poVar3;
  undefined4 uVar4;
  allocator local_1e;
  allocator local_1d;
  string local_1c [4];
  string local_18 [4];
  string local_14 [4];
  undefined4 *local_10;
  
  local_10 = &param_1;
  if (param_1 < 2) {
    // Menampilkan pesan penggunaan jika tidak ada argumen
    pcVar1 = (char *)*param_2;
    poVar3 = std::operator<<((ostream *)std::cerr,"usage : ");
    poVar3 = std::operator<<(poVar3,pcVar1);
    poVar3 = std::operator<<(poVar3," password");
    std::ostream::operator<<(poVar3,std::endl<>);
    uVar4 = 5;
  }
  else {
    // Inisialisasi string dari data statis di binary
    std::allocator<char>::allocator();
    std::string::string(local_14,&DAT_08048dc4,&local_1d);
    std::allocator<char>::allocator();
    std::string::string(local_18,&DAT_08048dcc,&local_1e);
    
    // Memproses string melalui fungsi plouf
    plouf(local_1c,local_18,local_14);
    std::string::~string(local_18);
    std::allocator<char>::~allocator((allocator<char> *)&local_1e);
    std::string::~string(local_14);
    std::allocator<char>::~allocator((allocator<char> *)&local_1d);
    
    // Membandingkan hasil dengan password yang diberikan
    bVar2 = std::operator==(local_1c,(char *)param_2[1]);
    if (bVar2) {
      poVar3 = std::operator<<((ostream *)std::cout,
                               "Bravo, tu peux valider en utilisant ce mot de passe...");
      std::ostream::operator<<(poVar3,std::endl<>);
      poVar3 = std::operator<<((ostream *)std::cout,
                               "Congratz. You can validate with this password...");
      std::ostream::operator<<(poVar3,std::endl<>);
    }
    else {
      poVar3 = std::operator<<((ostream *)std::cout,"Password incorrect.");
      std::ostream::operator<<(poVar3,std::endl<>);
    }
    uVar4 = 0;
    std::string::~string(local_1c);
  }
  return uVar4;
}

Memahami Logika Program

Fungsi main menggunakan dua string kunci yang disimpan sebagai konstanta dalam binary: DAT_08048dc4 dan DAT_08048dcc.

String-string ini dimasukkan ke sebuah fungsi bernama plouf(), yang kemudian menghasilkan output yang disimpan dalam local_1c. Hasil ini kemudian dibandingkan dengan password yang dimasukkan oleh pengguna. Jika cocok, pesan keberhasilan akan ditampilkan.

Mari kita periksa fungsi plouf():

string * plouf(string *param_1,uint param_2,uint param_3)
{
  byte bVar1;
  byte *pbVar2;
  char *pcVar3;
  allocator local_21;
  int local_20;
  
  std::allocator<char>::allocator();
  std::string::string(param_1,"",&local_21);
  std::allocator<char>::~allocator((allocator<char> *)&local_21);
  local_20 = 0;
  while( true ) {
    pcVar3 = (char *)std::string::operator[](param_2);
    if (*pcVar3 == '\0') break;
    pbVar2 = (byte *)std::string::operator[](param_2);
    bVar1 = *pbVar2;
    std::string::length();
    pbVar2 = (byte *)std::string::operator[](param_3);
    std::string::operator+=(param_1,*pbVar2 ^ bVar1);
    local_20 = local_20 + 1;
  }
  return param_1;
}

Fungsi plouf() melakukan operasi XOR antara karakter-karakter dari dua string input dan menggabungkan hasilnya.

Mengekstrak Nilai Kunci dengan GDB

Untuk mengekstrak nilai asli dari DAT_08048dc4 dan DAT_08048dcc, saya akan menggunakan GDB:

(gdb) x/s 0x8048dc4
0x8048dc4: "\030\326\025\312\372w"

(gdb) x/s 0x08048dcc
0x8048dcc: "P\263g\257\245\016w\243J\242\233\001}\211a\245\245\002v\262p\270\211\003y\270q\225\233(t\277a\276\226\022G\225>\341\245\004l\243s\254\211"

Mendekode Password

Sekarang setelah saya memiliki dua komponen kunci, saya dapat mendekode password dengan mengimplementasikan operasi XOR yang sama dalam Python:

# Kunci dan Password Terenkripsi dari hasil GDB
key = b"\x18\xd6\x15\xca\xfa\x77"
encoded = b"P\xb3g\xaf\xa5\x0ew\xa3J\xa2\x9b\x01}\x89a\xa5\xa5\x02v\xb2p\xb8\x89\x03y\xb8q\x95\x9b(t\xbfa\xbe\x96\x12G\x95>\xe1\xa5\x04l\xa3s\xac\x89"

# Proses dekoding XOR berdasarkan panjang kunci
decoded = bytes([encoded[i] ^ key[i % len(key)] for i in range(len(encoded))])

# Menampilkan password yang dihasilkan
print("Decoded Password:", decoded.decode(errors="ignore"))

Menjalankan script ini menghasilkan jawaban:

Decoded Password: Here_you_have_to_understand_a_little_C++_stuffs

Solusi

Password untuk challenge ini adalah: Here_you_have_to_understand_a_little_C++_stuffs

Challenge ini membutuhkan pemahaman tentang reverse engineering binary C++, ekstraksi nilai kunci menggunakan GDB, dan implementasi algoritma dekripsi XOR sederhana untuk mendapatkan password tersembunyi.

Leave a Reply

Your email address will not be published. Required fields are marked *