Начинающий
- Статус
- Оффлайн
- Регистрация
- 21 Июн 2025
- Сообщения
- 107
- Реакции
- 5
Исключительно для специалистов аналитиков угроз и разработчиков средств защиты. Все примеры - для изучения методов атак с целью разработки контрмер.
Статья писалась исключительно для югейма, ну, потому что скучно)
Сразу скажу, ту же сигнатуру UPX это точно сломает. Я видел, как школьники(малварь-девы) тупо вешали на наличие в импорте только трёх импортов - VirtualProtect и ещё каких-то двух функций.
Меняем VirtualProtect на ординал, и нет UPX.
Мини-статья, погнали.
Возможно кому-то будет полезна
1) Запускаем x64 Native Tools Command Prompt For VS 2022 или обычную cmd.
2) После чего вводим dumpbin, экспортирование и указанием полного пути к библиотеке, после чего через findstr непосредственно находим ординал нужной нам функции:
После чего мы видим:
По левому ряду расположены непосредственно сами ординалы, теперь вопрос, как малварь-девы используют подобную технику для скрытия детектов? Ну, или сокращения их количества, об этом ниже:
Это максимальное противоественно для нормальных программ, что вызывает недоверие со стороны антивируса.
Весь наш исполняемый код:
Если делать наоборот - писать на высокоуровнем языке вредонос, то:
1. Внедрить не получится - вес большой
2. Внедрить получится = из-за большого веса антивирус сразу увидит жирное пятно на бинарнике - артефакт
3. Заморочишься делать адекватную инъекцию. Если на ассемблере я могу из бинарника изъять RVA функции из импорт-таблицы и сделать call [hMod+RVA] и полностью слиться с программой, быть с ней одним целым, то на С так не сделать - нужно танцевать с бубном как дурак.
4. Без инъекции адекватный "крипт" не сделать - будешь пытаться что-то своё мусолить, что-то генерировать, но нейросеть на антивирусе скажет, что это херня и аномалия.
Статья писалась исключительно для югейма, ну, потому что скучно)
Сразу скажу, ту же сигнатуру UPX это точно сломает. Я видел, как школьники(малварь-девы) тупо вешали на наличие в импорте только трёх импортов - VirtualProtect и ещё каких-то двух функций.
Меняем VirtualProtect на ординал, и нет UPX.
Мини-статья, погнали.
Возможно кому-то будет полезна
1) Что такое ординал и как его найти
В первую очередь нужно задуматься о том, как вообще нам найти сам ординал, но перед этим стоит рассказать про ординал.
Что такое ординал функции? - Это просто индексы в массиве экспортируемых функций
Я попробую привести аналогию: Как мы знаем, в ntdll каждая функция ядра имеет сискол-таблы, то есть, у каждого сисемного вызова есть сискол-номер.
Тоже самое и с ординалом функции, каждая функция имеет некий идентификатор(ординал) пример: MessageBoxA -> 2151
Ну, что, что такое ординал мы узнали, теперь можно переходить к вопросу: Как найти ординал функции, все просто - через dumpbinВ первую очередь нужно задуматься о том, как вообще нам найти сам ординал, но перед этим стоит рассказать про ординал.
Что такое ординал функции? - Это просто индексы в массиве экспортируемых функций
Я попробую привести аналогию: Как мы знаем, в ntdll каждая функция ядра имеет сискол-таблы, то есть, у каждого сисемного вызова есть сискол-номер.
Тоже самое и с ординалом функции, каждая функция имеет некий идентификатор(ординал) пример: MessageBoxA -> 2151
1) Запускаем x64 Native Tools Command Prompt For VS 2022 или обычную cmd.
2) После чего вводим dumpbin, экспортирование и указанием полного пути к библиотеке, после чего через findstr непосредственно находим ординал нужной нам функции:
dumpbin:
dumpbin /exports C:\Windows\System32\kernel32.dll | findstr VirtualAlloc
2) Практика
Как инструмент мы будем использовать компилятор и ассемблер FASM, он простой и понятен.
Немного стоит поговорить про кодовую базу и про сам FASM.
Чаще всего, малварь разработчики не используют никакие упаковщики, потому что понимают, что кодовая база должна быть чистой и уникальной. В последнее время часто пишут малвари на GO, поскольку их кодовая база достаточно чиста и пока не разложилась на вредоносные гены, как на Си и С++.
А касаемо фасма, он дает полностью сырой и девственный бинарь. Для антивирусов - для них это аномалия.(он тоже не чист и имеет вредоносные гены)Как инструмент мы будем использовать компилятор и ассемблер FASM, он простой и понятен.
Немного стоит поговорить про кодовую базу и про сам FASM.
Чаще всего, малварь разработчики не используют никакие упаковщики, потому что понимают, что кодовая база должна быть чистой и уникальной. В последнее время часто пишут малвари на GO, поскольку их кодовая база достаточно чиста и пока не разложилась на вредоносные гены, как на Си и С++.
Ну, что, переходим к практике.
Я реализовал немного подозрительный код для антивирусов и сканеров.
Наш код будет выделять 4096 байт в памяти процесса, после чего моментально их освободит.
Регистр r9 имеет значение 40h(PAGE_EXECUTE_READWRITE)
Я реализовал немного подозрительный код для антивирусов и сканеров.
Наш код будет выделять 4096 байт в памяти процесса, после чего моментально их освободит.
Регистр r9 имеет значение 40h(PAGE_EXECUTE_READWRITE)
Это максимальное противоественно для нормальных программ, что вызывает недоверие со стороны антивируса.
C:
// чистая программа
.text -> PAGE_EXECUTE_READ (0x20) // исполнить код
.data -> PAGE_READWRITE (0x04) // читать или писать данные
// малварь объеденяют все сразу:
.shellcode → PAGE_EXECUTE_READWRITE (0x40)
Весь наш исполняемый код:
C:
format PE64 GUI
entry start
include 'C:\FLAT\INCLUDE\win64a.inc'
section '.text' code readable executable
start:
sub rsp, 28h
mov rcx, 0
mov rdx, 4096 // тут выделяемые байты
mov r8, 3000h
mov r9, 40h // тот самый PAGE
call [VirtualAlloc]
test rax, rax
jz error_alloc
mov [alloc_ptr], rax // указатель который хранит информацию касаемо ошибки в случае безуспешности
mov rcx, [alloc_ptr]
xor edx, edx
mov r8, 8000h
xor r9, r9
call [VirtualFree]
test rax, rax
jz error_free
xor rcx, rcx
lea rdx, [msg]
lea r8, [title]
xor r9, r9
call [MessageBoxA]
jmp exit
error_alloc:
lea rdx, [msg_alloc_fail]
jmp show_error
error_free:
lea rdx, [msg_free_fail]
show_error:
xor rcx, rcx
lea r8, [title]
mov r9, 10h
call [MessageBoxA]
exit:
xor rcx, rcx
call [ExitProcess]
section '.data' data readable writeable
msg db 'mem test - yes not error',0
titles db 'memory test',0
alloc_ptr dq 0
msg_success db 'VirtualAlloc + VirtualFree - sucessfyly!',0
msg_alloc_fail db 'virtualloc failed!',0
msg_free_fail db 'virtualfree failed!',0
title db 'mem test',0
section '.idata' import data readable writeable
library user32, 'USER32.DLL', \
kernel32, 'KERNEL32.DLL'
import user32, \
MessageBoxA, 'MessageBoxA'
import kernel32, \
ExitProcess, 'ExitProcess',\
VirtualAlloc, 'VirtualAlloc',\
VirtualFree, 'VirtualFree'
Прошу заметить, что пока-что мы не используем ординалы функций, а просто вызываем ее напрямую, антивирус это видит судя по IAT:
Проверяем работоспособность нашей программы:
Все прекрасно работает, в процессе выделяется память, наши байты, теперь преобразуем нашу программу в EXE файл и посмотрим что выведет VirusTotal:
Получилось 7 детектов, что, кстати не столь много, но для малварь-дрочеров это считается большим, поэтому они решают прибегнуть к использованию ординаров, давайте же сделаем ту же самую программу, только уже вызывая функцию через ее идентификатор, а не напрямую:
Заходим в CMD находим ординар нужным нам функций:
Теперь в таблице импорта используем наши ординары вместо прямого вызова:
Код:
Проверяем работоспособность нашей программы:
Все прекрасно работает, в процессе выделяется память, наши байты, теперь преобразуем нашу программу в EXE файл и посмотрим что выведет VirusTotal:
Получилось 7 детектов, что, кстати не столь много, но для малварь-дрочеров это считается большим, поэтому они решают прибегнуть к использованию ординаров, давайте же сделаем ту же самую программу, только уже вызывая функцию через ее идентификатор, а не напрямую:
Заходим в CMD находим ординар нужным нам функций:
Теперь в таблице импорта используем наши ординары вместо прямого вызова:
Код:
C:
format PE64 GUI
entry start
include 'C:\FLAT\INCLUDE\win64a.inc'
section '.text' code readable executable
start:
sub rsp, 28h
mov rcx, 0
mov rdx, 4096
mov r8, 3000h
mov r9, 40h
call [VirtualAlloc]
test rax, rax
jz error_alloc
mov [alloc_ptr], rax
mov rcx, [alloc_ptr]
xor edx, edx
mov r8, 8000h
xor r9, r9
call [VirtualFree]
test rax, rax
jz error_free
xor rcx, rcx
lea rdx, [msg]
lea r8, [title]
xor r9, r9
call [MessageBoxA]
jmp exit
error_alloc:
lea rdx, [msg_alloc_fail]
jmp show_error
error_free:
lea rdx, [msg_free_fail]
show_error:
xor rcx, rcx
lea r8, [title]
mov r9, 10h
call [MessageBoxA]
exit:
xor rcx, rcx
call [ExitProcess]
section '.data' data readable writeable
msg db 'mem test - yes not error',0
titles db 'memory test',0
alloc_ptr dq 0
msg_success db 'VirtualAlloc + VirtualFree - sucessfyly!',0
msg_alloc_fail db 'virtualloc failed!',0
msg_free_fail db 'virtualfree failed!',0
title db 'mem test',0
section '.idata' import data readable writeable
library user32, 'USER32.DLL', \
kernel32, 'KERNEL32.DLL'
import user32, \
MessageBoxA, 'MessageBoxA'
import kernel32, \
ExitProcess, 'ExitProcess',\
VirtualAlloc, 1536,\ // ОРДИНАР
VirtualFree, 1539 // ОРДИНАР
Теперь в таблице импорта красуются наши ординары функций, теперь, давайте скомпилируем нашу программу и посмотрим результат на VirusTotal:
Вауля! Получается уже 5 детектов.
Заключение.
Вообще, малварь-разработчики любят использовать code-save инъекцию в процесс шеллкодом, чтобы снизить процесс детектов.
Во вредоносной сфере используется так называемый "крипт". И тут проходит главная цепочка - пишем на ассемблере (широкие возможности в реализации, девственный бинарь, малый размер), а внедряем его в доверенные легитимные высокоуровневые программы. "Волк в овечьей шкуре".Вауля! Получается уже 5 детектов.
Заключение.
Вообще, малварь-разработчики любят использовать code-save инъекцию в процесс шеллкодом, чтобы снизить процесс детектов.
Если делать наоборот - писать на высокоуровнем языке вредонос, то:
1. Внедрить не получится - вес большой
2. Внедрить получится = из-за большого веса антивирус сразу увидит жирное пятно на бинарнике - артефакт
3. Заморочишься делать адекватную инъекцию. Если на ассемблере я могу из бинарника изъять RVA функции из импорт-таблицы и сделать call [hMod+RVA] и полностью слиться с программой, быть с ней одним целым, то на С так не сделать - нужно танцевать с бубном как дурак.
4. Без инъекции адекватный "крипт" не сделать - будешь пытаться что-то своё мусолить, что-то генерировать, но нейросеть на антивирусе скажет, что это херня и аномалия.
Всем поки.