|| Author: SPTH/rRlf || Back to articles ||

	  *************************************************************
	  *************************************************************
	  ************                                      ***********
	  ************         Hashes for Encryption        ***********
	  ************     by Second Part To Hell/[rRlf]    ***********
	  ************                                      ***********
	  *************************************************************
	  *************************************************************


  Index:
  ******

  0) Intro Words

  1) The Idea

  2) The Practice
     a) Simple MD5 encryption
     b) Multible-byte MD5 encryption
     c) Multibe-byte MD5/SHA1 encryption
     d) The final attempt

  3) Outro Words







  0) Intro Words

     A hash function  (or hash algorithm)  is a way of creating a small digital
     "fingerprint"  from any kind of data.  You can neighter  find the original
     fingerprinted  string  nor  create a  new  string  with the  same checksum
     (without a great effort). Beside of rainbow-lists,  bruteforce is the only
     way to find out what the  checksum stands for.  Bruteforce uses more time,
     the longer the  fingerprinted data is.  If hash functions  will be used in
     viruses for encryption, antivirus programms would have to use a bruteforce
     attack to find the real virus code.  As bruteforce requires much time, and
     less  scanning time is essential for  antivirus-programs,  hash-encryption
     might be a useful weapon against antivirus programs.





  1) The Idea

     A typical  cryptographic  one-way function,  such as  MD5 or SHA1,  is not
     one-to-one and makes an effective hash function.  How can this be used for
     encryption?  I wrote bruteforce  requires more time  the longer the string
     is. Now imagine: Create checksums of 1-3 bytes of your virus. Then write a
     bruteforce function  which finds the real content,  combine the content to
     the  full code  and execute it.  This  bruteforce search  should need some
     seconds for finding the real content, because emulators will also need the
     same time -  and the longer an emulator will use,  the worse it is for the
     antivirus program.  Imagine an antivirus program that need 15 - 30 seconds
     for scanning one file - whereas the time is no problem for the virus.





  2) The Practice

     In my examples I've used PHP, because it has an existing MD5/SHA1 function
     so  it is easy to understand  the examples.  When I've thought  about this
     technique I've thought about real binary viruses (assembler would be good,
     as you can write very fast bruteforce engines with it).

     a) Simple MD5 encryption

        In this example  I show you how to primitively use this technique.  The
        code  simple uses a  bruteforce  function  to find  the strings  of the
        checksums  and prints it to the browser.  The checksums are  always one
        single byte, encrypted with MD5;  which means that bruteforce will only
        need 2^8 trials per each checksum.

 - - - - - - - - - - - - - [ Simple MD5 encryption ] - - - - - - - - - - - - -
<?php
$code=array('c1d9f50f86825a1a2302ec2449c17196',  // H
            'e1671797c52e15f763380b45e841ec32',  // e
            '2db95e8e1a9267b7a1188556b2013b33',  // l
            '2db95e8e1a9267b7a1188556b2013b33',  // l
            'd95679752134a2d9eb61dbd7b91c4bcc',  // o
            '7215ee9c7d9dc229d2921a40e899ec5f',  // <space>
            '5206560a306a2e085a437fd258eb57ce',  // V
            '02129bb861061d1a052c592e2dc6b383',  // X
            'e1671797c52e15f763380b45e841ec32',  // e
            '4b43b0aee35624cd95b910189b3dc231',  // r
            '03c7c0ace395d80182db07ae2c30f034',  // s
            '9033e0e305f247c0c3c80d0c7848c8b3'); // !
$i=0; $j=0; $z='';
while ($code[$j])
{
  do
  {
    $i++;
  } while (md5(chr($i))!=$code[$j]);
  $z.=chr($i);
  $j++;
}
echo $z;
?>
 - - - - - - - - - - - - - [ Simple MD5 encryption ] - - - - - - - - - - - - -




     b) Multible-byte MD5 encryption

        This improved version  can handle an  unlimited number of  bytes (well,
        limited by time  -  the checksums are 1 or 2 bytes,  because more needs
        too much time for the  slow PHP interpreter and 30  seconds limit of my
        webserver).  It uses MD5 again.  At this example, the bruteforce engine
        needs 2^16 trials to find the correct string.  You could increase it to
        2^24 (3 bytes)  or even 2^32 if you have a damn fast webserver and much
        time, but I think 2^24 is realistic.

 - - - - - - - - - - - [ Multible-byte MD5 encryption ] - - - - - - - - - - - -
<?php
$code=array('a64cf5823262686e1a28b2245be34ce0',  // He
            '5b54c0a045f179bcbbbc9abcb8b5cd4c',  // ll
            'd95679752134a2d9eb61dbd7b91c4bcc',  // o
            '380f40674dcc13ab964f970e5c5750bb',  // <space>V
            '02129bb861061d1a052c592e2dc6b383',  // X
            '818f9c45cfa30eeff277ef38bcbe9910',  // er
            '530490af3588a14fb123af08e8bf4b95'); // s!
$j=0; $z='';
while ($code[$j])
{
  $k=''; $i=0; $r=1;
  do
  {
    while(++$i>255)
    {
      if ($k=='')
      {
        $k=chr(0); $i=0;
      }
      elseif (ord($k{strlen($k)-$r})==255)
      {
        $k{strlen($k)-$r}=chr(0);
        if (strlen($k)-$r) { $r++; }
        else { $k=chr(0).$k; $i=0; }
      }
      else
      {
        $k{strlen($k)-$r}=chr(ord($k{strlen($k)-$r})+1);
        $i=0;
      }
    }
  } while (md5($k.chr($i))!=$code[$j]);
  $z.=$k.chr($i);
  $j++;
}
echo $z;
?>
 - - - - - - - - - - - [ Multible-byte MD5 encryption ] - - - - - - - - - - - -




     c) Multibe-byte MD5/SHA1 encryption

        The  next improvement  is to add another  checksum,  which  doubles the
        amount of trials needed  for finding the encrypt string.  There is just
        one line that has changed - the while-condition. There is a significant
        difference  between MD5 and SHA1:  MD5 builds 32-byte  checksums,  SHA1
        creates 40-byte checksums.To not manifest which hash algorithm has been
        used,the checksum has to be reduced to 32 byte.  This is no problem for
        the bruteforce,  as it can compare the  reduced 32 byte.  An bruteforce
        emulator needs about 2^17 trials per checksum now to decrypt it.

 - - - - - - - - - - [ Multibe-byte MD5/SHA1 encryption ] - - - - - - - - - - -
<?php
$code=array('a64cf5823262686e1a28b2245be34ce0',  // 'He' MD5
            '110c8a30c16070bf2813480d9492a1a1',  // 'll' SHA1
            'd95679752134a2d9eb61dbd7b91c4bcc',  // 'o'  MD5
            '4a980110005e2e6de062cd0dfd73db7e',  // ' V' SHA1
            'c032adc1ff629c9b66f22749ad667e6b',  // 'X'  SHA1
            '818f9c45cfa30eeff277ef38bcbe9910',  // 'er' MD5
            '6393a74e8dceffcbc8e77e7a54e1b813'); // 's!' SHA1
$j=0; $z='';
while ($code[$j])
{
  $k=''; $i=0; $r=1;
  do
  {
    while(++$i>255)
    {
      if ($k=='')
      {
        $k=chr(0); $i=0;
      }
      elseif (ord($k{strlen($k)-$r})==255)
      {
        $k{strlen($k)-$r}=chr(0);
        if (strlen($k)-$r) { $r++; }
        else { $k=chr(0).$k; $i=0; }
      }
      else
      {
        $k{strlen($k)-$r}=chr(ord($k{strlen($k)-$r})+1);
        $i=0;
      }
    }
  } while (md5($k.chr($i))!=$code[$j] && substr(sha1($k.chr($i)),0,32)!=$code[$j]);
  $z.=$k.chr($i);
  $j++;
}
echo $z;
?>
 - - - - - - - - - - [ Multibe-byte MD5/SHA1 encryption ] - - - - - - - - - - -




     d) The final attempt

        As we know  that the checksum  does not contain  more that two or three
        bytes,  we could also  include garbage  into the checksums.  We have to
        include a counter to the bruteforce function, and count all trials.  If
        the counter reaches a point where no code has been found, it stopps the
        searching,  and  continues  with the  next checksum.  Furthermore  I've
        included a function which  creates new checksums and  writes it  to the
        browser.  The encryption function takes one or two bytes of the string,
        creates MD5 or SHA1 checksums  and randomly includes garbage checksums.
        In a real malware,  which uses that technique,  the encryption function
        is inside the encrypted code - of course -  together with the spreading
        routines.

 - - - - - - - - - - - - - - [ The final attempt ] - - - - - - - - - - - - - -
<?php
$code=array('a64cf5823262686e1a28b2245be34ce0',  // 'He' MD5
            '110c8a30c16070bf2813480d9492a1a1',  // 'll' SHA1
            'd95679752134a2d9eb61dbd7b91c4bcc',  // 'o'  MD5
            '62686dec2c331fbdc2e2e260b39f8ef6',  // GARBAGE
            '4a980110005e2e6de062cd0dfd73db7e',  // ' V' SHA1
            'c032adc1ff629c9b66f22749ad667e6b',  // 'X'  SHA1
            'a853cc79167c18e737532c32a3401b68',  // GARBAGE
            '818f9c45cfa30eeff277ef38bcbe9910',  // 'er' MD5
            '6393a74e8dceffcbc8e77e7a54e1b813'); // 's!' SHA1

$j=0; $z='';
while ($code[$j])
{
  $k=''; $i=0; $r=1; $c=0;
  do
  {
    while(++$i>255)
    {
      if ($k=='')
      {
        $k=chr(0); $i=0;
      }
      elseif (ord($k{strlen($k)-$r})==255)
      {
        $k{strlen($k)-$r}=chr(0);
        if (strlen($k)-$r) { $r++; }
        else { $k=chr(0).$k; $i=0; }
      }
      else
      {
        $k{strlen($k)-$r}=chr(ord($k{strlen($k)-$r})+1);
        $i=0;
      }
    }
  } while (md5($k.chr($i))!=$code[$j] && substr(sha1($k.chr($i)),0,32)!=$code[$j] && ++$c<65535);
  if ($c<65535) { $z.=$k.chr($i); }
  $j++;
}
echo $z.'<br><br>';
echo "Now let's see some other possible variants:<br>";
srand((double)microtime()*1000000);
$nz='';
while (strlen($z)>0)
{
  $t=0;
  $y=substr($z,0,rand(1,2));
  if (!rand(0,3)) { $nz=$nz.'<br>'.md5(chr(rand(0,255)).chr(rand(0,255)).chr(rand(0,255))); }
  if (strlen($z)==1) { $y.=$z{1}; }
  if (rand(0,1))
  {
    $nz=$nz.'<br>'.md5($y);
  }
  else
  {
    $nz=$nz.'<br>'.substr(sha1($y),0,32);
  }
  if (!rand(0,3)) { $nz=$nz.'<br>'.substr(sha1(chr(rand(0,255)).chr(rand(0,255)).chr(rand(0,255))),0,32); }
  $z=substr($z,strlen($y));
}
echo $nz;
?>
 - - - - - - - - - - - - - - [ The final attempt ] - - - - - - - - - - - - - -





  5) Outro words

     In my opinion,  emulators are not fast enough to detect a virus using hash
     encrypted malware. If the virus is static,of course, this technique is not
     very useful,  because the checksums  of all  possible  variants of the the
     first  n bytes can  be used as  scan-string;  but if the  virusbody morphs
     itself a little bit,  this  technique could  make antivirus  researchers a
     very hard life.  I want to  mention again,  that I think this idea is very
     useful for assembler-viruses, because assembler is very fast, and they are
     binary (255 possibilities per byte, not just [A-Z&&a-z&&0-9].

     Thanks for reading - I'm checking out now - Over!



                                                  - - - - - - - - - - - - - - -
                                                    Second Part To Hell/[rRlf]  
                                                    www.spth.de.vu
                                                    spth@priest.com
                                                    written in September 2006

                                                    ...surrealistic viruswriter...
                                                  - - - - - - - - - - - - - - -