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

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

sqlmap源码分析(一)的更多相关文章

  1. SQLMAP源码分析(一)

    说起来,学习Python很大一部分原因是由于对WEB安全的兴趣以及对SQLMAP这款工具的好奇,曾经设想学完Python基础就读一读SQLMAP源码,然而懒病一犯,随之就大江东去.近来,又重新燃起了读 ...

  2. SQLmap源码分析之框架初始化(一)

    SQLmap是现在搞web人手一个的注入神器,不仅包含了主流数据库的SQL注入检测,而且包含提权以及后渗透模块.基于python2.x开发而成,使用方便.所以研究web安全少不了分析源码,学习代码的同 ...

  3. SQLMAP源码分析-目录结构

    -----------------------------------------------------------------------------│  README.md│  sqlmap.c ...

  4. Python:Sqlmap源码精读之解析xml

    XML <?xml version="1.0" encoding="UTF-8"?> <root> <!-- MySQL --&g ...

  5. MyBatis源码分析(1)-MapConfig文件的解析

    1.简述 MyBatis是一个优秀的轻ORM框架,由最初的iBatis演化而来,可以方便的完成sql语句的输入输出到java对象之间的相互映射,典型的MyBatis使用的方式如下: String re ...

  6. Mybatis源码分析之SqlSessionFactory(一)

    简介 MyBatis的前身叫iBatis,本是apache的一个开源项目, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBa ...

  7. ABP源码分析一:整体项目结构及目录

    ABP是一套非常优秀的web应用程序架构,适合用来搭建集中式架构的web应用程序. 整个Abp的Infrastructure是以Abp这个package为核心模块(core)+15个模块(module ...

  8. HashMap与TreeMap源码分析

    1. 引言     在红黑树--算法导论(15)中学习了红黑树的原理.本来打算自己来试着实现一下,然而在看了JDK(1.8.0)TreeMap的源码后恍然发现原来它就是利用红黑树实现的(很惭愧学了Ja ...

  9. nginx源码分析之网络初始化

    nginx作为一个高性能的HTTP服务器,网络的处理是其核心,了解网络的初始化有助于加深对nginx网络处理的了解,本文主要通过nginx的源代码来分析其网络初始化. 从配置文件中读取初始化信息 与网 ...

随机推荐

  1. SQL存储过程的学习01

    虽工作多年,但是sql的存储过程一致都没怎么用过,今天来按照博客https://www.cnblogs.com/applelife/p/11016674.html来学习一下(我使用postgre sq ...

  2. 有没有想过String为什么设计为不可变对象

    1.声明为final类的目的: 主要目的就是保证String是不可变(immutable).不可变就是第二次给一个String 变量赋值的时候,不是在原内存地址上修改数据,而是重新指向一个新对象,新地 ...

  3. Linux 环境部署Skywalking支持Elasticsearch

    一.环境准备 1.Java JKD 1.8(建议) 2.Elasticsearch 3.Skywalking 二. 环境搭建 安装Skywalking分为两个步骤: a.安装Backend后端服务 b ...

  4. 我们如何监视所有 Spring Boot 微服务?

    Spring Boot 提供监视器端点以监控各个微服务的度量.这些端点对于获取有关应用程序的信息(如它们是否已启动)以及它们的组件(如数据库等)是否正常运行很有帮助.但是,使用监视器的一个主要缺点或困 ...

  5. ruoyi首次使用常见问题的解决方案

    1.导入项目之后,下载依赖包之后,模块的依赖项飘红(我这里无法复现,当参考图吧) 解决方法: 2.ruoyi框架代码生成之后,需要自己进行替换到指定位置.相应的官方文档位置,否则,可能会出现404,访 ...

  6. Servlet之间的关联

  7. 说出 5 条 IO 的最佳实践?

    IO 对 Java 应用的性能非常重要.理想情况下,你不应该在你应用的关键路径上 避免 IO 操作.下面是一些你应该遵循的 Java IO 最佳实践: a)使用有缓冲区的 IO 类,而不要单独读取字节 ...

  8. MiL → SiL → PiL → HiL 是什么?

    基于模型的快速原型开发通常分为四个过程:MiL → SiL → PiL → HiL 1. MiL(Model in Loop)模型在环  在PC上基于模型的测试,它的输出是经过验证的控制算法模型.验证 ...

  9. Creating a File View

    创建文件视图 为了映射一个文件的数据到进程的虚拟内存,你必须创建一个文件的视图.MapViewofFile和MapViewofFileEX使用CreateFileMapping返回的句柄,在虚拟地址空 ...

  10. Python读文件并写入数组

    直接上代码: # 读文件 def get_venue(file): fname = file # 文件名 # 获取数据长度 len = 0 with open(fname, 'r+', encodin ...