
Разбирает бинарные файлы Go для восстановления символов, метаданных функций, типов, путей к файлам и встроенных строк, включая stripped- и UPX-упакованные образцы, с поддержкой импорта в IDA Pro.

GoReSym — это парсер символов Go, который извлекает метаданные программы (такие как архитектура CPU, ОС, порядок байтов, версия компилятора и т. д.), метаданные функций (начальный и конечный адреса, имена, исходные файлы), метаданные имён файлов и номеров строк, а также встроенные структуры и типы. Эта кроссплатформенная программа основана непосредственно на открытом исходном коде компилятора Go и коде среды выполнения.
Код среды выполнения Go из upstream расширен для обработки:
moduledataПодробности обратного проектирования и примеры использования см. на https://www.mandiant.com/resources/blog/golang-internals-symbol-recovery.
Вы можете скачать готовые бинарные файлы GoReSym для linux, macos и windows на вкладке Releases.
Чтобы собрать из исходного кода с помощью свежего компилятора Go, вызовите компилятор Go:
go build
После сборки вызывайте GoReSym следующим образом:
GoReSym.exe -t -d -p /path/to/input.exe
В этом примере мы просим GoReSym восстановить имена типов (-t), имена пользовательских пакетов, имена стандартных пакетов Go (-d) и пути входных файлов (-p), встроенные в файл /path/to/input.exe. Вывод выглядит так:
{
"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": [ ... ]
}
Вот все доступные флаги:
-d ("default", необязательный) — выводит стандартные пакеты Go в дополнение к пользовательским пакетам.-p ("paths", необязательный) — выводит любые пути к файлам, встроенные в pclntab.-t ("types", необязательный) — выводит имена типов Go.-strings (необязательный) — извлекает встроенные строки Go из бинарного файла путём анализа таблицы интернирования строк.-m <virtual address> ("manual", необязательный) — выводит структуру RTYPE рекурсивно по указанному виртуальному адресу-v <version string> ("version", необязательный) — переопределяет автоматическое определение версии и использует указанную версию. Это необходимо для некоторых stripped-бинарников. Разбор типов завершится ошибкой, если версия указана неточно.-human (необязательный) — выводит плоский текстовый список вместо JSON. Особенно полезно при выводе структурных и интерфейсных типов.-about (необязательный) — выводит информацию о лицензииЧтобы импортировать эту информацию в IDA Pro, можно запустить скрипт, найденный в https://github.com/mandiant/GoReSym/blob/master/IDAPython/goresym_rename.py. Он прочитает json-файл, созданный GoReSym, и установит символы/метки в IDA.
Поскольку компилятор и среда выполнения Go менялись, менялись и встроенные структуры метаданных. GoReSym поддерживает следующие комбинации версий Go и метаданных:
pclntab: >= Go 1.2moduledata: >= Go 1.2moduledata: >= Go 1.5Таблица moduledata, используемая для извлечения типов, не существует до Go 1.5, поэтому эта библиотека никогда не будет поддерживать извлечение типов из очень старых версий Go.
В настоящее время эта библиотека обрабатывает раскладки pclntab до 1.2, 1.2, 1.16, 1.18 и 1.20. Обратите внимание, что версия pclntab всегда <= версии среды выполнения Go (например, среда выполнения Go 1.19 использует раскладку pclntab 1.18); мы стремимся всегда поддерживать последние версии среды выполнения.
Большая часть исходного кода GoReSym скопирована из каталога исходного кода вышестоящего компилятора Go /internal. Чтобы это работало, нам пришлось немного видоизменить исходный код. Если вы хотите внести вклад в GoReSym, читайте дальше, и мы объясним этот процесс импорта.
Из-за того, как работают пакеты Go, нам пришлось удалить путь /internal из дерева исходных файлов. Это привело к масштабному копированию внутренних файлов Go, где дерево каталогов в основном сохранено, но с небольшими изменениями импортов во многих файлах: ссылки на пути /internal были заменены на github.com/mandiant/GoReSym/.
Мы также изменили многие внутренние структуры, чтобы экспортировать поля и методы. Они не экспортируются в вышестоящем Go, поскольку пользователи не должны на них полагаться. Однако цель этого инструмента — извлекать внутреннюю информацию, поэтому мы берём на себя задачу поддержки этих структур. Ситуация не идеальна, но её нелегко избежать. Если вы обновляете этот репозиторий, вы должны позаботиться о сохранении этих модификаций. Вероятно, лучше вручную вливать коммиты из вышестоящего репозитория, чем целиком копировать вышестоящие файлы.
Я открыт для предложений о том, как лучше структурировать этот проект, чтобы избежать этих проблем и при этом собираться с помощью обычного go build. Ранее было обсуждение с мейнтейнерами Go здесь.
Если не считать некоторых тривиальных изменений, большая часть новой логики находится в /objfile. Например, файл objfile/internals определяет реверсированные внутренние структуры Go, которые разбирает GoReSym.
pclntab: golang.org/s/go12symtabpclntab: pclntab.go#L169objfile:
buildID: golang/go#50809