
نص برمجي لـ radare2 لتحليل جدول gopclntab لتسهيل الهندسة العكسية لثنائيات Go.
ملاحظة: تم تنفيذ هذه الميزة مباشرة في نواة radare2 باسم gopc analysis plugin
محلل gopclntab لـ Go يعتمد على radare2 لاستعادة رموز الدوال من ملفات Go الثنائية، بما في ذلك تلك التي تم تجريدها بالكامل. يدعم ملفات ELF و Mach-O و PE عبر إصدارات Go 1.2 و 1.16 و 1.18 و 1.20+.
كل ملف ثنائي لـ Go 1.2+ يحتوي على منطقة بيانات تسمى gopclntab (جدول خطوط عداد البرنامج) التي تستخدمها بيئة تشغيل Go لتتبعات المكدس ورسائل الذعر وجمع القمامة ودعم المصحح. إنها واحدة من أكثر مصادر معلومات الرموز قيمة في ملفات Go الثنائية.
يقرأ r2gopclntabParser هذه المنطقة عبر radare2، ويحلل الهياكل الخاصة بالإصدار، ثم يطبع قائمة الدوال المستعادة (مع العناوين وملفات المصدر وأرقام الأسطر) أو يطبق الأسماء المستعادة مرة أخرى في جلسة radare2 المفتوحة كتعريفات دوال وعلامات وتعليقات.
| التبعية | الحد الأدنى للإصدار |
|---|---|
| Python 3 | 3.8+ |
| radare2 | 5.0+ (تم الاختبار على 6.0.9) |
| r2pipe | أي |
لا يلزم وجود حزم Python أخرى. يستخدم البرنامج النصي فقط المكتبة القياسية (struct, json, argparse, os, sys) بالإضافة إلى r2pipe.
python3 r2_gopclntab.py -f ./mybinary -l
python3 r2_gopclntab.py -f ./mybinary -n main.main
python3 r2_gopclntab.py -f ./mybinary -v -l
python3 r2_gopclntab.py -f ./mybinary --apply
python3 r2_gopclntab.py -f ./mybinary --json
#!pipe python3 r2_gopclntab.py --r2pipe --apply -v
## مرجع CLI```
usage: r2_gopclntab.py [-h] [-f FILE] [-n FUNCNAME] [-v] [-l]
[--apply] [--json] [--files] [--r2pipe]
| العلم | الوصف |
|---|---|
-f FILE, --file FILE | مسار الملف الثنائي Go لتحليله. يقوم السكريبت بتشغيل مثيل r2 خاص به. |
--r2pipe | الاتصال بجلسة r2 قيد التشغيل (للاستخدام داخل وحدة تحكم r2). |
| العلم | الوصف |
|---|---|
-l, --list | طباعة كل دالة مستردة مع عنوانها. |
-n NAME, --funcname NAME | طباعة الدوال التي يحتوي اسمها على NAME فقط (مطابقة جزئية). في حالة وجود تطابق تام، يتم طباعة عنوانه بشكل منفصل. |
-v, --verbose | طباعة رسائل التقدم، وحقول الرأس المُحللة، والإزاحات الداخلية. |
--apply | كتابة أسماء الدوال المستردة في جلسة radare2 كتعريفات دالة (af+)، وعلم في مساحة الأعلام go.، وتعليقات مع اسم Go الأصلي وموقع المصدر. |
--json | إخراج الرأس وقائمة الدوال الكاملة بصيغة JSON إلى stdout. |
--files | طباعة قائمة مسارات ملفات المصدر المستخرجة من جدول الملفات. |
-h, --help | إظهار رسالة المساعدة. |
يمكن دمج الأعلام بحرية. عندما لا يتم إعطاء علم إخراج، يكون السلوك الافتراضي هو طباعة الرأس وقائمة الدوال الكاملة.
جميع الأمثلة أدناه تم تشغيلها على ملف ثنائي Go 1.26 Mach-O arm64 مُجرّد (مبني بـ -ldflags="-s -w"). البرنامج الاختباري يعرّف main.main، main.fibonacci، main.helloWorld، وmain.addNumbers. قام المترجم بدمج helloWorld وaddNumbers داخلياً، لذا لا تظهران في gopclntab.
التشغيل بدون أعلام (أو فقط -f) يطبع الرأس المُحلل متبوعًا بجدول الدوال الكامل:```
$ python3 r2_gopclntab.py -f ./gotest_stripped
يبدو أن الإدخال فارغ. لا يوجد نص للترجمة.```
============================================================
Go pclntab Header
============================================================
Magic: 0xFFFFFFF1
Go version: 1.20+
Pointer size: 8
Min LC (quantum):4
Num functions: 2030
Num files: 261
funcnameOffset: 0x48
cuOffset: 0x14D20
filetabOffset: 0x158D8
pctabOffset: 0x19A98
pclnOffset: 0x55E40
============================================================
ADDRESS FUNCTION NAME
----------------------------------------------------------------------
0x100001000 go:buildid
0x100001070 internal/abi.BoundsDecode (/opt/homebrew/Cellar/go/1.26.1/libexec/src/internal/abi/bounds.go:86)
0x100001150 internal/abi.NoEscape (/opt/homebrew/Cellar/go/1.26.1/libexec/src/internal/abi/escape.go:19)
0x100001160 internal/abi.Kind.String (/opt/homebrew/Cellar/go/1.26.1/libexec/src/internal/abi/type.go:143)
0x1000011E0 internal/abi.TypeOf (/opt/homebrew/Cellar/go/1.26.1/libexec/src/internal/abi/type.go:181)
0x1000011F0 internal/abi.(*Type).ExportedMethods (/opt/homebrew/Cellar/go/1.26.1/libexec/src/internal/abi/type.go:453)
...
0x1000A0BB0 main.fibonacci (/tmp/gotest/main.go:13)
0x1000A0C20 main.main (/tmp/gotest/main.go:20)
0x1000A0D20 go:textfipsstart
0x1000A0D30 go:textfipsend
[+] 2030 function(s) shown
يضيف تقدم فحص الأقسام، وتفاصيل دقة textStart، ومعلومات الإزاحة الداخلية:``` $ python3 r2_gopclntab.py -f ./gotest_stripped -v
* أُضيفت أوضاع الواجهة الداكنة والفاتحة (يمكن تغييرها من شريط الأدوات)
* التاريخ: 24 يناير 2022
* الإصدار: 2.2.0
* حقوق النشر (c) 2015-2022 [Yogesh Khatri](https://github.com/ydkhatri) ([@SwiftForensics](https://twitter.com/SwiftForensics))```
[*] Running radare2 analysis...
[*] Binary format: mach0, endian: little, arch: arm, bits: 64
[*] Scanning binary for gopclntab magic bytes...
[*] Scanning section '0.__TEXT.__text' (0x100001000, 0x9FD44)...
[*] Scanning section '1.__TEXT.__symbol_stub1' (0x1000A0D60, 0x2B8)...
[*] Scanning section '2.__TEXT.__rodata' (0x1000A1020, 0xACC2)...
[*] Scanning section '3.__TEXT.__gopclntab' (0x1000ABCE8, 0xA48AE)...
[*] Found magic at vaddr=0x1000ABCE8
[*] Parsed header: PcHeader(magic=0xFFFFFFF1, version=1.20+, ptrSize=8, minLC=4,
nfunc=2030, nfiles=261, textStart=0x0)
[*] textStart is 0, using .text section vaddr: 0x100001000
[*] Parsed 2030 functions
============================================================
Go pclntab Header
============================================================
Magic: 0xFFFFFFF1
Go version: 1.20+
...
يقوم بتصفية قائمة الدوال حسب تطابق السلسلة الفرعية. إذا وُجد تطابق تام، يتم طباعة عنوانه بشكل منفصل.
بحث عن السلسلة الفرعية لجميع الدوال التي تحتوي على main.:```
$ python3 r2_gopclntab.py -f ./gotest_stripped -n "main."
Please provide the Markdown content to translate.```
ADDRESS FUNCTION NAME
----------------------------------------------------------------------
0x100041920 runtime.main.func2 (/opt/homebrew/Cellar/go/1.26.1/libexec/src/runtime/proc.go:207)
0x10006CE30 runtime.main.func1 (/opt/homebrew/Cellar/go/1.26.1/libexec/src/runtime/proc.go:174)
0x1000A0BB0 main.fibonacci (/tmp/gotest/main.go:13)
0x1000A0C20 main.main (/tmp/gotest/main.go:20)