مرکزی مواد پر جائیں

اسمارٹ کانٹریکٹ کے بگز تلاش کرنے کے لیے Slither کا استعمال کیسے کریں

Solidity
اسمارٹ کانٹریکٹس
سیکیورٹی
ٹیسٹنگ
ایڈوانسڈ
Trailofbits
۹ جون، ۲۰۲۰
9 منٹ کی پڑھائی

Slither کا استعمال کیسے کریں

اس ٹیوٹوریل کا مقصد یہ دکھانا ہے کہ اسمارٹ کانٹریکٹس میں خودکار طریقے سے بگز تلاش کرنے کے لیے Slither کا استعمال کیسے کیا جائے۔

انسٹالیشن

Slither کے لیے Python >= 3.6 درکار ہے۔ اسے pip کے ذریعے یا docker کا استعمال کرتے ہوئے انسٹال کیا جا سکتا ہے۔

pip کے ذریعے Slither:

pip3 install --user slither-analyzer

docker کے ذریعے Slither:

docker pull trailofbits/eth-security-toolbox
docker run -it -v "$PWD":/share trailofbits/eth-security-toolbox

آخری کمانڈ ایک docker میں eth-security-toolbox چلاتی ہے جسے آپ کی موجودہ ڈائرکٹری تک رسائی حاصل ہوتی ہے۔ آپ اپنے ہوسٹ سے فائلیں تبدیل کر سکتے ہیں، اور docker سے فائلوں پر ٹولز چلا سکتے ہیں

docker کے اندر، چلائیں:

cd /share

اسکرپٹ چلانا

python 3 کے ساتھ python اسکرپٹ چلانے کے لیے:

python3 script.py

کمانڈ لائن

کمانڈ لائن بمقابلہ صارف کے متعین کردہ اسکرپٹس۔ Slither پہلے سے طے شدہ ڈیٹیکٹرز کے ایک سیٹ کے ساتھ آتا ہے جو بہت سے عام بگز تلاش کرتے ہیں۔ کمانڈ لائن سے Slither کو کال کرنے سے تمام ڈیٹیکٹرز چلیں گے، اس کے لیے سٹیٹک اینالیسس کے تفصیلی علم کی ضرورت نہیں ہے:

slither project_paths

ڈیٹیکٹرز کے علاوہ، Slither میں اپنے printers (opens in a new tab) اور tools (opens in a new tab) کے ذریعے کوڈ کا جائزہ لینے کی صلاحیتیں موجود ہیں۔

نجی ڈیٹیکٹرز اور GitHub انضمام تک رسائی حاصل کرنے کے لیے crytic.io (opens in a new tab) کا استعمال کریں۔

سٹیٹک اینالیسس

Slither سٹیٹک اینالیسس فریم ورک کی صلاحیتوں اور ڈیزائن کو بلاگ پوسٹس (1 (opens in a new tab), 2 (opens in a new tab)) اور ایک اکیڈمک پیپر (opens in a new tab) میں بیان کیا گیا ہے۔

سٹیٹک اینالیسس مختلف اقسام میں موجود ہے۔ آپ کو غالباً اندازہ ہوگا کہ clang (opens in a new tab) اور gcc (opens in a new tab) جیسے کمپائلرز ان تحقیقی تکنیکوں پر انحصار کرتے ہیں، لیکن یہ (Infer (opens in a new tab)، CodeClimate (opens in a new tab)، FindBugs (opens in a new tab) اور رسمی طریقوں پر مبنی ٹولز جیسے Frama-C (opens in a new tab) اور Polyspace (opens in a new tab) کی بھی بنیاد ہے۔

ہم یہاں سٹیٹک اینالیسس کی تکنیکوں اور محققین کا تفصیلی جائزہ نہیں لیں گے۔ اس کے بجائے، ہم اس بات پر توجہ مرکوز کریں گے کہ Slither کے کام کرنے کے طریقے کو سمجھنے کے لیے کیا ضروری ہے تاکہ آپ اسے بگز تلاش کرنے اور کوڈ کو سمجھنے کے لیے زیادہ مؤثر طریقے سے استعمال کر سکیں۔

کوڈ کی نمائندگی

ڈائنامک اینالیسس کے برعکس، جو ایک ہی ایگزیکیوشن پاتھ کے بارے میں استدلال کرتا ہے، سٹیٹک اینالیسس ایک ہی وقت میں تمام پاتھس کے بارے میں استدلال کرتا ہے۔ ایسا کرنے کے لیے، یہ ایک مختلف کوڈ کی نمائندگی پر انحصار کرتا ہے۔ دو سب سے عام نمائندگیاں ایبسٹریکٹ سنٹیکس ٹری (AST) اور کنٹرول فلو گراف (CFG) ہیں۔

ایبسٹریکٹ سنٹیکس ٹریز (AST)

جب بھی کمپائلر کوڈ کو پارس کرتا ہے تو AST کا استعمال کیا جاتا ہے۔ یہ شاید وہ سب سے بنیادی ڈھانچہ ہے جس پر سٹیٹک اینالیسس کیا جا سکتا ہے۔

مختصراً، ایک AST ایک ساختی درخت (structured tree) ہے جہاں، عام طور پر، ہر پتے (leaf) میں ایک متغیر (variable) یا مستقل (constant) ہوتا ہے اور اندرونی نوڈز آپرینڈز یا کنٹرول فلو آپریشنز ہوتے ہیں۔ درج ذیل کوڈ پر غور کریں:

1function safeAdd(uint a, uint b) pure internal returns(uint){
2 if(a + b <= a){
3 revert();
4 }
5 return a + b;
6}

متعلقہ AST اس میں دکھایا گیا ہے:

AST

Slither solc کے ذریعے ایکسپورٹ کردہ AST کا استعمال کرتا ہے۔

اگرچہ اسے بنانا آسان ہے، لیکن AST ایک نیسٹڈ (nested) ڈھانچہ ہے۔ بعض اوقات، اس کا تجزیہ کرنا سب سے سیدھا کام نہیں ہوتا۔ مثال کے طور پر، ایکسپریشن a + b <= a کے ذریعے استعمال ہونے والے آپریشنز کی شناخت کرنے کے لیے، آپ کو پہلے <= اور پھر + کا تجزیہ کرنا ہوگا۔ ایک عام طریقہ نام نہاد وزیٹر پیٹرن (visitor pattern) کا استعمال کرنا ہے، جو درخت کے ذریعے بار بار (recursively) نیویگیٹ کرتا ہے۔ Slither میں ExpressionVisitor (opens in a new tab) میں ایک عام وزیٹر شامل ہے۔

درج ذیل کوڈ یہ پتہ لگانے کے لیے ExpressionVisitor کا استعمال کرتا ہے کہ آیا ایکسپریشن میں اضافہ (addition) شامل ہے:

1from slither.visitors.expression.expression import ExpressionVisitor
2from slither.core.expressions.binary_operation import BinaryOperationType
3
4class HasAddition(ExpressionVisitor):
5
6 def result(self):
7 return self._result
8
9 def _post_binary_operation(self, expression):
10 if expression.type == BinaryOperationType.ADDITION:
11 self._result = True
12
13visitor = HasAddition(expression) # ایکسپریشن وہ ایکسپریشن ہے جس کی جانچ کی جانی ہے
14print(f'The expression {expression} has a addition: {visitor.result()}')

کنٹرول فلو گراف (CFG)

کوڈ کی دوسری سب سے عام نمائندگی کنٹرول فلو گراف (CFG) ہے۔ جیسا کہ اس کے نام سے ظاہر ہے، یہ گراف پر مبنی نمائندگی ہے جو تمام ایگزیکیوشن پاتھس کو ظاہر کرتی ہے۔ ہر نوڈ میں ایک یا ایک سے زیادہ ہدایات ہوتی ہیں۔ گراف میں کنارے (Edges) کنٹرول فلو آپریشنز (if/then/else، لوپ، وغیرہ) کی نمائندگی کرتے ہیں۔ ہماری پچھلی مثال کا CFG یہ ہے:

CFG

CFG وہ نمائندگی ہے جس کی بنیاد پر زیادہ تر تجزیے بنائے جاتے ہیں۔

کوڈ کی اور بھی بہت سی نمائندگیاں موجود ہیں۔ آپ جو تجزیہ کرنا چاہتے ہیں اس کے لحاظ سے ہر نمائندگی کے فوائد اور نقصانات ہوتے ہیں۔

تجزیہ

Slither کے ساتھ آپ جو سب سے آسان قسم کے تجزیے کر سکتے ہیں وہ سنٹیکٹک (syntactic) تجزیے ہیں۔

سنٹیکس کا تجزیہ

Slither پیٹرن میچنگ جیسی اپروچ کا استعمال کرتے ہوئے تضادات اور خامیوں کو تلاش کرنے کے لیے کوڈ کے مختلف اجزاء اور ان کی نمائندگی کے ذریعے نیویگیٹ کر سکتا ہے۔

مثال کے طور پر درج ذیل ڈیٹیکٹرز سنٹیکس سے متعلق مسائل تلاش کرتے ہیں:

سیمینٹک تجزیہ

سنٹیکس کے تجزیے کے برعکس، ایک سیمینٹک تجزیہ زیادہ گہرائی میں جائے گا اور کوڈ کے "معنی" کا تجزیہ کرے گا۔ اس فیملی میں تجزیوں کی کچھ وسیع اقسام شامل ہیں۔ یہ زیادہ طاقتور اور مفید نتائج کا باعث بنتے ہیں، لیکن انہیں لکھنا بھی زیادہ پیچیدہ ہوتا ہے۔

سیمینٹک تجزیے سب سے جدید کمزوریوں (vulnerabilities) کا پتہ لگانے کے لیے استعمال ہوتے ہیں۔

ڈیٹا ڈیپینڈنسی کا تجزیہ

ایک ویری ایبل variable_a کو variable_b پر ڈیٹا پر منحصر (data-dependent) کہا جاتا ہے اگر کوئی ایسا پاتھ موجود ہو جس کے لیے variable_a کی قدر variable_b سے متاثر ہوتی ہو۔

درج ذیل کوڈ میں، variable_a کا انحصار variable_b پر ہے:

1// ...
2variable_a = variable_b + 1;

Slither اپنی درمیانی نمائندگی (جس پر بعد کے سیکشن میں بحث کی گئی ہے) کی بدولت بلٹ ان ڈیٹا ڈیپینڈنسی (opens in a new tab) کی صلاحیتوں کے ساتھ آتا ہے۔

ڈیٹا ڈیپینڈنسی کے استعمال کی ایک مثال خطرناک سخت برابری کے ڈیٹیکٹر (dangerous strict equality detector) (opens in a new tab) میں مل سکتی ہے۔ یہاں Slither کسی خطرناک قدر کے ساتھ سخت برابری کے موازنے کو تلاش کرے گا (incorrect_strict_equality.py#L86-L87 (opens in a new tab))، اور صارف کو مطلع کرے گا کہ اسے حملہ آور کو کانٹریکٹ میں پھنسانے سے روکنے کے لیے == کے بجائے >= یا <= کا استعمال کرنا چاہیے۔ دیگر چیزوں کے علاوہ، ڈیٹیکٹر balanceOf(address) پر کال کی ریٹرن ویلیو کو خطرناک سمجھے گا (incorrect_strict_equality.py#L63-L64 (opens in a new tab))، اور اس کے استعمال کو ٹریک کرنے کے لیے ڈیٹا ڈیپینڈنسی انجن کا استعمال کرے گا۔

فکسڈ پوائنٹ کیلکولیشن

اگر آپ کا تجزیہ CFG کے ذریعے نیویگیٹ کرتا ہے اور کناروں (edges) کی پیروی کرتا ہے، تو آپ کو پہلے سے دیکھے گئے نوڈز نظر آنے کا امکان ہے۔ مثال کے طور پر، اگر کوئی لوپ نیچے دکھائے گئے طریقے سے پیش کیا گیا ہے:

1for(uint i; i < range; ++i){
2 variable_a += 1
3}

آپ کے تجزیے کو یہ جاننے کی ضرورت ہوگی کہ کب رکنا ہے۔ یہاں دو اہم حکمت عملیاں ہیں: (1) ہر نوڈ پر ایک محدود تعداد میں اعادہ (iterate) کریں، (2) ایک نام نہاد فکس پوائنٹ (fixpoint) کا حساب لگائیں۔ فکس پوائنٹ کا بنیادی مطلب یہ ہے کہ اس نوڈ کا تجزیہ کرنے سے کوئی بامعنی معلومات فراہم نہیں ہوتی ہیں۔

استعمال شدہ فکس پوائنٹ کی ایک مثال ری اینٹرنسی (reentrancy) ڈیٹیکٹرز میں مل سکتی ہے: Slither نوڈز کو دریافت کرتا ہے، اور ایکسٹرنل کالز، اسٹوریج میں لکھنے اور پڑھنے کو تلاش کرتا ہے۔ ایک بار جب یہ فکس پوائنٹ پر پہنچ جاتا ہے (reentrancy.py#L125-L131 (opens in a new tab))، تو یہ دریافت کو روک دیتا ہے، اور مختلف ری اینٹرنسی پیٹرنز (reentrancy_benign.py (opens in a new tab)، reentrancy_read_before_write.py (opens in a new tab)، reentrancy_eth.py (opens in a new tab)) کے ذریعے یہ دیکھنے کے لیے نتائج کا تجزیہ کرتا ہے کہ آیا ری اینٹرنسی موجود ہے۔

موثر فکسڈ پوائنٹ کیلکولیشن کا استعمال کرتے ہوئے تجزیے لکھنے کے لیے اس بات کی اچھی سمجھ کی ضرورت ہوتی ہے کہ تجزیہ اپنی معلومات کو کیسے پھیلاتا ہے۔

درمیانی نمائندگی (Intermediate representation)

ایک درمیانی نمائندگی (IR) ایک ایسی زبان ہے جس کا مقصد اصل زبان کی نسبت سٹیٹک اینالیسس کے لیے زیادہ موزوں ہونا ہے۔ Slither Solidity کا اپنی IR میں ترجمہ کرتا ہے: SlithIR (opens in a new tab)۔

اگر آپ صرف بنیادی چیکس لکھنا چاہتے ہیں تو SlithIR کو سمجھنا ضروری نہیں ہے۔ تاہم، اگر آپ جدید سیمینٹک تجزیے لکھنے کا ارادہ رکھتے ہیں تو یہ کارآمد ثابت ہوگا۔ SlithIR (opens in a new tab) اور SSA (opens in a new tab) پرنٹرز آپ کو یہ سمجھنے میں مدد کریں گے کہ کوڈ کا ترجمہ کیسے کیا جاتا ہے۔

API کی بنیادی باتیں

Slither میں ایک API ہے جو آپ کو کانٹریکٹ اور اس کے فنکشنز کی بنیادی خصوصیات کو دریافت کرنے کی سہولت دیتی ہے۔

کوڈ بیس لوڈ کرنے کے لیے:

1from slither.slither import Slither
2slither = 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): اس کے نام سے ایک StateVariable واپس کرتا ہے

ایک 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)): پڑھے گئے اسٹیٹ ویری ایبلز کی فہرست (variables`read کا ذیلی سیٹ)
  • state_variables_written (list(StateVariable)): لکھے گئے اسٹیٹ ویری ایبلز کی فہرست (variables`written کا ذیلی سیٹ)

صفحہ کی آخری اپ ڈیٹ: ۳ مارچ، ۲۰۲۶

کیا یہ ٹیوٹوریل مددگار تھا؟