IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    w3af学习笔记(三)

    一根稻草发表于 2014-09-13 00:00:00
    love 0

    本文以menu切换,插件加载与启动为主线,分析w3af源代码中函数调用和各类之间的继承与组合关系,阅读之前请先有一个DFS(深度优先遍历)的准备。

    一、menu切换

    1.menu类继承关系

    • object
    • menu
    • rootMenu
    • pluginsMenu
    • pluginsTypeMenu
    • ConfigMenu
    • profilesMenu
    • bug_report_menu
    • kbMenu
    • exploit

    2.w3af>>plugins执行过程

    输入plugins+回车之后,指令从ConsoleUI类的sh()方法依次执行:

    self.onEnter()->self.execute()->self._context.execute()

    为了分析清楚类之间的关系,下文统一将self替换成类的名字,如果实例对象对分析过程有影响,会特别标出对象名字。

    sef._context,在sh()中初始化时是rootMenu类的实例,顾名思义,context是一个上下文,它会随着程序的执行而变化,具体的说它会随着w3af shell提示符的变化而变化,从回车之后,一步一步深入分析下去,过程如下。

    ConsoleUI.onEnter()->ConsoleUI.execute()->rootMenu.execute()

    2.1 rootMenu.execute()

    ConsoleUI._context就是类rootMenu的对象,rootMenu是menu类的子类,rootMenu没有重新定义execute方法,所以最后执行的是menu.execute('plugins')

    childrenmenu.get_children()#返回一个字典menu._children child = children['plugins']#返回一个类pluginsMenu对象,它在rootMenu对象创建时完成的创建 reutn child.execute([])#即pluginsMenu.execute([])

    由于参数为空,转向执行父类的execute函数,menu.execute([]),在该函数中,由于参数为空,终止递归,return self,此处也就是pluginsMenu对象。

    2.2 ConsoleUI._execute()

    返回上一层 ConsoleUI._execute(),接着执行:

    menu = pluginsMenu  #这是2.1返回的一个对象,menu在此是一个临时变量
    ConsoleUI._trace.append(ConsoleUI._context) #保存路径
    if menu is not None:
    self._context = menu  #完成上下文切换
    

    2.3 ConsoleUI._onEnter()

    再返回上一层ConsoleUI._execute(),接着执行:

    ConsoleUI._initPrompt()
    ConsoleUI._showPrompt()#重新显示shell提示符:w3af/plugins>>>
    

    3.w3af/plugins>>>back执行过程

    输入back+回车之后,指令从ConsoleUI类的sh()方法依次执行:

    ConsoleUI.onEnter()->ConsoleUI.execute()->pluginsMenu.execute()

    3.1 pluginsMenu.execute()

    目前ConsoleUI._context就是类pluginsMenu的对象,pluginsMenu是menu类的子类,由于back不是一个插件类型,所以最后执行的是menu.execute('back'),其执行过程如下:

    return pluginsMenu._cmd_back()
    return pluginsMenu._console.back()
    return ConsoleUI.back()
    return ConsoleUI._trace.pop()
    

    从第2节能够知道_trace在尾部append的是rootMenu对象,所以此处弹出的也是rootMenu对象。

    3.2 ConsoleUI._execute()

    返回上一层 ConsoleUI._execute(),接着执行:

    menu = rootMenu  #这是2.1返回的一个对象,menu在此是一个临时变量
    if menu is not None:
        self._context = menu  #完成上下文切换
    

    3.3 ConsoleUI._onEnter()

    再返回上一层ConsoleUI._execute(),接着执行:

    ConsoleUI._initPrompt()
    ConsoleUI._showPrompt()#重新显示shell提示符:w3af>>>
    

    二、加载插件

    加载爬虫插件web spider的命令是: w3af新版本命令:w3af/plugins>>>crawl web_spider w3af旧版本命令:w3af/plugins>>>discovery webSpider

    1.命令解析

    crawl/discovery代表插件类型,w3af的插件类型就是w3af\plugins目录下的目录名(除去attack,tests),包括audit,crawl,auth,output等。它对应于类pluginsTypeMenu.

    web_spider/webSpider代表具体的插件名字,位于w3af\plugins\插件类型\目录下。

    2.获取所有的可用插件

    从w3af_console启动,到获取每一种类型的所有插件的过程如下

    1)ConsoleUI的_init_()中 self._w3af = w3afCore()
    2)ConsoleUI的sh()中调用rootMenu(...,self._w3af,...)
    3)rootMenu的_init_()中生成pluginsMenu对象
    4)pluginsMenu的_init_()中调用w3af.plugins.get_plugin_types(),返回所有的插件类型types
    5)对于每一个插件类型type,生成一个pluginsTypeMenu对象
    6)pluginsTypeMenu的_init_()中调用w3af.plugins.get_plugin_list(name),返回一种插件的所有插件名字
    7)对于一种插件的所有具体插件,pluginsTypeMenu的_init_()中调用self._w3af.plugins.get_plugin_inst(self._name, p).get_options()返回一个具体插件的使用选项说明
    

    ps: w3af.plugins是类w3af_core_plugins对象

    3.w3af/plugins>>>crawl web_spider

    此时的上下文是pluginsMenu(参考一.3)

    ConsoleUI.onEnter()->ConsoleUI.execute()->pluginsMenu.execute(['crawl','web_spider'])

    3.1 pluginsMenu.execute(['crawl','web_spider'])

    1)pluginsMenu.execute(['crawl','web_spider'])

    2)menu.execute(['crawl','web_spider'])

    commands='crawl'
    params=['web_spider']
    #由上一节可知,每一个插件类型已经生成pluginsTypeMenu对象,此外查找crawl对应的pluginsTypeMenu
    

    3)pluginsTypeMenu.execute(['web_spider'])

    4)pluingsTypeMenu._enablePlugins('web_spider')

    5)w3afCore.w3af_core_plugins.set_plugins([...,'web_spider'],'crawl')

    6)w3af_core_plugins.set_plugins_generic('crawl','web_spider') #加入字典plugins_names_dict

    至此,web_spider插件加载成功。

    3.2 返回过程省略

    三、启动插件

    w3af>>start执行后,如何创建web_spider插件类实例,并启动插件呢?

    1. 创建web_spider实例

    首先,当前的上下文_context是rootMenu。函数调用过程如下

    1)rootMenu._cmd_start()

    2)rootMenu._real_start()

    3)rootMenu._w3af.plugins.init_plugins()

    即w3af_core_plugins.init_plugins()

    4)w3af_core_plugins.plugin_factory()

    5)w3af_core_plugins.create_instances()

    6)w3af_core_plugins.get_plugin_inst()

    def get_plugin_inst(self, plugin_type, plugin_name):
        """
        :return: An instance of a plugin.
        """
        plugin_inst = factory('w3af.plugins.%s.%s' % (plugin_type, plugin_name))
        plugin_inst.set_url_opener(self._w3af_core.uri_opener)
        plugin_inst.set_worker_pool(self._w3af_core.worker_pool)
    
        if plugin_name in self._plugins_options[plugin_type].keys():
            custom_options = self._plugins_options[plugin_type][plugin_name]
            plugin_inst.set_options(custom_options)
    
        # This will init some plugins like mangle and output
        if plugin_type == 'attack' and not self.initialized:
            self.init_plugins()
    
        return plugin_inst
    

    7)factory类,就是import web_spider 插件,同时保证插件中的类名字和文件名字完全相同;web_spider类的继承关系为

    object-->Configurable-->plugin-->CrawlPlugin-->web_spider
    

    2. 运行插件

    web_spider插件的启动过程如下:

    1) rootMenu._cmd_start()

    2) rootMenu._real_start()

    3) rootMenu._w3af.start()

    4) w3af_core_strategy.start()

    5) w3af_core_strategy._setup_crawl_infrastructure()

    6) crawl_infrastructure.start()

    四、小结

    本文用DFS的方式,跟踪分析了w3af_console的menu切换,插件加载与启动的过程,理清了函数调用关系,初步弄懂了各类之间的关联。



沪ICP备19023445号-2号
友情链接