Детерминированный конвейер извлечения, триажа и локальной LLM-компиляции на основе PyGhidra для реимплементации на C.
Спасибо за скачивание моего конвейера Ghidra + LLM.
Это мой первый README. ASL (американский жестовый язык) — мой первый язык, поэтому мой английский не идеален. Я старался как мог.
Я люблю старую PC-симуляцию, в которую играю с детства, и хочу улучшить её под капотом.
Глядя на open-source игры вроде OpenRA и OpenTTD, я понял вот что: любительская реимплементация — это не про получение оригинального исходного кода. Это про создание новой open-source версии игры, которая может загружать ассеты оригинала. Тогда любой сможет её расширять или вносить вклад.
Для работы я использую два вида ИИ вместе:
Каждая функция получает одну метку. Это экономит много времени, потому что я не трачу усилия на большую массу мусора из ОС и рантайма.
|-----------|------------------------------------------------------------------------------------------------------------------
| Метка | Значение |
|---|---|
| KEEP | Собственная логика игры (например, модель полёта, модель повреждений, TrackIR) |
| WRAP | Связующий код для Java, вызывающий API ОС или ввода: сохранить сигнатуру, написать новое тело. |
| (IL-2 1946 — интересный движок: C++ и Java вместе.) | |
| REPLACE | Старый C-рантайм, аллокатор, thunks: их предоставляет компилятор или ОС, поэтому новой 64-битной версии они не нужны |
| UNKNOWN | Неясно: посмотреть вручную |
| ----------- | ------------------------------------------------------------------------------------------------------------------ |
В моей тестовой программе около 44% функций были REPLACE, так что их вообще не нужно было конвертировать.
Вначале я доверял C-псевдокоду как содержащему все ответы. Это было наивно. Это интерпретация ассемблера от Ghidra, и она догадывается (типы переменных, потерянные аргументы).
Ассемблер — это сырая правда. В нём нет типов переменных, но он содержит точное поведение каждой функции. Поэтому скрипты читают ассемблер и превращают его в чертёж в C-подобной форме. C от Ghidra сохраняется только как подсказка.
Мои ранние тесты использовали локальные LLM (Qwen 2.5 Coder, DeepSeek Coder V2 Lite, Mellum 2) для чтения ассемблера напрямую. Это никогда не работало надёжно. Они галлюцинировали, потому что созданы писать код, а не читать сырой машинный код.
После многих неудачных экспериментов я разделил работу:
ПРИМЕЧАНИЕ: Как Python проверяет ответ
Текстовые проверки: имя функции, каждый вызов, глобальная переменная и строка из чертежа, циклы, размеры шагов, сравниваемые константы, возвращаемое значение, а также отсутствие оставшихся имён регистров или выдуманных имён.
проверка компиляции gcc: код компилируется с помощью gcc (только синтаксис, ничего не запускается). Это очень помогло. В одном из ранних прогонов текстовые проверки пропустили ответы Mellum 2, но ни один из них не скомпилировался из-за заголовочного комментария, написанного вне комментария. gcc ловит то, чего не видят текстовые проверки: необъявленные или повторно объявленные переменные, неверные типы, а также сломанные скобки или точки с запятой. Функция считается PASS только тогда, когда и текстовые проверки, и компиляция прошли успешно. gcc не доказывает правильность логики, поэтому я по-прежнему сверяю код с чертежом.
Если проверка не проходит, LLM получает список того, что не удалось, и пробует ещё раз.
Python сам исправляет мелкие огрехи, без участия LLM: объявляет каждую переменную один раз, оборачивает свободные строки заголовка в комментарий, заставляет последний return возвращать правильный результат, а также добавляет include и объявления.
Чек-лист появился после того, как я увидел, что LLM спотыкаются на очень длинных функциях. Он работает как чек-лист, которым пользуется пилот перед взлётом и посадкой. Python составляет его по функции и сверяет с ним ответ. В моих тестах длинные функции начали проходить, а прогоны стали быстрее.
|-------------------|---------------------------------------|---------------------------------------------
| Папка | Что она делает | Читать |
|---|---|---|
ghidra_pipeline | Дамп, группировка, триаж, роли | ghidra_pipeline/INSTRUCTION.txt |
llm_pipeline | Чертежи и запуск LLM (v3) | llm_pipeline/INSTRUCTION_BLUEPRINT_LLM.txt |
| ------------------- | --------------------------------------- | --------------------------------------------- |
Начните с ghidra_pipeline, затем переходите к llm_pipeline, когда будете готовы использовать свои локальные LLM.
Сначала проанализируйте свою программу в PyGhidra и запустите PyGhidra Scripts/decompile_full_dump.py.
Два файла INSTRUCTION объясняют настройку папок. Затем:
Сначала проанализируйте свою программу в PyGhidra и запустите PyGhidra Scripts/decompile_full_dump.py.
Два файла INSTRUCTION объясняют настройку папок. Затем:
python .\make_full_lite_v2.py --in . --out .\OUT
python .\triage_evidence_v2.py --lite .\OUT\LITE_AC
python .\build_roles_v2.py --triage .\OUT\TRIAGE
python .\blueprint_v3.py --group ".\SOURCE\LITE_AC\<GroupName>" --out ".\G_<GroupName>\BLUEPRINT_v3"
python .\run_blueprint_llm_v3.py --bp ".\G_<GroupName>\BLUEPRINT_v3" --out ".\G_<GroupName>\RUN1_v3_<model>" --model <model name>
Для работы нужны Ghidra с PyGhidra, Python 3, LM Studio (с загруженной моделью) и gcc (рекомендуется, используется для проверки компиляции).