
Uno script per radare2 per analizzare il gopclntab per facilitare il reverse engineering di binari Go.
Nota: Questa funzionalità è stata implementata direttamente nel core di radare2 come plugin di analisi gopc
Un parser gopclntab di Go basato su radare2 per recuperare simboli di funzioni da binari Go, inclusi quelli completamente stripped. Supporta binari ELF, Mach-O e PE su versioni Go 1.2, 1.16, 1.18 e 1.20+.
Ogni binario Go 1.2+ incorpora una regione di dati chiamata gopclntab (Program Counter Line Table) che il runtime di Go utilizza per stack trace, messaggi di panic, garbage collection e supporto al debugger. È una delle fonti più preziose di informazioni sui simboli nei binari Go.
r2gopclntabParser legge questa regione attraverso radare2, analizza le strutture specifiche della versione e stampa l'elenco delle funzioni recuperate (con indirizzi, file sorgente e numeri di riga) oppure applica i nomi recuperati nella sessione aperta di radare2 come definizioni di funzioni, flag e commenti.
| Dipendenza | Versione Minima |
|---|---|
| Python 3 | 3.8+ |
| radare2 | 5.0+ (testato su 6.0.9) |
| r2pipe | qualsiasi |
Non sono richiesti altri pacchetti Python. Lo script utilizza solo la libreria standard (struct, json, argparse, os, sys) più 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
## Riferimento CLI```
usage: r2_gopclntab.py [-h] [-f FILE] [-n FUNCNAME] [-v] [-l]
[--apply] [--json] [--files] [--r2pipe]
| Flag | Descrizione |
|---|---|
-f FILE, --file FILE | Percorso del binario Go da analizzare. Lo script avvia la propria istanza r2. |
--r2pipe | Si collega a una sessione r2 già in esecuzione (da usare dentro la console r2). |
| Flag | Descrizione |
|---|---|
-l, --list | Stampa ogni funzione recuperata con il suo indirizzo. |
-n NAME, --funcname NAME | Stampa solo le funzioni il cui nome contiene NAME (corrispondenza parziale). Se esiste una corrispondenza esatta, il suo indirizzo viene stampato separatamente. |
-v, --verbose | Stampa messaggi di avanzamento, campi dell'intestazione analizzati e offset interni. |
--apply | Scrive i nomi delle funzioni recuperate nella sessione radare2 come definizioni di funzione (af+), flag nel flagspace go. e commenti con il nome Go originale e la posizione nel codice sorgente. |
--json | Invia l'intestazione e l'elenco completo delle funzioni in formato JSON su stdout. |
--files | Stampa l'elenco dei percorsi dei file sorgente estratti dalla tabella dei file. |
-h, --help | Mostra il messaggio di aiuto. |
I flag possono essere combinati liberamente. Se non viene specificato alcun flag di output, il comportamento predefinito è stampare l'intestazione e l'elenco completo delle funzioni.
Tutti gli esempi seguenti sono stati eseguiti su un binario stripped Go 1.26 Mach-O arm64 (compilato con -ldflags="-s -w"). Il programma di test definisce main.main, main.fibonacci, main.helloWorld e main.addNumbers. Il compilatore ha inlineato helloWorld e addNumbers, quindi non appaiono nel gopclntab.
Eseguendo senza flag (o solo con -f) stampa l'intestazione analizzata seguita dalla tabella completa delle funzioni:```
$ python3 r2_gopclntab.py -f ./gotest_stripped
### ☁️ Strumenti per Hacker - MEGA Cloud Drive
Molti strumenti e risorse utilizzati da hacker etici e ricercatori di sicurezza sono disponibili su drive cloud MEGA.```
============================================================
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
Aggiunge il progresso della scansione delle sezioni, i dettagli della risoluzione di textStart e le informazioni sugli offset interni:``` $ python3 r2_gopclntab.py -f ./gotest_stripped -v
Please provide the Markdown content to translate.```
[*] 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+
...