في العمق EVM- المخاطر الكامنة وراء مسألة تافهة تصنيف العقد

في مجال العقود الذكية ، تعتبر "Ethereum Virtual Machine EVM" وخوارزمياتها وهياكل البيانات هي المبادئ الأولى.

تبدأ هذه المقالة من سبب تصنيف العقود ، وتجمع بين نوع الهجمات الضارة التي قد يواجهها كل سيناريو ، وتقدم أخيرًا مجموعة من خوارزميات تحليل تصنيف العقود الآمنة نسبيًا.

** على الرغم من أن المحتوى الفني مرتفع ، إلا أنه يمكن استخدامه أيضًا كمواد قراءة لمحادثات متنوعة. ** ألقِ نظرة على الغابة المظلمة للألعاب بين الأنظمة اللامركزية.

1. لماذا يجب تصنيف العقود؟

نظرًا لأنه مهم جدًا ، يمكن القول إنه حجر الزاوية في Dapps مثل التبادلات والمحافظ ومتصفحات blockchain ومنصات تحليل البيانات وما إلى ذلك!

السبب في أن المعاملة هي تحويل ERC20 هو أن سلوكه يتوافق مع معيار ERC20 ، على الأقل:

  1. حالة الصفقة هي نجاح
  2. العنوان هو عقد يتوافق مع معيار ERC20
  3. يتم استدعاء وظيفة التحويل ، وتتمثل الخاصية في أن الأرقام الأربعة الأولى من CallData للمعاملة هي 0xa9059cbb
  4. بعد التنفيذ ، يتم إرسال حدث التحويل على العنوان "إلى"

** إذا كان التصنيف خاطئًا ، فسيتم سوء تقدير سلوك المعاملة **

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

** إذا كان التصنيف خاطئًا ، فستدخل المعاملة في الثقب الأسود عن طريق الخطأ **

إذا قام المستخدم بتحويل رمز مميز إلى عقد معين ، وإذا لم يكن للعقد طريقة وظيفة محددة مسبقًا لتحويل الرمز المميز ، فسيتم قفل الأموال بنفس طريقة Burn ولا يمكن التحكم فيها

والآن بعد أن بدأ عدد كبير من المشاريع في إضافة دعم المحفظة المدمج ، أصبح من الحتمي إدارة المحافظ للمستخدمين.من الضروري تصنيف أحدث العقود المنشورة من السلسلة في الوقت الفعلي في جميع الأوقات ، سواء كان بإمكانهم تلبية معايير الأصول.

! [في عمق المخاطر الكامنة وراء الأمر التافه لتصنيف عقد EVM] (https://img.gateio.im/social/moments-40baef27dd-ed9a8c6ef0-dd1a6f-62a40f)

2. ما هي مخاطر التصنيف؟

** السلسلة مكان لا هوية ولا سيادة قانون ، ولا يمكنك إيقاف معاملة عادية حتى لو كانت خبيثة. **

يمكن أن يكون ذئبًا يتظاهر بأنه جدة ، ويقوم بمعظم السلوكيات التي تتوقع أن تفعلها الجدة ، ولكن بغرض اقتحام المنزل والسرقة.

** معيار المطالبات ، ولكن قد لا يلبي في الواقع **

تتمثل إحدى طرق التصنيف الشائعة في اعتماد معيار EIP-165 مباشرةً لقراءة ما إذا كان العنوان يدعم ERC20 وما إلى ذلك. بالطبع ، هذه طريقة فعالة ، ولكن بعد كل شيء ، يتم التحكم في العقد من قبل الطرف الآخر ، لذلك يمكن أن يكون البيان مزورة بعد كل شيء.

الاستعلام القياسي 165 هو مجرد طريقة لمنع تحويل الأموال إلى الثقوب السوداء بأقل تكلفة بين أكواد التشغيل المحدودة في السلسلة.

هذا هو السبب عندما قمنا بتحليل NFT من قبل ، ذكرنا على وجه التحديد أنه سيكون هناك طريقة SafeTransferFrom في المعيار ، حيث يشير Safe إلى استخدام معيار 165 لتحديد أن الطرف الآخر لديه القدرة على نقل NFT.

فقط من خلال البدء من الرمز الثانوي للعقد ، وإجراء تحليل ثابت على مستوى كود المصدر ، والبدء من السلوك المتوقع للعقد ، يمكن أن يكون أكثر دقة.

3. تصميم مخطط تصنيف العقود

بعد ذلك ، سنقوم بتحليل الخطة الشاملة بشكل منهجي ، ونلاحظ أن هدفنا النهائي هو المؤشرين الأساسيين "الدقة" و "الكفاءة". **

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

3.1. كيفية الحصول على الرمز؟

من وجهة نظر الذهاب إلى السلسلة ، هناك getCode ، وهي طريقة RPC ، والتي يمكنها الحصول على الرمز الثانوي من العنوان المحدد في السلسلة. وهي سريعة جدًا من حيث القراءة وحدها ، لأن codeHash يتم وضعها في الحساب هيكل EVM في القمة.

! [في أعماق المخاطر الكامنة وراء الأمر التافه لتصنيف عقد EVM] (https://img.gateio.im/social/moments-40baef27dd-040abf2b06-dd1a6f-62a40f)

لكن هذه الطريقة هي بمثابة الحصول على عنوان معين فقط هل تريد زيادة تحسين الدقة والكفاءة؟

إذا كانت معاملة نشر عقد ، فكيف يتم الحصول على الكود المنشور بعد تنفيذه مباشرة أو حتى عندما لا يزال في تجمع الذاكرة؟

إذا كانت المعاملة في وضع المصنع التعاقدي ، فهل هناك أي كود مصدر في Calldata للمعاملة؟

في النهاية ، طريقي هو التصنيف في وضع يشبه الغربال

  1. بالنسبة للمعاملات غير المنشورة بموجب عقد ، استخدم getCode مباشرةً للحصول على العناوين المتضمنة للتصنيف.
  2. بالنسبة لآخر معاملات تجمع الذاكرة ، قم بتصفية المعاملات التي يكون عنوانها فارغًا ، والتي يكون CallData الخاص بها هو كود المصدر مع المُنشئ
  3. بالنسبة لمعاملة وضع المصنع التعاقدي ، نظرًا لأن العقد الذي تم نشره بموجب العقد يمكن إعادة تدويره لاستدعاء عقود أخرى لتنفيذ النشر ، فإنه سيحلل بشكل متكرر المعاملات الفرعية للمعاملة ، ويسجل كل مكالمة من نوعها من النوع "إنشاء" أو CREATE2.

عندما أجريت تطبيقًا تجريبيًا ، وجدت أن إصدار rpc مرتفع نسبيًا الآن ، لأن أصعب جزء من العملية بأكملها هو كيفية العثور بشكل متكرر على استدعاء من النوع المحدد عند تنفيذ 3. طريقة المستوى السفلي هي استعادة السياق من خلال شفرة التشغيل. لقد فوجئت!

لحسن الحظ ، هناك طريقة debug \ _traceTransaction في إصدار geth الحالي ، والتي يمكن أن تساعد في فرز معلومات السياق لكل مكالمة من خلال كود تشغيل كود التشغيل ، وفرز الحقول الأساسية.

في النهاية ، يمكن الحصول على الرموز البايتية الأصلية لأنماط النشر المختلفة (النشر المباشر ، النشر الفردي في وضع المصنع ، نشر الدُفعات في وضع المصنع).

3.2 كيف تصنف من الكود؟

إن أبسط طريقة ولكنها غير آمنة هي إجراء مطابقة مباشرة للسلسلة مع الشفرة. وبأخذ ERC20 كمثال ، فإن الوظيفة التي تلبي المعيار

! [في عمق المخاطر الكامنة وراء الأمر التافه لتصنيف عقد EVM] (https://img.gateio.im/social/moments-40baef27dd-0534306c0a-dd1a6f-62a40f)

بعد اسم الوظيفة هو توقيع الوظيفة. كما هو مذكور في التحليل السابق ، تعتمد المعاملة على مطابقة الأرقام الأربعة الأولى من callData للعثور على الوظيفة الهدف. مزيد من القراءة:

لذلك ، يجب تخزين توقيعات هذه الوظائف الست في الرمز الثانوي للعقد.

بالطبع ، هذه الطريقة سريعة جدًا ويمكنك العثور على كل 6 ، لكن العامل غير الآمن هو أنه إذا استخدمت عقد الصلابة وتصميم متغير بقيمة تخزين 0x18160ddd ، فسيعتقد أن لدي هذه الوظيفة.

3.3. تحسين معدل الدقة 1- إلغاء الترجمة

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

الصلابة (لغة عالية المستوى) -> الرمز الثانوي (الرمز الثانوي) -> كود التشغيل (رمز التشغيل)

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

! [في أعماق المخاطر الكامنة وراء الأمر التافه لتصنيف عقد EVM] (https://img.gateio.im/social/moments-40baef27dd-73d9b6214a-dd1a6f-62a40f)

لقد أجريت أيضًا تجربة أداء بسيطة ، ويجب أن أقول إن لغة Go فعالة للغاية ، ولا تستغرق سوى 220 مللي ثانية مقابل 10000 مرة من إلغاء الترجمة.

ما يلي سيكون صعبًا

3.4. تحسين معدل الدقة 2- البحث عن كتلة التعليمات البرمجية

تم تحسين معدل الدقة أعلاه ولكن ليس كافيًا ، لأنه بحث عن نص كامل PUSH4 ، لأنه لا يزال بإمكاننا إنشاء متغير ، وهو من النوع byte4 ، والذي سيؤدي أيضًا إلى تشغيل الأمر PUSH4.

عندما شعرت بالضيق ، فكرت في تنفيذ بعض المشاريع مفتوحة المصدر. ETL هي أداة لقراءة البيانات على السلسلة للتحليل. ستحلل نقل ERC20 و 721 إلى جداول منفصلة ، لذلك يجب أن يكون لديها القدرة على التصنيف انكماش.

! [في أعماق المخاطر الكامنة وراء الأمر التافه لتصنيف عقد EVM] (https://img.gateio.im/social/moments-40baef27dd-fd43dc33ea-dd1a6f-62a40f)

بعد التحليل ، يمكن العثور على أنه يعتمد على تصنيف كتل التعليمات البرمجية ويعالج فقط الكتل الأساسية الأولى \ _الكتل [0] تعليمات push4 في

** يأتي السؤال ، كيف نحكم بدقة على كتلة الكود **

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

! [في أعماق المخاطر الكامنة وراء الأمر التافه لتصنيف عقد EVM] (https://img.gateio.im/social/moments-40baef27dd-d2918eb54a-dd1a6f-62a40f)

3.5. تحسين معدل الدقة 3-البحث عن محدد الوظيفة

وظيفة محدد الوظيفة هي قراءة أول 4 بايتات من Calldata للمعاملة ، ومطابقتها مع توقيع وظيفة العقد المحدد مسبقًا في الكود ، ومساعدة التعليمات للانتقال إلى موقع الذاكرة المحدد بواسطة طريقة الوظيفة

لنجرب الحد الأدنى من التنفيذ الوهمي

هذا الجزء هو مخزن المحدد (uint 256) واسترداد () من الوظيفتين ، ويمكن حساب التوقيع على أنه 2e64cec1، 6057361d

! [في عمق المخاطر الكامنة وراء الأمر التافه لتصنيف عقد EVM] (https://img.gateio.im/social/moments-40baef27dd-f39503befa-dd1a6f-62a40f)

بعد فك التحويل ، ستحصل على سلسلة كود التشغيل التالية ، والتي يمكن القول أنها مقسمة إلى جزأين

الجزء الاول:

في المترجم ، سيحصل جزء محدد الوظيفة فقط من العقد على محتوى callData ، مما يعني الحصول على توقيع استدعاء الوظيفة لـ CallData الخاص به ، كما هو موضح في الشكل أدناه.

! [في أعماق المخاطر الكامنة وراء الأمر التافه لتصنيف عقد EVM] (https://img.gateio.im/social/moments-40baef27dd-6ef58e385a-dd1a6f-62a40f)

يمكننا أن نرى التأثير من خلال محاكاة تغيير مجموعة ذاكرة EVM

! [في عمق المخاطر الكامنة وراء الأمر التافه لتصنيف عقد EVM] (https://img.gateio.im/social/moments-40baef27dd-f2c6fd1270-dd1a6f-62a40f)

الجزء الثاني:

عملية الحكم على ما إذا كانت تتطابق مع قيمة المحدد

  1. قم بتمرير توقيع دالة 4 بايت (0x2e64cec1) لاسترداد () إلى المكدس ،

  2. ينبثق كود التشغيل EQ متغيرين من منطقة المكدس ، وهما 0x2e64cec1 و 0x6057361d ، ويتحقق مما إذا كانا متساويين

  3. ينقل PUSH2 2 بايت من البيانات (0x003b هنا ، 59 في النظام العشري) إلى المكدس.يوجد عداد برنامج في منطقة المكدس ، والذي يحدد موضع أمر التنفيذ التالي في رمز بايت. هنا قمنا بتعيين 59 لأن هذا هو المكان الذي يبدأ فيه رمز الاسترداد ()

  4. يرمز JUMPI إلى "الانتقال إلى إذا ..." ، ويخرج قيمتين من المكدس كمدخلات ، وإذا كان الشرط صحيحًا ، فسيتم تحديث عداد البرنامج إلى 59.

هذه هي الطريقة التي تحدد بها أداة EVM موقع الرمز الثانوي للوظيفة التي تحتاج إلى تنفيذها بناءً على استدعاء الوظيفة في العقد.

في الواقع ، هذه مجرد مجموعة بسيطة من "عبارات if" لكل وظيفة في العقد وأين ينتقلون إليها.

! [في أعماق المخاطر الكامنة وراء الأمر التافه لتصنيف عقد EVM] (https://img.gateio.im/social/moments-40baef27dd-7ed0aa7c33-dd1a6f-62a40f)

4. ملخص المخطط

الموجز العام على النحو التالي

  1. يمكن لكل عنوان عقد الحصول على الرمز الثانوي بعد النشر من خلال rpcgetcode أو debug \ _traceTransaction ، باستخدام مكتبات VM و ASM في GO ، والحصول على كود التشغيل بعد فك التجميع
  2. وفقًا لمبدأ تشغيل EVM ، سيكون للعقد الخصائص التالية
  • استخدم REVERT + JUMPDEST لتمييز كتلة التعليمات البرمجية
  • يجب أن يحتوي العقد على وظيفة محدد الوظيفة ، ويجب أن تكون هذه الوظيفة أيضًا في أول كتلة رمز
  • في محدد الوظيفة ، تستخدم جميع أساليب وظيفتها PUSH4 كرمز تشغيل ،
  • في كود التشغيل المضمن في هذا المحدد ، سيكون هناك PUSH1 00 متتالي ؛ CALLDATALOAD ؛ PUSH1 e0 ؛ SHR ؛ DUP1. تتمثل الوظيفة الأساسية في تحميل بيانات تاريخ المكالمة وتنفيذ عمليات الإزاحة. من وظيفة العقد ، لن يتم إنشاء بناء جملة آخر
  1. يتم تعريف توقيع الوظيفة المقابلة في eip ، وهناك تعليمات واضحة إلزامية واختيارية

4.1. إثبات التفرد

في هذه المرحلة ، يمكننا القول إن طريقة تحليل العقود عالية الكفاءة والدقة قد تحققت بشكل أساسي. بالطبع ، نظرًا لأنها كانت صارمة لفترة طويلة ، فقد نكون أكثر صرامة. في المخطط أعلاه ، نحن استخدم REVER + JUMPDEST لتمييز كتل التعليمات البرمجية ، ودمج تحميل CallDate الحتمي والإزاحة لإصدار حكم فريد. هل يمكنني استخدام عقد متانة لتنفيذ تسلسل شفرة تشغيل مماثل؟

قمت بتجربة تحكم بالرغم من وجود طرق للحصول على CallData مثل msg.sig من مستوى قواعد الصلابة ، إلا أن طرق تنفيذ كود التشغيل بعد التجميع مختلفة.

! [في أعماق المخاطر الكامنة وراء الأمر التافه لتصنيف عقد EVM] (https://img.gateio.im/social/moments-40baef27dd-059e61ce9f-dd1a6f-62a40f)

شاهد النسخة الأصلية
المحتوى هو للمرجعية فقط، وليس دعوة أو عرضًا. لا يتم تقديم أي مشورة استثمارية أو ضريبية أو قانونية. للمزيد من الإفصاحات حول المخاطر، يُرجى الاطلاع على إخلاء المسؤولية.
  • أعجبني
  • تعليق
  • مشاركة
تعليق
0/400
لا توجد تعليقات
  • تثبيت