E
ESCalator
@ptescalator7.2K подп.
2.9Kпросмотров
40.6%от подписчиков
16 марта 2026 г.
📷 ФотоScore: 3.2K
Опять CFG 👋 Частой задачей при извлечении конфигураций ВПО на потоке является получение границ функций и ссылок. Наиболее типичный пример — функции декрипта строк, поскольку там зачастую отличаются только входные аргументы, содержащие зашифрованный буфер. Подобный функционал является базовой частью инструментов для анализа, таких как IDA, Binary Ninja и др., но для наших нужд они избыточны и не всегда удобны для встраивания в проект. 🤔 Далее на ум приходит angr. Попробуем построить CFG с его помощью: io_wrapper = BytesIO(code) proj = angr.Project( io_wrapper, main_opts={ "backend": "blob", "arch": "x86", "base_addr": imagebase, }, auto_load_libs=False, ) cfg = proj.analyses.CFGFast( cross_references=True, normalize=True, ) После нескольких экспериментов становится ясно, что скорость — не его сильная сторона: анализ тестового буфера занимал в среднем 45 секунд. ⏰ В нашем случае скорость важна, поэтому немного погуглив, находим проект SMDA и решаем поэкспериментировать с ним. Для начала инициализируем конфиг, сразу отключив ненужные фичи и задав ограничения по времени анализа и размеру: config = SmdaConfig() config.CALCULATE_HASHING = False config.CALCULATE_SCC = False # having a valid prologue is enough config.CONFIDENCE_THRESHOLD = 0.29 config.MAX_IMAGE_SIZE = 5 * 2 ** 20 # config.TIMEOUT = 60 Запустим анализ и проверим результаты. Библиотека позволяет задавать произвольный базовый адрес, что крайне удобно при работе с образами из дампов: dism = Disassembler(config=config, backend="intel") report = dism.disassembleBuffer(file_content=code, base_addr=imagebase, bitness=32) if report.status == "ok": report.initCodeXrefs() Если анализ прошел успешно, отчет будет содержать информацию по функциям, их базовым блокам, инструкциям в блоке и ссылкам между функциями. Получить все это можно следующим образом: for smda_func in report.getFunctions(): if smda_func.blocks: for block_instructions in smda_func.blocks.values(): for smda_isnn in block_instructions: print(f"{smda_func.offset} | {smda_isnn.detailed}") for smda_out_ref in smda_func.getCodeOutrefs(): print(f"{smda_func.offset} | Out ref {smda_out_ref.to_func}") for smda_in_ref in smda_func.getCodeInrefs(): print(f"{smda_func.offset} | In ref {smda_in_ref.from_func}") 👀 Пример вывода для одной из функций: c749b0 | <CsInsn 0xc749b0 [ff742408]: push dword ptr [esp + 8]> c749b0 | <CsInsn 0xc749b4 [ff742408]: push dword ptr [esp + 8]> c749b0 | <CsInsn 0xc749b8 [e893feffff]: call 0xc74850> c749b0 | <CsInsn 0xc749bd [83c408]: add esp, 8> c749b0 | <CsInsn 0xc749c0 [89c1]: mov ecx, eax> c749b0 | <CsInsn 0xc749c2 [31c0]: xor eax, eax> c749b0 | <CsInsn 0xc749c4 [85c9]: test ecx, ecx> c749b0 | <CsInsn 0xc749c6 [7409]: je 0xc749d1> c749b0 | <CsInsn 0xc749c8 [83790402]: cmp dword ptr [ecx + 4], 2> c749b0 | <CsInsn 0xc749cc [7503]: jne 0xc749d1> c749b0 | <CsInsn 0xc749ce [8b4108]: mov eax, dword ptr [ecx + 8]> c749b0 | <CsInsn 0xc749d1 [c3]: ret > c749b0 | Out ref 0xc749b8 (0xc749b0) -> 0xc74850 (0xc74850) Замерив время анализа, получаем результат около 1 секунды, что является хорошим показателем и подходит для использования на потоке. ✍️ Резюмируя: SMDA — быстрый и удобный инструмент, если задачей является только получение CFG и ссылок. Для других типов черной магии анализа лучше подойдут более тяжеловесные инструменты вроде angr. #tip #reverse #malware @ptescalator (X, Max)
2.9K
просмотров
3536
символов
Да
эмодзи
Да
медиа

Другие посты @ptescalator

Все посты канала →
Опять CFG 👋 Частой задачей при извлечении конфигураций ВПО — @ptescalator | PostSniper