
Analiza binarios de Go para recuperar símbolos, metadatos de funciones, tipos, rutas de archivos y cadenas incrustadas, incluidos muestras eliminadas o empaquetadas con UPX, con soporte de importación en IDA Pro.

GoReSym es un analizador de símbolos de Go que extrae metadatos del programa (como la arquitectura de CPU, el SO, el endianness, la versión del compilador, etc.), metadatos de funciones (direcciones de inicio y fin, nombres, fuentes), metadatos de nombres de archivo y números de línea, y estructuras y tipos embebidos. Este programa multiplataforma está basado directamente en el compilador de Go de código abierto y en el código del runtime.
El código del runtime de Go upstream se amplía para manejar:
moduledataConsulte https://www.mandiant.com/resources/blog/golang-internals-symbol-recovery para obtener detalles de ingeniería inversa y ejemplos de uso.
Puede descargar binarios de GoReSym precompilados para linux, macos y windows desde la pestaña Releases.
Para compilar desde el código fuente con un compilador de Go reciente, invoque el compilador de Go:
go build
Una vez compilado, invoque GoReSym así:
GoReSym.exe -t -d -p /path/to/input.exe
En este ejemplo, solicitamos a GoReSym que recupere los nombres de tipos (-t), los nombres de paquetes de usuario, los nombres de paquetes estándar de Go (-d) y las rutas de archivos de entrada (-p) incrustados dentro del archivo /path/to/input.exe. La salida tiene este aspecto:
{
"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": [ ... ]
}
Estas son todas las flags disponibles:
-d ("default", opcional) imprimirá los paquetes estándar de Go además de los paquetes de usuario.-p ("paths", opcional) imprimirá cualquier ruta de archivo incrustada en el pclntab.-t ("types", opcional) imprimirá los nombres de los tipos de Go.-strings (opcional) extraerá las cadenas de Go incrustadas en el binario analizando la tabla de internamiento de cadenas.-m <virtual address> ("manual", opcional) volcará la estructura RTYPE de forma recursiva en la dirección virtual indicada-v <version string> ("version", opcional) anulará la detección automática de versión y usará la versión proporcionada. Esto es necesario para algunos binarios con símbolos eliminados. El análisis de tipos fallará si la versión no es precisa.-human (opcional) imprimirá un listado en texto plano en lugar de JSON. Especialmente útil al imprimir tipos de estructura e interfaz.-about (opcional) imprimirá la información de la licenciaPara importar esta información a IDA Pro puede ejecutar el script que se encuentra en https://github.com/mandiant/GoReSym/blob/master/IDAPython/goresym_rename.py. Leerá un archivo json producido por GoReSym y establecerá símbolos/etiquetas en IDA.
A medida que el compilador y el runtime de Go han cambiado, también lo han hecho las estructuras de metadatos incrustadas. GoReSym admite las siguientes combinaciones de versiones de Go y metadatos:
pclntab: >= Go 1.2moduledata: >= Go 1.2moduledata: >= Go 1.5La tabla moduledata utilizada para extraer tipos no existe antes de Go 1.5, por lo que esta biblioteca nunca admitirá la extracción de tipos de versiones muy antiguas de Go.
Esta biblioteca maneja actualmente los diseños de pclntab anteriores a 1.2, 1.2, 1.16, 1.18 y 1.20. Tenga en cuenta que la versión de pclntab siempre es <= la versión del runtime de Go (ej.: el runtime de Go 1.19 usa el diseño de pclntab de 1.18); nuestro objetivo es admitir siempre las últimas versiones del runtime.
Gran parte del código fuente de GoReSym está copiado del directorio de código fuente del compilador de Go upstream /internal. Para que esto funcione, hemos tenido que adaptar un poco el código fuente. Si desea contribuir a GoReSym, siga leyendo para que podamos explicar este proceso de importación.
Debido a la forma en que funcionan los paquetes de Go, necesitábamos eliminar la ruta /internal del árbol de archivos fuente. Esto dio como resultado una gran cantidad de copias de archivos internos de Go, donde el árbol de directorios está en su mayor parte intacto pero con pequeños cambios en las importaciones de muchos archivos: las referencias a rutas /internal se reemplazaron con github.com/mandiant/GoReSym/.
También modificamos muchas estructuras internas para exportar campos y métodos. Estos no son exportados por Go upstream porque los usuarios no deberían depender de ellos. Sin embargo, el propósito de esta herramienta es extraer información interna, por lo que asumimos la tarea de mantener estas estructuras. No es una gran situación, pero no es fácilmente evitable. Si actualiza este repositorio, debe tener cuidado de mantener estas modificaciones intactas. Probablemente sea mejor fusionar manualmente los commits de upstream en lugar de copiar los archivos de upstream en su totalidad.
Estoy abierto a sugerencias sobre cómo estructurar mejor este proyecto para evitar estos problemas mientras siga compilando con el típico go build. Hay una discusión previa con los mantenedores de Go aquí.
Ignorando algunos cambios triviales, la mayor parte de la nueva lógica existe en /objfile. Por ejemplo, el archivo objfile/internals define las estructuras internas invertidas de Go que GoReSym analiza.
pclntab: golang.org/s/go12symtabpclntab: pclntab.go#L169objfile:
buildID: golang/go#50809