Anti-Malware Research

Third Iteration of Linux Ransomware Still not Ready for Prime-Time

A new variant of the Linux Encoder ransomware is now targeting vulnerable servers worldwide. As of the moment of writing, more than 600 servers have been infected. The good news is that we still can decrypt the files held at ransom for free.

But let’s backtrack a few weeks.

Last November saw the emergence of an interesting piece of ransomware targeting vulnerable Linux web servers. Fortunately, a programming flaw allowed Bitdefender researchers to get hold of the decryption key and provide victims with a free recovery utility. Soon after the release of the decryption tool, we learnt about the existence of an even older version of the ransomware that allowed us to guess the symmetric AES key used for decryption.

As we expected, the creators of Linux.Encoder have fixed their previous “bugs” and have come up with a new and improved variant. Luckily for the victims, the new variant of Linux.Encoder is still vulnerable to key recovery attacks.

What went wrong this time?

The old version of the Linux.Encoder ransomware used to generate a 16-byte initialization vector and a 16-byte AES key by calling the rand() function. The initial seed to the RNG was taken from the current timestamp, which was actually very close to the modification time of the file after encryption.

In the current version of the Linux.Encoder ransomware, every file that goes through the encryption process is given the modification time of the original, unencrypted file. If a file generated in 2012 is encrypted now, it would still appear that it has been last modified in 2012, so we wouldn’t be able to look at the modification time and use it as a decryption key.

When we documented the flawed approach to generating IVs and keys in the previous versions, the Twitter community ridiculed the developers by suggesting wild improvements to the ransomware’s functionality.

Apparently, the operators actually took note of these sarcastic recommendations;  As a result, the IV is now generated from a hash of the file size and the filename – 32 bytes from rand() are hashed 8 times and used as the AES-256 key.

Moreover, the new Linux.Encoder now does not statically link the libc library such that older systems (which are more likely to be vulnerable and thus more susceptible to getting infected) are not compatible with the ransomware and will fail to even start the program.

However, the breaking flaw shipped with the Linux.Encoder ransomware resides in the way the attackers are hashing the random bytes to produce the AES-256 key. Apparently, they have completely forgotten to select a hashing algorithm, so the output of the hashing function is unchanged. This means that all calls to the Update and Finish primitives do not, in effect, do anything. As a result, the full AES key is now written to the encrypted file, which makes its recovery a walk in the park.

If you have been hit by the new version of this ransomware and would like to get your files back for free, head over to the download section, download and run the decryption utility provided by Bitdefender. While this is the third lucky strike, please make sure that, after recovery, you update the vulnerable platforms and stop this type of attack cold in the first place. Next time, hackers could actually come up with a working version of the ransomware that won’t be as easy to decrypt.

Download the decryption utility

This tool is based on research provided by Bitdefender crypto specialist Radu Caragea.

About the author



Bogdan Botezatu is living his second childhood at Bitdefender as director of threat research. When he is not documenting sophisticated strains of malware or planning removal tools, he teaches extreme sports such as surfing the web without protection or rodeo with wild Trojan horses. He believes that most things in life can be beat with strong heuristics and that antimalware research is like working for a secret agency: you need to stay focused at all times, but you get all the glory when you catch the bad guys.


Click here to post a comment
  • Hey Radu, it is gift to have a such a professional on the good side. The decryption tool works great! Many thanks!

    For others hit with this version, you can use this simple script to decrypt all your files.
    It should be run as superuser, as it attempts to chown the files back to the original USER/GROUP. It accepts one parameter that should be a file containing all the encrypted files

    You can get the file list simply by
    find / -name ‘*.encrypted’ > file.list

    the script itself


    # run this as superuser to avoid permission denied and be able to chown the files
    if [[ ! -f “./” ]] ; then
    echo “The encoder decrypter script does not exist on the current path”

    if [[ -f “$1” ]]; then

    for fillnm in `cat $1` ; do
    echo “Processing $fillnm”
    ./ $fillnm
    FILEOWNER=`stat -c “%U” $fillnm`
    FILEGROUP=`stat -c “%G” $fillnm`
    #shell builtin to save perf
    # attempt to restore user and group

    echo “First parameter must be file that contains all encrypted files you want to decrypt”

    #end of exec

  • still no work!
    apt-get install python
    Reading package lists… Done
    Building dependency tree
    Reading state information… Done
    python is already the newest version.
    0 upgraded, 0 newly installed, 0 to remove and 185 not upgraded.

    python -f /var/www/clients/client1/web21/web/configuration.php.encrypted
    Traceback (most recent call last):
    File “”, line 6, in
    f = open(input_name, “r”)
    IOError: [Errno 2] No such file or directory: ‘-f’

    • You don’t need “-f”. Just use “python /var/www/clients/client1/web21/web/configuration.php.encrypted”

  • I write you from Argentina. I was infected by Linux.Encoder.3. I use your great script and i get the seed. It works great, but i couldnt process the sorted_list it only works file by file (entering the name manually) what im doing wrong?

    • Hello! What seed? This decryption tool does not need any “preprocessing” like for linux.encoder.1 to get the seed. Just input any file as a command line parameter and it will be decrypted. Check the Python source for more details. If you want to decrypt all your files you need a shellscript like the one Radek wrote or whatever you consider.

  • I input the full path and filename, I can decryted the file, but I try to use script (by Radek), always show:-
    Processing /var/www/clients/client1/web21/web/plugins/search/index.html.encrypted line 10: ./ Permission denied

  • Ok! Thank for your answer, i dont undestand much of programing.
    I have generated a file with all the name of the infected files.

    Where i have to put it the radek script? Where is the first parameter? 7: [[: not found 24: [[: not found
    “First parameter must be file that contains all encrypted files you want to decrypt”

  • I have comented the line #if [[ -f “$1” ]]; then and it works for me. Thanks you very much. Mariano from Argentina.

  • still some error!
    root@server:/# python /decrypter/ ./home/web/web/configuration.php.encrypte
    This file doesn’t seem to be encrypted with Linux.Encoder.3
    root@server:/# python /decrypter/ -f ./home/web/web/configuration.php.encrypte
    [!] File is probably truncated
    [!] Seed not found! Timestamps corrupt?

  • Hi everyone!
    Great work Ladies and Gentleman, thank you for your effort. Since we are seeing rapid increase of cases with ransomware encrypted Joomla websites I have decided to translate your algorithm to PHP and make a script uploadable to the hosted website to batch-decrypt all the files. I hope you will like it.
    Webmasters mostly don’t have access to a full shell, and Python is also much more rare on the hosting accounts than PHP, which makes using your original great script much harder for webmasters…

    Here is a GitHub repo , be free to update your article to offer the link to all the hacked encrypted webmasters that are left desperate with ransom.

  • my joomla can decryted, but php, html and css files have additional code, may affect the normal.
    html: /J��”1����t$�E
    css:…o2k7SkinSilver .mceButtonDialog:before{background-color:#eee;border-color:#bbb;}���q#0���.aL0n
    js: ….};win.WFWindowPopup = WFWindowPopup;
    php: …?>�9�Ίs���_��

  • Hi everyone and thanks Radu,

    This py script works a treat but I am also having trouble cleaning up the leftover code. Has anyone worked out a bash script or something along those lines to find the additional bytes of code and remove them from the files.

    We are finding the code primarily in php, js, css and html files.

  • @Chang & @AUS-IP: I am waiting for further sample encrypted files to check how to fix this extra chars. If someone provides more samples maybe we might find a solution

  • There is no easy (automated) fix for the garbage characters. Otherwise, I would have integrated it in the decryption script. However, I can tell you this: either the file has 0 extra characters or exactly 16 extra characters.

    For php, css, html files it should be pretty easy to check that those bytes are in printable range and if not just truncate the last 16 bytes (with a command such as “truncate -s -16 filename”. but be careful not to remove data from files that don’t have the garbage bytes!!!)

    For binary files (zip, jpg, rar, png, etc) it is not trivial to detect them and it’s best to just leave them be as they don’t affect in any way opening of the files.

  • @Radu I have been manually removing them with VIM which is quite a tedious task. Any pointers on where I can find some information so that I can automate this from the console using console commands or a Bash script.

    • I would personally use something like this. But as I said, you need to be careful not to truncate valid data.


      for i in `cat $file_list`; do
      echo "Processing file $i. Here are the last 32 bytes. If the last 16 bytes look random then you should probably truncate them"
      xxd -s "-32" $i
      read -p $'Truncate this file? y/n\n' yn
      case $yn in
      [Yy]* ) echo "Truncating $i"; truncate -s -16 $i ;;
      * ) echo "Not truncating";;

  • This script as of 02/16/16 doesn’t work for us

    Running this:
    python /var/www/vhosts/domain/index.php.encrypted


    Done! Remember to check the decryption output before destroying the encrypted files and to adjust the permissions for the decrypted files
    Also, because of a bug in the encryption, the output files might contain 16 random bytes at the end.

    However, the file in question is not decrypted, even though it is renamed to index.php in this case.

    This means Linux.Encoder is emerged in some new – possibly x4 strain. BitDefender Team – please confirm that this is correct. And update your article or issue a new one. Looks like this time we are not lucky.

  • <strong>… [Trackback]</strong>

    […] Read More Infos here: […]