> 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/2021/2021-qiang-wang-bei/pop_master.md).

# pop\_master

构造POP链的题目，主要核心点：

* 每个class和function名都是唯一的，虽然有9999个类，但是调用链在选定调用的function后只有一种class对应。
* 大部分的方法只有一种调用链，只有用了`method_exists`会有分叉。
* POP链构造：深度优先搜索，沿着每个方法走下去，直到遇到eval函数命令执行。
* POP链剪枝：POP链中，如果传入的参数被替换（注意不是拼接，拼接可以通过注释来绕过），是不可以执行命令的，具体用正则表示就是含有`=`但不含有`.`。

虽然写正则很搞人心态，但是题目整体的思路很清晰，直接撸脚本就可以了（写的正则很垃圾，随便看看就好）。

```php
import os
import requests
import re
classPop = []
funcPop = []
array = []

def deleteIfAndFor(f):
    text = f.read()
    s = re.findall("(if\((\d+)>(\d+)\){([\w\W]+?)})", text)
    for i in s:
        if int(i[1]) < int(i[2]):
            text = text.replace(i[0], "")
        else:
            text = text.replace(i[0], i[3].strip())
    s = re.findall("(for\(\$i = 0; \$i < (\d+); \$i \+\+\){([\w\W]+?)})", text)
    for i in s:
        if int(i[1]) == 0:
            text = text.replace(i[0], "")
        else:
            text = text.replace(i[0], i[2].strip())
    with open("result.txt", "w") as g:
        g.write(text)

def search(key):
    # func 入栈
    funcPop.append(key)
    for i in array:
        if i.find("function " + key) != -1:
            # class入栈
            classPop.append(re.findall(r'class\s([a-zA-Z0-9_]{6})', i)[0])
            tmp = fr'public\sfunction\s{key}' + '\(\$[a-zA-Z0-9]{5}\)\{[\w\W]*?\}\n'
            # 提取调用方法
            func = re.findall(tmp, i)
            # 进行过滤，如果传入的参数被顶掉，直接返回
            tmp2 = fr'public\sfunction\s{key}' + '\(\$([a-zA-Z0-9]{5})\)\{[\w\W]*?\}\n'
            e = re.findall(tmp2, i)
            tmp3 = fr'{e[0]}\s*?=\s*?'
            if (re.findall(tmp3, func[0]).__len__() > 0) and (func[0].find(".") == -1):
                classPop.pop()
                return
            # 检测是否存在eval，如果存在则打印classPop
            if func[0].find('eval') != -1:
                print(classPop)
            # 提取调用链
            nextFunc = re.findall(r'\$this->[a-zA-Z0-9]{7}->([a-zA-Z0-9]{6})\(\$[a-zA-Z0-9]{5}\);', func[0])
            # 遍历所有func
            for j in nextFunc:
                search(j)
                # func 出栈
                funcPop.pop()
            # class 出栈
            classPop.pop()

if __name__ == "__main__":
    # f = open("./class.php", "r+")
    # deleteIfAndFor(f)
    # f.close()
    f = open("./result.txt", "r+")
    content = f.read()
    array = re.findall(r'class\s[a-zA-Z0-9_]+{[\w\W]*?}\n\n', content)
    search("lgeDXz")
```

跑出来的所有POP链都是可以用的，最后直接拿flag就行。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://gitbook-88.gitbook.io/ctf-writeup/2021/2021-qiang-wang-bei/pop_master.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
