Reversing Ethereum Smart Contracts to find out what's behind EVM bytecode (Devcon4)

Devcon 4 · 11 Dec 2018 · 18:59

This Devcon4 talk covers reverse engineering Ethereum smart contracts, working backward from raw EVM bytecode to understand what a deployed contract actually does when its source code isn't available. It covers the tools and techniques involved in that kind of bytecode level analysis.

Speakers

Topics

From Devcon 4, hosted by Ethereum Foundation.

Transcript

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

بالبلوكشين بدأت لأنني كنت أعمل على تتبع معاملات البلوكشين وما شابه، ولهذا السبب احتجت لتحليل الكود المصدري (Bytecode) مثل عمليات التدمير الذاتي وغيرها، ومن هنا بدأت مشروعي الذي يسمى Octopus. إنه إطار عمل لتحليل الأمان. أنا أدعم EVM بالطبع، لكني أدعم أيضاً منصات أخرى مثل EOS و Neo. لذا إذا أردتم إلقاء نظرة على كود العقود الذكية لـ NEO و

EOS، فقد تكون هذه فرصة جيدة، ولنبدأ. سأقدم مقدمة سريعة ثم سأتحدث عن مخطط تدفق التحكم، ولماذا نحتاج إلى استخدام الهندسة العكسية في مرحلة ما، ومن وجهة نظر المطور لماذا قد تحتاج لاستخدامها. عادةً ما تكون الهندسة العكسية للعقود الذكية بسيطة للغاية. الهدف هو أن تمتلك كود EVM وتريد ترجمته إلى لغة التجميع (Assembly)، وعملية الهندسة العكسية للعقد الذكي تكون عادةً بتحليل كود التجميع هذا. إذا

ألقيت نظرة على الكود، فيمكنك أن تجد نوعين من أكواد EVM. الأول سيكون هذا النوع الكبير الذي يحتوي على كود التحميل (Loader code). في الواقع، كود التحميل هو المسؤول عن دفع كود وقت التشغيل ( Runtime code) إلى البلوكشين . غالباً ما يظهر هذا النمط إذا نظرت إلى معاملات إنشاء العقود وإذا فحصت بيانات الإدخال. في تلك الحالات ستحصل على كود التحميل، ونحن نهتم أكثر بكود وقت التشغيل الذي سيكون الكود النهائي لعقدك الذكي.

هذا الكود هو الذي سيتم تشغيله داخل EVM. لن أقضي الكثير من الوقت في هذا. وهكذا دواليك. الخطوة الأولى هي أننا بحاجة إلى تفكيك الكود (Disassemble). وهو أمر بسيط للغاية. ربما رأى بعضكم أداة Opcode من Etherscan، وهذا هو بالضبط ما تفعله. إنه أشبه بمفكك تجميع أساسي. وطريقة عمله، فك التجميع بشكل عام يتطلب وجود علاقة بين كود العملية (op code) وتعليمات EVM. عادةً ما تأخذ مجموعة تعليمات EVM وتقوم بالمطابقة،

وهذا يفي بالغرض. الجزء الأكثر تعقيداً سيكون حول مخطط تدفق التحكم (Control Flow Graph). لأولئك الذين لا يستخدمون أدوات مثل Binary Ninja أو IDA، مخطط تدفق التحكم هو تمثيل مرئي لمنطق برنامجك. عادةً إذا كان لديك شرط (if else) وما شابه، يمكنك تحديده مباشرة بناءً على التمثيل المرئي، وفي أغلب الحالات ستحتاج لإنشاء كتل (أو عقد) وروابط بين تلك الكتل.

لذلك، هناك بعض التعليمات الحاسمة التي تساعدك في إعادة إنشاء مخطط تدفق التحكم (CFG). هذه التعليمات، وبالأخص أول اثنتين، هي الجواهر الحقيقية بالطبع. فهي تساعدك على إنشاء الروابط، والأخرى تساعدك على تفكيك تجميع EVM المضمن إلى كتل أساسية. ولتبسيط الأمر، سيبدو هكذا قبل وبعد، والخطوة التالية هي إجراء الربط بين تلك الكتل الأساسية. إذا أخذنا فكرة أساسية، وهي أنني أريد إجراء

تحليل ثابت، سأتحقق مما إذا كانت التعليمات قبل القفز ( jump) هي تعليمات دفع (push) تضع إزاحة وجهة القفز في المكدس. قد ينجح هذا . في الواقع، قد ينجح في 50 إلى 60%من الحالات، لكن في مرحلة ما ستواجه مشكلة، وعادة ما تحدث عند إجراء عمليات على المكدس. في هذه الحالات، يكون لديك كتلة أساسية واحدة، لا يوجد دفع فيها، ولديك عملية قفز (jump). لذا، إذا كنت لا تعرف القيمة الموجودة في أعلى المكدس، فلن تتمكن من تحديد إزاحة وجهة القفز. هناك

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

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

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

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

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

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

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

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

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

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

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

إنه أمر رائع حقاً وتطبيق نموذجي لذلك. سبب آخر، كشركة بالطبع لديك تدقيق أمني، لكنني سأتحدث عن ذلك لاحقاً، عذراً. سبب آخر يمكن أن يكون تحسين رمز البايت ( Bytecode). كم منكم يعتقد أن رمز البايت الخاص بـ EVM مُحسَّن؟ حسناً. جيد جداً. لا أعرف إن كان أي منكم قد رأى هذه التغريدة من ريان من Tra bits، حيث اكتشف أنه في مرحلة ما على البلوكشين، تستخدم الكثير من العقود الذكية الأسس (Exponentiation ) لحساب القيمة واحد.

الحقيقة هي أن الأسس تكلف 10 وحدات غاز. وهذا يعني أن الكثير من الناس ينفقون الغاز بلا داعٍ. وبشكل أكبر حتى. إذا كانت وسيطات تعليمة الأسس ثابتة، يمكنك تبسيطها مباشرة عبر "دفع"(push) بسيط جداً . وإذا كانت إحدى الوسيطات صفراً أو واحداً، يمكنك حساب القيمة مباشرة عند... عند التجميع، أو تعديلها مباشرة بواسطة متغير وقت التشغيل. لذا فهي حالات أكثر تحديداً،

لكنها تعمل بشكل جيد، وقد أجرى مارتن من مؤسسة إيثيريوم بعض الاختبارات حول هذا الافتراض وكرره على 16 كتلة عشوائية، ووجد أن 73%من جميع عمليات استدعاء الأسس يمكن تبسيطها وتحسينها. لذا ، بدأ الأمر يصبح شيئاً مهماً في الواقع . لا أعرف ما إذا كانت هناك تعديلات مباشرة على مترجم Solidity لإصلاح ذلك، أو ربما إذا استخدمت علامة التحسين، فهل يتغير شيء؟ لا أعرف. لم أستغرق الوقت للتحقق من ذلك، لكننا بالتأكيد نحتاج ربما

لإخبار مطوري Solidity بأن هناك بعض التحسينات التي يجب القيام بها في هذا الجزء. سبب آخر أكثر شهرة هو عادة التدقيق الأمني، والبحث عن الأخطاء، وأبحاث الثغرات الأمنية. والحقيقة أنني لا أعرف إن كان أي منكم يستخدم أياً من هذه الأدوات. أنا متأكد من أن بعضكم يفعل ذلك. وعادةً ما تستخدم هذه الأدوات رمز البايت الخاص بـ EVM مباشرة للقيام بتحليلها. إذن، السبب في ذلك، ومعظمها يستخدم كشف مطابقة الأنماط للثغرات، هو أن كود EVM المترجم ( Bytecode) هو ما يتم تخزينه على البلوكشين. وفي

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

العقود الذكية لنقل أموالها دون أن يتم كشفها، وهي تقنيات مشابهة لما استخدمه " جاي" قبلي في تحليل ما بعد تنفيذ العقود الذكية. فإذا كان لديك عقد ذكي يتم تدميره وقمت بالدخول على مستكشف البلوكشين، فسترى ذلك وستشعر بخيبة أمل. لكن الحقيقة، وكما أخبرتكم، أن كود العقد الذكي وكود التشغيل ( Runtime code) متاحان مباشرة في مدخلات إنشاء العقد الذكي. لذا إذا ألقيت نظرة على هذه المعاملة ، ستحصل على كود

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

عرضاً حول تحليل تطبيق "العالم الموازي"(L-world) من شركة Parity Technology، فقد يكون ذلك مثيراً لاهتمام البعض منكم. قد تجدون فيه فائدة لكم. وقد قدمت ورشة عمل مؤخراً حول كيفية إنشاء أنماط لاكتشاف أنواع معينة من الثغرات. كل شيء متاح مباشرة عبر الرابط. شكراً لكم.