Download as pdf or txt
Download as pdf or txt
You are on page 1of 6

JFD: Automatic Java Fuzz Driver Generation

Zhuo Chen Yongjun Wang†


College of Computer College of Computer
National University of Defense Technology National University of Defense Technology
Changsha Hunan China Changsha Hunan China

chenzhuo9797@126.com Corresponding author wangyongjun@nudt.edu.cn

ABSTRACT top spot from April 2015 to April 2020, only to be overtaken by C
in May 2020 to fall to second place.
Java is widely used in many areas. There have been a lot of works
Fuzzing is one of the most popular software testing techniques,
on improving the security of Java. In the industry, fuzzing is the
which can find various weaknesses in the program by generating a
most efficient software testing technique to discover real-world
large number of test inputs. Fuzzing was first proposed by Miller
vulnerabilities and improve software security. Recent efforts are
et al.[4], the University of Wisconsin, the USA in 1988, after which
seen to make library fuzzing more automatically and have
it developed into an effective, fast and practical method for finding
performed well in general library fuzzing. However, these tools
software vulnerabilities.
cannot solve problems in Java library fuzzing appropriately. In this
At present, most studies are mainly focused on general
paper, we present JFD, an automatic Java fuzz driver generation
programs that can be executed directly, but a large number of
system, which can generate fuzz drivers based on consumer
library programs are often ignored because they cannot be
programs, that utilize target library programs. Our approach
executed directly. Compared with general programs, fuzzy testing
consists of three parts: a static-analysis-based method to analyze
of library programs has more problems. Libraries cannot be run as
call dependencies graphs of target Java library, a value-set-based
stand-alone programs, instead, libraries need to be invoked through
method to analyze argument dependencies graphs of target Java
another application. Triggering vulnerabilities deep in the library
library, and a method to synthesize fuzz drivers in the style of JQF.
remains challenging because a specific sequence of API calls is
We then evaluate JFD on JVM native libraries. JFD can generate
required to build the necessary state.
appropriate fuzz drivers.
The common method to solve the fuzzing of library programs
is to write a fuzz driver manually which can be executed directly
CCS CONCEPTS
by analyzing the API call dependency of the library under test, and
• Software and its engineering → Software creation and then use various fuzzer to test. However, due to the diversity of
management → Software verification and validation → Software libraries, this method requires testers to spend a lot of energy and
defect analysis→Software testing and debugging • Security and has a low level of automation and intelligence.
privacy→Software and application security→Software security There has been some work into automated fuzz driver
generation. JDriver[1] is an automatic driver class generation
engineering
framework for AFL-based fuzzing tools. JDriver can generate
method sequences to mutate the status of the class instances.
KEYWORDS
However, its analysis of the dependency is simple, resulting in the
Java, fuzzing, fuzz driver generation, JQF, software security generated fuzzing driver classes are not efficient. FUDGE[2] is
Google's recently introduced semi-automatic fuzz driver
generation framework. FUDGE constructs the fuzz driver by
1 Introduction
scanning the program's source code for vulnerable function calls
Java is one of the most popular programming languages. It is and generates the fuzzy driver by parameter substitution.
widely used in desktop applications, Web applications, distributed FuzzGen[3] is another tool for the automatic generation of fuzz
systems, and embedded system applications due to its "write once, drivers. By analyzing existing programs of calling libraries,
run many places" characteristic. In the TIOBE Index, which tracks FuzzGen obtains the dependencies between APIs of the target
trends in the popularity of programming languages, Java held the library and then generates fuzz drivers according to the
dependencies. FuzzGen can generate fuzz drivers based on
Permission to make digital or hard copies of all or part of this work for existing programs, but only supports C language, not Java
personal or classroom use is granted without fee provided that copies are language.
not made or distributed for profit or commercial advantage and that copies
bear this notice and the full citation on the first page. Copyrights for
We design and implement JFD, an automatic Java fuzz driver
components of this work owned by others than ACM must be honored. generation system. It analyzes dependencies among APIs based on
Abstracting with credit is permitted. To copy otherwise, or republish, to the analysis of existing programs using the target library. Based on
post on servers or to redistribute to lists, requires prior specific permission the dependencies among APIs, JFD generates Java fuzz drivers for
and/or a fee. Request permissions from Permissions@acm.org.
EITCE 2021, October 22–24, 2021, Xiamen, China
© 2021 Association for Computing Machinery.
ACM ISBN 978-1-4503-8432-2/21/10…$15.00
https://doi.org/10.1145/3501409.3501564
862
JQF, which is widely used in fuzzing Java programs. Overall, we theoretically explore all the execution paths of the target program,
make the following contributions: and realizes the comprehensive and fast search of the target
(1) Based on existing programs that use the target library, program through dynamic symbol execution and coverage
analyzing dependencies among APIs, including calling maximization heuristic search algorithm. Unlike black-box
dependencies and argument dependencies. fuzzing technology, white-box fuzzing technology requires
(2) Based on the dependencies, generating Java fuzz drivers information from the target program and uses the information
that can efficiently expose vulnerabilities in the target needed to guide the generation of test cases. Specifically, using a
library for JQF, the most popular Java fuzzer, given specific input to start the executable, white-box fuzzing tools
automatically. under the input along the path of execution of all the conditional
The remaining paper is organized as below: Section 2 statements to collect symbol constraints. So, after one execution,
introduces related works. Section 3 describes our approach, the white-box fuzzing tool combines all the symbolic constraints
Section 4 depicts the implementation, and Section 5 shows our together to form a path constraint and then the white-box fuzzing
evaluation results. We illustrate our thoughts on future work in tool systematically negates one of the constraints and solves the
Section 6, and conclusions are given in Section 7. new path constraint and the new test case directs the program to
run a different execution path. Using a heuristic search algorithm,
the white-box fuzzing tool can find errors as quickly as possible in
2 Related Work the target program theoretically, white-box fuzzing can generate
test cases that cover all program paths. However, in practical, due
2.1 Fuzzing to the numerous execution paths in the actual software system and
According to the different methods of generating test cases, the low precision of solving constraints in the symbolic execution
fuzzing technology can be divided into fuzzing technology based process, the code coverage of white-box fuzzing cannot reach
on generation and fuzzing technology based on mutation. Fuzzing 100%. One of the most famous white-box fuzzing tools is
technology based on generation generally produces test cases SAGE[5]. SAGE targets large Windows applications and uses
under the guidance of prior knowledge according to defined rules. some optimizations to handle a large number of execution paths.
The prior knowledge determines the quality of the generated test 2.1.3 Grey-box Fuzzing. Grey-box fuzzing technology is between
cases. A good generation model can produce more effective test black-box fuzzing technology and white-box fuzzing technology.
cases, so as to cover more of the input space. However, the The common method of grey-box fuzzing is code implement.
dependence on prior knowledge limits the application scope of this Through this method, the grey-box fuzzing tool can obtain the code
kind of fuzzy testing tool. Mutation-based fuzzing is to modify coverage of the target program at run time, and then use this
existing test cases to generate new test cases. This approach is information to adjust its mutation strategy, to create a more
relatively less dependent on prior knowledge. Due to the locality execution path, or to find vulnerabilities in faster test cases.
of program input, the test cases generated by such tools cover Another method of grey-box fuzzing is taint analysis, which can
fewer paths. trace taint data stream by code implement.
According to the understanding degree of the program under AFL[6] is a representative of grey-box fuzzing tools. It aims at
test, fuzzing technology can be divided into black-box fuzzing improving coverage and generating test cases based on mutation.
technology, white-box fuzzing technology, grey-box fuzzing AFL uses branches as the target of coverage. AFL determines
technology. The information includes code coverage, data flow whether the input execution covers the new branch according to
coverage, the program's memory usage, CPU utilization, or any the items in the branch table. AFL defines a lot of modification
other information that can guide test case generation. operations, including random modification and modification with
2.1.1 Black-box Fuzzing. Black-box fuzzing is also known as specific values. The mutation strategy based on the genetic
black-box random testing. Black-box fuzzing techniques do not algorithm adopted by AFL makes it faster, more stable, and has
require any information from the target program or input format, higher coverage than the previous fuzzing tools. In practice, AFL
but instead create input by random mutations (such as bit-flipping found a number of real vulnerabilities.
byte copy, and byte deletion, etc.) of the seed file of a given format 2.1.4 Comparison. Generally speaking, the traditional black-box
through some predefined rules. Recently the black-box fuzzing fuzzing only uses random mutation methods to generate test cases,
also uses grammar or enters a specific knowledge to generate half- which cannot achieve high code coverage. It usually can only find
black-box fuzzing effective input test because of its effectiveness shallow program vulnerabilities. its advantages are lightweight,
in discovering software vulnerabilities and use of simple, very fast, and easy to use. In contrast, white-box fuzzing or grey-box
popular in the software industry. However, the disadvantage of the fuzzing can achieve higher code coverage and thus discover more
black-box fuzzing technique is also obvious. It is difficult to hidden program vulnerabilities, but they require more time and
generate test cases covering a large number of execution paths in space and are more complex to build.
target programs. Because of this blindness, black-box fuzzing Grey-box fuzzing is similar to white-box fuzzing in that both
often has low code coverage in practice. methods use information about the target program to guide the
2.1.2 White-box Fuzzing. Based on the internal logic knowledge generation of test cases. But there is an obvious difference: the
grey-box fuzzing only uses some runtime information about the
of the target program, the white box fuzzing uses a method that can
target program (such as code coverage, tainted data flow, etc.) to

863
determine the state of the explored path. Because grey-box fuzzing mutate the status of the class instances. However, its analysis of
uses only partial information to guide test case generation, it does the dependency is simple, resulting in the generated fuzzing driver
not guarantee that using this information will generate better test classes are not efficient.
cases to override new paths or trigger specific program FUDGE is Google's recently introduced semi-automatic fuzz
vulnerabilities. In contrast, white-box fuzzing systematically driver generation framework. FUDGE constructs fuzz drivers by
explores all execution paths using the source code or binary code scanning the program's source code for vulnerable function calls
of the target program. By using symbolic execution and constraint and generates fuzz drivers by parameter substitution. FUDGE
solvers, white-box fuzzing ensures that the resulting test cases will works well in specific scenarios, but it tends to produce too many
lead the target program to explore new execution paths. Therefore, fuzz drivers for large projects where invalid results need to be
white-box fuzzing can help to reduce blindness in fuzzing more manually removed.
thoroughly. However, compared to grey-box fuzzing, white-box FuzzGen is another tool for the automatic generation of fuzz
fuzzing is not very practical in the industry because it is very drivers. By analyzing existing programs using target libraries,
expensive in terms of time and resource consumption and faces FuzzGen obtains the dependencies between APIs of the target
many challenges (such as path explosion, memory modeling, and library and then generates fuzz drivers according to the
constraint solving, etc.). To sum up, both methods use the dependencies. FuzzGen can generate fuzz drivers based on
information of the target program to reduce the blindness of black- existing programs, but only supports C language, not Java
box fuzzing, but to different degrees. language.

2.2 Java Fuzzing


JFuzz[7] is a mutation method combined with a disintegration test
3 Approach
proposed by Zhu et al. Disintegration test is a test based on
3.1 Overview
disintegration relationships. JFuzz defines a variety of heuristics
mutation operations. However, JFuzz needs to be defined by users, Figure 1 shows the high-level architecture of the JFD system. First,
and it is difficult for users who are not familiar with the program JFD extracts all the APIs from library programs. Then, the API call
under test to find appropriate metamorphosis relationships, which dependency of the target library is obtained through static analysis
leads to JFuzz has not been widely used of library consumer programs, which use the target library, and the
Kelinci[8] is an agent between AFL and Java programs parameter dependency in the call relationship is obtained through
implemented by Kersten et al. Kelinci transplanted the implement value set analysis, so as to obtain the API dependency graph. Then
module of AFL and implement the code used for statistical branch JFD synthesizes the fuzz driver for the target library from the API
coverage into the program under test. After the fuzzing starts, dependence graph.
Kelinci receives test cases with AFL and feeds back branch
coverage and execution results to AFL. In this way, Kelinci
realized fuzzing for Java programs. Because AFL’s test case is
stored in the file, it is relatively easy to test for methods that
process files, but for methods that do not process files, testers need
to read the contents of the file in an appropriate way and construct
variables of the appropriate type for the function under test.
JQF[9] is a coverage-guided Java fuzzing platform
implemented by Rohan Padhye et al. JQF contains AFL, Zest[10], Figure 1: High-level overview
PerfFuzz[11], and other test backends, while also allowing for
expansion. JQF provides a good foundation for Java fuzzing by 3.2 API Dependencies Analysis
enabling practitioners to use familiar attribute-based testing styles, The key algorithm of the API dependencies analysis is shown in
using coverage-guided fuzzing for test programs that require Algorithm 1. Firstly, the API list is extracted by analyzing target
structured input, and enabling researchers to implement new library programs. Then, JFD analyzes consumer programs utilizing
coverage-guided fuzzing algorithms to drive attribute-based the target library by static analysis to get the API call dependencies
testing. of the target library. Finally, the value-set analysis of the target
library program is continued, and the dependencies between the
2.3 Automatic Fuzz Driver Generation arguments of APIs in the API dependencies graph is analyzed, and
JDriver is an automatic driver class generation framework for the API dependencies graph is supplemented. For example, the
AFL-based fuzzing tools. It can build driver class for method result of the previous API call is the first parameter of the next API
whether processing files or not. It analyzes the call/modification call, or a parameter is fixed.
relationship between each field and method to get
call/modification graphs. Then it generates fuzzing driver classes
according to the graphs. JDriver can generate method sequences to

864
Table 1: Argument attributes from value-set analysis
Algorithm 1 Dependence analysis
Attribute Description
Input: libProg (Library program)
dead Not used
consumerList (consumer program)
invariant Not modified
Output: apiDepGraph (API Dependence Graph)
predefined A value in a set
1 apiList ← newArrayList()
random A random value
2 for method in libProg do
3 apiList.add(method) output As output

4 end for dependent Dependent on another argument

5 apiDepGraph ← newGraph() 3.3 Fuzz Driver Synthesis


6 for consumerProg in consumerList do The fuzz driver synthesis is based on the output of API
dependencies analysis, API dependencies graph. Based on the API
7 valueSet ← newArrayList()
dependencies graph, JFD sets the API call sequence of the API. In
8 for stmt in consumerProg do addition, JFD set arguments according to their different types: for
arguments that can be determined in the API dependencies graph,
9 valueSet.update() arguments are set according to the analysis results; For arguments
10 if stmt ∈ apiList do that cannot be determined by static analysis, the arguments are set
as target arguments of fuzzing, which will be tested by fuzzer later.
11 apiDepGraph.add(stmt)
12 end if
4 Implementation
13 apiDepGraph.argDep(valueSet) Our automatic fuzz driver generation approach has been
14 end for implemented into JFD with around 10,000 lines of Java code. It
uses the Java optimization framework Soot[12][13][14], which can
3.2.1 Call dependencies analysis. An appropriate sequence of API support static analysis of Java well, to perform API extraction and
calls is the basis for generating fuzz drivers. If the sequence of API API dependencies analysis. JFD takes library programs and library
calls is not set properly, the fuzzer will consume a lot of energy in consumer programs as input, and produces fuzz driver in the
shallow error checking, reducing the efficiency of the generated following steps:
fuzz driver. (1) extracting APIs. JFD starts with iterating all of the target
For each consumer, JFD iterates through its control flow library programs to extract all of the APIs for the
diagram through static analysis, extracting all APIs of the target following steps.
library, resulting in call dependencies graphs. Because the target (2) analyzing API call dependencies. JFD iterates each
library APIs may be scattered across branches of the control flow consumer analyzing call dependencies according to the
graph, it may end up with many call dependencies graphs. algorithm described in Section 3.2 and 3.2.1.
Therefore, the merge of dependencies graphs is important. (3) analyzing API argument dependencies. JFD iterates each
To merge the call dependencies graphs, JFD iterates through consumer analyzing argument dependencies according to
each one. Two call dependencies graphs can be merged if and only the algorithm described in Section 3.2.2.
if they have at least one node in common. The same node means: (4) synthesizing fuzz drivers. Finally, JFD synthesizes fuzz
first, the API name is the same; Second, the API takes the same drivers based on API dependencies graphs in the style of
arguments. JQF fuzzer.
3.2.2 Argument dependencies analysis. Argument dependence is
as important as call dependencies. Fuzz drivers must not only
provide the correct sequence of API but also ensure the accuracy
5 Evaluation
of parameter passing between APIs. Otherwise, the fuzzer will also We first demonstrate our fuzz driver generation with a simple
consume a lot of energy in shallow error checking. example in Section 5.1. Then, we work on the JVM native library
In the dependency analysis module, the dependency between javax.xml to evaluate the fuzz driver in Section 5.2.
arguments is obtained by value-set analysis. By traversing
sequential statements, different attributes of each parameter can be 5.1 Simple Example
obtained based on data flow analysis. The set of possible attributes We use a simple example to illustrate how our approach works.
is shown in Table 1. For example, the value of a parameter that is Figure 2 shows the source code of the library. The class Foo has
never modified is set to invariant. three member methods: Foo (Implicit constructor), foo_init (lines

865
4-9), and foo_add (lines 11-14). Figure 3 shows the source code of
the library consumer. The class Consumer invokes APIs in the
library Foo in the sequence of Foo (line 8), foo_init (line 9), and
twice foo_add (line 10, 11). Besides, the arguments of the two calls
to foo_add are related. Figure 4 shows the source code of the fuzz
driver generated. It calls APIs according to the consumer's call
sequence and sets the arguments appropriately.

Figure 4: The example fuzz driver

5.2 Evaluating Fuzz Driver Generation


Figure 2: The example library
Figure 5 shows the source code of a fuzz driver generated by JFD
for javax.xml. The fuzz driver initializes, then reads and parses the
XML string from the file, and finally gets the information in the
XML.

Figure 3: The example library consumer

Figure 5: Sample fuzz driver generated by JFD

866
[17] Jun Li, Bodong Zhao and Chao Zhang. “Fuzzing: a survey” Spring
6 Discussion and Future Work Cybersecurity. 2018
JFD can generate Java fuzz drivers automatically and appropriately. [18] James Fell. “A Review of Fuzzing Tools and Methods”. 2017
[19] Marcel B., Cristian C, et al. “Fuzzing: Challenges and Reflections”. IEEE
It still has some opportunities for improvement. Computer Society. 2020
For now, JFD only supports a single library. There are many [20] Valentin J. et al. “The Art, Science, and Engineering of Fuzzing: A Survey”
IEEE Transactions on Software Engineering. 2019
scenes that APIs from different libraries interact in Java programs. [21] Hongliang, Liang, Xiaoxiao, et al. “Fuzzing: State of the Art”. IEEE
Supporting multiple libraries may means the challenge of complex Transactions on Reliability, 2018
dependencies analysis. In the future, we will extend JFD to support [22] Lindholm T, Yellin F, Bracha G, et al. The Java® Virtual Machine Specification
[M/OL]. 2014. http://docs.oracle.com/javase/specs/jvms/se8/jvms8.pdf.
multiple library dependencies analysis.

7 Conclusions
Research on automatic Java fuzz driver generation technique can
improve the efficiency of Java library fuzzing. In this paper, we
propose a method to generate Java fuzz drivers automatically. Our
approach employs static analysis to analyze APIs call
dependencies graphs and then employs value-set analysis to
analyze APIs argument dependencies graphs. We analyze the API
dependence graph in order to allow fuzz drivers generated to cover
deep paths of library programs. We design a method to synthesize
Java fuzz drivers for JQF. We implement our approach in JFD. We
evaluate JFD on real-world JVM native libraries and prove that
JFD can generate Java fuzz drivers in the style of JQF
appropriately based on existing programs using the target library.

ACKNOWLEDGMENTS
We’d like to express our appreciation to anonymous editors.

REFERENCES
[1] Huang, Z. , & Wang, Y. . (2018). Jdriver: automatic driver class generation for
afl-based java fuzzing tools. Symmetry, 10(10).
[2] Babi D. , Bucur S. , et al. “FUDGE: Fuzz driver generation at scale”. ACM
SIGSOFT Symposium on the Foundation of Software Engineering/ European
Software Engineering Conference, 2019
[3] Ispoglou Kyriakos K, Austin Daniel, Mohan Vishwath, Payer Mathias.
“FuzzGen: Automatic Fuzzer Generation”. USENIX Security. 2020
[4] Miller, B.P.; Fredriksen, L.; So, B. An Empirical Study of the Reliability of
UNIX Utilities. Commun. ACM 1990, 33, 32–44.
[5] P. Godefroid, M. Y. Levin, and D. Molnar, SAGE: Whitebox fuzzing for
security testing[J]. 2012, Queue, vol. 10, no. 1, pp. 20:20–20:27.
[6] M. Zalewski, “american fuzzy lop,” 2017. [Online]. Available:
http://lcamtuf.coredump.cx/afl/
[7] Hong Z . “JFuzz: A Tool for Automated Java Unit Testing Based on Data
Mutation and Metamorphic Testing Methods”. 2015
[8] Kersten Rody, Field Moffett, et al. “POSTER : AFL-based Fuzzing for Java with
Kelinci”. ACM Conference on Computer and Communications Security. 2017
[9] Lemieux, Caroline. “JQF : Coverage-Guided Property-Based Testing in Java”.
International Symposium on Software Testing and Analysis. 2019
[10] Padhye, Rohan Lemieux, et al. “Semantic fuzzing with ZEST”. International
Symposium on Software Testing and Analysis. 2019
[11] Lemieux Caroline, Padhye Rohan, et al. “PerfFuzz: Automatically generating
pathological inputs”. ISSTA 2018 - Proceedings of the 27th ACM SIGSOFT
International Symposium on Software Testing and Analysis. 2018
[12] Vallee-Rai R , Hendren L, Sundaresan V, et al. “Soot—a Java bytecode
optimization framework”. Proceedings of Cascon. 1999.
[13] R Vallée-Rai, Lam P , Verbrugge C , et al. “Soot (poster session): a Java
bytecode optimization and annotation framework”. Addendum to the
Conference on Object-oriented Programming, 2000.
[14] Lam P, Bodden E, Lhoták O, et al. The Soot framework for Java program
analysis: a retrospective [C]. In Cetus Users and Compiler Infastructure
Workshop (CETUS 2011). 2011: 35.
[15] Pengfei Wang, Xu Zhou, et al. “SoK: The Progress, Challenges, and
Perspectives of Directed Greybox Fuzzing”. Arxiv. 2020
[16] “Fuzzing: Hack, Art, and Science”. CACM. 2020

867

You might also like