Reverse Engineering

ChallengeLink

Yggdarsil (656 Pts)

Here

Goliath (699 Pts)

Here

Yggdarsil (656 Pts)

Description

-

PoC

Diberikan file mach-o , jadi kami coba jalankan terlebih dahulu menggunakan vm mac-os.

Selanjutnya kita coba lakukan decompile terhadap file tersebut.

Terlihat bahwa program tersebut dibuat menggunakan rust , pada fungsi main terdapat fungsi untuk memanggil webview , jadi bisa kita simpulkan dari hasil eksekusi dan static analysis bahwa program tersebut melakukan load terhadap web. Ada 2 kemungkinan disini , web bisa online atau di store di program itu sendiri, jadi lakukan string untuk melihat string apa aja yang disimpan oleh program.

Terlihat terdapat kode html ,lakukan search pada “Incorrect!”

Dapat dilihat pada potongan kode diatas bahwa terdapat pengecekan terhadap hasil encrypt dari input kita.

Berikut adalah kode dari fungsi doEncrypt

var $author$project$Main$doEncrypt = F3(
    function (time, passphrase, plaintext) {
   	 return A3(
   		 $billstclair$elm_crypto_string$Crypto$Strings$encrypt,
   		 $elm$random$Random$initialSeed(time),
   		 passphrase,
   		 plaintext);
    });

Fungsi tersebut menjalankan fungsi billstclair$elm_crypto_string$Crypto$Strings$encrypt dan salah satu argumen juga menjalankan suatu fungsi $elm$random$Random$initialSeed. Jadi tinggal search aja untuk kedua fungsi tersebut dan didapatkan informasi bahwa kode tersebut dibuat menggunakan elm-lang dan fungsi encrypt diambil dari salah satu library yang ada pada elm-lang

Lakukan install terhadap elm-lang dan juga librarynya , lalu coba fungsinya ( lakukan encrypt decrypt ).

Karena sudah bisa encrypt decrypt maka kita coba lakukan decrypt terhadap ct yang dibandingkan dengan hasil encrypt input kita.

A3($author$project$Main$doEncrypt, 1337, 'sacred_key_for_sacred_tree', flag)),
var $author$project$Main$ct = 'LUYEOHmRZ4iocP3J67VJ5Cg6WENfuCS6B5BXeqBjMtARkE7d80JjKU53yfTM\n3mm5TgE74LOtl/q6nedvGI+Qbg==';

Karena sudah memiliki key dan ct maka lakukan decrypt

Flag : CJ2021{a_delightful_flag_for_reliable_reverser}

Goliath (699 Pts)

Description

-

PoC

Diberikan file ELF 64-bit , kalau diliat dari strings program tersebut dibuat menggunakan rust

Selanjutnya kita coba jalankan file tersebut dan ada yang aneh , yaitu keluar encrypted tapi telat ( sepertinya program lain ) dan hasil md5sum berubah

Maka dari itu kami coba lakukan static analysis dan dynamic analysis.

Pertama kita tahu bahwa goliath berubah , berarti terdapat open terhadap file goliath . Dapat dipastikan ketika kita ubah nama filenya maka akan error

Cek fungsi open dan liat reference terhadap fungsi tersebut

Hanya dipanggil difungsi main dan sepertinya bisa kita skip

Selanjutnya cek fungsi open64

Terlihat bahwa dipanggil oleh beberapa fungsi , jadi kita keep informasi ini. Berdasarkan informasi sebelumnya kita ketahui bahwa ada perubahan terhadap file dengan nama goliath , jadi kita search string goliath.

Didapatkan string goliath juga diload di fungsi sub_8CAC , maka selanjutnya analisis fungsi sub_8CAC.

Disini kami melakukan analisis beberapa fungsi secara dynamic , adapun berikut untuk beberapa address penting yang kami catat.

Num Type       Disp Enb Address        What
1   breakpoint keep y   0x000055555540cd75
    breakpoint already hit 1 time
2   breakpoint keep y   0x0000555555408cbb
    breakpoint already hit 1 time
3   breakpoint keep y   0x0000555555408cd8 -> detect file
    breakpoint already hit 1 time
4   breakpoint keep y   0x0000555555408e0c -> check length
5   breakpoint keep y   0x0000555555408e60
7   breakpoint keep y   0x0000555555408f4d
8   breakpoint keep y   0x0000555555408ed5
9   breakpoint keep y   0x0000555555409019 -> ptrace
10  breakpoint keep y   0x0000555555409034 -> ptrace
11  breakpoint keep y   0x0000555555409041

Jadi untuk fungsi ptrace kita bypass , caranya adalah dengan mengubah nilai ecx menjadi 6

Selanjutnya akan dilakukan xor value yang ada dimemory $rbp+$rdi dan $r14+$rbx

Jadi kita lakukan dump terhadap nilai pada address tersebut, adapun untuk panjangnya kita ketahui dari perbandingan nilai rbx dan r12

Berikut untuk dumpnya

Selanjutnya tinggal lakukan xor dan cek hasil dari xor tersebut.

key = [0xa1, 0xad, 0xcf, 0xdb, 0x47, 0x95, 0xba, 0x46, 0x49, 0xa4, 0x42, 0xcd, 0x72, 0x84, 0x59, 0x38, 0x35, 0x2a, 0x1a, 0x6a, 0xea, 0x23, 0x47, 0x2e, 0xca, 0x1d, 0xa8, 0x26, 0x3a, 0x73, 0x76, 0x89]
f = open("xor1.bin","rb").read()
res = []
q = open("out","wb")
for i in range(len(f)):
    res.append(f[i]^key[i%len(key)])
q.write(bytes(res))

Ternyata file gzip , jadi ubah extensi jadi gz lalu lakukan extract.

Didapatkan file out yang merupakan file ELF64 bit

Yang mana ketika kita jalankan akan menghasilkan output seperti yang diawal tadi

Jadi selanjutnya langsung decompile file tersebut

// local variable allocation has failed, the output may be wrong!
void __cdecl main_main()
{
  string length; // [rsp+10h] [rbp-E0h]
  __int64 lengtha; // [rsp+10h] [rbp-E0h]
  string lengthb; // [rsp+10h] [rbp-E0h]
  string lengthc; // [rsp+10h] [rbp-E0h]
  uint8 *elem; // [rsp+18h] [rbp-D8h]
  string elema[3]; // [rsp+18h] [rbp-D8h] OVERLAPPED
  __int64 a; // [rsp+20h] [rbp-D0h]
  __int128 aa; // [rsp+20h] [rbp-D0h] OVERLAPPED
  string ab; // [rsp+20h] [rbp-D0h]
  __interface_{} ac; // [rsp+20h] [rbp-D0h]
  string a_16; // [rsp+30h] [rbp-C0h]
  string plaintext; // [rsp+48h] [rbp-A8h]
  string key_len; // [rsp+58h] [rbp-98h]
  char v13[64]; // [rsp+68h] [rbp-88h] BYREF
  uint8 *key_ptr; // [rsp+A8h] [rbp-48h]
  uint8 *iv_ptr; // [rsp+B0h] [rbp-40h]
  string v16; // [rsp+B8h] [rbp-38h] BYREF
  _OWORD v17[2]; // [rsp+C8h] [rbp-28h] BYREF

  main_ran(32LL);
  key_ptr = elem;
  *((_QWORD *)&aa + 1LL) = main_ran(16LL).str;
  iv_ptr = elem;
  length.str = (uint8 *)"https://gist.githubusercontent.com/vidner/6fede10781c23f76d222fdbec6c4607c/raw/1058e0711938e1c80"
                    	"d69ecfeebd470790a2f4863/viva-el-rey";
  length.len = 131LL;
  *(__uint8 *)&elema[1LL].len = main_doRequest(length);
  lengtha = a;
  *(_QWORD *)&aa = elema[1LL].len;
  crypto_sha256_Sum256(lengtha, *((_QWORD *)&aa + 1LL));
  ((void (*)(void))loc_4564A4)();
  v17[1LL] = 0LL;
  *(runtime_eface_0 *)&elema[1LL].len = runtime_convT2Enoptr((runtime__type_0 *)&stru_6969C0, v13);
  v17[1LL] = aa;
  lengthb.str = (uint8 *)"%x";
  lengthb.len = 2LL;
  *(_QWORD *)&aa = &v17[1LL];
  *((_QWORD *)&aa + 1LL) = 1LL;
  elema[1LL].len = 1LL;
  plaintext = fmt_Sprintf(lengthb, *(__interface_{} *)&aa);
  elema[0LL].str = (uint8 *)"CJ2021{";
  elema[0LL].len = 7LL;
  elema[1LL] = elema[2LL];
  elema[2LL].str = (uint8 *)"}";
  elema[2LL].len = 1LL;
  key_len = runtime_concatstring3((uint8 (*)[32])&v13[32LL], *(string (*)[3])&elema[0LL].str);
  ab.str = key_ptr;
  ab.len = (__int64)key_len.str;
  a_16.str = iv_ptr;
  a_16.len = key_len.len;
  main_Ase256(plaintext, ab, a_16, 16LL);
  v16 = plaintext;
  v17[0LL] = 0LL;
  runtime_convT2Estring((runtime__type_0 *)&e, &v16);
  v17[0LL] = *(_OWORD *)&ac.array;
  lengthc.str = (uint8 *)"Too bad its already encrypted: %v\n";
  lengthc.len = 34LL;
  ac.array = (interface_{} *)v17;
  ac.len = 1LL;
  ac.cap = 1LL;
  fmt_Printf(lengthc, ac);
}

Terlihat bahwa program melakukan request terhadap suatu gist lalu melakukan sha256 dan enkripsi aes. Karena terlihat terdapat format flag maka kemungkinan yang di encrypt adalah flag , jadi lakukan breakpoint pada pemanggilan fungsi main_Ase256 agar tahu value dari argumentnya (flag).

Adapun berikut breakpoint yang kami set sebelumnya untuk melakukan analisis pada binary tersebut

Flag : CJ2021{eaca9080fa4c6a8bca426dc205e73d96a5e5814fdef8aa7ef0f219c6ba761fb3}

Last updated