VGCrypt PE Encryptor v0.75 Beta Source

;
;**WARNING: Encryption and Decryption code closed to public for security (as if there
; were any<g>). Everything else is here tho.
;
;
;VGCrypt PE Encryptor v0.75 Beta
;(c)1998 Virogen
;email: vgen@hotmail.com
;www: http://virogen.cjb.net
;----------------------------------------------------------------
;
; 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<g>:
;       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
;   http://virogen.cjb.net.
;
;
; 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<g>.
;                   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<g>. 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,'http://virogen.cjb.net 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 vsize<psize
ifdef console_app
        lea     ebx,found_hole_obj
        call    WriteString
        mov     ebx,eax
        call    WriteString
endif  
no_hole_here:               
        push    offset cr_lf_tab
        push    offset eobj_txt
        call    lstrcat
        popad
        pushad
        push    eax
        push    offset eobj_txt
        call    lstrcat
        popad
               
        push    eax ecx
        mov     ebx,eax[objflags]                        ; get obj flags
        or      ebx,oflag_write                           ; OR in writable flag
        mov     eax[objflags],ebx                        ; save new object flags
        mov     ebx,eax[objrva]                          ; get the object's rva       
        mov     [edi],ebx                                ; save it
        mov     ecx,[edi+4]                              ; see if we set above
        or      ecx,ecx                                  ; if so then we are
        jnz     already_vsize                            ; gonna use vsize
        mov     ecx,eax[objpsize]                        ; get the object's physical size  
        mov     [edi+4],ecx              
already_vsize:                                                                         
ifdef console_app      
        lea     ebx,doing_obj_txt
        call    WriteString    
        mov     ebx,eax
        call    WriteString
endif  
        add     edi,8                                    ; increment to next table member      
        push    edi                                                                           
        mov     esi,eax[objpoff]                         ; esi->object 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.<g>
;
        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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值