Sabtu, 13 Februari 2010

advanced shellcode tehnic

Pendahuluan

Tulisan ini mengasumsikan pengetahuan bekerja shellcoding dasar teknik, dan x86 perakitan, aku tidak akan pengulangan ini dalam makalah ini. Saya berharap untuk mengajarkan Anda beberapa teknik shellcoding kurang dikenal bahwa aku telah memilih, yang akan memungkinkan Anda untuk menulis lebih kecil dan lebih baik shellcodes. Saya tidak mengklaim telah menemukan salah satu teknik ini, kecuali bagi orang yang menggunakan instruksi div.


Banyaknya mul

Teknik ini pada awalnya dikembangkan oleh Sorbo dari darkircop.net. Instruksi yang mul mungkin, di permukaan, tampak biasa, dan tujuan jelas. Namun, ketika dihadapkan dengan tantangan yang sulit menyusut shellcode Anda, itu terbukti cukup berguna. Pertama latar belakang informasi tentang instruksi mul itu sendiri.

mul melakukan suatu unsigned mengalikan dua bilangan bulat. Hanya membutuhkan satu operand, yang lain secara implisit ditentukan oleh% eax register. Jadi, instruksi mul umum akan terlihat seperti ini:

movl $ 0x0a,% eax
mul $ 0x0a

Ini akan kalikan nilai disimpan dalam% eax oleh operand dari mul, yang dalam hal ini akan menjadi 10 * 10. Hasilnya kemudian secara implisit disimpan dalam EDX: EAX. Hasilnya disimpan selama rentang dua register karena memiliki potensi untuk menjadi jauh lebih besar dari nilai sebelumnya, mungkin melebihi kapasitas satu register (hal ini juga bagaimana mengapung poin disimpan dalam beberapa kasus, seperti yang menarik sidenote) .

Jadi, sekarang datang yang selalu pertanyaan penting. Bagaimana kita dapat menggunakan atribut ini untuk keuntungan kita ketika menulis shellcode? Yah, mari kita berpikir sejenak, instruksi yang hanya membutuhkan satu operand, oleh karena itu, karena itu adalah instruksi yang sangat umum, itu akan menghasilkan hanya dua byte terakhir kami shellcode. It mengalikan apa pun yang berlalu kepadanya oleh nilai yang disimpan di% eax, dan menyimpan nilai dalam kedua% edx dan% eax, benar-benar Timpa isi dari kedua register, terlepas dari apakah perlu untuk melakukannya, untuk menyimpan hasil dari perkalian. Mari kita memakai topi matematikawan kami untuk kedua, dan mempertimbangkan ini, apa yang satu-satunya hasil dari perkalian dengan 0? Jawabannya, seperti yang bisa Anda tebak, adalah 0. Saya pikir sudah waktunya untuk beberapa contoh kode, jadi here it is:

xorl% ecx,% ecx
mul% ecx

Apa shellcode ini lakukan? Yah, itu 0 yang keluar dari% ecx xor mendaftar menggunakan instruksi, jadi kita sekarang tahu bahwa% ecx adalah 0. Maka tidak seorang mul% ecx, yang seperti kita baru tahu, mengalikan itu operand oleh nilai di% eax, dan kemudian berlanjut untuk menyimpan hasil perkalian ini dalam EDX: EAX. Jadi, terlepas dari% eax isi sebelumnya,% eax sekarang harus 0. Namun itu belum semua,% edx adalah 0'd sekarang juga, karena, meskipun tidak ada overflow terjadi, itu masih menimpa% edx mendaftarkan dengan bit tanda (bit paling kiri) dari% eax. Dengan menggunakan teknik ini kita dapat nol tiga register hanya dalam waktu tiga byte, sedangkan dengan metode lainnya (yang saya ketahui) itu akan diambil sekurang-kurangnya enam.


Div instruksi

Div adalah sangat serupa dengan mul, di bahwa dibutuhkan hanya satu operand dan secara implisit membagi operand oleh nilai di% eax. Juga seperti, mul ini menyimpan hasil dari membagi dalam% eax. Sekali lagi, kita akan memerlukan sisi matematis otak kita untuk mengetahui bagaimana kita dapat mengambil keuntungan dari instruksi ini. Tapi pertama-tama, mari kita berpikir tentang apa yang biasanya disimpan di dalam% eax register. The% eax mendaftar memegang nilai kembali fungsi dan / atau syscalls. Kebanyakan syscalls yang digunakan dalam shellcoding akan kembali -1 (pada kegagalan) atau nilai positif dari beberapa jenis, hanya jarang akan mereka kembali 0 (meskipun hal itu terjadi). Jadi, jika kita tahu bahwa setelah dilakukan syscall,% eax akan punya nilai bukan nol, dan bahwa instruksi divl% eax akan membagi% eax dengan sendirinya, dan kemudian menyimpan hasilnya dalam% eax, kita dapat mengatakan bahwa pelaksanaan yang divl% eax instruksi setelah syscall akan meletakkan nilai 1 ke dalam% eax. Jadi ... bagaimana ini berlaku untuk shellcoding? Yah, mereka adalah hal penting lain yang% eax digunakan untuk, dan yang lulus syscall spesifik yang Anda ingin panggilan ke int $ 0x80. Kebetulan bahwa syscall bahwa sesuai dengan nilai 1 adalah keluar (). Sekarang untuk sebuah contoh:

      
xorl% ebx,% ebx
mul% ebx
push% edx
pushl $ 0x3268732f
pushl $ 0x6e69622f
mov% esp,% ebx
push% edx
push% ebx
mov% esp,% ecx
movb $ 0xb,% al # execve () syscall, tidak kembali sama sekali, kecuali jika gagal, dalam hal ini mengembalikan -1
int $ 0x80

divl% eax # -1 / -1 = 1
int $ 0x80

Sekarang, kami memiliki 3 byte keluar fungsi, dimana sebelum itu adalah 5 bytes. Namun, ada menangkap, bagaimana jika seorang syscall tidak kembali 0? Baik dalam situasi yang aneh yang bisa terjadi, Anda bisa melakukan banyak hal yang berbeda, seperti inc% eax, Desember% eax, bukan% eax sesuatu yang akan membuat% eax non-nol. Beberapa orang mengatakan bahwa keluar yang tidak penting dalam shellcode, karena kode Anda dijalankan peduli apakah atau tidak keluar bersih. Mereka benar juga, jika Anda benar-benar perlu untuk menyimpan 3 byte yang sesuai dengan shellcode di suatu tempat, keluar () tidak layak disimpan. Namun, ketika kode Anda tidak selesai, itu akan mencoba untuk melaksanakan apa pun yang setelah instruksi terakhir Anda, yang kemungkinan besar akan menghasilkan SIG Ill (instruksi ilegal) yang merupakan kesalahan yang agak aneh, dan akan dicatat oleh sistem. Jadi, keluar () hanya menambahkan lapisan ekstra siluman mengeksploitasi Anda, sehingga bahkan jika itu gagal atau Anda tidak dapat menghapus semua log, setidaknya ini bagian dari keberadaan Anda akan menjadi jelas.



Membuka kunci kekuatan Leal

The Leal instruksi adalah instruksi yang sering diabaikan dalam shellcode, meskipun itu cukup berguna. Pertimbangkan potongan pendek ini shellcode.

xorl% ecx,% ecx
Leal 0x10 (% ecx),% eax

Hal ini akan memuat nilai 17 ke eax, dan jelas semua bit ekstra eax. Hal ini terjadi karena beban instruksi Leal variabel panjang dari jenis ini desitination ke operand. Di dalamnya penggunaan normal, ini akan memuat alamat dari suatu variabel ke register, sehingga menciptakan semacam pointer. Namun, karena ecx adalah 0'd dan 0 17 = 17, kita muat ke dalam 17 nilai eax apapun bukan alamat sebenarnya. Dalam normal shellcode kita akan melakukan sesuatu seperti ini, untuk mencapai hal yang sama:

xorl% eax,% eax
movb $ 0x10,% eax

Saya dapat mendengar Anda berkata, tetapi bahwa shellcode adalah byte Leal lebih pendek daripada satu, dan kau benar. Namun, dalam real shellcode Anda mungkin sudah memiliki untuk 0 out register seperti ecx (atau mendaftar lainnya), sehingga instruksi di xorl shellcode Leal tidak dihitung. Berikut adalah contohnya:

xorl% eax,% eax
xorl% ebx,% ebx
movb $ 0x17,% al
int $ 0x80
      
xorl% ebx,% ebx
Leal 0x17 (% ebx),% al
int $ 0x80

Kedua panggilan shellcodes setuid (0), tapi satu melakukannya di 7 bytes sementara yang lain melakukannya di 8. Sekali lagi, saya mendengar Anda katakan, tetapi itu hanya satu byte itu tidak membuat banyak perbedaan, dan Anda benar, ini tidak membuat banyak perbedaan (kecuali untuk dalam ukuran shellcode kencing kontes = p) , tetapi ketika diterapkan pada shellcodes jauh lebih besar, yang memiliki banyak fungsi panggilan dan perlu melakukan hal-hal seperti ini sering, dapat menyimpan cukup sedikit ruang.

0 komentar:

Posting Komentar