Пожалуйста, не обращайте внимания на качество картинок, сгенерировано фигмой+моими корявыми клешнями немного допилено до приемлемого уровня.
Исходя из правил конкурса, я использовал ИИ в допустимых нормах. Большая часть текста написана лично мной
Я не претендую на звание супер пупер крутого программиста, я всего лишь обычный любитель, которые изо дня в день поглощает, проверяет и тестирует всю информацию что мне попадётся на глаза. Статьи я тоже не особо красиво умею оформлять, поэтому как сделано - так сделано, сильно не гнобите пожалуйста.
Оформление может немного поплыть в силу того, что сижу на стареньком мониторе 1600х900,извините 
В случае, если я выиграю одно из любых мест в конкурсе - все деньги пойдут на благотворительность, ни копейки не будет положено в карман.
В данный момент мы живём в эпоху нейросетей, это ни для кого не секрет. Статья написана исходя из личного опыта, путём проб и ошибок. Наброски были ещё пару месяцев назад, а так как стартовал конкурс, то решил дописать, обновить информацию.
Картинки были созданы с помощью фигмы, где то я сам делал, где-то иишкой красиво подправлял.
Исходя из правил конкурса, я использовал ИИ в допустимых нормах. Большая часть текста написана лично мной
Я не претендую на звание супер пупер крутого программиста, я всего лишь обычный любитель, которые изо дня в день поглощает, проверяет и тестирует всю информацию что мне попадётся на глаза. Статьи я тоже не особо красиво умею оформлять, поэтому как сделано - так сделано, сильно не гнобите пожалуйста.
В случае, если я выиграю одно из любых мест в конкурсе - все деньги пойдут на благотворительность, ни копейки не будет положено в карман.
В данный момент мы живём в эпоху нейросетей, это ни для кого не секрет. Статья написана исходя из личного опыта, путём проб и ошибок. Наброски были ещё пару месяцев назад, а так как стартовал конкурс, то решил дописать, обновить информацию.
Картинки были созданы с помощью фигмы, где то я сам делал, где-то иишкой красиво подправлял.
Любой, кто хоть раз занимался анализом любого вида софта, понимает о чём я. Вы загружаете малварь/другое ПО в IDA Pro(любой другой дизассемблер,Иду я беру в качестве примера), включаете декомпилятор и сталкиваетесь с кучей всякого непонятного.
Вместо внятной логики перед глазами предстает синтаксическая жесть (по другому не назвать)
Переменные по типу v1, v2, v3
Функций вида sub_403000 , а Константы вообще без комментариев
long long func_8048A10()
{
long long res;
long long temp_v;
res = internal_call_1(2, 1, 0);
if ( res < 0 )
return -1LL;
temp_v = res;
*(short *)(res + 2) = helper_transform(8080);
*(int *)(temp_v + 4) = parse_addr("127.0.0.1");
if ( (unsigned int)check_status(temp_v, res, 16) < 0 )
{
cleanup(temp_v);
return -1LL;
}
return (unsigned int)temp_v;
}
C
{
long long res;
long long temp_v;
res = internal_call_1(2, 1, 0);
if ( res < 0 )
return -1LL;
temp_v = res;
*(short *)(res + 2) = helper_transform(8080);
*(int *)(temp_v + 4) = parse_addr("127.0.0.1");
if ( (unsigned int)check_status(temp_v, res, 16) < 0 )
{
cleanup(temp_v);
return -1LL;
}
return (unsigned int)temp_v;
}
C
Код:
long long func_8048A10()
{
long long res;
long long temp_v;
res = internal_call_1(2, 1, 0);
if ( res < 0 )
return -1LL;
temp_v = res;
*(short *)(res + 2) = helper_transform(8080);
*(int *)(temp_v + 4) = parse_addr("127.0.0.1");
if ( (unsigned int)check_status(temp_v, res, 16) < 0 )
{
cleanup(temp_v);
return -1LL;
}
return (unsigned int)temp_v;
}
Прежде чем интегрировать искусственный интеллект, нужно понять как вообще получается псевдокод из машинного кода.
На старте у нас есть только массив байтов. Задача первого этапа, это сопоставить байты с конкретными процессорными инструкциями.
Стандартом является библиотека Capstone Engine. Она берет на себя всю сложность поддержки различных архитектур (я не буду вдаваться в подробности, это не столь важно)
P.S Для примера я попросил набросать код нейронку
from capstone import *
# Срез байтов из исполняемого сегмента файла
raw_payload = b"\x55\x48\x89\xe5\x48\x83\xec\x10"
# Конфигурация движка под 64-битную архитектуру Intel
disassembler = Cs(CS_ARCH_X86, CS_MODE_64)
for instruction in disassembler.disasm(raw_payload, 0x1000):
print(f"ADDR: 0x{instruction.address:x} | {instruction.mnemonic.upper()} {instruction.op_str}")
Python
# Срез байтов из исполняемого сегмента файла
raw_payload = b"\x55\x48\x89\xe5\x48\x83\xec\x10"
# Конфигурация движка под 64-битную архитектуру Intel
disassembler = Cs(CS_ARCH_X86, CS_MODE_64)
for instruction in disassembler.disasm(raw_payload, 0x1000):
print(f"ADDR: 0x{instruction.address:x} | {instruction.mnemonic.upper()} {instruction.op_str}")
Python
Код:
from capstone import *
# Срез байтов из исполняемого сегмента файла
raw_payload = b"\x55\x48\x89\xe5\x48\x83\xec\x10"
# Конфигурация движка под 64-битную архитектуру Intel
disassembler = Cs(CS_ARCH_X86, CS_MODE_64)
for instruction in disassembler.disasm(raw_payload, 0x1000):
print(f"ADDR: 0x{instruction.address:x} | {instruction.mnemonic.upper()} {instruction.op_str}")
На выходе мы получаем линейный список мнемоник. Это уже можно читать, но общая логика программы все еще скрыта.
Давайте уясним одно, программа - это не просто список команд,а целое древо всевозможных решений. Чтобы восстановить так называемое древо, мы строим График потока управления
Суть этого процесса:
- Базовые блоки: Мы группируем инструкции в атомарные узлы. Внутри такого блока нет прыжков или вызовов - выполнение идет сверху вниз.
- Ребра графа: Соединяем блоки линиями перехода. Условный переход создает две ветки (T/F в просто народе правда или не правда), формируя структуру if-else.
Многие ошибочно полагают, что декомпилятор просто заменяет слова MOV на знак =
На самом деле, между сырым ассемблером и читаемым кодом лежит переводческий мост. Это универсальный язык посредник. Представьте, что вы переводите с китайского на инди через английский.
Проблема ассемблера в том, что он перегружен флагами. Инструкция ADD не просто складывает числа, она меняет флаги нуля, переноса, переполнения. IR очищает эту логику, делая её явной и понятной для математического анализа.
Для удобства, я сделал картинку в виде таблицы

Почему это важно для обучения нейронок
Если мы будем закидывать в нейросеть чистый ассемблер, ей придется тратить очень много времени, чтобы понять архитектурные особенности конкретного процессора.
Если мы будем закидывать в нейросеть чистый ассемблер, ей придется тратить очень много времени, чтобы понять архитектурные особенности конкретного процессора.
Финальный этап: конвертация IR в читаемый C код.
Анализируем CFG, определяем тип блоков, и генерируем соответствующие конструкции:
int function_400000(int arg1) {
int var_4;
var_4 = arg1;
if (var_4 <= 0) {
return 0;
}
return 1;
}
C
int var_4;
var_4 = arg1;
if (var_4 <= 0) {
return 0;
}
return 1;
}
C
Код:
int function_400000(int arg1) {
int var_4;
var_4 = arg1;
if (var_4 <= 0) {
return 0;
}
return 1;
}
Но самое важное, имена переменных все еще автоматические (var_4, arg1) Здесь в нашу скажем так игру вступает ИИ
Представьте: у вас есть функция с 20 переменными. Вручную анализировать каждую это часы работы. ИИ нам поможет в любом случае:
- Понять контекст
- Предложить имена
- Добавить комментарии:
- Определить назначение функции
Конечно,это далеко не весь список,где ИИшки могут помочь, поэтому не стал описывать дальше.
Все мы прекрасно понимаем что цензуры есть везде, нейронки не исключение. ChatGPT для анализа вредоносов вам не поможет, вы упрётесь в цензуру.
Обходы ищите сами, я в этом вам не помогу.
Гемини я специально не брал в таблицу, в нём нет смысла от слова совсем.
Обходы ищите сами, я в этом вам не помогу.
Гемини я специально не брал в таблицу, в нём нет смысла от слова совсем.
Декомпилятор отправляет в ИИшку три вещи:
1. Псевдокод функции
2. Контекст
3. Промпт

import requests
[SIZE=4]import json[/SIZE]
[SIZE=4]class AIDecompiler:[/SIZE]
[SIZE=4] def __init__(self, api_key, model="gpt-5.2"):[/SIZE]
[SIZE=4] self.api_key = api_key[/SIZE]
[SIZE=4] self.model = model[/SIZE]
[SIZE=4] self.cache = {}[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] def analyze_function(self, pseudocode, context):[/SIZE]
[SIZE=4] # Проверяем кэш[/SIZE]
[SIZE=4] cache_key = hashlib.sha256(pseudocode.encode()).hexdigest()[/SIZE]
[SIZE=4] if cache_key in self.cache:[/SIZE]
[SIZE=4] return self.cache[cache_key][/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] # Формируем промпт[/SIZE]
[SIZE=4] prompt = self.build_prompt(pseudocode, context)[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] # API запрос[/SIZE]
[SIZE=4] response = requests.post([/SIZE]
[SIZE=4] "https://api.openai.com/v1/chat/completions",[/SIZE]
[SIZE=4] headers={[/SIZE]
[SIZE=4] "Authorization": f"Bearer {self.api_key}",[/SIZE]
[SIZE=4] "Content-Type": "application/json"[/SIZE]
[SIZE=4] },[/SIZE]
[SIZE=4] json={[/SIZE]
[SIZE=4] "model": self.model,[/SIZE]
[SIZE=4] "messages": [[/SIZE]
[SIZE=4] {"role": "system", "content": self.get_system_prompt()},[/SIZE]
[SIZE=4] {"role": "user", "content": prompt}[/SIZE]
[SIZE=4] ],[/SIZE]
[SIZE=4] "temperature": 0.2,[/SIZE]
[SIZE=4] "response_format": {"type": "json_object"}[/SIZE]
[SIZE=4] }[/SIZE]
[SIZE=4] )[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] result = response.json()[/SIZE]
[SIZE=4] analysis = json.loads(result['choices'][0]['message']['content'])[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] # Сохраняем в кэш[/SIZE]
[SIZE=4] self.cache[cache_key] = analysis[/SIZE]
[SIZE=4] return analysis[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] def build_prompt(self, code, ctx):[/SIZE]
[SIZE=4] return f"""Analyze this decompiled function:[/SIZE]
[SIZE=4]```c[/SIZE]
[SIZE=4]{code}[/SIZE]
[SIZE=4]```[/SIZE]
[SIZE=4]Context:[/SIZE]
[SIZE=4]- API calls: {', '.join(ctx.get('apis', []))}[/SIZE]
[SIZE=4]- Strings: {', '.join(ctx.get('strings', []))}[/SIZE]
[SIZE=4]- Constants: {', '.join(map(str, ctx.get('numbers', [])))}[/SIZE]
[SIZE=4]Provide JSON with function_name, purpose, and variable renames."""[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] def get_system_prompt(self):[/SIZE]
[SIZE=4] return "You are an expert reverse engineer. Analyze code and suggest meaningful names based on usage patterns. Output JSON only."
Python
[/SIZE]
[SIZE=4]import json[/SIZE]
[SIZE=4]class AIDecompiler:[/SIZE]
[SIZE=4] def __init__(self, api_key, model="gpt-5.2"):[/SIZE]
[SIZE=4] self.api_key = api_key[/SIZE]
[SIZE=4] self.model = model[/SIZE]
[SIZE=4] self.cache = {}[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] def analyze_function(self, pseudocode, context):[/SIZE]
[SIZE=4] # Проверяем кэш[/SIZE]
[SIZE=4] cache_key = hashlib.sha256(pseudocode.encode()).hexdigest()[/SIZE]
[SIZE=4] if cache_key in self.cache:[/SIZE]
[SIZE=4] return self.cache[cache_key][/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] # Формируем промпт[/SIZE]
[SIZE=4] prompt = self.build_prompt(pseudocode, context)[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] # API запрос[/SIZE]
[SIZE=4] response = requests.post([/SIZE]
[SIZE=4] "https://api.openai.com/v1/chat/completions",[/SIZE]
[SIZE=4] headers={[/SIZE]
[SIZE=4] "Authorization": f"Bearer {self.api_key}",[/SIZE]
[SIZE=4] "Content-Type": "application/json"[/SIZE]
[SIZE=4] },[/SIZE]
[SIZE=4] json={[/SIZE]
[SIZE=4] "model": self.model,[/SIZE]
[SIZE=4] "messages": [[/SIZE]
[SIZE=4] {"role": "system", "content": self.get_system_prompt()},[/SIZE]
[SIZE=4] {"role": "user", "content": prompt}[/SIZE]
[SIZE=4] ],[/SIZE]
[SIZE=4] "temperature": 0.2,[/SIZE]
[SIZE=4] "response_format": {"type": "json_object"}[/SIZE]
[SIZE=4] }[/SIZE]
[SIZE=4] )[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] result = response.json()[/SIZE]
[SIZE=4] analysis = json.loads(result['choices'][0]['message']['content'])[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] # Сохраняем в кэш[/SIZE]
[SIZE=4] self.cache[cache_key] = analysis[/SIZE]
[SIZE=4] return analysis[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] def build_prompt(self, code, ctx):[/SIZE]
[SIZE=4] return f"""Analyze this decompiled function:[/SIZE]
[SIZE=4]```c[/SIZE]
[SIZE=4]{code}[/SIZE]
[SIZE=4]```[/SIZE]
[SIZE=4]Context:[/SIZE]
[SIZE=4]- API calls: {', '.join(ctx.get('apis', []))}[/SIZE]
[SIZE=4]- Strings: {', '.join(ctx.get('strings', []))}[/SIZE]
[SIZE=4]- Constants: {', '.join(map(str, ctx.get('numbers', [])))}[/SIZE]
[SIZE=4]Provide JSON with function_name, purpose, and variable renames."""[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] def get_system_prompt(self):[/SIZE]
[SIZE=4] return "You are an expert reverse engineer. Analyze code and suggest meaningful names based on usage patterns. Output JSON only."
Python
Код:
import requests
[SIZE=4]import json[/SIZE]
[SIZE=4]class AIDecompiler:[/SIZE]
[SIZE=4] def __init__(self, api_key, model="gpt-5.2"):[/SIZE]
[SIZE=4] self.api_key = api_key[/SIZE]
[SIZE=4] self.model = model[/SIZE]
[SIZE=4] self.cache = {}[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] def analyze_function(self, pseudocode, context):[/SIZE]
[SIZE=4] # Проверяем кэш[/SIZE]
[SIZE=4] cache_key = hashlib.sha256(pseudocode.encode()).hexdigest()[/SIZE]
[SIZE=4] if cache_key in self.cache:[/SIZE]
[SIZE=4] return self.cache[cache_key][/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] # Формируем промпт[/SIZE]
[SIZE=4] prompt = self.build_prompt(pseudocode, context)[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] # API запрос[/SIZE]
[SIZE=4] response = requests.post([/SIZE]
[SIZE=4] "https://api.openai.com/v1/chat/completions",[/SIZE]
[SIZE=4] headers={[/SIZE]
[SIZE=4] "Authorization": f"Bearer {self.api_key}",[/SIZE]
[SIZE=4] "Content-Type": "application/json"[/SIZE]
[SIZE=4] },[/SIZE]
[SIZE=4] json={[/SIZE]
[SIZE=4] "model": self.model,[/SIZE]
[SIZE=4] "messages": [[/SIZE]
[SIZE=4] {"role": "system", "content": self.get_system_prompt()},[/SIZE]
[SIZE=4] {"role": "user", "content": prompt}[/SIZE]
[SIZE=4] ],[/SIZE]
[SIZE=4] "temperature": 0.2,[/SIZE]
[SIZE=4] "response_format": {"type": "json_object"}[/SIZE]
[SIZE=4] }[/SIZE]
[SIZE=4] )[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] result = response.json()[/SIZE]
[SIZE=4] analysis = json.loads(result['choices'][0]['message']['content'])[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] # Сохраняем в кэш[/SIZE]
[SIZE=4] self.cache[cache_key] = analysis[/SIZE]
[SIZE=4] return analysis[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] def build_prompt(self, code, ctx):[/SIZE]
[SIZE=4] return f"""Analyze this decompiled function:[/SIZE]
[SIZE=4]```c[/SIZE]
[SIZE=4]{code}[/SIZE]
[SIZE=4]```[/SIZE]
[SIZE=4]Context:[/SIZE]
[SIZE=4]- API calls: {', '.join(ctx.get('apis', []))}[/SIZE]
[SIZE=4]- Strings: {', '.join(ctx.get('strings', []))}[/SIZE]
[SIZE=4]- Constants: {', '.join(map(str, ctx.get('numbers', [])))}[/SIZE]
[SIZE=4]Provide JSON with function_name, purpose, and variable renames."""[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] def get_system_prompt(self):[/SIZE]
[SIZE=4] return "You are an expert reverse engineer. Analyze code and suggest meaningful names based on usage patterns. Output JSON only."
Оптимизируем наш код, добавляя многопоточность
from concurrent.futures import ThreadPoolExecutor
[SIZE=4]def analyze_all_functions(functions, ai_client):[/SIZE]
[SIZE=4] results = {}[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] with ThreadPoolExecutor(max_workers=8) as executor:[/SIZE]
[SIZE=4] futures = {}[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] for func in functions:[/SIZE]
[SIZE=4] future = executor.submit([/SIZE]
[SIZE=4] ai_client.analyze_function,[/SIZE]
[SIZE=4] func.pseudocode,[/SIZE]
[SIZE=4] func.context[/SIZE]
[SIZE=4] )[/SIZE]
[SIZE=4] futures[future] = func[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] for future in futures:[/SIZE]
[SIZE=4] func = futures[future][/SIZE]
[SIZE=4] try:[/SIZE]
[SIZE=4] result = future.result()[/SIZE]
[SIZE=4] results[func.address] = result[/SIZE]
[SIZE=4] except Exception as e:[/SIZE]
[SIZE=4] print(f"Failed to analyze {func.name}: {e}")[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] return results[/SIZE]
[SIZE=4]
Python
[/SIZE]
[SIZE=4]def analyze_all_functions(functions, ai_client):[/SIZE]
[SIZE=4] results = {}[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] with ThreadPoolExecutor(max_workers=8) as executor:[/SIZE]
[SIZE=4] futures = {}[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] for func in functions:[/SIZE]
[SIZE=4] future = executor.submit([/SIZE]
[SIZE=4] ai_client.analyze_function,[/SIZE]
[SIZE=4] func.pseudocode,[/SIZE]
[SIZE=4] func.context[/SIZE]
[SIZE=4] )[/SIZE]
[SIZE=4] futures[future] = func[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] for future in futures:[/SIZE]
[SIZE=4] func = futures[future][/SIZE]
[SIZE=4] try:[/SIZE]
[SIZE=4] result = future.result()[/SIZE]
[SIZE=4] results[func.address] = result[/SIZE]
[SIZE=4] except Exception as e:[/SIZE]
[SIZE=4] print(f"Failed to analyze {func.name}: {e}")[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] return results[/SIZE]
[SIZE=4]
Python
Код:
from concurrent.futures import ThreadPoolExecutor
[SIZE=4]def analyze_all_functions(functions, ai_client):[/SIZE]
[SIZE=4] results = {}[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] with ThreadPoolExecutor(max_workers=8) as executor:[/SIZE]
[SIZE=4] futures = {}[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] for func in functions:[/SIZE]
[SIZE=4] future = executor.submit([/SIZE]
[SIZE=4] ai_client.analyze_function,[/SIZE]
[SIZE=4] func.pseudocode,[/SIZE]
[SIZE=4] func.context[/SIZE]
[SIZE=4] )[/SIZE]
[SIZE=4] futures[future] = func[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] for future in futures:[/SIZE]
[SIZE=4] func = futures[future][/SIZE]
[SIZE=4] try:[/SIZE]
[SIZE=4] result = future.result()[/SIZE]
[SIZE=4] results[func.address] = result[/SIZE]
[SIZE=4] except Exception as e:[/SIZE]
[SIZE=4] print(f"Failed to analyze {func.name}: {e}")[/SIZE]
[SIZE=4] [/SIZE]
[SIZE=4] return results[/SIZE]
[SIZE=4]
Результат: С 8 потоками анализ 1к функций занимает +-10-15 минут вместо кучи часов.

Каждый лично для себя сделает вывод исходя из прочитанного. В наше время ИИ естественно не может полностью заменить человека, но как минимум облегчить рутину, массивные задачи она с лёгкостью сможет.
Благодарю за прочтение. В следующей статье мы рассмотрим реальный кейс,будем анализировать малвари(вы можете скинуть любой свой вирус, его мы тоже можем рассмотреть в качестве подопытного)





Комментарии 0