sqlmap源码分析(一)

Sqlmap源码分析(一)

此次分析的sqlmap目标版本为1.6.1.2#dev

只对sqlmap的核心检测代码进行详细分析其他的一带而过

sqlmap.py文件结构

为了不让篇幅过长下面只写出了sqlmap.py(入口点)引用的前三个函数,

from __future__ import print_function  # 即使在python2.X,使用print就得像python3.X那样加括号
try:
    '''
    	代码作用:
        python版本检测 导入必要的包 禁止生成__pycache__
        导入官方模块
        消除一些可忽略的警告
        导入自定义模块
    '''
except KeyboardInterrupt:
    '''
    代码作用:
    处理ctrl c v手动中断
    '''  
	
def modulePath():
    pass 
def checkEnvironment():
    pass # 下方有详细代码 这里为了方便展示整体结构不再列出
def main():
    try:
        dirtyPatches() # 补丁 针对python3进行额外配置,对其他第三方的一些参数调整(下方有详细代码)
        resolveCrossReferences() # 解决交叉引用(下方有详细代码)
        checkEnvironment()  # 检测环境 sqlmap版本和路径是否正常(下方有详细代码)
        setPaths(modulePath())  # 路径配置
        banner()  # 见名知意打印banner信息
		'''
		代码作用:
		对命令行进行处理
		根据信息进行初始化
		下面的if和elif中代码 测试sqlmap能否能正常运行如果没问题就进入start()执行sql注入
		'''
        if:           
            pass
        elif:
            pass
        else:
            pass
            start()
            pass
	except:# 长达300行的自定义错误处理
        pass
    finally:# 收尾工作
        pass

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        pass
    except SystemExit:
        raise
    except:
        traceback.print_exc()
    finally:   # 根据线程数设定不同的退出方式
        if threading.active_count() > 1:
            os._exit(getattr(os, "_exitcode", 0))
        else:
            sys.exit(getattr(os, "_exitcode", 0))
else:
    __import__("lib.controller.controller")

dirtyPatches函数

函数作用

  • 对http.client进行参数的修改,以及针对python3相应方法的重新设置
  • 对universaldetector检测编码方式的调整
  • 针对Windows操作系统上添加对inet_pton()
  • PLACE.CUSTOM_POST调整
def dirtyPatches():
    """
    在thirdparty\six\init.py中有这样一行 MovedModule("http_client", "httplib", "http.client"),
    six是Python2和3的兼容性库。这个项目旨在支持可同时运行在Python2和3上的代码库
    如果是python3 _http_client实际就是http.client
    """
    # 可以接收很长的响应头结果行 在Python\Lib\http\client.py中_MAXLINE=65536
    _http_client._MAXLINE = 1 * 1024 * 1024

    if six.PY3:  # 如果是python3就执行这部分代码
        '''
            hasattr 返回对象是否具有具有给定名称的属性
            如果_http_client.HTTPConnection没有__send_output(python3中没有)
            就新建一个并且函数引用,现在执行__send_output函数等同于_send_output
        '''
        if not hasattr(_http_client.HTTPConnection, "__send_output"):
            _http_client.HTTPConnection.__send_output = _http_client.HTTPConnection._send_output

        def _send_output(self, *args, **kwargs):
            '''
            conf是AttribDict类(在lib/core/datatype.py中)的对象
            此类定义了字典,并添加了将成员作为属性访问的功能。因为AttribDict继承了python的dict类重写了一部分功能
            产生的对象就可以理解为字典
            '''
            if conf.get("chunked") and "encode_chunked" in kwargs:
                kwargs["encode_chunked"] = False
            self.__send_output(*args, **kwargs)

        # 理解为将_send_output函数内容更新
        _http_client.HTTPConnection._send_output = _send_output

        # 现在xx.__send_output的内容为原xx._send_output
        # 现在xx._send_output=自定义函数的内容
        
    if IS_WIN:
        # 针对Windows操作系统上添加对inet_pton()的支持处理ipv4,将ip地址192.168.1.1转换成二进制的ip地址
        from thirdparty.wininetpton import win_inet_pton

    # 关于编码的配置
    codecs.register(lambda name: codecs.lookup("utf-8") if name == "cp65001" else None)

    # 与上面_send_output操作流程类似
    if hasattr(_http_client, "LineAndFileWrapper"):
        def _(self, *args):
            return self._readline()

        _http_client.LineAndFileWrapper._readline = _http_client.LineAndFileWrapper.readline
        _http_client.LineAndFileWrapper.readline = _

    # 原值为0.2 universaldetector是Mozilla公司提供的检测编码方式的工具
    thirdparty.chardet.universaldetector.MINIMUM_THRESHOLD = 0.90

    # 从命令行中匹配对应值 如果匹配到并且值不等于"POST"进行替换操作
    match = re.search(r" --method[= ](\w+)", " ".join(sys.argv))
    if match and match.group(1).upper() != PLACE.POST:
        PLACE.CUSTOM_POST = PLACE.CUSTOM_POST.replace("POST", "%s (body)" % match.group(1))

    try:
        os.urandom(1)  # 返回包含适合加密使用的随机字节的字节对象(b'\x03')
    except NotImplementedError:
        if six.PY3:
            os.urandom = lambda size: bytes(random.randint(0, 255) for _ in range(size))
        else:
            os.urandom = lambda size: "".join(chr(random.randint(0, 255)) for _ in xrange(size))

resolveCrossReferences函数

下面全部都是函数的替换,等号右侧isDigit、readInput等都是函数。

def resolveCrossReferences():
    lib.core.threads.isDigit = isDigit
    lib.core.threads.readInput = readInput
    lib.core.common.getPageTemplate = getPageTemplate
    lib.core.convert.filterNone = filterNone
    lib.core.convert.isListLike = isListLike
    lib.core.convert.shellExec = shellExec
    lib.core.convert.singleTimeWarnMessage = singleTimeWarnMessage
    lib.core.option._pympTempLeakPatch = pympTempLeakPatch
    lib.request.connect.setHTTPHandlers = _setHTTPHandlers
    lib.utils.search.setHTTPHandlers = _setHTTPHandlers
    lib.controller.checks.setVerbosity = setVerbosity
    lib.utils.sqlalchemy.getSafeExString = getSafeExString
    thirdparty.ansistrm.ansistrm.stdoutEncode = stdoutEncode

checkEnvironment函数

函数作用:

  • 检测目录是否正常
  • 检测sqlmap版本是否在1.0以上
  • 将对应的特殊的字典类型变量放到全局中
def checkEnvironment():
    try:  # 检测是否是一个正常的目录 如果有编码问题报错处理
        os.path.isdir(modulePath())
    except UnicodeEncodeError:
        errMsg = "your system does not properly handle non-ASCII paths. "
        errMsg += "Please move the sqlmap's directory to the other location"
        logger.critical(errMsg)
        raise SystemExit
        
    # 检测sqlmap版本 如果过低提示更新版本 并退出
    if LooseVersion(VERSION) < LooseVersion("1.0"):
        errMsg = "your runtime environment (e.g. PYTHONPATH) is "
        errMsg += "broken. Please make sure that you are not running "
        errMsg += "newer versions of sqlmap with runtime scripts for older "
        errMsg += "versions"
        logger.critical(errMsg)
        raise SystemExit

    if "sqlmap.sqlmap" in sys.modules:
        for _ in ("cmdLineOptions", "conf", "kb"):
            # 将系统路径lib.core.data中的"cmdLineOptions", "conf", "kb"变为同名的全局变量,这三个是AttribDict(dict)的对象。
            globals()[_] = getattr(sys.modules["lib.core.data"], _)

        for _ in (
                "SqlmapBaseException", "SqlmapShellQuitException", "SqlmapSilentQuitException",
                "SqlmapUserQuitException"):
            globals()[_] = getattr(sys.modules["lib.core.exception"], _)

通过读代码发现sqlmap花费了大量的代码在python2的基础上进行修补😶😶😶

start函数

@stackedmethod
def start():
    '''
    	这些if并不涉及核心的检测代码所以忽略掉
    '''
	if xxx:
		pass
	if xxx:
		pass
	if xxx:
		pass
	for targetUrl, targetMethod, targetData, targetCookie, targetHeaders in kb.targets:
        # 核心代码 核心代码 核心代码
	
	if xxx:
		pass
	if xxx:
		pass
	return True

核心代码很复杂需要花一些时间 在后续的随笔中再进行分析

posted @   beginner_z  阅读(755)  评论(2编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」
点击右上角即可分享
微信分享提示