0x00 前言
SQLMap作为SQL注入的神器,又方便同时功能也非常的多,所以阅读sqlmap能学习到很多东西,这篇文章作为开篇来学习一下,也算是一个系列的开始
0x01 正文
我们这里直接从入口文件 sqlmap.py 开始看起来
__import__
相当于动态引入类,和java反射有些类似,这里看到代码中动态引入lib.utils.versioncheck库,我们跟过去看看
try:
# 动态引入sqlmap对版本检查文件
__import__("lib.utils.versioncheck") # this has to be the first non-standard import
except ImportError:
sys.exit("[!] wrong installation detected (missing modules). Visit 'https://github.com/sqlmapproject/sqlmap/#installation' for further details")
versioncheck文件
首先进行了一个语言版本的检测,如果语言版本低于2.6那么就会自动退出程序
接下来的extensions = ("bz2", "gzip", "pyexpat", "ssl", "sqlite3", "zlib") 中存的是运行sqlmap必要的库
这里还是利用__import__
进行一个动态引入,如果没有安装库那么自然就会进行一个报错,然后被try...except 进行一个捕捉添加到我们专门存储报错信息的errors数组中
所以总结一下我们可以发现,这个文件主要是负责python版本的检测 以及运行过程中必要的库的一些检测
# 如果低于 2.6 程序自动退出
if PYVERSION < "2.6":
sys.exit("[%s] [CRITICAL] incompatible Python version detected ('%s'). To successfully run sqlmap you'll have to use version 2.6, 2.7 or 3.x (visit 'https://www.python.org/downloads/')" % (time.strftime("%X"), PYVERSION))
errors = []
# 集合中存放着sqlmap需要的库,然后进行动态引入 如果报错那么就添加错误信息
# 这个功能主要是检查必要的库是否存在
extensions = ("bz2", "gzip", "pyexpat", "ssl", "sqlite3", "zlib")
for _ in extensions:
try:
__import__(_)
except ImportError:
errors.append(_)
if errors:
errMsg = "[%s] [CRITICAL] missing one or more core extensions (%s) " % (time.strftime("%X"), ", ".join("'%s'" % _ for _ in errors))
errMsg += "most likely because current version of Python has been "
errMsg += "built without appropriate dev packages"
sys.exit(errMsg)
我们还是继续查看我们的主文件 sqlmap.py
这一段就是捕捉前面的报错信息,如果前面出现了报错这里就会进行一个捕捉
首先会检测我们当前的命名空间中是否存在logger(个人觉得通俗的说就是检测有没有引入logger库),如果存在的话就将错误信息写到我们的日志中,并且记录危害为严重级别
如果没有就直接进行退出
except KeyboardInterrupt:
# 用户自行终止
errMsg = "user aborted"
# 如果命名空间中引入 logger就将错误信息写到我们的日志中
if "logger" in globals():
# 在日志中记载 critical 级别的信息
logger.critical(errMsg)
raise SystemExit
else:
import time
sys.exit("\r[%s] [CRITICAL] %s" % (time.strftime("%X"), errMsg))
继续往下看,下面是一个modelPath函数
一开始看到这个函数有点蒙蒙的我们来仔细看一下
def modulePath():
"""
This will get us the program's directory, even if we are frozen
using py2exe
"""
# weAreFrozen 返回的信息如果是true 路径就为sys.executable 反之就是说明是脚本 赋值为 __file__
# 如果是exe 返回的路径是sys.executable 反之返回文件的路径
try:
_ = sys.executable if weAreFrozen() else __file__
except NameError:
_ = inspect.getsourcefile(modulePath)
# 将获取的路径转化成想要的编码 sys.getfilesystemencoding() 获取系统默认编码 utf-8
return getUnicode(os.path.dirname(os.path.realpath(_)), encoding=sys.getfilesystemencoding() or UNICODE_ENCODING)
我们看到if语句中调用了 weAreFrozen()我们跟过去看一下,发现给了一个链接我们去看看
发现主要是为了解决如下问题
大致意思就是:如果我们将python文件打包之后,负责打包的py2exed中不包含__file__
这就导致exe运行过程中无法使用该方法,但是可以使用 .
但是这也只代表着只能当前的应用目录下才能进行运行
所以modulePath方法就是为了解决 当被打包成exe的时候无法使用__file__
的情况下 仍能获取当前执行文件路径的问题
接下来我们来看看怎么实现吧
def weAreFrozen():
"""
Returns whether we are frozen via py2exe.
This will affect how we find out where we are located.
# Reference: http://www.py2exe.org/index.cgi/WhereAmI
"""
return hasattr(sys, "frozen")
首先 hasattr 方法是检测 对象中是否包含frozen 如果包含返回true 不包含则返回 false
在脚本的情况下我们发现我们的sys中并没有这个属性
接下来利用pyinstaller 对程序进行一个打包,我们打包成一个exe 来观察是否含有 frozen 属性
我们写一个简单的测试py文件
import sys
print(sys.executable)
print(sys.frozen)
print("hello,world")
然后利用
pyinstaller -F 1.py
然后进入 dist文件夹,并且进行执行,发现exe中果然含有frozen属性
然后再来看这个python语句
如果 weAreFrozen 为 True 说明是exe 然后就 赋值给 _ 也就是当前文件的路径
反之说明不是exe文件则可以正常使用 __file__
方法
_ = sys.executable if weAreFrozen() else __file__
(不得不说,代码写的真的太好了,看湿了