
Analyse les binaires Go pour récupérer les symboles, les métadonnées de fonctions, les types, les chemins de fichiers et les chaînes intégrées, y compris pour les échantillons strippés ou packés avec UPX, avec prise en charge de l'import dans IDA Pro.

GoReSym est un analyseur de symboles Go qui extrait les métadonnées du programme (telles que l'architecture du processeur, le système d'exploitation, l'endianness, la version du compilateur, etc.), les métadonnées des fonctions (adresses de début et de fin, noms, sources), les métadonnées des noms de fichiers et des numéros de ligne, ainsi que les structures et types intégrés. Ce programme multiplateforme est directement basé sur le compilateur Go open source et le code du runtime.
Le code du runtime Go en amont est étendu pour gérer :
moduledataReportez-vous à https://www.mandiant.com/resources/blog/golang-internals-symbol-recovery pour les détails de rétro-ingénierie et des exemples d'utilisation.
Vous pouvez télécharger des binaires GoReSym précompilés pour linux, macos et windows depuis l'onglet Releases.
Pour compiler depuis les sources avec un compilateur Go récent, invoquez le compilateur Go :
go build
Une fois compilé, invoquez GoReSym comme ceci :
GoReSym.exe -t -d -p /path/to/input.exe
Dans cet exemple, nous demandons à GoReSym de récupérer les noms de types (-t), les noms de paquets utilisateur, les noms de paquets Go standard (-d) et les chemins de fichiers d'entrée (-p) intégrés dans le fichier /path/to/input.exe. La sortie ressemble à ceci :
{
"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": [ ... ]
}
Voici tous les indicateurs disponibles :
-d ("default", facultatif) affichera les paquets Go standard en plus des paquets utilisateur.-p ("paths", facultatif) affichera tous les chemins de fichiers intégrés dans le pclntab.-t ("types", facultatif) affichera les noms de types Go.-strings (facultatif) extraira les chaînes Go intégrées dans le binaire en analysant la table d'internement des chaînes.-m <virtual address> ("manual", facultatif) videra la structure RTYPE de manière récursive à l'adresse virtuelle donnée-v <version string> ("version", facultatif) remplacera la détection automatique de version et utilisera la version fournie. Cela est nécessaire pour certains binaires dépouillés. L'analyse des types échouera si la version n'est pas exacte.-human (facultatif) affichera une liste en texte brut au lieu de JSON. Particulièrement utile lors de l'affichage des types de structure et d'interface.-about (facultatif) affichera les informations de licencePour importer ces informations dans IDA Pro, vous pouvez exécuter le script disponible dans https://github.com/mandiant/GoReSym/blob/master/IDAPython/goresym_rename.py. Il lira un fichier json produit par GoReSym et définira les symboles/étiquettes dans IDA.
Comme le compilateur et le runtime Go ont changé, les structures de métadonnées intégrées ont également changé. GoReSym prend en charge les combinaisons suivantes de versions Go et de métadonnées :
pclntab : >= Go 1.2moduledata : >= Go 1.2moduledata : >= Go 1.5La table moduledata utilisée pour extraire les types n'existe pas avant Go 1.5, cette bibliothèque ne prendra donc jamais en charge l'extraction des types depuis des versions très anciennes de Go.
Cette bibliothèque gère actuellement les dispositions du pclntab antérieures à 1.2, 1.2, 1.16, 1.18 et 1.20. Notez que la version du pclntab est toujours <= à la version du runtime Go (ex : le runtime Go 1.19 utilise la disposition pclntab 1.18), nous visons à toujours prendre en charge les dernières versions du runtime.
Une grande partie du code source de GoReSym est copiée du répertoire source du compilateur Go upstream /internal. Pour que cela fonctionne, nous avons dû retravailler un peu le code source. Si vous souhaitez contribuer à GoReSym, lisez la suite pour que nous puissions expliquer ce processus d'importation.
En raison du fonctionnement des paquets Go, nous avons dû supprimer le chemin /internal de l'arborescence des fichiers source. Cela a entraîné de nombreuses copies de fichiers internes Go, où l'arborescence des répertoires est en grande partie intacte mais avec de petites modifications dans les imports de nombreux fichiers : les références aux chemins /internal ont été remplacées par github.com/mandiant/GoReSym/.
Nous avons également modifié de nombreuses structures internes pour exporter des champs et des méthodes. Ceux-ci ne sont pas exportés par Go upstream car les utilisateurs ne devraient pas s'y fier. Cependant, le but de cet outil est d'extraire des informations internes, nous prenons donc en charge la maintenance de ces structures. Ce n'est pas une situation idéale, mais elle n'est pas facilement évitable. Si vous mettez à jour ce dépôt, vous devez veiller à conserver ces modifications intactes. Il est probablement préférable de fusionner manuellement les commits depuis upstream plutôt que de copier les fichiers upstream en bloc.
Je suis ouvert aux suggestions sur la façon de mieux structurer ce projet pour éviter ces problèmes tout en continuant à compiler avec le go build classique. Il y a une discussion précédente impliquant les mainteneurs de Go ici.
En ignorant quelques modifications triviales, la majeure partie de la nouvelle logique se trouve dans /objfile. Par exemple, le fichier objfile/internals définit les structures internes Go inversées que GoReSym analyse.
pclntab : golang.org/s/go12symtabpclntab : pclntab.go#L169objfile :
buildID : golang/go#50809