#!/usr/bin/env python

"""
Copyright (c) 2006-2024 sqlmap developers (https://sqlmap.org/)  
See the file 'LICENSE' for copying permission
"""

from lib.controller.handler import setHandler  # 从 handler 模块导入 setHandler 函数
from lib.core.common import Backend  # 从 common 模块导入 Backend 类
from lib.core.common import Format  # 从 common 模块导入 Format 类
from lib.core.data import conf  # 从 data 模块导入 conf 对象
from lib.core.data import kb  # 从 data 模块导入 kb 对象
from lib.core.data import logger  # 从 data 模块导入 logger 对象
from lib.core.data import paths  # 从 data 模块导入 paths 对象
from lib.core.enums import CONTENT_TYPE  # 从 enums 模块导入 CONTENT_TYPE 枚举类
from lib.core.exception import SqlmapNoneDataException  # 从 exception 模块导入 SqlmapNoneDataException 类
from lib.core.exception import SqlmapUnsupportedDBMSException  # 从 exception 模块导入 SqlmapUnsupportedDBMSException 类
from lib.core.settings import SUPPORTED_DBMS  # 从 settings 模块导入 SUPPORTED_DBMS 列表
from lib.utils.brute import columnExists  # 从 brute 模块导入 columnExists 函数
from lib.utils.brute import fileExists  # 从 brute 模块导入 fileExists 函数
from lib.utils.brute import tableExists  # 从 brute 模块导入 tableExists 函数

def action():
    """
    该函数利用受影响的 URL 参数上的 SQL 注入漏洞，并从后端数据库管理系统或操作系统中提取请求的数据（如果可能）。
    """

    # 首先，我们需要识别后端数据库管理系统，才能继续注入操作
    setHandler()  # 设置数据库处理程序

    if not Backend.getDbms() or not conf.dbmsHandler:  # 如果无法识别数据库或没有对应的数据库处理程序
        htmlParsed = Format.getErrorParsedDBMSes()  # 解析 HTML 错误页面以识别数据库

        errMsg = "sqlmap was not able to fingerprint the "  # 错误信息
        errMsg += "back-end database management system"

        if htmlParsed:  # 如果从 HTML 错误页面解析到了数据库信息
            errMsg += ", but from the HTML error page it was "
            errMsg += "possible to determinate that the "
            errMsg += "back-end DBMS is %s" % htmlParsed

        if htmlParsed and htmlParsed.lower() in SUPPORTED_DBMS:  # 如果解析到的数据库在支持的数据库列表中
            errMsg += ". Do not specify the back-end DBMS manually, "
            errMsg += "sqlmap will fingerprint the DBMS for you"
        elif kb.nullConnection:  # 如果是使用 null connection 模式
            errMsg += ". You can try to rerun without using optimization "
            errMsg += "switch '%s'" % ("-o" if conf.optimize else "--null-connection")

        raise SqlmapUnsupportedDBMSException(errMsg)  # 抛出不支持的数据库管理系统异常

    conf.dumper.singleString(conf.dbmsHandler.getFingerprint())  # 打印识别到的数据库指纹

    kb.fingerprinted = True  # 设置已识别数据库指纹

    # 枚举选项
    if conf.getBanner:  # 如果需要获取数据库版本信息
        conf.dumper.banner(conf.dbmsHandler.getBanner())  # 打印数据库版本信息

    if conf.getCurrentUser:  # 如果需要获取当前用户
        conf.dumper.currentUser(conf.dbmsHandler.getCurrentUser())  # 打印当前用户

    if conf.getCurrentDb:  # 如果需要获取当前数据库
        conf.dumper.currentDb(conf.dbmsHandler.getCurrentDb())  # 打印当前数据库

    if conf.getHostname:  # 如果需要获取数据库主机名
        conf.dumper.hostname(conf.dbmsHandler.getHostname())  # 打印数据库主机名

    if conf.isDba:  # 如果需要判断当前用户是否为 DBA
        conf.dumper.dba(conf.dbmsHandler.isDba())  # 打印判断结果

    if conf.getUsers:  # 如果需要获取所有用户
        conf.dumper.users(conf.dbmsHandler.getUsers())  # 打印所有用户

    if conf.getStatements:  # 如果需要获取数据库中的所有 SQL 语句
        conf.dumper.statements(conf.dbmsHandler.getStatements())  # 打印所有 SQL 语句

    if conf.getPasswordHashes:  # 如果需要获取用户密码哈希
        try:
            conf.dumper.userSettings("database management system users password hashes", conf.dbmsHandler.getPasswordHashes(), "password hash", CONTENT_TYPE.PASSWORDS)  # 打印用户密码哈希
        except SqlmapNoneDataException as ex:
            logger.critical(ex)  # 打印错误信息
        except:
            raise  # 抛出其他异常

    if conf.getPrivileges:  # 如果需要获取用户权限
        try:
            conf.dumper.userSettings("database management system users privileges", conf.dbmsHandler.getPrivileges(), "privilege", CONTENT_TYPE.PRIVILEGES)  # 打印用户权限
        except SqlmapNoneDataException as ex:
            logger.critical(ex)  # 打印错误信息
        except:
            raise  # 抛出其他异常

    if conf.getRoles:  # 如果需要获取用户角色
        try:
            conf.dumper.userSettings("database management system users roles", conf.dbmsHandler.getRoles(), "role", CONTENT_TYPE.ROLES)  # 打印用户角色
        except SqlmapNoneDataException as ex:
            logger.critical(ex)  # 打印错误信息
        except:
            raise  # 抛出其他异常

    if conf.getDbs:  # 如果需要获取所有数据库
        try:
            conf.dumper.dbs(conf.dbmsHandler.getDbs())  # 打印所有数据库
        except SqlmapNoneDataException as ex:
            logger.critical(ex)  # 打印错误信息
        except:
            raise  # 抛出其他异常

    if conf.getTables:  # 如果需要获取数据库中的所有表
        try:
            conf.dumper.dbTables(conf.dbmsHandler.getTables())  # 打印所有表
        except SqlmapNoneDataException as ex:
            logger.critical(ex)  # 打印错误信息
        except:
            raise  # 抛出其他异常

    if conf.commonTables:  # 如果需要获取一些常见的表
        try:
            conf.dumper.dbTables(tableExists(paths.COMMON_TABLES))  # 打印常见的表
        except SqlmapNoneDataException as ex:
            logger.critical(ex)  # 打印错误信息
        except:
            raise  # 抛出其他异常

    if conf.getSchema:  # 如果需要获取数据库架构信息
        try:
            conf.dumper.dbTableColumns(conf.dbmsHandler.getSchema(), CONTENT_TYPE.SCHEMA)  # 打印数据库架构信息
        except SqlmapNoneDataException as ex:
            logger.critical(ex)  # 打印错误信息
        except:
            raise  # 抛出其他异常

    if conf.getColumns:  # 如果需要获取数据库中的所有列
        try:
            conf.dumper.dbTableColumns(conf.dbmsHandler.getColumns(), CONTENT_TYPE.COLUMNS)  # 打印所有列
        except SqlmapNoneDataException as ex:
            logger.critical(ex)  # 打印错误信息
        except:
            raise  # 抛出其他异常

    if conf.getCount:  # 如果需要获取表中的数据行数
        try:
            conf.dumper.dbTablesCount(conf.dbmsHandler.getCount())  # 打印数据行数
        except SqlmapNoneDataException as ex:
            logger.critical(ex)  # 打印错误信息
        except:
            raise  # 抛出其他异常

    if conf.commonColumns:  # 如果需要获取一些常见的列
        try:
            conf.dumper.dbTableColumns(columnExists(paths.COMMON_COLUMNS))  # 打印常见的列
        except SqlmapNoneDataException as ex:
            logger.critical(ex)  # 打印错误信息
        except:
            raise  # 抛出其他异常

    if conf.dumpTable:  # 如果需要导出表中的数据
        try:
            conf.dbmsHandler.dumpTable()  # 导出表中的数据
        except SqlmapNoneDataException as ex:
            logger.critical(ex)  # 打印错误信息
        except:
            raise  # 抛出其他异常

    if conf.dumpAll:  # 如果需要导出数据库中的所有数据
        try:
            conf.dbmsHandler.dumpAll()  # 导出数据库中的所有数据
        except SqlmapNoneDataException as ex:
            logger.critical(ex)  # 打印错误信息
        except:
            raise  # 抛出其他异常

    if conf.search:  # 如果需要在数据库中搜索数据
        try:
            conf.dbmsHandler.search()  # 在数据库中搜索数据
        except SqlmapNoneDataException as ex:
            logger.critical(ex)  # 打印错误信息
        except:
            raise  # 抛出其他异常

    if conf.sqlQuery:  # 如果需要执行 SQL 查询
        for query in conf.sqlQuery.strip(';').split(';'):  # 循环执行每个 SQL 查询语句
            query = query.strip()
            if query:  # 如果查询语句不为空
                conf.dumper.sqlQuery(query, conf.dbmsHandler.sqlQuery(query))  # 打印查询结果

    if conf.sqlShell:  # 如果需要进入 SQL shell
        conf.dbmsHandler.sqlShell()  # 进入 SQL shell

    if conf.sqlFile:  # 如果需要从文件读取 SQL 查询语句
        conf.dbmsHandler.sqlFile()  # 从文件读取 SQL 查询语句并执行

    # 用户定义函数选项
    if conf.udfInject:  # 如果需要注入用户定义函数
        conf.dbmsHandler.udfInjectCustom()  # 注入用户定义函数

    # 文件系统选项
    if conf.fileRead:  # 如果需要读取文件
        conf.dumper.rFile(conf.dbmsHandler.readFile(conf.fileRead))  # 打印读取的文件内容

    if conf.fileWrite:  # 如果需要写入文件
        conf.dbmsHandler.writeFile(conf.fileWrite, conf.fileDest, conf.fileWriteType)  # 写入文件

    if conf.commonFiles:  # 如果需要读取一些常见的文件
        try:
            conf.dumper.rFile(fileExists(paths.COMMON_FILES))  # 打印读取的常见文件内容
        except SqlmapNoneDataException as ex:
            logger.critical(ex)  # 打印错误信息
        except:
            raise  # 抛出其他异常

    # 操作系统选项
    if conf.osCmd:  # 如果需要执行操作系统命令
        conf.dbmsHandler.osCmd()  # 执行操作系统命令

    if conf.osShell:  # 如果需要进入操作系统 shell
        conf.dbmsHandler.osShell()  # 进入操作系统 shell

    if conf.osPwn:  # 如果需要利用操作系统漏洞
        conf.dbmsHandler.osPwn()  # 利用操作系统漏洞

    if conf.osSmb:  # 如果需要利用 SMB 协议
        conf.dbmsHandler.osSmb()  # 利用 SMB 协议

    if conf.osBof:  # 如果需要利用缓冲区溢出漏洞
        conf.dbmsHandler.osBof()  # 利用缓冲区溢出漏洞

    # Windows 注册表选项
    if conf.regRead:  # 如果需要读取注册表值
        conf.dumper.registerValue(conf.dbmsHandler.regRead())  # 打印读取的注册表值

    if conf.regAdd:  # 如果需要添加注册表值
        conf.dbmsHandler.regAdd()  # 添加注册表值

    if conf.regDel:  # 如果需要删除注册表值
        conf.dbmsHandler.regDel()  # 删除注册表值

    # 其他选项
    if conf.cleanup:  # 如果需要清理数据库中的数据
        conf.dbmsHandler.cleanup()  # 清理数据库中的数据

    if conf.direct:  # 如果使用直接连接模式
        conf.dbmsConnector.close()  # 关闭数据库连接