Ступень 3: самый мусорный
Идея: внедряем в расшифровщик мусорные команды, не имеющие никакого побочного эффекта, но преображающие код до неузнаваемости. Чаще всего используются различные вариации NOP, которых насчитываются десятки (например, XCHG EBX, EBX/MOV ECX,ECX/Jx$+2/XCHG EAX, EBX; XCHG EBX, EAX и т.д. — главное фантазию иметь).
Обработанный расшифровщик из листинга 4 после "экзекуции" может выглядеть, например, так:
XCHG ECX, ECX
MOV ESI, offset body_begin
JO $+2
MOV EDI, ESI
MOV EAX, EAX
MOV ECX, offset body_end - body_begin
NOP
my_begin:
LODSB
JNZ $+2
XOR AL, 66h
MOV EDI,EDI
STOSB
JZ $+2
LOOP my_begin
Листинг 9 расшифровщик, разбавленный ничего не значащими мусорными командами
Какие проблемы возникают при кодировании? Проблем много. Рассмотрим лишь две из них, как самые важные. Если не предпринять никаких усилий, уже через несколько поколений размер вируса вырастет до облаков и продолжит расти до тех пор, пока не упрется в конец адресного пространства (или отведенной приложению памяти). Чтобы этого избежать, необходимо либо вычищать имеющийся мусор перед добавлением новой порции (что сложно), либо включить в зашифрованное тело копию расшифровщика и всегда "издеваться" только над ней.
А вот вторая проблема. Чтобы добавить мусорную инструкцию между двумя другими, необходимо как-то определить где кончается одна и начинается другая. Вот для этого нам и нужен дизассемблер длин. Дизассемблер длин представляет собой до предела упрощенный x86 дизассемблер, декодирующий инструкции и определяющий их границы. Это достаточно сложная задача, которая не имеет простых и красивых решений. Приходится зарываться в формат кодирования машинных команд, а это целый исторический пласт с кучей наслоений. Когда-то мы дойдем и до него, но нельзя ли пока обойтись методом грубой силы? Можно! Некоторые вирусы определяют границы команд с помощью трассировки, так сказать, руками самого процессора. Но это все равно утомительно. Лучше (и быстрее!) определить границы вручную и занести в специальную таблицу. Уродливо, зато эффективно.
Как антивирусы справляются с такими файлами? Да очень просто! Вычищают весь мусор и натягивают на отстоявшийся "осадок" старую добрую сигнатуру. Мусорные команды легко генерировать, но легко и распознавать! Так что данная методика крайне ненадежна и годится разве что для тренировки.