学习fuzz
,狂看代码。
BFuzz
是github
上的开源的一款浏览器fuzz
工具,现有的代码感觉也不能算得上fuzz
工具,最多说得上是用浏览器跑html
页面测试用例的工具。
基本原理
用法是:
warmachine@ftw:~/BFuzz$ ./generate.sh
warmachine@ftw:~/BFuzz$ python BFuzz.py
Enter the browser type:
1: Chrome
2: Firefox
>>
该工具的原理是先用domato生成测试用例,保存在recurve
目录中。然后根据选择fuzz
的浏览器类型,遍历recurve
目录下的html
文件,并调用浏览器进行加载,来看是否会造成浏览器崩溃,以此来实现fuzz
。
源码分析
样例生成
首先看generate.sh
调用domato
来生成测试用例,该sh
内容如下:
#!/bin/bash
cd domato
python generator.py --output_dir ../recurve/ --no_of_files 50
可以看到进到集成的domato
目录下,调用generator.py
生成50
个测试用例,保存在recurve
目录下。
对于测试用例的生成与变异,该框架并没有做什么操作,而是直接用的现成的domato
。domato
是基于规则生成的样例生成工具,该框架相对还比较复杂,对于该框架的分析不属于BFuzz
的分析范畴,可以去读一读domato
源码。
样例运行
生成了样例之后,就是用浏览器运行生成的样例并查看生成的结果,来看BFuzz
是如何做的。
BFuzz.py
是实现该功能的代码,代码行数只有60
行,功能是简单的目录遍历并调用浏览器执行样本。
下面对源码进行分析,入口是runWebTest
函数:
// BFuzz.py: 59
if __name__ == '__main__':
runWebTest()
// BFuzz.py: 9
def runWebTest():
dir_path = os.path.dirname(os.path.realpath(__file__))
print("Enter the browser type: \n 1: Chrome \n 2: Firefox")
browserType = input('>>')
timeout = input(
"Duration the browser process should wait before stopping(>=15 seconds to ensure full load of page):")
checkValidBrowserType(browserType)
for root, folders, fileNames in os.walk("recurve"):
for fileName in fileNames:
if not fileName.endswith('.html'):
continue
processCommand = getBrowserApplication(browserType)
if processCommand is not None:
setupExploit(dir_path, fileName, processCommand, root)
runExploit(processCommand, timeout)
else:
print "Invalid Browser Type"
runWebTest
函数先获取项目的文件夹路径dir_path
,然后让输入要fuzz
的类型是chrome
还是firefox
(项目只支持对这二者的fuzz
),然后再输入一个timeout
,该变量让用户决定每次启动浏览器运行一个样例要等多久。
输入完成后,调用checkValidBrowserType
检查选择的浏览器类型是否正确。
// BFuzz.py: 53
def checkValidBrowserType(browserType):
if browserType not in [1, 2]:
print("Incorrect option!!")
sys.exit(0)
在检查完类型以后,for root, folders, fileNames in os.walk("recurve")
遍历recurve
文件夹,如果文件后缀不是html
,则跳过。
根据选择的浏览器类型,调用getBrowserApplication
函数获取稍后启动浏览器所需的路径以及参数。可以看到对于chrome
浏览器,启动的命令是google-chrome
;对于firefox
,启动的命令是firefox -new-tab
。
// BFuzz.py: 43
def getBrowserApplication(browserType):
if browserType == 1:
processCommand = ['google-chrome']
elif browserType == 2:
processCommand = ['firefox', '-new-tab']
else:
processCommand = None
return processCommand
获取了程序的启动命令后,调用setupExploit
函数来构造最终的启动命令。将html
文件路径作为参数拼接到启动命令的后面,形成完整的启动命令。如样例的绝对路径是/tmp/recurve/a.html
的话,最终chrome
运行的参数是google-chrome file://tmp/recurve/a.html
,firefox -new-tab file://tmp/recurve/a.html
。
// BFuzz.py: 36
def setupExploit(dir_path, fileName, processCommand, root):
filePath = os.path.join(dir_path, root, fileName)
filePath = "file://" + filePath
print "Testing with exploit:" + filePath
processCommand.append(filePath)
最终调用runExploit
函数来启动浏览器运行样例,调用subpocess.Popen
直接启动浏览器运行样例。
// BFuzz.py: 28
def runExploit(processCommand, timeout):
print "Executing Command: " + " ".join(processCommand)
process = subprocess.Popen(processCommand)
sleep(timeout)
# print "Killing browser process.... bye bye"
sleep(3)
总结
总的来说这个项目不是一个完整的fuzzer
,它没有崩溃监控,也没有样本保存,从它的ToDo
中也可以看到它想做的事,但是项目已经很久没更新了,计划成了永远的计划。
ToDo
Handle Exeception, Add banner, Optimize Code, Mangle testcases.
但是从这个项目中也可以看到一个基本的fuzzer
的影子,看到了样本的生成以及运行,可以作为fuzzer
学习的demo
。不过domato
才是样例生成的关键,它里面的代码不是那么简单。