Поглиблений EVM – ризики, що лежать в основі незначного питання класифікації контракту

У сфері смарт-контрактів «Віртуальна машина Ethereum EVM» та її алгоритми та структури даних є першоосновою.

Ця стаття починається з того, чому слід класифікувати контракти, об’єднує типи зловмисних атак, з якими може зіткнутися кожен сценарій, і, нарешті, надає набір відносно безпечних алгоритмів аналізу класифікації контрактів.

**Хоча технічний вміст високий, його також можна використовувати як матеріал для читання для різноманітних розмов **Погляньте на темний ліс ігор між децентралізованими системами.

1. Чому контракти повинні бути секретними?

Оскільки це дуже важливо, можна сказати, що це наріжний камінь Dapps, таких як біржі, гаманці, блокчейн-браузери, платформи аналізу даних тощо!

Причина, чому транзакція є переказом ERC20, полягає в тому, що його поведінка відповідає стандарту ERC20, принаймні:

  1. Статус транзакції – успіх
  2. Адреса Кому – це контракт, який відповідає стандарту ERC20
  3. Викликається функція передачі, і характерно те, що перші 4 цифри CallData транзакції є 0xa9059cbb
  4. Після виконання подія передачі надсилається на адресу Кому

Якщо класифікація неправильна, поведінку транзакції буде неправильно оцінено

Зважаючи на поведінку транзакцій як наріжний камінь, питання про те, чи можна точно класифікувати адресу «Кому», призведе до зовсім іншого висновку щодо її CallData. Для Dapp передача інформації в ланцюжку та поза ним сильно залежить від моніторингу подій транзакцій, і тому самому коду події можна довіряти, лише якщо він надісланий у контракті, який відповідає стандартам.

Якщо класифікація неправильна, транзакція помилково потрапляє в чорну діру

Якщо користувач передає токен у певний контракт, якщо в контракті немає попередньо встановленого функціонального методу для передачі токена, кошти будуть заблоковані так само, як і Burn, і ними неможливо буде керувати.

І тепер, коли велика кількість проектів почала додавати вбудовану підтримку гаманців, це неминуче керувати гаманцями для користувачів. Необхідно класифікувати останні розгорнуті контракти з ланцюжка в режимі реального часу в будь-який час, чи можуть вони відповідати стандарти активів.

Глибоко в ризик, що стоїть за тривіальним питанням класифікації контракту EVM

2. Які ризики класифікації?

**Ланцюжок — це місце, де немає ідентичності та верховенства права. Ви не можете зупинити звичайну транзакцію, навіть якщо вона шкідлива. **

Він може бути вовком, який прикидається бабусею, виконуючи більшість дій, які ви очікуєте від бабусі, але з метою увірватися в будинок і пограбувати.

Стверджує стандарт, але насправді може не відповідати

Загальним методом класифікації є пряме прийняття стандарту EIP-165 для визначення того, чи підтримує адреса ERC20 тощо. Звичайно, це ефективний метод, але врешті-решт контракт контролюється іншою стороною, тому заяву можна підроблені все-таки.

Стандартний запит 165 — це лише метод запобігання переміщенню коштів у чорні діри з найнижчою вартістю серед обмежених операційних кодів у ланцюжку.

Ось чому, коли ми раніше аналізували NFT, ми спеціально згадували, що в стандарті буде метод SafeTransferFrom, де Safe посилається на використання стандарту 165 для визначення того, що інша сторона має можливість передавати NFT.

Тільки починаючи з байт-коду контракту, виконуючи статичний аналіз на рівні вихідного коду та починаючи з очікуваної поведінки контракту, він може бути більш точним.

3. Дизайн схеми класифікації контракту

Далі ми систематично проаналізуємо загальний план і зауважимо, що нашою кінцевою метою є два основні показники «точність» і «ефективність». **

Ви повинні знати, що навіть якщо напрямок правильний, шлях до іншого берега океану незрозумілий.Перша зупинка для аналізу байт-коду - отримати код

3.1 Як отримати код?

З точки зору переходу в ланцюжок, є getCode, метод RPC, який може отримати байт-код з адреси, зазначеної в ланцюжку. Це дуже швидко з точки зору читання, оскільки codeHash розміщується в структурі облікового запису EVM на самому верху.

Глибоко в ризик, що стоїть за тривіальним питанням класифікації контракту EVM

Але цей спосіб рівнозначний отриманню лише певної адреси.Бажаєте ще більше підвищити точність та ефективність?

Якщо це транзакція розгортання контракту, як отримати розгорнутий код відразу після його виконання або навіть коли він все ще знаходиться в пулі пам’яті?

Якщо транзакція виконується в заводському режимі контракту, чи є вихідний код у Calldata транзакції?

Зрештою, мій спосіб полягає в тому, щоб класифікувати в ситоподібному режимі

  1. Для транзакцій, розгорнутих без контракту, безпосередньо використовуйте getCode, щоб отримати залучені адреси для класифікації.
  2. Для останніх транзакцій пулу пам’яті відфільтруйте транзакції, адреса яких порожня, а CallData — вихідний код із конструктором
  3. Для транзакції режиму фабрики контрактів, оскільки контракт, розгорнутий контрактом, може бути повторно використаний для виклику інших контрактів для виконання розгортання, він рекурсивно аналізуватиме підтранзакції транзакції та записуватиме кожен виклик, тип якого CREATE або CREATE2 .

Коли я зробив демонстраційну реалізацію, я виявив, що версія rpc зараз відносно висока, тому що найскладнішою частиною всього процесу є те, як рекурсивно знайти виклик зазначеного типу під час виконання 3. Метод нижнього рівня полягає у відновленні контекст через код операції. Я був здивований!

На щастя, у поточній версії geth є метод debug_traceTransaction, який може допомогти відсортувати контекстну інформацію кожного виклику через код операції коду операції та відсортувати основні поля.

Зрештою можна отримати оригінальні байт-коди різних режимів розгортання (пряме розгортання, одноразове розгортання в заводському режимі, пакетне розгортання в заводському режимі).

3.2 Як класифікувати з коду?

Найпростіший, але небезпечний спосіб — безпосередньо зіставляти рядки з кодом. Якщо взяти ERC20 як приклад, функція, яка відповідає стандарту,

Глибоко в ризик, що стоїть за тривіальним питанням класифікації контракту EVM

Після назви функції вказується сигнатура функції. Як згадувалося в попередньому аналізі, транзакція залежить від відповідності перших 4 цифр у callData для пошуку цільової функції. Подальше читання:

Таким чином, підписи цих 6 функцій повинні зберігатися в байт-коді контракту.

Звичайно, цей метод дуже швидкий, і ви можете знайти всі 6, але небезпечним фактором є те, що якщо я використовую контракт солідності та розроблю змінну зі значенням зберігання 0x18160ddd, тоді він подумає, що я маю цю функцію.

3.3 Підвищення рівня точності 1- декомпіляція

Подальшим точним методом є декомпіляція Opcode! Декомпіляція — це процес перетворення отриманих байт-кодів на коди операцій, а більш просунута декомпіляція — це перетворення їх на псевдокоди, що є більш сприятливим для читання людиною. Цього разу нам це не потрібно. Метод декомпіляції наведено в додатку за адресою кінець статті.

solidity (мова високого рівня) -> bytecode (байт-код) -> код операції (код операції)

Ми можемо чітко знайти функцію, сигнатура функції виконуватиметься за допомогою коду операції PUSH4, тому наступним методом є вилучення вмісту після PUSH4 із повного тексту та зіставлення його зі стандартом функції.

Глибоко в ризики, що стоять за тривіальним питанням класифікації контракту EVM

Я також провів простий експеримент продуктивності, і я повинен сказати, що мова Go є дуже ефективною, і вона займає лише 220 мс для 10 000 разів декомпіляції.

Далі буде важко

3.4 Підвищення рівня точності блок коду 2-знаходження

Наведену вище точність покращено, але недостатньо, оскільки це повнотекстовий пошук PUSH4, оскільки ми все ще можемо створити змінну типу byte4, яка також запускатиме команду PUSH4.

Коли я був засмучений, я подумав про впровадження деяких проектів з відкритим кодом. ETL — це інструмент для читання даних у ланцюжку для аналізу. Він аналізуватиме перенесення ERC20 і 721 в окремі таблиці, тому він повинен мати можливість класифікувати контракти.

Глибоко в ризик, що стоїть за тривіальним питанням класифікації контракту EVM

Після аналізу можна виявити, що він заснований на класифікації блоків коду і обробляє лише перші базові_блоки [0] Інструкція push4 в

Виникає питання, як точно оцінити блок коду

Концепція блоку коду походить від двох послідовних кодів операції REVERT + JUMPDEST. Тут має бути два послідовних коди операції, оскільки в інтервалі коду операції всього селектора функцій, якщо функцій забагато, з’явиться логіка перегортання сторінок Потім також з’явиться команда JUMPDEST.

Глибоко в ризики, що стоять за тривіальним питанням класифікації EVM-контрактів

3.5 Покращення рівня точності Селектор функцій 3-Find

Функція селектора функцій полягає в тому, щоб прочитати перші 4 байти Calldata транзакції та зіставити їх із підписом функції контракту, заданим у коді, і допомогти інструкції перейти до місця пам’яті, визначеного методом функції

Давайте спробуємо мінімальний макет виконання

Ця частина є селектором store(uint 256) і retrieve() двох функцій, а підпис можна обчислити як 2e64cec1, 6057361d

Глибоко в ризик, що стоїть за тривіальним питанням класифікації контракту EVM

Після декомпіляції ви отримаєте наступний рядок коду операції, який, можна сказати, розділений на дві частини

перша частина:

У компіляторі лише частина контракту селектора функцій отримає вміст callData, що означає отримання підпису виклику функції свого CallData, як показано на малюнку нижче.

Глибоко в ризик, що стоїть за тривіальною проблемою класифікації контракту EVM

Ми можемо побачити ефект, імітуючи зміну пулу пам’яті EVM

Глибоко в ризик, що стоїть за тривіальним питанням класифікації контракту EVM

друга частина:

Процес визначення того, чи відповідає він значенню селектора

  1. Передайте 4-байтову сигнатуру функції (0x2e64cec1) retrieve() у стек,

  2. Код операції EQ витягує 2 змінні з області стеку, а саме 0x2e64cec1 і 0x6057361d, і перевіряє, чи вони рівні

  3. PUSH2 передає 2 байти даних (тут 0x003b, 59 у десятковій системі) у стек.В області стеку є програмний лічильник, який визначає позицію наступної команди виконання в байт-коді. Тут ми встановлюємо 59, тому що саме тут починається байт-код retrieve().

  4. JUMPI розшифровується як «Jump to if...», він витягує 2 значення зі стеку як вхідні дані, і якщо умова виконується, програмний лічильник буде оновлено до 59.

Ось як EVM визначає розташування байт-коду функції, який він повинен виконати на основі виклику функції в контракті.

Насправді це просто набір операторів if для кожної функції в контракті та місця, куди вони переходять.

Глибоко в ризик, що стоїть за тривіальним питанням класифікації контракту EVM

4. Коротка схема

Загальний бриф виглядає наступним чином

  1. Кожна контрактна адреса може отримати байт-код після розгортання через rpcgetcode або debug_traceTransaction, використовуючи бібліотеки VM і ASM у GO, і отримати код операції після декомпіляції
  2. За принципом дії EVM договір матиме наступні характеристики
  • Використовуйте REVERT+JUMPDEST як розрізнення блоку коду
  • Контракт повинен мати функцію селектора функцій, і ця функція також повинна бути на першому блоці коду
  • У селекторі функцій всі його функціональні методи використовують PUSH4 як код операції,
  • У коді операції, що міститься в цьому селекторі, будуть послідовні PUSH1 00; CALLDATALOAD; PUSH1 e0; SHR; DUP1. Основна функція полягає в завантаженні даних callDate і виконанні операцій переміщення. З функції контракту інший синтаксис не генеруватиме
  1. Відповідна сигнатура функції визначена в eip, і є обов’язкові та необов’язкові чіткі інструкції

4.1 Доказ унікальності

На даний момент ми можемо сказати, що метод аналізу контрактів із високою ефективністю та високою точністю в основному реалізований. Звичайно, оскільки він так довго був суворим, ми могли б бути більш суворими. У наведеній вище схемі ми використовуйте REVER+JUMPDEST, щоб розрізнити блоки коду, і поєднайте неминуче завантаження CallDate і переміщення, щоб зробити унікальне судження.Чи існує можливість використання контракту надійності для реалізації подібної послідовності коду операції?

Я провів контрольний експеримент. Хоча існують методи отримання CallData, наприклад msg.sig, із рівня граматики твердості, методи реалізації коду операції після компіляції відрізняються.

Глибоко в ризик, що стоїть за тривіальним питанням класифікації контракту EVM

Переглянути оригінал
Контент має виключно довідковий характер і не є запрошенням до участі або пропозицією. Інвестиційні, податкові чи юридичні консультації не надаються. Перегляньте Відмову від відповідальності , щоб дізнатися більше про ризики.
  • Нагородити
  • Прокоментувати
  • Поділіться
Прокоментувати
0/400
Немає коментарів
  • Закріпити