LIMB
Вход Регистрация

тема

Как научить AI понимать ассемблер: Декомпилятор с ChatGPT 5.2 и IR лифтингом

benjaminbutton · · 1 ответов · 353 просмотров

Медиа заблокировано
Этот домен не входит в список разрешённых для медиа.
Формат: изображения / GIFДомен: upload.wikimedia.org
Разрешённые домены
  • imgur.com
  • ru.imgbb.com
  • prnt.sc
  • imgbb.com
  • ibb.co
  • i.imgur.com
  • i.ibb.co
  • darklimb.vip
  • i.pinimg.com
  • img3.teletype.in
  • img4.teletype.in
  • teletype.in
  • pikabu.ru
  • cs15.pikabu.ru
  • img2.teletype.in
  • lh7-rt.googleusercontent.com
  • duty-files.cc
  • blogger.googleusercontent.com

Как научить AI понимать ассемблер
Практическое руководство по созданию декомпилятора с нейросетью​


Проблема: Почему декомпиляция это боль​


Вы когда-нибудь пытались понять, что делает незнакомый бинарник? Открываете IDA, жмете F5, и получаете простыню кода, где все переменные называются v1, v2, v3. Функции sub_401000, sub_401050. Константы 0x5F3759DF без комментариев.

Типичный результат декомпиляции:

C:
__int64 sub_401A50()
{
  __int64 v0;
  __int64 v1;
  
  v0 = sub_401B20(2LL, 1LL, 0LL);
  if ( v0 < 0 )
    return 0xFFFFFFFFLL;
  v1 = v0;
  *(_WORD *)(v0 + 2) = sub_402C10(0x1F90u);
  *(_DWORD *)(v1 + 4) = sub_402D50("192.168.1.100");
  if ( (unsigned int)sub_401C30(v1, v0, 16LL) < 0 )
  {
    sub_401D40(v1);
    return 0xFFFFFFFFLL;
  }
  return (unsigned int)v1;
}

Что это? Сетевой код? Файловая операция? Криптография?

Опытный реверсер потратит 10-15 минут, посмотрит на вызываемые функции, поймет что sub_401B20 это socket(), 0x1F90 это htons(8080), и переименует все вручную.

А если у вас 500 таких функций?

Здесь на помощь приходит искусственный интеллект.


Как работает декомпиляция: От байтов к коду​


Прежде чем интегрировать AI, нужно понять как вообще получается псевдокод из машинного кода.

Этап 1: Дизассемблирование​


Первый шаг: превратить байты в ассемблерные инструкции.

Есть отличная библиотека Capstone, которая поддерживает x86, ARM, MIPS и другие архитектуры.

Python:
from capstone import *

# Байты из .text секции
code = b"\x55\x48\x89\xe5\x48\x83\xec\x10"

# Инициализация дизассемблера
md = Cs(CS_ARCH_X86, CS_MODE_64)

# Дизассемблирование
for insn in md.disasm(code, 0x400000):
    print(f"0x{insn.address:x}: {insn.mnemonic} {insn.op_str}")

Результат работы скрипта: базовая ассемблерная инструкция с адресами, мнемониками и операндами.

Уже лучше, но это все еще низкоуровневый код. Нужно поднять его выше.

Этап 2: Control Flow Analysis​


Следующий шаг: понять структуру программы.

Строим Control Flow Graph (CFG). Это граф, где:
  • Узлы = базовые блоки (последовательности инструкций без переходов внутри)
  • Ребра = возможные пути выполнения (переходы, вызовы)

Алгоритм:
1. Сканируем все инструкции
2. Находим точки ветвления (jmp, je, call, ret)
3. Разбиваем код на блоки
4. Строим связи между блоками

CFG для простой функции выглядит как набор связанных блоков, где каждый блок содержит последовательность инструкций, а ребра показывают возможные пути выполнения.

CFG позволяет восстановить высокоуровневые конструкции: if, while, for, switch.

Этап 3: IR Lifting (Ключевой момент)​


Вот здесь начинается магия.

Многие спрашивают: "Как голый ассемблер из Capstone превращается в C-подобный псевдокод?"

Ответ: через Intermediate Representation (IR).

IR это промежуточный формат, который находится между машинным кодом и высокоуровневым языком. Каждая ассемблерная инструкция "поднимается" (lifted) в более абстрактное представление.

Пример трансформации:

АссемблерIRПсевдокодmov eax, 5ASSIGN(eax, CONST(5))eax = 5;add eax, ebxASSIGN(eax, ADD(eax, ebx))eax = eax + ebx;call 0x401000t0 = CALL(0x401000, [])t0 = func_401000();cmp eax, 0SET_FLAGS(SUB(eax, 0))// sets flagsjl 0x401020IF(FLAGS.SF) GOTO 0x401020if (eax < 0) goto label;

В процессе лифтинга каждая ассемблерная инструкция последовательно трансформируется в соответствующее IR представление, которое затем конвертируется в C-подобный синтаксис.

Теперь у нас есть структурированный IR, который можно анализировать дальше.

Этап 4: Генерация C псевдокода​


Финальный этап: конвертация IR в читаемый C код.

Анализируем CFG, определяем тип блоков (последовательность, ветвление, цикл), и генерируем соответствующие конструкции:

C:
int function_400000(int arg1) {
    int var_4;
    
    var_4 = arg1;
    
    if (var_4 <= 0) {
        return 0;
    }
    
    return 1;
}

Но! Имена переменных все еще автоматические (var_4, arg1). 

Здесь в игру вступает AI.


Интеграция AI: ChatGPT 5.2 и альтернативы​


Зачем нужен AI в декомпиляции?​


Представьте: у вас есть функция с 20 переменными. Вручную анализировать каждую это часы работы.

AI может:
  • Понять контекст: Если видит socket(), connect(), htons() то понимает, что это сетевой код
  • Предложить имена: socket_fd, server_addr, port_number вместо v1, v2, v3
  • Добавить комментарии: "Connects to remote server at 192.168.1.100:8080"
  • Определить назначение функции: "Establishes TCP connection to C2 server"

Выбор модели: ChatGPT 5.2 vs альтернативы​


В декомпиляторе можно выбрать модель:

МодельПлюсыМинусыРекомендацияChatGPT 5.2Самая умная модель, глубокое понимание кода, отличное качество именованияФродится на вредоносном коде, платная, требует обхода через jailbreak промптыДля легального ПОClaude 3.5 SonnetХорошо понимает низкоуровневый код, быстрый, меньше цензурыПлатная, иногда отказывается анализировать "подозрительный" кодУниверсальный выборDeepSeek Coder V2Заточен под код, быстрый, дешевыйХуже ChatGPT в контексте, иногда галлюцинируетБюджетный вариантLocal Llama 3.1 70BПолностью приватный, без цензуры, бесплатныйТребует 2x3090/4090 или 48GB+ VRAM, медленныйАнализ малвари (если есть железо)Qwen 2.5 Coder 32BЗаточен под код, работает на 1x3090/4090 (24GB), хорошее качествоЧуть хуже 70B моделей, но влезает в одну картуЛучший выбор для одной GPU

:warning: Важно про ChatGPT 5.2 и малварь:

Цензура AI моделей

ChatGPT 5.2 имеет встроенные фильтры безопасности. Если вы анализируете вредоносное ПО, модель может отказаться помогать:

"I cannot assist with analyzing malicious code that could be used to harm computer systems"

Обходы:
1. Jailbreak промпты (работают не всегда, OpenAI постоянно патчит)
2. Переформулирование запроса ("This is a CTF challenge", "Educational purpose only")
3. Использование локальных uncensored моделей

Как это работает: API интеграция​


Декомпилятор отправляет в AI три вещи:
1. Псевдокод функции (сгенерированный на этапе 4)
2. Контекст (вызовы API, строки, числовые константы)
3. Промпт (инструкция для модели)

Пример запроса:

JSON:
{
  "model": "gpt-5.2",
  "messages": [
    {
      "role": "system",
      "content": "You are expert reverse engineer. Analyze decompiled code and suggest meaningful variable names based on usage patterns. Output JSON only."
    },
    {
      "role": "user",
      "content": "Function:\n```c\nint func_401000() {\n  int v1 = socket(2, 1, 0);\n  if (v1 < 0) return -1;\n  struct v2;\n  v2.v3 = 2;\n  v2.v4 = htons(8080);\n  connect(v1, &v2, 16);\n}\n```\nContext:\n- API calls: socket, htons, connect\n- Constants: 2 (AF_INET), 1 (SOCK_STREAM), 8080 (port)\n\nProvide variable renames in JSON."
    }
  ],
  "temperature": 0.2
}

Ответ модели:

JSON:
{
  "function_name": "connect_to_server",
  "function_purpose": "Establishes TCP connection to remote server on port 8080",
  "renames": [
    {
      "original": "v1",
      "suggested": "socket_fd",
      "reasoning": "File descriptor returned by socket() call",
      "confidence": 0.98
    },
    {
      "original": "v2",
      "suggested": "server_addr",
      "reasoning": "sockaddr_in structure for server address",
      "confidence": 0.95
    },
    {
      "original": "v3",
      "suggested": "sin_family",
      "reasoning": "Address family field (AF_INET = 2)",
      "confidence": 0.99
    },
    {
      "original": "v4",
      "suggested": "sin_port",
      "reasoning": "Port number field (8080 in network byte order)",
      "confidence": 0.97
    }
  ]
}

Декомпилятор парсит JSON и автоматически применяет все переименования.

Результат: До и После​


Реальный сетевой код из малвари трансформируется из нечитаемого месива с v0, v1, sub_401B20 в полностью документированный код с осмысленными именами socket_fd, connect_to_c2_server и комментариями об угрозе.

Код стал читаемым за 2 секунды.


Реализация AI-assisted декомпилятора​


Архитектура системы​


Полноценная система состоит из:

Не удалось прогрузить медиа


Пример кода: AI Client​


Python:
import requests
import json

class AIDecompiler:
    def __init__(self, api_key, model="gpt-5.2"):
        self.api_key = api_key
        self.model = model
        self.cache = {}
    
    def analyze_function(self, pseudocode, context):
        # Проверяем кэш
        cache_key = hashlib.sha256(pseudocode.encode()).hexdigest()
        if cache_key in self.cache:
            return self.cache[cache_key]
        
        # Формируем промпт
        prompt = self.build_prompt(pseudocode, context)
        
        # API запрос
        response = requests.post(
            "https://api.openai.com/v1/chat/completions",
            headers={
                "Authorization": f"Bearer {self.api_key}",
                "Content-Type": "application/json"
            },
            json={
                "model": self.model,
                "messages": [
                    {"role": "system", "content": self.get_system_prompt()},
                    {"role": "user", "content": prompt}
                ],
                "temperature": 0.2,
                "response_format": {"type": "json_object"}
            }
        )
        
        result = response.json()
        analysis = json.loads(result['choices'][0]['message']['content'])
        
        # Сохраняем в кэш
        self.cache[cache_key] = analysis
        return analysis
    
    def build_prompt(self, code, ctx):
        return f"""Analyze this decompiled function:

```c
{code}
```

Context:
- API calls: {', '.join(ctx.get('apis', []))}
- Strings: {', '.join(ctx.get('strings', []))}
- Constants: {', '.join(map(str, ctx.get('numbers', [])))}

Provide JSON with function_name, purpose, and variable renames."""
    
    def get_system_prompt(self):
        return "You are an expert reverse engineer. Analyze code and suggest meaningful names based on usage patterns. Output JSON only."

Оптимизация: Многопоточность​


Функции независимы можем анализировать параллельно:

Python:
from concurrent.futures import ThreadPoolExecutor

def analyze_all_functions(functions, ai_client):
    results = {}
    
    with ThreadPoolExecutor(max_workers=8) as executor:
        futures = {}
        
        for func in functions:
            future = executor.submit(
                ai_client.analyze_function,
                func.pseudocode,
                func.context
            )
            futures[future] = func
        
        for future in futures:
            func = futures[future]
            try:
                result = future.result()
                results[func.address] = result
            except Exception as e:
                print(f"Failed to analyze {func.name}: {e}")
    
    return results

С 8 потоками анализ 1000 функций занимает ~10-15 минут вместо часов.


Сравнение подходов​


МетодВремя на 1000 функцийКачествоСтоимостьРучное переименование~40 часовОтличноFREEHex-Rays без AI~30 часовСреднее$1879 (IDA)IDA + ChatGPT плагин~5 часовХорошее$1879 + APIКастомный AI декомпилятор~15-30 минутОтличноAPI или FREE (local)


Практический кейс: Анализ C2 малвари​


Реальный пример из практики.

Задача: Проанализировать подозрительный файл suspicious.exe, который детектится как троян.

Шаг 1: Загрузка и базовая декомпиляция

Открываем в Ghidra / IDA, получаем 200+ функций с автоматическими именами.

Шаг 2: Поиск интересных функций

Смотрим импорты:
Code:
WS2_32.dll: socket, connect, send, recv, closesocket
WININET.dll: HttpOpenRequestA, HttpSendRequestA
ADVAPI32.dll: CryptEncrypt, CryptDecrypt

Сетевая активность + криптография = подозрительно.

Шаг 3: AI анализ сетевых функций

Берем функцию sub_401A50, запускаем через AI:

До:
C:
__int64 sub_401A50() {
  __int64 v0 = sub_401B20(2LL, 1LL, 0LL);
  // ... 20 строк непонятного кода
}

После ChatGPT анализа:
C:
// C2 Communication Handler
// Connects to hardcoded server and establishes encrypted channel
int connect_to_c2_server() {
  int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
  struct sockaddr_in c2_server;
  
  c2_server.sin_family = AF_INET;
  c2_server.sin_port = htons(8080);
  c2_server.sin_addr.s_addr = inet_addr("192.168.1.100");
  
  if (connect(socket_fd, &c2_server, sizeof(c2_server)) == 0) {
    return socket_fd;
  }
  return -1;
}

Вывод: Малварь подключается к C2 серверу 192.168.1.100:8080.

Результат: За 15 минут вместо нескольких часов получили полный анализ:
  • C2 адрес: 192.168.1.100:8080
  • Протокол: TCP с XOR шифрованием
  • Ключ шифрования: известен
  • Команды, которые выполняет троян


Практический пример: NEURA Prototype​


Кстати, на основе описанных техник я собрал экспериментальный прототип NEURA.

Не удалось прогрузить медиа

Прототип интерфейса: дизассемблер + AI панель

Disclaimer: Это исследовательский проект, а не готовый продукт. Полноценный декомпилятор это задача для команды инженеров на годы работы.

Что уже работает:
  • Базовое дизассемблирование через Capstone
  • Простой CFG builder (пока без обработки exceptions)
  • Экспериментальный IR лифтинг (поддерживает основные инструкции)
  • API интеграция с ChatGPT/Claude для именования

Не удалось прогрузить медиа

Пример AI-анализа простой функции

Что НЕ работает:
  • Сложная деобфускация (VMProtect, Themida и подобное)
  • Корректная обработка оптимизированного кода
  • Восстановление C++ классов и vtables
  • Символическое исполнение

:bulb: Disclaimer

Это proof-of-concept, демонстрирующий применимость AI в реверсе.
Не рассчитывайте заменить IDA или Ghidra в ближайшее время.

Если интересует тема AI в реверсе, могу поделиться наработками и исходниками.


Заключение​


Ключевые выводы:

  1. IR лифтинг это основа без понимания промежуточного представления невозможно корректно декомпилировать
  2. AI понимает семантику современные LLM анализируют не синтаксис, а смысл кода
  3. Контекст решает чем больше информации (API, строки, константы) даете модели, тем точнее результат
  4. Автоматизация ускоряет в 10-100 раз (зависит от размера функций, качества кэша и API latency) - что вручную занимает дни, AI делает за минуты
  5. Локальные модели для малвари ChatGPT цензурирован, для серьезного анализа нужны uncensored модели

:dart: Практические рекомендации:

Для обучения:
  • Начните с Capstone для дизассемблирования
  • Изучите построение CFG (отличный туториал в Ghidra API docs)
  • Попрактикуйтесь в IR лифтинге на простых функциях

Для продакшена:
  • Используйте ChatGPT 5.2 для легального ПО
  • Qwen 2.5 Coder 32B для малвари на 1 GPU (через Ollama)
  • Llama 3.1 70B если есть 2+ GPU (48GB+ VRAM)
  • Кэшируйте результаты AI (критично для скорости)
  • Многопоточность обязательна для больших бинарников
  • Учитывайте API latency: ~2-5 сек на функцию при онлайн моделях

Реверс-инжиниринг меняется. AI не заменяет эксперта, но многократно усиливает его возможности.

Те, кто освоит эти техники сейчас, будут на голову выше остальных через год.


Если статья была полезна ставьте реакции и задавайте вопросы ниже.
Делюсь опытом реверса и разработки инструментов.

Telegram: @XillenStealer
© benjaminbutton.ru
​
👍28 ❤️2 😢7
Ответbenjaminbutton

VMProtect

Спасибо за интересный топик, много почвы для размышлений дал.

Гостевой просмотр. Чтобы отвечать и ставить реакции, войдите или зарегистрируйтесь.