@ -10,13 +10,16 @@ from __future__ import print_function
try :
import sys
# 防止Python自动生成.pyc文件
sys . dont_write_bytecode = True
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 " )
# 导入标准库模块
import bdb
import glob
import inspect
@ -32,6 +35,7 @@ try:
import traceback
import warnings
# 忽略DeprecationWarning, 除非命令行参数中包含"--deprecations"
if " --deprecations " not in sys . argv :
warnings . filterwarnings ( action = " ignore " , category = DeprecationWarning )
else :
@ -41,14 +45,17 @@ try:
if sys . version_info > = ( 3 , 0 ) :
warnings . simplefilter ( " ignore " , category = ResourceWarning )
# 忽略特定警告
warnings . filterwarnings ( action = " ignore " , message = " Python 2 is no longer supported " )
warnings . filterwarnings ( action = " ignore " , message = " .*was already imported " , category = UserWarning )
warnings . filterwarnings ( action = " ignore " , message = " .*using a very old release " , category = UserWarning )
warnings . filterwarnings ( action = " ignore " , message = " .*default buffer size will be used " , category = RuntimeWarning )
warnings . filterwarnings ( action = " ignore " , category = UserWarning , module = " psycopg2 " )
# 导入sqlmap的核心日志模块
from lib . core . data import logger
# 导入sqlmap的核心功能模块
from lib . core . common import banner
from lib . core . common import checkPipedInput
from lib . core . common import checkSums
@ -90,6 +97,8 @@ try:
from lib . core . settings import VERSION
from lib . parse . cmdline import cmdLineParser
from lib . utils . crawler import crawl
except Exception as ex :
print ( " An error occurred: " + str ( ex ) )
except KeyboardInterrupt :
errMsg = " user aborted "
@ -102,26 +111,38 @@ except KeyboardInterrupt:
def modulePath ( ) :
"""
This will get us the program ' s directory, even if we are frozen
using py2exe
"""
获取程序的目录路径 , 即使使用了 py2exe 进行冻结打包也能正确获取 。
返回值 :
返回程序所在目录的Unicode编码路径字符串 。
"""
try :
# 如果程序被py2exe冻结, 则使用sys.executable获取路径; 否则使用__file__获取
_ = sys . executable if weAreFrozen ( ) else __file__
except NameError :
# 如果__file__未定义( 在某些环境下可能发生) , 则使用inspect模块获取当前函数的文件路径
_ = inspect . getsourcefile ( modulePath )
# 获取_的目录路径, 并转换为Unicode编码
return getUnicode ( os . path . dirname ( os . path . realpath ( _ ) ) , encoding = sys . getfilesystemencoding ( ) or UNICODE_ENCODING )
def checkEnvironment ( ) :
"""
检查运行环境是否适合运行 sqlmap 。
如果在检查过程中发现问题 , 则会记录错误信息并退出程序 。
"""
try :
# 检查程序目录是否存在
os . path . isdir ( modulePath ( ) )
except UnicodeEncodeError :
# 如果系统无法正确处理非ASCII路径, 则记录错误信息并退出
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的版本是否低于1.0,如果是,则说明运行环境有问题
if LooseVersion ( VERSION ) < LooseVersion ( " 1.0 " ) :
errMsg = " your runtime environment (e.g. PYTHONPATH) is "
errMsg + = " broken. Please make sure that you are not running "
@ -130,68 +151,81 @@ def checkEnvironment():
logger . critical ( errMsg )
raise SystemExit
# Patch for pip (import) environment
# 如果是通过pip安装的sqlmap, 则需要对sys.modules进行一些修补操作
if " sqlmap.sqlmap " in sys . modules :
for _ in ( " cmdLineOptions " , " conf " , " kb " ) :
# 将lib.core.data模块中的cmdLineOptions、conf、kb变量添加到全局变量中
globals ( ) [ _ ] = getattr ( sys . modules [ " lib.core.data " ] , _ )
for _ in ( " SqlmapBaseException " , " SqlmapShellQuitException " , " SqlmapSilentQuitException " , " SqlmapUserQuitException " ) :
# 将lib.core.exception模块中的异常类添加到全局变量中
globals ( ) [ _ ] = getattr ( sys . modules [ " lib.core.exception " ] , _ )
def main ( ) :
"""
Main function of sqlmap when running from command line .
当从命令行运行时, 这是 sqlmap 的主函数 。
"""
try :
# 应用脏补丁和解析交叉引用
dirtyPatches ( )
resolveCrossReferences ( )
# 检查运行环境并设置程序路径
checkEnvironment ( )
setPaths ( modulePath ( ) )
banner ( )
# Store original command line options for possible later restoration
# 解析命令行参数并更新全局配置
args = cmdLineParser ( )
cmdLineOptions . update ( args . __dict__ if hasattr ( args , " __dict__ " ) else args )
initOptions ( cmdLineOptions )
# 如果有管道输入,则设置批量模式
if checkPipedInput ( ) :
conf . batch = True
# 如果配置了API, 设置API日志和重定向标准输出和错误
if conf . get ( " api " ) :
# heavy imports
# 延迟导入(重量级导入)
from lib . utils . api import StdDbOut
from lib . utils . api import setRestAPILog
# Overwrite system standard output and standard error to write
# to an IPC database
# 重定向标准输出和错误到IPC数据库
sys . stdout = StdDbOut ( conf . taskid , messagetype = " stdout " )
sys . stderr = StdDbOut ( conf . taskid , messagetype = " stderr " )
setRestAPILog ( )
# 设置显示时间并显示法律声明和启动信息
conf . showTime = True
dataToStdout ( " [!] legal disclaimer: %s \n \n " % LEGAL_DISCLAIMER , forceOutput = True )
dataToStdout ( " [*] starting @ %s \n \n " % time . strftime ( " %X / % Y- % m- %d / " ) , forceOutput = True )
# 初始化程序
init ( )
# 如果没有设置更新所有选项,则执行后续操作
if not conf . updateAll :
# Postponed imports (faster start)
# 延迟导入(更快的启动)
if conf . smokeTest :
# 运行烟雾测试
from lib . core . testing import smokeTest
os . _exitcode = 1 - ( smokeTest ( ) or 0 )
elif conf . vulnTest :
# 运行漏洞测试
from lib . core . testing import vulnTest
os . _exitcode = 1 - ( vulnTest ( ) or 0 )
else :
# 启动sqlmap控制器
from lib . controller . controller import start
if conf . profile :
# 如果设置了性能分析,则进行性能分析
from lib . core . profiling import profile
globals ( ) [ " start " ] = start
profile ( )
else :
try :
# 如果设置了爬取深度和批量文件,则开始爬取
if conf . crawlDepth and conf . bulkFile :
targets = getFileItems ( conf . bulkFile )
@ -223,6 +257,7 @@ def main():
except Exception as ex :
os . _exitcode = 1
# 如果无法启动新线程,则记录错误信息并退出
if " can ' t start new thread " in getSafeExString ( ex ) :
errMsg = " unable to start new threads. Please check OS (u)limits "
logger . critical ( errMsg )
@ -230,6 +265,7 @@ def main():
else :
raise
# 捕获并处理各种异常,记录错误信息并退出
except SqlmapUserQuitException :
if not conf . batch :
errMsg = " user quit "
@ -272,61 +308,73 @@ def main():
os . _exitcode = 255
# 如果异常信息中包含内存耗尽相关的消息,则记录内存耗尽错误并退出
if any ( _ in excMsg for _ in ( " MemoryError " , " Cannot allocate memory " ) ) :
errMsg = " memory exhaustion detected "
logger . critical ( errMsg )
raise SystemExit
# 如果异常信息中包含磁盘空间不足相关的消息,则记录磁盘空间错误并退出
elif any ( _ in excMsg for _ in ( " No space left " , " Disk quota exceeded " , " Disk full while accessing " ) ) :
errMsg = " no space left on output device "
logger . critical ( errMsg )
raise SystemExit
# 如果异常信息中包含分页文件空间不足的消息,则记录分页文件空间错误并退出
elif any ( _ in excMsg for _ in ( " The paging file is too small " , ) ) :
errMsg = " no space left for paging file "
logger . critical ( errMsg )
raise SystemExit
# 如果异常信息中包含权限拒绝和Metasploit相关的消息, 则记录Metasploit权限错误并退出
elif all ( _ in excMsg for _ in ( " Access is denied " , " subprocess " , " metasploit " ) ) :
errMsg = " permission error occurred while running Metasploit "
logger . critical ( errMsg )
raise SystemExit
# 如果异常信息中包含权限拒绝和metasploit相关的消息, 则记录Metasploit权限错误并退出
elif all ( _ in excMsg for _ in ( " Permission denied " , " metasploit " ) ) :
errMsg = " permission error occurred while using Metasploit "
logger . critical ( errMsg )
raise SystemExit
# 如果异常信息中包含只读文件系统的消息,则记录只读文件系统错误并退出
elif " Read-only file system " in excMsg :
errMsg = " output device is mounted as read-only "
logger . critical ( errMsg )
raise SystemExit
# 如果异常信息中包含系统资源不足的消息,则记录资源耗尽错误并退出
elif " Insufficient system resources " in excMsg :
errMsg = " resource exhaustion detected "
logger . critical ( errMsg )
raise SystemExit
# 如果异常信息中包含磁盘I/O错误的消息, 则记录I/O错误并退出
elif " OperationalError: disk I/O error " in excMsg :
errMsg = " I/O error on output device "
logger . critical ( errMsg )
raise SystemExit
# 如果异常信息中包含URL违反BIDI规则的消息, 则记录无效URL错误并退出
elif " Violation of BIDI " in excMsg :
errMsg = " invalid URL (violation of Bidi IDNA rule - RFC 5893) "
logger . critical ( errMsg )
raise SystemExit
# 如果异常信息中包含无效IPv6 URL的消息, 则记录无效URL错误并退出
elif " Invalid IPv6 URL " in excMsg :
errMsg = " invalid URL ( ' %s ' ) " % excMsg . strip ( ) . split ( ' \n ' ) [ - 1 ]
logger . critical ( errMsg )
raise SystemExit
# 如果异常信息中包含临时文件访问问题的消息,则记录临时文件访问错误并退出
elif " _mkstemp_inner " in excMsg :
errMsg = " there has been a problem while accessing temporary files "
logger . critical ( errMsg )
raise SystemExit
# 如果异常信息中包含无法写入临时目录的消息,则记录临时目录写入错误并退出
elif any ( _ in excMsg for _ in ( " tempfile.mkdtemp " , " tempfile.mkstemp " , " tempfile.py " ) ) :
errMsg = " unable to write to the temporary directory ' %s ' . " % tempfile . gettempdir ( )
errMsg + = " Please make sure that your disk is not full and "
@ -335,131 +383,139 @@ def main():
logger . critical ( errMsg )
raise SystemExit
# 如果异常信息中包含权限拒绝的消息,则记录文件访问权限错误并退出
elif " Permission denied: ' " in excMsg :
match = re . search ( r " Permission denied: ' ([^ ' ]*) " , excMsg )
errMsg = " permission error occurred while accessing file ' %s ' " % match . group ( 1 )
logger . critical ( errMsg )
raise SystemExit
# 如果异常信息中包含sqlalchemy包版本问题的消息, 则记录sqlalchemy版本错误并退出
elif all ( _ in excMsg for _ in ( " twophase " , " sqlalchemy " ) ) :
errMsg = " please update the ' sqlalchemy ' package (>= 1.1.11) "
errMsg + = " (Reference: ' https://qiita.com/tkprof/items/7d7b2d00df9c5f16fffe ' ) "
# 由于网络原因,无法解析提供的链接,可能是链接问题或网络问题,请检查链接的合法性并适当重试。
logger . critical ( errMsg )
raise SystemExit
# 如果异常信息中包含Python版本问题的消息, 则记录Python版本错误并退出
elif " invalid maximum character passed to PyUnicode_New " in excMsg and re . search ( r " \ A3 \ .[34] " , sys . version ) is not None :
errMsg = " please upgrade the Python version (>= 3.5) "
errMsg + = " (Reference: ' https://bugs.python.org/issue18183 ' ) "
# 由于网络原因,无法解析提供的链接,可能是链接问题或网络问题,请检查链接的合法性并适当重试。
logger . critical ( errMsg )
raise SystemExit
# 如果异常信息中包含PyMySQL包版本问题的消息, 则记录PyMySQL版本错误并退出
elif all ( _ in excMsg for _ in ( " scramble_caching_sha2 " , " TypeError " ) ) :
errMsg = " please downgrade the ' PyMySQL ' package (=< 0.8.1) "
errMsg + = " (Reference: ' https://github.com/PyMySQL/PyMySQL/issues/700 ' ) "
# 由于网络原因,无法解析提供的链接,可能是链接问题或网络问题,请检查链接的合法性并适当重试。
logger . critical ( errMsg )
raise SystemExit
elif " must be pinned buffer, not bytearray " in excMsg :
errMsg = " error occurred at Python interpreter which "
errMsg + = " is fixed in 2.7. Please update accordingly "
errMsg + = " (Reference: ' https://bugs.python.org/issue8104 ' ) "
logger . critical ( errMsg )
raise SystemExit
# 如果异常信息中包含Python解
elif all ( _ in excMsg for _ in ( " OSError: [Errno 22] Invalid argument: ' " , " importlib " ) ) :
errMsg = " unable to read file ' %s ' " % extractRegexResult ( r " OSError: \ [Errno 22 \ ] Invalid argument: ' (?P<result>[^ ' ]+) " , excMsg )
logger . critical ( errMsg )
raise SystemExit
elif " hash_randomization " in excMsg :
errMsg = " error occurred at Python interpreter which "
errMsg + = " is fixed in 2.7.3. Please update accordingly "
errMsg + = " (Reference: ' https://docs.python.org/2/library/sys.html ' ) "
logger . critical ( errMsg )
raise SystemExit
elif " AttributeError: unable to access item " in excMsg and re . search ( r " 3 \ .11 \ . \ d+a " , sys . version ) :
errMsg = " there is a known issue when sqlmap is run with ALPHA versions of Python 3.11. "
errMsg + = " Please downgrade to some stable Python version "
logger . critical ( errMsg )
raise SystemExit
elif all ( _ in excMsg for _ in ( " Resource temporarily unavailable " , " os.fork() " , " dictionaryAttack " ) ) :
errMsg = " there has been a problem while running the multiprocessing hash cracking. "
errMsg + = " Please rerun with option ' --threads=1 ' "
logger . critical ( errMsg )
raise SystemExit
elif " can ' t start new thread " in excMsg :
errMsg = " there has been a problem while creating new thread instance. "
errMsg + = " Please make sure that you are not running too many processes "
if not IS_WIN :
errMsg + = " (or increase the ' ulimit -u ' value) "
logger . critical ( errMsg )
raise SystemExit
elif " can ' t allocate read lock " in excMsg :
errMsg = " there has been a problem in regular socket operation "
errMsg + = " ( ' %s ' ) " % excMsg . strip ( ) . split ( ' \n ' ) [ - 1 ]
logger . critical ( errMsg )
raise SystemExit
# 假设excMsg是一个包含异常信息的字符串变量
# 检查excMsg是否包含"pymysql"和"configparser"这两个字符串
elif all ( _ in excMsg for _ in ( " pymysql " , " configparser " ) ) :
# 如果都包含,则设置错误信息为检测到'pymsql'的错误初始化( 使用了Python3的依赖)
errMsg = " wrong initialization of ' pymsql ' detected (using Python3 dependencies) "
# 使用logger记录这个严重错误
logger . critical ( errMsg )
# 抛出SystemExit异常, 导致程序退出
raise SystemExit
# 检查excMsg是否包含"ntlm"、"socket.error, err"和"SyntaxError"这三个字符串
elif all ( _ in excMsg for _ in ( " ntlm " , " socket.error, err " , " SyntaxError " ) ) :
# 如果都包含,则设置错误信息为检测到'python-ntlm'的错误初始化( 使用了Python2的语法)
errMsg = " wrong initialization of ' python-ntlm ' detected (using Python2 syntax) "
# 使用logger记录这个严重错误
logger . critical ( errMsg )
# 抛出SystemExit异常, 导致程序退出
raise SystemExit
# 检查excMsg是否包含"drda"和"to_bytes"这两个字符串
elif all ( _ in excMsg for _ in ( " drda " , " to_bytes " ) ) :
# 如果都包含,则设置错误信息为检测到'drda'的错误初始化( 使用了Python3的语法)
errMsg = " wrong initialization of ' drda ' detected (using Python3 syntax) "
# 使用logger记录这个严重错误
logger . critical ( errMsg )
# 抛出SystemExit异常, 导致程序退出
raise SystemExit
# 检查excMsg是否包含特定的错误信息, 即'WebSocket'对象没有'status'属性
elif " ' WebSocket ' object has no attribute ' status ' " in excMsg :
# 如果包含, 则设置错误信息为检测到错误的websocket库
errMsg = " wrong websocket library detected "
# 添加参考链接到错误信息中
errMsg + = " (Reference: ' https://github.com/sqlmapproject/sqlmap/issues/4572#issuecomment-775041086 ' ) "
# 使用logger记录这个严重错误
logger . critical ( errMsg )
# 抛出SystemExit异常, 导致程序退出
raise SystemExit
# 检查excMsg是否包含特定的错误信息, 即初始化GUI界面时出现问题
elif all ( _ in excMsg for _ in ( " window = tkinter.Tk() " , ) ) :
# 如果包含, 则设置错误信息为GUI界面初始化问题
errMsg = " there has been a problem in initialization of GUI interface "
# 添加具体的错误信息到错误消息中
errMsg + = " ( ' %s ' ) " % excMsg . strip ( ) . split ( ' \n ' ) [ - 1 ]
# 使用logger记录这个严重错误
logger . critical ( errMsg )
# 抛出SystemExit异常, 导致程序退出
raise SystemExit
# 检查excMsg是否包含特定的错误信息, 即使用了不同版本的sqlmap文件
elif any ( _ in excMsg for _ in ( " unable to access item ' liveTest ' " , ) ) :
# 如果包含, 则设置错误信息为检测到使用了不同版本的sqlmap文件
errMsg = " detected usage of files from different versions of sqlmap "
# 使用logger记录这个严重错误
logger . critical ( errMsg )
# 抛出SystemExit异常, 导致程序退出
raise SystemExit
# 检查errMsg是否包含特定的错误信息, 即版本号相关的错误
elif any ( _ in errMsg for _ in ( " : 9.9.9# " , ) ) :
# 如果包含,则设置错误信息为一个简单的文本
errMsg = " LOL xD "
# 使用logger记录这个严重错误
logger . critical ( errMsg )
# 抛出SystemExit异常, 导致程序退出
raise SystemExit
# 检查是否设置了键盘中断的标记
elif kb . get ( " dumpKeyboardInterrupt " ) :
# 如果设置了, 则抛出SystemExit异常, 导致程序退出
raise SystemExit
# 检查excMsg是否包含特定的错误信息, 即"Broken pipe"
elif any ( _ in excMsg for _ in ( " Broken pipe " , ) ) :
# 如果包含, 则直接抛出SystemExit异常, 导致程序退出
raise SystemExit
# 检查valid变量是否为False
elif valid is False :
# 如果为False, 则设置错误信息为代码校验失败
errMsg = " code checksum failed (turning off automatic issue creation). "
errMsg + = " You should retrieve the latest development version from official GitHub "
errMsg + = " repository at ' %s ' " % GIT_PAGE
# 使用logger记录这个严重错误
logger . critical ( errMsg )
# 打印空行
print ( )
# 将错误信息输出到标准输出
dataToStdout ( excMsg )
# 抛出SystemExit异常, 导致程序退出
raise SystemExit
# 检查errMsg和excMsg组合后是否包含特定的错误信息, 即文件路径或特定参数
elif any ( _ in " %s \n %s " % ( errMsg , excMsg ) for _ in ( " tamper/ " , " waf/ " , " --engagement-dojo " ) ) :
# 如果包含, 则使用logger记录这个严重错误
logger . critical ( errMsg )
# 打印空行
print ( )
# 将错误信息输出到标准输出
dataToStdout ( excMsg )
# 抛出SystemExit异常, 导致程序退出
raise SystemExit
elif any ( _ in excMsg for _ in ( " ImportError " , " ModuleNotFoundError " , " <frozen " , " Can ' t find file for module " , " SAXReaderNotAvailable " , " <built-in function compile> returned NULL without setting an exception " , " source code string cannot contain null bytes " , " No module named " , " tp_name field " , " module ' sqlite3 ' has no attribute ' OperationalError ' " ) ) :
@ -606,21 +662,31 @@ def main():
conf . disableBanner = True
main ( )
# 检查是否是作为主模块运行,如果是,则执行以下代码
if __name__ == " __main__ " :
try :
# 尝试调用main函数
main ( )
except KeyboardInterrupt :
# 如果用户按下Ctrl+C( 键盘中断) , 则捕获KeyboardInterrupt异常, 但不执行任何操作( pass表示空操作)
pass
except SystemExit :
# 如果程序调用了sys.exit(), 则重新抛出SystemExit异常, 允许正常退出流程
raise
except :
# 捕获其他所有异常,并打印异常信息
traceback . print_exc ( )
finally :
# Reference: http://stackoverflow.com/questions/1635080/terminate-a-multi-thread-python-program
# 无论try块中的代码是否成功执行, 都会执行finally块中的代码
# 参考: http://stackoverflow.com/questions/1635080/terminate-a-multi-thread-python-program
# 检查当前线程数量是否大于1( 主线程和至少一个其他线程)
if threading . active_count ( ) > 1 :
# 如果大于1, 则调用os._exit强制退出程序, 不进行清理操作
# getattr(os, "_exitcode", 0)用于获取os模块的_exitcode属性, 如果不存在则默认为0
os . _exit ( getattr ( os , " _exitcode " , 0 ) )
else :
# 如果只有主线程,则正常退出程序
sys . exit ( getattr ( os , " _exitcode " , 0 ) )
else :
# cancelling postponed imports (because of CI/CD checks)
# 如果不是作为主模块运行, 则取消延迟导入( 因为CI/CD检查)
__import__ ( " lib.controller.controller " )