Suture adalah poin statis untuk dan alat analisis noda orde tinggi (untuk C) berdasarkan LLVM IR dan dibangun di atas Dr. Checker (terima kasih banyak kepada penciptanya!), Dua sorotan adalah:
Kami menamainya jahitan dengan harapan bahwa itu bisa tepat pembedahan, sambil dapat menjahit beberapa fungsi syscall/entri bersama-sama untuk membangun aliran data tingkat tinggi. Untuk detail lebih lanjut silakan merujuk ke makalah kami: secara statis menemukan kerentanan gaya noda tingkat tinggi di kernel OS di ACM CCS'21 .
Klon pertama repo:
~$ git clone https://github.com/seclab-ucr/SUTURE.git suture
Kemudian siapkan lingkungan LLVM untuk jahitan:
~$ cd suture
~/suture$ python setup_suture.py -o ../suture_deps
Opsi (untuk setup_suture.py ):
-b Menentukan nama cabang LLVM yang akan diatur untuk Jahitan, itu default untuk "Release_90" (yaitu, LLVM 9.0) di LLVM Mirror Repo ini.-o Menentukan folder untuk meng -host semua barang yang dibutuhkan oleh Suture (misalnya, LLVM), gunakan folder apa pun yang Anda sukai. Bergantung pada perangkat keras Anda, pengaturan LLVM mungkin memakan waktu cukup lama. Setelah selesai, file SRCIPT bernama env.sh akan dihasilkan di bawah folder root Suture, berisi perintah untuk mengatur variabel lingkungan yang digunakan oleh jahitan.
Penting : Pastikan untuk mengaktifkan env.sh ini setiap kali sebelum membangun/menggunakan jahitan (Anda juga dapat menambahkan perintah yang terkandung ke .bashrc untuk aktivasi otomatis pada login shell)!
~/suture$ source env.sh
Selanjutnya kita akan membangun jahitan:
~/suture$ cd llvm_analysis
~/suture/llvm_analysis$ ./build.sh
Setelah membangun yang sukses, jahitan siap digunakan.
Jahitan dapat digunakan untuk menemukan kerentanan noda orde tinggi di luar kotak, di bagian ini kami berjalan melalui proses ini dengan contoh (misalnya, contoh memotivasi seperti yang ditunjukkan pada bagian 2.1 dalam makalah kami).
Untuk menemukan kerentanan jahitan memerlukan dua jenis input: (1) modul program yang dikumpulkan ke bitcode LLVM (misalnya, file .bc ), dan (2) file konfigurasi untuk modul yang memanifestasikan fungsi entri dan argumen yang dikendalikan pengguna.
Pertama -tama mari kita siapkan bitcode LLVM untuk contoh memotivasi kami:
~/suture$ cd benchmark
~/suture/benchmark$ ./gen.sh motivating_example
Catatan : Untuk kenyamanan kami menyediakan gen.sh untuk mengkompilasi .c ke .bc dan .ll (bitcode llvm yang dapat dibaca manusia), dengan level optimisasi -O1 .
Sekarang kita harus memiliki motivasi_example.bc di bawah folder patokan yang sama, itulah modul program input untuk jahitan.
Kemudian datang ke file konfigurasi, kami telah menyiapkan satu untuk contoh memotivasi:
~/suture/benchmark$ cat conf_motivating_example
entry0 MY_IOCTL 1
entry1 NULL_ARG
entry2 NULL_ARG
Penjelasan : Setiap baris dalam file konfigurasi menjelaskan informasi dari satu fungsi entri (misalnya, fungsi tingkat atas dengan penelepon dan biasanya berfungsi sebagai antarmuka eksternal) dalam modul program, berisi hingga 3 token yang dipisahkan ruang:
entry_x MY_IOCTL 0_2 .Jadi seperti yang ditunjukkan di atas, conf_motivating_example menentukan bahwa ada tiga fungsi entri dalam motivasi_example.c : entri0 (parameter 1 dikendalikan pengguna), entri1 dan entry2 (tidak ada parameter yang dikontrol pengguna). Ini cocok dengan kode contoh yang memotivasi.
Setelah bitcode program dan file konfigurasi entri siap, kami dapat menjalankan Suture untuk menemukan kerentanan yang ternoda:
~/suture$ ./run_nohup.sh benchmark/motivating_example.bc benchmark/conf_motivating_example
Penjelasan : run_nohup.sh adalah skrip sederhana yang memohon tiket analisis LLVM yang dikompilasi dari jahitan:
~/suture$ ./run_nohup.sh [path/to/program.bc] [path/to/entry_func_config]
Setelah dimulai, tergantung pada perangkat keras yang sebenarnya dan kompleksitas program target, waktu yang diperlukan untuk Jahitan untuk menyelesaikan analisis dan penemuan kerentanan sangat bervariasi. Program sederhana seperti contoh memotivasi kami biasanya selesai secara instan.
Putuskan apakah analisis selesai : Selama eksekusi, Jahitan terus masuk ke file di bawah direktori yang sama dari file konfigurasi entri , misalkan jalur file konfigurasi adalah /path/to/conf_program , file log akan /path/to/conf_program.log . Kita dapat memutuskan apakah analisis selesai dengan memantau log:
~/suture$ grep "Bug Detection Phase finished" benchmark/conf_motivating_example.log
File log yang disebutkan di atas juga merupakan output jahitan, Jahitan akan menanamkan potensi kerentanan potensial dalam file log, yang dapat diekstraksi dan diatur ke dalam laporan peringatan akhir setelah analisis selesai:
~/suture$ ./ext_warns.sh benchmark/conf_motivating_example.log
Penjelasan : ext_warns.sh akan mengekstrak semua peringatan (dalam JSON) yang tertanam dalam file log yang diberikan, mengatur kembali dan mencetak cukup mereka ke dalam laporan peringatan akhir. Laporan peringatan akan dimasukkan ke dalam folder di bawah jalur file log yang sama, misalkan file log adalah /path/to/conf_program.log , folder laporan peringatan akan /path/to/warns-conf_program-hyyy-mm-dd .
~/suture$ ls benchmark/warns-conf_motivating_example-2021-11-10/
all int_overflow taint_data_use taint_loopbound taint_ptr_def
Di folder ada 5 laporan peringatan, semua berisi semua jenis peringatan yang dikelompokkan bersama sesuai dengan hubungan aliran data mereka, sementara laporan lain hanya berisi jenis peringatan tertentu (misalnya, integer overflow, dereferensi penunjuk yang tercemar, dll.), Rincian lebih lanjut tentang bagaimana kami mengelompokkan peringatan dapat ditemukan dalam makalah kami (Bagian 4). Kami biasanya hanya menggunakan laporan terpadu semua .
~/suture$ cat -n benchmark/warns-conf_motivating_example-2021-11-10/all
1 =========================GROUP 0 (2 - 2)=========================
2 #####Warned Insts#####
3 (u'motivating_example.c', 30, [u'IntegerOverflowDetector'])
4 ######################
5
6 ++++++++++++++++WARN 0 (2 - 2)++++++++++++++++
7 IntegerOverflowDetector says: motivating_example.c@30 (bar : %add = add i8 %0, -16, !dbg !31)
8 ********Trace 0(2)********
9 #####CTX##### entry0
10 entry0 (motivating_example.c@18)
11 #####INSTS#####
12 >>>>>>>>>>>>>>>>>>tag: 0x55b206570420 tf: 0x55b20695b1b0 (2)>>>>>>>>>>>>>>>>>>
13 motivating_example.c@18 ( %cond = icmp eq i32 %cmd, 0, !dbg !31)
14 motivating_example.c@21 ( store i8 %user_input, i8* getelementptr inbounds (%struct.data, %struct.data* @d, i64 0, i32 1, i64 0), align 4, !dbg !32, !tbaa !34)
15 #####CTX##### entry1 -> bar
16 entry1 (motivating_example.c@35)
17 ----> (motivating_example.c@35 : %call = tail call i32 @bar(i8* bitcast (%struct.data* @d to i8*)), !dbg !27)
18 bar (motivating_example.c@30)
19 #####INSTS#####
20 >>>>>>>>>>>>>>>>>>tag: 0x55b2065e7050 tf: 0x55b2068174f0 (1)>>>>>>>>>>>>>>>>>>
21 motivating_example.c@30 ( %0 = load i8, i8* %add.ptr, align 1, !dbg !31, !tbaa !32)
22 motivating_example.c@30 ( %add = add i8 %0, -16, !dbg !31)
23
Penjelasan : Pada tingkat tinggi, laporan peringatan berisi beberapa kelompok peringatan, masing -masing kelompok berisi beberapa peringatan , dan setiap peringatan berisi beberapa jejak nakal yang berasal dari input pengguna dan tenggelam ke pernyataan program sensitif yang sama. Dengan kata lain, satu peringatan diangkat untuk pernyataan program tertentu dan jenis tertentu (misalnya, integer overflow), sementara suatu kelompok berisi beberapa peringatan yang terkait erat dari perspektif aliran data (lihat bagian 4 dalam makalah kami), sehingga suatu kelompok mungkin memiliki banyak pernyataan program yang diperingatkan dan termasuk jenis peringatan yang berbeda.
Ambil laporan peringatan di atas sebagai contoh:
===GROUP No. (min_order - max_order)=== , di mana min_order adalah urutan minimal (misalnya, sederhananya, pesanan adalah waktu dari fungsi masuk yang diperlukan dalam propagasi noda, lihat bagian 3.2 dalam makalah kami untuk definisi yang lebih formal.) Dari traint di dalam kelompok ini, dan max_order max.WARN No. adalah lokal untuk grupnya.***Trace No. (order)*** , jejak noda selalu memiliki urutan unik yang dapat dihitung (misalnya, bukan rentang).Laporan peringatan menunjukkan kerentanan integer overflow yang valid dalam contoh yang memotivasi, sambil menghindari alarm palsu potensial yang dapat dihasilkan oleh alat analisis statis yang kurang tepat, rincian dapat ditemukan di bagian 2.1 dari makalah kami.
Repo ini juga berisi beberapa alat/skrip lain yang mungkin Anda temukan berguna.
~/suture$ python llvm_analysis/AnalysisHelpers/EntryPointIdentifier/entry_point_identifier.py /path/to/prog_module.bc
~/suture$ cat /path/to/prog_module.bc.all_entries
Penjelasan : Skrip ini dapat mengidentifikasi beberapa fungsi entri umum dalam modul driver perangkat Linux (misalnya, ioctl () , baca () , tulis () , dll.), Yang membantu konstruksi file konfigurasi entri sebagai input ke jahitan. Utilitas ini sebagian besar diimplementasikan oleh Dr. Checker asli berdasarkan pada beberapa pengetahuan domain kernel (misalnya, struktur data spesifik seperti file_operations yang digunakan untuk mendefinisikan titik masuk driver), kami kemudian membuat beberapa perbaikan (misalnya, membuat heuristik lebih kuat).
~/suture$ python flt_warns.py /path/to/warn_report [Regex] > /path/to/filtered_warn_report
Penjelasan : Dari pengalaman kami, banyak alarm palsu dalam laporan peringatan sering kali berbagi jejak sub-mencela bermasalah yang sama (lihat Bagian 6.3 dalam makalah kami). Selama pengulas peringatan memeriksa satu alarm palsu dan mengenali sub-trace yang menginduksi FP, secara alami, ia dapat mencoba secara otomatis mengecualikan semua alarm palsu serupa lainnya yang berisi sub-trace yang sama, mengurangi tingkat alarm palsu yang dipikirkan oleh pengulas. Untuk tujuan ini, kami memberikan flt_warns.py sederhana ini yang mengambil laporan peringatan asli dan ekspresi reguler Python sebagai input, kemudian akan cocok dengan RE dengan setiap jejak noda dalam laporan, setelah dicocokkan, jejak noda akan diperlakukan sebagai alarm palsu. Script akan menghasilkan laporan peringatan baru yang disaring tidak termasuk semua jejak noda yang cocok.
Anda mungkin tertarik untuk menggunakan Jahitan sebagai analisis statis tujuan umum (misalnya, dapatkan poin-ke/noda set variabel di lokasi program tertentu), ini pasti bisa dilakukan, tetapi tidak seperti penemuan kerentanan, Anda perlu membuat tangan kotor dan menyelami kode jahitan untuk dibiasakan dengan struktur data utama yang digunakannya dan beberapa fungsi penting. Saya berharap tips berikut dapat membantu:
LLVM berkembang sangat cepat, tanpa jaminan kompatibelinya ke belakang. Jadi sangat mungkin Anda akan mengalami beberapa kesalahan kompilasi saat mencoba membangun jahitan dengan versi LLVM yang lebih baru (misalnya,> 9.0). Tapi untungnya, kesalahan kompilasi seperti itu biasanya mudah diselesaikan (misalnya, sering kali kita hanya perlu mengganti API LLVM yang sudah ketinggalan zaman dengan yang lebih baru). Jadi pada dasarnya, untuk mengadaptasi jahitan dengan versi LLVM yang lebih baru, pertama -tama kita perlu mengatur LLVM yang lebih baru di 0x0 (misalnya, perlu memodifikasi setup_suture.py untuk mengkloning LLVM repo dari sumber aktif dan menentukan nama cabang yang lebih baru), dan kemudian mencoba untuk membangun jahitan terhadapnya, menyelesaikan komponen yang ditemui.