sqlmap源码解析(一)
打算写扫描器了 参考一下最经典的sqlmap来做
目录
主函数
在运行之前先运行了四个函数
dirtyPatches
修复了一个windows cmd下python的bug
checkEnvironment
检测了当前的运行环境
setPaths
将当前运行的环境设置为工作目录
banner
输出banner
cmdLineParser
然后通过这个来解析传入的参数
调用了一个optparse
的库来解析参数
parser.add_option_group(target)
parser.add_option_group(request)
parser.add_option_group(optimization)
parser.add_option_group(injection)
parser.add_option_group(detection)
parser.add_option_group(techniques)
parser.add_option_group(fingerprint)
parser.add_option_group(enumeration)
parser.add_option_group(brute)
parser.add_option_group(udf)
parser.add_option_group(filesystem)
parser.add_option_group(takeover)
parser.add_option_group(windows)
parser.add_option_group(general)
parser.add_option_group(miscellaneous)
总共分为这么多类
cmdLineOptions.update(cmdLineParser().__dict__)
这样传入的
然后进入initOptions(cmdLineOptions)
cmdLineOptions
就是一个字典参数包含着输入的一些东西输出看看
python sqlmap.py -u "www.bilibili.com?id=1" --dbs --random-agent --level 5
的cmdLineOptions
{'fileDest': None, 'code': None, 'getUsers': None, 'getPasswordHashes': None, 'excludeSysDbs': None, 'ignoreTimeouts': None, 'skip': None, 'prefix': None, 'osShell': None, 'googlePage': None, 'randomAgent': True, 'testSkip': None, 'authType': None, 'safeUrl': None, 'requestFile': None, 'predictOutput': None, 'wizard': None, 'stopFail': None, 'forms': None, 'uChar': None, 'secondReq': None, 'taskid': None, 'pivotColumn': None, 'preprocess': None, 'dropSetCookie': None, 'dbmsCred': None, 'getAll': None, 'risk': None, 'sqlFile': None, 'rParam': None, 'getCurrentUser': None, 'notString': None, 'getRoles': None, 'getPrivileges': None, 'testParameter': None, 'tbl': None, 'showVersion': None, 'trafficFile': None, 'forceDbms': None, 'osBof': None, 'osSmb': None, 'level': 5, 'dnsDomain': None, 'outputDir': None, 'skipWaf': None, 'timeout': None, 'firstChar': None, 'torPort': None, 'advancedHelp': None, 'charset': None, 'getComments': None, 'binaryFields': None, 'checkTor': None, 'commonTables': None, 'direct': None, 'tmpPath': None, 'titles': None, 'getSchema': None, 'timeSec': None, 'paramDel': None, 'safeReqFile': None, 'regKey': None, 'limitStart': None, 'regRead': None, 'crawlExclude': None, 'flushSession': None, 'loadCookies': None, 'csvDel': None, 'offline': None, 'method': None, 'tmpDir': None, 'fileWrite': None, 'disablePrecon': None, 'murphyRate': None, 'invalidLogical': None, 'getCurrentDb': None, 'hexConvert': None, 'proxyFile': None, 'mobile': None, 'answers': None, 'host': None, 'dependencies': None, 'cookie': None, 'proxy': None, 'updateAll': None, 'regexp': None, 'repair': None, 'optimize': None, 'limitStop': None, 'search': None, 'shLib': None, 'uFrom': None, 'noCast': None, 'testFilter': None, 'ignoreCode': None, 'eta': None, 'csrfToken': None, 'threads': None, 'logFile': None, 'os': None, 'col': None, 'user': None, 'proxyCred': None, 'verbose': None, 'crawlDepth': None, 'encoding': None, 'privEsc': None, 'forceDns': None, 'paramExclude': None, 'base64Parameter': None, 'header': None, 'api': None, 'hashFile': None, 'invalidBignum': None, 'regType': None, 'getDbs': True, 'freshQueries': None, 'uCols': None, 'smokeTest': None, 'regData': None, 'udfInject': None, 'invalidString': None, 'tor': None, 'forceSSL': None, 'beep': None, 'disableColoring': None, 'configFile': None, 'delay': None, 'scope': None, 'authFile': None, 'isDba': None, 'torType': None, 'regVal': None, 'dummy': None, 'checkInternet': None, 'mnemonics': None, 'listTampers': None, 'skipUrlEncode': None, 'referer': None, 'liveTest': None, 'retries': None, 'extensiveFp': None, 'dumpTable': None, 'getColumns': None, 'batch': None, 'purge': None, 'headers': None, 'authCred': None, 'osCmd': None, 'suffix': None, 'smart': None, 'regDel': None, 'chunked': None, 'sitemapUrl': None, 'identifyWaf': None, 'msfPath': None, 'dumpAll': None, 'fileRead': None, 'getHostname': None, 'sessionFile': None, 'safePost': None, 'noEscape': None, 'getTables': None, 'safeFreq': None, 'agent': None, 'sqlmapShell': None, 'webRoot': None, 'exclude': None, 'lastChar': None, 'string': None, 'dbms': None, 'forceThreads': None, 'dumpWhere': None, 'tamper': None, 'ignoreRedirects': None, 'hpp': None, 'runCase': None, 'osPwn': None, 'evalCode': None, 'cleanup': None, 'csrfUrl': None, 'secondUrl': None, 'getBanner': None, 'profile': None, 'disableStats': None, 'bulkFile': None, 'db': None, 'dumpFormat': None, 'alert': None, 'harFile': None, 'nullConnection': None, 'forcePivoting': None, 'skipStatic': None, 'parseErrors': None, 'getCount': None, 'data': None, 'regAdd': None, 'ignoreProxy': None, 'database': None, 'url': u'www.bilibili.com?id=1', 'googleDork': None, 'saveConfig': None, 'sqlQuery': None, 'sqlShell': None, 'vulnTest': None, 'tech': None, 'textOnly': None, 'cookieDel': None, 'commonColumns': None, 'keepAlive': None}
传入initOptions
def initOptions(inputOptions=AttribDict(), overrideOptions=False):
_setConfAttributes()
_setKnowledgeBaseAttributes()
_mergeOptions(inputOptions, overrideOptions)
_setConfAttributes
是用来给conf做初始化的
之后所有的参数都是存在conf里面的
_setKnowledgeBaseAttributes
给kb做初始化
KnowledgeBase
_mergeOptions
用作者给的注释来解释
Merge command line options with configuration file and default options.
合并参数到conf里面
进入初始化函数init()
Set attributes into both configuration and knowledge base singletons based upon command line and configuration file options.
特别长
慢慢看
_useWizardInterface
Presents simple wizard interface for beginner users
隐藏模块
给新入门用的
将conf.wizard为True就好了
在参数里面找到了所以只需要
sqlmap --wizard就可以开启了
_setRequestFromFile
可以看到他是解析-r参数获得的数据
用
parseRequestFile
来解析请求包
parseRequestFile
Parses WebScarab and Burp logs and adds results to the target URL list
通过readCachedFileContent
函数来查询缓存
_parseBurpLog
这个是解析从burpsuite中获得的txt文件
_parseWebScarabLog
这个是捷信从webscarab中获得的文件
_parseBurpLog
平常burp用的多久看这个方法了
这一段解析了所有的请求头
\A是开头必须为string \S就可以为任何字符串后面带着:就可以
提取出所有的header
match = re.search(r"\A(%s) (.+) HTTP/[\d.]+\Z" % "|".join(getPublicTypeMembers(HTTPMETHOD, True)), line) if not method else None
if len(line.strip()) == 0 and method and method != HTTPMETHOD.GET and data is None:
data = ""
params = True
elif match:
method = match.group(1)
url = match.group(2)
if any(_ in line for _ in ('?', '=', kb.customInjectionMark)):
params = True
getPostReq = True
通过正则来匹配出method和url
if not(conf.scope and not re.search(conf.scope, url, re.I)):
yield (url, conf.method or method, data, cookie, tuple(headers))
返回的结果
将所有的结果放入
kb.secondReq
中
后记
之前也写了一点扫描器的部分参考了
https://github.com/Xyntax/POC-T
https://github.com/w-digital-scanner/
https://github.com/knownsec/pocsuite3
看了很多发现都是基于POC-T
然后POC-T又是基于sqlmap就看sqlmap了=。=