💾 Archived View for spam.works › mirrors › textfiles › virus › datut008.txt captured on 2023-06-16 at 21:02:08.
-=-=-=-=-=-=-
????????????????????? EXE Self-Disinfection ????????????????????? By Dark Angel Phalcon/Skism ????????????????????? In the last issue of 40Hex, Demogorgon presented an article on self- disinfecting COM files. COM file disinfection is simplistic and very straightforward. In this article, we shall deal with the somewhat more complex topic of EXE file self-disinfection. You should already be familiar with the EXE file header and how each of the fields work. A brief summary follows (a fuller treatment may be found in 40Hex-8.007): Offset Description 00 'MZ' or 'ZM' EXE signature word 02 Bytes in last page of the image 04 Number of pages in the file 06 Number of relocation items 08 Size of the header in paragraphs 0A Minimum memory required in paragraphs 0C Maximum memory requested in paragraphs 0E Initial SS, offset from header in paragraphs 10 Initial SP 12 Negative checksum (ignored) 14 Initial IP 16 Initial CS, offset from header in paragraphs 18 Offset of relocation table from start of file 1A Overlay number (ignored) There are several methods which allow a virus to infect an EXE file. The most common method involves the virus twiddling with the entry point of the program to point to the virus. Another involves the virus altering the code at the original entry point to jmp to its own code. A further method involves the virus simply overwriting the code at the entry point and storing the original code somewhere else, possibly at the end of the file. A final method involves altering the structure of the EXE file so it is instead recognised as a COM file. The ideal self-check routine should be able to handle all these cases. Part 1 - Detection ~~~~~~~~~~~~~~~~~~ The strategy for detection is simple; one simply needs to store a copy of the original header and the first few bytes located at the entry code. When the program executes, simply check these bytes to those found in the copy of the program located on the disk. If they differ, then there is clearly something amiss. This is essentially the same as the process for COM self- checking, but an extra layer of complexity is added since the header is not loaded into memory at startup. This minor difficulty may be readily overcome by simply physically storing the header at some point in the program. Since the header is not known before assembling the file, it is necessary to patch the header into the file after assembly. This may be done rather easily with a simple utility called 40patch. It will insert the header and the first 20h (32d) bytes at the entry point of an EXE file at the first occurence of the string 'Dark Angel eats goat cheese.' in the program. This string is exactly the length of the header, so be sure to allocate an additional 20h bytes after the string for the entry point code. A sample self-checking program follows: ----EXE Self-Check Program 1 begin---- .model small .radix 16 .code ; Self-Checking EXE 1 ; Written by Dark Angel of Phalcon/Skism ; For 40Hex #13 ; To assemble: (tested with TASM 2.0) ; tasm <filename> ; tlink <filename> entry_point: mov ah,51 ; Get current PSP to BX int 21 mov ds,bx mov bx,ds:2c ; Search the environment for mov es,bx ; our own filename. Note that mov di,1 ; this only works in DOS 3+. xor ax,ax dec di ; It also won't work if the scasw ; environment has been jnz $ - 2 ; released. xchg dx,di inc dx inc dx push es ; filename to ds:dx pop ds mov ax,3d02 ; unless this handler is int 21 ; tunneled, a virus may xchg ax,bx ; infect it mov ax,_DATA mov ds,ax ; restore DS and ES mov es,ax jc error mov cx,1c ; check the header for mov si,offset header ; corruption call read_buffer jc close_error mov ax,4200 ; go to the entry point xor cx,cx mov dx,word ptr [header+8] add dx,word ptr [header+16] rept 4 shl dx,1 adc cx,0 endm add dx,word ptr [header+14] ; add this to the entry point adc cx,0 ; offset from header int 21 jc close_error mov cx,20 ; now check the first 32 bytes mov si,offset first20 ; for corruption call read_buffer jc close_error close_error: pushf mov ah,3e ; close the file int 21 popf jc error mov dx,offset good ; In an actual program, replace ; this line with a JMP to the jmp short $+5 ; program entry point error: mov dx,offset bad mov ah,9 int 21 mov ax,4c00 int 21 read_buffer: mov ah,3f mov dx,offset readbuffer int 21 jc error_read clc cmp ax,cx jnz error_read xchg dx,di rep cmpsb clc jz $+3 error_read: stc ret .data good db 'Self-check passed with flying colours.',0Dh,0A,'