#python #c #reverse-engineering
#python #c #обратный инжиниринг
Вопрос:
Я стал больше интересоваться обращением двоичных файлов с тех пор, как АНБ выпустило Ghidra, в котором есть встроенная функция, которая создает псевдокод C из дизассемблирования двоичного файла.
У меня была идея создать базу данных с кодом операции с соответствующей сборкой и кодом C. Я хочу написать инструмент, который может выводить двоичный файл, такой как readelf и objdump, извлекать символы и функции из исходного файла C и объединять все это
Итак, чтобы сделать это более понятным, давайте рассмотрим один пример.
Мы загружаем vim-исходный код в систему Ubuntu. Мы компилируем ее с помощью ./configure и ./make. Когда двоичный файл готов, мы запускаем наш инструмент, извлекаем коды операций символов, создаем из кода ассемблерный код, извлекаем функцию и тело функции из .c-файла, объединяем все это и записываем в базу данных.
Итак, база данных должна содержать следующий материал:
исходный код c-функции, подобный
int main()
{
return 0;
}
Ассемблер может выглядеть как:
push rbp
mov rbp, rsp
...
ret
и раздел с кодом операции, подобный:
55 48 89 e5 89 7d ec 89 75 ...
Итак, мой вопрос… Имеет ли смысл каталогизировать эти данные, чтобы использовать это, возможно, в качестве плагина в дизассемблере? Идея заключалась в том, что плагин может отправлять коды операций в веб-сервис и получать возможные исходные коды c обратно. Таким образом, декомпилятор может использовать это, чтобы удалить псевдокод и заменить его примерами реального кода.
Я знаю, что это не так просто, потому что у нас разные компиляторы, архитектуры, версии, порядковые номера и так далее. Но в целом, с большой базой данных, содержащей коды операций для каждой архитектуры / версии / компилятора, должно быть возможно упростить обратное проектирование неизвестных двоичных файлов.
Я собрал код для этого вчера, но я не уверен, будет ли это полезно для расширения дизассемблеров.
Чтобы получить представление об этом, вот пример небольшого calc-инструмента, который я написал на c, и выходные данные моего инструмента еще:
|==================================================================|
| Adress | Function | Size |
|====================|================================|============|
| 0x0000000000000679 | add | 33 |
|==================================================================|
| OPCode |
|==================================================================|
| 55 48 89 e5 89 7d ec 89 75 e8 c7 45 fc 00 00 00 00 8b 55 ec 8b |
| 45 e8 01 d0 89 45 fc 8b 45 fc 5d c3 |
|==================================================================|
| Assembler |
|==================================================================|
| 0x1000 : push rbp |
| 0x1001 : mov rbp, rsp |
| 0x1004 : mov dword ptr [rbp - 0x14], edi |
| 0x1007 : mov dword ptr [rbp - 0x18], esi |
| 0x100a : mov dword ptr [rbp - 4], 0 |
| 0x1011 : mov edx, dword ptr [rbp - 0x14] |
| 0x1014 : mov eax, dword ptr [rbp - 0x18] |
| 0x1017 : add eax, edx |
| 0x1019 : mov dword ptr [rbp - 4], eax |
| 0x101c : mov eax, dword ptr [rbp - 4] |
| 0x101f : pop rbp |
| 0x1020 : ret |
|==================================================================|
| Source |
|==================================================================|
| int add(int a, int b) |
| { |
| int c = 0; |
| c = a b; |
| return c; |
| } |
| |
|==================================================================|
Комментарии:
1. Не уверен, в чем здесь вопрос. Несколько человек / компаний выпустили дизассемблеры с разной степенью успеха. Если вы хотите быть следующим, кто попробует это, дерзайте.
2. Отличная проблема.Но: сложно. Пожалуйста, продолжайте. (вы уже исследовали самоизменяющийся код?)
3. Нет, я этого еще не делал. Есть ли у вас какие-либо примеры кода для этого, чтобы я мог с этим работать?
Ответ №1:
Такие базы данных с кодом операции уже реализованы в различных компиляторах, которые компилируются в машинный код.
Например, LLVM имеет такие базы данных в виде файлов языка TableGen. Внутренние дизассемблеры в основном автоматически генерируются на основе этих описаний. Взгляните, например, на серверную часть Sparc.
Такие проекты, как Capstone Disassembler, используют LLVM для дизассемблирования кода для различных процессоров.