vulscan部分的目录结构如下:
vulscan里面包含的是扫描插件,有两种类型一是python脚本型插件,一是json文件型插件;
vulscan代码分析
1、程序开头
sys.path.append(sys.path[0] + '/vuldb')
sys.path.append(sys.path[0] + "/../")
将 vuldb 目录和上级目录加入系统路径中;
2、找到程序入口
if __name__ == '__main__':
# 插件初始化加载
init()
init() 函数首先进行插件初始化加载,如果发现数据库中已经存储有插件数据,就不继续执行了。
file_list = os.listdir(sys.path[0] + '/vuldb')
for filename in file_list:
try:
if filename.split('.')[1] == 'py':
script_plugin.append(filename.split('.')[0])
if filename.split('.')[1] == 'json':
json_plugin.append(filename)
except:
pass
插件信息如果没有存储到数据库中,用 os.listdir() 函数列出插件目录下的文件, 按文件名后缀对两种类型插件分类。
os.listdir() 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表。
语法:os.listdir(path)
for plugin_name in script_plugin:
try:
res_tmp = __import__(plugin_name)
plugin_info = res_tmp.get_plugin_info()
plugin_info['add_time'] = time_
plugin_info['filename'] = plugin_name
plugin_info['count'] = 0
na_plugin.insert(plugin_info)
except:
pass
对于 python 脚本插件,用 import (动态导入),然后统一调用插件中的 get_plugin_info() 方法,将插件详细的描述信息存入数据库;
for plugin_name in json_plugin:
try:
json_text = open(sys.path[0] + '/vuldb/' + plugin_name, 'r').read()
plugin_info = json.loads(json_text)
plugin_info['add_time'] = time_
plugin_info['filename'] = plugin_name
plugin_info['count'] = 0
# 删除关于检测部分的漏洞,然后也是只将描述信息存入数据库
del plugin_info['plugin']
na_plugin.insert(plugin_info)
except:
pass
对 json 文件型插件,用 json.loads() 函数加载文件内容;
3、初始化插件之后
将密码字典、运行线程数、超时时间、ip地址白名单从数据库中取出;
PASSWORD_DIC, THREAD_COUNT, TIMEOUT, WHITE_LIST = get_config()
接着开启了一个监控线程--------监控是否加载任务,并及时更新密码字典、运行线程数、超时时间、ip 地址白名单;
python thread.start_new_thread(monitor, ())
def monitor():
global PASSWORD_DIC, THREAD_COUNT, TIMEOUT, WHITE_LIST
while True:
queue_count = na_task.find({"status": 0, "plan": 0}).count()
if queue_count:
load = 1
else:
ac_count = thread._count()
load = float(ac_count - 6) / THREAD_COUNT
if load > 1:
load = 1
if load < 0:
load = 0
na_heart.update({"name": "load"}, {
"$set": {"value": load, "up_time": datetime.datetime.now()}})
这里设置load值,表示当前有无插件被调用(1正被调用,0没有调用)。
4、while True语句
while True:
# 取出计划任务信息
try:
task_id, task_plan, task_target, task_plugin = queue_get()
# 如过没有任务,sleep后,回到上一行代码
if task_id == '':
time.sleep(10)
continue # 否则进入下面的流程,准备扫描漏洞
if PLUGIN_DB:
del sys.modules[PLUGIN_DB.keys()[0]]
清理插件缓存,sys.modules.key()储存了已经加载的模块,在调用是获得其中的缓存,并没有重新导入;
PLUGIN_DB.keys()[0]
sys.modules是一个全局字典,该字典是python启动后就加载在内存中。每当程序员导入新的模块,sys.modules都将记录这些模块。字典sys.modules对于加载模块起到了缓冲的作用。当某个模块第一次导入,字典sys.modules将自动记录该模块。当第二次再导入该模块时,python会直接到字典中查找,从而加快了程序运行的速度。
5、接下来开始扫描部分
for task_netloc in task_target:
while True:
if int(thread._count()) < THREAD_COUNT:
# 跳过白名单ip
if task_netloc[0] in WHITE_LIST:
break
try:
thread.start_new_thread(
vulscan, (task_id, task_netloc, task_plugin))
except Exception as e:
print e
break
遍历目标,一个目标开一个线程,但是只有当前运行的总线程数(thread._count())小于设置的总线程数(THREAD_COUNT)时,才会继续开新的线程,避免目标过多,开的线程太多卡死;
if int(thread._count()) < THREAD_COUNT:
然后检测了ip地址是否为白名单中的地址,如果不是才会继续进行下去;将任务id、ip地址和端口号、使用的插件传入VulScan进行正式扫描。
if task_netloc[0] in WHITE_LIST:
break
try:
thread.start_new_thread(
vulscan, (task_id, task_netloc, task_plugin))
except Exception as e:
print e
break
else:
time.sleep(2)
6、然后看类vulscan下面定义的每一个函数的功能:
class vulscan():
# 数据初始化
def __init__(self, task_id, task_netloc, task_plugin):...
# 扫描流程
def start(self):...
# 根据插件名查询插件信息
def get_plugin_info(self):...
# 读取json插件信息
def load_json_plugin(self):...
# 数据结构转换为请求对象
def set_request(self):...
# 获取网站页面编码方式
def get_code(self, header, html):...
# json 文件型插件的漏洞检测函数 poc_check()
def poc_check(self):...
#保存结果到数据库
def save_request(self):...
#控制台信息输出
def log(self, info):...
然后对每个函数具体分析。