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

تصنيف العقود هو حجر الزاوية في البورصات والمحافظ ومتصفحات blockchain ومنصات تحليل البيانات وما إلى ذلك.

** بقلم: أربعة عشر يونيو **

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

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

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

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

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

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

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

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

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

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

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

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

قراءة موسعة للفقرة 1: [تفسير العقد] CryptoPunk هو أقدم سوق تداول لا مركزي في العالم باستخدام NFT

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

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

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

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

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

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

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

قراءة موسعة للفقرة 2.2: [تفسير رمز المصدر] ما هو NFT الذي اشتريته بالضبط؟

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

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

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

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

** 3.1. كيف أحصل على الرمز؟ **

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

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

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

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

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

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

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

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

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

** 3.2 كيف تصنف حسب الكود؟ **

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

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

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

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

** 3.3 ، زيادة معدل الدقة 1- إلغاء الترجمة **

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

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

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

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

ما يلي سيكون صعبًا إلى حد ما.

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

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

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

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

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

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

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

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

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

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

60003560e01c80632e64cec11461003b5780636057361d1461005957

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

الجزء الاول:

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

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

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

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

  • قم بتمرير توقيع وظيفة 4 بايت (0x2e64cec1) لاسترداد () إلى المكدس ،
  • ينبثق رمز تشغيل EQ متغيرين من منطقة المكدس ، وهما 0x2e64cec1 و 0x6057361d ، ويتحقق مما إذا كانا متساويين
  • ينقل PUSH2 2 بايت من البيانات (0x003b هنا ، 59 في النظام العشري) إلى المكدس. يوجد عداد برنامج في منطقة المكدس ، والذي يحدد موضع أمر التنفيذ التالي في رمز بايت. هنا قمنا بتعيين 59 لأن هذا هو المكان الذي يبدأ فيه رمز الاسترداد ()
  • يرمز JUMPI إلى "Jump to if ..." ، ويخرج قيمتين من المكدس كمدخلات ، وإذا كان الشرط صحيحًا ، فسيتم تحديث عداد البرنامج إلى 59.

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

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

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

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

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

** 4.1 ، دليل على التفرد **

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

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

** 5. ملخص **

بعد هذا التحليل البليغ ، مرت 3 أيام.

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

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

فقط من خلال مبدأ عدم الثقة يمكننا المضي قدمًا في عالم web3.

اليوم ، سألني أحد الأصدقاء عن موضوع مثير للتفكير ، ما هي النتيجة النهائية لكونك شركة KOL؟ ما هو نموذج عملك؟

على الرغم من أنني أعلم أن حركة المقالات الفنية دائمًا ما تكون قاتمة ، لكن الازدحام ليس الغرض. أتمنى أن يكون دائمًا على الرؤية الأصلية:

💡 من منظور التكنولوجيا ، اكتساب نظرة ثاقبة على التغييرات الرئيسية في التنمية الصناعية ، وتبادل الخبرات السابقة والفرص المستقبلية في التنمية الصناعية ، وتقديم مساعدة متمايزة للبناة في العصر الجديد.

** الملحق **

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

مكتبة تابعة:

تحليل المبدأ:

مرجع كود مصدر مشروع مفتوح المصدر:

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