Reverse Engineering — Buffer Overflow

Post By, Afrizal Tanggal, 03-10-2018 20:15:26

Saya mau membuat pengumuman bahwa saya juga akan nulis tentang Reverse Engineering dengan tag “Reverse”. Kalau dipikir, agak lucu juga buat kamu yang merasa ilmu securitynya sudah tinggi namun ga pernah menyentuh namanya proses ini. Jadi, wajib hukumnya buat kamu untuk juga membaca tag “Reverse” juga yaa *maksa.

Harus diakui, ini akan menjadi lebih sulit dibandingkan pentest, trust me. Tapi, jelas insya allah akan worth untuk dibaca. Apalagi buat kamu yang udah merasa bosen (jago) dengan pentest dan ingin mendapatkan ilmu yang lebih dari itu.

Jadi, mungkin antara tag “Pentest Series” dan “Reverse” akan dipost secara bergantian.

Definisi

Reverse Engineering adalah teknik hacker untuk mengetahui lajur dan cara kerja dari suatu program. Harapannya adalah hacker dapat mengetahui dan berharap mendapatkan flaw atau celah dari program yang dimaksud. Hal ini dilakukan dengan cara melihat source code pada program tersebut.

Pada tag “Reverse” ini SEMUAnya akan mendebug program binary executable yang dicompile dengan bahasa C. Hasil reverse dari binary tersebut pasti berupa assembly. Sehingga, mau tidak mau kamu harus punya basic di bahasa assembly.

Kenapa ini penting?

Semua local root exploit yang kamu pake adalah hasil exploitasi dan debugging pada binary kernel yg berjalan. Kamu mah tinggal compile terus pake doang hahaha.

Masak iya seumur hidup cuma mau ngerti cara make exploit aja. Tentu kamu juga mau tau bagaimana cara membuatnya, iya kan? Ga cuma itu, disini kamu akan hands-on membuat exploit kamu sendiri terhadap aplikasi yang akan dicoba.

Loh, kok mirip pentest?
EXACTLY, cuma kamu melakukan pentest terhadap aplikasi binary

Oh iya, tentu namanya proses reverse engineering memiliki banyak tujuan dan teknik. Khusus tag “Reverse” kebanyakan akan membahas bagaimana cara melakukan exploitasi dengan teknik Buffer Overflow. Exploitasi ditujukan untuk melakukan injeksi shell dan berharap bisa mendapatkan shell linux hasil eksploitasi kita pada program.

Apa itu Buffer?

Tanpa perlu banyak basa-basi, langsung aja deh gan ke materi pengenalan.

A buffer is simply a contiguous block of computer memory that holds multiple instances of the same data type.  C programmers normally associate with the word buffer arrays. Most commonly, character arrays.  Arrays, like all variables in C, can be 
declared either static or dynamic.  Static variables are allocated at load  time on the data segment.  Dynamic variables are allocated at run time on the stack. To overflow is to flow, or fill over the top, brims, or bounds.

Pokoknya perhatikan yang saya bold. Buffer adalah blok kontigu dari memori komputer yang berisikan data yang sejenis. Inti mudahnya seperti array pada bahasa C lah.

Sebelum lanjut, pastikan agan PERNAH menggunakan bahasa C. Kalau belum, silahkan dicoba dahulu

Terdapat 2 jenis variable yaitu statis dan dinamis. Statis selalu dialokasikan pada data segment, sedangkan dynamic dialokasikan pada stack

Tujuan utama Buffer Overflow adalah untuk melakukan penulisan ulang terhadap stack program yang ada. Sehingga memungkinkan kita untuk melakukan kontrol terhadap program yang sedang dijalankan. Salah satu contoh “kontrol” yang saya maksud adalah pemanggilan shell (/bin/sh) yang akan menjadi fokus utama tag “Reverse”

Process-Memory Organization

Namanya program yang sedang berjalan (yang kemudian disebut “proses”) itu berjalan pada memory dan memiliki 3 hal berikut

         /------------------  lower
         |                  |  memory
         |       Text       |  addresses
         |                  |
         |------------------|
         |   (Initialized)  |
         |        Data      |
         |  (Uninitialized) |
         |------------------|
         |                  |
         | New Memory Cap   |
         |                  |   
         |------------------|
         |                  |
         |       Stack      |  higher
         |                  |  memory
         ------------------/  addresses
  1. Text
    Bagian program yang bersifat read-only, berisi instruksi dan data statis milik program. Intinya bukan daerah ini yang akan kamu exploit
  2. Data
    Terdapat 2 jenis data yaitu initialized dan uninitialized. Variabel static diletakkan pada bagian ini. Apabila saat menjalankan program, si user membutuhkan alokasi data yang lebih besar. Program akan dihentikan sementara dan akan dilakukan penjadwalan ulang terhadap program dengan tambahan alokasi memory yang terletak antara data dan stack
  3. Stack
    Kamu pernah mendengar istilah ini sebelumnya? Apalagi buat kamu mahasiswa informatika PASTI pernah mendengar ini di kuliah semacam Algoritma & Struktur Data.
    Namanya Stack pada program ini memang memiliki cara kerja yang sama dengan stack yang kamu dengar pada kuliah. Seluruh instruksi akan dijalankan pada bagian ini. Inisialisasi alur dan pengambilan instruksi dilakukan dengan metode POP dan PUSH
Buat yang masih baru dengan “Stack”. Silahkan googling ya

Pokoknya, 2 rule untuk stack:

  1. After a PUSH, Stack Pointerwill point to a lower memory address
  2. After a POP, Stack Pointer will point to a higher memory address

Sehingga, setiap instruksi pasti memiliki address. Pada bahasa C, setiap instruksi atau line-of-code PASTI berada pada suatu subrutin. Minimal subrutin main(). Seperti contoh kode hello world dibawah

int main(){
       printf(“Hello World”);
       return 0;
}

Setiap subrutin juga berdiam menempati tempat yang bernama stack frame. Lokasi dari stack bisa terdapat pada register ESP dan lokasi dari base function/stack frame terdapat pada register EBP. Sekarang, kalau kamu mau lihat assembly dari program itu. Compile sebagai 32bit dan jalankan gdb seperti perintah dibawah

kucing$ gcc index.c -m32 -o index
kucing$ gdb index
(gdb) disas main
Dump of assembler code for function main:
   0x0804840b <+0>:     lea    0x4(%esp),%ecx
   0x0804840f <+4>:     and    $0xfffffff0,%esp
   0x08048412 <+7>:     pushl  -0x4(%ecx)
   0x08048415 <+10>:    push   %ebp
   0x08048416 <+11>:    mov    %esp,%ebp
   0x08048418 <+13>:    push   %ecx
   0x08048419 <+14>:    sub    $0x4,%esp
   0x0804841c <+17>:    sub    $0xc,%esp
   0x0804841f <+20>:    push   $0x80484c0
   0x08048424 <+25>:    call   0x80482e0 <printf@plt>
   0x08048429 <+30>:    add    $0x10,%esp
   0x0804842c <+33>:    mov    $0x0,%eax
   0x08048431 <+38>:    mov    -0x4(%ebp),%ecx
   0x08048434 <+41>:    leave  
   0x08048435 <+42>:    lea    -0x4(%ecx),%esp
   0x08048438 <+45>:    ret    
End of assembler dump.
(gdb)

Kamu lihat pada *main+10 bahwa register ebp dipush ke dalam stack. Lalu register ESP yang merupakan stack pointer yang berisikan alamat awal program diletakkan pada register EBP (*main +11). Dan pointer ESPlah yang selalu berubah-ubah hingga program/subrutin selesai.

Selanjutnya kita akan bicara register.

Registers

Setiap program yang berjalan PASTI memiliki sesuatu yang bernama register. Intinya adalah memori internal milik dari program tersebut. Digunakan untuk menyimpan variabel-variabel yang dibutuhkan

Mengapa program masih perlu namanya memori internal berupa register? Soalnya bayangin aja gan kalau si program harus bolak-balik kontak prosesor dan memory untuk meminta variabel yang sering dipake, belum termasuk datanya harus lewat bus dll. Nanti kan repot dan malah memperlambat kinerja dari program.

Kalau sudah punya memory storage internal. Jadinya si program tinggal akses langsung tanpa perlu melalui memori komputer lagi.

Namanya register itu pada dasarnya berisi kumpulan variabel, ini sangat bergantung pada mesin yang digunakan. Namun sebagai gambaran dasar, berikut adalah register yang digunakan pada mesin Intel x86 (32-bit)

  • EAX : accumulator : used for performing calculations, and used to store return values from function calls. Basic operations such as add, subtract, compare use this general-purpose register
  • EBX : base (does not have anything to do with base pointer). It has no general purpose and can be used to store data.
  • ECX : counter : used for iterations. ECX counts downward.
  • EDX : data : this is an extension of the EAX register. It allows for more complex calculations (multiply, divide) by allowing extra data to be stored to facilitate those calculations.
  • ESP : stack pointer
  • EBP : base pointer
  • ESI : source index : holds location of input data
  • EDI : destination index: points to location of where result of data operation is stored
  • EIP : instruction pointer

Dan biasanya untuk yang 64-bit. Register yang depannya “E” itu menjadi “R”.

Sebagai contoh RAX, RBX, RCX, RDX, RSI, and RDI

Sebagai perbandingan lagi, address yang digunakan pada 32-bit adalah 4 byte (range 0x00000000 — 0xFFFFFFFF) dan untuk 64-bit adalah 8 byte (range 0x0000000000000000 — 0x00007FFFFFFFFFFF).

What’s next?

Saya rasa akan terlalu panjang kalau dilanjutkan ke percobaan buffer overflow. Untuk itulah, saya akan post di artikel selanjutnya. Langsung praktek bagaimana buffer overflow bekerja, termasuk juga didalamnya cara membuat exploit.

Tapi, saya sangat sarankan anda membaca seluruh referensi yang saya tulis dibawah ini.

 EMAIL  WHATSAPP