EVM mendalam - risiko di balik masalah sepele klasifikasi kontrak

Di bidang kontrak pintar, "EVM Mesin Virtual Ethereum" dan algoritme serta struktur datanya adalah prinsip pertama.

Artikel ini dimulai dari mengapa kontrak harus diklasifikasikan, dan menggabungkan jenis serangan jahat yang mungkin dihadapi setiap skenario, dan akhirnya memberikan sekumpulan algoritme analisis klasifikasi kontrak yang relatif aman.

**Meskipun konten teknisnya tinggi, ini juga dapat digunakan sebagai bahan bacaan untuk pembicaraan lain-lain. **Sekilas ke dalam hutan gelap permainan antara sistem yang terdesentralisasi.

1. Mengapa kontrak harus diklasifikasikan?

Karena sangat penting, dapat dikatakan sebagai landasan Dapps seperti bursa, dompet, browser blockchain, platform analisis data, dll.!

Alasan mengapa suatu transaksi adalah transfer ERC20 adalah karena perilakunya sesuai dengan standar ERC20, setidaknya:

  1. Status transaksi sukses
  2. To address adalah kontrak yang sesuai dengan standar ERC20
  3. Fungsi Transfer dipanggil, dan cirinya adalah 4 digit pertama CallData transaksi adalah 0xa9059cbb
  4. Setelah eksekusi, event transfer dikirim ke alamat Ke

Jika klasifikasi salah, perilaku transaksi akan salah menilai

Dengan perilaku transaksi sebagai landasan, apakah alamat Ke dapat diklasifikasikan secara akurat akan menghasilkan kesimpulan yang sama sekali berbeda dalam penilaian CallData-nya. Untuk Dapp, komunikasi informasi di dalam dan di luar rantai sangat bergantung pada pemantauan kejadian transaksi, dan kode kejadian yang sama hanya dapat dipercaya jika dikirimkan dalam kontrak yang memenuhi standar.

Jika klasifikasi salah, transaksi akan masuk ke lubang hitam secara tidak sengaja

Jika pengguna mentransfer Token ke dalam kontrak tertentu, jika kontrak tersebut tidak memiliki metode fungsi preset untuk transfer Token, dana akan dikunci dengan cara yang sama seperti Pembakaran dan tidak dapat dikendalikan

Dan sekarang sejumlah besar proyek telah mulai menambahkan dukungan dompet bawaan, tidak dapat dihindari untuk mengelola dompet untuk pengguna.Kontrak terbaru yang digunakan dari rantai perlu diklasifikasi secara real time setiap saat, apakah mereka dapat bertemu standar aset.

Mendalami risiko di balik masalah sepele klasifikasi kontrak EVM

2. Apa risiko klasifikasi?

**Rantai adalah tempat di mana tidak ada identitas dan tidak ada aturan hukum. Anda tidak dapat menghentikan transaksi normal, meskipun itu berbahaya. **

Dia bisa menjadi serigala yang berpura-pura menjadi nenek, melakukan sebagian besar perilaku yang Anda harapkan dari seorang nenek, tetapi dengan tujuan membobol rumah dan merampok.

Standar klaim, tetapi mungkin tidak benar-benar memenuhi

Metode klasifikasi yang umum adalah dengan langsung mengadopsi standar EIP-165 untuk membaca apakah alamat tersebut mendukung ERC20, dll. Tentu saja, ini adalah metode yang efisien, tetapi bagaimanapun juga, kontrak dikendalikan oleh pihak lain, sehingga pernyataan dapat dibuat dipalsukan setelah semua.

Permintaan standar 165 hanyalah metode untuk mencegah dana ditransfer ke lubang hitam dengan biaya terendah di antara kode operasi terbatas pada rantai.

Inilah sebabnya ketika kami menganalisis NFT sebelumnya, kami secara khusus menyebutkan bahwa akan ada metode SafeTransferFrom dalam standar, di mana Safe mengacu pada penggunaan standar 165 untuk menentukan bahwa pihak lain memiliki kemampuan untuk mentransfer NFT.

Hanya dengan memulai dari kode byte kontrak, melakukan analisis statis pada tingkat kode sumber, dan mulai dari perilaku kontrak yang diharapkan, dapatkah lebih akurat.

3. Rancangan skema klasifikasi kontrak

Selanjutnya, kami akan menganalisis keseluruhan rencana secara sistematis, dan perhatikan bahwa tujuan akhir kami adalah dua indikator utama "presisi" dan "efisiensi". **

Anda harus tahu bahwa meskipun arahnya benar, cara untuk mencapai sisi lain lautan tidak jelas. Pemberhentian pertama untuk melakukan analisis bytecode adalah mendapatkan kodenya

3.1. Bagaimana cara mendapatkan kodenya?

Dari sudut pandang pergi ke rantai, ada getCode, metode RPC, yang bisa mendapatkan bytecode dari alamat yang ditentukan pada rantai, sangat cepat dalam hal membaca, karena codeHash ditempatkan di struktur akun dari EVM. di bagian paling atas.

Mendalami risiko di balik masalah sepele klasifikasi kontrak EVM

Namun cara ini sama saja dengan mendapatkan alamat tertentu saja Ingin lebih meningkatkan akurasi dan efisiensinya?

Jika ini adalah transaksi penerapan kontrak, bagaimana cara mendapatkan kode yang diterapkan tepat setelah dieksekusi atau bahkan saat masih berada di kumpulan memori?

Jika transaksi dalam mode pabrik kontrak, apakah ada kode sumber di Calldata transaksi?

Pada akhirnya, cara saya adalah mengklasifikasikan dalam mode seperti saringan

  1. Untuk transaksi non-contract-deployed, langsung gunakan getCode untuk mendapatkan alamat yang terlibat untuk klasifikasi.
  2. Untuk transaksi kumpulan memori terbaru, saring transaksi yang alamatnya kosong, dan yang CallData-nya adalah kode sumber dengan konstruktor
  3. Untuk transaksi mode pabrik kontrak, karena kontrak yang digunakan oleh kontrak dapat didaur ulang untuk memanggil kontrak lain untuk mengeksekusi penerapan, maka secara rekursif akan menganalisis sub-transaksi dari transaksi tersebut, dan mencatat setiap panggilan yang jenisnya CREATE atau CREATE2 .

Ketika saya membuat implementasi demo, saya menemukan bahwa versi rpc relatif tinggi sekarang, karena bagian tersulit dari keseluruhan proses adalah bagaimana menemukan panggilan jenis yang ditentukan secara rekursif saat mengeksekusi 3. Metode level bawah adalah mengembalikan konteks melalui opcode. Saya terkejut!

Untungnya, ada metode debug_traceTransaction dalam versi geth saat ini, yang dapat membantu memilah informasi konteks setiap panggilan melalui kode operasi opcode, dan memilah bidang inti.

Pada akhirnya, bytecode asli dari berbagai mode penerapan (penyebaran langsung, penerapan tunggal dalam mode pabrik, penerapan batch dalam mode pabrik) dapat diperoleh.

3.2 Bagaimana mengklasifikasikan dari kode?

Cara paling sederhana namun tidak aman adalah dengan langsung melakukan pencocokan string dengan kode. Mengambil ERC20 sebagai contoh, fungsi yang memenuhi standar memiliki

Mendalami risiko di balik masalah sepele klasifikasi kontrak EVM

Setelah nama fungsi adalah fungsi tanda tangan Seperti yang disebutkan dalam analisis sebelumnya, transaksi tergantung pada pencocokan 4 digit pertama callData untuk menemukan fungsi target Bacaan lebih lanjut:

Oleh karena itu, tanda tangan dari 6 fungsi ini harus disimpan dalam kode byte kontrak.

Tentu saja, metode ini sangat cepat dan Anda dapat menemukan semua 6, tetapi faktor yang tidak aman adalah jika saya menggunakan kontrak soliditas dan mendesain variabel dengan nilai penyimpanan 0x18160ddd, dia akan berpikir bahwa saya memiliki fungsi ini.

3.3 Peningkatan tingkat akurasi 1- dekompilasi

Metode akurat lebih lanjut adalah mendekompilasi Opcode! Dekompilasi adalah proses mengubah bytecode yang diperoleh menjadi opcode, dan dekompilasi yang lebih maju adalah mengubahnya menjadi pseudocode, yang lebih kondusif untuk dibaca manusia. Kami tidak membutuhkannya saat ini. Metode dekompilasi tercantum dalam lampiran di akhir artikel.

soliditas (bahasa tingkat tinggi) -> bytecode (bytecode) -> opcode (kode operasi)

Kami dapat dengan jelas menemukan fitur, tanda tangan fungsi akan dieksekusi oleh opcode PUSH4, jadi metode selanjutnya adalah mengekstrak konten setelah PUSH4 dari teks lengkap dan mencocokkannya dengan standar fungsi.

Mendalami risiko di balik masalah sepele klasifikasi kontrak EVM

Saya juga melakukan eksperimen kinerja sederhana, dan saya harus mengatakan bahwa bahasa Go sangat efisien, dan hanya membutuhkan 220ms untuk 10.000 kali dekompilasi.

Berikut ini akan sulit

3.4 Peningkatan tingkat akurasi 2-temukan blok kode

Tingkat akurasi di atas telah ditingkatkan tetapi tidak cukup, karena ini adalah pencarian teks lengkap PUSH4, karena kita masih dapat membuat variabel, yang bertipe byte4, yang juga akan memicu perintah PUSH4.

Ketika saya tertekan, saya memikirkan implementasi beberapa proyek open source. ETL adalah alat untuk membaca data pada rantai untuk dianalisis. Ini akan menganalisis transfer ERC20 dan 721 ke dalam tabel terpisah, sehingga harus memiliki kemampuan untuk mengklasifikasikan kontrak.

Mendalami risiko di balik masalah sepele klasifikasi kontrak EVM

Setelah analisis, dapat ditemukan bahwa ia didasarkan pada klasifikasi blok kode dan hanya memproses blok_dasar pertama [0] Instruksi push4 di

Pertanyaannya muncul, bagaimana menilai blok kode secara akurat

Konsep blok kode berasal dari dua opcode berturut-turut REVERT + JUMPDEST Harus ada dua opcode berurutan di sini, karena dalam interval opcode seluruh pemilih fungsi, jika terlalu banyak fungsi, logika pembalikan halaman akan muncul .Kemudian akan muncul juga perintah JUMPDEST.

Mendalami risiko di balik masalah sepele klasifikasi kontrak EVM

3.5.Peningkatan tingkat akurasi 3-Temukan pemilih fungsi

Fungsi pemilih fungsi adalah untuk membaca 4 byte pertama dari Calldata transaksi, dan mencocokkannya dengan tanda tangan fungsi kontrak yang telah ditetapkan dalam kode, dan membantu instruksi untuk melompat ke lokasi memori yang ditentukan oleh metode fungsi

Mari kita coba eksekusi tiruan minimal

Bagian ini adalah toko pemilih (uint 256) dan mengambil () dari dua fungsi, dan tanda tangan dapat dihitung sebagai 2e64cec1, 6057361d

Mendalami risiko di balik masalah sepele klasifikasi kontrak EVM

Setelah dekompilasi, Anda akan mendapatkan string opcode berikut, yang bisa dikatakan terbagi menjadi dua bagian

bagian pertama:

Di dalam compiler, hanya bagian pemilih fungsi dari contract yang akan mendapatkan isi callData, yang artinya mendapatkan fungsi call signature dari CallData-nya, seperti terlihat pada gambar di bawah ini.

Mendalami risiko di balik masalah sepele klasifikasi kontrak EVM

Kita dapat melihat efeknya dengan mensimulasikan perubahan kumpulan memori EVM

Mendalami risiko di balik masalah sepele klasifikasi kontrak EVM

bagian kedua:

Proses penjurian apakah cocok dengan nilai pemilih

  1. Berikan tanda tangan fungsi 4-byte (0x2e64cec1) dari retrieve() ke stack,

  2. Opcode EQ mengeluarkan 2 variabel dari area stack, yaitu 0x2e64cec1 dan 0x6057361d, dan memeriksa apakah keduanya sama

  3. PUSH2 mentransfer 2 byte data (0x003b di sini, 59 dalam desimal) ke stack Ada penghitung program di area stack, yang menentukan posisi perintah eksekusi berikutnya dalam bytecode. Di sini kita menetapkan 59 karena disitulah bytecode retrieve() dimulai

  4. JUMPI adalah singkatan dari "Jump to if...", itu muncul 2 nilai dari tumpukan sebagai input, dan jika kondisinya benar, penghitung program akan diperbarui ke 59.

Beginilah cara EVM menentukan lokasi bytecode fungsi yang perlu dijalankan berdasarkan pemanggilan fungsi dalam kontrak.

Pada kenyataannya, ini hanyalah sekumpulan "pernyataan if" sederhana untuk setiap fungsi dalam kontrak dan ke mana mereka melompat.

Mendalami risiko di balik masalah sepele klasifikasi kontrak EVM

4. Ringkasan Skema

Ringkasan keseluruhan adalah sebagai berikut

  1. Setiap alamat kontrak dapat memperoleh bytecode setelah penyebaran melalui rpcgetcode atau debug_traceTransaction, menggunakan perpustakaan VM dan ASM di GO, dan mendapatkan opcode setelah dekompilasi
  2. Pada prinsip pengoperasian EVM, kontrak akan memiliki karakteristik sebagai berikut
  • Gunakan REVERT+JUMPDEST sebagai perbedaan blok kode
  • Kontrak harus memiliki fungsi pemilih fungsi, dan fungsi ini juga harus ada di blok kode pertama
  • Di pemilih fungsi, semua metode fungsinya menggunakan PUSH4 sebagai opcode,
  • Dalam opcode yang terdapat dalam pemilih ini, akan ada PUSH1 00; CALLDATALOAD; PUSH1 e0; SHR; DUP1 berturut-turut. Fungsi intinya adalah memuat data callDate dan melakukan operasi perpindahan. Dari fungsi kontrak, sintaks lain tidak akan dihasilkan
  1. Tanda tangan fungsi yang sesuai didefinisikan dalam eip, dan ada instruksi wajib dan opsional yang jelas

4.1 Bukti Keunikan

Pada titik ini, kita dapat mengatakan bahwa metode analisis kontrak dengan efisiensi tinggi dan akurasi tinggi pada dasarnya telah direalisasikan.Tentu saja, karena sudah lama ketat, kita mungkin juga lebih ketat.Dalam skema di atas, kita gunakan REVER+JUMPDEST untuk membuat blok kode Bedakan, dan gabungkan pemuatan dan perpindahan CallDate yang tak terelakkan untuk membuat penilaian yang unik.Apakah ada yang bisa saya gunakan kontrak soliditas untuk mengimplementasikan urutan opcode serupa?

Saya melakukan eksperimen kontrol.Meskipun ada metode untuk mendapatkan CallData seperti msg.sig dari tingkat tata bahasa soliditas, metode implementasi opcode setelah kompilasi berbeda.

Mendalami risiko di balik masalah sepele klasifikasi kontrak EVM

Lihat Asli
Konten ini hanya untuk referensi, bukan ajakan atau tawaran. Tidak ada nasihat investasi, pajak, atau hukum yang diberikan. Lihat Penafian untuk pengungkapan risiko lebih lanjut.
  • Hadiah
  • Komentar
  • Bagikan
Komentar
0/400
Tidak ada komentar
  • Sematkan
Perdagangkan Kripto Di Mana Saja Kapan Saja
qrCode
Pindai untuk mengunduh aplikasi Gate.io
Komunitas
Indonesia
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)