
Analizza i binari Go per recuperare simboli, metadati delle funzioni, tipi, percorsi di file e stringhe incorporate, inclusi campioni stripped o pacchettizzati con UPX, con supporto all'importazione in IDA Pro.

GoReSym è un parser di simboli Go che estrae metadati del programma (come architettura della CPU, sistema operativo, endianness, versione del compilatore, ecc.), metadati delle funzioni (indirizzi di inizio e fine, nomi, sorgenti), metadati di nomi di file e numeri di riga, e strutture e tipi incorporati. Questo programma multipiattaforma si basa direttamente sul compilatore Go open source e sul codice del runtime.
Il codice del runtime Go upstream è esteso per gestire:
moduledataFare riferimento a https://www.mandiant.com/resources/blog/golang-internals-symbol-recovery per i dettagli di reverse engineering e gli esempi d'uso.
È possibile scaricare i binari GoReSym precompilati per linux, macos e windows dalla scheda Releases.
Per compilare dal sorgente con un compilatore Go recente, invocare il compilatore Go:
go build
Una volta compilato, invoca GoReSym in questo modo:
GoReSym.exe -t -d -p /path/to/input.exe
In questo esempio, chiediamo a GoReSym di recuperare i nomi dei tipi (-t), i nomi dei pacchetti utente, i nomi dei pacchetti standard Go (-d) e i percorsi dei file di input (-p) incorporati nel file /path/to/input.exe. L'output è simile a questo:
{
"Version": "1.14.15",
"BuildId": "Zb9QmokKTiOUgHKmaIwz/wd2rtE3W9PN-um1Ocdzh/qTdqcTY_jVajHy_-TtYv/Z_kJu9M77OjfijEiHMcF",
"Arch": "amd64",
"TabMeta": {
"VA": 5174784,
"Version": "1.2",
"Endianess": "LittleEndian",
"CpuQuantum": 1,
"CpuQuantumStr": "x86/x64",
"PointerSize": 8
},
"ModuleMeta": {
"VA": 5678816,
"Types": 4845568,
"ETypes": 5171904,
"Typelinks": {
"Data": 5171904,
"Len": 695,
"Capacity": 695
},
"ITablinks": {
"Data": 5174688,
"Len": 11,
"Capacity": 11
},
"LegacyTypes": {
"Data": 0,
"Len": 0,
"Capacity": 0
}
},
"Types": [ ... ],
"Files": [ ... ],
"Strings": [ ... ],
"UserFunctions": [ ... ],
"StdFunctions": [ ... ]
}
Ecco tutti i flag disponibili:
-d ("default", opzionale) stamperà i pacchetti Go standard in aggiunta ai pacchetti utente.-p ("paths", opzionale) stamperà eventuali percorsi di file incorporati nel pclntab.-t ("types", opzionale) stamperà i nomi dei tipi Go.-strings (opzionale) estrarrà le stringhe Go incorporate dal binario analizzando la tabella di internamento delle stringhe.-m <virtual address> ("manual", opzionale) eseguirà il dump della struttura RTYPE in modo ricorsivo all'indirizzo virtuale specificato-v <version string> ("version", opzionale) sovrascriverà il rilevamento automatico della versione e utilizzerà la versione fornita. Questo è necessario per alcuni binari stripped. L'analisi dei tipi fallirà se la versione non è accurata.-human (opzionale) stamperà un elenco testuale semplice invece di JSON. Particolarmente utile quando si stampano tipi struttura e interfaccia.-about (opzionale) stamperà le informazioni sulla licenzaPer importare queste informazioni in IDA Pro è possibile eseguire lo script presente in https://github.com/mandiant/GoReSym/blob/master/IDAPython/goresym_rename.py. Leggerà un file json prodotto da GoReSym e imposterà simboli/etichette in IDA.
Poiché il compilatore e il runtime Go sono cambiati, sono cambiate anche le strutture dei metadati incorporate. GoReSym supporta le seguenti combinazioni di release Go e metadati:
pclntab: >= Go 1.2moduledata: >= Go 1.2moduledata: >= Go 1.5La tabella moduledata utilizzata per estrarre i tipi non esiste prima di Go 1.5, quindi questa libreria non supporterà mai l'estrazione dei tipi da versioni di Go molto vecchie.
Questa libreria attualmente gestisce i layout del pclntab precedenti alla 1.2, 1.2, 1.16, 1.18 e 1.20. Si noti che la versione del pclntab è sempre <= alla versione del runtime Go (es: il runtime Go 1.19 utilizza il layout del pclntab 1.18); il nostro obiettivo è supportare sempre le ultime versioni del runtime.
Gran parte del codice sorgente di GoReSym è copiato dalla directory sorgente del compilatore Go upstream /internal. Per far funzionare il tutto, abbiamo dovuto adattare un po' il sorgente. Se vuoi contribuire a GoReSym, continua a leggere così possiamo spiegarti questo processo di importazione.
A causa del modo in cui funzionano i pacchetti Go, abbiamo dovuto rimuovere il percorso /internal dall'albero dei file sorgente. Questo ha comportato molta copia di file interni di Go, in cui l'albero delle directory è per lo più intatto ma con piccole modifiche agli import di molti file: i riferimenti ai percorsi /internal sono stati sostituiti con github.com/mandiant/GoReSym/.
Abbiamo inoltre modificato molte strutture interne per esportare campi e metodi. Questi non sono esportati da Go upstream perché gli utenti non dovrebbero fare affidamento su di essi. Tuttavia, lo scopo di questo strumento è estrarre informazioni interne, quindi ci assumiamo il compito di mantenere queste strutture. Non è una situazione ideale, ma non è facilmente evitabile. Se aggiorni questo repository, devi fare attenzione a mantenere intatte queste modifiche. Probabilmente è meglio unire manualmente i commit da upstream piuttosto che copiare in blocco i file upstream.
Sono aperto a suggerimenti su come strutturare meglio questo progetto per evitare questi problemi pur continuando a compilare con il tipico go build. C'è una precedente discussione che coinvolge i maintainer di Go qui.
Ignorando alcune modifiche banali, la maggior parte della nuova logica risiede in /objfile. Ad esempio, il file objfile/internals definisce le strutture interne invertite di Go che GoReSym analizza.
pclntab: golang.org/s/go12symtabpclntab: pclntab.go#L169objfile:
buildID: golang/go#50809