Compare commits

...

3 Commits

Binary file not shown.

@ -1,7 +1,7 @@
#!/usr/bin/env python
"""
Copyright (c) 2006-2024 sqlmap developers (https://sqlmap.org/)
Copyright (c) 2006-2024 sqlmap developers (https://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""
@ -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
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
# 如果异常信息中包含Python解
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')"
# 添加参考链接到错误信息中
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)
__import__("lib.controller.controller")
# 如果不是作为主模块运行则取消延迟导入因为CI/CD检查
__import__("lib.controller.controller")
Loading…
Cancel
Save