Skip to content
KitploitKITPLOIT
StrumentiBlog
Invia
StrumentiBlog
Invia

Strumenti di Hacking, PenTest e Cybersecurity per il tuo Arsenale di Sicurezza!

Kitploit è una directory di strumenti di hacking, cybersecurity e pentesting. Scopri gli ultimi aggiornamenti dei progetti per trovare vulnerabilità, analizzare sistemi, automatizzare i test e rafforzare la tua sicurezza.

··Feed·Contatto·Privacy·© 2026 Kitploit

Directory degli strumenti

Categorie

Vedi tutte le categorie
Loading categories
r2gopclntabParser — Uno script per radare2 per analizzare il gopclntab per facilitare il reverse engineering di binari Go. | Kitploit
Strumenti/GitHubGitHub/asherdll/r2gopclntabparser
Analisi StaticaReverse EngineeringDebuggerInformatica ForenseAnalisi MalwareAnalisi di Binari
GitHubasherdll/r2gopclntabparser

r2gopclntabParser

Uno script per radare2 per analizzare il gopclntab per facilitare il reverse engineering di binari Go.

Vedi Repository
174 mesi faNon ancora revisionato

Più Popolari

Vedi tutti →

Scopri gli strumenti più utilizzati dalla nostra community.

Esplora tutti gli strumenti

Sfoglia la nostra collezione di strumenti

Vedi tutti gli strumenti →
Condividi

r2gopclntabParser

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.


Indice

  • Prerequisiti
  • Avvio Rapido
  • Riferimento CLI
  • Modalità di Output ed Esempi
    • Modalità Predefinita (Intestazione + Elenco Funzioni)
    • Modalità Dettagliata (-v)
    • Modalità Ricerca (-n)
    • Output JSON (--json)
    • Elenco File Sorgente (--files)
    • Modalità Applica (--apply)
  • Riepilogo Risultati: Mach-O (Binario di Test Stripped)
  • Test PE: Greenblood, un Binario Ransomware Go
  • Casi d'Uso per Reverse Engineering
  • Piattaforme e Versioni Go Supportate
  • Metodologia
    • Strategia di Localizzazione delle Sezioni
    • textStart vs Sezione .text
    • Parsing delle Strutture in base alla Versione
    • Decodifica dei Dati PC
  • Limitazioni
  • Documentazione Aggiuntiva
  • Riferimenti

Prerequisiti

DipendenzaVersione Minima
Python 33.8+
radare25.0+ (testato su 6.0.9)
r2pipequalsiasi

Non sono richiesti altri pacchetti Python. Lo script utilizza solo la libreria standard (struct, json, argparse, os, sys) più r2pipe.


Avvio Rapido```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:~
## Riferimento CLI```
usage: r2_gopclntab.py [-h] [-f FILE] [-n FUNCNAME] [-v] [-l]
                       [--apply] [--json] [--files] [--r2pipe]

Obbligatorio (uno tra)

FlagDescrizione
-f FILE, --file FILEPercorso del binario Go da analizzare. Lo script avvia la propria istanza r2.
--r2pipeSi collega a una sessione r2 già in esecuzione (da usare dentro la console r2).

Opzionale

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.


Modalità di output ed esempi

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.

Modalità predefinita (intestazione + elenco funzioni)

Eseguendo senza flag (o solo con -f) stampa l'intestazione analizzata seguita dalla tabella completa delle funzioni:``` $ python3 r2_gopclntab.py -f ./gotest_stripped

root@kitploit:~
### ☁️ 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

Modalità Verbosa (-v)

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

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

Modalità di ricerca (-n)

Filtra la lista delle funzioni per corrispondenza di sottostringa. Se esiste una corrispondenza esatta, il suo indirizzo viene stampato separatamente.

Ricerca per sottostringa per tutte le funzioni contenenti main.:``` $ python3 r2_gopclntab.py -f ./gotest_stripped -n "main."

root@kitploit:~
(empty response due to missing input)```
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)

Ricerca esatta:``` $ python3 r2_gopclntab.py -f ./gotest_stripped -n "main.fibonacci"

root@kitploit:~
Since no input was provided, there is no text to translate. Please provide the chunk content.```
ADDRESS       FUNCTION NAME
----------------------------------------------------------------------
0x1000A0BB0   main.fibonacci  (/tmp/gotest/main.go:13)

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

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

Ricerca degli interni del runtime correlati al GC:``` $ python3 r2_gopclntab.py -f ./gotest_stripped -n "runtime.gc"

root@kitploit:~
- [Httpx](https://github.com/projectdiscovery/httpx) - Un toolkit HTTP veloce e multiuso che permette di eseguire più probe utilizzando la libreria retryablehttp. Progettato per mantenere l'affidabilità dei risultati con un numero maggiore di thread.
- [Jsubfinder](https://github.com/ThreatUnkown/jsubfinder) - Cerca pagine web alla ricerca di JavaScript e le analizza per individuare sottodomini nascosti e segreti. Supporta regex personalizzate, risultati di ricerca organizzati.
- [Knock](https://github.com/guelfoweb/knock) - Knockpy è uno strumento Python progettato per enumerare i sottodomini su un dominio target tramite una wordlist. Progettato per eseguire la scansione del trasferimento di zona DNS e anche per tentare di bypassare automaticamente il carattere jolly.
- [Lepus](https://github.com/gfek/Lepus) - Una utility per identificare i sottodomini, verificare la presenza di caratteri jolly ed eseguire ricognizione passiva per raccogliere informazioni sul target.
- [Massdns](https://github.com/blechschmidt/massdns) - Un resolver DNS stub ad alte prestazioni per ricerche massive e ricognizione (mass, da cui il nome). Supporta un'ampia gamma di tipi di record DNS e formati di output.
- [Puredns](https://github.com/d3mondev/puredns) - Strumento veloce di risoluzione dei domini e di brute force dei sottodomini in grado di filtrare accuratamente i sottodomini jolly e le voci DNS avvelenate.
- [Raptor](https://github.com/0xdea/raptor) - Strumento che esegue ricognizione DNS con diverse tecniche tra cui brute force DNS, trasferimento di zona DNS, test del carattere jolly DNS ed enumerazione dei tipi di record DNS.
- [Shuffledns](https://github.com/projectdiscovery/shuffledns) - Un wrapper scritto in Go per massdns che consente di enumerare sottodomini validi utilizzando brute force attivo, nonché di risolvere i sottodomini con gestione dei caratteri jolly e un semplice supporto input-output.
- [Subfinder](https://github.com/projectdiscovery/subfinder) - Strumento di scoperta dei sottodomini che individua sottodomini validi per i siti web. Progettato come framework passivo per essere utile per i bug bounty e sicuro per i penetration test.
- [Turbolist3r](https://github.com/alex14324/Turbolist3r) - Strumento di enumerazione dei sottodomini con funzionalità di analisi per i domini scoperti. Utilizza un'architettura client-server per l'enumerazione distribuita e supporta più sorgenti.
- [Turbolist3r](https://github.com/fleetcaptain/Turbolist3r) - Un fork dello strumento di scoperta sottodomini sublist3r che integra funzionalità di brute force dei sottodomini con risoluzione DNS e gestione migliorata dell'output.```
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)

Ricerca di fmt. (stampa della libreria standard):``` $ python3 r2_gopclntab.py -f ./gotest_stripped -n "fmt."

root@kitploit:~
| `-n` | Nome del listener. Se non specificato, viene utilizzato un nome generato a partire dagli argomenti. |
| `-a`, `--address` | Indirizzo del listener. Se non specificato, verrà utilizzato l'indirizzo dell'adattatore. |
| `-p`, `--port` | Porta del listener. |
| `-s`, `--server` | **IMPORTANTE:** Il dominio, l'indirizzo IPv4 o l'indirizzo IPv6 per il server HTML Follina. Per scenari avanzati, potrebbe essere l'indirizzo del redirector. |
| `-P`, `--server-port` | Porta per il server HTML Follina. Predefinita `8080`. |
| `-w`, `--wait` | Tempo di attesa per una connessione in ingresso, in secondi. Predefinito `0` secondi. |
| `-t`, `--type` | Tipo di payload personalizzato da eseguire. Predefinito `custom` (esegue uno script personalizzato codificato in base64). |
| `-d`, `--payload` | Il payload dello script personalizzato da eseguire, richiesto quando `--type` è `custom`. |
| `--http-port` | Porta su cui avviare il server HTTP. Predefinita `80`. |
| `--https-port` | Porta su cui avviare il server HTTPS. Predefinita `443`. |
| `--payload-path` | **IMPORTANTE:** Specifica un percorso del payload da eseguire. (Il percorso relativo inizia con "." esempio: `..\path\to\payload`). |
| `—no-https` | Di default, insieme al server HTTP viene avviata anche un'operazione HTTPS. Questa opzione abilita solo un server HTTP. |```
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)
...

Ricerca di sync. (primitive di concorrenza):``` $ python3 r2_gopclntab.py -f ./gotest_stripped -n "sync."

root@kitploit:~
*   Funziona con il framework MITRE ATT&CK®.```
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)
...

Output JSON (--json)

Output leggibile dalla macchina per scripting e integrazione pipeline:``` $ python3 r2_gopclntab.py -f ./gotest_stripped --json

root@kitploit:~
shields.io/badge/HackTheBox-Profile-9cf?style=for-the-badge&logo=HackTheBox&logoColor=white)](https://www.hackthebox.eu/home/users/profile/12345)```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
}

Elenco dei file sorgente (--files)

Estrae tutti i percorsi dei file sorgente incorporati nel binario:``` $ python3 r2_gopclntab.py -f ./gotest_stripped --files

root@kitploit:~
[*] HTTP/2 è in uso per la comunicazione
    [+] Il target imposta i cookie utilizzando il cookie \x1b[1;34m__cf_bm\x1b[0m, indicativo della gestione dei bot di CloudFlare
    [*] Sembra che il target sia protetto da CloudFlare. Prova a usare cloudscraper per aggirare questo.
    [!] Cookie 'cf_clearance' mancante, il bypass automatico potrebbe non funzionare. Fallo manualmente...```
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
  <autogenerated>
  /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

Modalità Apply (--apply)

Scrive tutti i nomi di funzione recuperati nella sessione di radare2. Il seguente mostra un confronto prima/dopo sul binario privo di simboli.

PRIMA (analisi nativa di r2 su binario privo di simboli, senza parsing di gopclntab):``` Functions found by r2 natively: 1913

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

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

root@kitploit:~
r2 ha trovato 1913 funzioni ma non ne ha nominata nessuna (solo etichette anonime `fcn.XXXXXXXX`). La ricerca di `main.main` o `main.fibonacci` non restituisce nulla. **Applicazione dei simboli 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)

DOPO (sessione r2 con simboli gopclntab applicati):``` 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

root@kitploit:~
Il disassemblaggio a `main.main` ora mostra il nome recuperato e la posizione del sorgente:```
            ;-- 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

Il disassemblaggio a main.fibonacci ora mostra il nome e la posizione del sorgente recuperati:``` ;-- 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

root@kitploit:~
La ricerca per nome ora funziona nella sessione r2:```
go.main.main resolves to: 0x1000a0c20
go.main.fibonacci resolves to: 0x1000a0bb0

Riepilogo dei risultati: Mach-O (Binary di test senza simboli)


Test PE: Greenblood, un Binary Ransomware in Go

Il parser è stato testato contro un binario PE reale, Greenblood (greenblood_1), un campione di ransomware in Go compilato come eseguibile Windows PE32+ x86-64. I binari PE non hanno una sezione .gopclntab dedicata, quindi questo esercita il percorso di fallback di scansione dei byte magici.

Rilevamento e Intestazione```

$ python3 r2_gopclntab.py -f ./greenblood_1 -v

root@kitploit:~

$ cat src/sh/jarm.sh ... ... $ sh src/sh/jarm.sh google.com | grep JARM JARM: 27d40d40d00040d000042d43d0000009e9f4e9c120f97792cbd22bfb3f192 ✅ Host google.com JARM: 27d40d40d00040d000042d43d0000009e9f4e9c120f97792cbd22bfb3f192 Esempio di analisi della cronologia dei certificati in tempo reale:

root@kitploit:~
[*] 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
```
Lo scanner ha trovato il gopclntab all'interno della sezione `.rdata` a `0x568C00`.
Poiché questo è un PE standard (non PIE), `textStart` è `0x401000` (non zero), quindi il valore dell'intestazione viene utilizzato direttamente per il calcolo dell'indirizzo.

| Campo | Valore |
|---|---|
| Formato | PE32+ x86-64 |
| Posizione gopclntab | `.rdata` a `0x568C00` (trovato tramite scansione magica) |
| Magic | `0xFFFFFFF1` (Go 1.20+) |
| Dimensione puntatore | 8 |
| Quantum (minLC) | 1 (x86) |
| textStart | `0x401000` (dall'intestazione) |
| Funzioni recuperate | 2596 |
| File sorgenti | 345 |

### Funzioni del malware recuperate

Ricerca del codice del malware stesso (`main.`):```
$ python3 r2_gopclntab.py -f ./greenblood_1 -n "main."
```
Esegui lo script `crypt.py` con il comando `python3 crypt.py` nel terminale. Assicurati di avere le dipendenze necessarie installate (`pycryptodome`, `requests`, `colorama`).```
ADDRESS       FUNCTION NAME
----------------------------------------------------------------------
0x4D91E0      main.init  (<autogenerated>: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)
```
Tutte le 43 funzioni utente sono state recuperate da un unico file sorgente in
`/root/victims/ransom/daf/enc.go`. I nomi delle funzioni rivelano immediatamente le
capacità del ransomware: gestione delle chiavi, fingerprinting della macchina,
crittografia dei file con traversal di path, posizionamento della nota di riscatto,
disabilitazione del ripristino, controllo dei privilegi, esecuzione di singola istanza
basata su mutex, enumerazione delle unità e auto-eliminazione.

### Dipendenze non standard della libreria

Estrazione dei file sorgente che non fanno parte della libreria standard di 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
```
L'unica dipendenza esterna è `golang.org/x/[email protected]` per le syscall specifiche di Windows (accesso al registro, token di sicurezza, caricamento DLL).

### Funzioni crittografiche

La ricerca di `crypto` rivela 137 funzioni legate a crittografia, tra cui:```
$ python3 r2_gopclntab.py -f ./greenblood_1 -n "crypto"
```
[No content to translate.]```
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)
```
Il profilo di utilizzo crittografico: AES (modalità CBC e CTR), SHA-256, SHA-512, HMAC, CSHAKE128 e DRBG (generatore deterministico di bit casuali). Ciò è coerente con ransomware che genera chiavi di crittografia per-macchina derivate da un'impronta della macchina, crittografa file con AES-CTR e utilizza HMAC per l'integrità.

### Apply Mode```
$ 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.
```
Tutte le 2596 funzioni applicate con successo, nessuna saltata.

---

## Casi d'uso per il Reverse Engineering

### 1. Triage e Identificazione

Determina istantaneamente se un binario è Go, con quale versione è stato compilato e
quali pacchetti utilizza. L'output `--files` rivela la versione del toolchain Go
(da percorsi file come `/usr/local/go/1.26.1/...`) e ogni percorso di file sorgente,
incluse le librerie di terze parti. Per il malware, questo rivela immediatamente se
il campione utilizza `crypto/tls`, `net/http`, `os/exec` o altri pacchetti di
interesse.

### 2. Recupero dei Simboli su Binari Strippati

Il caso d'uso principale. I binari Go strippati con `-ldflags="-s -w"` perdono la
tabella dei simboli, ma gopclntab sopravvive. Questo strumento ripristina ogni nome di funzione,
trasformando anonime `fcn.1000a0c20` in `main.main`. Questo si applica a
campioni di malware, sfide CTF, binari di produzione e qualsiasi eseguibile Go
strippato.

### 3. Navigazione del Runtime Go

I binari Go incorporano l'intero runtime (tipicamente da 1500 a oltre 2000 funzioni).
Senza nomi, il runtime è un muro impenetrabile di funzioni anonime.
Con i nomi, puoi individuare istantaneamente `runtime.mallocgc`, `runtime.gopanic`,
`runtime.newproc`, `runtime.gcStart` e capire cosa sta facendo il binario
in ogni punto di chiamata.

### 4. Separazione del Codice Utente dal Runtime

Cercando `main.` o il percorso del pacchetto dell'applicazione, puoi isolare
solo il codice dell'utente dal runtime. Negli esempi sopra, filtrando per
`main.` si rivelano immediatamente `main.main` e `main.fibonacci` tra 2030
funzioni totali. Puoi anche cercare per nome di pacchetto di terze parti
(es., `-n "github.com/user/repo"`) per identificare dipendenze esterne.

### 5. Contesto a Livello di Sorgente

Ogni funzione viene fornita con il percorso del file sorgente e il numero di riga di inizio. Questo
significa che puoi incrociare il disassemblaggio con il codice sorgente della libreria standard
Go (che è aperto), anche quando analizzi un binario strippato. Sapere
che una funzione inizia alla riga 733 di `runtime/mgc.go` ti permette di leggere il
sorgente originale insieme al disassemblaggio.

### 6. Pipeline e Automazione

La modalità `--json` abilita lo scripting. Invia l'output a importatori per IDA/Ghidra,
strumenti di diff, generatori di regole YARA o qualsiasi pipeline di analisi.
Ad esempio, per estrarre tutte le funzioni relative alla crittografia:```bash
python3 r2_gopclntab.py -f sample.exe --json \
  | jq '.functions[] | select(.name | contains("crypto"))'
```
### 7. Flusso di lavoro interattivo con radare2

Dopo `--apply`, l'intera sessione r2 diventa navigabile per nome Go. Puoi
posizionarti sulle funzioni (`s go.main.main`), cercare nell'elenco delle
funzioni (`afl~runtime.gc`), ispezionare i riferimenti incrociati
(`axf go.main.fibonacci`) e vedere i commenti sulla posizione del codice
sorgente direttamente nell'output del disassemblatore (`pd`). Questo
trasforma r2 da un disassemblatore generico in un ambiente di analisi
consapevole di Go.

---

## Piattaforme supportate e versioni di Go

### Formati binari

| Formato | Metodo di individuazione delle sezioni | Testato |
|---|---|---|
| ELF (Linux) | Nome sezione `.gopclntab` o `.data.rel.ro.gopclntab` | Sì |
| Mach-O (macOS) | Nome sezione `__gopclntab` (all'interno del segmento `__TEXT`) | Sì |
| PE (Windows) | Scansione dei byte magici (nessuna sezione dedicata) | Sì (testato su Greenblood, un ransomware Go PE64) |

Per i binari PE e i binari ELF/Mach-O fortemente stripati privi dell'intestazione
della sezione, lo strumento ricade sulla scansione di tutte le sezioni alla
ricerca dei 4 byte magici seguiti dai byte di validazione (pad=0, ptrSize in {4,8},
minLC in {1,2,4}).

### Versioni di Go

| Magic | Versione Go | `textStart` nell'intestazione | Tipo `functab.entry` | Campo `startLine` | Stato |
|---|---|---|---|---|---|
| `0xFFFFFFFB` | 1.2 | No | `uintptr` (assoluto) | No | Supportato |
| `0xFFFFFFFA` | 1.16 | No | `uintptr` (assoluto) | No | Supportato |
| `0xFFFFFFF0` | 1.18 - 1.19 | Sì | `uint32` (relativo) | No | Supportato |
| `0xFFFFFFF1` | 1.20+ | Sì (può essere 0) | `uint32` (relativo) | Sì | Supportato |

Il magic `0xFFFFFFF1` è utilizzato da Go 1.20 fino almeno a Go 1.26.

---

## Metodologia

### Strategia di localizzazione delle sezioni

Il parser utilizza un approccio a due fasi per trovare i dati gopclntab:

**Fase 1 (ELF/Mach-O):** Interroga l'elenco delle sezioni di radare2 (`iSj`) e cerca
le sezioni denominate `.gopclntab`, `.data.rel.ro.gopclntab` o `__gopclntab`.

**Fase 2 (PE/fallback):** Se non viene trovata alcuna sezione nominata, scansiona
tutte le sezioni alla ricerca dei 4 byte magici. Ogni candidato viene validato
verificando che i byte 4-7 corrispondano allo schema atteso: due byte di padding
zero, una dimensione del puntatore valida (4 o 8) e un quanto di istruzione
valido (1, 2 o 4). Questo elimina i falsi positivi derivanti da pattern
byte coincidenti.

### textStart contro la sezione .text

In Go >= 1.18, gli indirizzi di ingresso delle funzioni nella functab sono
memorizzati come offset relativi. Il calcolo dell'indirizzo virtuale assoluto
richiede una base:```
absolute_addr = base + entryoff
```
La base viene risolta con la seguente logica:```
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
```
Il caso `textStart == 0` si verifica in Go >= 1.22 per binari Mach-O e PIE.
Quando ciò accade, i valori di `entryoff` sono relativi all'inizio della sezione `.text`,
quindi il parser interroga r2 per l'indirizzo virtuale di `.text` e lo utilizza
come base.

Ciò è stato verificato su un binario Go 1.26 Mach-O arm64:
- `textStart` nell'header: `0x0`
- vaddr della sezione `.text`: `0x100001000`
- `functab[1].entryoff`: `0x70`
- Indirizzo calcolato: `0x100001000 + 0x70 = 0x100001070`
- L'analisi nativa di r2 ha confermato `internal/abi.BoundsDecode` a `0x100001070`

### Parsing Strutturale Versione-Consapevole

Il layout della struct `_func` differisce tra Go 1.18 e Go 1.20+. L'unica
modifica è l'inserimento di un campo `startLine` di 4 byte all'offset 36 in Go
1.20+, che sposta `funcID`, `flag` e `nfuncdata` di 4 byte:

| Campo | Offset Go 1.18 | Offset Go 1.20+ |
|---|---|---|
| `entryOff` | 0 | 0 |
| `nameOff` | 4 | 4 |
| `args` | 8 | 8 |
| `cuOffset` | 32 | 32 |
| `startLine` | (assente) | 36 |
| `funcID` | 36 | 40 |
| `flag` | 37 | 41 |
| `nfuncdata` | 39 | 43 |

Il parser controlla il numero magico per determinare quale layout utilizzare.

### Decodifica dei Dati PC

Gli indici dei file sorgente e i numeri di riga sono memorizzati come "programmi dati PC" compatti
nella regione pctab. Ogni programma codifica una sequenza
di coppie `(value_delta, pc_delta)` utilizzando interi a lunghezza variabile con codifica
zig-zag per i valori con segno. Il parser decodifica questi per risolvere:

- File sorgente: `_func.pcfile` -> programma pctab -> indice file -> cutab ->
  filetab -> stringa del percorso del file
- Numero di riga: `_func.pcln` -> programma pctab -> numero di riga (più
  l'offset `startLine` per Go 1.20+)

---

## Limitazioni

1. **Le funzioni inline** non appaiono nella tabella delle funzioni di primo livello. Esse
   sono codificate nelle strutture `FUNCDATA_InlTree` / `PCDATA_InlTreeIndex`,
   che questo strumento attualmente non decodifica. Nel binario di test,
   `main.helloWorld` e `main.addNumbers` sono state inline dal compilatore e quindi
   non compaiono nell'output.

2. **Il supporto Go 1.2** è al meglio. Il formato Go 1.2 è sostanzialmente
   diverso (nessun funcnametab separato, nessun cutab, puntatori assoluti in functab)
   e si incontra raramente nella pratica.

3. **Architetture big-endian** sono gestite in linea di principio (l'endianess è
   rilevata dalle informazioni binarie di radare2 e utilizzata per tutte le letture di struct)
   ma non sono state testate.

4. La modalità `--apply` crea stub di funzione con `af+` che possono entrare in conflitto
   con l'auto-analisi di r2. Eseguirla su una sessione pulita (prima o
   invece di `aaa`) può dare risultati migliori in alcuni casi.

---

## Documentazione Aggiuntiva

La documentazione tecnica dettagliata è disponibile nella directory `documentation/`:

- [DOCUMENTATION.md](https://github.com/asherdll/r2gopclntabparser/blob/HEAD/documentation/DOCUMENTATION.md) - Documentazione utente completa
  con tutte le modalità di utilizzo, i formati di output e le combinazioni di flag.
- [METHODOLOGY.md](https://github.com/asherdll/r2gopclntabparser/blob/HEAD/documentation/METHODOLOGY.md) - Decisioni progettuali e
  algoritmi: risoluzione textStart vs .text, parsing versione-consapevole,
  strategia di scansione PE, decodifica dati PC, dettagli integrazione r2.
- [GOPCLNTAB_FORMAT.md](https://github.com/asherdll/r2gopclntabparser/blob/HEAD/documentation/GOPCLNTAB_FORMAT.md) - Il formato binario gopclntab
  attraverso le versioni di Go: layout delle struct a livello di byte, modello di memoria,
  catene di offset, codifica varint, riepilogo differenze tra versioni.

---

## Riferimenti

- Sorgente runtime Go (pcHeader): [go1.20.6/src/runtime/symtab.go#L414](https://github.com/golang/go/blob/go1.20.6/src/runtime/symtab.go#L414)
- Linker Go (scrive il formato): [go1.20.6/src/cmd/link/internal/ld/pcln.go](https://github.com/golang/go/blob/go1.20.6/src/cmd/link/internal/ld/pcln.go)
- Mandiant - Golang Internals Symbol Recovery: [mandiant.com/resources/blog/golang-internals-symbol-recovery](https://www.mandiant.com/resources/blog/golang-internals-symbol-recovery)
- Documento di progettazione tabella simboli Go 1.2: [docs.google.com/document/d/1lyPIbmsYbXnpNj57a261hgOYVpNRcgydurVQIyZOz_o](https://docs.google.com/document/d/1lyPIbmsYbXnpNj57a261hgOYVpNRcgydurVQIyZOz_o/pub)
Scarica lo strumento
FlagDescrizione
-l, --listStampa ogni funzione recuperata con il suo indirizzo.
-n NAME, --funcname NAMEStampa solo le funzioni il cui nome contiene NAME (corrispondenza parziale). Se esiste una corrispondenza esatta, il suo indirizzo viene stampato separatamente.
-v, --verboseStampa messaggi di avanzamento, campi dell'intestazione analizzati e offset interni.
--applyScrive 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.
--jsonInvia l'intestazione e l'elenco completo delle funzioni in formato JSON su stdout.
--filesStampa l'elenco dei percorsi dei file sorgente estratti dalla tabella dei file.
-h, --helpMostra il messaggio di aiuto.
Metricar2 Nativo (senza simboli)Dopo r2_gopclntab.py
Funzioni trovate1913 (etichette anonime fcn.XXXX)2030 (nomi completi con pacchetto Go)
Funzioni utente identificate0main.main, main.fibonacci con sorgente + riga
File sorgente recuperati0261 (percorsi assoluti completi)
Simboli denominatiSolo stub di import C (sym.imp.mmap, ecc.)Ogni funzione Go etichettata (go.main.main, go.runtime.gcStart, ecc.)
Commenti sorgenteNessunoIn linea src: /tmp/gotest/main.go:20 nel disassemblato
Navigabile per nomeNoSì (s go.main.main, afl~runtime.gc)