Binary exploitation sering terlihat seperti sesuatu yang sangat rumit: debugger, register, hexadecimal, assembly, stack, shellcode, ROP, dan segudang istilah lainnya.

Padahal inti dari banyak kasus klasik sebenarnya cukup sederhana:

Program menulis data melewati batas memory yang seharusnya digunakan oleh sebuah buffer.

Ketika data tersebut menimpa bagian memory lain yang memiliki arti bagi program, terutama data yang berhubungan dengan alur kontrol, sebuah bug memory-safety dapat berubah menjadi vulnerability yang memungkinkan perubahan perilaku program.

NIST mendefinisikan buffer overflow sebagai kondisi ketika data yang dimasukkan ke buffer melebihi kapasitasnya sehingga dapat menimpa informasi lain di memory. MITRE mengklasifikasikan bentuk klasiknya sebagai CWE-120: Buffer Copy without Checking Size of Input, sedangkan overflow pada buffer yang berada di stack dikategorikan sebagai CWE-121: Stack-based Buffer Overflow. NIST Computer Security Resource Center

Artikel ini membahas mekanismenya dari level program C, memory, CPU, sampai mitigasi modern. Contoh praktik dibuat dalam lingkungan lokal dan difokuskan untuk pembelajaran serta analisis defensif, bukan untuk mengambil alih sistem pihak lain.


1. Apa Itu Binary Exploitation?

Binary exploitation adalah proses memanfaatkan kelemahan pada program yang sudah dikompilasi sehingga perilaku program dapat dipengaruhi melebihi maksud pembuatnya.

Program:

Source Code
    ↓
Compiler
    ↓
Machine Code
    ↓
Executable / Binary

Ketika seorang security researcher menganalisis binary, yang dilihat bukan lagi sekadar:

printf("Hello");

tetapi hal-hal seperti:

register
stack
heap
instruction
memory address
control flow
calling convention
binary protections

Salah satu kelas vulnerability klasik yang sangat penting untuk memahami binary exploitation adalah buffer overflow.


2. Apa Itu Buffer?

Buffer hanyalah area memory yang digunakan untuk menyimpan data.

Contohnya:

char name[16];

Program meminta compiler menyediakan ruang untuk array:

name
┌──────────────────────────────┐
│ 16 byte                      │
└──────────────────────────────┘

Secara konseptual:

Address
│
├── 0x1000  [00]
├── 0x1001  [00]
├── 0x1002  [00]
├── ...
└── 0x100F  [00]

Buffer tersebut memiliki batas.

Jika program mencoba menulis 30 byte:

Buffer capacity = 16 byte
Input           = 30 byte

maka 14 byte sisanya harus masuk ke tempat lain.

Di situlah masalah dimulai.

NIST secara khusus menjelaskan bahwa buffer overflow terjadi ketika input melebihi kapasitas buffer dan akibatnya dapat menimpa informasi lain. NIST Computer Security Resource Center


3. Bagian Terpenting: Memory Tidak Mengetahui "Ini Milik Saya"

Ini konsep yang sangat penting.

Bayangkan memory:

┌──────────────┐
│ buffer[16]   │
├──────────────┤
│ data lain    │
├──────────────┤
│ metadata     │
├──────────────┤
│ control data │
└──────────────┘

CPU pada dasarnya bekerja dengan alamat memory dan instruksi.

Tidak ada konsep sederhana di hardware yang mengatakan:

"Byte ke-17 ini tidak boleh masuk karena masih milik buffer."

Itulah mengapa bounds checking sangat penting.

Dalam bahasa atau runtime yang memiliki memory-safety lebih kuat, banyak operasi akan memeriksa batas secara otomatis. C dan C++ secara historis memberikan kontrol memory yang sangat dekat dengan hardware, sehingga programmer harus sangat berhati-hati terhadap batas array dan operasi pointer. SEI CERT memiliki materi khusus mengenai kesalahan memory management dan buffer overflow pada C/C++. SEI


4. Contoh Buffer Overflow Paling Sederhana

Misalnya:

#include <stdio.h>
#include <string.h>

int main(void) {
    char buffer[8];

    strcpy(buffer, "AAAAAAAAAAAAAAAA");

    printf("%s\n", buffer);

    return 0;
}

Kita mempunyai:

buffer = 8 byte

tetapi strcpy() tidak mengetahui bahwa destination hanya memiliki ruang 8 byte. Ia terus menyalin string hingga menemukan null terminator.

MITRE menggunakan pola strcpy() tanpa pemeriksaan panjang sebagai contoh klasik CWE-120. CWE

Secara konseptual:

SEBELUM

buffer
┌────┬────┬────┬────┬────┬────┬────┬────┐
│    │    │    │    │    │    │    │    │
└────┴────┴────┴────┴────┴────┴────┴────┘


SETELAH INPUT TERLALU PANJANG

buffer
┌────┬────┬────┬────┬────┬────┬────┬────┐
│ A  │ A  │ A  │ A  │ A  │ A  │ A  │ A  │
└────┴────┴────┴────┴────┴────┴────┴────┘
       ↓
       ↓
┌────┬────┬────┬────┐
│ A  │ A  │ A  │ A  │  ← memory setelah buffer
└────┴────┴────┴────┘

Keempat byte terakhir bukan lagi bagian dari buffer.

Mereka telah menjadi out-of-bounds write.


5. Undefined Behavior: Ini Sangat Penting

Dalam bahasa C, menulis di luar batas objek merupakan undefined behavior.

Artinya kita tidak boleh mengasumsikan hasil tertentu dari program yang melakukan operasi tersebut.

Hasilnya bisa berupa:

program normal
crash
data berubah
memory corruption
hasil aneh
control-flow corruption

Tidak ada jaminan bahwa overflow akan selalu menghasilkan segmentation fault.

Ini menjelaskan mengapa:

"Program saya tadi tidak crash"

bukan berarti:

"Program saya aman."

MITRE juga mencatat bahwa buffer overflow umumnya dapat menyebabkan crash, tetapi pada kondisi tertentu dapat memiliki konsekuensi terhadap integrity, confidentiality, availability, dan control flow. CWE


6. Kenapa Stack Sangat Penting?

Sekarang kita masuk ke bagian inti binary exploitation.

Ketika fungsi dipanggil, program biasanya membutuhkan stack frame untuk menyimpan berbagai data sementara.

Secara konseptual:

┌──────────────────────┐
│ argument / data      │
├──────────────────────┤
│ local variables      │
│                      │
│ buffer               │
├──────────────────────┤
│ saved state           │
├──────────────────────┤
│ return address       │
└──────────────────────┘

Detail persis layout bergantung pada arsitektur, ABI, compiler, optimization level, dan fungsi yang dikompilasi. Pada x86-64 System V ABI, aturan calling sequence dan penggunaan register serta stack frame menentukan bagaimana fungsi berinteraksi dengan caller. Linux Foundation Specs


7. Apa Itu Return Address?

Misalkan:

int main(void) {
    vulnerable();
}

Saat CPU melakukan pemanggilan fungsi, harus ada cara untuk mengetahui:

Setelah vulnerable() selesai, instruksi mana yang harus dieksekusi berikutnya?

Itulah fungsi return address.

Secara konseptual:

main()
  │
  │ call vulnerable
  ▼
vulnerable()
  │
  │ ...
  │ ret
  ▼
kembali ke instruksi setelah call

Instruksi CALL menyimpan alamat untuk kembali, dan RET menggunakan informasi tersebut untuk melanjutkan eksekusi. Dokumentasi Intel menjelaskan mekanisme procedure call/return dan penyimpanan instruction pointer pada stack untuk jenis call yang relevan. Intel


8. Di Sinilah Buffer Overflow Menjadi Menarik

Bayangkan layout sederhana:

Alamat lebih tinggi
┌───────────────────────┐
│ Return Address        │
├───────────────────────┤
│ Saved frame data      │
├───────────────────────┤
│ buffer[16]            │
└───────────────────────┘
Alamat lebih rendah

Kemudian program secara tidak sengaja menulis:

16 byte buffer
+
data tambahan

Jika penulisan terus melewati batas:

AAAAAAAAAAAAAAAA
BBBBBBBB

secara konseptual bisa terjadi:

┌───────────────────────┐
│ BBBBBBBB              │ ← data yang tertulis melewati batas
├───────────────────────┤
│ saved frame data      │
├───────────────────────┤
│ AAAAAAAAAAAAAAAA      │ ← buffer
└───────────────────────┘

Dalam kasus stack overflow klasik, data yang berada setelah buffer dapat mencakup return address.

Linux kernel documentation menjelaskan konsep inti ini secara langsung: stack buffer overflow klasik terjadi ketika penulisan melewati akhir variabel stack dan akhirnya dapat menimpa return address yang tersimpan pada stack. Linux Kernel Documentation


9. Mengapa Mengubah Return Address Sangat Berbahaya?

Karena return address bukan sekadar angka biasa.

Ia merepresentasikan:

"setelah fungsi selesai, lanjutkan eksekusi di sini."

Jika nilai tersebut rusak:

return address
      ↓
nilai yang salah
      ↓
RET
      ↓
CPU mencoba melanjutkan eksekusi
      ↓
alamat tidak valid / target berbeda

Akibatnya dapat terjadi:

Crash

atau, dalam kondisi exploitability tertentu:

Control Flow Hijacking

CWE-121 menjelaskan bahwa stored return address merupakan salah satu data security-critical pada stack dan bahwa perubahan terhadap control data tersebut dapat berhubungan dengan eksekusi kode yang tidak diotorisasi. CWE


10. Yang Sebenarnya "Dieksploitasi" Bukan Buffer-nya

Ini miskonsepsi yang sering muncul.

Orang sering mengatakan:

"Exploit buffer."

Lebih tepatnya:

Bug
 ↓
Out-of-bounds write
 ↓
Memory corruption
 ↓
Corruption of security-relevant state
 ↓
Potential control-flow/data-flow manipulation

Jadi buffer overflow hanyalah primitive memory corruption.

Nilai security-nya bergantung pada apa yang berhasil ditimpa dan kondisi program.


11. Memory Layout Program

Untuk memahami binary exploitation, kenali pembagian memory secara kasar:

High Address
┌──────────────────────┐
│ Stack                │
│                      │
│ local variables      │
│ call-related data    │
└──────────────────────┘

        ↓

┌──────────────────────┐
│ Memory mappings      │
│ shared libraries     │
│ mmap regions         │
└──────────────────────┘

        ↓

┌──────────────────────┐
│ Heap                 │
│ dynamic allocations  │
└──────────────────────┘

        ↓

┌──────────────────────┐
│ BSS                  │
│ global/static data   │
└──────────────────────┘

┌──────────────────────┐
│ Data                 │
│ initialized globals  │
└──────────────────────┘

┌──────────────────────┐
│ Text / Code          │
│ machine instructions │
└──────────────────────┘

Low Address

Ini merupakan gambaran konseptual, bukan layout universal untuk semua executable dan semua OS.

Yang penting dipahami:

stack ≠ heap ≠ code

Masing-masing memiliki penggunaan dan karakteristik yang berbeda.


12. Stack Overflow vs Heap Overflow

Stack-based Buffer Overflow

Buffer berada pada stack.

Contoh:

void function(void) {
    char buffer[32];
}

MITRE mengategorikan kondisi tersebut sebagai CWE-121. CWE

Heap-based Buffer Overflow

Buffer berasal dari dynamic allocation:

char *buffer = malloc(32);

kemudian program menulis melebihi 32 byte.

MITRE mengategorikan jenis tersebut sebagai CWE-122. CWE

Konsekuensi dan teknik exploitation dapat berbeda karena struktur data pada heap tidak sama dengan stack.


13. Buffer Overflow Tidak Selalu Mengubah Return Address

Ini juga penting.

Overflow bisa mengenai:

variabel lain
pointer
length
function pointer
object metadata
heap metadata
control data

Misalnya:

buffer
   ↓
[AAAAAAAA]
   ↓
flags

Jika flags menentukan:

if (is_admin) {
    ...
}

kerusakan memory mungkin mengubah data tersebut.

Jadi konsep lebih luasnya adalah:

Memory corruption dapat memengaruhi data maupun kontrol program.

NIST dan CWE mencatat bahwa operasi di luar batas buffer dapat menimpa memory lain, bukan hanya return address. CWE


14. Apa yang Terjadi di CPU?

Sekarang lihat dari perspektif CPU.

Misalnya program memiliki instruksi:

mov
lea
call
cmp
jne
ret

CPU menjalankan instruksi berdasarkan instruction pointer.

Secara sederhana:

Instruction Pointer
        ↓
fetch instruction
        ↓
decode
        ↓
execute
        ↓
next instruction

Normal:

A → B → C → D → E

Jika control-flow data rusak:

A → B → C → ???

Maka program mungkin:

crash

atau control flow-nya berubah.

Intel menjelaskan bahwa penyimpangan control-flow pada return/call/jump merupakan salah satu kelas ancaman yang ingin dimitigasi oleh teknologi seperti CET. Intel Resource Download


15. Kenapa Hexadecimal Sangat Penting?

Ketika mempelajari binary exploitation, Anda akan sering melihat:

0x7fffffffe000
0x401146
0x00000000

Hexadecimal digunakan karena sangat praktis untuk merepresentasikan binary data.

Satu digit hex:

0-F

merepresentasikan:

4 bit

Contoh:

0x41

adalah byte yang umum dikenal sebagai karakter A dalam ASCII.

Maka:

AAAAAAAA

secara byte dapat terlihat sebagai:

41 41 41 41 41 41 41 41

Ini membuat memory dump jauh lebih mudah dianalisis.


16. Mengenal Register

Pada x86-64, register adalah lokasi penyimpanan kecil dan sangat cepat yang berada di CPU.

Contohnya:

RAX
RBX
RCX
RDX
RSI
RDI
RBP
RSP
RIP

Dua register yang sangat penting untuk memahami stack adalah:

RSP
RBP

Secara konseptual:

RSP → posisi stack saat ini
RBP → frame reference tertentu, jika compiler menggunakan frame pointer
RIP → instruksi yang sedang/akan dieksekusi

Tetapi compiler dapat melakukan optimization sehingga penggunaan frame pointer tidak selalu sama.

System V AMD64 ABI menjelaskan aturan register dan stack yang digunakan dalam function calling sequence. Linux Foundation Specs


17. Apa Itu Stack Frame?

Saat fungsi dijalankan, compiler dapat membentuk struktur untuk kebutuhan fungsi tersebut.

Misalnya secara sederhana:

foo()

┌─────────────────────┐
│ return information  │
├─────────────────────┤
│ saved state         │
├─────────────────────┤
│ local variable      │
├─────────────────────┤
│ buffer[32]          │
└─────────────────────┘

Dalam assembly Anda dapat melihat instruksi yang mengatur stack pointer dan register lainnya.

Tetapi jangan menghafal satu layout tertentu sebagai aturan mutlak.

Optimization dapat mengubah:

posisi variable
register allocation
frame pointer
stack layout

Itulah sebabnya binary exploitation selalu sangat bergantung pada binary yang sebenarnya dianalisis.


18. Coba Lab Lokal: Mengamati Buffer Overflow

Sekarang kita buat eksperimen sederhana.

Buat:

overflow.c

Isi:

#include <stdio.h>
#include <string.h>

void vulnerable(const char *input) {
    char buffer[16];

    strcpy(buffer, input);

    printf("Input: %s\n", buffer);
}

int main(void) {
    vulnerable("ABCDEFGHIJKLMNOPQRSTUVWXYZ");

    return 0;
}

Tujuannya bukan membuat exploit, melainkan mengamati memory-safety violation.


19. Compile dengan AddressSanitizer

Gunakan GCC atau Clang dengan AddressSanitizer:

gcc -g -O0 -fsanitize=address -fno-omit-frame-pointer overflow.c -o overflow

Kemudian:

./overflow

AddressSanitizer dirancang untuk mendeteksi berbagai memory error, termasuk buffer overflow, dan compiler GCC mendokumentasikan penggunaannya melalui -fsanitize=address. GCC

Output biasanya akan memberikan laporan bahwa terjadi:

stack-buffer-overflow

serta menunjukkan lokasi sumber yang berhubungan dengan kesalahan.

Ini sangat bagus untuk tahap awal karena kita dapat melihat:

BUG
 ↓
DETECTED

tanpa perlu membuat exploit.


20. Kenapa -g Digunakan?

Flag:

-g

memasukkan debug information yang membantu debugger menghubungkan machine code dengan source code.

Tanpa debug information, Anda bisa melihat:

0x000000000040....

tetapi lebih sulit mengetahui:

ini berasal dari baris mana?

Dengan -g, GDB dapat memberikan konteks yang jauh lebih berguna.


21. Gunakan GDB untuk Melihat Memory

Jalankan:

gdb ./overflow

Kemudian:

break vulnerable
run

Setelah berhenti:

info registers

Kemudian:

x/32gx $rsp

GDB menyediakan perintah x untuk memeriksa memory dalam berbagai format. Format seperti x/32gx dapat digunakan untuk melihat 32 unit memory sebagai hexadecimal giant words. Sourceware

Ini memungkinkan kita melihat:

STACK
↓
raw bytes
↓
nilai hexadecimal

22. Mengapa Debugger Sangat Penting?

Tanpa debugger:

program crash

Dengan debugger:

program crash
 ↓
alamat instruksi
 ↓
register
 ↓
stack
 ↓
memory
 ↓
source line

Binary exploitation pada dasarnya banyak berkaitan dengan pertanyaan:

Apa yang berubah?
Di mana berubah?
Kapan berubah?
Mengapa berubah?
Apa yang menggunakan nilai tersebut?

GDB sangat membantu menjawab pertanyaan tersebut.


23. Coba Bandingkan Program Aman

Daripada:

strcpy(buffer, input);

gunakan API yang melakukan pembatasan panjang sesuai kebutuhan program.

Contoh sederhana:

snprintf(
    buffer,
    sizeof(buffer),
    "%s",
    input
);

Dengan demikian ukuran destination diketahui oleh fungsi.

Namun tetap perlu memahami truncation dan kebutuhan null termination. Tidak semua pergantian API secara otomatis menjamin seluruh program aman.


24. Compiler Juga Memiliki Proteksi

Salah satu pertahanan klasik adalah stack protector.

GCC menyediakan:

-fstack-protector

dan:

-fstack-protector-strong

GCC menjelaskan bahwa stack protector memasukkan guard value pada fungsi tertentu dan memeriksanya saat fungsi akan selesai. Jika guard rusak, program dapat dihentikan. GCC

Secara konseptual:

SEBELUM

buffer
saved data
return address

Dengan canary:

buffer
canary
saved data
return address

Jika overflow melewati buffer:

buffer
   ↓
CANARY RUSAK
   ↓
return
   ↓
CANARY CHECK
   ↓
FAIL
   ↓
PROGRAM TERMINATE

Linux kernel documentation juga menjelaskan stack canary sebagai defense yang ditempatkan antara stack variables dan return address lalu diverifikasi sebelum fungsi kembali. Linux Kernel Documentation


25. Apa Itu Stack Canary?

Stack canary adalah nilai guard yang diletakkan di lokasi strategis pada stack.

Tujuannya bukan:

mencegah write

melainkan:

mendeteksi kerusakan

Jadi:

Buffer overflow
      ↓
memory corruption
      ↓
canary ikut rusak
      ↓
deteksi
      ↓
abort

Ini penting:

Canary tidak membuat bug menghilang.

Ia mengurangi kemungkinan tertentu dari corruption berkembang menjadi control-flow compromise.


26. NX atau DEP

Pertahanan lain adalah mencegah area memory tertentu dieksekusi sebagai code.

Nama konsepnya dapat muncul sebagai:

NX
No-eXecute
DEP
Data Execution Prevention

Secara sederhana:

DATA MEMORY
    │
    ├── read ✅
    ├── write ✅
    └── execute ❌

Tujuannya mengurangi kelas serangan yang mengandalkan eksekusi kode langsung dari area data.

Namun:

NX aktif

bukan berarti:

semua buffer overflow tidak dapat dieksploitasi

Teknik modern dapat berusaha memanfaatkan code yang sudah ada dalam executable/shared libraries, sehingga pertahanan tidak boleh dianggap berdiri sendiri.

Intel mendokumentasikan ROP/COP/JOP sebagai bentuk control-flow subversion dan berbagai teknologi hardware/OS modern berusaha mengurangi kelas serangan tersebut. Intel Resource Download


27. ASLR

Address Space Layout Randomization membuat posisi berbagai memory region tidak selalu berada pada alamat yang sama dari satu proses ke proses lain.

Secara konseptual:

Run 1

stack → address A
libc  → address B
heap  → address C

kemudian:

Run 2

stack → address X
libc  → address Y
heap  → address Z

Tujuannya membuat memory address lebih sulit diprediksi.

Ini sangat relevan terhadap exploitation karena banyak teknik control-flow manipulation membutuhkan pengetahuan tentang lokasi target.

Karena itu binary exploitation modern tidak hanya memikirkan:

bug

tetapi juga:

memory layout
+
protections
+
information leaks

28. Information Disclosure Sangat Penting

Bayangkan sebuah program memiliki:

buffer overflow

tetapi alamat penting tidak diketahui.

Kemudian terdapat bug lain:

information leak

yang membocorkan alamat memory.

Maka vulnerability kedua dapat membuat vulnerability pertama jauh lebih berguna.

Secara konseptual:

Memory corruption
      +
Address disclosure
      ↓
lebih banyak informasi
      ↓
attack surface meningkat

Inilah mengapa vulnerability tidak selalu berdiri sendiri.


29. ROP Itu Apa?

Setelah mengenal NX, Anda akan bertemu istilah:

Return-Oriented Programming atau ROP.

Secara konseptual, ROP tidak mengharuskan attacker memasukkan instruksi machine code baru untuk setiap langkah.

Sebaliknya, pendekatan ini memanfaatkan potongan instruksi yang sudah ada dalam memory executable atau library, yang sering disebut gadgets, kemudian control flow disusun agar potongan-potongan tersebut digunakan.

Intel menjelaskan ROP sebagai salah satu metodologi untuk melakukan control-flow subversion dan menyebut shadow stack sebagai salah satu hardware defense terhadap ROP. Intel Resource Download

Untuk tahap pemula, cukup pahami:

Stack overflow
 ↓
control-flow corruption
 ↓
return address
 ↓
existing code sequences
 ↓
ROP

Tidak perlu langsung belajar menyusun ROP chain.


30. Shadow Stack

Teknologi yang lebih modern adalah shadow stack.

Konsepnya:

NORMAL STACK
┌────────────────┐
│ return address │
└────────────────┘

SHADOW STACK
┌────────────────┐
│ return address │
└────────────────┘

Saat fungsi dipanggil, return address dicatat pada keduanya.

Ketika RET:

normal return address
        ≠
shadow return address

        ↓

CONTROL PROTECTION EXCEPTION

Intel menjelaskan bahwa CET menggunakan shadow stack untuk melindungi return address dari manipulasi dan melakukan pemeriksaan saat RET. Intel Resource Download

Ini merupakan contoh menarik bagaimana defense semakin berpindah dari software-only protection ke hardware-assisted control-flow protection.


31. Mengapa Compiler Optimization Bisa Membingungkan?

Coba compile:

gcc -O0

kemudian:

gcc -O2

Machine code yang dihasilkan dapat berbeda secara signifikan.

Akibatnya:

-O0

sering lebih mudah dipelajari melalui debugger karena compiler melakukan lebih sedikit optimization.

Sedangkan:

-O2

dapat:

menghilangkan variable
memindahkan nilai ke register
mengubah control flow
mengubah stack layout

Jadi dalam pembelajaran binary analysis:

-g -O0

sering menjadi titik awal yang nyaman.


32. Mengapa Binary Exploitation Harus Belajar Assembly?

Karena pada akhirnya CPU tidak menjalankan:

strcpy(...)

CPU menjalankan machine instructions.

Compiler mengubah:

C
 ↓
Compiler
 ↓
Assembly / machine code

Sehingga security researcher perlu memahami hubungan:

source code
      ↓
compiler
      ↓
assembly
      ↓
register
      ↓
memory
      ↓
CPU behavior

Tidak perlu langsung menghafal ratusan instruksi.

Mulai dari:

mov
lea
push
pop
call
ret
cmp
test
jmp
je
jne

Itu sudah sangat membantu untuk memahami control flow dasar.


33. Stack Pointer dan Return Instruction

Dua konsep penting:

RSP

dan:

RET

Secara konseptual:

RSP
 ↓
[return address]

Kemudian:

RET
 ↓
ambil return address
 ↓
lanjutkan eksekusi

Linux kernel menjelaskan bahwa pada stack buffer overflow klasik, corruption terhadap stored return address merupakan titik penting dalam pengambilalihan control flow. Linux Kernel Documentation


34. Kenapa "Offset" Sering Dibicarakan?

Saat menganalisis stack corruption, researcher ingin mengetahui hubungan antara:

awal buffer

dan:

data penting yang berada setelahnya

Secara konseptual:

[ buffer ]
    ↓
    ↓ offset N
    ↓
[ control data ]

Jadi istilah offset pada binary exploitation pada dasarnya menjawab:

Berapa jauh posisi target dari awal data yang dikontrol?

Untuk pembelajaran defensif, Anda dapat memahami konsep ini dengan GDB dan memory inspection tanpa perlu membuat payload takeover.


35. Mengapa Crash Sendiri Belum Berarti Exploitable?

Ini salah satu kesalahan pemula.

Misalnya program:

AAAAAAAAAAAAAAAAAAAAAAAA

langsung crash.

Kesimpulan:

Buffer overflow terjadi.

mungkin benar.

Tetapi:

Buffer overflow
≠
automatic code execution

Eksploitabilitas bergantung pada:

apa yang tertimpa
apakah control data dapat dipengaruhi
apakah memory layout diketahui
apakah proteksi aktif
apakah corrupted state dapat digunakan
bagaimana compiler membangun binary

CWE-121 sendiri membedakan konsekuensi seperti crash dengan kemungkinan unauthorized code execution. CWE


36. Bagaimana Security Researcher Menganalisis Binary?

Workflow edukatif yang umum:

1. Identify binary
       ↓
2. Check protections
       ↓
3. Static analysis
       ↓
4. Dynamic analysis
       ↓
5. Find crash / memory bug
       ↓
6. Understand root cause
       ↓
7. Determine impact
       ↓
8. Develop mitigation
       ↓
9. Regression test

Tools yang umum antara lain:

GDB
objdump
readelf
strings
Ghidra
IDA
Binary Ninja
LLDB
AddressSanitizer
Valgrind

Untuk tahap awal:

GDB
+
objdump/readelf
+
AddressSanitizer

sudah sangat cukup untuk membangun fundamental.


37. Static vs Dynamic Analysis

Static Analysis

Binary dianalisis tanpa menjalankannya.

Misalnya:

ELF headers
symbols
imports
strings
assembly
control flow

Dynamic Analysis

Binary dijalankan dan diamati:

register
memory
stack
syscalls
execution flow
crash

Kombinasi keduanya:

STATIC
   +
DYNAMIC
   ↓
pemahaman binary lebih lengkap

38. Cek Binary dengan file

Setelah compile:

file overflow

Misalnya hasil:

ELF 64-bit LSB executable

Ini memberi informasi dasar mengenai format executable dan arsitektur.

Kemudian:

readelf -h overflow

untuk melihat ELF header.


39. Cek Symbol dan Section

Gunakan:

readelf -S overflow

Anda akan menemukan section seperti:

.text
.rodata
.data
.bss

Secara konseptual:

.text
↓
machine code

.rodata
↓
read-only data

.data
↓
initialized writable data

.bss
↓
uninitialized global/static data

Memahami section membantu menghubungkan source-level constructs dengan representation dalam executable.


40. Amati Assembly

Gunakan:

objdump -d overflow

atau:

objdump -M intel -d overflow

Anda bisa melihat instruksi seperti:

push
mov
sub
lea
call
leave
ret

Kemudian hubungkan:

source C
      ↓
assembly
      ↓
stack operation
      ↓
memory behavior

Di titik inilah binary exploitation mulai terasa masuk akal.


41. Mengapa Stack Canary Tidak Sama dengan Bounds Checking?

Ini perbedaan penting.

Bounds checking

Mencegah:

write out of bounds

atau setidaknya mendeteksinya sebelum dampak lebih jauh.

Stack canary

Mendeteksi indikasi:

stack corruption

setelah operasi yang merusak mungkin sudah terjadi.

Jadi defense terbaik adalah:

secure code
+
compiler protection
+
runtime detection
+
OS/hardware protection

NIST menekankan bahwa buffer overflow dapat ditangani melalui berbagai pendekatan seperti pengembangan software yang lebih aman dan mekanisme deteksi pada compiler. NIST


42. AddressSanitizer vs Stack Canary

Keduanya bukan hal yang sama.

AddressSanitizer:

instrumentation
↓
detect memory errors

Cocok untuk:

development
testing
fuzzing
debugging

Stack Canary:

runtime guard
↓
detect stack corruption

Cocok sebagai bagian dari binary hardening.

GCC mendokumentasikan -fsanitize=address untuk AddressSanitizer dan -fstack-protector sebagai mekanisme stack overflow detection. GCC


43. Cara Memperbaiki Buffer Overflow

Pertahanan pertama selalu memperbaiki root cause.

Misalnya hindari operasi tanpa batas seperti penggunaan strcpy() pada destination berukuran tetap.

Gunakan API yang memungkinkan program mempertimbangkan ukuran destination dan lakukan validasi panjang secara eksplisit.

Juga:

gunakan compiler modern
aktifkan stack protection
gunakan ASan pada testing
aktifkan hardening
lakukan fuzzing
lakukan code review

SEI CERT C/C++ menyediakan pedoman secure coding yang secara khusus membahas kesalahan memory management dan string manipulation. SEI


44. Defense in Depth

Sistem modern tidak boleh mengandalkan satu mekanisme:

"Sudah pakai canary, selesai."

Tidak.

Pendekatan yang lebih tepat:

           Secure Code
               │
               ▼
        Compiler Checks
               │
               ▼
        Stack Protector
               │
               ▼
              ASLR
               │
               ▼
               NX
               │
               ▼
        Control-flow Defense
               │
               ▼
          Sandbox / OS

Jika satu lapisan gagal, lapisan lain masih memberikan perlindungan tambahan.


45. Hal yang Sering Salah Dipahami Pemula

"Buffer overflow = langsung dapat shell"

Tidak.

Buffer overflow adalah vulnerability class.

Exploitability bergantung pada konteks.

"Kalau program tidak crash berarti aman"

Salah.

Undefined behavior tidak harus crash.

"Semua stack layout sama"

Tidak.

Compiler, ABI, optimization, arsitektur, dan platform memengaruhinya.

"Canary mencegah overflow"

Lebih tepat:

canary membantu mendeteksi sebagian stack corruption.

"NX membuat buffer overflow tidak berbahaya"

Tidak.

NX hanya menghadang kelas tertentu dari code execution.

"Binary exploitation cuma hafal command GDB"

Tidak.

Fundamental utamanya adalah:

C
+
memory
+
assembly
+
CPU
+
OS
+
ABI
+
security mitigations

46. Roadmap Belajar Binary Exploitation

Untuk mahasiswa atau pemula cybersecurity, urutan yang masuk akal:

LEVEL 1
C programming
│
├── pointer
├── array
├── struct
├── memory allocation
└── string handling
        ↓
LEVEL 2
Computer Architecture
│
├── register
├── CPU
├── memory
├── instruction
└── stack
        ↓
LEVEL 3
Assembly
│
├── mov
├── call
├── ret
├── cmp
├── jmp
└── stack operations
        ↓
LEVEL 4
Linux
│
├── ELF
├── process
├── virtual memory
├── permissions
└── debugger
        ↓
LEVEL 5
Binary Analysis
│
├── GDB
├── Ghidra
├── objdump
└── readelf
        ↓
LEVEL 6
Memory Bugs
│
├── stack overflow
├── heap overflow
├── use-after-free
├── out-of-bounds
└── format string
        ↓
LEVEL 7
Mitigations
│
├── ASLR
├── NX
├── Canary
├── PIE
└── CET / shadow stack

Setelah fundamental ini kuat, barulah konsep exploitation yang lebih lanjut seperti control-flow hijacking dan ROP menjadi jauh lebih mudah dipahami.


47. Lab yang Bagus untuk Belajar

Jangan menguji binary exploitation terhadap:

server orang lain
website publik
aplikasi produksi
komputer yang bukan milik sendiri

Gunakan:

VM
Docker
CTF
lab lokal
binary latihan

Buat environment seperti:

Ubuntu VM
+
GDB
+
GCC
+
Ghidra
+
ASan

Dengan begitu Anda bebas melakukan eksperimen tanpa merusak sistem produksi.


48. Inti Buffer Overflow dalam Satu Diagram

Kalau semua pembahasan di atas diringkas:

        INPUT
          │
          ▼
┌──────────────────┐
│  Buffer terbatas │
│     16 byte      │
└────────┬─────────┘
         │
         │ input terlalu besar
         ▼
┌──────────────────┐
│ Out-of-bounds    │
│ write            │
└────────┬─────────┘
         │
         ▼
┌──────────────────┐
│ Memory corruption│
└────────┬─────────┘
         │
         ├───────────────┐
         ▼               ▼
   Data berubah     Control data
                         │
                         ▼
                  Return address
                         │
                         ▼
                  Control-flow
                     corruption
                         │
                    ┌────┴────┐
                    ▼         ▼
                  Crash    Potential
                           exploitation

Sedangkan sistem yang dilindungi:

Overflow attempt
      │
      ▼
Stack Canary / ASan
      │
      ▼
Detection
      │
      ▼
Process terminated

49. Jadi Apa yang Sebenarnya Terjadi Saat Buffer Overflow?

Jawaban paling teknis tetapi sederhana adalah:

Program melakukan operasi memory yang melewati boundary objek yang seharusnya.

Kemudian:

1. Input masuk
2. Program menyalin data
3. Tidak ada bounds checking yang memadai
4. Penulisan melewati buffer
5. Byte tambahan masuk ke memory lain
6. Data lain dapat rusak
7. Jika control data terkena, control flow dapat berubah
8. Jika pertahanan mendeteksi corruption, program dapat dihentikan
9. Jika kondisi tertentu memungkinkan, vulnerability dapat berkembang menjadi security compromise

Jadi buffer overflow bukanlah "sihir hacker".

Ia merupakan konsekuensi langsung dari hubungan antara:

programmer
    ↓
memory model
    ↓
compiler
    ↓
machine code
    ↓
CPU

Begitu Anda memahami hubungan tersebut, binary exploitation yang awalnya tampak seperti sekumpulan angka hexadecimal mulai terlihat sebagai sesuatu yang sangat logis.


Kesimpulan

Buffer overflow adalah vulnerability memory-safety yang terjadi ketika program menulis melewati batas buffer. Pada stack-based buffer overflow, memory yang berdekatan dengan buffer dapat mencakup data penting untuk eksekusi fungsi, termasuk stored return address. Jika control data tersebut rusak, program dapat crash atau, dalam kondisi tertentu, mengalami control-flow corruption. Linux Kernel Documentation

Binary exploitation kemudian menjadi persoalan memahami:

Memory
+
Assembly
+
Calling Convention
+
CPU
+
Compiler
+
Operating System
+
Mitigations

Dan inilah alasan mengapa belajar buffer overflow bukan sekadar belajar "cara mendapatkan shell". Fundamental sebenarnya adalah memahami bagaimana software menggunakan memory dan bagaimana kesalahan kecil pada memory-safety dapat memengaruhi perilaku program.

Di dunia modern, teknik pertahanan seperti stack protector, ASLR, NX, AddressSanitizer, dan shadow stack juga membuat exploitation semakin kompleks dan sekaligus memberikan materi penting untuk dipelajari dari sisi defensive security. GCC, Linux, dan Intel masing-masing mendokumentasikan berbagai mekanisme tersebut. GCC


SIBRA SECURITY

Binary vulnerability membutuhkan pemahaman teknis yang jauh lebih dalam daripada sekadar menjalankan vulnerability scanner.

SIBRA Security membantu kebutuhan cybersecurity seperti security assessment, vulnerability assessment, penetration testing, security hardening, website security assessment, serta konsultasi cybersecurity untuk membantu organisasi memahami risiko dan memperkuat sistem mereka.