T : Mengapa diperlukan dekompiler lain, terutama yang sudah lumpuh?
J : Kenyataan yang menyedihkan adalah sebagian besar decompiler di luar sana lumpuh. Banyak yang tidak dapat mendekompilasi konstruksi sepele, yang lain tidak dapat mendekompilasi lebih lanjut, konstruksi yang tampaknya dapat menanganinya, menjadi lumpuh karena hanya mendukung arsitektur dan OS yang membosankan. Dan hampir semuanya ditulis sedemikian rupa sehingga mengubah atau menambahkan arsitektur baru menjadi rumit. Decompiler adalah alat untuk rekayasa balik, tetapi ironisnya, jika Anda ingin menggunakan decompiler biasa secara produktif atau membuatnya sesuai dengan kebutuhan Anda, pertama-tama Anda perlu merekayasa balik decompiler itu sendiri, dan itu bisa memakan waktu berbulan-bulan (atau bertahun-tahun) .
Bagian utama dari decompiler (dan kerangka transformasi program apa pun) adalah Intermediate Representation (IR). Dekompiler harus bekerja pada IR, dan harus menganggapnya sebagai masukan, dan konversi assembler arsitektur tertentu ke IR ini harus dipisahkan dengan baik dari dekompiler, atau jika tidak, diperlukan upaya luar biasa untuk menambahkan dukungan untuk arsitektur lain (yang pada gilirannya membatasi basis pengguna dekompiler).
Dekompilasi adalah tugas yang kompleks, jadi harus ada pemahaman yang mudah tentang proses dekompilasi. Ini berarti IR yang digunakan oleh dekompiler harus ramah manusia, misalnya menggunakan sintaksis yang familiar bagi pemrogram, memetakan secara langsung ke perakit mesin pada umumnya, dll.
Persyaratan di atas seharusnya sudah cukup jelas. Jika belum, dapat dipelajari dari buku-buku yang membahas hal tersebut, misalnya:
"Penulis kompiler juga memerlukan mekanisme yang memungkinkan manusia memeriksa program IR dengan mudah dan langsung. Kepentingan pribadi harus memastikan bahwa penulis kompiler memperhatikan poin terakhir ini."
(Keith Cooper, Linda Torczon, "Rekayasa Kompiler")
Namun, proyek dekompiler, termasuk proyek OpenSource, secara rutin melanggar persyaratan ini: proyek tersebut terkait erat dengan arsitektur mesin tertentu, tidak mengizinkan masukan IR, dan seringkali tidak mengekspos atau mendokumentasikannya sama sekali kepada pengguna.
ScratchABlock adalah upaya untuk mengatakan "tidak" terhadap praktik tersebut dan mengembangkan kerangka dekompilasi berdasarkan persyaratan di atas. Perhatikan bahwa ScratchABlock dapat dianggap sebagai proyek pembelajaran/penelitian, dan selain niat baik dan kritik terhadap proyek lain, ScratchABlock mungkin tidak menawarkan terlalu banyak kepada pengguna biasa - saat ini, atau mungkin sama sekali. Hal ini tentu dapat dikritik dalam banyak aspek juga.
ScratchABlock dirilis berdasarkan ketentuan GNU General Public License v3 (GPLv3).
ScratchABlock ditulis dalam bahasa Python3, dan diuji dengan versi 3.3 dan lebih tinggi, meskipun mungkin juga berfungsi dengan 3.2 atau lebih rendah (tidak akan berfungsi dengan versi Python2 lama). Ada beberapa ketergantungan:
Di Debian/Ubuntu Linux, ini dapat diinstal dengan sudo apt-get install python3-yaml python3-nose
. Alternatifnya, Anda dapat menginstalnya melalui manajer paket pip
milik Python (dapat digunakan untuk OS apa pun): pip3 install -r requirements.txt
.
ScratchABlock menggunakan assembler PseudoC sebagai IR-nya. Ini adalah bahasa assembler yang diekspresikan semaksimal mungkin menggunakan sintaks bahasa C yang familiar. Idenya adalah bahwa setiap programmer C akan memahaminya secara intuitif (contoh), namun ada upaya berkelanjutan untuk mendokumentasikan PseudoC secara lebih formal.
Perhatikan bahwa berdasarkan persyaratan yang dijelaskan di bagian dokumen sebelumnya, dan mengikuti "paradigma Unix" yang terkenal, ScratchABlock melakukan "satu hal" - analisis dan transformasi pada program PseudoC, dan secara eksplisit tidak berkaitan dengan konversi instruksi mesin dari arsitektur tertentu ke PseudoC (setidaknya, untuk saat ini). Itu berarti ScratchABlock tidak memaksa Anda untuk menggunakan konverter/pengangkat tertentu - Anda dapat menggunakan apa pun yang Anda suka. Peringatan: Anda harus memilikinya untuk menggunakannya. Lihat bagian akhir dokumen untuk mengetahui beberapa petunjuk terkait hal tersebut.
Kode sumber dan skrip antarmuka berada di root repositori. Skrip yang paling penting adalah:
apply_xform.py
- Driver pusat, memungkinkan penerapan serangkaian transformasi (atau secara umum, skrip analisis/transformasi tingkat tinggi) ke satu file atau direktori file ("direktori proyek").
inter_dataflow.py
- Driver analisis aliran data (WIP) antarprosedural (global).
script_*.py
- Skrip analisis/transformasi tingkat tinggi untuk apply_xform.py
( --script
switch).
script_i_*.py
- Skrip analisis untuk inter_dataflow.py
.
run_tests
- Pelari testsuite regresi. Mayoritas testsuite adalah tingkat tinggi, terdiri dari menjalankan apply_xform.py dengan lintasan berbeda pada file dan memeriksa hasil yang diharapkan.
Subdirektori lain dari repositori:
tests_unit
- Tes unit klasik untuk modul Python, ditulis dengan Python.
tests
- Tes utama. Meskipun bersifat integrasi, biasanya menguji satu pass pada satu file sederhana, sehingga mengikuti filosofi pengujian unit. Pengujian direpresentasikan sebagai file masukan PseudoC, sedangkan hasil yang diharapkan - sebagai PseudoC dengan anotasi blok dasar dan (jika berlaku) CFG dalam format .dot. Melihat kasus uji ini, mencoba memodifikasinya dan melihat hasilnya adalah cara terbaik untuk mempelajari cara kerja ScratchABlock.
docs
- Koleksi dokumentasi yang terus bertambah. Misalnya, terdapat spesifikasi bahasa rakitan PseudoC yang berfungsi sebagai representasi perantara (IR) untuk ScratchABlock dan survei mengapa IR lain yang sudah ada tidak dipilih.
Pendekatan ScratchABlock saat ini adalah mengembangkan kumpulan algoritma yang relatif longgar digabungkan ("passes") untuk analisis dan transformasi program, menyertakannya dalam pengujian, dan memungkinkan akses pengguna yang mudah ke algoritma tersebut. Keajaiban dekompilasi terdiri dari penerapan algoritma ini dalam urutan yang benar dan jumlah yang tepat. Kemudian, untuk meningkatkan kinerja dekompilasi, lintasan ini biasanya memerlukan penggabungan yang lebih erat. Menjelajahi arah tersebut menjadi prioritas berikutnya setelah melaksanakan inventarisasi pass seperti yang dijelaskan di atas.
Algoritma dan transformasi yang diterapkan oleh ScratchABlock:
Algoritma grafik:
Formulir Tugas Tunggal Statis (SSA):
Analisis aliran data:
Perambatan:
Penghapusan kode mati (DCE)
Menulis ulang:
Penataan aliran kontrol:
Format keluaran:
Alat mitra ScratchABlock adalah ScratchABit, yang merupakan pembongkaran interaktif yang dimaksudkan untuk melakukan tugas proses dekompilasi tingkat terendah, seperti pemisahan kode dari data, dan mengidentifikasi batas fungsi. ScratchABit biasanya bekerja dengan sintaks assembler arsitektur asli, tetapi untuk beberapa arsitektur (biasanya, RISC yang setia), jika tersedia plugin yang sesuai, ia dapat mengeluarkan sintaks PseudoC, yang dapat berfungsi sebagai masukan ke ScratchABlock.