خارج الشفرة الأصلية: Python ، JVM ، .NET ، و WebAssembly Bytecode
Type: Build
Languages: Python, TypeScript, Java, C#, WebAssembly text
Prerequisites: Phase 13 · 32 (ELF from scratch), 33 (disassembly and control flow)
Time: ~150 minutes
أهداف التعلم
- اقرأ 16 بايت
.pycالعنوان من PEP 552 و إزالة الرمز من الكود دونmarshalالوحدة، للملفات التي كتبها أربعة إصدارات مترجم. - تحليل ملف فئة JVM من JVMS الفصل 4: مجموعة ثابتة، الحقول، الأساليب،
Codeالصفة الثانيةjavac -gيضيف - تفكيك رموز JVM في
Ledger.classو إثبات الإدراج ضدjavap -cعلى أربعة بناءات من نفس المصدر - اقرأ قسم وحدات WebAssembly قسمًا بعد قسم ، و فك كل جسم وظيفة ، و أثبت النتيجة مقابل
wasm-objdump -d. . . - قم بتنقل البيانات المعدنية ECMA-335 من مجموعة .NET من دليل البيانات PE إلى
MethodDefالصفوف و CIL لكل طريقة، والتحقق من مكتبة القارئ التي تستخدم ILSpy. - قياس، لعمل واحد في خمسة حاويات، أي أسماء وأنواع، وهيكل التحكم كل تنسيق يحتفظ بها والتي تفقدها.
المشكلة
لقد بنيتledger.pyووجدتledger.cpython-314.pycفي__pycache__سألت العميل ما الذي يحتوي عليه الملف، قام العميل بإجراء عملية تحليل، طبعت الأداةUnsupported opcodeوخط يقول# WARNING: Decompyle incompleteوخلص العميل إلى أن الملف قد تم التشويش عليه
الملف لم يُغمض، أول بايتين لهما2b 0e، الكلمة 3627 . هذا هو الرقم CPython 3.14 يكتب، وتوقف جداول الكود الاكتتاب في 3.13. كانت الأداة قديمة. وكيل لم يقرأ الرأس، لذلك لم يتمكن من معرفة الفرق.
دراسة 33 أظهرت ما يفقد الرمز الأصلي: أسماء المعلمات، الأنواع، والـ switchأصبح هذا طاولة قفزة حاويات رمز البايت تفقد أقل، وكل واحد يفقد شيئا مختلفا. الـ (بايك) يحافظ على كل اسم متغير ولا يوجد نوع ملف الفئة يحفظ النماذج والأسماء المحلية فقط عندما تسأل. وحدة "وازم" تحتفظ بهيكل التحكم وتسقط الأسماء ما لم يحملها قسم مخصص. يحتفظ الجمعية .NET بأسماء المعلمات في الجدول ويترك الأسماء المحلية إلى ملف منفصل. لا يمكنك تحكم في نتائج المتحلل على أي منها حتى تعرف من الملاحظات كان الحاوية لبدء.
هذه الدروس تبني أربعة قراء في مكتبة Python القياسية. كل واحد يقرأ الحاوية من أول بايت، ويرسل وظيفة واحدة، ويتم التحقق من أداة النموذج الخاصة على الأدوات التي قمت ببناءها.gradeمنledgerجنبا إلى جنب في جميع الحاويات الخمسة
الرأس هو أربعة كلمات
تعريف PEP 552 الرأس بأربعة كلمات 32 بت. الأول هو الرقم السحري. الثاني هو حقل بيت. مجموعة بيت 0 تعني الملف على أساس الهاش. مجموعة بيت 1 تعني check_source: المترجم يضغط المصدر عند الاستيراد ويقارن. مع بيت 0 واضحة، الكلمات الثالثة والرابعة هي mtime المصدر وحجم المصدر. مع مجموعة بيت 0، فإنها تحتوي على SipHash 64 بت من المصدر.
العدد السحري يعيش فيInclude/internal/pycore_magic_number.hقاعدة من 3.11 هي أن Python 3.n تبدأ عند 2900 + 50n ، وكل تغيير في رمز البايت داخل دورة الإصدار يضيف واحد. الوهم المخزن هو رقم 16 بت متبوعا\r\n3،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،5،
الأجهزة تحتوي على ملفات بيك لكل مترجمcompile_pyc.pyكتبهم معpy_compile.compile(..., dfile="ledger.py")حتى يكون اسم الملف المحفوظledger.pyوليس مسار آلة البناء أول 16 بايت من الملفات 3.14:
checked-hash 2b 0e 0d 0a 03 00 00 00 c7 16 c7 fc c5 1d 81 01
timestamp 2b 0e 0d 0a 00 00 00 00 8d 60 cf 6a f1 01 00 00اقرأ رأس العلامة الزمنية كلمة بعد كلمة03 00 00 00أو00 00 00 00هو كلمة العلم8d 60 cf 6aهو 0x6acf608d = 1791975565, mtime من ledger.pyعندما تم بناء الملفf1 01 00 00هو 497، حجم المصدر. الملف المحقق من الهاش يحمل العلامات 3 وثمانية بايتات الهاش بدلا من ذلك. يوافق المترجمون الأربعة على كل شيء في العنوان باستثناء الكلمة السحرية:
| Interpreter | Magic bytes | Word | File bytes | grade.co_code bytes | grade instructions |
|---|---|---|---|---|---|
| 3.11.14 | a7 0d 0d 0a | 3495 | 1054 | 80 | 31 |
| 3.12.12 | cb 0d 0d 0a | 3531 | 937 | 62 | 26 |
| 3.13.12 | f3 0d 0d 0a | 3571 | 943 | 70 | 26 |
| 3.14.6 | 2b 0e 0d 0a | 3627 | 965 | 96 | 35 |
read_pyc_header()فيcode/main.pyيعيد هذه الحقول ويعطي الاسم للنسخة من الكلمة. importlib.util.MAGIC_NUMBERيعطي نفس أربعة بايتات للمترجم الجاري. python3 code/main.py compareيجمع المصدر مع كل python3.11إلىpython3.15وجدت علىPATHلكل منها يطبع الرأس الذي يراه قارئنا بجانب الحقائق التي يبلغ عنها المترجم عن نفسه
مارشال يكتب الرمز موضوع الحقل حسب الحقل
البايت 16 من كل جهاز هو e3هذا هو0x80 | ord('c'): رمز النوع المرجعي لشيء رمز مع FLAG_REFمجموعة، التي تخبر القارئ لتذكر الكائن لاحقا rالمرجحات. الوثائق المرجعية تقول أن النموذج غير مُوثق بشكل متعمد وأن كود الأشياء غير متوافقة بين الإصدارات. كلاهما صحيحان، والنموذج لا يزال صغيرًا بما فيه الكفاية للقراءة. Python/marshal.cيصف رموز النوع: Nلا أحدiإدخال 32 بت، sالبايتاتzوZسلسلة ASCII قصيرة(و)أضعافcكائن رمزي، rإشارة خلفية، يحجز الحاويات مساحة الإشارة أمام أطفالهم، لذا يقوم القارئ بنفس الشيء.
w_complex_object()يكتب كود كائن في ترتيب ثابت. بالنسبة 3.11 إلى 3.15 هو argcount،posonlyargcount،kwonlyargcount،stacksize،flagsبـ 32 بت، ثم code،consts،names،localsplusnames،localspluskinds،filename،name،qualnameكجسام، ثم firstlineno، ثمlinetableوexceptiontable. فك رمز الوحدة كود كائن ملف 3.14 يدويا من بايت 17:
00 00 00 00 argcount 0
00 00 00 00 posonlyargcount 0
00 00 00 00 kwonlyargcount 0
01 00 00 00 stacksize 1
00 00 00 00 flags 0
f3 22 00 00 00 type 's' with FLAG_REF, 34 bytes of co_code follow
80 00 52 06 74 00 52 01 17 00 74 01 ...إن بايتات الرمز اثنان لكل تعليم: 80 00هوRESUME 0،52 06هوLOAD_CONST 6،74 00هوSTORE_NAME 0و17 00هوMAKE_FUNCTION. في القائمة 3.14 في الأجهزة الطباعة نفس البيانات الخمسة على مستوى الوحدة. بعد codeيأتي الثابتات، التي تحتوي على أربعة كائنات رمزية مستوى، وبعد ذلك names: ('LABELS', 'percent_change', 'grade', 'total', 'grade_label'). . .
Unmarshallerفيcode/main.pyيقرأ هذا التخطيط والقديم الذي استخدم 3.9 و 3.10، حيث nlocals،varnames،freevarsوcellvarsكانت حقل منفصلة.CodeObjectمع نفس أسماء الصفات التي يمتلكها الكائن الحقيقي.varnamesالصفائحlocalsplusnamesمن قبلCO_FAST_LOCALقليلاًlocalspluskinds- لأجلgradeفي كل ملف من الملفات الأربعة التي يعود بها('score', 'bucket')،firstlineno10، و غير فارغ linetable- الاختبارtest_unmarshaller_agrees_with_the_running_interpreterيُقارن كل مجال معmarshal.loads()الملفات الثلاثة الأخرى يمكن قراءتها بواسطة رمزنا وغير يمكن قراءتها بواسطةmarshalتحت هذا المترجم.
أربعة مترجمين، أربعة رمزات للاستعراض
يحتوي المستندات المزيفة على تحذير واحد على كل نسخة: رمز البايت هو تفاصيل تنفيذ CPython ولا يوجد ضمان بأن يبقى نفسه.python3.1N -m dis ledger.pyتم التقاط كل مترجم
في 3.11 gradeيبدأ هكذا:
11 2 LOAD_FAST 0 (score)
4 LOAD_CONST 1 (10)
6 BINARY_OP 2 (//)
10 STORE_FAST 1 (bucket)
12 12 LOAD_FAST 1 (bucket)
14 LOAD_CONST 2 (9)
16 COMPARE_OP 5 (>=)
22 POP_JUMP_FORWARD_IF_FALSE 2 (to 28)BINARY_OPيقع في التفاصيل 6 والإرشاد التالي في 10. البايتين بينهم هو مدخل مخزن مخزن داخلي من PEP 659، المترجم التكيفي المتخصص. COMPARE_OPفي 16 يلي 22، لذلك هو يمتلك إدخالات مخزن اثنين.show_caches=True. 3.12 يبدل LOAD_CONSTبالإضافةRETURN_VALUEمعRETURN_CONST, تغيير اسم القفز إلى POP_JUMP_IF_FALSEو يختصرونgradeمن 80 إلى 62 بايت. 3.13 طباعة العلامات L1إلىL4بدلا من تعويضات وتعطى CLI -Cلخزائن الاحتياطي و-Oلتحويلات. 3.14 إزالة RETURN_CONSTمرة أخرى، يضيف LOAD_SMALL_INTوLOAD_FAST_BORROW، و إدخالات NOT_TAKENبعد كل قفزة مشروطة:
12 20 LOAD_FAST_BORROW 1 (bucket)
22 LOAD_SMALL_INT 9
24 COMPARE_OP 188 (bool(>=))
26 CACHE 0 (counter: 0)
28 POP_JUMP_IF_FALSE 3 (to L1)
30 CACHE 0 (counter: 0)
32 NOT_TAKEN- نعم
-C -Oالعروض المدرجة 13CACHEإدخالات داخلgrade: بعد خمسةBINARY_OP، واحد بعد كل واحدCOMPARE_OP، واحد بعد كل واحدPOP_JUMP_IF_FALSE.الجهاز التكيفي يظهر ما هي الاكشافات .بعد 200 مكالمةdis.dis(grade, adaptive=True)بصماتRESUME_CHECKوCOMPARE_OP_INTحيث كان الإدراج المُباشرRESUMEوCOMPARE_OPوtotalتظهرFOR_ITER_LIST،BINARY_OP_ADD_INTوJUMP_BACKWARD_NO_JIT. الأشكال المتخصصة تعيش في نفسco_codeالبايتات. لم يحتوي جهاز الكمبيوتر على هذه البايتات أبداً، لأن التخصص يحدث في الذاكرة.
هذا هو السبب في أن المفكّرات لديها سقف إصدار. uncompyle6 3.9.3 تقول أنها تقبل رمز البايت من Python 1.0 إلى 3.8. decompyle3 3.9.3 يقرأ 3.7 و 3.8. xdis 6.3.0, وقطع الإصدارات المتقاطعة وراء كل منهما، يقرأ إلى 3.13. pycdc لديه جداول رمز الاختيار حتى python_3_13.cppفي ملف بناءها، وعلى طبعات رمز opcode مجهولة Unsupported opcodeويشير الملف إلى أن النتائج غير كاملة. يطالب PyLingual بكل إصدار صدر منذ 3.6 ويستخدم مترجمين من 3.8 إلى 3.15 لإعادة تجميع وتحقق من النتائج الخاصة به. بالنسبة لملف 3.14، فإن الثلاثة الأولى ترفض أو تفشل، ولا تنطبق إلا الأخيرتين. اقرأ الكلمة السحرية قبل اختيار أداة.
ملف الفئة يحافظ على قاموسه
في JVMS Java SE 25، القسم 4.1، يقدم التخطيط كهيكل واحد: magic،minor_version،major_version،constant_pool_count, المسبح المستمر ,access_flags،this_class،super_class، واجهات ، حقل ، طرق ، صفات السحر هو0xCAFEBABE. يقبل جهاز جاوا SE 25 الافتراضي الإصدارات الرئيسية 45 إلى 69، ويعتبر أقل من 65535 ملفًا من ميزة المشاهدة المسبقة.Ledger-g.classهل هيca fe ba be 00 00 00 41 00 5e: الرئيسية 65 هو جاوا 21 و 0x5e= 94 هو عدد المجموعة المستمرة. Ledger-jdk25.class، تم بناؤه بواسطة javac 25.0.2 من نفس المصدر، يبدأ ca fe ba be 00 00 00 45الرئيسي 69
المجموعة المستمرة هي حيث يحتفظ ملف الفصل قاموسه الخاص.#13في-gالبناء هوMethodrefهذا يشير إلى الصف#8و الاسم و النوع#14. تتبع المؤشرات يعطيLedger.grade:(I)I، والذي هو بالضبط ماjavap -vبصمات بعد//. وصف(I)Iهو واحدintالمعلم وintالنتيجة([I)Iعلىtotalيقول أن المعلم هوintالمصفوفة. كل طريقة، وحقل، والفئة التي يلمسها الرمز له مثل هذا الإدخال، والتحقق في القسم 4.10 يرفض الملف الذي لا يوافق مع تعليماتها.ClassFileالفصل فيcode/main.pyيقرأ جميع علامات الثابتة الـ 17 من الجدول 4.4 ويعالجLongأوDoubleيرتفع على علامة مجهولة وعلى البايتات بعد الصفحة الأخيرة
الصفات تعتمد على الفئة، كل حقل، كل طريقة، وال Codeسمة نفسها. يقول JVMS أن الآلة الافتراضية يجب أن تتجاهل الصفات التي لا تعرفها ، ولهذا السبب يمكن إضافة جداول التحليل أو إسقاطها دون تغيير جسم طريقة. دليل javac يقول -gيُولد كل معلومات التحليل بما في ذلك المتغيرات المحلية، أن الإعداد الافتراضي يُولد أرقام الخط والملف المصدر فقط، وأن -g:noneلا يخلق شيئاً، الثلاثة يبني مقياساً
| Build | Bytes | Constant pool count | LineNumberTable | LocalVariableTable | SourceFile | grade code bytes |
|---|---|---|---|---|---|---|
javac -g | 1832 | 94 | 7 methods | 6 methods | yes | 50 |
javac | 1581 | 82 | 7 methods | none | yes | 50 |
javac -g:none | 1404 | 79 | none | none | no | 50 |
50 بايت رمزية من gradeويتم التحقق من ذلك-gيضيف لgradeهو واحدLocalVariableTableالصف: بداية 0، طول 50، فتحة 0، اسم score، وصفIبدونها ، فالمُفكّر يرى فتحة 0 من النوعintو يجب أن يختلق اسمًاStackMapTableيبقى في كل بناء لأن المؤكد يحتاجه، وال BootstrapMethodsالصفحة تبقى لأن mainيُحدد الخيوط عبر invokedynamic. . .
فك تشفير المفاتيح من خلال اليد
يحدد الفصل 6 من JVMS كل تعليمات بايت واحد opcode والعمليات التي تسمي opcode. تعادلات الفرع هي قيم مؤكدة 16-bit بالنسبة إلى عنوان الفرع opcode، والتي تختلف عن x86-64, حيث التحول بالنسبة إلى التعليمات التالية. tableswitchوlookupswitchتبدأ مع صفر إلى ثلاثة بايتات التشغيل بحيث تبدأ أوبراندها 32-بيت من عنوان هو مضاعف أربعة.
البايتات من gradeمن حاسوب 4 في Ledger-g.class:
aa tableswitch at pc 4
00 00 00 padding to pc 8
00 00 00 2c default: 4 + 44 = 48
00 00 00 06 low 6
00 00 00 0a high 10
00 00 00 2a case 6: 4 + 42 = 46
00 00 00 28 case 7: 4 + 40 = 44
00 00 00 26 case 8: 4 + 38 = 42
00 00 00 24 case 9: 4 + 36 = 40
00 00 00 24 case 10: 4 + 36 = 4036 بايت، تعليمات واحدة، والكلswitch (score / 10)مع قضيتها المشتركة ل 9 و 10.switchفي الدروس 33 كان يحتاج إلى فحص الحدودlea، أmovslq، وaddهنا الأهداف في التعليمات، وكذلك حقيقة أنهم ينتمون معا.
disassemble_jvm()تغطي جميع 202 رمزًا محددًا مع عرض أوبراندها ، وتتبع قاعدة التدليك ، وتجعل أوبراندها طريقة javapنعمcompare_with_javap()يُحلل المُسجنينjavap -c -pالنص، بما في ذلك الخطوط المتعددة tableswitchكل أربعة تشكيلات تتفق على 108 من 108 تعليمات.test_branch_offsets_are_relative_to_the_branch_instructionالتحققاتifneفي pc 1 الهبوط على 6 ، if_icmpgeعند 13 الهبوط على 33 ، وgotoفي 30 الهبوط مرة أخرى على 10.
رادار2 6.2.4 ، تم بناؤه من المصدر لهذه الدروس ، يقرأ نفس الملف. rabin2 -Iتقارير arch java،lang java 21،linenum trueوlsyms true، والتي هي قراءة الإصدار والجدولين التصحيحي. pd 14 @ sym.Ledger.gradeيطبعtableswitchمع السهام إلى أهدافها الخمسة.Unable to parse code attribute: 2في هذا الملف، وهو قيود أداة أسماء نفسها وسبب للحفاظ على javapكالمعرفة. إنّ مُحللات هذا النموذج متقدمة بالمقارنة مع Python. CFR 0.152 مرخصة مع معهد ماساتشوستس للتكنولوجيا Procyon 0.6.0 و Vineflower 1.12.0 هي Apache-2.0 و Vineflower هو فرن فلور مع دعم جاوا 21. (فيرنفلور) نفسه يعيش داخل مخزن مجتمع (إنتلي جي) تغطي JADX 1.5.6 تنسيق Android DEX ، وكانت آخر إصدار JD-GUI في عام 2019. قام هاراند وسوتو فاليرو ومونبروس وبودري بقياس ثمانية منها في عام 2020. أفضل إنتاج صحيحة نحو نحو 84 في المائة من الفصول والإنتاج معادل معنويًا لـ 78 في المائة. استعاد مُحلل التلفزيونات المُتَعَدّدُ 37.6 بالمئة من الفئات التي لم تتعامل بها أداة واحدة. الأنواع والأسماء والكؤوس المحققة تجعل النموذج قابل للكمبلة. لا يُكملون أيّ مُحاميل واحد.
وحدة الجذع قائمة من القسمات
المواصفات الأساسية تعرّف الوحدة على أنها المواصلة 00 61 73 6d 01 00 00 00، السلسلة\0asmوالإصدار 1، تليها أقسام. كل أقسام هي بايت واحدu32حجم في LEB128 ومحتوياته. أرقام 1 إلى 13 هي القسمات المعروفة، كل مرة على الأكثر في الترتيب. id 0 هو قسم مخصص مع اسم، يسمح في أي مكان. جميع الأرقام الكاملة هي LEB128, لذلك e4 00هو 100 و 80 08هو 1024wasm-objdump -hعلىledger.wasmيذكر سبع أقسام، وWasmModuleيجد نفس السبع مع نفس تعويضات الحمولة المفيدة:
| Section | Payload | Count | What it holds for ledger |
|---|---|---|---|
| Type | 10 to 26 | 3 | (i32) -> nil, (i32, i32) -> i32, (i32) -> i32 |
| Import | 28 to 39 | 1 | env.log with type 0 |
| Function | 41 to 46 | 4 | type index for each defined function |
| Memory | 48 to 51 | 1 | one page, no maximum |
| Export | 53 to 110 | 5 | memory and the four function names |
| Code | 113 to 271 | 4 | bodies of 23, 63, 44, and 23 bytes |
| Data | 273 to 290 | 1 | F\0D\0C\0B\0A\0 at offset 1024 |
توجد فصل بين أجزاء الوظيفة والرمز بحيث يمكن للمتنشر أن يبدأ في تجميع قبل وصول الملف بأكمله. كل إدخال رمز هو حجم، ومركز من الإعلانات المحلية، والتعبير.gradeالمتجه المحلي هو01 7f: مجموعة واحدة من واحد i32هذا هوbucket، مع نوعها ودون اسمه
تدفق التحكم هو مهيكل من خلال البناء.block،loopأوifالمكونات. يتم تحديد العلامات حسب عمق العشب. br_tableيقوم بإجراء فرع غير مباشر من خلال جهاز عمل يُصفف قائمة العلامات.gradeفي تعويض الملفات0xa3:
0e br_table
0b 11 labels follow
04 04 04 04 04 04 buckets 0 to 5: label 4, the outermost block, returns 0
03 02 01 00 buckets 6, 7, 8, 9: labels 3, 2, 1, 0
00 bucket 10: label 0, shared with 9
04 default label 4كل ملصق هو عمق.block، والرقم بعدendهوi32.const 4يليها br 4خارج حجر النتيجة.blockالتعليمات أمام الطاولة، والعشرة علامات، والخمسة brالتعليمات بعد أن يكون كله switchويقوم المحقق بتجاهل أي فرع يغادر الهيكلdisassemble_wasm()تتبع العمق حتى الرسومات المدرجة مثل wasm-objdump، تغطي كل رمز خيار واحد من unreachableإلىi64.extend32_s، و يطابق الاعتقالاتwasm-objdump -dعلى 77 من 77 تعليمات لكل من البنايات.
الأسماء هي الشيء الوحيد الذي يُسقطه الوحدة العاديةwasm-objdumpبصمات مستمرة<grade>لأن قسم التصدير يقوم بتخريط تلك السلسلة إلى مؤشر الوظيفة 2 ، والقارئ يفعل الشيء نفسه. الأسماء المحلية لا توجد في أي مكان في الملف البايت 290. wat2wasm --debug-namesيضيف قسمًا مخصصًا يسمى nameمع الفرق الفرعية لسم الوحدة، أسماء الوظائف، والأسماء المحلية. النظام الملف ينمو إلى 425 بايت. القارئ يجد {0: 'score', 1: 'bucket'}للعمل 2 و {0: 'values', 1: 'count', 2: 'sum', 3: 'i'}للعمل 3. wasm-stripيزيل القسم مرة أخرى. مخزن الاتفاقيات الأداة يصف اثنين من المحاملين. يمكن دمج DWARF على النحو.debug_*القسمات المخصصة.sourceMappingURLيمكن أن يشير القسم المخصص إلى خريطة مصدر أعداد العمود هي تعويضات بايت إلى الثنائي.
أدوات تحرك خلال عام 2026، وبت 1.0.42، أصدرت في عام 2026-09-15, تم إزالتهاwasm-decompileو المُبني على هذه الآلة لديه بالضبط الأدوات الـ11 المتبقيةprint،objdumpوdemangle. إصدار (بيناريان)_133 يقدم wasm-dis. رادار2 6.2.4 يقرأ الوحدة أيضاً.rabin2 -Iيقولarch wasm. رمزها لـgradeيبدأ في0x8e، حيث يبدأ متجه المحليين، بينما wasm-objdumpتسمية الوظيفة في 0x8bحيث تبدأ حقل الحجم.get_local،set_localوbrtable 11 4 4 ...مع طباعة عدد العلامات البايتات هي نفسها في كل الأدوات الثلاثة وتختلف التكليف، لذلك يجب أن يكون المقارنة اسم الأداة التي تم التقاطها بها. البحث لهذا الدروس لم يجد أي وحدات معالج WebAssembly في دليل معالج Ghidra، ولم يتم قراءة هذا القائمة بالكامل. إنّ مُبنى Ghidra-wasm-plugin v2.4.0 من طرف ثالث يستهدف Ghidra 12.0. المواصفات نفسها هي وثيقة حية واحدة. صفحة W3C للwasm-core-2هو مشروع توصية المرشحين المؤرخ 13 أكتوبر 2026 الذي يصف ملخصه الإصدار 3.0، ومشروع المحررين يحمل نفس التاريخ.
البيانات المعدنية ECMA-335 هي قاعدة بيانات البرنامج الخاصة
مجموعة .NET هي ملف PE. LedgerNet.dllيبدأ بـMZ، لديه ثلاثة أقسام اسمها.text،.rsrcو.reloc، ويقول آلة0x14cلأن المجمع أصدرت رمز محايد المنصة. دليل البيانات 14 من الرأس الاختياري، الرأس CLR Runtime، يشير إلى RVA 0x2008. ECMA-335 II.25.3.3 تعريف 72 بايت هناك:
48 00 00 00 Cb 72
02 00 05 00 MajorRuntimeVersion 2, MinorRuntimeVersion 5
78 21 00 00 MetaData RVA 0x2178
84 07 00 00 MetaData size 1924
01 00 00 00 Flags: COMIMAGE_FLAGS_ILONLY
05 00 00 06 EntryPointToken 0x06000005, MethodDef row 5, which is Mainجذور البيانات المعدنية في RVA 0x2178يبدأ بالتوقيع42 53 4a 42، والتي تقرأBSJB، ثم النسخة 1.1 والسلسلة v4.0.30319خمسة رؤوس التيار تتبع:#~في التكافؤ0x6c، ثم#Strings،#US،#GUIDو#Blob. II.24.2 يقول كل نوع من التيارات تحدث مرة واحدة على الأكثر.#~التيار يبدأ بـHeapSizesبايت، صفر هنا، لذلك كل سلسلة، GUID، ومرجع البقع هو 2 بايت واسع، و 64 بت Validالقناع الذي يسمي الجداول المحتلة. يتم تعيين 14 قطعة:
| Table | Id | Rows | Row size | What the rows say |
|---|---|---|---|---|
| Module | 0x00 | 1 | 10 | the module name and its GUID |
| TypeRef | 0x01 | 21 | 6 | System.Object, System.Console, 19 more |
| TypeDef | 0x02 | 4 | 14 | <Module>, Ledger, and two compiler helpers |
| Field | 0x04 | 2 | 6 | Labels and a static array initialiser |
| MethodDef | 0x06 | 6 | 14 | the five methods and .cctor |
| Param | 0x08 | 5 | 6 | before, after, score, values, score |
| MemberRef | 0x0a | 16 | 6 | 12 attribute constructors and the 4 methods that Main calls |
| CustomAttribute | 0x0c | 12 | 6 | attributes the compiler and the SDK add |
| StandAloneSig | 0x11 | 3 | 2 | the three local variable signatures |
| Assembly, AssemblyRef, ClassLayout, FieldRva, NestedClass | 1, 2, 1, 1, 1 | identity, references, layout |
لا يتم تخزين حجم الصف في أي مكان. يعطي II.22 لكل عمود نوعاً، و II.24.2.6 يعطي قاعدة الحجم. مؤشر كومة هو بثنين أو أربعة بايتات من HeapSizes. مؤشر الجدول البسيط هو بثنين بايت بينما يكون هذا الجدول أقل من 65536 سطر. مؤشر مدمج يمكن أن يشير إلى n جداول مع ب بيتات علامة هو بثنين بايت بينما كل من هذه الجدول لديها أقل من 2^(16-b) الصفوف. CliAssemblyيحسب حجم 14 صف من هذه القواعد ويعد الصف. النظام.التفكير.مدونة البيانات المعدنية في الأجهزة الإصدارية تقرير نفس الحجم و نفس تعويضات الجدول، وهذا هو كيفية إثبات الاختبار الحساب.
يحدد III.1.9 الرمز: البايت العالي هو الجدول، والبايت الثلاثة المنخفضة هي الصف القائم على 1. 0x06000002هوMethodDefالصف 2 . هذا الصف لديه RVA 0x2060اسمكGrade، وقطعة توقيع00 01 08 08: الاتفاقية الافتراضية للاتصال، معايير واحدة، العودة int32، المعلمint32. إنهParamListالنقاط في الصف 3 من Param، اسمهاscoreطاولة " بارام " هي سبب إمكانية طباعة " إيلسبي "Grade(int score)من إطلاق منشأة منقطعة.0x2060يبدأ جسم المنهج بالرأس الدهني:
13 30 flags 0x13: fat, init locals; size 3 dwords
02 00 MaxStack 2
2d 00 00 00 CodeSize 45
01 00 00 11 LocalVarSigTok 0x11000001StandAloneSigالصف 1 يحتفظ07 01 08: LOCAL_SIG، محلي واحد ،int32. المحلية لديها نوع وليس اسم. ECMA-335 تحتفظ بأسماء محلية في شكل إصلاح تبادل القسم V، و .NET SDK يكتبها إلى PDB. تم بناء هذا الجهاز مع DebugTypeلا يوجد أي طاولة ولا ملف يحمل اسمbucket. .PercentChangeلديه رأس صغير بدلاً من ذلك: أول بايت3aهو0x0e << 2 | 2، جسم 14 بايت بدون محليين و كومة افتراضية من 8.
45 بايت رمزية من Gradeفك الرمز مع جدول الشفرات المشتركة في القسم الثالث. switchهو رمز الاختيار0x45يليها u32العد والكثير من ذلكint32الأهداف المتعلقة بالمرشد بعد الجدول:
IL_0000: 02 ldarg.0
IL_0001: 1f 0a ldc.i4.s 10
IL_0003: 5b div
IL_0004: 0a stloc.0
IL_0005: 06 ldloc.0
IL_0006: 1c ldc.i4.6
IL_0007: 59 sub
IL_0008: 45 05 00 00 00 08 00 00 00 06 00 00 00 04 00 00 00 02 00 00 00 02 00 00 00
switch (IL_0029, IL_0027, IL_0025, IL_0023, IL_0023)
IL_0021: 2b 08 br.s IL_002b
IL_0023: 1a 2a ldc.i4.4, retالمحمول خصم 6 قبل switch، لذا الحالة 6 هي الهدف الأول.disassemble_cil()يعطي الرموز عبر الجداول: ldsfld Labels،call Grade،call System.Console::WriteLineوldstr ' 'من#USالمُتَكَلُّمُ لكلّ هذا هوMetaDump، برنامج C# قصير في الأجهزة المبنية علىSystem.Reflection.Metadataيطبخ عدد الصفوف، وحجم، وتعويض كل طرق، و RVA كل التوقيع، أسماء المعلمات، و بايت IL، و 226 حقل من System.Reflection.Emit.OpCodes. .compare_with_metadump()يوافق على جميع الشيكات 246 . الجدول الزمني لديه 218 رمزات إضافة إلى ثمانيةprefixالمشاركين في الجدول الدراسي يحتوي على 219 إدخالًا لأنه يحتوي علىno.من III.2.2 ، التي لم يكن لها جدول إصدار.
أدوات للصيغة: ILSpy 11.0 (MIT ، أصدرت 2026-08-12) تعمل على macOS من خلال إعداد سطح المكتب Avalonia. ilspycmd11.1.0.9782 طباعة IL مع -ilو يختار طريقة من خلال الوهم مع -m 0x06000002. dnSpyEx 6.6.0 يستمر dnSpy على Windows فقط.ildasmالسفن كحزمة NuGet بدلا من داخل SDK. radare2 6.2.4 يقرأ البيانات المعدنية أيضا: rabin2 -Iيقولarch cilوclass PE32وisالقوائمLedger.Grade(int:score):intمع اسم المعلمات وكلاهما من النوعين المأخوذة من الجداول المعلمية والتوقيع. ليس لديها إزالة CIL في هذا البناء. تم بناء هذا الإصلاح مع .NET SDK 8.0.205 لأن هذا هو SDK مثبت على آلة البناء. .NET 10 كان حاليا منذ 2025-11-11 ويكتب نفس الهياكل ECMA-335 .
ما تحتفظ به كل حاوية
ضعgradeمن كل الحاويات الخمسة في طاولة واحدة. كل سطر يأتي منpython3 code/main.py keeps، الذي يُشغل القراء على الأجهزة:
| Container | Body bytes | Function name | Parameter names | Parameter and return types | Local names | Line numbers | Control flow |
|---|---|---|---|---|---|---|---|
| ELF object, clang -O0 | 118 | grade in .symtab | none | none | none | none, no .debug_* sections | 5 jumps and 1 indirect jump through a relocation table |
| CPython 3.14 pyc | 96 | co_qualname | score | none | bucket | co_linetable, first line 10 | 4 compare and POP_JUMP_IF_FALSE pairs |
JVM class, javac -g | 50 | constant pool | score in LocalVariableTable | (I)I | none beyond the parameter | LineNumberTable, 6 rows | 1 tableswitch |
| WebAssembly | 63 | Export section | only with a name section | (i32) -> i32 | only with a name section | none | 6 nested blocks, 1 br_table, 4 br |
| .NET assembly | 45 | MethodDef | score in Param | static int32(int32) | none, types only in StandAloneSig | none without a PDB | 1 switch, 1 br.s |
الجدول يشرح نتائج تحليل الملفات التي ستراها.int total(const int *, int)معint total(long param_1, uint param_2)أن Ghidra استنتج من الرمز الأصلي، لأن الرمز الأصلي لا يحفظ أي من هذه العمودات. يحتفظ Pyc كل الاسم ولا أي نوع، وتدفق التحكم هو القفزات التي تتغير شكلها كل إصدار، لذلك يقوم مفكّر Python بقطع كل نسخة واسترداد الأسماء مجانا.-gهو على، ويُعبر عنswitchوحدة "الغص" تبقي الهيكل من خلال البناء، لذاwasm2watهو رحلة ذهاب وإياب بدون خسائر والخسارة الوحيدة هي الأسماء. مجموعة .NET تحتفظ بالوصف الأكثر اكتمالاً، لأن الجداول البيانات المعدنية هي قياسية، ولا تزال بحاجة إلى PDB لاسم محلي.
يخبرك الجدول ما كان على المتحلل العمل معه ، ومع أي من نتائجها نسخ حقيقة مخزنة ومع أي إستنتاج. اسم المعلم في إرسال ILSpy هو نسخة. اسم محلي في نفس الإنفاذ هو استنتاج ما لم يكن PDB موجودًا. تدرسة 35 تسجل هذا الفرق كسلطة لكل ادعاء.
بناءها
أطلق التجربة:
cd phases/13-tools-and-protocols/43-bytecode-and-managed-formats
python3 code/main.py
npx tsx code/main.tsإن المخرج هو تقرير JSON واحد. لكل Pyc يعطي كل من العناوين، الملف و gradeالحجم، عدد التعليمات وأسماء رمزات الاختيار من القائمة التي تم التقاطها، وما إذا كان المترجم الجاري يمكن قراءتها. لكل طبقة يقدم النسخة، الحجم، حسابات جدول التحليل، والـ javapلكل بناء من "السوم" يقدم أقسام، أنواع، وظائف، محتويات قسم الاسم، والwasm-objdumpالاتفاق. لجميعها يعطي عنوان CLI، وتدفقات، وعد صفوف الجدول، والطرق، واتفاق النظام.التفكير. البيانات المعدنية. إنه ينتهي بتبيع الجدول والقائمة من المترجمين الموجودة على PATH. . .
اقرأcode/main.pyفي هذا الترتيب:
Readerيحمل الوسيط والعرض الكامل.uleb()وsleb()هذه قراءة LEB128 التي تحتاجها Wasm و .NETread_pyc_header()،UnmarshallerوPycFileاقرأوا جهاز التشغيلparse_dis_text()يقرأ المعتقلينdisالقوائم بحيث لا يحتاج المقارنة بين الإصدارات إلى أربعة مترجمين في وقت الاختبار.ClassFileيقرأ ملف الفصل وdisassemble_jvm()يفكّر رمزهاparse_javap_code()وcompare_with_javap()هو التحقق من الوساطة.WasmModuleيقرأ القصص وdisassemble_wasm()يُفكّر تعبيرًا بعمقهاcompare_with_wasm_objdump()هو التحقق من الوساطة.CliAssemblyيمرون PE، رأس CLI، جذور البيانات المعدنية، التيارات، والجدولات.TABLE_SCHEMASوCODED_INDEXESهي II.22 و II.24.2.6 كمعلومات.disassemble_cil()يُفكّر الجسم وcompare_with_metadump()تحقق من ذلك.NativeObjectيقرأ ELF بما فيه الكفاية لرد الرموز الوظيفية ويأخذ الدروس 33 قائمة كنصها.what_each_keeps()وfigure_data()بناء المقارنة.
هناك خمسة أوامر أخرىpython3 code/main.py pyc FILE،class FILE،wasm FILEوdll FILEطبع الهيكل و قائمة كل وظيفة في الملف الذي تعطيه لهم. python3 code/main.py compareتجميعات ledger.pyمع كل مترجم علىPATHويقومون بطبع ما كتب كل منهم
استخدمها
استخدم القراء بهذه الترتيب على حاوية صنعتها
- اقرأ أول بايت و اسم النموذج ثم بايتين
0d 0aهو (بيك)ca fe ba beملف الفصل،00 61 73 6dوحدة،4d 5aمع إدراج البيانات 14 وضع الجمع. - اقرأ الرأس واكتب النسخة المنتجة التي يسميها. لـ pyc التي هي الكلمة السحرية، لملف الصفحة النسخة الرئيسية، لجمعة وقت تشغيل و metadata نسخة السلاسل.
- تحقق من كل جهاز إزالة الكمبيوتر الذي تخططين لتنفيذه مقابل هذا النسخة قبل تشغيله، وقم بتسجيل السقف وأين توثيق الأداة.
- قم بتشغيل القارئ وأداة النموذج الخاصة به على نفس الملف وقارنها صف بعد صف. عدم الملاءمة هو خطأ في القارئ أو تغيير في الأداة، ويجب فهم أي من هذه الأدوات قبل أن تكون القائمة دليلًا.
- املأ جدول الاحتفاظ بالوظيفة التي تهتم بها، وقم بتشخيص كل حقيقة كمتحتفظ بها أو ضائعة، واطلق اسم الجدول أو الصف أو القسم الذي جاء منه.
- فقط بعد ذلك قراءة إصدار المتحول، وقم بتشخيص كل اسم وتكليف في ذلك كنسخة من حقيقة حفظ أو كإستنتاج.
احتفظ بملفات النص في Oracle مع الحاويات. عندما يتغير مترجم، JDK، SDK، أو نسخة wabt، اعيد بناءها مع build_fixtures.shوإعادة التقاطها، لأن القائمة المتغيرة هي جهاز متغير.
المختبر التفاعلي
المختبر A: قراءة العنوان، ثم الكود الكائن
منcodeالإرشادات، مفتوحة Python:
cd phases/13-tools-and-protocols/43-bytecode-and-managed-formats/code
python3 -qأركض
from main import *
pyc = load_pyc("ledger.cpython-311.pyc")
pyc.header.to_dict()
pyc.module.names
pyc.functions()["grade"].varnames
len(pyc.functions()["grade"].code)اكتب الكلمة السحرية قبل المكالمة الأولى ثم قم بتحميلledger.cpython-314.pycو قم بتقارن الاثنينcodeثم حاولimport marshal; marshal.loads(pyc.data[16:])في الملف 3.11 تحت مترجمك وقرأ الخطأ.
المختبر ب: سلسلة المسبح المستمرة
cls = load_class("Ledger-g.class")
cls.constant(13)
cls.constant(14)
cls.describe_constant(13)
[row["text"] for row in jvm_listing(cls, "grade")]اتبع#13إلى#8و#14، ثم إلىUtf8الإدخالات، يدوياً قبل الاتصالdescribe_constant- ثم تحميلLedger-gnone.classو اتصلcls.method("grade").attribute_names()على كليهماCodeالمجموعة هي نفسها، والخصائص ليست كذلك.
المختبر (ج): عمق وملفات
module = load_wasm("ledger.wasm")
[(row["depth"], row["text"]) for row in wasm_listing(module, "grade")]
module.function_name(2)
load_wasm("ledger-names.wasm").names["locals"][2]إبحث عنbr_tableصف و اقرأ عمقها اعدendالصفوف بعد ذلك وتطابق كل واحد من أرقام اللوحة في الجدول. ثم فتح ledger.watو العثور علىblock $sixتلك العلامة 3 أسماء.
المختبر D: من الرمز إلى البايت
asm = load_assembly("LedgerNet.dll")
asm.method("Grade")
body = asm.method_body(asm.method("Grade")["RVA"])
body.fat, body.max_stack, body.code_size, hex(body.local_signature_token)
asm.token_text(0x11000001)
[row["text"] for row in cil_listing(asm, "GradeLabel")]احسب تعويض الملفات من RVA 0x2060من.textعنوان القسم يدوياً و مقارنة مع asm.rva_to_offset(0x2060)إذاً انظر للأعلىasm.row(0x08, 3)و ابحث عن مكان الاسمscoreحياة
مختبر التدريب
أضف لغة مصدر خامس للمقارنة، أو حقيقة سادسة إلى الجدول.
المتطلبات:
- اكتب وظيفة مع حلول وتغير محلي في لغة التي لديك محفز، على سبيل المثال Kotlin إلى ملف فئة أو Rust إلى وحدة Wasm. إلتزام الخروج وإدراج القائمة في النص مع القاعدة الدقيقة في
build_fixtures.sh. . . - اجعل القارئ المتطابق يوافق على كل تعليمات القرآن. أضف رموز إضافية فقط عندما يحتاجها المكون.
- التمديد
what_each_keeps()مع الحاوية الجديدة، و مع حقيقة واحدة أخرى لكل حاوية: ما إذا كان الجسم يحمل طاولة استثناء أوtryالمنطقة - إضافة الحاوية الجديدة إلى
figure_data()ويتم إعادة التأهيلsite/figures-re-43.js. . . - اكتب اختبار يفشل عندما يبلغ القارئ عن حقيقة كما تم حفظها دون تسمية الجدول أو الصفة أو القسم الذي يحتوي عليها.
النجاح يعنيpython3 code/main.py keepsيظهر الصف الجديد مع أدلة لكل خلية، وكل مقارنة في النبي صلى الله عليه وسلم لا تزال توافق.
درساً أساسياً
هذا الدروس يتضمنoutputs/skill-bytecode-and-managed-formats.md. استخدمها لتحويل حاوية رمز البايت إلى تقرير رأس ، وإدراج معين لمهمة واحدة ، وجداول معلومات ترسم كل اسم ونوع ، والهيكل كما تم الحفاظ عليه أو فقدته. يتطلب أداة النموذج الخاصة بها كحكيم ، وتحقق النسخة قبل أي مفكّر ، وإعلان عن مكان كل حقيقة فقدت قد عاش.
تحقق من ذلك
إشغال التجربة والسلسلة التحديدية:
cd phases/13-tools-and-protocols/43-bytecode-and-managed-formats
python3 code/main.py
npx tsx code/main.ts
python3 -m unittest discover -s code/tests -vيجب أن تثبت التحقق:
- تحتوي الرأس الأربعة على الكلمات السحرية 3495، 3531، 3571، و 3627، العلامات 3، والهاش 8 بايت، وملفات العلامات الزمنية تحتوي على العلامات 0، mtime 1791975565, والحجم 497
- كل كلمة سحرية ل 3.11 و بعد ذلك يجلس في النطاق
2900 + 50nالقاعدة تعطى إطلاقها - يعيد المُحاكم الأسماء، المستمرات، أجزاء رمزية، أسماء المتغيرات، و جدول الخط
marshal.loads()على الملف الذي كتب المترجم المدير - كل الملفات الأربعة تحتفظ بأسم الوحدات
('score', 'bucket')لـgrade، أول سطر 10 ، وledger.pyكاسم الملف grade.co_codeهو 80، 62، 70، و 96 بايت في جميع النسخ الأربعة والقوائم التي تم التقاطها لديها 31، 26، 26، و 35 تعليمات- القائمة 3.11
POP_JUMP_FORWARD_IF_FALSE3 ، 12 و 3 ، 13RETURN_CONSTو 3.14 لديهLOAD_SMALL_INT،LOAD_FAST_BORROWوNOT_TAKEN - 3.14
-C -Oيظهر القائمة 13 إدخال في الاحتفاظgrade، خمسة منهم بعدBINARY_OP، وترتيبات الإدراجاتCOMPARE_OP_INT - رأس بدون
0d 0a، رأس محطم، وجسم ليس كود كائن رفعFormatError - قائمة التعليمات موجودة فقط للجهاز المكتب الذي كتبه المترجم الجاري وتطابق المقاطع
disالناتج - الملفات الفئة لديها 65 أو 69 أساسية، أحجام 1581, 1832, 1404 و 1581, وتعدد الجمع الثابت 82, 94, 79, و 82
- مستمرة
#13يقررMethod Ledger.grade:(I)Iو#47إلىString F - إنّ مُفكّر الـ JVM يوافق على
javap -c -pعلى 108 من 108 تعليمات في كل أربع البناءات tableswitchفي pc 4 هو 36 بايت مع 6 منخفضة، 10 منخفضة، 48 الافتراضي، والهدف 46, 44, 42, 40, 40- مستويات التحليل الثلاثة تغير عدد الصفات وتترك 50 بايت رمز من
gradeمتطابقة ifne،if_icmpgeوgotoالأهداف نسخية عن رمز الخيارات- سحرية خاطئة، تعقب البايتز، ورفع رمز الخيار غير محدد
FormatError - ستة أقسام " واص " لديها تعويضات للحميل المفيد
wasm-objdump -hالطوابع، والأسماء المُبنية يضيفnameقسم العمليات الإجتماعية في 293 إلى 425 - النوع،
env.logالإيرادات، الخمسة الصادرات، وقطاع البيانات في 1024 رمز التشريح كما هو مكتوب فيledger.wat - إنّ مُفكّر " ويزم " يوافق على ذلك
wasm-objdump -dعلى 77 من 77 تعليمات في كل من البناء gradeلديه 6 كتلة متجمعةbr_tableمع علامات4 4 4 4 4 4 3 2 1 0 0و 4 افتراضي في عمق 6 و 1i32المحلية- أسماء الوظائف تأتي من الصادرات بدون قسم الأسماء والأسماء المحلية فقط معها
- LEB128
e4 00هو 1007fهو -180 08هو 1024، وتعطي أنواع الكتل مثلwasm-objdump - إصدار 2 خاطئ، ورفع رمز الاختيار غير معروف
FormatError - الجمع هو PE32 مع آلة
0x14c، عنوان CLI في RVA0x2008, وقت التشغيل 2.5 ,ILONLY، و نقطة دخول0x06000005 - نسخة البيانات المعدنية هي
v4.0.30319، هناك خمسة تيار ، والجداول 14 لديها عدد الصفوف وحجم الصفوف تقارير الوساطة - قراءة .NET يوافقون على نظام.عكس.المعلومات المتعددة على 246 من 246 التحقق
Gradeلديه مُعيارscore, توقيعstatic int32(int32)، رأس سمين معMaxStack2 و 45 بايت رمز، و واحدint32محلية بدون اسم- (CIL)
switchالأهدافbr.s،ldsfld،callوldstrالـ (أوبراند) يُحلّون عبر الجداول والكثائب - جدول CIL opcode يغطي كل رمز opcode في وقت التشغيل ويضيف فقط
no. - تبلغ جدول الحفاظ على اسم المعلم في أربعة حاويات ولا في أي منها للرمز الأصلي، وتصنيف في ثلاثة
- كل خط في التجربة يقرأ n من n
- الرقم التفاعلي يضم نفس البيانات
figure_data()تنتج
أساليب فشل الإنتاج
| Failure | What the weak tool reports | What the analysis must prove |
|---|---|---|
| Decompiler older than the interpreter | Unsupported opcode, output marked incomplete, or a claim of obfuscation | The magic word, the release it names, and the tool's documented ceiling |
| pyc read with the wrong interpreter | marshal.loads raises or returns garbage | Our unmarshaller reads names, constants, and sizes from any 3.9 to 3.15 file, and instructions come from the matching dis |
| Specialised opcodes mistaken for the file's content | COMPARE_OP_INT in a listing | A pyc holds the unspecialised form, specialisation happens in memory after warm-up |
| Local names reported for a default javac build | var1, var2 presented as source names | LocalVariableTable is present only with -g, the 50 code bytes are identical either way |
| Branch target off by the instruction length | A JVM listing whose jumps land mid-instruction | Offsets relative to the branch opcode, checked against javap |
| Switch padding skipped | A tableswitch with a wrong default and shifted cases | Zero to three padding bytes to a 4-aligned pc, 36 bytes for five cases |
| Wasm names assumed stripped | "no symbols" | Exports name every exported function, locals need the name section, wasm-strip removes only that section |
| Three tools, three spellings | get_local versus local.get, a function at 0x8b versus 0x8e | Same bytes, and the listing that the comparison was captured with |
| Table row size guessed | Every row after the first table misread | Row sizes from HeapSizes, row counts, and coded index widths, equal to the oracle's |
| Local names expected in a release assembly | V_0 presented as the source name | Locals have types in StandAloneSig and names only in a PDB that DebugType none did not write |
| Reader guesses an unknown opcode or type code | A plausible mnemonic | FormatError with the offset, and the oracle comparison stops there |
| Oracle captured from another build | Tests pass on stale text | build_fixtures.sh names every tool version and writes versions.txt and sha256.txt |
قاعدة العمليات
اقرأ الرأس أولاً وسمي المنتج الذي يشير إليه. اقرأ الحاوية مع قارئ يرفض ما لا يعرفه، و تحقق من قائمةها مع أداة النموذج الخاصة في نفس الملف. ثم قل، لكل اسم وتصفيف في إصدار المتحول، سواء كان الحاوية قد تخزنها أو أداة استنتجته.
المزيد من القراءة
- PEP 552: Deterministic pycs
- CPython
Include/internal/pycore_magic_number.h - Python
marshalmodule documentation - CPython
Python/marshal.c - Python 3.14
dismodule documentation - PEP 659: Specializing Adaptive Interpreter
- PEP 626: Precise line numbers for debugging and other tools
- PEP 790: Python 3.15 Release Schedule
- uncompyle6 on PyPI،decompyle3 on PyPI،xdis on PyPI،pycdc on GitHub،PyLingual on GitHub
- The Java Virtual Machine Specification, Java SE 25, Chapter 4: The class File Format
- The Java Virtual Machine Specification, Java SE 25, Chapter 6: The Java Virtual Machine Instruction Set
- javac manual, Java SE 25وjavap manual
- CFR،Procyon،Vineflower،Fernflower in intellij-community،JADX
- Harrand, Soto-Valero, Monperrus, Baudry, "Java Decompiler Diversity and its Application to Meta-decompilation" (JSS 2020)
- ECMA-335, Common Language Infrastructure, 6th edition (June 2012)
- PE Format, Microsoft Learn
- System.Reflection.Metadata.Ecma335.TableIndex
- ILSpy on GitHub،ilspycmd on NuGet،dnSpyEx on GitHub
- WebAssembly Core Specification: Binary Format, ModulesوValues
- WebAssembly Core Specification: Custom Sections (name section)
- WebAssembly tool-conventions: Debugging
- wabt 1.0.42 release notes،wasm-tools،Binaryen،ghidra-wasm-plugin
- radare2 on GitHub، الإصدار 6.2.4 بنيت من المصدر لهذا الدروس
This free lesson is part of the AI Engineering from Scratch curriculum. Read the full explanation, run the lesson code, and verify the result in the interactive reader or from the repository source.
Browse the complete course catalog or open this lesson on GitHub.