Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
efcf-framework — EF/CF - اختبار عشوائي فائق السرعة للعقود الذكية | Kitploit
أدوات/GitHubGitHub/uni-due-syssec/efcf-framework
تحليل الثغرات الأمنيةالاستغلالالاختبار العشوائيتحليل الملفات الثنائية
GitHubuni-due-syssec/efcf-framework

efcf-framework

EF/CF - اختبار عشوائي فائق السرعة للعقود الذكية

عرض المستودع
7013منذ 3 سنواتتمت المراجعة من قبل Kitploit

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

EF/CF - أداة الاختبار العشوائي للعقود الذكية فائقة السرعة (لإيثريوم)

EF/CF هو نهج جديد للاختبار العشوائي (fuzzing) للعقود الذكية: بدلاً من استخدام أداة اختبار عشوائي جديدة مبنية خصيصًا، يعيد توظيف البنية التحتية الحالية للاختبار العشوائي الخاصة بأكواد C/C++ لتخدم العقود الذكية. حاليًا، AFL++ هي أداة الاختبار العشوائي المدعومة بشكل أساسي، مع وجود دعم بدائي جدًا لكل من libfuzzer وhonggfuzz أيضًا.

لماذا نستخدم البنية التحتية الحالية للاختبار العشوائي؟

  • السرعة. يمكننا إجراء الاختبار العشوائي بشكل أسرع. نحصل بانتظام على حوالي 20k execs/sec/core.
  • أدوات الاختبار العشوائي للكود الأصلي (native code) مصممة جيدًا ومحسَّنة.
  • توجيه تغطية سليم، وإدارة طوابير، وإعادة تشغيل حتمية لحالات الاختبار، إلخ.

ما هي بعض المشكلات التي نواجهها أثناء ذلك؟

  • نحتاج إلى تعليم أداة الاختبار العشوائي بنية البيانات: أي ما هي المعاملة و ما هي واجهة ABI الخاصة بالعقد الذكي. نستخدم محولًا مخصصًا (mutator) لهذا الغرض: ./src/ethmutator/
  • لزيادة السرعة والحصول على تغذية راجعة مفيدة حول التغطية، نترجم البايت كود الخاص بـ EVM إلى C++ باستخدام مترجم مخصص (transpiler) ./src/evm2cpp/

يُعد هذا المستودع نقطة الدخول الأساسية لمشروع EF/CF. يحتوي على جميع الأكواد ذات الصلة كمشاريع فرعية في ./src/ وعلى عدة نصوص برمجية ملائمة للتثبيت، ونصوص لإطلاق حملات الاختبار العشوائي، ومجموعات بيانات متنوعة لاختبار أداة الاختبار العشوائي (والمقارنة مع الأدوات الأخرى).

  • ./src/ - يحتوي على كل المصادر اللازمة لبناء وتشغيل EF/CF؛ ومن أجل قابلية إعادة الإنتاج، تُضاف جميع التبعيات المباشرة كوحدات فرعية تابعة لـ git.
  • ./data/ - يحتوي على مجموعات البيانات المستخدمة أثناء التقييم
  • ./scripts - يحتوي على نصوص لتشغيل التجارب والتثبيت، إلخ.
  • ./docker - ملف Dockerfile لسير عمل قائم على الحاويات
    • النظام القياسي هو Ubuntu، لكن يمكنك أيضًا استخدام حاوية مبنية على Fedora أو Arch Linux إذا أردت.
    • ./docker/tools/ يحتوي على ملفات Dockerfiles للأدوات التي قارنّا EF/CF معها. حاولنا جاهدين تثبيت الإصدارات التي قيّمناها في ورقتنا البحثية داخل ملفات Dockerfiles.
  • ./EXPERIMENTS.md - يحتوي على دليل لإعادة إنتاج التجارب من ورقتنا البحثية.
  • ./examples - يحتوي على مخرجات أمثلة مولّدة بواسطة EF/CF

ورقة EF/CF البحثية

نصف في ورقتنا البحثية بنية EF/CF وتنفيذها ونلخص نتائج تقييمنا: النسخة الأولية على arxiv.org

الاقتباس في الأعمال الأكاديمية

عند الإشارة إلى EF/CF في الأعمال الأكاديمية، يرجى استخدام إدخال BibTeX التالي للاستشهاد:```bibtex @InProceedings{efcf2023, author = "Michael Rodler and David Paaßen and Wenting Li and Lukas Bernhard and Thorsten Holz and Ghassan Karame and Lucas Davi", title = "EF/CF: High Performance Smart Contract Fuzzing for Exploit Generation", booktitle = "{IEEE} European Symposium on Security and Privacy ({EuroS&P})", publisher = "{IEEE}", year = "2023", }

root@kitploit:~
## البدء السريع

الطريقة الموصى بها هي تشغيل EF/CF كحاوية docker تفاعلية.

1. ادخل إلى الحاوية باستخدام shell   ```
   docker run --rm -it ghcr.io/uni-due-syssec/efcf-framework

أو قم ببناء الحاوية من المستودع المُستنسَخ ``` make gitmodules # to fetch the git submodules make container-enter

root@kitploit:~
1. قم بتجميع ثم بعمل fuzz على عقد Solidity حتى يتم
اكتشاف أول انهيار/خطأ:   ```
efcfuzz --until-crash --out ./baby_bank_results/ --source ./data/examples/baby_bank.sol
  1. افحص التعطل المحدد ``` cd /tmp/baby_bank_results/ ./r.sh crashes_min/default_id:000000*
    root@kitploit:~

التثبيت / الإعداد

الوحدات الفرعية Git

ليس لديك Git؟ إذا كنت تستخدم إصدار tarball/docker، فتجاهل هذا.

شغّل git submodule update --init لجلب آخر التزامات الوحدات الفرعية على المستودعات المستنسخة بالفعل. تأكد من تشغيل هذا أيضًا في ./src/eEVM.``` git submodule update --init; cd src/eEVM/; git submodule update --init; cd ../../

root@kitploit:~
*تحذير:* تنفيذ `git clone --recursive $repo` أو تمرير وسيط `--recursive` إلى `git sumbodule (update|init)` سيجعل git يدخل بشكل تكراري إلى الوحدات الفرعية لمستودع AFL++، وهي غير مطلوبة لهذا المشروع. لذا، لتوفير بعض المساحة، من الأفضل تجنب عمليات السحب التكراري للوحدات الفرعية.


### الحاوية

نوفّر أهداف make الملائمة التالية لسير العمل القائم على الحاويات:```sh
make container-build  # build default efcf container
make container-enter  # enter default efcf container in current working dir

إذا كنت تريد ضمان بناء نظيف، يمكنك استخدام الأمر التالي```sh make container-build CLEAN_CHECKOUT=1

root@kitploit:~
بدلاً من ذلك، يمكن بناء الحاوية باستخدام أمر docker التالي:```sh
docker build \
    -f docker/ubuntu.Dockerfile \
    -t efcf:latest \
    .

لاحظ أنه يوجد أيضًا Dockerfile مبني على Archlinux و Fedora. يجب أن تعمل أيضًا، لكنها ليست مختبرة جيدًا.

لتوزيع صورة docker يدويًا (على سبيل المثال، إذا كنت تتضمن بعض التغييرات المحلية)، استخدم:``` make container-release docker load -i ./efcf*.tar

root@kitploit:~
نوصي بخيارات docker التالية للتشغيل:

* `--security-opt seccomp=unconfined` - أداء أفضل لـ fuzzing
* `--net=host` - للوصول السهل إلى عقدة ethereum محلية
* `--tmpfs "/tmp/efcf/":exec,size=6g` - ضع الملفات المؤقتة لـ EF/CF على ramdisk إن أمكن (تآكل أقل للقرص)
* `--privileged` - لتشغيل `afl-system-config` أو `efcfuzz --configure-system`
* `-v` - لحفظ بيانات مخرجات EF/CF بشكل دائم


### VM / العتاد المادي

لسير العمل القائم على VM أو العتاد المادي:```sh
make system-install   # install efcf to current system (requires root or sudo rights)

لاحظ أن الكثير من السكربتات تعمل على تخطيط الدليل النسبي على أي حال، لذا فإن هذا الأمر يثبّت في الغالب التبعيات وبعض الأدوات التي من المفيد أن تكون في PATH الخاص بك. لقد اختبرنا تشغيل EF/CF على توزيعات لينكس التالية:

  • Ubuntu Jammy (أو أحدث)
  • Fedora ($ > 35 $)
  • Archlinux

(لا يهم التوزيعة كثيرًا، لقد اختبرنا LLVM 13 و14 مع كون 14 هو الخيار المفضل. قد لا يزال LLVM 11 أو 12 يعمل أيضًا، ولكن كما هو الحال دائمًا - كلما كان أحدث كان أفضل. الجزء المهم هو وجود LLVM متوافق مع fork الخاص بنا من AFL++.)

على Mac OS / M1

لم نختبر EF/CF على Mac OS بشكل أصلي. من المحتمل أن الأمور لن تعمل (على سبيل المثال، يبدو أن afl-clang-lto على Mac OS لا يعمل). الخيار الأفضل هو استخدام docker.```sh

make sure that the submodules are initialized

make gitmodules

pull the linux/amd64 base image

docker pull ubuntu:jammy --platform linux/amd64

build the ef/cf image

docker build -t efcf:latest -f docker/ubuntu.Dockerfile --platform linux/amd64 .

launch the EF/CF container

docker run --tmpfs "/tmp/efcf/":exec,size=8g --platform linux/amd64 --rm -it -v $(pwd):$(pwd) -w $(pwd) efcf:latest

root@kitploit:~
اختبرنا باستخدام Docker Desktop v4.21.1 ويعمل الاستخدام الأساسي لـ EF/CF بشكل صحيح. ومع ذلك، ضع في اعتبارك ما يلي:
* إذا رأيت أخطاء segfault أثناء البناء: حاول زيادة حد الذاكرة للجهاز الافتراضي الذي يستخدمه docker على Mac OS.
* حاول تمكين التسريع باستخدام rosetta داخل docker - نأمل أن يكون هذا أسرع قليلاً.

### الإعداد للتطوير

الأدوات بشكل عام لا تحتاج إلى تثبيت. قم بتثبيت التبعيات المطلوبة
كما هو موضح في سكربت `system-install.sh` أو كما في ملفات Dockerfiles.

للتيسير، لدينا بعض السكربتات لتحديث `PATH` الخاص بك:```sh
# POSIX-like shells (i.e., bash, ...)
source ./scripts/env.sh

# for the fish shell
source ./scripts/env.fish

مفتاح API الخاص بـ Etherscan

تتطلب بعض السكربتات مفتاح API لجلب البيانات الوصفية (مثل ABI) من خدمة Etherscan. إذا كان لديك مفتاح API، فيجب عليك ضبط متغير البيئة ETHERSCAN_API_KEY لتمريره إلى السكربتات. بالنسبة لسير العمل المعتمد على Docker، يمكنك إما تشغيل حاوية Docker مع علامة --env أو وضع مفتاح API الخاص بك في ملف .etherscan_api_key، مما سيدمج مفتاح API داخل حاوية Docker.

تشغيل EF/CF باستخدام المشغِّل

لتسهيل الأمر، نستخدم سكربت غلاف يعتني بجميع التفاصيل نيابةً عنك عند تشغيل أداة الفزّينغ EF/CF: efcfuzz

يمكنك ضبط العديد من خيارات سطر الأوامر لتكوين سلوك أداة الفزّينغ فيما يتعلق بعملية البناء والفزّينغ. ألقِ نظرة على efcfuzz --help للحصول على قائمة بالخيارات.

أمثلة

قم بترجمة الكود المصدري لـ Solidity إلى كود أصلي لـ EF/CF وابدأ الفزّينغ لمدة 5 دقائق (أي 300 ثانية).```bash efcfuzz --timeout 300 --source ./data/examples/baby_bank.sol

root@kitploit:~
بدلاً من ذلك، قم بالتشغيل مع تقليل مخرجات الفزينغ (`--quiet` يكتم
مخرجات الفازر الأساسي، بينما `--print-progress` سيطبع ملخصًا قصيرًا
لتقدم الفزينغ)، وقم بتشغيل الفازر على 4 أنوية.```bash
efcfuzz --quiet --print-progress --cores 4 --timeout 300 --source ./data/examples/baby_bank.sol

استخدم bytecode المُجمَّع بالفعل، وحوّله إلى كود أصلي EF/CF، ثم ابدأ الفيوزينج.```bash

efcfuzz can handle the combined.json output of the solidity compiler

pushd ./data/examples/; make baby_bank.combined.json; popd efcfuzz --timeout 300 --bin-runtime ./data/examples/baby_bank.combined.json

but you can also explicitely pass the runtime and deploy bytecode and the ABI

definition. This is useful if you want to fuzz contracts using other

compilers (e.g., vyper).

pushd ./data/examples/; make baby_bank; popd efcfuzz --timeout 300
--bin-runtime ./data/examples/baby_bank.bin-runtime
--bin-deploy ./data/examples/baby_bank.bin
--abi ./data/examples/baby_bank.abi

root@kitploit:~
يمكن للمغلّف تصدير حالة العقد من عقدة go-ethereum/erigon وبدء fuzzing من هناك.```bash
$ efcfuzz --timeout 300 --live-state 0xfffF8D17CB019E0825c478c666B251A7099df3FD

بالإضافة إلى ذلك، يمكنك تمرير --include-address-deps=y للبحث بشكل متكرر عن عناوين الحسابات الأخرى في تخزين العقد المُصدَّر وتضمينها أيضًا في تصدير الحالة. ومع ذلك، لا يشمل ذلك العقود الأخرى المخزّنة في أنواع mapping في Solidity. لتصدير الحالة كاملة بشكل متكرر، مرّر أيضًا علم --include-mapping-deps=y.

لكن انتبه، قد يؤدي هذا البحث المتكرر إلى أوقات تجميع طويلة وأداء ضعيف للاختبار العشوائي. خاصةً أن العقود المستخدمة كثيرًا قد تحتوي على قدر كبير من الحالة الداخلية، واستخدام حالتها المُصدَّرة قد يجعل الاختبار العشوائي بطيئًا. تحقق مما إذا كان بإمكان المُختبِر العشوائي تحقيق أكثر من 1k عملية تنفيذ في الثانية. إذا لم يكن الأمر كذلك، فمن الأفضل محاولة إنشاء حالة صناعية أصغر. جرّب تشغيل عقدة go-ethereum محلية في وضع --dev وانشر عقودك هناك. ثم صدّر الحالة المباشرة من هناك.

يخزّن المغلّف نتائج البناء مؤقتًا، لذا يجب أن يُطلق تشغيل الاختبار العشوائي الثاني بشكل أسرع بكثير، لأن وقت التجميع الأولي لم يعد مطلوبًا. إذا أردت فقط البناء ووضعه في الذاكرة المؤقتة، فمرّر الوسيط --build-only.

مثال: الاختبار العشوائي باستخدام الخصائص

يدعم EF/CF أيضًا الاختبار العشوائي القائم على الخصائص باستخدام نفس تعريف الخصائص المُستخدم في المُختبِر echidna. تُعبَّر الخصائص (أو الثوابت) كدوال في solidity تعمل كمرجع لكشف الأخطاء بالنسبة للمُختبِر العشوائي. على سبيل المثال، يمكنك إضافة دالة solidity:```solidity function test_property_balance() public view returns (bool) { return total_balance < 1000; }

root@kitploit:~
وهو ما يمثل الخاصية التي يجب أن يكون total_balance دائمًا أقل من
1000. سيقوم EF/CF عندها بالإبلاغ عن خطأ إذا تمكن من انتهاك هذه الخاصية باستخدام
تسلسل معين من المعاملات، أي أن oracle يُرجع `false`.

لإخبار EF/CF بأن هذه خاصية، تحتاج إلى تحديد قائمة بتوقيعات الدوال
في ملف، والتي سيلتقطها EF/CF كقائمة من الخصائص
للتحقق منها أثناء fuzzing.

أسهل طريقة هي الحصول على التوقيعات ذات الصلة باستخدام علامة `--hashes`
لمترجم Solidity، على سبيل المثال،```
solc --hashes ./path/to/your.sol | grep test_property > property_list

الآن يمكنك تشغيل الفازر باستخدام:``` efcfuzz --source ./path/to/your.sol --properties ./property_list -C

root@kitploit:~
يمكنك أيضًا إضافة `--disable-detectors` لتعطيل أدوات كشف الأخطاء المدمجة القائمة على ether.

يمكنك تجربة المثال التالي للاختبار القائم على الخصائص:```
efcfuzz \
    --properties ./data/examples/harvey_baz_properties.signatures
    --disable-detectors \
    --until-crash --timeout 120 \
    --source ./data/examples/harvey_baz.sol \

مثال: التخمين (Fuzzing) للأحداث

يدعم EF/CF التخمين (fuzzing) لانتهاكات التأكيدات (assertion) التي يتم التعبير عنها من خلال الأحداث. في الواقع، ندعم أيضًا استخدام أحداث مخصصة عشوائية كدليل على وجود خطأ (oracle). افتراضيًا، سيحدد EF/CF وجود خطأ إذا سجّل العقد المستهدف واحدًا من الأحداث التالية: AssertionFailed()، AssertionFailed(uint256)، AssertionFailed(string)، وPanic(uint256).``` efcfuzz --event-assertions
--timeout 120 --until-crash
--source ./data/properties-assertions-tests/verifyfunwithnumbers.sol

root@kitploit:~
يمكنك أيضًا تحديد مواضيع/تجزئات أحداث مخصصة إضافية لمراقبتها في
ملف عبر `--event-assertions-list ./path/to/eventslist.txt`. كما هو الحال مع
قائمة الخصائص سابقًا، يمكنك الحصول على الصيغة باستخدام `solc --hashes` و
نسخ تجزئات الأحداث وأسمائها إلى ملف قائمة الأحداث.

افتراضيًا، سيتجاهل EF/CF الأحداث التي لم يصدرها العقد
المستهدف. إذا كنت تريد تغيير ذلك، استخدم `--event-assertions-target-only=n`.

(ملاحظة: يمكنك استخدام `--assertions` لتفعيل فحص كل من الأحداث وتأكيدات
Solidity)

**مثال: Fuzzing لتأكيدات Solidity ^0.8**

حاليًا، لا ندعم استخدام fuzzing للتأكيدات التعسفية في كود Solidity
لإصدارات Solidity الأقل من 0.8. سابقًا، كانت تأكيدات Solidity تؤدي ببساطة
إلى تشغيل كود تشغيلي `invalid`، مما يسفر عن تراجع قسري إلى حد ما. غيّر
إصدار Solidity 0.8 هذا السلوك، فبدلاً من استخدام كود التشغيل `invalid`
لتراجع المعاملات، أصبح الآن يستخدم آلية `revert` ويرسل إشارات الأخطاء
مرة أخرى إلى المتصل. يمكننا استخدام هذا النوع من انتشار الأخطاء كـ
oracle في EF/CF. حاليًا، يدعم EF/CF التحقق من نوع خطأ
Solidity `Panic(uint256)`. [مزيد من المعلومات حول أخطاء
Solidity.](https://docs.soliditylang.org/en/v0.8.0/control-structures.html?highlight=assert#panic-via-assert-and-error-via-require)```
efcfuzz --sol-assertions \
    --timeout 120 --until-crash \
    --source ./data/assertions-tests/overflow.sol

(ملاحظة: يمكنك استخدام --assertions لتفعيل فحص الأحداث وفحص تأكيدات Solidity معًا)

مواصفات النظام والإعداد

نوصي بتخصيص من 4 إلى 16 نواة وحوالي 1 غيغابايت من الذاكرة لكل نواة. يمكنك استخدام خيار --configure-system لتهيئة نظامك للـ fuzzing عالي السرعة، أو قم بتهيئته بنفسك. في حاويات docker تحتاج أيضًا إلى تهيئة المضيف للحصول على أفضل أداء. إذا كان المضيف غير حرج، يمكنك تشغيل الحاوية باستخدام --privileged واستخدام /usr/local/bin/afl-system-config لتهيئة النظام للـ fuzzing عالي السرعة (لاحظ أن هذا يشغّل الحاوية بشكل أساسي كجذر).```

configure system

docker run --rm -it --privileged efcf afl-system-config

run fuzzer (somewhat sandboxed and using a tmpfs for less SSD wear)

docker run --rm -it
--security-opt seccomp=unconfined
--tmpfs "/tmp/efcf/":exec,size=6g
efcf

root@kitploit:~
## تشغيل تجربة فيزينغ

لتشغيل التجربة على مجموعة البيانات `data/tests/` يمكنك استخدام الأمر التالي لبناء العقود وأداة الفيزينغ الخاصة بها ثم تشغيل الفيزر بإعدادات مختلفة، وتكرارات متعددة، إلخ. ولأن هذا قد يستغرق وقتًا طويلًا، يمكننا تشغيل هذه التجارب بالتوازي. نقسم تجارب الفيزينغ إلى خطوة بناء وخطوة فيزينغ. خطوات البناء ستبني جميع العقود الذكية بالتتابع (رغم أن البناء نفسه يستخدم أنوية متعددة). ثم نطلق 8 مثيلات من الفيزر في الخلفية، والتي ستأخذ مخرجات البناء من خطوة البناء وتبدأ جولات الفيزينغ. سيقوم ملف Makefile تلقائيًا بمحاولة إطلاق كل شيء داخل الحاوية المناسبة إذا كان `docker` أو `podman` متاحًا.```bash
make build-tests
make fuzz-tests CONTAINER_BACKGROUND=1 FUZZER_INSTANCES=8

We disable seccomp and network sandboxing when launching the containers in background. Disabling seccomp sandboxing, improves fuzzing performance. Using the host network allows EF/CF to access Ethereum nodes in the local network without further configuration.

We used the script ./scripts/run-tools-on-dataset.py to run the other tools inside docker containers on these datasets, e.g. with these commands for the multi dataset:```bash python3 ./scripts/run-tools-on-dataset.py ./data/multi/ cd ./results/tools-multi/ python3 ../../scripts/get-tools-on-dataset-stats.py head stats.csv

root@kitploit:~
تحتاج إلى تعديل البرنامج النصي لضبط الأدوات وعدد مرات التشغيل.

### إعداد تجربة Fuzzing

نستخدم هنا تجربة `tests` كمثال. ببساطة استبدل السلسلة `tests` باسم التجربة في الخطوات التالية:

1. اجمع مجموعة البيانات الخاصة بك في `./data/`، على سبيل المثال مجموعة البيانات `./data/tests` التي تحتوي على عقود اختبار.
   بالنسبة لعقود Solidity لدينا `Makefile` عام لبناء العقود: `sol.Makefile`. يمكنك إعادة استخدامه إذا أردت، انظر `./data/tests/Makefile` كمثال.
2. أنشئ برنامجًا نصيًا لبناء نواتج البناء بما في ذلك أي خطوات معالجة مسبقة/استخراج ضرورية. على سبيل المثال، لتجربة `tests` لدينا البرنامج النصي `./scripts/build-tests.sh`. يجب تخزين نواتج البناء في `./builds/tests/${contract}.build.tar.xz`.
3. أنشئ برنامجًا نصيًا لإطلاق حملة Fuzzing، على سبيل المثال لمجموعة البيانات `tests` أنشئ برنامجًا نصيًا باسم `./scripts/fuzz-tests.sh`. يمكنك عادةً استخدام دالة حملة Fuzzing الشائعة من `./scripts/common.sh`. ألقِ نظرة على `fuzz-tests.sh` كقالب.
4. سيتم تخزين نتائج `fuzz-tests.sh` في `./results/run-fuzz-tests/`.
5. لتلخيص النتائج، نوفر `./scripts/summarize.py` للبرامج النصية للإطلاق المبنية على bash و`./scripts/summarize_l.py` للبرامج النصية للإطلاق المكتوبة بلغة بايثون (أداة `efcfuzz`).
   قد تحتاج إلى تعديل هذه البرامج النصية اعتمادًا على خطوتك 3.


### تجارب Fuzzing الحالية

#### المعايير

* <a href="./data/multi/">`./data/multi`</a> يحتوي على معيار قابلية التوسع الذي استخدمناه لتقييم مدى قدرة أداة التحليل على التكيف مع تسلسلات معاملات أطول. يتكون من ثلاثة أنواع من العقود:
    * `multi_gen_*.sol` - عقود مُصنَّعة تلقائيًا، تقوم بمجموعة من `require(input <= MAGIC)` ثم تعيّن متغير حالة داخلي. إذا تم تعيين جميع متغيرات الحالة، فيمكن عندئذٍ تشغيل `selfdestruct` (أو أوراكل echidna).
    * `multi_man_complex_*.sol` - نسخ معدلة يدويًا تعمل بشكل مشابه لعقود نوع `multi_gen`، لكنها تتميز بقيود أكثر صعوبة (مثل: أمور أخرى غير المساواة وعدم المساواة مع قيمة سحرية)
    * `justlen_*.sol` - هذه مأخوذة من [مثال echidna-parade](https://github.com/crytic/echidna-parade/blob/main/examples/justlen.sol)
    * `multi_simple_*.sol` - فحوصات سلامة تتحقق من أن أداة Fuzzing/الأداة يمكنها نظريًا العثور على أخطاء تتطلب 9 أو 10 معاملات. هنا يحتاج المحلل فقط إلى استدعاء 10 دوال بالترتيب الصحيح دون أي وسائط. هذا سهل جدًا لمعظم أدوات التحليل.
* <a href="./data/throughput/">`./data/throughput`</a> يحتوي على العقود التي استخدمناها لتقييم معدل الإنتاجية (throughput). هذه مجموعة مختارة من العقود بأحجام مختلفة. لاحظ أننا أصلحنا جميع الثغرات في هذه العقود، بحيث لا تؤثر الثغرات المكتشفة على قياسات الإنتاجية.
* <a href="./data/cov-max-testset">`./data/cov-max-testset`</a> يحتوي على العقود التي استخدمناها لمقارنة أدوات Fuzzing بناءً على تغطية الكود.

#### كشف الثغرات

* <a href="./data/ethbmc-vuln">`./data/ethbmc-vuln`</a> قائمة بالعقود التي اكتشفها EthBMC على أنها قابلة للاختراق.
* <a href="./data/ethbmc-timeouts">`./data/ethbmc-timeouts`</a> قائمة بالعقود التي أوقف EthBMC تحليلها بسبب انتهاء المهلة (timeout).
* <a href="./data/reentrancy">`./data/reentrancy`</a> مجموعة من العقود المعرضة لهجمات إعادة الدخول (reentrancy).
* <a href="./data/sailfish-dao-tp">`./data/sailfish-dao-tp`</a> مجموعة من العقود التي تم التحقق من أنها تحتوي على خطأ إعادة الدخول كجزء من [دراسة sailfish](https://github.com/ucsb-seclab/sailfish/tree/master/data/ground-truth).
* <a href="./data/sailfish-dao">`./data/sailfish-dao`</a> قائمة بجميع العقود التي وجد فيها [sailfish](https://github.com/ucsb-seclab/sailfish/tree/master/data/bugs) خطأ إعادة الدخول.
* <a href="./data/sereum">`./data/sereum`</a> قائمة بالعقود المعرضة لهجمات إعادة الدخول وفقًا لـ [Sereum](https://github.com/uni-due-syssec/sereum-results).
* <a href="./data/smartbugs-curated-accesscontrol">`./data/smartbugs-curated-accesscontrol`</a> عقود من smartbugs المنسقة، مُصنفة كأخطاء "التحكم بالوصول" ([smartbugs github](https://github.com/smartbugs/smartbugs/tree/master/dataset/access_control))
* <a href="./data/smartbugs-curated-reentrancy">`./data/smartbugs-curated-reentrancy`</a> عقود من smartbugs المنسقة، مُصنفة كأخطاء "إعادة الدخول" ([smartbugs github](https://github.com/smartbugs/smartbugs/tree/master/dataset/reentrancy))

#### الاختبارات

تحتوي مجموعات البيانات التالية على عقود اختبار اصطناعية أساسية لاختبار قدرات أداة Fuzzing:
  
* <a href="./data/tests">`./data/tests`</a> اختبارات أساسية تم جمعها من مصادر متعددة تتحقق من القدرات الأساسية لأداة Fuzzing. جميعها تستخدم أوراكل selfdestruct.
* <a href="./data/tests-not-vuln">`./data/tests-not-vuln`</a> نفس الاختبارات، لكن يجب ألا يتم اكتشافها على أنها قابلة للاختراق.
* <a href="./data/properties-tests">`./data/properties-tests`</a> اختبارات لـ Fuzzing المستند إلى الخصائص
* <a href="./data/assertions-tests">`./data/assertions-tests`</a> اختبارات لـ Fuzzing من أجل التأكيدات.


## مزيد من التفاصيل حول Fuzzing

نستخدم البرامج النصية المغلفة (wrapper scripts) لإطلاق أداة Fuzzing الفعلية (AFL++ في حالتنا). يتم ذلك تلقائيًا عند استخدام مُطلق `efcfuzz`.```bash
$ cd data/tests
$ make SimpleDAO.evm2cpp
$ cd ../../src/eEVM/
$ env AFL_BENCH_UNTIL_CRASH=1 ./fuzz/launch-aflfuzz.sh SimpleDAO

إذا كان لديك tmux وtmuxp مثبتين، فقد تكون النسخة التفاعلية من السكربت مفيدة للتطوير والفحص:```bash $ ./fuzz/interactive-aflfuzz.sh -b SimpleDAO

root@kitploit:~
سيؤدي هذا بعد ذلك إلى التجميع وتنفيذ عملية fuzzing لفترة طويلة. يمكنك بعدها
استخدام `cd ./fuzz/out/SimpleDAO*` لعرض نتائج الـ fuzzing. تقوم نصوصنا البرمجية المساعدة
ببعض العمل الإضافي فوق تشغيل برنامج `afl-fuzz`، أي في معظمها
معالجة النتائج. بالإضافة إلى ذلك، سينشئ عدة نصوص برمجية ملائمة
لتحليل حالات الاختبار المولّدة.

* `./a.sh` - طباعة شكل قابل للقراءة البشرية لحالة اختبار، وهو غلاف حول
  `efuzzcaseanalyzer`.
* `./r.sh` - تشغيل حالة اختبار بنفس الإعدادات التي تم بها تشغيل الـ fuzzer.
* `./m.sh` - تصغير حالة اختبار بنفس الإعدادات التي تم بها
  تشغيل الـ fuzzer.
* `./c.sh` - تحليل "سلسلة" حالات الاختبار التي تؤدي إلى حالة الاختبار
  المحددة. مفيد لتحليل/تحسين الـ fuzzer. يمكنك أن ترى بسرعة أي حالة اختبار
  تم إنتاجها بواسطة أي سلسلة طفرات على أي من مدخلات قائمة الانتظار. 
  يتطلب `fzf`.

هناك أيضًا بعض التقارير الملائمة الأخرى، مثل

* `./bugs` و `./bugtypes` اللذان يلخصان أي أخطاء تم تحديدها.
* `./crashes_min`، والذي يحتوي على حالات الانهيار المصغّرة لجميع نسخ
  `afl-fuzz`.

**عرض تغطية كود الكتل الأساسية في EVM**```bash
$ cat coverage-percent-all.evmcov
70.73170731707317

سيكتب السكربت fuzz/evm-bb-coverage.sh حساب تغطية الكتل الأساسية (basic block coverage) عند إعطائه دليل مخرجات AFL. يمكن للأداة المساعدة اختياريًا تفريغ أثر (trace) للكتل الأساسية، والتي تُقارن بعد ذلك بقائمة الكتل الأساسية التي يُخرجها evm2cpp (أي ملفات .bb_list في eEVM/contracts/).

بشكل افتراضي، نحسب أيضًا التغطية التي تُنتجها بذورنا العامة الافتراضية (انظر eEVM/fuzz/generic_seeds):```bash $ cat coverage-percent-seeds.evmcov 10.5890

root@kitploit:~
يتم تخزين قائمة الكتل الأساسية المغطاة في الملف `all.evmcov`.


**عرض ملخص حالات الاختبار المُولَّدة**

يمكن استخدام `efuzzcaseanalyzer` لعرض/تلخيص حالات الاختبار المُولَّدة،
على سبيل المثال،```
$ efuzzcaseanalyzer -a ./contract.abi -s ./crashes_min/
Transactions Sequences:
--------------------------------------------------------------
TX [🪙]
    deposit()[🪙];
    withdraw(uint256)[↕️ ↩️ ];
    withdraw(uint256)[];
--------------------------------------------------------------
Number of fuzzcases: 1
Average number of TXs: 3
Number of unique TX sequences: 1
Number of unique TX sequences (consecutive deduplicated): 1

عادةً ما تُخزَّن الملخصات في الملفّين crashes_tx_summary و queue_tx_summary، لكن هذا الأخير قد يكون مطوَّلًا بعض الشيء.

تحليل حالة اختبار واحدة تسبّب الانهيار``` $ ./a.sh default/crashes/id:000000,...

roughly equivalent to running

$ efuzzcaseanalyzer -a ./contract.abi default/crashes/id:000000,... Block header: number: 0 difficulty: 0 gas_limit: 0 timestamp: 0 initial_ether: 0

TX with tx_sender: 54 (selector); call_value: 0x0; length: 36; block+=1; #returns=0 func: withdraw(uint256) input: { Uint(80), } TX with tx_sender: 238 (selector); call_value: 0x246ddf979; length: 4; block+=1; #returns=0 func: deposit() input: { } TX with tx_sender: 153 (selector); call_value: 0x3860e6373; length: 4; block+=1; #returns=0 func: deposit() input: { } TX with tx_sender: 166 (selector); call_value: 0x0; length: 36; block+=1; #returns=1 func: withdraw(uint256) input: { Uint(37000000000000000000), } returns: return val: 1; allows reenter: 2; data: 0x0000000000000000000000000000000000000000000000000000000000000001 TX with tx_sender: 166 (selector); call_value: 0x0; length: 36; block+=1; #returns=0 func: withdraw(uint256) input: { Uint(37000000000000000000), }

root@kitploit:~
وللحصول على النتيجة الفعلية لهدف fuzz، يمكنك تنفيذ:```
$ ./r.sh default/crashes/id:000000,sig:06,src:000000+000010,time:1584,EM-________SAO_______AD
# roughly equivalent to running
$ env EVM_DEBUG_PRINT=1 ./build/fuzz_multitx default/crashes/id:000000,sig:06,src:000000+000010,time:1584,EM-________SAO_______AD

[...]

account 0xc4b803ea8bc30894cc4672a9159ca000d377d9a3 has balance 0x100000000000000000000000000000001bc16d67562e80000( > 0x1000000000000000000000000000000000000000000000000)
Aborted (core dumped)

يُعطيك هذا الكثير من المخرجات التفصيلية، بما في ذلك بعض أجزاء آثار تنفيذ العقود ونتيجة فحص الرصيد التي يقوم بها الـ harness.

تصغير المدخلات المُتسببة في الانهيار

غالبًا ما تحتوي المدخلات المُتسببة في الانهيار على معاملات غير ذات صلة بسبب أسلوب الاختبار العشوائي. يمكن التخفيف من ذلك عبر إجراء تصغير على المدخل المُنهار (أي تقليل المدخل طالما أنه ما زال يتسبب في انهيار). إذا أردت تصغير مدخلات غير مُنهارة، يمكنك استخدام العلم -M لتفعيل التصغير وفقًا للتغطية كمعيار للتصغير.

سيؤدي الأمر التالي إلى تقليص حالة الاختبار والكتابة فوق الملف:``` $ efuzzcaseminimizer -oa ./contract.abi ./build/fuzz_multitx ./default/crashes/id:000000,sig:06,src:000000+000010,time:1584,EM-________SAO_______AD

[..]

=== Before minimizing: === Block header: number: 0 difficulty: 0 gas_limit: 0 timestamp: 0 initial_ether: 0

TX with tx_sender: 54 (selector); call_value: 0x0; length: 36; block+=1; #returns=0 func: withdraw(uint256) input: { Uint(80), } TX with tx_sender: 238 (selector); call_value: 0x246ddf979; length: 4; block+=1; #returns=0 func: deposit() input: { } TX with tx_sender: 153 (selector); call_value: 0x3860e6373; length: 4; block+=1; #returns=0 func: deposit() input: { } TX with tx_sender: 166 (selector); call_value: 0x0; length: 36; block+=1; #returns=1 func: withdraw(uint256) input: { Uint(37000000000000000000), } returns: return val: 1; allows reenter: 2; data: 0x0000000000000000000000000000000000000000000000000000000000000001 TX with tx_sender: 166 (selector); call_value: 0x0; length: 36; block+=1; #returns=0 func: withdraw(uint256) input: { Uint(37000000000000000000), }

=== After minimizing: === Block header: number: 0 difficulty: 0 gas_limit: 0 timestamp: 0 initial_ether: 15133991795

TX with tx_sender: 4 (selector); call_value: 0x246ddf979; length: 4; block+=0; #returns=0 func: deposit() input: { } TX with tx_sender: 4 (selector); call_value: 0x0; length: 36; block+=1; #returns=1 func: withdraw(uint256) input: { Uint(37000000000000000000), } returns: return val: 1; allows reenter: 2; data: 0x TX with tx_sender: 0 (selector); call_value: 0x0; length: 36; block+=1; #returns=0 func: withdraw(uint256) input: { Uint(37000000000000000000), }

root@kitploit:~
## قراءة صيغة حالة الاختبار

صيغة حالة الاختبار موجّهة نحو التضمين العشوائي (fuzzing) وليست سهلة القراءة مباشرة. هناك عدة تفاصيل دقيقة يجب أن تكون على دراية بها.

* تُعتبر صيغة حالة الاختبار بمثابة "طابور" من المعاملات التي يمكن تنفيذها. فور اكتشاف أي مشكلة، يتوقف معالجة حالة الاختبار. يشمل ذلك:
    * عندما تتراجع معاملة (revert).
    * أي خطأ يواجهه كود التجهيز (harness).
    * أي خطأ يتم تشغيله واكتشافه.
  ونتيجة لذلك، فإن حالة الاختبار المطبوعة لا تتوافق بالضرورة مع ما يتم تنفيذه - فقد تكون هناك معاملات في النهاية لم يتم تنفيذها. تحقق من المخرجات المفصّلة (verbose) واستخدم أداة التصغير (minimizer) للتخلص من تلك المعاملات!
* وبالمثل، قد يكون هناك عدد كبير جداً من `returns` أو أعلام `reenter` زائفة. استخدم مصغّر حالة الاختبار للتخلص من هذه.
* لا يتم إعادة الدخول إلى العقد (contract) إلا عندما تكون هناك معاملة أخرى في القائمة بعد المعاملة التي يُفترض أن تقوم بإعادة الدخول (أي وجود إدخال تالٍ في الطابور).
* حتى إذا كان علم `reenter` مُعيَّناً على قيمة ما، فإن هذا لا يعني بالضرورة أن العقد سيُعاد الدخول إليه، بل فقط أن كود التجهيز سيحاول القيام بذلك إن أمكن. على سبيل المثال، إذا كان العقد لا يقوم باستدعاء، فسيتم تجاهل علم إعادة الدخول نظراً لعدم وجود إمكانية لإعادة الدخول. عادةً ما يقوم المصغّر بإزالة أي أعلام `reenter` زائفة.

بشكل عام، تختفي العديد من هذه المشكلات عند استخدام مصغّر حالة الاختبار، لذا يُنصح دائماً باستخدامه قبل تحليل حالات الاختبار المُولّدة.

## أخطاء الإنذار الكاذب المعروفة

لاحظنا عدة أنواع من أخطاء الإنذار الكاذب التي تبدو متكررة عند التضمين العشوائي للعقود باستخدام EF/CF.

* العقود التي تدفع Ether حسب التصميم. سيلتقط مُنبّه أخطاء كسب Ether في EF/CF هذه العقود على أنها قابلة للاستغلال، على الرغم من أنها تعمل كما هو مُصمَّم:
    * عقود المقامرة: تحتوي العديد من عقود المقامرة على شكل من أشكال العشوائية، وهو بالفعل ممارسة سيئة في إيثيريوم. ومع ذلك، فإن بعض عقود المقامرة مُنفَّذة بطريقة تُجبرك على التخمين، على سبيل المثال، آخر رقمين من blockhash التالي أو ما شابه ذلك. يمكن تفعيل ذلك باستخدام مخطط التزام (commitment scheme)، أي أن المعاملة الأولى تُلزم المستخدم بقيمة معينة والثانية تُطلق التخمين والدفع عند الفوز. عادةً لا يمكن استغلال هذه العقود في سلسلة الكتل الحقيقية. ومع ذلك، في سلسلة الكتل المُحاكاة في EF/CF، يمكن للمُضمِّن العشوائي تكييف الالتزام بعد ملاحظة القيمة في المعاملة الثانية. هذه الحقيقة مهمة لـ EF/CF للوصول إلى تغطية أفضل للكود. ومع ذلك، فإنها تجعل من السهل أيضاً على EF/CF تحديد تسلسل معاملات يسمح للمُضمِّن العشوائي بالفوز حتمياً في عقد المقامرة.
    * العقود التي تدفع فوائد: هناك العديد من العقود الصغيرة التي تسمح لك باستثمار Ether ثم تدفع نسبة مئوية معينة من الفوائد كل `N` كتلة. المهاجم المُحاكى في EF/CF قادر على انتظار `N` كتلة ثم receives دفعة الفائدة، وهو ما يلتقطه مُنبّه أخطاء كسب Ether مرة أخرى.
    * الإسقاطات الجوية (Airdrops): تتيح بعض عقود الرموز المميزة إسقاطات جوية، أي مجرد توزيع الرموز على أي شخص يطلبها حتى يتم الوصول إلى حدود معينة. على سبيل المثال، غالباً ما تكون الإسقاطات الجوية مُفعّلة فقط لفترة قصيرة من الزمن. إذا تم نشر مثل هذا العقد داخل EF/CF، فمن المرجح أن يكون الحد الزمني مُعيَّناً بحيث تظل الإسقاطات الجوية مفعّلة. عندها يلتقط EF/CF خطأ كسب Ether إذا كان من الممكن بيع الرموز الموزعة مرة أخرى.
* الإبلاغ المبكر عن `DELEGATECALL` القابل للتحكم: نبلغ حالياً عن delegatecall قابل للتحكم بمجرد استدعائه. ومع ذلك، هناك العديد من العقود التي تحتوي على دوال تسمح عمداً للمتصل بتنفيذ delegatecall إلى عنوان عشوائي. ومع ذلك، فإن هذه الدوال سترجع المعاملة (revert) بشكل غير مشروط فور انتهاء delegatecall. وهذا يمنع أي تحديثات للحالة أو تحويلات Ether من الاستمرار. عادةً ما تحتوي هذه الدوال على كلمات مثل "simulate" في أسمائها، وبالتالي يسهل اكتشافها.
    * يمكن إصلاح ذلك في EF/CF عن طريق تأخير الإبلاغ حتى نهاية التنفيذ. ومع ذلك، فإن هذا يعقّد مُنبّه الأخطاء قليلاً.
    * لا توجد حالياً خطط لإصلاح هذا.
* دالة التهيئة (initializer) قابلة للاستدعاء: لاحظنا أنه عند التضمين العشوائي للعقود المُصدَّرة من سلسلة الكتل، يكون EF/CF قادراً أحياناً على استدعاء دوال التهيئة، حتى لو كان العقد قد تمت تهيئته بالفعل. في العادة، يجب أن يؤدي ذلك إلى revert، لكنه لا يحدث في بيئة EVM الخاصة بـ EF/CF. غالباً ما يؤدي استدعاء دالة التهيئة مرة أخرى إلى مكاسب Ether تافهة، لأنه على سبيل المثال، تقوم دالة التهيئة بتعيين متغير *owner* أو ما شابه ذلك.
    * لسنا متأكدين بعد من السبب الجذري لهذه المشكلة. ومع ذلك، من السهل عادةً اكتشافها، لأن دالة التهيئة تُسمى عادةً `initializer` أو `init` أو ما شابه ذلك.

## الأخطاء الشائعة

لقد بذلنا قصارى جهدنا لجعل هذه الأداة قابلة للاستخدام إلى حد ما، لكنها لا تزال نموذجاً أولياً بحثياً. توقع حدوث أعطال. فيما يلي بعض المشكلات الشائعة التي لاحظناها:

* *س: أواجه خطأ ترجمة غريباً بسبب ماكرو `TOKENPASTE`.*  
  ج: يحدث هذا غالباً عندما يخمّن `efcfuzz` اسم العقد الخاطئ (أي أنه يخمّن عقداً مجرداً). جرّب تمرير `--name YourContract` لتحديد العقد المستهدف.
تنزيل الأداة