Dapatkah Anda memikirkan penggunaan yang sah (cerdas) untuk modifikasi kode runtime (program yang memodifikasi kode itu sendiri saat runtime)?
Sistem operasi modern tampaknya tidak menyukai program yang melakukan ini karena teknik ini telah digunakan oleh virus untuk menghindari deteksi.
Yang dapat saya pikirkan adalah beberapa jenis pengoptimalan runtime yang akan menghapus atau menambahkan beberapa kode dengan mengetahui sesuatu pada saat runtime yang tidak dapat diketahui pada waktu kompilasi.
Jawaban:
Ada banyak kasus yang valid untuk modifikasi kode. Menghasilkan kode pada waktu proses dapat berguna untuk:
Terkadang kode diterjemahkan ke dalam kode saat runtime (ini disebut terjemahan biner dinamis ):
Modifikasi kode dapat digunakan untuk mengatasi keterbatasan set instruksi:
Lebih banyak kasus modifikasi kode:
sumber
Ini telah dilakukan dalam grafik komputer, khususnya perender perangkat lunak untuk tujuan pengoptimalan. Pada waktu proses, status banyak parameter diperiksa dan versi kode rasterizer yang dioptimalkan dihasilkan (berpotensi menghilangkan banyak persyaratan) yang memungkinkan seseorang untuk membuat grafik primitif misalnya segitiga jauh lebih cepat.
sumber
Salah satu alasan yang valid adalah karena set instruksi asm kekurangan beberapa instruksi yang diperlukan, yang dapat Anda buat sendiri. Contoh: Pada x86 tidak ada cara untuk membuat interupsi ke variabel dalam register (misalnya membuat interupsi dengan nomor interupsi di ax). Hanya nomor const yang dikodekan ke dalam opcode yang diizinkan. Dengan kode selfmodifying seseorang dapat meniru perilaku ini.
sumber
Beberapa kompiler menggunakannya untuk inisialisasi variabel statis, menghindari biaya bersyarat untuk akses selanjutnya. Dengan kata lain, mereka menerapkan "jalankan kode ini hanya sekali" dengan menimpa kode tersebut tanpa operasi saat pertama kali dijalankan.
sumber
Ada banyak kasus:
Beberapa model keamanan OS berarti kode modifikasi sendiri tidak dapat berjalan tanpa hak akses root / admin, sehingga tidak praktis untuk penggunaan tujuan umum.
Dari Wikipedia:
Pada OS tersebut, bahkan program seperti Java VM memerlukan hak akses root / admin untuk menjalankan kode JIT mereka. (Lihat http://en.wikipedia.org/wiki/W%5EX untuk lebih jelasnya)
sumber
The Sintesis OS pada dasarnya dievaluasi sebagian program anda sehubungan dengan panggilan API, dan diganti kode OS dengan hasilnya. Manfaat utamanya adalah banyak pengecekan kesalahan hilang (karena jika program Anda tidak akan meminta OS untuk melakukan sesuatu yang bodoh, itu tidak perlu diperiksa).
Ya, itu adalah contoh pengoptimalan waktu proses.
sumber
Bertahun-tahun yang lalu saya menghabiskan pagi mencoba untuk men-debug beberapa kode modifikasi diri, satu instruksi mengubah alamat target dari instruksi berikut, yaitu, saya sedang menghitung alamat cabang. Itu ditulis dalam bahasa assembly dan bekerja dengan sempurna ketika saya mengikuti instruksi program satu per satu. Tetapi ketika saya menjalankan program itu gagal. Akhirnya, saya menyadari bahwa mesin sedang mengambil 2 instruksi dari memori dan (seperti instruksi yang diletakkan dalam memori) instruksi yang saya modifikasi telah diambil dan dengan demikian mesin sedang menjalankan versi instruksi yang tidak dimodifikasi (salah). Tentu saja, ketika saya men-debug, itu hanya melakukan satu instruksi dalam satu waktu.
Maksud saya, kode yang mengubah diri sendiri bisa sangat buruk untuk diuji / debug dan sering kali memiliki asumsi tersembunyi mengenai perilaku mesin (baik itu perangkat keras atau virtual). Selain itu, sistem tidak pernah dapat membagikan halaman kode di antara berbagai thread / proses yang dijalankan pada mesin multi-core (sekarang). Ini mengalahkan banyak manfaat untuk memori virtual, dll. Ini juga akan membatalkan pengoptimalan cabang yang dilakukan di tingkat perangkat keras.
(Catatan - saya tidak memasukkan JIT dalam kategori kode modifikasi diri. JIT menerjemahkan dari satu representasi kode ke representasi alternatif, itu tidak mengubah kode)
Secara keseluruhan, itu hanya ide yang buruk - sangat rapi, sangat tidak jelas, tetapi sangat buruk.
tentu saja - jika yang Anda miliki hanyalah memori 8080 dan ~ 512 byte, Anda mungkin harus menggunakan praktik semacam itu.
sumber
Dari tampilan kernel sistem operasi, setiap Just In Time Compiler dan Linker Runtime melakukan modifikasi diri teks program. Contoh yang menonjol adalah Penerjemah Skrip ECMA V8 Google.
sumber
Alasan lain untuk mengubah kode sendiri (sebenarnya kode "yang dihasilkan sendiri") adalah untuk menerapkan mekanisme kompilasi Just-In-time untuk kinerja. Misalnya, program yang membaca ekspresi algebric dan menghitungnya pada berbagai parameter input dapat mengubah ekspresi tersebut dalam kode mesin sebelum menyatakan kalkulasi.
sumber
Anda tahu kastanye lama bahwa tidak ada perbedaan logis antara perangkat keras dan perangkat lunak ... orang juga dapat mengatakan bahwa tidak ada perbedaan logis antara kode dan data.
Apa itu kode modifikasi sendiri? Kode yang menempatkan nilai-nilai dalam aliran eksekusi sehingga dapat ditafsirkan bukan sebagai data tetapi sebagai perintah. Tentu ada sudut pandang teoritis dalam bahasa fungsional bahwa sebenarnya tidak ada perbedaan. Saya mengatakan bahwa e dapat melakukan ini secara langsung dalam bahasa imperatif dan penyusun / penafsir tanpa asumsi status yang sama.
Apa yang saya maksud adalah dalam arti praktis bahwa data dapat mengubah jalur eksekusi program (dalam beberapa hal ini sangat jelas). Saya memikirkan sesuatu seperti compiler-compiler yang membuat tabel (array data) yang dilintasi seseorang dalam parsing, berpindah dari satu negara bagian ke negara bagian (dan juga memodifikasi variabel lain), seperti bagaimana sebuah program bergerak dari perintah ke perintah , memodifikasi variabel dalam prosesnya.
Jadi, bahkan dalam contoh biasa di mana kompilator membuat ruang kode dan merujuk ke ruang data yang sepenuhnya terpisah (heap), seseorang masih dapat memodifikasi data untuk mengubah jalur eksekusi secara eksplisit.
sumber
Saya telah menerapkan program menggunakan evolusi untuk membuat algoritme terbaik. Ini menggunakan kode modifikasi diri untuk memodifikasi cetak biru DNA.
sumber
Salah satu kasus penggunaan adalah file tes EICAR yang merupakan file COM executable DOS yang sah untuk menguji program antivirus.
Itu harus menggunakan modifikasi kode sendiri karena file yang dapat dieksekusi harus berisi hanya karakter ASCII yang dapat dicetak / dapat diketik dalam rentang [21h-60h, 7Bh-7Dh] yang membatasi jumlah instruksi yang dapat dienkode secara signifikan
Detailnya dijelaskan di sini
Ini juga digunakan untuk operasi floating-point di DOS
Beberapa kompiler akan memancarkan
CD xx
dengan xx mulai dari 0x34-0x3B di tempat instruksi floating-point x87. KarenaCD
adalah opcode untukint
instruksi, itu akan melompat ke interupsi 34h-3Bh dan meniru instruksi itu dalam perangkat lunak jika koprosesor x87 tidak tersedia. Jika tidak, penangan interupsi akan mengganti 2 byte tersebut dengan9B Dx
sehingga eksekusi selanjutnya akan ditangani secara langsung oleh x87 tanpa emulasi.Apa protokol untuk emulasi floating point x87 di MS-DOS?
sumber
The Linux Kernel memiliki loadable Kernel Modul yang melakukan hal itu.
Emacs juga memiliki kemampuan ini dan saya menggunakannya setiap saat.
Apa pun yang mendukung arsitektur plugin dinamis pada dasarnya memodifikasi kodenya saat runtime.
sumber
Saya menjalankan analisis statistik terhadap database yang terus diperbarui. Model statistik saya ditulis dan ditulis ulang setiap kali kode dijalankan untuk mengakomodasi data baru yang tersedia.
sumber
Skenario di mana ini dapat digunakan adalah program pembelajaran. Menanggapi masukan pengguna, program mempelajari algoritme baru:
Ada pertanyaan bagaimana melakukan itu di Java: Apa saja kemungkinan modifikasi diri kode Java?
sumber
Versi terbaik dari ini mungkin Lisp Macros. Tidak seperti makro C yang hanya sebuah preprocessor Lisp memungkinkan Anda memiliki akses ke seluruh bahasa pemrograman setiap saat. Ini tentang fitur paling kuat di cadel dan tidak ada dalam bahasa lain.
Saya sama sekali bukan seorang ahli tetapi salah satu dari orang-orang cadel membicarakannya! Ada alasan mengapa mereka mengatakan bahwa Lisp adalah bahasa yang paling kuat di sekitar dan orang pintar tidak karena mereka mungkin benar.
sumber