├── README.md ├── apis └── api.ini ├── common ├── __pycache__ │ ├── logger.cpython-37.pyc │ └── login.cpython-37.pyc ├── logger.py └── login.py ├── fuzzers ├── chromedriver.exe ├── fuzzer.py ├── geckodriver.exe ├── geckodriver.log ├── rtsp_fuzzer.py └── snmp_fuzzer.py ├── logs └── nvr_2019-06-03.log └── payloads ├── format_string.txt ├── overflow.txt ├── random_num.txt ├── special_char.txt └── unicode.txt /README.md: -------------------------------------------------------------------------------- 1 | 2 | https://www.cnblogs.com/lsdb/p/10958933.html -------------------------------------------------------------------------------- /apis/api.ini: -------------------------------------------------------------------------------- 1 | ; 目标主机信息配置节区 2 | [server_info] 3 | ; 要探测的IP地址 4 | ;server_ip = 10.10.15.236 5 | server_ip = 10.10.6.93 6 | ; 要探测的端口 7 | server_port = 443 8 | ; 数据包使用的协议,可以是http或https 9 | server_type = https 10 | ; 发送数据包时是否使用用户名和密码进行认证,可以是True或False 11 | use_user = True 12 | ; 发送数据包使用的用户名 13 | username = admin 14 | ; 发送数据包使用的密码 15 | password = ABcd1234 16 | ; 是否使用代理,可以是True或False 17 | use_proxy = True 18 | ; 代理协议及地址,不要使用单引号 19 | proxies = { 20 | "http":"127.0.0.1:8080", 21 | "https":"127.0.0.1:8080" 22 | } 23 | ; 日志输出位置,可以是console或file 24 | log_type = file 25 | ; 当log_type为file时用作日志文件的前辍,当log_type为console时不起作用 26 | log_file_prefix = nvr 27 | ; 要进行模糊测试的类型,及模糊测试类型对应的payload文件 28 | fuzz_payload_dict = { 29 | "overflow":"overflow.txt", 30 | "format_string": "format_string.txt", 31 | "random_num": "random_num.txt", 32 | "special_char": "special_char.txt", 33 | "unicode": "unicode.txt" 34 | } 35 | 36 | ; 协议api节区 37 | [protocol] 38 | ; 都要使用"api_name = api_format"格式,api_name是故URL用的不能随便乱写 39 | ; api_format有多行,在ini文件中后续行要以开头 40 | ; 要模糊测试的位置使用fuzz_var()包含起来即可 41 | testLogin = 42 | 43 | 44 | fuzzer_var(admin) 45 | fuzzer_var(admin) 46 | 47 | 48 | 49 | ; 第二个请求一样写 50 | editParam = 51 | 52 | 53 | 54 | fuzzer_var(manual) 55 | fuzzer_var(60) 56 | fuzzer_var(5,10,30,60,120,0) 57 | fuzzer_var(true) 58 | 59 | 60 | 61 | 62 | ; 后续请求类似前面一样继续点在后边即可 63 | -------------------------------------------------------------------------------- /common/__pycache__/logger.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrettyUp/Fuzzer/9a40d4634c08a73d39837ec684c717b398d042c5/common/__pycache__/logger.cpython-37.pyc -------------------------------------------------------------------------------- /common/__pycache__/login.cpython-37.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrettyUp/Fuzzer/9a40d4634c08a73d39837ec684c717b398d042c5/common/__pycache__/login.cpython-37.pyc -------------------------------------------------------------------------------- /common/logger.py: -------------------------------------------------------------------------------- 1 | import os 2 | import datetime 3 | import logging 4 | 5 | class LogConfig: 6 | def __init__(self, log_type="console", log_file_prefix="nvr"): 7 | # 指定日志输出到控制台时的初始化 8 | if log_type == "console": 9 | logging.basicConfig(level=logging.INFO, 10 | format='%(asctime)s %(levelname)s %(message)s', 11 | datefmt='%Y-%m-%d %H:%M:%S', 12 | ) 13 | # 指定日志输出到文件的初始化 14 | elif log_type == "file": 15 | # 创建存放日志的目录 16 | if not os.path.exists('../logs'): 17 | os.mkdir('../logs') 18 | 19 | # 操作系统本身不允许文件名包含:等特殊字符,所以这里也不要用,不然赋给filename时会报错 20 | nowTime = datetime.datetime.now().strftime('%Y-%m-%d') 21 | 22 | file_name = f'../logs/{log_file_prefix}_{nowTime}.log' 23 | file_handler = logging.FileHandler(filename=file_name,encoding = 'utf-8', mode = 'w+') 24 | # level----指定打印的日志等级;默认为WARNING;可为NOTSET、DEBUG、INFO、WARNING、ERROR、CRITICAL 25 | # format----指定整条日志的格式;这里设置为“时间-等级-日志内容” 26 | # datefmt----format中时间的格式; 27 | # filename----日志输出到的文件;默认打印到控制台 28 | # filemode----日志文件读写形式;默认为“a”;配合filename使用,如果不用filename该参数也可不用 29 | # 本来输出到文件使用filename和filemode两个参数就可以了,不需要handlers 30 | # 但是logging将日志输出到文件时中文会乱码,而logging.basicConfig又没有提供指定编码的参数,要指定编码只能使用handlers 31 | logging.basicConfig(level=logging.INFO, 32 | format='%(asctime)s %(levelname)s %(message)s', 33 | datefmt='%Y-%m-%d %H:%M:%S', 34 | # filename=file_name, 35 | # filemode='a', 36 | handlers=[file_handler], 37 | ) 38 | 39 | # self.logger = logging.getLogger() 40 | 41 | def getLogger(self): 42 | logger = logging.getLogger() 43 | return logger 44 | 45 | if __name__ == "__main__": 46 | # log_type = "console" 47 | log_type = "file" 48 | logger = LogConfig(log_type).getLogger() 49 | logger.debug('print by debug') 50 | logger.info('print by info') 51 | logger.warning('prit by warning') -------------------------------------------------------------------------------- /common/login.py: -------------------------------------------------------------------------------- 1 | import json 2 | import time 3 | from selenium import webdriver 4 | from selenium.webdriver.support.wait import WebDriverWait 5 | from selenium.webdriver.support import expected_conditions as EC 6 | from selenium.webdriver.common.by import By 7 | 8 | class GetSessionAndToken(): 9 | def __init__(self,url,username,password): 10 | # 启用无头模式,可选 11 | browser_options = webdriver.FirefoxOptions() 12 | browser_options.add_argument('--headless') 13 | browser_options.add_argument('--disable-gpu') 14 | self.browser = webdriver.Firefox(firefox_options=browser_options) 15 | # self.browser = webdriver.Chrome() 16 | self.login_system(url,username,password) 17 | 18 | # 登录系统,具体到自己系统时需要自行修改 19 | def login_system(self,url,username,password): 20 | # 登录用户名密码,改成目标系统用户名密码 21 | # username = "admin" 22 | # password = "123456" 23 | # 登录页面url,改成目标系统登录页面 24 | # url = "https://10.10.6.93/#login" 25 | self.browser.get(url) 26 | # 显性等待,直到用户名控件加载出来才进行下一步 27 | WebDriverWait(self.browser,20,0.5).until(EC.presence_of_element_located((By.ID,"txtUserName"))) 28 | # 填写用户名 29 | self.browser.find_element_by_id("txtUserName").send_keys(username) 30 | # 填写密码 31 | self.browser.find_element_by_id("txtPassword").send_keys(password) 32 | # 点击登录 33 | self.browser.find_element_by_id("btnLogin").click() 34 | # 强制等待5秒,待session和token都成功返回并存到浏览器中 35 | # restful隐性等待不太好用?self.browser.implicitly_wait(5) 36 | time.sleep(5) 37 | 38 | # 获取sessionid 39 | def get_sessionid(self): 40 | # 是要从localStorage中获取还是要从sessionStorage中获取,具体看目标系统存到哪个中 41 | # window.sessionStorage和直接写sessionStorage是等效的 42 | # 一定要使用return,不然获取到的一直是None 43 | # get的Item不一定就叫sessionId,得具体看目标系统把sessionid存到哪个变量中 44 | sessionid = self.browser.execute_script('return sessionStorage.getItem("sessionId");') 45 | 46 | # 另外sessionid一般都直接通过返回Set-Cookies头设置到Cookie中,所以也可以从Cookie读取 47 | # 获取浏览器所有Set-Cookie,返回对象是字典列表 48 | # cookies = self.browser.get_cookies() 49 | # 获取单项Cookie,是不是叫sessionId取决于系统存成什么变量,单项Cookie是字典 50 | # cookie = self.browser.get_cookie("sessionId") 51 | # cookie = cookie["value"] 52 | # print(f"{cookies}") 53 | return sessionid 54 | 55 | # 获取token 56 | def get_token(self): 57 | # 是要从localStorage中获取还是要从sessionStorage中获取,具体看目标系统存到哪个中 58 | # window.sessionStorage和直接写sessionStorage是等效的 59 | # 一定要使用return,不然获取到的一直是None 60 | # get的Item不一定就叫token,得具体看目标系统把token存到哪个变量中 61 | token = self.browser.execute_script('return sessionStorage.getItem("token");') 62 | # print(f"{token}") 63 | return token 64 | 65 | def __del__(self): 66 | # 退出程序时关闭浏览器 67 | self.browser.close() 68 | 69 | if __name__ == "__main__": 70 | obj = GetSessionAndToken() 71 | obj.login_system() 72 | sessionid = obj.get_sessionid() 73 | token = obj.get_token() 74 | print(f"sessionid为: {sessionid}\n" 75 | f"token为: {token}") -------------------------------------------------------------------------------- /fuzzers/chromedriver.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrettyUp/Fuzzer/9a40d4634c08a73d39837ec684c717b398d042c5/fuzzers/chromedriver.exe -------------------------------------------------------------------------------- /fuzzers/fuzzer.py: -------------------------------------------------------------------------------- 1 | import configparser 2 | import logging 3 | import re 4 | import requests 5 | import json 6 | from common.logger import LogConfig 7 | from common.login import GetSessionAndToken 8 | 9 | # configparser.ConfigParser的optionxform方法返回的是名称的小写,但我们这是的名称是区分大小写的 10 | # 所以我们需要重写其optionxform方法,直接保持名称原大小写返回 11 | class MyConfigParser(configparser.ConfigParser): 12 | # python不会自己调用父类init方法,所以需要手动调用一下 13 | def __init__(self, defaults=None): 14 | configparser.ConfigParser.__init__(self, defaults=defaults) 15 | 16 | def optionxform(self, optionstr): 17 | # return optionstr.lower() 18 | return optionstr 19 | 20 | class Fuzzer: 21 | def __init__(self, fuzz_config_file ="api.ini"): 22 | # 读取配置文件 23 | self.config = MyConfigParser() 24 | self.config.read(f'../apis/{fuzz_config_file}', encoding="utf-8-sig") 25 | self.fuzz_payload_dict = json.loads(self.config["server_info"]["fuzz_payload_dict"]) 26 | self.proxies = json.loads(self.config["server_info"]["proxies"]) 27 | 28 | # 设置日志格式 29 | log_type = self.config["server_info"]["log_type"] 30 | log_file_prefix = self.config["server_info"]["log_file_prefix"] 31 | LogConfig(log_type=log_type, log_file_prefix=log_file_prefix) 32 | 33 | # 设置登录URL、用户名、密码,并获取session和cookie 34 | # 需要根据自己系统修改登录逻辑,session和token的获取可能也要修复 35 | url = f'{self.config["server_info"]["server_type"]}://{self.config["server_info"]["server_ip"]}:{self.config["server_info"]["server_port"]}/#login' 36 | username = self.config["server_info"]["username"] 37 | password = self.config["server_info"]["password"] 38 | obj = GetSessionAndToken(url,username,password) 39 | sessionid = obj.get_sessionid() 40 | self.token = obj.get_token() 41 | self.fuzz_headers = { 42 | 'Host': f'{self.config["server_info"]["server_ip"]}', 43 | 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:60.0) Gecko/20100101 Firefox/60.0', 44 | 'Accept': 'application/xml, text/xml, */*; q=0.01', 45 | 'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2', 46 | 'Accept-Encoding': 'gzip, deflate', 47 | 'Referer': f'{self.config["server_info"]["server_type"]}://{self.config["server_info"]["server_ip"]}', 48 | 'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8', 49 | 'X-Requested-With': 'XMLHttpRequest', 50 | 'Cookie': f'Secure; sessionId={sessionid}', 51 | 'Connection': 'close', 52 | } 53 | 54 | 55 | # 主要的遍历逻辑 56 | def exec_fuzz(self): 57 | url_pre = f'{self.config["server_info"]["server_type"]}://{self.config["server_info"]["server_ip"]}:{self.config["server_info"]["server_port"]}/' 58 | regexp = "fuzzer_var\([^\)]*\)" 59 | # 循环所有api 60 | for api in self.config["protocol"]: 61 | url = url_pre + api 62 | org_api_data = self.config["protocol"][f"{api}"] 63 | # 在开头插入token,如果自己系统token不是这么插入的则根据自己系统进行修改 64 | org_api_data = org_api_data.replace("""clientType="WEB">""",f"""clientType="WEB">{self.token}""") 65 | # 循环模糊测试类型 66 | for payload_type,payload_file in self.fuzz_payload_dict.items(): 67 | logging.info(f"start to test {payload_type}") 68 | # 找出所有fuzz_var() 69 | fuzz_vars = re.findall(regexp, org_api_data) 70 | # 使用set去重使用list变回列表 71 | 72 | fuzz_vars = list(set(fuzz_vars)) 73 | # 遍历所有fuzz_var() 74 | for fuzz_var in fuzz_vars: 75 | 76 | # 对该变量循环具体测试类型的载荷 77 | for fuzz_payload in open(f"../payloads/{payload_file}","r",encoding="utf-8"): 78 | fuzz_payload = fuzz_payload.strip("\n") 79 | # 排除空载荷情况,因为payload文件中为了方例使用了很多空行,不排除的话空载荷会反复多次进行测试 80 | if fuzz_payload.strip() != "": 81 | # 如果是缓冲区溢出,由于我这里payload使用"A"*10等形式,所以需要先使用eval动态执行转成最终的字符串 82 | if payload_type == "overflow": 83 | fuzz_payload = eval(fuzz_payload) 84 | # 为了后边的空载荷不再把发送代码写一遍,所以这里独立出了一个参数复杂的发送函数,但自己一般不用修改所以还行吧 85 | self.send_payload(url, org_api_data, regexp, fuzz_payload,api,payload_type,fuzz_var) 86 | # 最后单独对空载荷进行测试 87 | fuzz_payload = "" 88 | self.send_payload(url,org_api_data, regexp, fuzz_payload,api,payload_type,fuzz_var) 89 | 90 | # 最终的发送函数 91 | def send_payload(self,url,org_api_data,regexp,fuzz_payload,api,payload_type,fuzz_var): 92 | # 将前遍历到的fuzz_var()修改成fuzz_var\(\),因为括号在正则中是特殊字符需要先转义才能是本身 93 | fuzz_var_fix = fuzz_var.replace("(", "\(").replace(")", "\)") 94 | # 获取当前遍历项的匹配个数 95 | count = re.findall(fuzz_var_fix,org_api_data).__len__() 96 | # 获取当前遍历项的原始值 97 | start_pos = re.search("\(", fuzz_var).end() 98 | end_pos = re.search("\)", fuzz_var).start() 99 | org_value = fuzz_var[start_pos:end_pos] 100 | # 如果匹配处不只一处 101 | for i in range(count): 102 | # 将目标位置前的匹配项都还原成原始值 103 | if i != 0: 104 | tt = re.sub(fuzz_var_fix, org_value, org_api_data,i) 105 | # 将目标位置替换成payload,最后的1表示只替换一次,这是关键 106 | tt = re.sub(fuzz_var_fix, fuzz_payload, tt,1) 107 | else: 108 | try: 109 | # 如果目标项是第一个匹配,那么tt来自于org_api_data 110 | tt = re.sub(fuzz_var_fix, fuzz_payload, org_api_data, 1) 111 | except: 112 | logging.warning(f"exception occur-{api}-{payload_type}-{fuzz_var}-{fuzz_payload}") 113 | continue 114 | # 对于剩下的所有fuzz_var\(\),进行直接删除处理 115 | tt = re.sub(regexp, self.delete_var_sign, tt) 116 | logging.info(f"{api}-{payload_type}-{fuzz_var}-{fuzz_payload}") 117 | # 检测是否使用代理 118 | if self.config["server_info"]["use_proxy"] == "True": 119 | response = requests.post(url=url, headers=self.fuzz_headers, data=tt.encode('utf-8'), verify=False, proxies=self.proxies) 120 | else: 121 | response = requests.post(url=url, headers=self.fuzz_headers, data=tt.encode('utf-8'), verify=False) 122 | logging.info(f"{api}-{payload_type}-{fuzz_var}-{fuzz_payload}-{response.status_code}") 123 | 124 | # 用于删除fuzz_var\(\),这里的\是正则中的转义 125 | def delete_var_sign(self,matched): 126 | value_org = matched.group() 127 | start_pos = re.search("\(",value_org).end() 128 | end_pos = re.search("\)",value_org).start() 129 | value = value_org[start_pos:end_pos] 130 | return value 131 | 132 | 133 | if __name__ == "__main__": 134 | fuzzer = Fuzzer() 135 | fuzzer.exec_fuzz() 136 | -------------------------------------------------------------------------------- /fuzzers/geckodriver.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrettyUp/Fuzzer/9a40d4634c08a73d39837ec684c717b398d042c5/fuzzers/geckodriver.exe -------------------------------------------------------------------------------- /fuzzers/geckodriver.log: -------------------------------------------------------------------------------- 1 | 1559526810576 mozrunner::runner INFO Running command: "d:\\Mozilla Firefox\\firefox.exe" "-marionette" "--headless" "--disable-gpu" "-foreground" "-no-remote" "-profile" "C:\\Users\\ls\\AppData\\Local\\Temp\\rust_mozprofile.MztK3mhDDrk5" 2 | *** You are running in headless mode. 3 | 1559526815908 Marionette INFO Listening on port 30252 4 | 1559526816220 Marionette WARN TLS certificate errors will be ignored for this session 5 | [Parent 12436, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 6 | [Child 6748, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 7 | [Parent 12436, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 8 | [Child 548, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 9 | [Child 548, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 10 | [Child 9904, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 11 | [Child 9904, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 12 | *** UTM:SVC TimerManager:registerTimer called after profile-before-change notification. Ignoring timer registration for id: telemetry_modules_ping 13 | 1559527049046 mozrunner::runner INFO Running command: "d:\\Mozilla Firefox\\firefox.exe" "-marionette" "--headless" "--disable-gpu" "-foreground" "-no-remote" "-profile" "C:\\Users\\ls\\AppData\\Local\\Temp\\rust_mozprofile.PYXo9qS7gQhe" 14 | *** You are running in headless mode. 15 | 1559527052660 Marionette INFO Listening on port 30392 16 | 1559527052995 Marionette WARN TLS certificate errors will be ignored for this session 17 | [Child 13032, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 18 | [Child 13872, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 19 | *** UTM:SVC TimerManager:registerTimer called after profile-before-change notification. Ignoring timer registration for id: telemetry_modules_ping 20 | 1559527207435 mozrunner::runner INFO Running command: "d:\\Mozilla Firefox\\firefox.exe" "-marionette" "--headless" "--disable-gpu" "-foreground" "-no-remote" "-profile" "C:\\Users\\ls\\AppData\\Local\\Temp\\rust_mozprofile.BLu99lLtZajc" 21 | *** You are running in headless mode. 22 | 1559527211166 Marionette INFO Listening on port 30530 23 | 1559527211302 Marionette WARN TLS certificate errors will be ignored for this session 24 | [Parent 14048, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 25 | [Child 14180, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 26 | [Child 13532, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 27 | [Parent 14048, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 28 | *** UTM:SVC TimerManager:registerTimer called after profile-before-change notification. Ignoring timer registration for id: telemetry_modules_ping 29 | 1559530581921 mozrunner::runner INFO Running command: "d:\\Mozilla Firefox\\firefox.exe" "-marionette" "--headless" "--disable-gpu" "-foreground" "-no-remote" "-profile" "C:\\Users\\ls\\AppData\\Local\\Temp\\rust_mozprofile.DaXkfpf6gsXV" 30 | *** You are running in headless mode. 31 | 1559530585691 Marionette INFO Listening on port 31189 32 | 1559530585835 Marionette WARN TLS certificate errors will be ignored for this session 33 | [Parent 12504, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 34 | [Parent 12504, Gecko_IOThread] WARNING: file z:/build/build/src/ipc/chromium/src/base/process_util_win.cc, line 188 35 | [Child 9804, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 36 | [Parent 12504, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 37 | [Child 14024, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 38 | *** UTM:SVC TimerManager:registerTimer called after profile-before-change notification. Ignoring timer registration for id: telemetry_modules_ping 39 | 1559531545335 mozrunner::runner INFO Running command: "d:\\Mozilla Firefox\\firefox.exe" "-marionette" "--headless" "--disable-gpu" "-foreground" "-no-remote" "-profile" "C:\\Users\\ls\\AppData\\Local\\Temp\\rust_mozprofile.6K8lDrTAF6a0" 40 | *** You are running in headless mode. 41 | 1559531549501 Marionette INFO Listening on port 31498 42 | 1559531549731 Marionette WARN TLS certificate errors will be ignored for this session 43 | JavaScript error: https://10.10.6.93/js/lib/require.js, line 168: Error: Script error for "PtzCtrl", needed by: app/Live/live 44 | http://requirejs.org/docs/errors.html#scripterror 45 | JavaScript error: https://10.10.6.93/js/lib/require.js, line 168: Error: Script error for "app/ChlCfg/editChlGroup", needed by: app/Live/live 46 | http://requirejs.org/docs/errors.html#scripterror 47 | JavaScript error: https://10.10.6.93/js/lib/require.js, line 168: Error: Script error for "grid", needed by: app/Live/live 48 | http://requirejs.org/docs/errors.html#scripterror 49 | JavaScript error: https://10.10.6.93/js/lib/require.js, line 168: Error: Script error for "app/ChlCfg/addPreset", needed by: app/Live/live 50 | http://requirejs.org/docs/errors.html#scripterror 51 | JavaScript error: https://10.10.6.93/js/lib/require.js, line 168: Error: Script error for "slider", needed by: app/Live/live 52 | http://requirejs.org/docs/errors.html#scripterror 53 | 54 | ###!!! [Child][MessageChannel] Error: (msgtype=0x48000E,name=PHttpChannel::Msg_DeletingChannel) Channel closing: too late to send/recv, messages will be lost 55 | 56 | JavaScript error: https://10.10.6.93/js/lib/require.js, line 168: Error: Script error for "listbox", needed by: app/Live/live 57 | http://requirejs.org/docs/errors.html#scripterror 58 | 59 | ###!!! [Child][MessageChannel] Error: (msgtype=0x48000E,name=PHttpChannel::Msg_DeletingChannel) Channel closing: too late to send/recv, messages will be lost 60 | 61 | JavaScript error: https://10.10.6.93/js/lib/require.js, line 168: Error: Script error for "app/ChlCfg/addChlGroup", needed by: app/Live/live 62 | http://requirejs.org/docs/errors.html#scripterror 63 | 64 | ###!!! [Child][MessageChannel] Error: (msgtype=0x48000E,name=PHttpChannel::Msg_DeletingChannel) Channel closing: too late to send/recv, messages will be lost 65 | 66 | JavaScript error: https://10.10.6.93/js/lib/require.js, line 168: Error: Script error for "spliter", needed by: app/Live/live 67 | http://requirejs.org/docs/errors.html#scripterror 68 | 69 | ###!!! [Child][MessageChannel] Error: (msgtype=0x48000E,name=PHttpChannel::Msg_DeletingChannel) Channel closing: too late to send/recv, messages will be lost 70 | 71 | JavaScript error: https://10.10.6.93/js/lib/require.js, line 168: Error: Script error for "tab", needed by: app/Live/live 72 | http://requirejs.org/docs/errors.html#scripterror 73 | 74 | ###!!! [Child][MessageChannel] Error: (msgtype=0x48000E,name=PHttpChannel::Msg_DeletingChannel) Channel closing: too late to send/recv, messages will be lost 75 | 76 | 77 | ###!!! [Child][MessageChannel] Error: (msgtype=0x2C00AF,name=PContent::Msg_ScriptError) Channel closing: too late to send/recv, messages will be lost 78 | 79 | 80 | ###!!! [Child][MessageChannel] Error: (msgtype=0x2C00AF,name=PContent::Msg_ScriptError) Channel closing: too late to send/recv, messages will be lost 81 | 82 | 83 | ###!!! [Child][MessageChannel] Error: (msgtype=0x2C00AF,name=PContent::Msg_ScriptError) Channel closing: too late to send/recv, messages will be lost 84 | 85 | 86 | ###!!! [Child][MessageChannel] Error: (msgtype=0x2C00AF,name=PContent::Msg_ScriptError) Channel closing: too late to send/recv, messages will be lost 87 | 88 | 89 | ###!!! [Child][RunMessage] Error: Channel closing: too late to send/recv, messages will be lost 90 | 91 | 92 | ###!!! [Child][MessageChannel] Error: (msgtype=0x2C00AF,name=PContent::Msg_ScriptError) Channel closing: too late to send/recv, messages will be lost 93 | 94 | 95 | ###!!! [Child][RunMessage] Error: Channel closing: too late to send/recv, messages will be lost 96 | 97 | 98 | ###!!! [Child][MessageChannel] Error: (msgtype=0x2C00AF,name=PContent::Msg_ScriptError) Channel closing: too late to send/recv, messages will be lost 99 | 100 | 101 | ###!!! [Child][MessageChannel] Error: (msgtype=0x2C00AF,name=PContent::Msg_ScriptError) Channel closing: too late to send/recv, messages will be lost 102 | 103 | 104 | ###!!! [Child][MessageChannel] Error: (msgtype=0x2C00AF,name=PContent::Msg_ScriptError) Channel closing: too late to send/recv, messages will be lost 105 | 106 | 107 | ###!!! [Child][MessageChannel] Error: (msgtype=0x2C00AF,name=PContent::Msg_ScriptError) Channel closing: too late to send/recv, messages will be lost 108 | 109 | [Parent 12436, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 110 | [Child 14184, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 111 | *** UTM:SVC TimerManager:registerTimer called after profile-before-change notification. Ignoring timer registration for id: telemetry_modules_ping 112 | 1559531605356 mozrunner::runner INFO Running command: "d:\\Mozilla Firefox\\firefox.exe" "-marionette" "--headless" "--disable-gpu" "-foreground" "-no-remote" "-profile" "C:\\Users\\ls\\AppData\\Local\\Temp\\rust_mozprofile.wCANx5AZX3C8" 113 | *** You are running in headless mode. 114 | 1559531609721 Marionette INFO Listening on port 31612 115 | 1559531609850 Marionette WARN TLS certificate errors will be ignored for this session 116 | 117 | ###!!! [Parent][MessageChannel] Error: (msgtype=0x1000B,name=PAPZ::Msg_Destroy) Channel error: cannot send/recv 118 | 119 | 120 | ###!!! [Parent][MessageChannel] Error: (msgtype=0x15008C,name=PBrowser::Msg_UpdateNativeWindowHandle) Channel error: cannot send/recv 121 | 122 | 123 | ###!!! [Parent][MessageChannel] Error: (msgtype=0x15007F,name=PBrowser::Msg_Destroy) Channel error: cannot send/recv 124 | 125 | A content process crashed and MOZ_CRASHREPORTER_SHUTDOWN is set, shutting down 126 | 127 | ###!!! [Parent][MessageChannel] Error: (msgtype=0x15008C,name=PBrowser::Msg_UpdateNativeWindowHandle) Channel error: cannot send/recv 128 | 129 | 130 | ###!!! [Parent][MessageChannel] Error: (msgtype=0x15007F,name=PBrowser::Msg_Destroy) Channel error: cannot send/recv 131 | 132 | 1559531630065 mozrunner::runner INFO Running command: "d:\\Mozilla Firefox\\firefox.exe" "-marionette" "--headless" "--disable-gpu" "-foreground" "-no-remote" "-profile" "C:\\Users\\ls\\AppData\\Local\\Temp\\rust_mozprofile.UwRY4McjclZ4" 133 | *** You are running in headless mode. 134 | 1559531634067 Marionette INFO Listening on port 31716 135 | 1559531634494 Marionette WARN TLS certificate errors will be ignored for this session 136 | [Parent 13816, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 137 | [Parent 13816, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 138 | [Child 9416, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 139 | *** UTM:SVC TimerManager:registerTimer called after profile-before-change notification. Ignoring timer registration for id: telemetry_modules_ping 140 | 1559531753215 mozrunner::runner INFO Running command: "d:\\Mozilla Firefox\\firefox.exe" "-marionette" "--headless" "--disable-gpu" "-foreground" "-no-remote" "-profile" "C:\\Users\\ls\\AppData\\Local\\Temp\\rust_mozprofile.xkhOVJsUAGBt" 141 | *** You are running in headless mode. 142 | 1559531757471 Marionette INFO Listening on port 32058 143 | 1559531757622 Marionette WARN TLS certificate errors will be ignored for this session 144 | [Child 13112, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 145 | [Child 13112, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 146 | [Child 13364, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 147 | [Parent 10808, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 148 | [Child 12864, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 149 | *** UTM:SVC TimerManager:registerTimer called after profile-before-change notification. Ignoring timer registration for id: telemetry_modules_ping 150 | 1559532007854 mozrunner::runner INFO Running command: "d:\\Mozilla Firefox\\firefox.exe" "-marionette" "--headless" "--disable-gpu" "-foreground" "-no-remote" "-profile" "C:\\Users\\ls\\AppData\\Local\\Temp\\rust_mozprofile.5k9wHAGp9Mim" 151 | *** You are running in headless mode. 152 | 1559532011835 Marionette INFO Listening on port 34226 153 | 1559532012341 Marionette WARN TLS certificate errors will be ignored for this session 154 | [Parent 11076, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 155 | [Child 12436, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 156 | [Child 12436, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 157 | [Parent 11076, Gecko_IOThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 158 | [Child 14104, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 159 | [Child 14104, Chrome_ChildThread] WARNING: pipe error: 109: file z:/build/build/src/ipc/chromium/src/chrome/common/ipc_channel_win.cc, line 346 160 | *** UTM:SVC TimerManager:registerTimer called after profile-before-change notification. Ignoring timer registration for id: telemetry_modules_ping 161 | -------------------------------------------------------------------------------- /fuzzers/rtsp_fuzzer.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import re 3 | import socket 4 | import hashlib 5 | import base64 6 | import time 7 | from common.logger import LogConfig 8 | 9 | config_dict = { 10 | 'server_username': 'admin', # RTSP用户名 11 | 'server_password': '123456', # RTSP用户名对应密码 12 | 'server_ip': '10.10.6.93', # RTSP服务器IP地址 13 | 'server_port': 554, # RTSP服务器使用端口 14 | 'server_path': '/chIP=1/', # URL中端口之后的部份,测试发现不同服务器对这部份接受的值是不一样的,也就是说自己使用时很可能得自己修改这部份的值 15 | 'cseq': 2, # RTSP使用的请求起始序列码,不需要改动 16 | 'user_agent': 'LibVLC/3.0.2 (LIVE555 Streaming Media v2016.11.28)', # 自定义请求头部 17 | 'buffer_len': 1024, # 用于接收服务器返回数据的缓冲区的大小 18 | 'auth_method': 'Digest', # RTSP使用的认证方法,Basic/Digest 19 | # OPTIONS/FIRST_DESCRIBE/SECOND_DESCRIBE/FIRST_SETUP/SECOND_SETUP/PLAY/GET_PARAMETER/TEARDOWN/ALL 20 | # 如果不是以上任何一个值那么就会一路正常请求 21 | 'fuzz_step': 'SECOND_DESCRIBE', 22 | 'fuzz_extern_header': False, # 是否对每个请求模糊测试额外的头部 23 | # 'header_normal_modify_allow': False, # 是否允许拼接其他协议规定的请求头的总开关,请些请求头的值为正常值(大多是RFC给出的示例) 24 | # 'header_overload_modify_allow': False, # 是否允许拼接其他协议规定的请求头的总开关,请些请求头的值为超长字符串 25 | # 'options_header_modify': True, # OPTIONS请求中,是否允许拼接其他协议规定的请求头的开关 26 | # 'describe_header_modify': True, # 第一次DESCRIBE请求中,是否允许拼接其他协议规定的请求头的开关 27 | # 'describe_auth_header_modify': True, # 第二次DESCRIBE请求中,是否允许拼接其他协议规定的请求头的开关 28 | # 'setup_header_modify': True, # 第一次SETUP请求中,是否允许拼接其他协议规定的请求头的开关 29 | # 'setup_session_header_modify': True, # 第二次SETUP请求中,是否允许拼接其他协议规定的请求头的开关 30 | # 'play_header_modify': True, # PLAY请求中,是否允许拼接其他协议规定的请求头的开关 31 | # 'get_parameter_header_modify': True, # GET PARAMETER请求中,是否允许拼接其他协议规定的请求头的开关 32 | # 'teardown_header_modify': True # TEARDOWN请求中,是否允许拼接其他协议规定的请求头的开关 33 | 'log_type': 'console', 34 | 'log_file_prefix': 'rtsp' 35 | } 36 | 37 | 38 | class RtspFuzzer(): 39 | def __init__(self): 40 | global config_dict 41 | # self.socket_send = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 42 | # self.socket_send.settimeout(5) 43 | # self.socket_send.connect((config_dict['server_ip'], config_dict['server_port'])) 44 | # self.config_dict = config_dict 45 | self.socket_send = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 46 | self.socket_send.settimeout(5) 47 | self.socket_send.connect((config_dict['server_ip'], config_dict['server_port'])) 48 | log_type = config_dict["log_type"] 49 | log_file_prefix = config_dict["log_file_prefix"] 50 | # LogConfig(log_type="file",test_protocol="tvt") 51 | LogConfig(log_type=log_type, log_file_prefix=log_file_prefix) 52 | self.regexp = "fuzzer_var\([^\)]*\)" 53 | self.fuzz_payload_dict = { 54 | "overflow": "overflow.txt", 55 | "format_string": "format_string.txt", 56 | "random_num": "random_num.txt", 57 | "special_char": "special_char.txt", 58 | "unicode": "unicode.txt", 59 | } 60 | self.uri = f"rtsp://{config_dict['server_ip']}:{config_dict['server_port']}{config_dict['server_path']}" 61 | pass 62 | 63 | # 用于Digest认证方式时生成response的值 64 | def gen_digest_response_value(self, uri, method, realm, nonce): 65 | HA1 = hashlib.md5((f"{config_dict['server_username']}:{realm }:{config_dict['server_password']}").encode()).hexdigest() 66 | HA2 = hashlib.md5((f"{method}:{uri}").encode()).hexdigest() 67 | response_value = hashlib.md5((f"{HA1}:{nonce}:{HA2}").encode()).hexdigest() 68 | return response_value 69 | 70 | # 生成options请求头部 71 | def gen_options_header(self): 72 | global config_dict 73 | str_options_header = (f"""OPTIONS fuzzer_var(rtsp):fuzzer_var(//)fuzzer_var({config_dict['server_ip']})fuzzer_var(:)fuzzer_var({config_dict['server_port']}){config_dict['server_path']}fuzzer_var() fuzzer_var(RTSP)/fuzzer_var(1.0)\r\n""" 74 | f"""CSeq: fuzzer_var({config_dict['cseq']})\r\n""" 75 | f"""User-Agent: fuzzer_var({config_dict['user_agent']})\r\n""" 76 | f"""\r\n""" 77 | ) 78 | return str_options_header 79 | 80 | # 生成first describe请求头部 81 | def gen_first_describe_header(self): 82 | global config_dict 83 | str_describe_header = (f"""DESCRIBE fuzzer_var(rtsp):fuzzer_var(//)fuzzer_var({config_dict['server_ip']})fuzzer_var(:)fuzzer_var({config_dict['server_port']}){config_dict['server_path']}fuzzer_var() fuzzer_var(RTSP)/fuzzer_var(1.0)\r\n""" 84 | f"""CSeq: fuzzer_var({config_dict['cseq'] + 1})\r\n""" 85 | f"""User-Agent: fuzzer_var({config_dict['user_agent']})\r\n""" 86 | f"""Accept: fuzzer_var(application/sdp)\r\n""" 87 | f"""\r\n""" 88 | ) 89 | return str_describe_header 90 | 91 | # 生成second describe请求头部 92 | def gen_second_describe_header(self, realm, nonce): 93 | global config_dict 94 | method = 'DESCRIBE' 95 | str_describe_auth_header = (f"""{method} rtsp://{config_dict['server_ip']}:{config_dict['server_port']}{config_dict['server_path']} RTSP/1.0\r\n""" 96 | f"""CSeq: fuzzer_var({config_dict['cseq'] + 2})\r\n""") 97 | if config_dict['auth_method'] == 'Basic': 98 | auth_64 = base64.b64encode((f"{config_dict['server_username']}:{config_dict['server_password']}").encode("utf-8")).decode() 99 | str_describe_auth_header += f"""Authorization: fuzzer_var(Basic) fuzzer_var({auth_64})\r\n""" 100 | else: 101 | response_value = self.gen_digest_response_value(self.uri, method, realm, nonce) 102 | str_describe_auth_header += f"""Authorization: Digest username="{config_dict['server_username']}", realm="{realm}", nonce="{nonce}", uri="{self.uri}", response="{response_value}"\r\n""" 103 | str_describe_auth_header += (f"""User-Agent: fuzzer_var({config_dict['user_agent']})\r\n""" 104 | f"""Accept: fuzzer_var(application/sdp)\r\n""" 105 | f"""\r\n""" 106 | ) 107 | return str_describe_auth_header 108 | 109 | # 生成first setup请求头部 110 | def gen_first_setup_header(self,realm, nonce): 111 | global config_dict 112 | method = 'SETUP' 113 | str_setup_header = (f"""{method} fuzzer_var(rtsp):fuzzer_var(//)fuzzer_var({config_dict['server_ip']}):fuzzer_var({config_dict['server_port']}){config_dict['server_path']}trackID=fuzzer_var(0) trackID=fuzzer_var(0) fuzzer_var(RTSP)/fuzzer_var(1.0)\r\n""" 114 | f"""CSeq: {config_dict['cseq'] + 3}\r\n""") 115 | if config_dict['auth_method'] == 'Basic': 116 | auth_64 = base64.b64encode((f"{config_dict['server_username']}:{config_dict['server_password']}").encode("utf-8")).decode() 117 | str_setup_header += f"""Authorization: Basic fuzzer_var({auth_64})\r\n""" 118 | else: 119 | response_value = self.gen_digest_response_value(self.uri, method, realm, nonce) 120 | str_setup_header += f"""Authorization: Digest username="fuzzer_var({config_dict['server_username']})", realm="fuzzer_var({realm})", nonce="fuzzer_var({nonce})", uri="fuzzer_var({self.uri})", response="fuzzer_var({response_value})"\r\n""" 121 | str_setup_header += (f"""User-Agent: fuzzer_var({config_dict['user_agent']})\r\n""" 122 | f"""Transport: fuzzer_var(RTP/AVP);fuzzer_var(unicast);client_port=fuzzer_var(50166)-50167\r\n""" 123 | f"""\r\n""" 124 | ) 125 | return str_setup_header 126 | 127 | # 生成second setup请求头部 128 | def gen_second_setup_header(self, realm, nonce, session): 129 | global config_dict 130 | method = 'SETUP' 131 | str_setup_session_header = (f"""{method} fuzzer_var(rtsp)://fuzzer_var({config_dict['server_ip']}):fuzzer_var({config_dict['server_port']}){config_dict['server_path']}trackID=fuzzer_var(1) trackID=fuzzer_var(1) fuzzer_var(RTSP)/fuzzer_var(1.0)\r\n""" 132 | f"""CSeq: fuzzer_var({config_dict['cseq'] + 4})\r\n""") 133 | if config_dict['auth_method'] == 'Basic': 134 | auth_64 = base64.b64encode((f"{config_dict['server_username']}:{config_dict['server_password']}").encode("utf-8")).decode() 135 | str_setup_session_header += f"Authorization: Basic fuzzer_var({auth_64})\r\n" 136 | else: 137 | response_value = self.gen_digest_response_value(self.uri, method, realm, nonce) 138 | str_setup_session_header += f"""Authorization: Digest username="fuzzer_var({config_dict['server_username']})", realm="fuzzer_var({realm})", nonce="fuzzer_var({nonce})", uri="fuzzer_var({self.uri})", response="fuzzer_var({response_value})"\r\n""" 139 | str_setup_session_header += (f"""User-Agent: fuzzer_var({config_dict['user_agent']})\r\n""" 140 | f"""Transport: fuzzer_var(RTP/AVP);unicast;client_port=fuzzer_var(50168)-fuzzer_var(50169)\r\n""" 141 | f"""Session: fuzzer_var({session})\r\n""" 142 | f"""\r\n""" 143 | ) 144 | return str_setup_session_header 145 | 146 | # 生成play请求头部 147 | def gen_play_header(self, realm, nonce, session): 148 | global config_dict 149 | method = 'PLAY' 150 | str_play_header = (f"""{method} fuzzer_var(rtsp)://fuzzer_var({config_dict['server_ip']}):fuzzer_var({config_dict['server_port']}){config_dict['server_path']} fuzzer_var(RTSP)/fuzzer_var(1.0)\r\n""" 151 | f"""CSeq: fuzzer_var({config_dict['cseq'] + 5})\r\n""") 152 | if config_dict['auth_method'] == 'Basic': 153 | auth_64 = base64.b64encode((f"{config_dict['server_username']}:{config_dict['server_password']}").encode("utf-8")).decode() 154 | str_play_header += f"Authorization: Basic fuzzer_var({auth_64})\r\n" 155 | else: 156 | response_value = self.gen_digest_response_value(self.uri, method, realm, nonce) 157 | str_play_header += f"""Authorization: fuzzer_var(Digest) username="fuzzer_var({config_dict['server_username']})", realm="fuzzer_var({realm})", nonce="fuzzer_var({nonce})", uri="fuzzer_var({self.uri})", response="fuzzer_var({response_value})"\r\n""" 158 | str_play_header += (f"""User-Agent: fuzzer_var({config_dict['user_agent']})\r\n""" 159 | f"""Session: fuzzer_var({session})\r\n""" 160 | f"""Range: npt=fuzzer_var(0.000-)\r\n""" 161 | f"""\r\n""" 162 | ) 163 | return str_play_header 164 | 165 | # 生成GET_PARAMETER请求头部 166 | def gen_get_parameter_header(self, realm, nonce, session): 167 | global config_dict 168 | method = 'GET_PARAMETER' 169 | str_get_parameter_header = (f"""{method} fuzzer_var(rtsp)://fuzzer_var({config_dict['server_ip']}):fuzzer_var({config_dict['server_port']}){config_dict['server_path']} fuzzer_var(RTSP)/fuzzer_var(1.0)\r\n""" 170 | f"""CSeq: fuzzer_var({config_dict['cseq'] + 6})\r\n""") 171 | if config_dict['auth_method'] == 'Basic': 172 | auth_64 = base64.b64encode((f"{config_dict['server_username']}:{config_dict['server_password']}").encode("utf-8")).decode() 173 | str_get_parameter_header += f"Authorization: Basic fuzzer_var({auth_64})\r\n" 174 | else: 175 | response_value = self.gen_digest_response_value(self.uri, method, realm, nonce) 176 | str_get_parameter_header += f"""Authorization: Digest username="fuzzer_var({config_dict['server_username']})", realm="fuzzer_var({realm})", nonce="fuzzer_var({nonce})", uri="fuzzer_var({self.uri})", response="fuzzer_var({response_value})"\r\n""" 177 | str_get_parameter_header += (f"""User-Agent: fuzzer_var({config_dict['user_agent']})\r\n""" 178 | f"""Session: fuzzer_var({session})\r\n""" 179 | f"""\r\n""" 180 | ) 181 | return str_get_parameter_header 182 | 183 | # 生成teardown请求头部 184 | def gen_teardown_header(self, realm, nonce, session): 185 | global config_dict 186 | method = 'TEARDOWN' 187 | str_teardown_header = (f"""{method} fuzzer_var(rtsp)://fuzzer_var({config_dict['server_ip']}):fuzzer_var({config_dict['server_port']}){config_dict['server_path']} fuzzer_var(RTSP)/fuzzer_var(1.0)\r\n""" 188 | f"""CSeq: fuzzer_var({config_dict['cseq'] + 11})\r\n""") 189 | if config_dict['auth_method'] == 'Basic': 190 | auth_64 = base64.b64encode((f"{config_dict['server_username']}:{config_dict['server_password']}").encode("utf-8")).decode() 191 | str_teardown_header += f"Authorization: Basic fuzzer_var({auth_64})\r\n" 192 | else: 193 | response_value = self.gen_digest_response_value(self.uri, method, realm, nonce) 194 | str_teardown_header += f"""Authorization: Digest username="fuzzer_var({config_dict['server_username']})", realm="fuzzer_var({realm})", nonce="fuzzer_var({nonce})", uri="fuzzer_var({self.uri})", response="fuzzer_var({response_value})"\r\n""" 195 | str_teardown_header += (f"""User-Agent: fuzzer_var({config_dict['user_agent']})\r\n""" 196 | f"""Session: fuzzer_var({session})\r\n""" 197 | f"""\r\n""" 198 | ) 199 | return str_teardown_header 200 | 201 | # 拼接rtsp协议的其他请求头,以测试程序对这些请求头部的处理是否有问题;这个方法与add_overload_header_according_to_protocol是互斥的 202 | def add_extern_protocol(self, str_header): 203 | str_header = str_header[0:len(str_header) - 2] 204 | str_header += ('Accept: fuzz_var(application/rtsl), fuzz_var(application/sdp);level=fuzz_var(-2)' 205 | 'Accept-Encoding: fuzz_var(gzip);q=fuzz_var(1.0), identity; q=fuzz_var(0.5), fuzz_var(*);q=fuzz_var(0)\r\n' 206 | 'Accept-Language: fuzz_var(da), en-gb;q=fuzz_var(0.8), en;q=fuzz_var(0.7)\r\n' 207 | 'Bandwidth: fuzz_var(4000) \r\n' 208 | 'Blocksize: fuzz_var(4000) \r\n' 209 | 'Cache-Control: fuzz_var(no-cache);fuzz_var(max-stale) \r\n' 210 | 'Conference: fuzz_var(199702170042.SAA08642@obiwan.arl.wustl.edu%20Starr) \r\n' 211 | 'Connection: fuzz_var(close)\r\n' 212 | 'Content-Base: fuzz_var(gzip)\r\n' 213 | 'Content-Encoding: fuzz_var(gzip)\r\n' 214 | 'Content-Language: fuzz_var(mi),fuzz_var(en)\r\n' 215 | 'Content-Length: fuzz_var(2034953454546565) \r\n' 216 | 'Content-Location: fuzz_var(/etc/passwd)\r\n' 217 | 'Content-Type: fuzz_var(text/html); charset=fuzz_var(ISO-8859-4gg)\r\n' 218 | 'Date: fuzz_var(Tue, 15 Nov 1995x 08:12:31 GMT)\r\n' 219 | 'Expires: fuzz_var(Thu, 01 Dec 1994 16:00:00 GMT) \r\n' 220 | 'From: fuzz_var(webmaster@w3.org)\r\n' 221 | 'If-Modified-Since: fuzz_var(Sat, 29 Oct 1994 19:43:31 GMT) \r\n' 222 | 'Last-Modified: fuzz_var(Tue, 15 Nov 1994 12:45:26 GMT)\r\n' 223 | 'Proxy-Require: fuzz_var(funky-feature)\r\n' 224 | 'Referer: fuzz_var(http://www.w3.org/hypertext/DataSources/Overview.html)\r\n' 225 | 'Require: fuzz_var(funky-feature) \r\n' 226 | 'Scale: fuzz_var(-3.5) \r\n' 227 | 'Speed: fuzz_var(2.5) \r\n' 228 | 'Transport: fuzz_var(RTP/AVP);fuzz_var(unicast);fuzz_var(client_port=3456-3457);mode="fuzz_var(PLAY)" \r\n' 229 | 'Via: fuzz_var(1.0 fred), fuzz_var(1.1 nowhere.com) (Apache/1.1)\r\n' 230 | 'Range: npt=fuzz_var(2)\r\n' 231 | '\r\n' 232 | ) 233 | return str_header 234 | 235 | def delete_var_sign(self,matched): 236 | value_org = matched.group() 237 | start_pos = re.search("\(",value_org).end() 238 | end_pos = re.search("\)",value_org).start() 239 | value = value_org[start_pos:end_pos] 240 | return value 241 | 242 | # 从服务器返回结果中提取出realm值 243 | def extract_realm_value(self,msg_recv): 244 | realm_pos = msg_recv.find('realm') 245 | realm_value_begin_pos = msg_recv.find('"', realm_pos) + 1 246 | realm_value_end_pos = msg_recv.find('"', realm_pos + 8) 247 | realm_value = msg_recv[realm_value_begin_pos:realm_value_end_pos] 248 | return realm_value 249 | 250 | # 从服务器返回结果中提取出nonce值 251 | def extract_nonce_value(self,msg_recv): 252 | nonce_pos = msg_recv.find('nonce') 253 | nonce_value_begin_pos = msg_recv.find('"', nonce_pos) + 1 254 | nonce_value_end_pos = msg_recv.find('"', nonce_pos + 8) 255 | nonce_value = msg_recv[nonce_value_begin_pos:nonce_value_end_pos] 256 | return nonce_value 257 | 258 | # 从服务器返回结果中提取出session值 259 | def extract_session_value(self,msg_recv): 260 | session_pos = msg_recv.find('Session') 261 | session_value_begin_pos = msg_recv.find(' ', session_pos + 8) + 1 262 | session_value_end_pos = msg_recv.find(';', session_pos + 8) 263 | session_value = msg_recv[session_value_begin_pos:session_value_end_pos] 264 | return session_value 265 | 266 | # fuzz的真正发包函数,被traverse_fuzz_var()调用 267 | def send_payload(self, org_step_header, fuzz_payload, step, payload_type, fuzz_var): 268 | # 将当前被遍历的fuzz_var()改为fuzz_var\(\)以和其他未遍历的fuzz_var()区分 269 | fuzz_var_fix = fuzz_var.replace("(", "\(").replace(")", "\)") 270 | count = re.findall(fuzz_var_fix, org_step_header).__len__() 271 | # 获取当前遍历项的原始值 272 | start_pos = re.search("\(", fuzz_var).end() 273 | end_pos = re.search("\)", fuzz_var).start() 274 | org_value = fuzz_var[start_pos:end_pos] 275 | 276 | # 先将当前遍历的fuzz_var()替换成测试载荷 277 | for i in range(count): 278 | # 将目标位置前的匹配项都还原成原始值 279 | if i != 0: 280 | tt = re.sub(fuzz_var_fix, org_value, org_step_header,i) 281 | # 将目标位置替换成payload,最后的1表示只替换一次,这是关键 282 | tt = re.sub(fuzz_var_fix, fuzz_payload, tt,1) 283 | else: 284 | try: 285 | # 如果目标项是第一个匹配,那么tt来自于org_step_header 286 | tt = re.sub(fuzz_var_fix, fuzz_payload, org_step_header, 1) 287 | except: 288 | logging.warning(f"exception occur-{step}-{payload_type}-{fuzz_var}-{fuzz_payload}") 289 | continue 290 | # 对于剩下的所有fuzz_var\(\),进行直接删除处理 291 | tt = re.sub(self.regexp, self.delete_var_sign, tt) 292 | logging.info(f"{step}-{payload_type}-{fuzz_var}-{fuzz_payload}") 293 | 294 | # try: 295 | # self.socket_send.send(tt.encode('utf-8')) 296 | # except: 297 | # logging.info(f"{step}-{payload_type}-{fuzz_var}-{fuzz_payload}-{tt}") 298 | # self.socket_send.connect((config_dict['server_ip'], config_dict['server_port'])) 299 | # self.socket_send.send(tt.encode('utf-8')) 300 | # 需要暂停一下,因为发现一直发送时服务端会返回continues一直让客户端发送数据不返回,最后就直接fin把连接给关了 301 | # 但似乎也只能延缓一下? 302 | time.sleep(1) 303 | self.socket_send.send(tt.encode('utf-8')) 304 | try: 305 | msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode() 306 | except: 307 | msg_recv = "recv time out" 308 | msg_recv_dict = msg_recv.split('\r\n') 309 | logging.info(f"{step}-{payload_type}-{fuzz_var}-{fuzz_payload}-{msg_recv_dict[0]}") 310 | 311 | # 遍历所有要模糊测试的变量 312 | def traverse_fuzz_var(self, step, org_step_header): 313 | # 如果要模糊测试额外头部,则给传过来的头部先加上 314 | if config_dict["fuzz_extern_header"]: 315 | org_step_header = self.add_extern_protocol(org_step_header) 316 | for payload_type, payload_file in self.fuzz_payload_dict.items(): 317 | logging.info(f"start to test {payload_type}") 318 | # payload_file_obj = open(f"{payload_file}","a",encoding="utf-8") 319 | # org_step_header = self.gen_options_header() 320 | # 全部被fuzz_var()包含的位置 321 | fuzz_vars = re.findall(self.regexp, org_step_header) 322 | # 遍历所有被fuzz_var()包含的位置 323 | for fuzz_var in fuzz_vars: 324 | 325 | # 对该变量循环具体测试类型的载荷 326 | for fuzz_payload in open(f"../payloads/{payload_file}", "r", encoding="utf-8"): 327 | fuzz_payload = fuzz_payload.strip("\n") 328 | # 排除空载荷情况 329 | if fuzz_payload.strip() != "": 330 | # 如果是缓冲区溢出,由于我这里payload使用"A"*10等形式,所以需要先使用eval动态执行转成最终的字符串 331 | if payload_type == "overflow": 332 | fuzz_payload = eval(fuzz_payload) 333 | self.send_payload( org_step_header, fuzz_payload, step, payload_type, fuzz_var) 334 | # 最后单独对空载荷进行测试 335 | # 前面排除这里进行是因为载荷中为了方便使用了很多空行 336 | fuzz_payload = "" 337 | self.send_payload( org_step_header, fuzz_payload, step, payload_type, fuzz_var) 338 | 339 | # 正确执行OPTIONS请求 340 | def exec_options_step(self): 341 | # logging.info('now start to check options operation') 342 | str_options_header = self.gen_options_header() 343 | # 删除所有fuzz_var()标志 344 | str_options_header = re.sub(self.regexp, self.delete_var_sign, str_options_header) 345 | self.socket_send.send(str_options_header.encode()) 346 | msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode() 347 | if '200 OK' in msg_recv: 348 | logging.info('OPTIONS is ok, next first DESCRIBE') 349 | return msg_recv,2000 350 | else: 351 | logging.info('OPTIONS request is BAD') 352 | return msg_recv,4000 353 | 354 | # 模糊测试OPTIONS请求 355 | def fuzz_options_step(self): 356 | step = "OPTIONS" 357 | org_options_header = self.gen_options_header() 358 | self.traverse_fuzz_var(step,org_options_header) 359 | 360 | # 正确执行first describe请求 361 | def exec_first_describe_step(self): 362 | str_describe_header = self.gen_first_describe_header() 363 | str_describe_header = re.sub(self.regexp, self.delete_var_sign, str_describe_header) 364 | self.socket_send.send(str_describe_header.encode()) 365 | msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode() 366 | if msg_recv.find('401 Unauthorized') != -1: 367 | logging.info('first DESCRIBE is ok, next second DESCRIBE') 368 | return msg_recv,2000 369 | else: 370 | msg_recv_dict = msg_recv.split('\r\n') 371 | logging.info('first DESCRIBE occur error: ') 372 | logging.info(msg_recv_dict[0]) 373 | return msg_recv,4000 374 | 375 | # 模糊测试first describe请求 376 | def fuzz_first_describe_step(self): 377 | step = "FIRST DESCRIBE" 378 | org_first_describe_header = self.gen_first_describe_header() 379 | self.traverse_fuzz_var(step,org_first_describe_header) 380 | 381 | # 正确执行second describe请求 382 | def exec_second_describe_step(self,realm, nonce): 383 | str_describe_auth_header = self.gen_second_describe_header(realm, nonce) 384 | str_describe_auth_header = re.sub(self.regexp, self.delete_var_sign, str_describe_auth_header) 385 | self.socket_send.send(str_describe_auth_header.encode()) 386 | msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode() 387 | if msg_recv.find('200 OK') != -1: 388 | logging.info('second DESCRIBE is ok, next first SETUP') 389 | return msg_recv,2000 390 | else: 391 | msg_recv_dict = msg_recv.split('\r\n') 392 | logging.info('second DESCRIBE request occur error: ') 393 | logging.info(msg_recv_dict[0]) 394 | return msg_recv, 4000 395 | 396 | # 模糊测试second describe请求 397 | def fuzz_second_describe_step(self, realm, nonce): 398 | step = "SECOND DESCRIBE" 399 | org_second_describe_header = self.gen_second_describe_header(realm, nonce) 400 | self.traverse_fuzz_var(step,org_second_describe_header) 401 | 402 | 403 | # 正确执行first setup请求 404 | def exec_first_setup_step(self, realm, nonce): 405 | # logging.info('second DESCRIBE is ok, next first SETUP') 406 | str_setup_header = self.gen_first_setup_header(realm, nonce) 407 | str_setup_header = re.sub(self.regexp, self.delete_var_sign, str_setup_header) 408 | self.socket_send.send(str_setup_header.encode()) 409 | msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode() 410 | if msg_recv.find('200 OK') != -1: 411 | logging.info('first SETUP is ok, next second SETUP') 412 | return msg_recv, 2000 413 | else: 414 | msg_recv_dict = msg_recv.split('\r\n') 415 | logging.info('first SETUP request occur error: ') 416 | logging.info(msg_recv_dict[0]) 417 | return msg_recv, 4000 418 | 419 | # 模糊测试first setup请求 420 | def fuzz_first_setup_step(self, realm, nonce): 421 | step = "FIRST_SETUP" 422 | org_first_setup_header = self.gen_first_setup_header(realm, nonce) 423 | self.traverse_fuzz_var(step, org_first_setup_header) 424 | 425 | # 正确执行second setup请求 426 | def exec_second_setup_step(self, realm, nonce, session): 427 | str_setup_session_header = self.gen_second_setup_header(realm, nonce, session) 428 | str_setup_session_header = re.sub(self.regexp, self.delete_var_sign, str_setup_session_header) 429 | self.socket_send.send(str_setup_session_header.encode()) 430 | msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode() 431 | if msg_recv.find('200 OK') != -1: 432 | logging.info('second SETUP is ok, next PLAY') 433 | return msg_recv, 2000 434 | else: 435 | msg_recv_dict = msg_recv.split('\r\n') 436 | logging.info('second SETUP request occur error: ') 437 | logging.info(msg_recv_dict[0]) 438 | return msg_recv, 4000 439 | 440 | # 模糊测试second setup请求 441 | def fuzz_second_setup_step(self, realm, nonce, session): 442 | step = "SECOND_SETUP" 443 | org_second_setup_header = self.gen_second_setup_header(realm, nonce, session) 444 | self.traverse_fuzz_var(step, org_second_setup_header) 445 | 446 | # 正确执行play请求 447 | def exec_play_step(self, realm, nonce, session): 448 | str_play_header = self.gen_play_header(realm, nonce, session) 449 | str_play_header = re.sub(self.regexp, self.delete_var_sign, str_play_header) 450 | self.socket_send.send(str_play_header.encode()) 451 | msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode() 452 | if msg_recv.find('200 OK') != -1: 453 | logging.info('PLAY is ok, next GET_PARAMETER') 454 | return msg_recv, 2000 455 | else: 456 | msg_recv_dict = msg_recv.split('\r\n') 457 | logging.info('PLAY request occur error: ') 458 | logging.info(msg_recv_dict[0]) 459 | return msg_recv, 4000 460 | 461 | # 模糊测试play请求 462 | def fuzz_play_step(self, realm, nonce, session): 463 | step = "PLAY" 464 | org_play_header = self.gen_play_header(realm, nonce, session) 465 | self.traverse_fuzz_var(step, org_play_header) 466 | 467 | # 正确执行get parameter请求 468 | def exec_get_parameter_step(self,realm, nonce, session): 469 | str_get_parameter_header = self.gen_get_parameter_header(realm, nonce, session) 470 | str_get_parameter_header = re.sub(self.regexp, self.delete_var_sign, str_get_parameter_header) 471 | self.socket_send.send(str_get_parameter_header.encode()) 472 | msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode() 473 | if msg_recv.find('200 OK') != -1: 474 | logging.info('GET_PARAMETER is ok, next TEARDOWN') 475 | return msg_recv, 2000 476 | else: 477 | msg_recv_dict = msg_recv.split('\r\n') 478 | logging.info('GET_PARAMETER error: ') 479 | logging.info(msg_recv_dict[0]) 480 | return msg_recv, 4000 481 | 482 | # 模糊测试get parameter请求 483 | def fuzz_get_parameter_step(self,realm, nonce, session): 484 | step = "GET_PARAMETER" 485 | org_get_parameter_header = self.gen_get_parameter_header(realm, nonce, session) 486 | self.traverse_fuzz_var(step, org_get_parameter_header) 487 | 488 | # 正确执行teardown请求 489 | def exec_teardown_step(self,realm, nonce, session): 490 | str_teardown_header = self.gen_teardown_header(realm, nonce, session) 491 | str_teardown_header = re.sub(self.regexp, self.delete_var_sign, str_teardown_header) 492 | self.socket_send.send(str_teardown_header.encode()) 493 | msg_recv = self.socket_send.recv(config_dict['buffer_len']).decode() 494 | if msg_recv.find('200 OK') != -1: 495 | logging.info('TEARDOWN is ok, next finish') 496 | return msg_recv, 2000 497 | else: 498 | msg_recv_dict = msg_recv.split('\r\n') 499 | logging.info('TEARDOWN occur error: ') 500 | logging.info(msg_recv_dict[0]) 501 | return msg_recv, 4000 502 | 503 | # 模糊测试teardown请求 504 | def fuzz_teardown_step(self,realm, nonce, session): 505 | step = "TEARDOWN" 506 | org_teardown_header = self.gen_teardown_header(realm, nonce, session) 507 | self.traverse_fuzz_var(step, org_teardown_header) 508 | 509 | # 当为ALL时组织所有步骤进行模糊测试 510 | def exec_fuzz_rtsp(self): 511 | if config_dict["fuzz_step"] == "ALL": 512 | fuzz_steps = ["OPTIONS", "FIRST_DESCRIBE", "SECOND_DESCRIBE", "FIRST_SETUP", "SECOND_SETUP", "PLAY", "GET_PARAMETER", "TEARDOWN"] 513 | for fuzz_step in fuzz_steps: 514 | self.exec_fuzz_rtsp_flow(fuzz_step) 515 | else: 516 | fuzz_step = config_dict["fuzz_step"] 517 | self.exec_fuzz_rtsp_flow(fuzz_step) 518 | 519 | # 主要的模糊测试流程 520 | def exec_fuzz_rtsp_flow(self, fuzz_step): 521 | 522 | # 这些if是顺序性的,如果不是对该步进行模糊测试则该步要正确执行,以便服务器允许进入下一步 523 | # 如果要模糊测试OPTIONS请求,则模糊测试后直接退出 524 | if fuzz_step == "OPTIONS": 525 | self.fuzz_options_step() 526 | return True 527 | else: 528 | msg_recv,result_flag = self.exec_options_step() 529 | # 如果要模糊测试FIRST DESCRIBE请求,则模糊测试后直接退出 530 | if fuzz_step == "FIRST_DESCRIBE": 531 | self.fuzz_first_describe_step() 532 | return True 533 | else: 534 | msg_recv, result_flag = self.exec_first_describe_step() 535 | # 从FIRST_DESCRIBE返回结果中提取realm和nonce 536 | # 在RTSP中后续的请求这两个值都是不变的 537 | realm = self.extract_realm_value(msg_recv) 538 | nonce = self.extract_nonce_value(msg_recv) 539 | 540 | # 如果要模糊测试SECOND DESCRIBE请求,则模糊测试后直接退出 541 | if fuzz_step == "SECOND_DESCRIBE": 542 | self.fuzz_second_describe_step(realm,nonce) 543 | return True 544 | else: 545 | msg_recv, result_flag = self.exec_second_describe_step(realm,nonce) 546 | 547 | # 如果要模糊测试FIRST_SETUP请求,则模糊测试后直接退出 548 | if fuzz_step == "FIRST_SETUP": 549 | self.fuzz_first_setup_step(realm, nonce) 550 | return True 551 | else: 552 | msg_recv, result_flag = self.exec_first_setup_step(realm,nonce) 553 | # 从FIRST_SETUP返回结果中提取session 554 | session = self.extract_session_value(msg_recv) 555 | 556 | # 如果要模糊测试SECOND_SETUP请求,则模糊测试后直接退出 557 | if fuzz_step == "SECOND_SETUP": 558 | self.fuzz_second_setup_step(realm, nonce, session) 559 | return True 560 | else: 561 | msg_recv, result_flag = self.exec_second_setup_step(realm, nonce, session) 562 | 563 | # 如果要模糊测试PLAY请求,则模糊测试后直接退出 564 | if fuzz_step == "PLAY": 565 | self.fuzz_play_step(realm, nonce, session) 566 | return True 567 | else: 568 | self.exec_play_step(realm, nonce, session) 569 | 570 | # 如果要模糊测试GET_PARAMETER请求,则模糊测试后直接退出 571 | if fuzz_step == "GET_PARAMETER": 572 | self.fuzz_get_parameter_step(realm, nonce, session) 573 | return True 574 | else: 575 | msg_recv, result_flag = self.exec_get_parameter_step(realm, nonce, session) 576 | 577 | # 如果要模糊测试TEARDOWN请求,则模糊测试后直接退出 578 | if fuzz_step == "TEARDOWN": 579 | self.fuzz_teardown_step(realm, nonce, session) 580 | return True 581 | else: 582 | self.exec_teardown_step(realm, nonce, session) 583 | return True 584 | 585 | def __del__(self): 586 | self.socket_send.close() 587 | pass 588 | 589 | 590 | if __name__ == '__main__': 591 | rtsp_client = RtspFuzzer() 592 | # OPTIONS/FIRST_DESCRIBE/SECOND_DESCRIBE/FIRST_SETUP/SECOND_SETUP/PLAY/GET_PARAMETER/TEARDOWN 593 | # step = "OPTIONS" 594 | rtsp_client.exec_fuzz_rtsp() 595 | # rtsp_client.exec_full_request() 596 | # rtsp_client.exec_force_request() 597 | # uri = "rtsp://10.10.6.93:554/chIP=1/" 598 | # nonce = "3a260a0da860c9b55b8dbde939962287" 599 | # realm = "RTSP SERVER" 600 | # method = "DESCRIBE" 601 | # result = rtsp_client.gen_digest_response_value(uri, method, realm, nonce) 602 | # pass -------------------------------------------------------------------------------- /fuzzers/snmp_fuzzer.py: -------------------------------------------------------------------------------- 1 | import binascii 2 | import logging 3 | from scapy.all import * 4 | from common.logger import LogConfig 5 | 6 | class SnmpFuzzer(): 7 | def __init__(self): 8 | # snmp模糊测试的主要配置项 9 | # target_ip--snmp服务主机ip地址 10 | # target_port--snmp服务端口 11 | # snmp_hex_string--snmp应用层数据的十六进制字符串,我随便从一个snmp数据包截这来的 12 | # log_type--日志类型,console将日志打印到控制台,file将日志写入到文件 13 | # log_file_prefix--日志文件前辍,console时不生效 14 | self.config = { 15 | "target_ip":"10.10.6.98", 16 | "target_port":161, 17 | "snmp_hex_string":"302202010104067075626c6963a01502047c07ac6c0201000201003007300506012b0500", 18 | 'log_type': 'console', 19 | 'log_file_prefix': 'snmp' 20 | } 21 | # 设置日志格式 22 | LogConfig(log_type=self.config["log_type"], log_file_prefix=self.config["log_file_prefix"]) 23 | 24 | def fuzzSnmp(self): 25 | snmp_hex_string_lenght = self.config["snmp_hex_string"].__len__() 26 | # 遍历每个字节 27 | for index in range(int(snmp_hex_string_lenght/2)): 28 | # 每个字节遍历0-255 29 | for value in range(0xff): 30 | # 遍历字节之前的部分 31 | snmp_hex_string_payload_pre = binascii.a2b_hex(self.config["snmp_hex_string"][0:index*2]) 32 | # 当前遍历到的字节 33 | value_hex = value.to_bytes(1,"big") 34 | # 遍历字节之后的部分 35 | snmp_hex_string_payload_post = binascii.a2b_hex(self.config["snmp_hex_string"][index*2+2:]) 36 | # 构造snmp应用层数据 37 | snmp_hex_string_payload = snmp_hex_string_payload_pre + value_hex + snmp_hex_string_payload_post 38 | # 构造最终要发送的snmp数据包 39 | udp_packet = IP(dst=self.config["target_ip"])/UDP(sport=9876,dport=self.config["target_port"])/snmp_hex_string_payload 40 | # 发送数据包并接收响应 41 | response_packet = sr1(udp_packet) 42 | logging.info(f"{index *2}-{value_hex}-{response_packet.show()}") 43 | 44 | 45 | if __name__ == "__main__": 46 | snmp_fuzzer = SnmpFuzzer() 47 | snmp_fuzzer.fuzzSnmp() 48 | -------------------------------------------------------------------------------- /payloads/format_string.txt: -------------------------------------------------------------------------------- 1 | %d 2 | %s 3 | %c 4 | %o 5 | %x 6 | %X 7 | %e 8 | %E 9 | %f 10 | %g 11 | %G 12 | %0xa 13 | %- 14 | %d%d 15 | %s%s 16 | %c%c 17 | %o%o 18 | %x%x 19 | %X%X 20 | %e%e 21 | %E%E 22 | %f%f 23 | %g%g 24 | %G%G 25 | %0xa%0xa 26 | %-%- 27 | 28 | %d%d%d%d%d 29 | %s%s%s%s%s 30 | %c%c%c%c%c 31 | %o%o%o%o%o 32 | %x%x%x%x%x 33 | %X%X%X%X%X 34 | %e%e%e%e%e 35 | %E%E%E%E%E 36 | %f%f%f%f%f 37 | %g%g%g%g%g 38 | %G%G%G%G%G 39 | %0xa%0xa%0xa%0xa 40 | %-%-%-%-%- 41 | 42 | %1024d 43 | %2048d 44 | %4096d 45 | %.1024d 46 | %.2048d 47 | %.4096d 48 | %1024c 49 | %2048c 50 | %4096c 51 | %.1024c 52 | %.2048c 53 | %.4096c 54 | 55 | %1024f 56 | %2048f 57 | %4096f 58 | %.1024f 59 | %.2048f 60 | %.4096f 61 | %s%c%d%f 62 | 63 | %s%p%x%d 64 | %p%p%p%p 65 | %x%x%x%x 66 | %d%d%d%d 67 | %s%s%s%s 68 | %99999999999s 69 | %08x 70 | %20d 71 | %20n 72 | %20x 73 | %20s 74 | %d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d 75 | %i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i%i 76 | %o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o%o 77 | %u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u%u 78 | %x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x%x 79 | %X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X%X 80 | %a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a%a 81 | %A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A%A 82 | %e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e%e 83 | %E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E%E 84 | %f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f%f 85 | %F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F%F 86 | %g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g%g 87 | %G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G%G 88 | %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s 89 | %p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p 90 | %#0123456x%08x%x%s%p%d%n%o%u%c%h%l%q%j%z%Z%t%i%e%g%f%a%C%S%08x%% 91 | XXXXX.%p 92 | XXXXX`perl -e 'print ".%p" x 80'` 93 | `perl -e 'print ".%p" x 80'`%n 94 | %08x.%08x.%08x.%08x.%08x\n 95 | XXX0_%08x.%08x.%08x.%08x.%08x\n 96 | %.16705u%2\$hn 97 | \x10\x01\x48\x08_%08x.%08x.%08x.%08x.%08x|%s| 98 | AAAAA%c 99 | AAAAA%d 100 | AAAAA%e 101 | AAAAA%f 102 | AAAAA%I 103 | AAAAA%o 104 | AAAAA%p 105 | AAAAA%s 106 | AAAAA%x 107 | AAAAA%n 108 | ppppp%c 109 | ppppp%d 110 | ppppp%e 111 | ppppp%f 112 | ppppp%I 113 | ppppp%o 114 | ppppp%p 115 | ppppp%s 116 | ppppp%x 117 | ppppp%n 118 | %@ 119 | %@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@% -------------------------------------------------------------------------------- /payloads/overflow.txt: -------------------------------------------------------------------------------- 1 | 2 | "A"*10 3 | "A"*30 4 | "A"*50 5 | "A"*100 6 | "A"*257 7 | -------------------------------------------------------------------------------- /payloads/random_num.txt: -------------------------------------------------------------------------------- 1 | -1 2 | -20 3 | -268435455 4 | 1 5 | 255 6 | 256 7 | 257 8 | 65536 9 | 65537 10 | 16777215 11 | 16777216 12 | 16777217 13 | 0xfffffff 14 | 1111111111 15 | 11111111111111111111111111111111111111111111111111 16 | 11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111 17 | 1.1 18 | 1.1.1.1 19 | 1.111111111111111111111111111111111111111111 20 | 111111 1111 21 | 111111-1111 22 | 111111+1111 23 | 111111*1111 24 | 111111/1111 -------------------------------------------------------------------------------- /payloads/special_char.txt: -------------------------------------------------------------------------------- 1 | ` 2 | ~ 3 | ! 4 | @ 5 | # 6 | $ 7 | % 8 | ^ 9 | & 10 | * 11 | ( 12 | ) 13 | - 14 | _ 15 | = 16 | + 17 | `` 18 | ~~ 19 | !! 20 | @@ 21 | ## 22 | $$ 23 | %% 24 | ^^ 25 | && 26 | ** 27 | (( 28 | )) 29 | -- 30 | __ 31 | == 32 | ++ 33 | ````` 34 | ~~~~~ 35 | !!!!! 36 | @@@@@ 37 | ##### 38 | $$$$$ 39 | %%%%% 40 | ^^^^^ 41 | &&&&& 42 | ***** 43 | ((((( 44 | ))))) 45 | ----- 46 | _____ 47 | ===== 48 | +++++ 49 | `````````` 50 | ~~~~~~~~~~ 51 | !!!!!~~~~~ 52 | @@@@@@@@@@ 53 | ########## 54 | $$$$$$$$$$ 55 | %%%%%%%%%% 56 | ^^^^^^^^^^ 57 | &&&&&&&&&& 58 | ********** 59 | (((((((((( 60 | )))))))))) 61 | ---------- 62 | __________ 63 | ========== 64 | ++++++++++ 65 | [ 66 | { 67 | ] 68 | } 69 | \\ 70 | |" 71 | "; 72 | : 73 | ' 74 | \" 75 | , 76 | < 77 | . 78 | > 79 | / 80 | ? 81 | [[ 82 | {{ 83 | ]] 84 | }} 85 | \\\\ 86 | || 87 | ;; 88 | :: 89 | '' 90 | "" 91 | ,, 92 | << 93 | .. 94 | >> 95 | // 96 | ?? 97 | [[[[[ 98 | {{{{{ 99 | ]]]]] 100 | }}}}} 101 | \\\\\\\\\\\\\\ 102 | ||||| 103 | ;;;;; 104 | ::::: 105 | ''''' 106 | """"" 107 | ,,,,, 108 | <<<<< 109 | ..... 110 | >>>>> 111 | ///// 112 | ????? 113 | [[[[[[[[[[ 114 | {{{{{{{{{{ 115 | ]]]]]]]]]] 116 | }}}}}}}}}} 117 | \\\\\\\\\\\\\\\\\\\\\\\\\\\\ 118 | |||||||||| 119 | ;;;;;;;;;; 120 | :::::::::: 121 | '''''''''' 122 | """""""""" 123 | ,,,,,,,,,, 124 | <<<<<<<<<< 125 | .......... 126 | >>>>>>>>>> 127 | ////////// 128 | ?????????? 129 | 130 | · 131 | ~ 132 | ! 133 | @ 134 | # 135 | ¥ 136 | % 137 | …… 138 | & 139 | * 140 | ( 141 | ) 142 | - 143 | —— 144 | = 145 | + 146 | ·· 147 | ~~ 148 | !! 149 | @@ 150 | ## 151 | ¥¥ 152 | %% 153 | ………… 154 | && 155 | ** 156 | (( 157 | )) 158 | -- 159 | ———— 160 | == 161 | ++ 162 | ····· 163 | ~~~~~ 164 | !!!!! 165 | @@@@@ 166 | ##### 167 | ¥¥¥¥¥ 168 | %%%%% 169 | ………………………… 170 | &&&&& 171 | ***** 172 | ((((( 173 | ))))) 174 | ----- 175 | —————————— 176 | ===== 177 | +++++ 178 | ·········· 179 | ~~~~~~~~~~ 180 | !!!!!!!!!! 181 | @@@@@@@@@@ 182 | ########## 183 | ¥¥¥¥¥¥¥¥¥¥ 184 | %%%%%%%%%% 185 | …………………………………………………… 186 | &&&&&&&&&& 187 | ********** 188 | (((((((((( 189 | )))))))))) 190 | ---------- 191 | ———————————————————— 192 | ========== 193 | ++++++++++ 194 | 【 195 | { 196 | 】 197 | } 198 | 、 199 | | 200 | ; 201 | : 202 | ’ 203 | ” 204 | , 205 | 《 206 | 。 207 | 》 208 | 、 209 | ? 210 | 【【 211 | {{ 212 | 】】 213 | }} 214 | 、、 215 | || 216 | ;; 217 | :: 218 | ‘’ 219 | ”“ 220 | ,, 221 | 《《 222 | 。。 223 | 》》 224 | 、、 225 | ?? 226 | 【【【【【 227 | {{{{{ 228 | 】】】】】 229 | }}}}} 230 | 、、、、、 231 | ||||| 232 | ;;;;; 233 | ::::: 234 | ‘’‘’‘ 235 | ”“”“” 236 | ,,,,, 237 | 《《《《《 238 | 。。。。。 239 | 》》》》》 240 | 、、、、、 241 | ????? 242 | 【【【【【【【【【【 243 | {{{{{{{{{{ 244 | 】】】】】】】】】】 245 | }}}}}}}}}} 246 | 、、、、、、、、、、 247 | |||||||||| 248 | ;;;;;;;;;; 249 | :::::::::: 250 | ‘’‘’‘‘’‘’‘ 251 | ”“”“””“”“” 252 | ,,,,,,,,,, 253 | 《《《《《《《《《《 254 | 。。。。。。。。。。 255 | 》》》》》》》》》》 256 | 、、、、、、、、、、 257 | ?????????? 258 | 259 | ` 260 | ~ 261 | ! 262 | @ 263 | # 264 | $ 265 | % 266 | ^ 267 | & 268 | * 269 | ( 270 | ) 271 | - 272 | _ 273 | = 274 | + 275 | `` 276 | ~~ 277 | !! 278 | @@ 279 | ## 280 | $$ 281 | %% 282 | ^^ 283 | && 284 | ** 285 | (( 286 | )) 287 | -- 288 | __ 289 | == 290 | ++ 291 | ````` 292 | ~~~~~ 293 | !!!!! 294 | @@@@@ 295 | ##### 296 | $$$$$ 297 | %%%%% 298 | ^^^^^ 299 | &&&&& 300 | ***** 301 | ((((( 302 | ))))) 303 | ----- 304 | _____ 305 | ===== 306 | +++++ 307 | `````````` 308 | ~~~~~~~~~~ 309 | !!!!!!!!!! 310 | @@@@@@@@@@ 311 | ########## 312 | $$$$$$$$$$ 313 | %%%%%%%%%% 314 | ^^^^^^^^^^ 315 | &&&&&&&&&& 316 | ********** 317 | (((((((((( 318 | )))))))))) 319 | ---------- 320 | __________ 321 | ========== 322 | ++++++++++ 323 | [ 324 | { 325 | ] 326 | } 327 | \ 328 | | 329 | ; 330 | : 331 | ' 332 | " 333 | , 334 | < 335 | . 336 | > 337 | / 338 | ? 339 | [[ 340 | {{ 341 | ]] 342 | }} 343 | \\ 344 | || 345 | ;; 346 | :: 347 | '' 348 | "" 349 | ,, 350 | << 351 | .. 352 | >> 353 | // 354 | ?? 355 | [[[[[ 356 | {{{{{ 357 | ]]]]] 358 | }}}}} 359 | \\\\\ 360 | ||||| 361 | ;;;;; 362 | ::::: 363 | ''''' 364 | """"" 365 | ,,,,, 366 | <<<<< 367 | ..... 368 | >>>>> 369 | ///// 370 | ????? 371 | [[[[[[[[[[ 372 | {{{{{{{{{{ 373 | ]]]]]]]]]] 374 | }}}}}}}}}} 375 | \\\\\\\\\\ 376 | |||||||||| 377 | ;;;;;;;;;; 378 | :::::::::: 379 | '''''''''' 380 | """""""""" 381 | ,,,,,,,,,, 382 | <<<<<<<<<< 383 | .......... 384 | >>>>>>>>>> 385 | ////////// 386 | ?????????? -------------------------------------------------------------------------------- /payloads/unicode.txt: -------------------------------------------------------------------------------- 1 | \000x99\000x99\000x99\000x99\000x99\000x99\000x99\000x99\000x99 2 | \000xCB\000xCB\000xCB\000xCB\000xCB\000xCB\000xCB\000xCB\000xCB 3 | \000xCD\000xCD\000xCD\000xCD\000xCD\000xCD\000xCD\000xCD\000xCD 4 | %u00 5 | %u000 6 | %u00%u00 7 | %u000%u000 --------------------------------------------------------------------------------