Sabtu, 29 Juli 2017

Reversing 1. Simple XOR

untitled

Reversing 1. Membaca Pseudocode, dan reverse langsung

Kali ini kita akan membahas sedikit tentang reverse engineering. Reverse engineering adalah Ilmu untuk merekonstruksi program dari program yang sudah dicompiled, menjadi pseudocode, dan memahami pseudocode tentang bagaimana program tersebut bekerja. Didalam dunia cyber security. Reversing adalah tingkat tertinggi bersamaan dengan binary eksploitation. Banyak manfaat yang dapat kita dapatkan jka kita belajar reverse engineering, kita dapat melihat suatu program bekerja apakah dia bekerja sebagai mana mestinya, atau ada kesalahan / bug / illegal instruction yang disisipkan pada program tersebut. Kemampuan reverse engineering juga dapat membantu bidang security lain seperti membaca suatu program yang mengenkripsi dengan menggunakan suatu metode kriptografi, dan juga membantu membaca kelemahan program yang dapat dieksploit. Tanpa kemampuan reverse engineering, kemungkinan kita bisa mengeksploit program sangat kecil bahkan mendekati nl.

Untuk belajar reverse engineering, kita membutuhkan kemampuan untuk memahami source code, dan tentu kemampuan coding. Untuk reverse engineerin tingkat atas, tentu kita juga membutuhkan kemampuan menggunakan dan memahami assembly, namun saya juga masih banyak belajar untuk assembly, jadi kita belum akan membahasnya disini.

Kali ini kita akan menggunakan soal dari slashroot CTF yang masing hangat yaitu soal Phunpack. (Binary diupload oleh Fanpage Cyber security IPB).

Seperti biasa, kita harus mengidentifikasi terlebih dahulu binary tersebut.

alfakatsuki@justPC:/media/sda6/CTF (All)/CTF Events/FINAL SLEZRUT/REVERSING$ file phunpack
phunpack: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.24, BuildID[sha1]=5bed9389e4ebb4a335c343185f4beec6fe31e741, not stripped
alfakatsuki@justPC:/media/sda6/CTF (All)/CTF Events/FINAL SLEZRUT/REVERSING$ checksec phunpack
[*] '/media/sda6/CTF (All)/CTF Events/FINAL SLEZRUT/REVERSING/phunpack'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
alfakatsuki@justPC:/media/sda6/CTF (All)/CTF Events/FINAL SLEZRUT/REVERSING$ ./phunpack
Enter the password: aaaaaaaaaaaa
No no no!
alfakatsuki@justPC:/media/sda6/CTF (All)/CTF Events/FINAL SLEZRUT/REVERSING$ ./phunpack
Enter the password: a
No no no!
alfakatsuki@justPC:/media/sda6/CTF (All)/CTF Events/FINAL SLEZRUT/REVERSING$ ./phunpack
Enter the password:
No no no!
alfakatsuki@justPC:/media/sda6/CTF (All)/CTF Events/FINAL SLEZRUT/REVERSING$

Bisa kita lihat bahwa program meminta kita untuk memberikan input berupa password dan jika salah akan memunculkan hasil tersebut.

Mari kita coba decompile dengan IDA 64 bit atau decompiler lain. Namun kali ini kita coba IDA karena hasil decompile yang paling mudah dibaca.

Berikut adalah layout pemanggilan Fungsi pada program.

Kita coba decompile fungsi Main.

Berikut adalah pseudocode C dari fungsi main

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int result; // eax@4
  __int64 v4; // rcx@4
  char v5; // [sp+10h] [bp-20h]@1
  __int64 v6; // [sp+28h] [bp-8h]@1

  v6 = *MK_FP(__FS__, 40LL);
  printf((unsigned __int64)"Enter the password: ");
  fgets(&v5, 11LL, stdin);
  if ( passcheck(&v5) == 10 )
    printf((unsigned __int64)"Correct flag! SlashRootCTF{%s}\n");
  else
    puts("No no no!");
  result = 0;
  v4 = *MK_FP(__FS__, 40LL) ^ v6;
  return result;
}

Kita tau bahwa fungsi fgets meminta kita untuk meminta sebuah inputan dan dimasukkan kedalam variabel v5. Untuk mendapatkan flag yang benar kita harus fungsi passcheck yang memiliki argumen v5 tadi harus return nilai 10,

Mari kita decompile fungsi passcheck dan lihat pseudo code nya.

__int64 __fastcall passcheck(__int64 a1)
{
  __int64 v1; // rax@1
  __int64 result; // rax@8
  __int64 v3; // rcx@8
  unsigned int v4; // [sp+18h] [bp-28h]@1
  signed int i; // [sp+1Ch] [bp-24h]@2
  char v6; // [sp+20h] [bp-20h]@1
  char v7; // [sp+21h] [bp-1Fh]@1
  char v8; // [sp+22h] [bp-1Eh]@1
  char v9; // [sp+23h] [bp-1Dh]@1
  char v10; // [sp+24h] [bp-1Ch]@1
  char v11; // [sp+25h] [bp-1Bh]@1
  char v12; // [sp+26h] [bp-1Ah]@1
  char v13; // [sp+27h] [bp-19h]@1
  char v14; // [sp+28h] [bp-18h]@1
  char v15; // [sp+29h] [bp-17h]@1
  __int64 v16; // [sp+38h] [bp-8h]@1

  v16 = *MK_FP(__FS__, 40LL);
  v4 = 0;
  v6 = 85;
  v7 = 110;
  v8 = 80;
  v9 = 65;
  v10 = 67;
  v11 = 75;
  v12 = 70;
  v13 = 84;
  v14 = 87;
  v15 = 33;
  LODWORD(v1) = strlen();
  if ( v1 == 10 )
  {
    for ( i = 0; i <= 9; ++i )
    {
      if ( *(_BYTE *)(i + a1) == *(&v6 + i) ) #### Penting
        ++v4;
      else
        v4 = 0;
    }
  }
  result = v4;
  v3 = *MK_FP(__FS__, 40LL) ^ v16;
  return result;
}

Fungsi passcheck mereturn nilai result. Nilai result didapat dari membandingkan tiap char pada argumen dari passcheck dengan char yang ada pada local variabel, yaitu char dari alamat v6. Apabila i sudah mencapai 10 maka program akan dia break.

Inputan kita dibandingkan dengan isi dari variabel v4 - v15. Kita tinggal membuat skrip python sederhana atau manual pun juga bisa untuk mengubah nilai int yang disana menjadi jilai char. Namun sekalian untuk belajar programming mari kita coding.

import re
from pwn import *
dump = """v6 = 85;
v7 = 110;
v8 = 80;
v9 = 65;
v10 = 67;
v11 = 75;
v12 = 70;
v13 = 84;
v14 = 87;
v15 = 33;"""

dump = dump.split('\n')

passs = ""

for i in dump :
  a = re.search('= (.+?);', i)
  passs += chr(eval(a.group(1)))

print passs
# p = process('./phunpack')
# p.recvline('password: ')
# p.sendline('passs')
# p.recvline()
# p.recvline()
# p.kill()

Skrip diatas itu kita sekalian submit ya. Lumayan sekalian belajar pwning juga. Tapi akhirnya saya ga jadi make karena ga tau kenapa binary nya ga bisa dipwn.

Didapat string 'UnPACKFTW!'. Ayo kita coba masukkan dipassword

alfakatsuki@justPC:/media/sda6/CTF (All)/CTF Events/REVERSING$ ./phunpack
Enter the password: UnPACKFTW!
Correct flag! SlashRootCTF{UnPACKFTW!}

Ternyata benar flagnya :D.

Jika kita melihat hasil dari pseudocode maka terlihat rumit sekali, namun ternyata hanya dibandingkan saja. Karena itu kita harus menguasai bahasa pemrograman untuk bisa melihat dan mengidentifikasi mana code code yang penting agar untuk kita reverse. :)

Sekian dari saya. Pada postingan kedepan, kita akan mencoba untuk mereversing dengan metode bruteforcing. Semoga bermanfaat.

Tidak ada komentar:

Posting Komentar