Oleh kerana saya tidak sabar untuk terus membincangkan topik ini, izinkan saya menceritakan sedikit sejarah, teori dan praktik mengenai kelemahan. Kita semua telah mendengar bahawa kekurangan keselamatan dapat menelan belanja yang tinggi, kita semua tahu bahawa kita mesti memperbarui perisian kita, kita semua tahu bahawa banyak kemas kini disebabkan oleh kesalahan keselamatan. Tetapi hari ini saya akan memberitahu anda sedikit mengenai bagaimana kesalahan ini dijumpai dan dieksploitasi 🙂 Tetapi sebelum ini kita akan menjelaskan beberapa butiran untuk mendapatkan gambaran keseluruhan yang lebih baik.
Sebelum anda bermula
Mula-mula saya ingin memberitahu anda bahawa kita akan menumpukan perhatian kepada kelemahan pertama yang saya pelajari, yang diketahui Limpahan Penimbal, dalam kerentanan ini, kami memanfaatkan kekurangan pengesahan memori untuk melakukan perkara yang menyeronokkan 🙂 Tetapi mari kita jelaskan sedikit lagi mengenainya.
Ini tidak akan menjadi senario dunia nyata
Saya tidak mampu untuk mengajar mereka untuk menghentikan program yang mereka lihat 🙂 pertama kerana berbahaya bagi komputer mereka, kedua kerana itu akan mengambil lebih banyak daripada kuota perkataan saya yang biasa.
Kami meneruskan perjalanan ke tahun 80an
Apa yang akan saya tunjukkan kepada anda boleh saya lakukan di komputer riba saya, tetapi itu tidak bermaksud bahawa ia dapat dilakukan hari ini dengan cara yang mudah 🙂 banyak konsep ini telah dimanfaatkan berkali-kali sehingga kaedah perlindungan baru dan kaedah baru untuk mengelakkan mereka telah muncul 😛 tetapi itu mengembalikan kita ke tempat yang sama, tidak ada ruang untuk dapat memberitahu semua itu 🙂
Ia mungkin tidak berfungsi pada pemproses anda
Walaupun saya akan menggunakan contoh yang sangat sederhana, saya ingin sejak awal lagi jelas bahawa perinciannya sangat banyak dan sangat berbeza sehingga sama seperti saya, jika anda ingin mencubanya , kesan yang diinginkan juga tidak dapat dicapai 🙂 Tetapi anda dapat membayangkan bahawa saya tidak dapat menjelaskannya di ruang ini, terutamanya kerana dengan pengenalan ini saya telah mengambil lebih dari 300 perkataan, jadi kami langsung sampai ke titik kami.
Apa itu a Limpahan Penyangga
Untuk menjawabnya, kita mesti memahami separuh pertama gabungan ini.
Buffer
Oleh kerana semuanya berkaitan dengan memori dalam komputer, adalah logik bahawa mesti ada beberapa jenis wadah maklumat. Apabila kita bercakap mengenai input o output, kami datang secara langsung kepada konsep penampan. Untuk memastikannya pendek, a penampan Ini adalah ruang memori dengan ukuran yang ditentukan di mana kita akan menyimpan sejumlah maklumat, mudah simple
Limpahan berlaku, seperti namanya, ketika penyangga mengisi dengan lebih banyak maklumat daripada yang dapat ditangani. Tetapi mengapa ini penting?
Menumpukkan
Juga dikenali sebagai tumpukan, mereka adalah jenis data abstrak di mana kita boleh timbunan maklumat, ciri utama mereka adalah bahawa mereka mempunyai pesanan LIFO (Terakhir dalam Keluar Pertama). Mari kita berfikir sejenak mengenai timbunan pinggan, kita meletakkannya di atas satu demi satu, dan kemudian kita mengeluarkannya satu persatu dari atas, ini menjadikan piring terakhir yang kita letakkan (yang ada di bahagian atas ) adalah plat pertama yang akan kita keluarkan, jelas jika kita hanya dapat mengambil satu pinggan pada satu masa dan kita memutuskan untuk melakukannya mengikut urutan: P.
Sekarang setelah anda mengetahui kedua konsep ini, kami harus menyusunnya. Tumpukan adalah penting kerana setiap program yang kita jalankan ada yang tersendiri timbunan pelaksanaan. Tetapi timbunan ini mempunyai ciri khas, tumbuh ke bawah. Satu-satunya perkara yang perlu anda ketahui ialah semasa program dijalankan, apabila fungsi dipanggil, timbunan beralih dari nombor X dalam memori ke nombor (Xn). Tetapi untuk meneruskannya kita mesti memahami satu konsep lagi.
Petunjuk
Ini adalah konsep yang membuat banyak pengaturcara tergila-gila ketika mereka bermula di dunia C, sebenarnya kehebatan pengaturcaraan C sebahagiannya disebabkan oleh penggunaan petunjuk. Untuk memastikannya mudah, penunjuk menunjuk ke alamat memori. Ini terdengar rumit, tetapi tidak begitu rumit, kita semua mempunyai RAM di mesin kita kan? Ini boleh ditakrifkan sebagai susunan blok berturut-turut, lokasi-lokasi ini biasanya dinyatakan dalam nombor heksadesimal (dari 0 hingga 9 dan kemudian dari A hingga F, seperti 0x0, 0x1, 0x6, 0xA, 0xF, 0x10). Di sini sebagai nota ingin tahu, 0x10 TIDAK sama dengan 10 😛 jika kita menukarnya ke urutan perpuluhan, ia akan sama dengan mengatakan 15. Ini adalah sesuatu yang juga membingungkan lebih dari satu pada mulanya, tetapi mari kita turunkan.
Rekod
Pemproses berfungsi dengan sebilangan rekod, yang berfungsi untuk menghantar lokasi dari memori fizikal ke pemproses, untuk seni bina yang menggunakan 64-bit, jumlah daftarnya besar dan sukar untuk dijelaskan di sini, tetapi untuk mendapatkan idea, daftar itu seperti penunjuk, mereka menunjukkan antara lain , ruang memori (lokasi).
Sekarang amalkan
Saya tahu bahawa sudah banyak maklumat yang diproses hingga sekarang, tetapi pada hakikatnya mereka adalah masalah yang agak rumit yang saya cuba terangkan dengan cara yang sangat mudah, kita akan melihat program kecil yang menggunakan penyangga dan kita akan memecahkannya untuk memahami ini mengenai limpahan, jelas ini bukan Program yang sebenar, dan kita akan "menghindari" banyak tindakan pencegahan yang digunakan hari ini, hanya untuk menunjukkan bagaimana perkara dilakukan sebelum ini 🙂 dan kerana beberapa di antaranya prinsip perlu untuk dapat mempelajari perkara yang lebih kompleks 😉
GDB
Program hebat yang tidak diragukan lagi salah satu yang paling sering digunakan oleh pengaturcara C. Di antara banyak kebajikannya, kita mempunyai hakikat bahawa ia membolehkan kita melihat semua ini yang kita bicarakan selama ini, daftar, timbunan, penyangga, dll. 🙂 Mari lihat program yang akan kita gunakan untuk contoh kita.
retinput.c
Ini adalah program yang cukup mudah, kami akan menggunakan perpustakaan stdio.h
untuk dapat memperoleh maklumat dan memaparkannya di terminal. Kita dapat melihat fungsi yang dipanggil return_input
yang menghasilkan a penampan dipanggil pelbagai, yang mempunyai panjang 30 bait (jenis data char panjangnya 1 bait).
Fungsi ini gets(array);
meminta maklumat melalui konsol dan fungsi printf()
mengembalikan kandungan array dan memaparkannya di skrin.
Setiap program yang ditulis dalam C bermula dengan fungsi main()
, ini hanya akan bertanggungjawab untuk memanggil return_input, sekarang kita akan menyusun program.
Mari ambil sedikit dari apa yang baru saya buat. Pilihannya -ggdb
memberitahu gcc untuk menyusun program dengan maklumat agar gdb dapat melakukan debug dengan betul. -fno-stack-protector
Ini adalah pilihan yang jelas kita tidak boleh gunakan, tetapi yang akan kita gunakan kerana jika tidak, mungkin untuk membuat overflow penyangga di timbunan. Pada akhirnya saya telah menguji hasilnya. ./a.out
ia hanya menjalankan apa yang baru saya kumpulkan, ia meminta saya maklumat dan mengembalikannya. Berlari 🙂
Amaran
Catatan lain di sini. Bolehkah anda melihat amarannya? jelas ia adalah sesuatu yang perlu diambil kira semasa kita bekerja dengan kod atau menyusun, ini sedikit jelas dan ada beberapa program yang pada masa ini mempunyai fungsi gets()
Dalam kod. Satu kelebihan Gentoo adalah bahawa dengan menyusun setiap program, saya dapat melihat apa yang salah, program "ideal" tidak boleh memilikinya, tetapi anda akan terkejut berapa banyak program besar yang mempunyai peringatan ini kerana ia sangat SANGAT besar dan itu sukar untuk mengawasi fungsi berbahaya apabila terdapat banyak amaran pada masa yang sama. Sekarang jika kita teruskan
Menyahpepijat program
Sekarang bahagian ini sedikit membingungkan, tetapi kerana saya sudah cukup menulis, saya tidak dapat menjelaskan semuanya, jadi maaf jika anda melihat bahawa saya terlalu cepat 🙂
Melucutkan kod
Mari mulakan dengan melihat program bahasa mesin yang disusun.
Ini adalah kod fungsi utama kami di Perhimpunan, inilah yang difahami oleh pemproses kami, garis di sebelah kiri adalah alamat fizikal dalam ingatan, <+ n> dikenali sebagai mengimbangi, pada dasarnya jarak dari awal fungsi (utama) ke pernyataan itu (dikenali sebagai Opcode). Kemudian kita melihat jenis arahan (push / mov / callq…) dan satu atau lebih register. Ringkasnya kita dapat mengatakan bahawa itu adalah petunjuk yang diikuti oleh sumber / asal dan tujuan. <return_input>
merujuk kepada fungsi kedua kami, mari kita lihat.
return_input
Ini sedikit lebih rumit, tetapi saya hanya mahu anda memeriksa beberapa perkara, terdapat tanda nama <gets@plt>
dan satu opcode terakhir dipanggil retq
menunjukkan akhir fungsi. Kami akan meletakkan beberapa titik pemisah, satu dalam fungsi gets
dan satu lagi di retq
.
Main
Sekarang kita akan menjalankan program untuk melihat bagaimana tindakannya bermula.
Kita dapat melihat bahawa anak panah kecil muncul yang menunjukkan opcode di mana kita berada, saya mahu mereka mengambil kira arahnya 0x000055555555469b
, ini adalah alamat selepas panggilan ke return_input
dalam fungsi main
, ini penting kerana di sinilah program akan kembali apabila anda selesai menerima input, mari masuk ke dalam fungsi. Sekarang kita akan memeriksa memori sebelum memasuki fungsi gets
.
Saya telah meletakkan fungsi utama untuk anda, dan saya telah menyoroti kod yang saya maksudkan, seperti yang anda lihat, kerana kemesraan telah dipisahkan menjadi dua segmen, saya mahu mereka mengambil kira arahnya 0x7fffffffdbf0
(yang pertama dari kiri selepas komando x/20x $rsp
) kerana ini adalah lokasi yang harus kita gunakan untuk memeriksa hasil yang diperoleh, mari kita teruskan:
Melanggar program
Saya telah mengetengahkannya 0x44444444
kerana mereka adalah representasi dari Ds kami 🙂 sekarang kami telah mula menambahkan input untuk program ini, dan seperti yang anda lihat, kami hanya dua baris dari alamat yang diinginkan, kami akan mengisinya sehingga kami berada tepat sebelum alamat yang kami sorot pada langkah sebelumnya.
Menukar jalan kembali
Sekarang kita berjaya memasukkan bahagian kod ini di mana ia menunjukkan kembalinya fungsi, mari kita lihat apa yang berlaku jika kita menukar alamat 🙂 dan bukannya pergi ke lokasi opcode yang mengikuti yang kita ada sebentar tadi, apa pendapat anda sekiranya kita kembali kepada return_input
? Tetapi untuk ini, perlu menulis alamat yang kita mahukan dalam binari, kita akan melakukannya dengan fungsi printf
dari bash 🙂
Sekarang kami telah menerima maklumat dua kali 😀 pastinya program ini tidak dibuat untuk itu, tetapi kami berjaya memecahkan kod tersebut dan membuatnya mengulangi sesuatu yang tidak sepatutnya dilakukan.
Refleksi
Perubahan sederhana ini boleh dianggap sebagai mengeksploitasi sangat asas 🙂 dia berjaya menghentikan program dan melakukan sesuatu yang kita mahu dia lakukan.
Ini hanyalah langkah pertama dalam senarai perkara yang hampir tidak terbatas untuk dilihat dan ditambahkan, ada cara untuk menambahkan lebih banyak perkara daripada sekadar mengulang pesanan, tetapi kali ini saya telah menulis banyak dan semua yang berkaitan dengan pengekodan shell adalah subjek untuk menulis lebih banyak daripada artikel, buku-buku lengkap yang akan saya katakan. Maaf sekiranya saya tidak dapat membahas sedikit lagi topik yang saya mahukan, tetapi pasti akan ada peluang 🙂 Salam dan terima kasih kerana sampai di sini.
Jadilah lebih langsung. Tulis lebih sedikit dan fokus pada perkara yang penting
Hai, terima kasih atas komen.
Sejujurnya, saya telah memotong sebilangan besar idea, tetapi walaupun saya berpendapat bahawa saya telah meninggalkan minimum sehingga seseorang yang tidak mempunyai pengetahuan pengaturcaraan dapat memperoleh idea.
salam
Masalahnya ialah mereka yang tidak mempunyai pengetahuan pengaturcaraan tidak akan mengetahui apa-apa kerana terlalu rumit untuk dimulakan, tetapi mereka yang tahu bagaimana memprogram menghargai mereka lebih langsung.
Saya rasa anda tidak dapat menjangkau semua orang, anda harus memilih, dan dalam kes ini anda telah berdosa kerana ingin membuat liputan banyak.
Ngomong-ngomong, saya katakan sebagai kritikan yang membina, saya suka topik-topik ini dan saya ingin anda terus menulis artikel, selamat!
Saya rasa perkara yang sama.
Terima kasih banyak kepada kedua-duanya !! sudah tentu sukar untuk memahami bagaimana menjangkau khalayak sasaran apabila kebenarannya adalah bahawa jumlah orang dengan tahap pengaturcaraan lanjutan yang membaca artikel ini sedikit (sekurang-kurangnya dapat disimpulkan berdasarkan komen)
Saya pastinya berdosa kerana ingin mempermudah sesuatu yang memerlukan asas pengetahuan yang luas untuk difahami. Saya harap anda memahami bahawa sejak saya baru memulakan blog, saya belum menemui titik yang tepat di mana pembaca saya tahu dan memahami apa yang saya katakan. Itu akan menjadikannya lebih mudah untuk mengatakan yang sebenarnya 🙂
Saya akan berusaha menjadi lebih pendek apabila pantas tanpa memformat format, kerana memisahkan cara penulisan dari kandungan sedikit lebih rumit daripada yang mungkin dibayangkan, sekurang-kurangnya saya mempunyai kaitannya, tetapi saya rasa akhirnya saya dapat untuk menambah baris dan bukannya memotong kandungan.
salam
Di mana anda boleh mengetahui lebih lanjut mengenai subjek ini? Ada buku yang disyorkan?
Contohnya diambil dari Buku Panduan The Shellcoder oleh Chris Anley, John Heasman, Felix Linder dan Gerardo Richarte, tetapi untuk melakukan terjemahan 64-bit saya harus belajar mengenai seni bina saya, manual pemaju intel, jilid 2 dan 3 adalah sumber yang cukup dipercayai untuk itu. Ada baiknya membaca dokumentasi GDB, yang disertakan dengan arahan 'info gdb', Untuk belajar Assembly dan C terdapat banyak buku yang sangat bagus, kecuali buku Assembly agak lama sehingga ada jurang untuk mengisi dengan buku lain taipkan dokumentasi.
Kod shell itu sendiri tidak lagi berkesan hari ini kerana pelbagai alasan, tetapi masih menarik untuk mempelajari teknik baru.
Semoga sedikit sebanyak membantu 🙂 Salam
Buen artículo, el viejo blog desdelinux ha vuelto a renacer =)
Apabila anda mengatakan bahawa cengkerang jarak jauh tidak begitu berkesan, anda bermaksud langkah-langkah pencegahan yang dirancang untuk mengurangkan serangan, mereka menyebutnya keselamatan yang menyinggung.
Salam dan teruskan
Terima kasih banyak Franz 🙂 kata-kata yang sangat baik, sebenarnya saya bermaksud bahawa Shellcoding hari ini jauh lebih kompleks daripada yang kita lihat di sini. Kami mempunyai ASLR (penjana lokasi memori rawak) pelindung timbunan, pelbagai langkah dan tindakan pencegahan yang membatasi bilangan opkod yang dapat disuntik ke dalam program, dan ini baru permulaan.
Regards,
Helo, adakah anda akan melakukan bahagian lain untuk memperluas topik? Ia menarik
Helo, topik ini tentunya cukup menarik, tetapi tahap kerumitan yang akan kita ambil akan menjadi sangat tinggi, mungkin melibatkan sebilangan besar catatan untuk menjelaskan pelbagai prasyarat untuk memahami yang lain. Saya mungkin akan menulis mengenainya, tetapi tidak akan menjadi catatan berikut, saya ingin menulis beberapa topik sebelum meneruskan topik ini.
Salam, dan terima kasih kerana berkongsi
Che sangat bagus! Anda menyumbang siaran hebat! Satu soalan, saya memulakan perkara Keselamatan IT ini dengan membaca buku berjudul "Menjamin keselamatan dengan ujian pen." Adakah buku ini disyorkan? Bagaimana anda mencadangkan agar saya mula bertanya mengenai masalah ini?
Halo kaktus, ini adalah keseluruhan alam semesta mengenai kelemahan, dan lain-lain, untuk mengatakan yang sebenarnya sangat bergantung pada apa yang menarik perhatian anda, dan keperluan yang anda miliki, seorang pengurus IT tidak perlu tahu sama dengan pen-tester, Atau penyelidik kerentanan, atau penganalisis forensik, pasukan pemulihan bencana mempunyai set kemahiran yang sangat berbeza. Jelas masing-masing memerlukan tahap pengetahuan teknikal yang berbeza, saya mengesyorkan agar anda mula menemui apa yang anda suka, dan mula memakan buku, artikel, dan lain-lain, dan yang paling penting, berlatih semua yang anda baca, walaupun sudah ketinggalan zaman, itu akan membuat perbezaan pada akhirnya.
Regards,
Hei.
Terima kasih banyak untuk menerangkan topik ini, serta memberi komen bahawa untuk maklumat tambahan kami mempunyai "Buku Panduan The Shellcoder". Saya sudah mempunyai bacaan yang belum selesai 😉