www.pudn.com > vgcrypt.zip > 75SRC.ASM


; 
;**WARNING: Encryption and Decryption code closed to public for security (as if there 
; were any). Everything else is here tho. 
; 
; 
;VGCrypt PE Encryptor v0.75 Beta 
;(c)1998 Virogen 
;email: vgen@hotmail.com 
;---------------------------------------------------------------- 
;  
; This is a fairly simple PE encryptor I wrote up. I commented everything 
; that is relavent to PE appendation or insertion, more so than I needed to 
; even. The most interesting feature of this encryptor is that it attempts to 
; find a location to insert itself between object virtual size and the next 
; file alignment boundary, thus not changing the physical file size. 
;  
; Note that this code is still under development. 
;  
; Features: 
;   -three types of PE parasticality: 
;       1) install in cave - no physical size increase 
;       2) append to last object 
;       3) create new object 
;   -full win95/98/NT compliant 
;   -does not add new object unless you want to 
;   -stores correct new checksum of PE executable 
;   -preserves original file data/time and attributes 
;   -prompts u to encrypt again if file already encrypted, you can encrypt 
;    a file as many times as you want. Of course, eventually you will run out 
;    of available caves and the filesize will start increasing. 
;  
; Usage: 
;   -VGCRYPT filename 
; 
; 
; known bugs: 
;   -might be problems with some encrypted DLLs. 
; 
; 
; Note to coders: 
;   If you need to retrieve API RVAs in the decryptor, the best way is to 
;   manually import from the kernel32 export table in memory. The base of 
;   kernel32.dll can be obtained by using [esp] at entry and scanning down 
;   to the base. For more information, see my viral code at 
; 
; 
; Updates: 
;   11/26/98 v0.40: Initial release 
;   11/27/98 v0.45: Added simple SEH anti-debugging code 
;                   Fixed command line problem when running under winnt 
;                    dos box 
;                   Other minor changes in decryptor 
;   11/28/98 v0.50: Fixed winNT image problems 
;                   Added better anti-debugging code, but still needs improvements, 
;                    optimization, etc.               
;                   Closed decryptor and encryption source. Sorry, but all the other 
;                    code is still open 
;   11/28/98 v0.51: Reformatted decryptor a little, anti-debugging code still needs to 
;                    be improved alot. 
;   11/28/98 v0.54: Fixed exception when object with no physical offset/size encountered. 
;                   Temporarily disabled portion of anti-debugging code. 
;   11/29/98 v0.56: Source code beautification by Ghiribizzo. 
;                   EBP now preserved correctly 
;                   Minor winNT command line problem fixed 
;                   Encrypted DLLs now load, but some have unusual problems 
;                   Executables which are loaded at an image base other than the one 
;                   specifid in the PE header (unusual) will now work properly. 
;                   No longer flagged by AVP if appended to last object 
;                   Note that when we reach v0.60 I will re-release the source 
;                   code, with the noted exceptions of the encryption and decryption 
;                   code. 
;   11/30/98 v0.57: If no "caves" found, gives you choice of appending to last object or 
;                   creating a new object. 
;   11/30/98 v0.58: Minor bug fix in creating new object. 
;		    Was missing last object while traversing thru object table, oops. 
;   11/31/98 v0.60: Checks to make sure there is room to add another object to 
;		    object table before allowing user to select this option. 
;		    Other minor changes here and there. 
;   12/05/98 v0.61: Now accounts correctly for PEs loaded at a differing image base.  
;    		    I had forgotten to recalculate encrypted object addresses. This 
;		    was a minor bug because it is rare to have a PE loaded a base other 
;		    than the one specified in the header. 
;   12/09/98 v0.65: Now avoids encrypting import & export table no matter where it is at.  
;   		    Oops, should done this in the first place.  
;   12/19/98 v0.75: Improved security a little bit, still not secure at all.. someday 
;		    I will remedy this. 
;                    
; 
; 
; ==================================================================================== 
; Special thanks to Ghiribizzo who has provided more anti-debugging ideas than I can 
;  even hope to have time to implement. http://Ghiribizzo.home.ml.org 
; Greetz lapse,jp,vecna,darkman,Iczelion, and everyone else. 
; ==================================================================================== 
; 
; 
; 
include mywin.inc        
 
ID_OFF          equ     0ch    ; offset of our marker in PE 
DECRYPTOR_SIZE  equ     (offset decryptor_code_end-offset decryptor_code)  ; 
VIRTUAL_SIZE    equ     DECRYPTOR_SIZE 
MAX_OBJS        equ     6               ; maximum objects we can handle 
                                        ; by increasing this you are increasing the size 
                                        ; of the table in decryptor by MAX_OBJS*8. 
 
.586p 
locals 
jumps 
.model flat,STDCALL 
 
extrn   ExitProcess:PROC          
extrn   CreateFileA:PROC          
extrn   CloseHandle:PROC          
extrn   ReadFile:PROC             
extrn   WriteFile:PROC            
extrn   SetFilePointer:PROC       
extrn   MapViewOfFile:PROC        
extrn   CreateFileMappingA:PROC   
extrn   UnmapViewOfFile:PROC      
extrn   SetEndOfFile:PROC         
extrn   SetFilePointer:PROC       
extrn   GetFileAttributesA:PROC   
extrn   SetFileAttributesA:PROC   
extrn   GetFileSize:PROC          
extrn   GetTickCount:PROC         
extrn   GetFileSize:PROC          
extrn   GetFileTime:PROC          
extrn   SetFileTime:PROC          
extrn   CheckSumMappedFile:PROC   
extrn   MessageBoxA:PROC          
extrn   GetCommandLineA:PROC      
extrn   lstrcat:PROC              
extrn   IsBadReadPtr:PROC         
extrn   WriteConsoleA:PROC 
extrn   GetStdHandle:PROC 
extrn   ReadConsoleA:PROC 
 
 
 
org 0   
.data                                   ; data object 
 
; conditional compile 
;console_app equ 1 
 
 
; 
cr      equ 0dh 
lf      equ 0ah 
tab     equ 9 
hline   equ 196 
marker  equ 90909090h 
 
cr_lf_tab       db cr,lf,tab,tab,0 
init_txt        db 50 dup(hline),cr,lf 
caption         db 'Virogen''s PE Encryptor v0.75, (c)1998 Virogen[NOP]' 
ifndef console_app 
                db 0 
endif            
ifdef console_app 
                db cr,lf,'                       email:vgen@hotmail.com',cr,lf 
                db 50 dup(hline),cr,lf,0         
endif            
badcmd_txt      db 'Invalid command line!',cr,lf,'Usage: VGCRYPT filename',cr,lf,0 
success_txt: 
ifdef console_app 
                db cr,lf 
endif            
                db 'Successfully encrypted!' 
ifdef console_app 
                db 0 
endif                            
file_txt        db cr,lf,' Installed on file: ',tab,0 
                db 400 dup (0)          ; plenty of space 
obj_txt         db cr,lf,' Installed in object: ',tab,0 
                db 9 dup(0) 
eobj_txt        db cr,lf,' Encrypted objects: ',0 
                db (MAX_OBJS*8)+1 dup(0)         
hole_txt        db cr,lf,'VGCrypt installed in alignment hole, with no phsyical size increase!',0 
already_txt: 
ifdef console_app 
                db cr,lf,'File appears to already be encrypted. Encrypting again.',0 
endif 
                db 'File appears to already be encrypted. Do you wish to encrypt again?',0 
append_question db 'Could not locate any "caves" to install into!',cr,lf,'Click YES' 
                db ' to create new object',cr,lf,'Click NO to append to last object.',0 
error_txt: 
ifdef console_app 
                db cr,lf,' ' 
endif            
                db 'There was an error encrypting the file!',cr,lf 
ifdef console_app 
                db 0 
endif            
fname_txt       db 'Specified file: ',0 
                db 260 dup(0) 
nohole_txt      db cr,lf,'No available "caves" to install into, forced to increase physical size.',0 
doing_obj_txt   db cr,lf,'Encrypting object: ',tab,0 
skip_obj_txt    db cr,lf,'Skipping object: ',tab,0 
found_hole_obj  db cr,lf,'Found hole in object: ',tab,0 
done_txt        db '..Done',0 
creation        dd 0,0                     ; our file time structures 
lastaccess      dd 0,0 
lastwrite       dd 0,0 
oldchksum       dd 0 
fsize           dd 0 
map_ptr         dd 0 
oldattrib       dd 0                        ; stored file attribs 
fnameptr        dd 0                        ; ptr to file name we're inf 
ptrpeheader     dd 0 
objPsize        dd 0 
maphandle       dd 0 
handle          dd 0 
objtblVA        dd 0 
objptr          dd 0 
lastobjimageoff dd 0 
originalpsize   dd 0 
originalvsize   dd 0 
error           db -1                       ; 
importtbl	dd 0 
exporttbl       dd 0 
byteswrote      dd 0 
hstdo           dd 0 
hstdi           dd 0 
ynbuf           db 0 
use_hole        db 0 
holeptr		dd 0 
 
 
bad_otbl:                       ; this is the list of bad objs - did I miss any? 
   dd 'rsr.'                            ; rsrc 
   dd 'ler.'                            ; relo 
   dd 'ade.'                            ; edata 
   dd 'ete.'                            ; etext 
   dd 'adi.'                            ; idata 
   dd 'adr.'                            ; rdata 
   dd 'slt.'                            ; tls  
   dd 0                                  
 
;---- decryptor code installed into file ----  
; 
; 
; 
;*** CLOSED SOURCE, for security 
; 
; 
; 
; --- end of decryptor code --- 
 
 
; --- start of VGCrypt --- 
.code                                   ; code object - change flags to rwx 
start: 
ifdef console_app        
        call    GetSHandle 
        lea     ebx,init_txt 
        call    WriteString 
endif    
        call    GetCommandLineA                 ; retrieve command line 
        or      eax,eax                          
        jz      _exit_bad_cmd_line              ; if none then abort /w msg 
        xchg    esi,eax 
sl: 
        cmp     byte ptr [esi],0                ; if first byte is NULL then something way wrong 
        jz      _exit_bad_cmd_line     
        shl     eax,8                           ; rotate 1 byte in eax, for loop.. eax running load 
        lodsb                           ; get next byte in al 
        cmp     eax,'rypt'                      ; end of our proggie name? 
        jnz     not_eoc 
        cmp     byte ptr [esi],'.' 
        jnz     esl 
not_eoc:     
        cmp     eax,'.exe'                      ; .exe end of our proggie name? 
        jz      esl 
        cmp     eax,'.EXE'                      ; .EXE end of our proggie name? 
        jnz     sl 
esl: 
        lodsb 
        cmp     al,' ' 
        jz      esl              
        cmp     al,'"' 
        jz      esl 
        dec     esi 
esl2:     
        cmp     byte ptr [esi],0                ; if first char in parameter 1 is NULL then we fuq 
        jz      _exit_bad_cmd_line     
         
ifndef console_app       
        push    esi                              
        push    offset success_txt               
        call    lstrcat                 ; append filename to success message 
endif    
ifdef console_app        
        push    esi 
        push    offset fname_txt 
        call    lstrcat  
        lea     ebx,fname_txt 
        call    WriteString 
endif    
        mov     fnameptr,esi                    ; set fnameptr->filename 
        call    EncryptFile                     ; go encrypt         
        ;cmp     error,-4 
        ;jz      _exit 
        cmp     error,-1                        ; error? 
        jz      _exit_error                     ; if so go display error message 
         
ifndef console_app       
        push    offset obj_txt 
        push    offset success_txt 
        call    lstrcat                 ; append object name we inserted or appending to 
         
        push    offset eobj_txt 
        push    offset success_txt 
        call    lstrcat                 ; append objects we encrypted    
         
        cmp     use_hole,1 
        jnz     no_hole_msg     
        push    offset hole_txt 
        jmp     app_success 
no_hole_msg:     
        push    offset nohole_txt     
app_success: 
        push    offset success_txt 
        call    lstrcat 
 
        push    0                  
        push    offset caption     
        push    offset success_txt 
        push    0                  
        call    MessageBoxA        
endif 
ifdef console_app 
        lea     ebx,success_txt 
        call    WriteString      
endif    
                                   
        xor     eax,eax            
        jmp     _exit              
 
_exit_error: 
ifndef console_app 
        push    fnameptr            
        push    offset error_txt    
        call    lstrcat             
 
        push    MB_ICONEXCLAMATION  
        push    offset caption      
        push    offset error_txt    
        push    0                   
        call    MessageBoxA         
endif 
ifdef console_app 
        lea     ebx,error_txt 
        call    WriteString      
endif    
        mov     eax,2               
        jmp     _exit               
  
_exit_bad_cmd_line:  
ifndef console_app       
        push    MB_ICONEXCLAMATION 
        push    offset caption     
        push    offset badcmd_txt  
        push    0                  
        call    MessageBoxA        
endif    
ifdef console_app 
        lea     ebx,badcmd_txt 
        call    WriteString 
endif    
        xor     eax,eax            
        inc     eax                
 
_exit:     
        call    ExitProcess,eax 
 
;----------------------------------------------- 
; encrypt file - call with fnameptr set 
; 
EncryptFile proc 
 
        mov     eax,fnameptr 
        push    eax                                                                
        call    GetFileAttributesA                  ; get file attributes          
        mov     oldattrib,eax                                                       
                                                                                    
        cmp     eax,-1                               ; if error then maybe shared   
        jnz     not_shared                                                          
        ret                                          ; can't encrypt it             
 
not_shared: 
        push    20h                                 ; +A 
        mov     eax,fnameptr 
        push    eax 
        call    SetFileAttributesA                  ; clear 'da attribs 
         
        mov     esi,fnameptr 
        call    OpenFile 
        call    test_error 
        jnc     open_ok 
        ret          
open_ok: 
        mov     handle,eax                                                           
                                                                                     
        push    offset creation                                                      
        push    offset lastaccess                                                    
        push    offset lastwrite                                                     
        push    eax                                                                  
        call    GetFileTime                           ; grab the file time           
                                                                                     
        xor     ecx,ecx                                ; only map size of file       
        call    create_mapping                        ; create file mapping          
        jc      abort_encrypt                                                        
                                               ; eax->mapped file                 
        cmp     word ptr [eax],'ZM'                    ; is EXE?                     
        jnz     abort_encrypt                                                        
                                                                                     
        call    GetPEHeader                           ; load esi->PE Header          
                                                                                     
        push    2                                                                    
        push    esi                                    ; test ptr for read acces  
        call    IsBadReadPtr                           ; was ptr any good?        
        or      eax,eax                                                              
        jnz     abort_encrypt                                                        
                                                                                     
        cmp     word ptr [esi],'EP'                    ; PE?                         
        jnz     abort_encrypt                                                        
        cmp     dword ptr [esi+ID_OFF],marker          ; marker?                     
        jnz     not_encrypted                          ; if yes, already processed   
ifndef console_app 
        push    MB_ICONHAND or MB_YESNO                                              
        push    offset caption                                                       
        push    offset already_txt                                                   
        push    0                                                                    
        call    MessageBoxA                                                          
        cmp     eax,IDYES                                                            
        jnz     abort_encrypt                                                        
endif 
ifdef console_app        
        lea     ebx,already_txt 
        call    WriteString 
endif    
not_encrypted: 
        call    unmap                                 ; unmap file                                    
                                                                                                      
        mov     ecx,1000h                              ; give us room to add to the file, if needed       
        call    create_mapping                        ; map file again                                
        jc      abort_encrypt                                                                         
                                                                                                      
        call    GetPEHeader                           ; load esi -> pe header                         
                                                                                                      
        call    GetTickCount                          ; get tick count                                
        mov     key,eax                                ; save for encryption key                      
                                                                                                      
        mov     dword ptr [esi+ID_OFF],marker          ; save marker                                  
                                                                                                      
        ;mov     eax,[esi+imagebase]                                                                   
        ;mov     svd_imagebase,eax                      ; save the image base                              
                                                                                                      
        mov     eax,[esi+datadir]			 
        mov     importtbl,eax 
        mov     eax,[esi+edatadir] 
        mov     exporttbl,eax 
         
        xor     eax,eax                                                                               
        mov     ax, word ptr [esi+NtHeaderSize]        ; get header size                              
        add     eax,18h                                ; object table is here                         
        add     eax,esi                                                                               
        mov     objptr,eax                                                                            
         
        ; Let's check for existance of cave after object table in PE header 
         
         
        ;mov     edi,[eax+objpoff] 
        ;add     edi,map_ptr 
        ;push    esi 
        ;int 3 
        ;push    eax 
        ;xor     eax,eax 
        ;mov     ax,[esi+numObj]         
        ;inc     eax 
        ;mov     ecx,40 
        ;xor     edx,edx         
        ;mul     ecx 
        ;pop     esi 
        ;add     esi,eax         
        ;cmp     esi,edi 
        ;jge     no_room_in_hdr 
        ;xchg    edi,esi 
        ;mov     cx,DECRYPTOR_SIZE 
        ;xor     eax,eax 
        ;push    edi 
        ;repz    scasb 
        ;pop     edi 
        ;or      cx,cx 
        ;jnz 	no_room_in_hdr                 
        ;pop     esi 
        ;push    esi 
        ;mov     eax,objptr 
         ;mov     ecx,[esi+filealign] 
        ;mov     ebx,[eax+objpoff] 
        ;sub     ebx,edi 
        ;sub     ebx,map_ptr 
        ;mov     [eax+objpoff],ebx 
                                 
        ;mov     holeptr,edi                 
        ;mov     use_hole,1 
no_room_in_hdr:         
                       
        ; Here we will traverse through the object table, encrypting objects 
        ; which can be encrypted and also searching for a 'cave' big enough 
        ; to hold us.         
        ;pop 	esi 
	push 	esi                 
        mov     eax,objptr 
        lea     edi,otable                                                          
        xor     ecx,ecx                                                             
        mov     cx,[esi+numObj]                          ; get number of objects    
;        dec     cx                                                                  
otbl_loop: 
        cmp     edi,offset otable_end-8                  ; filled up table? 
        jz      next_obj     
        call    test_obj                                 ; see if good obj name 
        jc      next_obj 
        pushad                               
        cmp     use_hole,1                               ; already found hole? 
        jz      no_hole_here 
        mov     edx,[eax+objpsize]                       ; get obj psize 
        mov     ecx,[eax+objvsize]                       ; get obj vsize         
        cmp     ecx,edx                                  ; any hole here? 
        jge     no_hole_here  
        sub     edx,ecx                                  ; get size of hole 
        cmp     edx,DECRYPTOR_SIZE                       ; big enough for us? 
        jl      no_hole_here     
        mov     objptr,eax                               ; save ptr obj rec 
        mov     use_hole,1                               ; set flag                                               
        mov     ecx,[eax+objvsize]                       ; encrypt vsize 
        mov     [edi+4],ecx                              ; if vsizeobject physical offset           
        add     esi,map_ptr                                                                      
        mov     edi,esi                                                                          
        call    encrypt_object                           ; encrypt the object                    
        pop     edi ecx eax                                                                              
ifdef console_app        
        lea     ebx,done_txt 
        call    WriteString      
endif    
ifdef console_app        
        jmp     next_did 
endif    
next_obj:     
ifdef console_app 
        lea     ebx,skip_obj_txt 
        call    WriteString      
        mov     ebx,eax 
        call    WriteString 
endif    
next_did: 
        add     eax,40                                   ; increment to next object record     
        loop    otbl_loop 
done_otbl:     
        pop     esi                                       ; restore ptr pe hdr    
                                                                               
        cmp     use_hole,1                                                    
        jz      found_hole                                                        
         
        sub     eax,40 
         
; make sure nuff room to add another object before we ask if 
; the user wants to. dunno if this is best way to do it, but I 
; just scan to make sure the next 40 bytes (1 object record) are 
; all 0. 
         
        pushad         
        mov     edi,eax 
        add     edi,40 
        mov 	ecx,40 
        xor	eax,eax 
 	repz    scasb 
 	or      ecx,ecx 
 	jnz 	go_append 	 
         
        push    MB_ICONQUESTION or MB_YESNO 
        push    offset caption 
        push    offset append_question 
        push    0 
        call    MessageBoxA              
        cmp     eax,IDNO 
        jz      go_append        
        ;cmp     eax,IDCANCEL 
        ;jnz     go_create 
        ;popad 
        ;mov     error,-4 
        ;jmp     abort_encrypt 
go_create:         
; user selected to create new object 
        popad                       	     
        mov     ecx,[eax+objrva]        	; get last object rva 
        add     ecx,[eax+objvsize]		; +=last object virtual size 
        push    eax				; save obj record ptr 
        xchg    ecx,eax				; eax=last object virtual end 
        mov     ecx,[esi+objalign]		; ecx=object alignment 
        call    align_fix			; go align da shiznit 
        xchg    ecx,eax                		; ecx=next object's rva 
        pop     eax               		; restore obj record ptr 
        mov     edx,[eax+objpoff]		; edx=last object physical offset 
        add     edx,[eax+objpsize]      	; edx+=last object psize=obj pend 
        add     eax,40				; goto next object in table (new) 
        mov     dword ptr [eax],'cgv.'		; set object name to .vgc 
        mov     dword ptr [eax+objpsize],0	; set psize to 0, updated later 
        mov     dword ptr [eax+objvsize],0	; set vsize to 0, update later 
        mov     [eax+objrva],ecx		; set rva of object 
        mov     [eax+objpoff],edx       	; set physical offset of obj 
        inc     word ptr [esi+numObj]  		; increment number of objects 
        jmp     after_apop 
         
go_append: 
        popad 
after_apop:      
        mov     objptr,eax                              ; objptr->last obj        
found_hole: 
        mov     edi,objptr                              ; objptr->obj /w hole 
 
	cmp 	holeptr,0 
	jnz     go_pe_hdr_hole 
	 
        push    edi                                                                   
        push    offset obj_txt                          ; strcat object name  
        call    lstrcat                         ; for display                 
                                                                                  
        mov     eax,[edi+objpoff]                       ; get object physical off 
        mov     lastobjimageoff,eax                     ; save it                 
        mov     ecx,[edi+objpsize]                      ; get object physical size    
        mov     originalpsize,ecx                       ; save it 4 later         
                                                                                  
        mov     eax,[edi+objvsize]                      ; get object virtual size 
        mov     originalvsize,eax                       ; save it                     
        cmp     use_hole,1                                                        
        jz      psize_less_vsize                                                  
        cmp     eax,ecx                                                           
        jge     psize_less_vsize                        ; padded space for alignment? 
        mov     eax,ecx                                 ; set vsize to psize      
psize_less_vsize: 
        add 	eax,VIRTUAL_SIZE                        ; add our virtual size 
        mov 	dword ptr [edi+objvsize],eax            ; save new virtual size 
         
        cmp     use_hole,1                              ; if using hole then add virtual size 
        jz      in_hole_no_psize                                                          
        mov     eax,originalpsize                       ; get physical size of object                                                
        add     eax,DECRYPTOR_SIZE                      ; adjust physical size of object  
        mov     ecx,[esi+filealign]                                                       
        call    align_fix                               ; on file alignment               
        mov     [edi+objpsize],eax                                                                
        ; now we must CORRECTLY calculate the new image size. This was the 
        ; bug under winNT appendation.     
        mov     ecx,dword ptr [esi+objalign]            ; get object alignment 
        mov     eax,dword ptr [edi+objvsize]            ; add virtual size 
        add     eax,dword ptr [edi+objrva]              ; +last object rva 
        call    align_fix                              ; set on obj alignment 
        mov     dword ptr [esi+imagesize],eax           ; save new imagesize   
             
         
        mov     eax,originalpsize 
        jmp     not_in_hole_psize_entry 
in_hole_no_psize:     
     
        mov     eax,originalvsize 
not_in_hole_psize_entry: 
 
        mov     [edi+objflags],0E0000060h               ; set object flags r/w/x/init data 
        add     eax,[edi+objrva]                        ; add last object's RVA      
                                	                ; eax now RVA of decryptor code 
	jmp     new_entry 
go_pe_hdr_hole: 
	mov     eax,holeptr 
	sub     eax,map_ptr 
new_entry:     
        mov     ebx,[esi+entrypointRVA]                  ; get original entry          
        mov     [esi+entrypointRVA],eax                  ; put our RVA as entry        
        mov     newep,eax                                ; save it for decryptor too 
                                                                                               
        mov     [host_eip],ebx                           ; save it                     
         
        push    esi 
         
        ; CLOSED SOURCE 
                 
        mov     edi,map_ptr 
        cmp     holeptr,0 
        jz      not_hdr_hole 
        mov     edi,holeptr 
        jmp     copy_to_hdr 
not_hdr_hole:         
        cmp     use_hole,1                               ; if in hole then install at end of vsize 
        jz      endvsize 
        add     edi,originalpsize                        ; add original physical size 
        jmp     go_copy 
endvsize:         
        add     edi,originalvsize                        ; add original virtual size 
go_copy:     
        add     edi,lastobjimageoff                      ; add object physical offset   
copy_to_hdr:         
        lea     esi,decryptor_code                       ; esi->decryptor code          
        mov     ecx,DECRYPTOR_SIZE                                                      
        rep     movsb                                                                   
                                                                                        
        pop     esi                                     ; restore ptr pe hdr                
                                                                                        
        cmp     use_hole,1                               ; did we find hole to install in?  
        jnz     go_pad_fixup_size                        ; if no then we better pad 
        mov     ecx,fsize                                ; else new filesize=old filesize   
        jmp     go_fixup_size                                                           
         
go_pad_fixup_size:             
        mov     ecx,[esi+filealign]                     ; calculate amt                          
        sub     ecx,DECRYPTOR_SIZE                       ; of padding needed                     
        xor     eax,eax                                                                      
        rep     stosb                                    ; pad up object to alignment        
                                                                                         
        mov     eax,map_ptr                              ; eax->beginning of mapped file         
        sub     edi,eax                                  ; get difference from current ptr       
        mov     ecx,edi                                  ; save file size                
go_fixup_size:     
        push    ecx                                     ; ecx=real file size              
                                                                                          
        call    unmap                                   ; unmap file                      
                                                                                          
        pop     ecx                                                                       
        push    FILE_BEGIN                              ; from file begin                 
        push    0                                       ; distance high                   
        push    ecx                                     ; distance low                    
        push    handle                                                                    
        call    SetFilePointer                           ; move file pointer to        
                                                 ; real EOF                            
        push    handle                                                                    
        call    SetEndOfFile                             ; set end of file             
go_checksum: 
; 
; now we need to calculate checksum. We need to remap the file to get it 
; right after file size change. I might be wrong about this, there could 
; have been a bug in my code, but it seems resonable. 
; 
        xor     ecx,ecx 
        call    create_mapping 
        jc      unmapped 
        call    GetPEHeader 
        lea     eax,[esi+checksum] 
        push    eax                                   ; destination of checksum in hdr 
        push    offset oldchksum 
        push    fsize                                 ; new file size 
        mov     eax,map_ptr 
        push    eax 
        call    CheckSumMappedFile 
        call    unmap 
         
        mov     error,0                                ; if we made it here then no error 
        jmp     unmapped                                 
abort_encrypt: 
        call    unmap                                  ;unmap if aborted infection 
unmapped: 
 
        push    offset creation                                               
        push    offset lastaccess                                             
        push    offset lastwrite                                              
        push    handle                                                        
        call    SetFileTime                    ; restore orginal file time 
                                                                              
        push    handle                                                        
        call    CloseHandle                                                   
         
        mov     eax,oldattrib                          ; get original attribs  
        push    eax  
        mov     eax,fnameptr 
        push    eax                     
        call    SetFileAttributesA                    ; restore the original attributes 
         
        ret                                  
EncryptFile endp 
; 
; CLOSED SOURCE 
; 
test_obj proc     
        cmp     dword ptr [eax+objpoff],0       ; make sure physical offset isn't 0 
        jz      ret_stc  
        cmp     dword ptr [eax+objpsize],0      ; make sure physical size isn't 0 
        jz      ret_stc 
	call    test_rvas 
	jc      ret_stc	 
        lea     esi,bad_otbl                     ; scan thru bad obj     
bobj_loop:                                       ; table 
        xchg    eax,ebx 
        lodsd 
        xchg    eax,ebx 
        cmp     ebx,[eax] 
        jz      ret_stc                                                          
        or      ebx,ebx 
        jnz     bobj_loop 
        clc 
        ret 
ret_stc: 
        stc     
        ret 
test_obj endp     
 
test_rvas proc 
        pushad 
        mov     ecx,2         
        lea     esi,importtbl         
rva_loop:         
	mov     edx,dword ptr [esi]         
        mov     ebx,dword ptr [eax+objrva]         
        cmp     ebx,edx 
        jg      not_bad 
        jz      ret_stc2 
        mov     ebx,dword ptr [eax+40+objrva] 
        or      ebx,ebx 
        jz	ret_stc 
        cmp     ebx,edx 
        jg      ret_stc2 
not_bad:         
        add     esi,4 
	loop    rva_loop 
	popad 
        clc 
        ret 
ret_stc2: 
	popad 
	stc 
	ret                 
endp 
 
 
GetPEHeader proc 
        mov     esi,[eax+3Ch]                        ; where PE hdr pointer is  
        add     esi,eax                                                         
        mov     ptrpeheader,esi                      ; esi->PE Hdr              
        ret 
GetPEHeader endp 
 
; create_mapping - create file mapping of [handle] 
; entry: ecx=+adjust mapping size 
; 
create_mapping proc 
        push    ecx                                ; save additional mapping size   
        push    0                                  ; high fsize storage, not needed 
        push    handle                             ; file handle                    
        call    GetFileSize                                                            
        call    test_error                                                             
        jc      create_abort                                                           
        mov     fsize,eax                                                              
         
        pop     ecx                     ; restore map size 
         
        push    0              ; no map name 
        add     eax,ecx 
        push    eax            ; low size+vs   
        push    0              ; high size    
        push    PAGE_READWRITE ; read&write   
        push    0                             
        push    handle                        
        call    CreateFileMappingA            
        call    test_error                    
        jc      create_abort 
        mov     maphandle,eax 
         
        push    0               ; # of bytes, 0= map entire file 
        push    0               ; file offset low 
        push    0               ; file offset high              
        push    FILE_MAP_WRITE  ; access flags - read&write        
        push    eax             ; handle                           
        call    MapViewOfFile                                      
        call    test_error                                         
        jc      create_abort 
        mov     map_ptr,eax 
 
create_abort: 
        ret 
create_mapping endp 
 
 
; test_error - test API for an error return 
;  entry: eax=API return 
;  returns: carry if error 
; 
test_error proc 
        cmp     eax,-1  
        jz      api_err 
        or      eax,eax 
        jz      api_err 
        clc 
        ret 
api_err: 
        stc 
        ret 
test_error endp 
 
; unmap file - Unmap view of file 
;  
unmap proc 
   
        push    map_ptr           
        call    UnmapViewOfFile   
        push    maphandle         
        call    CloseHandle       
        ret 
 
unmap endp 
 
; sets eax on alignment of ecx 
; 
align_fix proc   
        xor     edx,edx                                                                     
        div     ecx                               ; /alignment                                   
        or      edx,edx				  ; if no remainder then no next 
        jz      no_adjust 
        inc     eax                               ; next alignment                                 
no_adjust:         
        mul     ecx                               ; *alignment                              
        ret 
align_fix endp      
 
OpenFile proc 
        push    0                                                 
        push    20h                          ; attribute normal   
        push    3                          ; 3=open existing file 
        push    0                                                 
        push    0                                                 
        push    0c0000000h                 ; permissions          
        push    esi                                               
        call    CreateFileA                                       
        ret 
OpenFile endp 
 
ifdef console_app 
GetSHandle proc 
        push    -11 
        call    GetStdHandle 
        mov     [hstdo],eax              
        push    -10 
        call    GetStdHandle 
        mov     [hstdi],eax 
        ret 
GetSHandle endp 
 
WriteString proc 
        pushad 
        mov     edi,ebx 
        xor     eax,eax  
        mov     ecx,0fffh 
        cld 
sc_loop:         
        scasb                                ; find end of string 
        jz      fnd 
        loop sc_loop 
fnd:     
        mov     ecx,edi               
        sub     ecx,ebx 
        push    0 
        push    offset byteswrote 
        push    ecx      
        push    ebx 
        push    [hstdo] 
        call    WriteConsoleA 
        popad 
        ret 
WriteString endp 
 
 
GetYN proc       
        pushad 
        lea edi,ynbuf 
        xor eax,eax 
        stosb 
        dec edi 
        push 0 
        push offset byteswrote 
        push 1 
        push edi 
        push [hstdi] 
        call ReadConsoleA 
        popad 
        cmp ynbuf,'y' 
        jz exit_y 
        cmp ynbuf,'Y' 
        jz exit_y 
        stc 
        ret 
exit_y: 
        clc 
        ret              
GetYN endp 
endif 
 
 
 
end start 
ends