اسمارٹ کنٹریکٹ بگز کو تلاش کرنے کے لیے Slither کا استعمال کیسے کریں
Slither کا استعمال کیسے کریں
اس ٹیوٹوریل کا مقصد یہ دکھانا ہے کہ اسمارٹ کنٹریکٹس میں بگز کو خود بخود تلاش کرنے کے لیے Slither کا استعمال کیسے کیا جائے۔
- انسٹالیشن
- کمانڈ لائن کا استعمال
- اسٹیٹک تجزیہ کا تعارف: اسٹیٹک تجزیہ کا مختصر تعارف
- API: پائتھن API کی تفصیل
انسٹالیشن
Slither کے لیے Python >= 3.6 درکار ہے۔ اسے pip کے ذریعے یا docker کا استعمال کرکے انسٹال کیا جاسکتا ہے۔
pip کے ذریعے Slither:
pip3 install --user slither-analyzerdocker کے ذریعے Slither:
docker pull trailofbits/eth-security-toolboxdocker run -it -v "$PWD":/home/trufflecon trailofbits/eth-security-toolboxآخری کمانڈ eth-security-toolbox کو ایک docker میں چلاتا ہے جس کی آپ کی موجودہ ڈائریکٹری تک رسائی ہے۔ آپ اپنے ہوسٹ سے فائلیں تبدیل کر سکتے ہیں، اور docker سے فائلوں پر ٹولز چلا سکتے ہیں
docker کے اندر، چلائیں:
solc-select 0.5.11cd /home/trufflecon/ایک اسکرپٹ چلانا
python 3 کے ساتھ ایک python اسکرپٹ چلانے کے لیے:
python3 script.pyکمانڈ لائن
کمانڈ لائن بمقابلہ صارف کے ذریعے متعین کردہ اسکرپٹس۔ Slither پہلے سے متعین ڈیٹیکٹرز کے ایک سیٹ کے ساتھ آتا ہے جو بہت سے عام بگز کو تلاش کرتے ہیں۔ کمانڈ لائن سے Slither کو کال کرنے پر تمام ڈیٹیکٹرز چل جائیں گے، اسٹیٹک تجزیہ کے تفصیلی علم کی ضرورت نہیں:
slither project_pathsڈیٹیکٹرز کے علاوہ، Slither میں اس کے پرنٹرزopens in a new tab اور ٹولزopens in a new tab کے ذریعے کوڈ ریویو کی صلاحیتیں ہیں۔
پرائیویٹ ڈیٹیکٹرز اور GitHub انٹیگریشن تک رسائی حاصل کرنے کے لیے crytic.ioopens in a new tab کا استعمال کریں۔
اسٹیٹک تجزیہ
Slither اسٹیٹک تجزیہ فریم ورک کی صلاحیتوں اور ڈیزائن کو بلاگ پوسٹس (1opens in a new tab, 2opens in a new tab) اور ایک تعلیمی مقالےopens in a new tab میں بیان کیا گیا ہے۔
اسٹیٹک تجزیہ مختلف اقسام میں موجود ہے۔ آپ کو شاید اس بات کا احساس ہوگا کہ clangopens in a new tab اور gccopens in a new tab جیسے کمپائلرز ان تحقیقی تکنیکوں پر انحصار کرتے ہیں، لیکن یہ (Inferopens in a new tab, CodeClimateopens in a new tab, FindBugsopens in a new tab اور Frama-Copens in a new tab اور Polyspaceopens in a new tab جیسے رسمی طریقوں پر مبنی ٹولز) کی بھی بنیاد ہے۔
ہم یہاں اسٹیٹک تجزیہ کی تکنیکوں اور محققین کا جامع طور پر جائزہ نہیں لیں گے۔ اس کے بجائے، ہم اس بات پر توجہ مرکوز کریں گے کہ Slither کے کام کرنے کے طریقے کو سمجھنے کے لیے کیا ضروری ہے تاکہ آپ بگز کو تلاش کرنے اور کوڈ کو سمجھنے کے لیے اس کا زیادہ مؤثر طریقے سے استعمال کر سکیں۔
کوڈ کی نمائندگی
ڈائنامک تجزیہ کے برعکس، جو ایک ہی ایگزیکیوشن پاتھ کے بارے میں استدلال کرتا ہے، اسٹیٹک تجزیہ ایک ہی وقت میں تمام پاتھس کے بارے میں استدلال کرتا ہے۔ ایسا کرنے کے لیے، یہ ایک مختلف کوڈ کی نمائندگی پر انحصار کرتا ہے۔ دو سب سے عام ہیں ایبسٹریکٹ سنٹیکس ٹری (AST) اور کنٹرول فلو گراف (CFG)۔
ایبسٹریکٹ سنٹیکس ٹریز (AST)
AST کا استعمال ہر بار کیا جاتا ہے جب کمپائلر کوڈ کو پارس کرتا ہے۔ یہ شاید سب سے بنیادی ڈھانچہ ہے جس پر اسٹیٹک تجزیہ کیا جا سکتا ہے۔
مختصراً، ایک AST ایک سٹرکچرڈ ٹری ہے جہاں، عام طور پر، ہر لیف میں ایک ویری ایبل یا ایک کانسٹنٹ ہوتا ہے اور انٹرنل نوڈز آپرینڈز یا کنٹرول فلو آپریشنز ہوتے ہیں۔ درج ذیل کوڈ پر غور کریں:
1function safeAdd(uint a, uint b) pure internal returns(uint){2 if(a + b <= a){3 revert();4 }5 return a + b;6}متعلقہ AST کو اس میں دکھایا گیا ہے:
Slither, solc کے ذریعے ایکسپورٹ کردہ AST کا استعمال کرتا ہے۔
بنانے میں آسان ہونے کے باوجود، AST ایک نیسٹڈ سٹرکچر ہے۔ بعض اوقات، اس کا تجزیہ کرنا سب سے سیدھا نہیں ہوتا ہے۔ مثال کے طور پر، ایکسپریشن a + b <= a کے ذریعے استعمال ہونے والے آپریشنز کی شناخت کے لیے، آپ کو پہلے <= اور پھر + کا تجزیہ کرنا ہوگا۔ ایک عام طریقہ نام نہاد وزیٹر پیٹرن کا استعمال کرنا ہے، جو ٹری کے ذریعے ریکرسیولی نیویگیٹ کرتا ہے۔ Slither میں ExpressionVisitoropens in a new tab میں ایک عام وزیٹر موجود ہے۔
درج ذیل کوڈ ExpressionVisitor کا استعمال کرتا ہے یہ پتہ لگانے کے لیے کہ آیا ایکسپریشن میں کوئی ایڈیشن ہے:
1from slither.visitors.expression.expression import ExpressionVisitor2from slither.core.expressions.binary_operation import BinaryOperationType34class HasAddition(ExpressionVisitor):56 def result(self):7 return self._result89 def _post_binary_operation(self, expression):10 if expression.type == BinaryOperationType.ADDITION:11 self._result = True1213visitor = HasAddition(expression) # expression is the expression to be tested14print(f'The expression {expression} has a addition: {visitor.result()}')سب دکھائیںکنٹرول فلو گراف (CFG)
دوسری سب سے عام کوڈ کی نمائندگی کنٹرول فلو گراف (CFG) ہے۔ جیسا کہ اس کے نام سے ظاہر ہے، یہ ایک گراف پر مبنی نمائندگی ہے جو تمام ایگزیکیوشن پاتھس کو ظاہر کرتی ہے۔ ہر نوڈ میں ایک یا ایک سے زیادہ ہدایات ہوتی ہیں۔ گراف میں ایجز کنٹرول فلو آپریشنز (if/then/else, loop, وغیرہ) کی نمائندگی کرتے ہیں۔ ہماری پچھلی مثال کا CFG یہ ہے:
CFG وہ نمائندگی ہے جس کے اوپر زیادہ تر تجزیے بنائے جاتے ہیں۔
بہت سی دوسری کوڈ کی نمائندگیاں موجود ہیں۔ ہر نمائندگی کے اپنے فائدے اور نقصانات ہیں اس تجزیہ کے مطابق جو آپ کرنا چاہتے ہیں۔
تجزیہ
سب سے آسان قسم کے تجزیے جو آپ Slither کے ساتھ کر سکتے ہیں وہ سنٹیکٹک تجزیے ہیں۔
سنٹیکس کا تجزیہ
Slither پیٹرن میچنگ جیسے طریقے کا استعمال کرتے ہوئے تضادات اور خامیوں کو تلاش کرنے کے لیے کوڈ کے مختلف اجزاء اور ان کی نمائندگی کے ذریعے نیویگیٹ کر سکتا ہے۔
مثال کے طور پر درج ذیل ڈیٹیکٹرز سنٹیکس سے متعلقہ مسائل کو تلاش کرتے ہیں:
-
اسٹیٹ ویری ایبل شیڈونگopens in a new tab: تمام اسٹیٹ ویری ایبلز پر ایٹریٹ کرتا ہے اور چیک کرتا ہے کہ آیا کوئی موروثی کنٹریکٹ سے کسی ویری ایبل کو شیڈو کرتا ہے (state.py#L51-L62opens in a new tab)
-
غلط ERC20 انٹرفیسopens in a new tab: غلط ERC20 فنکشن سگنیچرز کو تلاش کرتا ہے (incorrect_erc20_interface.py#L34-L55opens in a new tab)
سیمنٹک تجزیہ
سنٹیکس تجزیہ کے برعکس، ایک سیمنٹک تجزیہ زیادہ گہرائی میں جائے گا اور کوڈ کے "معنی" کا تجزیہ کرے گا۔ اس فیملی میں کچھ وسیع اقسام کے تجزیے شامل ہیں۔ یہ زیادہ طاقتور اور مفید نتائج کی طرف لے جاتے ہیں، لیکن لکھنے میں بھی زیادہ پیچیدہ ہیں۔
سیمنٹک تجزیے سب سے جدید کمزوریوں کا پتہ لگانے کے لیے استعمال کیے جاتے ہیں۔
ڈیٹا کا انحصاری تجزیہ
ایک ویری ایبل variable_a کو variable_b پر ڈیٹا-ڈیپینڈینٹ کہا جاتا ہے اگر کوئی ایسا پاتھ ہے جس کے لیے variable_a کی قدر variable_b سے متاثر ہوتی ہے۔
درج ذیل کوڈ میں، variable_a، variable_b پر منحصر ہے:
1// ...2variable_a = variable_b + 1;Slither بلٹ ان ڈیٹا ڈیپینڈینسیopens in a new tab کی صلاحیتوں کے ساتھ آتا ہے، اس کی درمیانی نمائندگی کی بدولت (جس پر بعد کے سیکشن میں بحث کی گئی ہے)۔
ڈیٹا ڈیپینڈینسی کے استعمال کی ایک مثال خطرناک سخت مساوات ڈیٹیکٹرopens in a new tab میں مل سکتی ہے۔ یہاں Slither ایک خطرناک قدر کے ساتھ سخت مساوات کے موازنہ کو تلاش کرے گا (incorrect_strict_equality.py#L86-L87opens in a new tab)، اور صارف کو مطلع کرے گا کہ اسے کسی حملہ آور کو کنٹریکٹ میں پھنسانے سے روکنے کے لیے == کے بجائے >= یا <= کا استعمال کرنا چاہیے۔ دیگر چیزوں کے علاوہ، ڈیٹیکٹر balanceOf(address) (incorrect_strict_equality.py#L63-L64opens in a new tab) پر کال کی واپسی کی قدر کو خطرناک سمجھے گا، اور اس کے استعمال کو ٹریک کرنے کے لیے ڈیٹا ڈیپینڈینسی انجن کا استعمال کرے گا۔
فکسڈ پوائنٹ کمپیوٹیشن
اگر آپ کا تجزیہ CFG کے ذریعے نیویگیٹ کرتا ہے اور ایجز کی پیروی کرتا ہے، تو آپ کو پہلے سے دیکھے گئے نوڈس نظر آنے کا امکان ہے۔ مثال کے طور پر، اگر ایک لوپ کو نیچے دکھایا گیا ہے:
1for(uint i; i < range; ++){2 variable_a += 13}آپ کے تجزیہ کو یہ جاننے کی ضرورت ہوگی کہ کب رکنا ہے۔ یہاں دو اہم حکمت عملیاں ہیں: (1) ہر نوڈ پر ایک محدود تعداد میں ایٹریٹ کریں، (2) ایک نام نہاد فکس پوائنٹ کا حساب لگائیں۔ ایک فکس پوائنٹ کا بنیادی طور پر مطلب ہے کہ اس نوڈ کا تجزیہ کوئی بامعنی معلومات فراہم نہیں کرتا ہے۔
فکس پوائنٹ کے استعمال کی ایک مثال ری اینٹرینسی ڈیٹیکٹرز میں مل سکتی ہے: Slither نوڈس کو ایکسپلور کرتا ہے، اور ایکسٹرنل کالز، اسٹوریج میں لکھنے اور پڑھنے کی تلاش کرتا ہے۔ ایک بار جب یہ فکس پوائنٹ (reentrancy.py#L125-L131opens in a new tab) تک پہنچ جاتا ہے، تو یہ ایکسپلوریشن کو روک دیتا ہے، اور نتائج کا تجزیہ کرتا ہے یہ دیکھنے کے لیے کہ آیا ری اینٹرینسی موجود ہے، مختلف ری اینٹرینسی پیٹرنز (reentrancy_benign.pyopens in a new tab, reentrancy_read_before_write.pyopens in a new tab, reentrancy_eth.pyopens in a new tab) کے ذریعے۔
موثر فکسڈ پوائنٹ کمپیوٹیشن کا استعمال کرتے ہوئے تجزیے لکھنے کے لیے اس بات کی اچھی سمجھ کی ضرورت ہوتی ہے کہ تجزیہ اپنی معلومات کو کیسے پھیلاتا ہے۔
درمیانی نمائندگی
ایک درمیانی نمائندگی (IR) ایک ایسی زبان ہے جو اصل زبان کے مقابلے میں اسٹیٹک تجزیہ کے لیے زیادہ موزوں ہو۔ Slither, Solidity کو اپنے IR: SlithIRopens in a new tab میں ترجمہ کرتا ہے۔
اگر آپ صرف بنیادی چیکس لکھنا چاہتے ہیں تو SlithIR کو سمجھنا ضروری نہیں ہے۔ تاہم، اگر آپ جدید سیمنٹک تجزیے لکھنے کا ارادہ رکھتے ہیں تو یہ کام آئے گا۔ SlithIRopens in a new tab اور SSAopens in a new tab پرنٹرز آپ کو یہ سمجھنے میں مدد کریں گے کہ کوڈ کا ترجمہ کیسے ہوتا ہے۔
API کی بنیادی باتیں
Slither میں ایک API ہے جو آپ کو کنٹریکٹ اور اس کے فنکشنز کی بنیادی خصوصیات کو ایکسپلور کرنے دیتا ہے۔
کوڈبیس کو لوڈ کرنے کے لیے:
1from slither import Slither2slither = Slither('/path/to/project')3کنٹریکٹس اور فنکشنز کو ایکسپلور کرنا
ایک Slither آبجیکٹ میں ہوتا ہے:
contracts (list(Contract): کنٹریکٹس کی فہرستcontracts_derived (list(Contract): ان کنٹریکٹس کی فہرست جو کسی دوسرے کنٹریکٹ سے موروثی نہیں ہیں (کنٹریکٹس کا سب سیٹ)get_contract_from_name (str): اس کے نام سے ایک کنٹریکٹ واپس کریں
ایک Contract آبجیکٹ میں ہوتا ہے:
name (str): کنٹریکٹ کا نامfunctions (list(Function)): فنکشنز کی فہرستmodifiers (list(Modifier)): فنکشنز کی فہرستall_functions_called (list(Function/Modifier)): کنٹریکٹ کے ذریعے پہنچنے کے قابل تمام اندرونی فنکشنز کی فہرستinheritance (list(Contract)): موروثی کنٹریکٹس کی فہرستget_function_from_signature (str): اس کے سگنیچر سے ایک فنکشن واپس کریںget_modifier_from_signature (str): اس کے سگنیچر سے ایک موڈیفائر واپس کریںget_state_variable_from_name (str): اس کے نام سے ایک اسٹیٹ ویری ایبل واپس کریں
ایک Function یا Modifier آبجیکٹ میں ہوتا ہے:
name (str): فنکشن کا نامcontract (contract): وہ کنٹریکٹ جہاں فنکشن کا اعلان کیا گیا ہےnodes (list(Node)): فنکشن/موڈیفائر کے CFG کو بنانے والے نوڈس کی فہرستentry_point (Node): CFG کا انٹری پوائنٹvariables_read (list(Variable)): پڑھے گئے ویری ایبلز کی فہرستvariables_written (list(Variable)): لکھے گئے ویری ایبلز کی فہرستstate_variables_read (list(StateVariable)): پڑھے گئے اسٹیٹ ویری ایبلز کی فہرست (ویری ایبلز`ریڈ کا سب سیٹ)state_variables_written (list(StateVariable)): لکھے گئے اسٹیٹ ویری ایبلز کی فہرست (ویری ایبلز`رٹن کا سب سیٹ)
صفحہ کی آخری تازہ کاری: 3 فروری، 2025

