Merge branch 'wangshenghui_branch' of https://bdgit.educoder.net/ptnqoxywl/sqlmap into wangshenghui_branch

wangshenghui_branch
Warmlight 3 months ago
commit 839e534304

Binary file not shown.

@ -9,96 +9,114 @@ See the file 'LICENSE' for copying permission
import os
import sys
import wave
import wave # 用于处理 WAV 文件格式
# 指定蜂鸣音频文件的路径
BEEP_WAV_FILENAME = os.path.join(os.path.dirname(__file__), "beep.wav")
def beep():
"""根据操作系统播放蜂鸣声。"""
try:
# 检测操作系统并调用相应的播放方法
if sys.platform.startswith("win"):
_win_wav_play(BEEP_WAV_FILENAME)
_win_wav_play(BEEP_WAV_FILENAME) # Windows 系统使用 WAV 播放
elif sys.platform.startswith("darwin"):
_mac_beep()
_mac_beep() # macOS 系统使用系统蜂鸣
elif sys.platform.startswith("cygwin"):
_cygwin_beep(BEEP_WAV_FILENAME)
_cygwin_beep(BEEP_WAV_FILENAME) # Cygwin 使用音频文件播放
elif any(sys.platform.startswith(_) for _ in ("linux", "freebsd")):
_linux_wav_play(BEEP_WAV_FILENAME)
_linux_wav_play(BEEP_WAV_FILENAME) # Linux 和 FreeBSD 系统使用 WAV 播放
else:
_speaker_beep()
_speaker_beep() # 其他系统使用控制台蜂鸣
except:
# 捕获异常并使用控制台蜂鸣
_speaker_beep()
def _speaker_beep():
sys.stdout.write('\a') # doesn't work on modern Linux systems
"""在控制台播放蜂鸣声(警报声)。"""
sys.stdout.write('\a') # 在现代 Linux 系统上可能无效
try:
sys.stdout.flush()
sys.stdout.flush() # 尝试刷新标准输出
except IOError:
pass
pass # 忽略任何 I/O 错误
# Reference: https://lists.gnu.org/archive/html/emacs-devel/2014-09/msg00815.html
# Cygwin 使用系统命令播放音频文件
def _cygwin_beep(filename):
os.system("play-sound-file '%s' 2>/dev/null" % filename)
# macOS 系统使用 Carbon 库的 SysBeep 函数
def _mac_beep():
import Carbon.Snd
Carbon.Snd.SysBeep(1)
import Carbon.Snd # 导入 Carbon 库
Carbon.Snd.SysBeep(1) # 播放系统蜂鸣声
# Windows 系统播放 WAV 文件
def _win_wav_play(filename):
import winsound
import winsound # 导入 winsound 库
winsound.PlaySound(filename, winsound.SND_FILENAME)
winsound.PlaySound(filename, winsound.SND_FILENAME) # 播放指定的 WAV 文件
# Linux 系统播放 WAV 文件的实现
def _linux_wav_play(filename):
# 尝试使用不同的命令播放音频文件
for _ in ("aplay", "paplay", "play"):
if not os.system("%s '%s' 2>/dev/null" % (_, filename)):
return
return # 成功播放音乐后返回
import ctypes
import ctypes # 导入 ctypes 库以调用 C 函数
# PulseAudio 的相关常量定义
PA_STREAM_PLAYBACK = 1
PA_SAMPLE_S16LE = 3
BUFFSIZE = 1024
BUFFSIZE = 1024 # 缓冲区大小
# 定义 PulseAudio 样本规格的结构
class struct_pa_sample_spec(ctypes.Structure):
_fields_ = [("format", ctypes.c_int), ("rate", ctypes.c_uint32), ("channels", ctypes.c_uint8)]
try:
pa = ctypes.cdll.LoadLibrary("libpulse-simple.so.0")
pa = ctypes.cdll.LoadLibrary("libpulse-simple.so.0") # 加载 PulseAudio 库
except OSError:
return
return # 如果加载失败,则返回
# 打开 WAV 文件
wave_file = wave.open(filename, "rb")
# 设置 PulseAudio 样本规格
pa_sample_spec = struct_pa_sample_spec()
pa_sample_spec.rate = wave_file.getframerate()
pa_sample_spec.channels = wave_file.getnchannels()
pa_sample_spec.format = PA_SAMPLE_S16LE
pa_sample_spec.rate = wave_file.getframerate() # 获取采样频率
pa_sample_spec.channels = wave_file.getnchannels() # 获取声道数
pa_sample_spec.format = PA_SAMPLE_S16LE # 设置样本格式
error = ctypes.c_int(0)
pa_stream = pa.pa_simple_new(None, filename, PA_STREAM_PLAYBACK, None, "playback", ctypes.byref(pa_sample_spec), None, None, ctypes.byref(error))
# 创建 PulseAudio 流
pa_stream = pa.pa_simple_new(None, filename, PA_STREAM_PLAYBACK, None,
"playback", ctypes.byref(pa_sample_spec), None, None, ctypes.byref(error))
if not pa_stream:
raise Exception("Could not create pulse audio stream: %s" % pa.strerror(ctypes.byref(error)))
while True:
# 获取延迟
latency = pa.pa_simple_get_latency(pa_stream, ctypes.byref(error))
if latency == -1:
raise Exception("Getting latency failed")
buf = wave_file.readframes(BUFFSIZE)
buf = wave_file.readframes(BUFFSIZE) # 从 WAV 文件读取帧
if not buf:
break
break # 如果没有更多帧可读,退出循环
# 播放读取的帧
if pa.pa_simple_write(pa_stream, buf, len(buf), ctypes.byref(error)):
raise Exception("Could not play file")
wave_file.close()
wave_file.close() # 关闭 WAV 文件
# 确保所有数据都已播放完成
if pa.pa_simple_drain(pa_stream, ctypes.byref(error)):
raise Exception("Could not simple drain")
pa.pa_simple_free(pa_stream)
pa.pa_simple_free(pa_stream) # 释放 PulseAudio 流资源
if __name__ == "__main__":
beep()
beep() # 调用蜂鸣函数

@ -7,82 +7,99 @@ Copyright (c) 2006-2024 sqlmap developers (https://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""
from __future__ import print_function
from __future__ import print_function # 兼容 Python 2 和 3 的 print 函数
import os
import struct
import sys
import zlib
import zlib # 用于数据压缩和解压缩
from optparse import OptionError
from optparse import OptionParser
# 在 Python 3 中定义 xrange 和 ord 的兼容
if sys.version_info >= (3, 0):
xrange = range
ord = lambda _: _
xrange = range # 使用 Python 3 的 range
ord = lambda _: _ # 在 Python 3 中直接使用字符
KEY = b"E6wRbVhD0IBeCiGJ"
KEY = b"E6wRbVhD0IBeCiGJ" # 定义加密/解密的密钥
def xor(message, key):
"""执行 XOR 操作,返回加密或解密后的字节序列。"""
# 对 message 的每个字节进行 XOR 运算,并返回字节串
return b"".join(struct.pack('B', ord(message[i]) ^ ord(key[i % len(key)])) for i in range(len(message)))
def cloak(inputFile=None, data=None):
"""对输入文件或数据进行加密和压缩。"""
if data is None:
# 如果没有提供数据,则读取文件内容
with open(inputFile, "rb") as f:
data = f.read()
data = f.read() # 以二进制模式读取文件数据
# 对数据进行压缩后再使用 XOR 加密
return xor(zlib.compress(data), KEY)
def decloak(inputFile=None, data=None):
"""对输入文件或数据进行解密和解压缩。"""
if data is None:
# 如果没有提供数据,则读取文件内容
with open(inputFile, "rb") as f:
data = f.read()
try:
# 首先对数据进行 XOR 解密,然后解压缩
data = zlib.decompress(xor(data, KEY))
except Exception as ex:
# 如果解压缩过程中发生异常,打印错误信息并退出
print(ex)
print('ERROR: the provided input file \'%s\' does not contain valid cloaked content' % inputFile)
sys.exit(1)
finally:
f.close()
f.close() # 确保文件流被关闭
return data
return data # 返回解密后的数据
def main():
usage = '%s [-d] -i <input file> [-o <output file>]' % sys.argv[0]
parser = OptionParser(usage=usage, version='0.2')
"""主函数,负责解析命令行参数并执行加密或解密操作。"""
usage = '%s [-d] -i <input file> [-o <output file>]' % sys.argv[0] # 使用说明
parser = OptionParser(usage=usage, version='0.2') # 创建 OptionParser 对象
try:
parser.add_option('-d', dest='decrypt', action="store_true", help='Decrypt')
parser.add_option('-i', dest='inputFile', help='Input file')
parser.add_option('-o', dest='outputFile', help='Output file')
# 添加命令行选项
parser.add_option('-d', dest='decrypt', action="store_true", help='Decrypt') # 解密选项
parser.add_option('-i', dest='inputFile', help='Input file') # 输入文件选项
parser.add_option('-o', dest='outputFile', help='Output file') # 输出文件选项
(args, _) = parser.parse_args()
(args, _) = parser.parse_args() # 解析命令行参数
if not args.inputFile:
parser.error('Missing the input file, -h for help')
parser.error('Missing the input file, -h for help') # 如果未提供输入文件,则报错
except (OptionError, TypeError) as ex:
parser.error(ex)
parser.error(ex) # 捕获解析错误
# 检查输入文件是否存在
if not os.path.isfile(args.inputFile):
print('ERROR: the provided input file \'%s\' is non existent' % args.inputFile)
sys.exit(1)
# 根据是否需要解密选择处理函数
if not args.decrypt:
data = cloak(args.inputFile)
data = cloak(args.inputFile) # 加密文件内容
else:
data = decloak(args.inputFile)
data = decloak(args.inputFile) # 解密文件内容
# 如果未指定输出文件名,则根据是否解密自动生成
if not args.outputFile:
if not args.decrypt:
args.outputFile = args.inputFile + '_'
args.outputFile = args.inputFile + '_' # 添加后缀表示加密
else:
args.outputFile = args.inputFile[:-1]
args.outputFile = args.inputFile[:-1] # 移除后缀表示解密
# 写入结果到输出文件
f = open(args.outputFile, 'wb')
f.write(data)
f.close()
f.write(data) # 写入数据
f.close() # 关闭文件
if __name__ == '__main__':
main()
main() # 程序入口

@ -7,7 +7,7 @@ Copyright (c) 2006-2024 sqlmap developers (https://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""
from __future__ import print_function
from __future__ import print_function # 兼容 Python 2 和 3 的 print 函数
import os
import sys
@ -16,81 +16,97 @@ from optparse import OptionError
from optparse import OptionParser
def convert(inputFile):
fileStat = os.stat(inputFile)
fileSize = fileStat.st_size
"""将给定的二进制输入文件转换为 ASCII 调试脚本。"""
fileStat = os.stat(inputFile) # 获取文件状态
fileSize = fileStat.st_size # 获取文件大小
# 检查文件大小是否超过 65280 字节(可调试的最大限制)
if fileSize > 65280:
print("ERROR: the provided input file '%s' is too big for debug.exe" % inputFile)
sys.exit(1)
sys.exit(1) # 如果文件太大,退出程序
script = "n %s\nr cx\n" % os.path.basename(inputFile.replace(".", "_"))
script += "%x\nf 0100 ffff 00\n" % fileSize
scrString = ""
counter = 256
counter2 = 0
# 开始构建调试脚本
script = "n %s\nr cx\n" % os.path.basename(inputFile.replace(".", "_")) # 设置脚本名称
script += "%x\nf 0100 ffff 00\n" % fileSize # 写入文件大小信息
scrString = "" # 用于构建写入命令
counter = 256 # 地址计数器从 256 开始
counter2 = 0 # 0 计数器,用于控制输出的字符数
# 读取输入文件的二进制内容
fp = open(inputFile, "rb")
fileContent = fp.read()
fileContent = fp.read() # 读取所有内容
# 遍历文件的每个字节
for fileChar in fileContent:
# 在 Python 3 中字符是字节,直接使用;在 Python 2 中需要使用 ord() 函数
unsignedFileChar = fileChar if sys.version_info >= (3, 0) else ord(fileChar)
# 如果字符不是空字节0则进行处理
if unsignedFileChar != 0:
counter2 += 1
counter2 += 1 # 增加有效字符计数
if not scrString:
# 如果 scrString 为空,开始创建新的写入命令
scrString = "e %0x %02x" % (counter, unsignedFileChar)
else:
# 否则,将字符附加到 scrString 中
scrString += " %02x" % unsignedFileChar
elif scrString:
# 如果遇到空字节,且 scrString 中有内容,需要把当前 scrString 添加到脚本
script += "%s\n" % scrString
scrString = ""
counter2 = 0
scrString = "" # 清空 scrString
counter2 = 0 # 重置有效字符计数
counter += 1
counter += 1 # 增加地址计数器
# 每 20 个有效字符输出一次
if counter2 == 20:
script += "%s\n" % scrString
scrString = ""
counter2 = 0
script += "%s\n" % scrString # 将当前 scrString 加入脚本
scrString = "" # 清空 scrString
counter2 = 0 # 重置计数
# 完成脚本,添加结束指令
script += "w\nq\n"
return script
return script # 返回生成的调试脚本
def main(inputFile, outputFile):
"""主功能,处理文件输入输出。"""
# 检查输入文件是否是常规文件
if not os.path.isfile(inputFile):
print("ERROR: the provided input file '%s' is not a regular file" % inputFile)
sys.exit(1)
sys.exit(1) # 如果不是,退出程序
# 调用转换函数
script = convert(inputFile)
# 如果提供了输出文件,写入脚本
if outputFile:
fpOut = open(outputFile, "w")
sys.stdout = fpOut
sys.stdout.write(script)
sys.stdout.close()
with open(outputFile, "w") as fpOut:
sys.stdout = fpOut # 将标准输出重定向到输出文件
sys.stdout.write(script) # 写入脚本内容
sys.stdout.close() # 关闭文件
else:
print(script)
print(script) # 如果没有输出文件,直接打印脚本
if __name__ == "__main__":
usage = "%s -i <input file> [-o <output file>]" % sys.argv[0]
parser = OptionParser(usage=usage, version="0.1")
usage = "%s -i <input file> [-o <output file>]" % sys.argv[0] # 程序用法说明
parser = OptionParser(usage=usage, version="0.1") # 创建解析器
try:
parser.add_option("-i", dest="inputFile", help="Input binary file")
parser.add_option("-o", dest="outputFile", help="Output debug.exe text file")
# 添加命令行选项
parser.add_option("-i", dest="inputFile", help="Input binary file") # 输入文件
parser.add_option("-o", dest="outputFile", help="Output debug.exe text file") # 输出文件
(args, _) = parser.parse_args()
(args, _) = parser.parse_args() # 解析参数
if not args.inputFile:
parser.error("Missing the input file, -h for help")
parser.error("Missing the input file, -h for help") # 必须提供输入文件
except (OptionError, TypeError) as ex:
parser.error(ex)
parser.error(ex) # 捕获错误并报告
inputFile = args.inputFile
outputFile = args.outputFile
inputFile = args.inputFile # 输入文件名
outputFile = args.outputFile # 输出文件名
main(inputFile, outputFile)
main(inputFile, outputFile) # 调用主函数

@ -5,7 +5,6 @@
#
# Copyright (c) 2010, Bernardo Damele A. G. <bernardo.damele@gmail.com>
#
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
@ -28,117 +27,117 @@ def setNonBlocking(fd):
"""
Make a file descriptor non-blocking
"""
import fcntl # 导入用于文件控制选项的库
import fcntl
flags = fcntl.fcntl(fd, fcntl.F_GETFL)
flags = flags | os.O_NONBLOCK
fcntl.fcntl(fd, fcntl.F_SETFL, flags)
flags = fcntl.fcntl(fd, fcntl.F_GETFL) # 获取当前文件描述符的状态标志
flags = flags | os.O_NONBLOCK # 将非阻塞标志添加到当前标志
fcntl.fcntl(fd, fcntl.F_SETFL, flags) # 设置文件描述符为非阻塞模式
def main(src, dst):
"""主程序函数,用于设置 ICMP socket 和处理命令。"""
if sys.platform == "nt":
sys.stderr.write('icmpsh master can only run on Posix systems\n')
sys.stderr.write('icmpsh master can only run on Posix systems\n') # 检查是否在 Windows 上运行
sys.exit(255)
try:
from impacket import ImpactDecoder
from impacket import ImpactPacket
from impacket import ImpactDecoder # 导入 Impacket 库用于解析数据包
from impacket import ImpactPacket # 导入 Impacket 用于构建数据包
except ImportError:
sys.stderr.write('You need to install Python Impacket library first\n')
sys.stderr.write('You need to install Python Impacket library first\n') # 检查是否安装 Impacket
sys.exit(255)
# Make standard input a non-blocking file
stdin_fd = sys.stdin.fileno()
# 将标准输入设置为非阻塞
stdin_fd = sys.stdin.fileno() # 获取标准输入的文件描述符
setNonBlocking(stdin_fd)
# Open one socket for ICMP protocol
# A special option is set on the socket so that IP headers are included
# with the returned data
# 为 ICMP 协议打开一个 socket
try:
sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP)
sock = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_ICMP) # 创建原始 ICMP socket
except socket.error:
sys.stderr.write('You need to run icmpsh master with administrator privileges\n')
sys.stderr.write('You need to run icmpsh master with administrator privileges\n') # 检查运行权限
sys.exit(1)
sock.setblocking(0)
sock.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)
sock.setblocking(0) # 设置 socket 为非阻塞模式
sock.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) # 启用 IP 头包含在发送包中
# Create a new IP packet and set its source and destination addresses
# 创建一个新的 IP 包,设置源和目的地址
ip = ImpactPacket.IP()
ip.set_ip_src(src)
ip.set_ip_dst(dst)
ip.set_ip_src(src) # 设置源 IP
ip.set_ip_dst(dst) # 设置目标 IP
# Create a new ICMP packet of type ECHO REPLY
# 创建一个新的 ICMP 包类型为回显应答ECHO REPLY
icmp = ImpactPacket.ICMP()
icmp.set_icmp_type(icmp.ICMP_ECHOREPLY)
# Instantiate an IP packets decoder
# 实例化 IP 数据包解码器
decoder = ImpactDecoder.IPDecoder()
# 在无限循环中发送和接收命令
while True:
try:
cmd = ''
# Wait for incoming replies
if sock in select.select([sock], [], [])[0]:
buff = sock.recv(4096)
# 等待输入的回复
if sock in select.select([sock], [], [])[0]: # 监控 socket 是否可读
buff = sock.recv(4096) # 接收最大 4096 字节的数据
if 0 == len(buff):
# Socket remotely closed
# 如果接收到的数据长度为 0说明对方关闭了 socket
sock.close()
sys.exit(0)
# Packet received; decode and display it
ippacket = decoder.decode(buff)
icmppacket = ippacket.child()
# 解析接收到的数据包
ippacket = decoder.decode(buff) # 解码 IP 包
icmppacket = ippacket.child() # 获取 ICMP 包
# If the packet matches, report it to the user
# 检查 ICMP 数据包的源和目的地址以及类型
if ippacket.get_ip_dst() == src and ippacket.get_ip_src() == dst and 8 == icmppacket.get_icmp_type():
# Get identifier and sequence number
# 获取标识符和序列号
ident = icmppacket.get_icmp_id()
seq_id = icmppacket.get_icmp_seq()
data = icmppacket.get_data_as_string()
data = icmppacket.get_data_as_string() # 获取数据
if len(data) > 0:
sys.stdout.write(data)
sys.stdout.write(data) # 输出接收到的数据
# Parse command from standard input
# 从标准输入读取命令
try:
cmd = sys.stdin.readline()
cmd = sys.stdin.readline() # 读取用户输入的命令
except:
pass
if cmd == 'exit\n':
if cmd == 'exit\n': # 如果输入为 'exit',退出循环
return
# Set sequence number and identifier
# 设置序列号和标识符,以便回复
icmp.set_icmp_id(ident)
icmp.set_icmp_seq(seq_id)
# Include the command as data inside the ICMP packet
# 将命令作为数据包含在 ICMP 包中
icmp.contains(ImpactPacket.Data(cmd))
# Calculate its checksum
# 计算 ICMP 包的校验和
icmp.set_icmp_cksum(0)
icmp.auto_checksum = 1
icmp.auto_checksum = 1 # 自动计算校验和
# Have the IP packet contain the ICMP packet (along with its payload)
# 将 ICMP 包插入到 IP 包中
ip.contains(icmp)
try:
# Send it to the target host
# 发送数据包到目标主机
sock.sendto(ip.get_packet(), (dst, 0))
except socket.error as ex:
sys.stderr.write("'%s'\n" % ex)
sys.stderr.write("'%s'\n" % ex) # 输出错误信息
sys.stderr.flush()
except:
break
if __name__ == '__main__':
# 检查参数,确保提供了源 IP 和目标 IP
if len(sys.argv) < 3:
msg = 'missing mandatory options. Execute as root:\n'
msg += './icmpsh-m.py <source IP address> <destination IP address>\n'
sys.stderr.write(msg)
sys.exit(1)
main(sys.argv[1], sys.argv[2])
main(sys.argv[1], sys.argv[2]) # 调用主函数,传入源和目标 IP

@ -2,7 +2,7 @@
runcmd - a program for running command prompt commands
Copyright (C) 2010 Miroslav Stampar
email: miroslav.stampar@gmail.com
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
@ -25,22 +25,27 @@
#include <string>
using namespace std;
int main(int argc, char* argv[])
{
FILE *fp;
string cmd;
FILE *fp;
string cmd;
for( int count = 1; count < argc; count++ )
cmd += " " + string(argv[count]);
// 从命令行参数获取命令并构建完整的命令字符串
for (int count = 1; count < argc; count++)
cmd += " " + string(argv[count]); // 将每个参数添加到 cmd 字符串中,并用空格分隔
// 使用 _popen() 函数以只读的方式打开一个命令进程
fp = _popen(cmd.c_str(), "r");
// 检查文件指针是否有效
if (fp != NULL) {
char buffer[BUFSIZ];
char buffer[BUFSIZ]; // 声明一个缓冲区用于接收输出
// 读取命令的输出并将其写到标准输出
while (fgets(buffer, sizeof buffer, fp) != NULL)
fputs(buffer, stdout);
fputs(buffer, stdout); // 将缓冲区的内容输出到控制台
}
return 0;
}
}

@ -3,28 +3,32 @@
# Copyright (c) 2006-2024 sqlmap developers (https://sqlmap.org/)
# See the file 'LICENSE' for copying permission
# Removes duplicate entries in wordlist like files
# Removes duplicate entries in wordlist-like files
from __future__ import print_function
from __future__ import print_function # 确保使用 Python 3 的 print() 函数
import sys
import sys # 导入系统模块,用于处理命令行参数和文件操作
if __name__ == "__main__":
# 检查程序是否接收到至少一个命令行参数
if len(sys.argv) > 1:
items = list()
items = list() # 初始化一个列表用于存储唯一条目
# 打开指定的文件进行读取
with open(sys.argv[1], 'r') as f:
for item in f:
item = item.strip()
for item in f: # 遍历文件中的每一行
item = item.strip() # 去掉行首尾的空白字符
try:
str.encode(item)
if item in items:
if item:
print(item)
str.encode(item) # 尝试对字符串编码,确保内容是有效的字符串
if item in items: # 检查条目是否已经在列表中
if item: # 确保条目不为空
print(item) # 打印重复的条目
else:
items.append(item)
items.append(item) # 如果条目不在列表中,则添加到列表
except:
pass
pass # 捕获异常,继续处理下一个条目
# 以写入模式打开同一个文件,准备写入去重后的唯一条目
with open(sys.argv[1], 'w+') as f:
f.writelines("\n".join(items))
f.writelines("\n".join(items)) # 将唯一条目写回文件,以换行符分隔

@ -6,25 +6,30 @@ import os
import sys
def check(filepath):
if filepath.endswith(".py"):
content = open(filepath, "rb").read()
pattern = "\n\n\n".encode("ascii")
# 检查给定路径的文件
if filepath.endswith(".py"): # 检查文件扩展名是否为 .py
content = open(filepath, "rb").read() # 以二进制模式打开文件并读取全部内容
pattern = "\n\n\n".encode("ascii") # 定义一个二进制模式的换行符序列,表示三个换行符
# 检查内容中是否包含三个连续的换行符
if pattern in content:
index = content.find(pattern)
index = content.find(pattern) # 找到模式在内容中的第一个出现位置
# 打印文件路径和模式前后各 30 个字节的内容
print(filepath, repr(content[index - 30:index + 30]))
if __name__ == "__main__":
try:
BASE_DIRECTORY = sys.argv[1]
except IndexError:
BASE_DIRECTORY = sys.argv[1] # 尝试获取命令行中指定的目录路径
except IndexError: # 如果没有指定目录参数
print("no directory specified, defaulting to current working directory")
BASE_DIRECTORY = os.getcwd()
BASE_DIRECTORY = os.getcwd() # 使用当前工作目录作为默认目录
print("looking for *.py scripts in subdirectories of '%s'" % BASE_DIRECTORY)
# 遍历指定目录及其子目录中的所有文件
for root, dirs, files in os.walk(BASE_DIRECTORY):
# 如果路径中包含 "extra" 或 "thirdparty",则跳过该目录
if any(_ in root for _ in ("extra", "thirdparty")):
continue
for name in files:
filepath = os.path.join(root, name)
check(filepath)
for name in files: # 遍历文件列表
filepath = os.path.join(root, name) # 构建文件的完整路径
check(filepath) # 调用 check 函数检查该文件

@ -6,6 +6,9 @@ vulnserver.py - Trivial SQLi vulnerable HTTP server (Note: for testing purposes)
Copyright (c) 2006-2024 sqlmap developers (https://sqlmap.org/)
See the file 'LICENSE' for copying permission
"""
# 该脚本实现了一个简单的 HTTP 服务器,故意留下 SQL 注入漏洞,供测试和学习之用。
# 它展示了基本的 Web 服务器如何处理请求、解析参数以及如何与 SQLite 数据库交互。
# 此类工具应仅在安全的实验环境中使用,以避免滥用和安全风险。在实际应用中,开发者应注意保护数据库查询以防止 SQL 注入攻击。
from __future__ import print_function
@ -17,29 +20,26 @@ import sys
import threading
import traceback
# 检查 Python 版本
PY3 = sys.version_info >= (3, 0)
UNICODE_ENCODING = "utf-8"
DEBUG = False
UNICODE_ENCODING = "utf-8" # 定义 Unicode 编码
DEBUG = False # 调试模式标志
if PY3:
from http.client import INTERNAL_SERVER_ERROR
from http.client import NOT_FOUND
from http.client import OK
from http.server import BaseHTTPRequestHandler
from http.server import HTTPServer
# 导入 Python 3 中的 HTTP 相关模块
from http.client import INTERNAL_SERVER_ERROR, NOT_FOUND, OK
from http.server import BaseHTTPRequestHandler, HTTPServer
from socketserver import ThreadingMixIn
from urllib.parse import parse_qs
from urllib.parse import unquote_plus
from urllib.parse import parse_qs, unquote_plus
else:
from BaseHTTPServer import BaseHTTPRequestHandler
from BaseHTTPServer import HTTPServer
from httplib import INTERNAL_SERVER_ERROR
from httplib import NOT_FOUND
from httplib import OK
# 对于 Python 2导入相应的 HTTP 相关模块
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
from httplib import INTERNAL_SERVER_ERROR, NOT_FOUND, OK
from SocketServer import ThreadingMixIn
from urlparse import parse_qs
from urllib import unquote_plus
# SQLite 模式定义,创建用户表并插入示例数据
SCHEMA = """
CREATE TABLE users (
id INTEGER,
@ -54,9 +54,11 @@ SCHEMA = """
INSERT INTO users (id, name, surname) VALUES (5, NULL, 'nameisnull');
"""
# 定义监听地址和端口
LISTEN_ADDRESS = "localhost"
LISTEN_PORT = 8440
# 全局变量
_conn = None
_cursor = None
_lock = None
@ -68,13 +70,15 @@ def init(quiet=False):
global _cursor
global _lock
# 在内存中创建 SQLite 数据库连接
_conn = sqlite3.connect(":memory:", isolation_level=None, check_same_thread=False)
_cursor = _conn.cursor()
_lock = threading.Lock()
_cursor = _conn.cursor() # 创建游标,用于执行 SQL 命令
_lock = threading.Lock() # 创建线程锁,以处理多线程环境下的数据库访问
_cursor.executescript(SCHEMA)
_cursor.executescript(SCHEMA) # 执行脚本以创建表并插入数据
if quiet:
# 如果 quiet 为 True则禁止输出
global print
def _(*args, **kwargs):
@ -83,6 +87,7 @@ def init(quiet=False):
print = _
class ThreadingServer(ThreadingMixIn, HTTPServer):
# 允许多线程处理 HTTP 请求
def finish_request(self, *args, **kwargs):
try:
HTTPServer.finish_request(self, *args, **kwargs)
@ -91,13 +96,16 @@ class ThreadingServer(ThreadingMixIn, HTTPServer):
traceback.print_exc()
class ReqHandler(BaseHTTPRequestHandler):
# 请求处理类
def do_REQUEST(self):
# 处理请求,分割路径和查询字符串
path, query = self.path.split('?', 1) if '?' in self.path else (self.path, "")
params = {}
if query:
params.update(parse_qs(query))
params.update(parse_qs(query)) # 解析查询字符串为字典
# 检查是否出现恶意脚本
if "<script>" in unquote_plus(query):
self.send_response(INTERNAL_SERVER_ERROR)
self.send_header("X-Powered-By", "Express")
@ -106,18 +114,25 @@ class ReqHandler(BaseHTTPRequestHandler):
self.wfile.write("CLOUDFLARE_ERROR_500S_BOX".encode(UNICODE_ENCODING))
return
# 处理请求数据(如果有)
if hasattr(self, "data"):
if self.data.startswith('{') and self.data.endswith('}'):
params.update(json.loads(self.data))
params.update(json.loads(self.data)) # JSON 数据
elif self.data.startswith('<') and self.data.endswith('>'):
params.update(dict((_[0], _[1].replace("&apos;", "'").replace("&quot;", '"').replace("&lt;", '<').replace("&gt;", '>').replace("&amp;", '&')) for _ in re.findall(r'name="([^"]+)" value="([^"]*)"', self.data)))
# 解析 HTML 表单数据
params.update(dict((_[0], _[1].replace("&apos;", "'").replace("&quot;", '"')
.replace("&lt;", '<').replace("&gt;", '>').replace("&amp;", '&'))
for _ in re.findall(r'name="([^"]+)" value="([^"]*)"', self.data)))
else:
self.data = self.data.replace(';', '&') # Note: seems that Python3 started ignoring parameter splitting with ';'
# 处理 URL 编码数据
self.data = self.data.replace(';', '&') # 兼容性处理
params.update(parse_qs(self.data))
# 处理请求头参数
for name in self.headers:
params[name.lower()] = self.headers[name]
# 处理 Cookie 参数
if "cookie" in params:
for part in params["cookie"].split(';'):
part = part.strip()
@ -125,14 +140,17 @@ class ReqHandler(BaseHTTPRequestHandler):
name, value = part.split('=', 1)
params[name.strip()] = unquote_plus(value.strip())
# 将多值参数转换为单值
for key in params:
if params[key] and isinstance(params[key], (tuple, list)):
params[key] = params[key][-1]
self.url, self.params = path, params
self.url, self.params = path, params # 存储 URL 和参数
if self.url == '/':
# 主页处理
if not any(_ in self.params for _ in ("id", "query")):
# 如果没有 ID 或查询参数,则显示主页面
self.send_response(OK)
self.send_header("Content-type", "text/html; charset=%s" % UNICODE_ENCODING)
self.send_header("Connection", "close")
@ -142,27 +160,33 @@ class ReqHandler(BaseHTTPRequestHandler):
code, output = OK, ""
try:
# 处理回显参数
if self.params.get("echo", ""):
output += "%s<br>" % self.params["echo"]
if self.params.get("reflect", ""):
output += "%s<br>" % self.params.get("id")
with _lock:
with _lock: # 使用锁来确保线程安全
if "query" in self.params:
# 执行任意 SQL 查询
_cursor.execute(self.params["query"])
elif "id" in self.params:
# 通过 ID 查询用户
if "base64" in self.params:
_cursor.execute("SELECT * FROM users WHERE id=%s LIMIT 0, 1" % base64.b64decode("%s===" % self.params["id"], altchars=self.params.get("altchars")).decode())
_cursor.execute("SELECT * FROM users WHERE id=%s LIMIT 0, 1" %
base64.b64decode("%s===" % self.params["id"],
altchars=self.params.get("altchars")).decode())
else:
_cursor.execute("SELECT * FROM users WHERE id=%s LIMIT 0, 1" % self.params["id"])
results = _cursor.fetchall()
results = _cursor.fetchall() # 获取查询结果
output += "<b>SQL results:</b><br>\n"
# 根据查询结果决定响应的状态码和内容
if self.params.get("code", ""):
if not results:
code = INTERNAL_SERVER_ERROR
code = INTERNAL_SERVER_ERROR # 出错
else:
if results:
output += "<table border=\"1\">\n"
@ -175,15 +199,16 @@ class ReqHandler(BaseHTTPRequestHandler):
output += "</table>\n"
else:
output += "no results found"
output += "no results found" # 查询无结果
output += "</body></html>"
except Exception as ex:
code = INTERNAL_SERVER_ERROR
# 捕获异常并返回错误信息
output = "%s: %s" % (re.search(r"'([^']+)'", str(type(ex))).group(1), ex)
# 发送响应
self.send_response(code)
self.send_header("Content-type", "text/html")
self.send_header("Connection", "close")
@ -194,26 +219,30 @@ class ReqHandler(BaseHTTPRequestHandler):
self.end_headers()
self.wfile.write(output if isinstance(output, bytes) else output.encode(UNICODE_ENCODING))
else:
# 对于未定义的路径返回 404
self.send_response(NOT_FOUND)
self.send_header("Connection", "close")
self.end_headers()
def do_GET(self):
self.do_REQUEST()
self.do_REQUEST() # 处理 GET 请求
def do_PUT(self):
self.do_POST()
self.do_POST() # 处理 PUT 请求
def do_HEAD(self):
self.do_REQUEST()
self.do_REQUEST() # 处理 HEAD 请求
def do_POST(self):
# 处理 POST 请求
length = int(self.headers.get("Content-length", 0))
if length:
# 读取请求体数据
data = self.rfile.read(length)
data = unquote_plus(data.decode(UNICODE_ENCODING, "ignore"))
self.data = data
elif self.headers.get("Transfer-encoding") == "chunked":
# 处理 chunked 请求
data, line = b"", b""
count = 0
@ -232,10 +261,10 @@ class ReqHandler(BaseHTTPRequestHandler):
self.data = data.decode(UNICODE_ENCODING, "ignore")
self.do_REQUEST()
self.do_REQUEST() # 处理 POST 逻辑
def log_message(self, format, *args):
return
return # 不记录日志
def run(address=LISTEN_ADDRESS, port=LISTEN_PORT):
global _alive
@ -244,16 +273,17 @@ def run(address=LISTEN_ADDRESS, port=LISTEN_PORT):
_alive = True
_server = ThreadingServer((address, port), ReqHandler)
print("[i] running HTTP server at 'http://%s:%d'" % (address, port))
_server.serve_forever()
_server.serve_forever() # 开始监听并处理请求
except KeyboardInterrupt:
_server.socket.close()
_server.socket.close() # 关闭服务器
raise
finally:
_alive = False
if __name__ == "__main__":
try:
init()
run(sys.argv[1] if len(sys.argv) > 1 else LISTEN_ADDRESS, int(sys.argv[2] if len(sys.argv) > 2 else LISTEN_PORT))
init() # 初始化数据库和服务器
run(sys.argv[1] if len(sys.argv) > 1 else LISTEN_ADDRESS,
int(sys.argv[2] if len(sys.argv) > 2 else LISTEN_PORT))
except KeyboardInterrupt:
print("\r[x] Ctrl-C received")
print("\r[x] Ctrl-C received") # 捕获 Ctrl-C 终止信号

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 964 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

@ -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")

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 439 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 864 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save