0%

Pocsuite3 Source Analysis

分析版本:pocsuite3-1.9.6

pip直接安装会附带两个可执行文件,pocsuite 对应CLI方式启动,poc-console 对应msf类型的console方式启动

可以从setup.py 和可执行文件源码中发现其实就是运行对应的python文件的方法

image

分析CLI模式,大概流程非常简单清晰,检查环境->初始化配置->start开始扫描任务

image

初始化配置

检查环境这个其实就是判断下是否安装在非全英文目录

pocsuite 模仿sqlmap 使用了AttribDict 来存储配置,更改了配置字典的使用方法,方便配置和更改

1
2
3
4
5
6
7
This class defines the sqlmap object, inheriting from Python data
type dictionary.

>>> foo = AttribDict()
>>> foo.bar = 1
>>> foo.bar
1

原来的字典的用法:dict1["key"],现在的自定义字典的用法:dict1.key

配置文件在pocsuite3/lib/core/data.py

image

这里使用了模块实现了单例模式,Python 的模块就是天然的单例模式,因为模块在第一次导入时,会生成 .pyc 文件,当第二次导入时,就会直接加载 .pyc 文件,而不会再次执行模块代码。因此,我们只需把相关的函数和数据定义在一个模块中,就可以获得一个单例对象了

set_paths(root_path) 设置路径信息

image

通过argparse 解析参数,AttribDict 传递配置

image

这里的配置在其注释里描述的已经很清晰,conf 存储共享的配置和对象,kb 存储目标、注册的POC、扫描的模式、扫描结果等。cmd_line_options 存储原始的命令行配置,merged_options 对应覆盖后参数配置,paths 对应路径信息

自定义了一个输出函数,会根据quiet 的设置判断是否输出,同时做了字符编码、添加颜色的处理,输出使用的是sys.stdout.write 而不是print 这里查了一下print 会多输出一个\n ,这样输出的样式会更好控制一点

image

init() 里关键的_set_pocs_modulespocsuite3/lib/core/option.py

image

遍历pocs目录加载poc,并判断poc是否匹配条件,最后是调用load_file_to_module 去加载poc。这里可以看到之后pocsuite想要直接从pyc文件加载poc,同时这里有从seebug漏洞库加载poc的提示,但是只是提示,实际的实现逻辑并不是在这

image

pocsuite3能够从本地和远程网站上加载poc,可以直接用__import__()来加载,但是如果要远程加载,需要自己实现”查找器”与”加载器”,可以参考

https://docs.python.org/zh-cn/3/reference/import.html

这里加载了名为pocs_xxx 的模块

image

加载的过程,obj 即对应poc文件的源代码,每个poc文件最后都执行register_poc(xxx) ,这里其实就是实例化poc模块,然后放在kb.registered_pocs

image

image

远程加载的逻辑以poc_from_seebug.py 插件为例从seebug漏洞库加载poc的逻辑大概即获取到poc的源代码后通过load_string_to_module 加载

image

image

开始扫描

遍历target和注册的poc存入task队列

image

这里多线程使用生产者/消费者模型,多个线程来消费一个队列,并没有使用Python线程中推荐的join()来阻塞线程,因为使用join()的话,python将无法响应用户输入的消息了,会导致Ctrl+C退出时没有任何响应,所以以while循环的方式来阻塞线程

image

image

taskrun** 函数里最终会调用poc模块父类POCBaseexecute 方法,execute 调用**_execute

image

最后即调用到poc里对应的方法

image

最后output 是一个AttribDict ,存于kb.results

image

参考链接