An automated testing method for Android native functions based on composite analysis
Through a composite analysis method, combining dynamic and static analysis, the mapping relationship between native functions and JNI functions is established, the test priority is evaluated and test cases are constructed, and the problem that the existing technology cannot automatically analyze and test Android native functions is solved, and efficient security testing and defect identification are achieved.
Patent Information
- Application Number
- CN202410541378.6
- Authority / Receiving Office
- CN · China
- Patent Type
- Patents(China)
- Current Assignee / Owner
- Filing Date
- 2024-04-30
- Publication Date
- 2025-04-18
- Estimated Expiration
- 2044-04-30
AI Technical Summary
The existing technology cannot automatically and comprehensively analyze Android native functions, lacks methods to automatically generate test samples, and does not use advanced fuzz testing methods such as coverage-guided testing, which limits the automation and effectiveness of Android native functions.
The Android native function automation testing method based on composite analysis is adopted, and the native function is extracted through a combination of dynamic analysis and static analysis, the mapping relationship between native function and JNI function is established, the test priority is evaluated using the weighted circle complexity, the test case is constructed, and the coverage-guided fuzz testing is realized through dynamic binary instrumentation.
It realizes automated security testing of Android native functions, can efficiently identify software defects and build a safer Android ecosystem.
Smart Images

Figure CN118427835B_ABST
Abstract
Description
Technical Field
[0001] The present invention belongs to the technical field of software security detection, and in particular relates to an automatic testing method for Android native functions based on composite analysis. Background Art
[0002] In the modern software development process, security testing is a key step to ensure application stability and user safety. Especially on the Android platform, due to its openness, applications are often threatened by security vulnerabilities. Traditional manual testing methods are time-consuming and labor-intensive, and it is difficult to meet the growing market demand. In order to detect and fix vulnerabilities in advance and prevent potential security risks from being exploited, automated fuzz testing has gradually gained attention as a more effective and comprehensive testing method. However, existing research has paid insufficient attention to automated fuzz testing of Android native functions (also known as Android native methods), and there are several main limitations: (1) it is impossible to automatically and comprehensively analyze Android native functions; (2) it does not provide a method for automatically generating test samples; (3) it does not adopt more advanced fuzz testing methods such as coverage-guided testing. These problems limit the automation and effectiveness of fuzz testing methods for Android native functions. Summary of the invention
[0003] In order to overcome the problem that existing fuzzy testing methods cannot automatically and effectively complete the security testing of Android native functions, the present invention provides an Android native function automated testing method based on composite analysis, which can not only automatically discover the native functions existing in Android programs, but also use the dynamic binary instrumentation method to effectively use coverage feedback to test Android native functions.
[0004] The present invention is achieved through the following technical solutions:
[0005] An automated testing method for Android native functions based on composite analysis includes the following steps:
[0006] Step 1: Use a combination of dynamic analysis and static analysis to fully extract the native functions of the Android application to be tested, and establish a mapping relationship between the native functions of the Android application and the JNI functions;
[0007] Step 2, using weighted cyclomatic complexity to evaluate the test priority of each native function of the Android application to be tested;
[0008] Step 3: Build a test case and adapt the test program for the Android application to be tested;
[0009] Step 4, arrange the test order of the native functions of the Android application to be tested according to the test priority generated in step 2, pass the JNI function to the fuzz tester using the mapping relationship established in step 1, and according to the test order, insert the test case adaptation test program constructed in step 3 as an Agent into the memory of the native function process of the Android application to be tested, and use shared memory on the Android platform to test the Android application to be tested.
[0010] In the above technical solution, in step 1, first use the shelling tool and disassembly tool to restore the native function library and Java code of the Android application; after obtaining the native function library, use Java parsing to generate an abstract syntax tree, and identify each native function in the Android application and its corresponding library through the generated abstract syntax tree analysis; according to the type of the native function, for each statically registered native function, automatically generate the name of its corresponding JNI function according to the static registration rules; load the .so file associated with each native function, check whether there is a matching JNI function name, if a matching JNI function is found, establish a mapping relationship between the JNI function and the statically registered native function; otherwise, by calling JNI_OnLoad, use low-level interception to determine the mapping relationship between the dynamically registered native function and its JNI function.
[0011] In the above technical solution, in step 2, in a black box environment, the control flow graph of the mapped JNI function in step 1 is exported by Ghidra software, and the number of two basic block memory operation functions connected by the edges in the obtained control flow graph of the JNI function is calculated for each edge E. i Assign weight W i , use N to represent the number of basic blocks in the control flow graph of the JNI function, n to represent the number of edges in the control flow graph of the JNI function, and determine the test priority of the native function according to the following weighted cyclomatic complexity scoring function formula of the native function:
[0012]
[0013] V represents the test priority, and G represents the input data flow.
[0014] In the above technical solution, step 3 includes the following steps:
[0015] Step 3.1: Start the test case assignment process;
[0016] Step 3.2: Input the native functions and test case set of the Android application to be tested, where the test case set is provided by the fuzz tester and includes an initial data set for testing;
[0017] Step 3.3: Divide the parameters of the native function of the Android application to be tested into value type parameters and reference type parameters;
[0018] Step 3.4: Assign test cases directly to value type parameters;
[0019] Step 3.5: Use the length of the remaining test cases as a random seed to provide randomness for the test case assignment of reference type parameters;
[0020] Step 3.6: Generate a random allocation ratio based on the random seed to evenly distribute the remaining test cases to each reference type parameter;
[0021] Step 3.7: Divide the remaining test cases into reference type parameters according to the generated random allocation ratio, ensuring that each reference type parameter has corresponding test case data;
[0022] Step 3.8: Check if there are any remaining unassigned test cases;
[0023] Step 3.9: If there are any remaining test cases, assign them all to the last reference type parameter;
[0024] Step 3.10: End the test case assignment process.
[0025] In the above technical solution, step 4 includes the following steps:
[0026] Step 4.1: First, arrange the test order of the native functions of the Android application to be tested according to the test priority generated in step 2;
[0027] Step 4.2: Use the mapping relationship established in step 1 to pass the JNI function to the fuzz tester for instrumentation;
[0028] Step 4.3: According to the test sequence, insert the test case adaptation test program constructed in step 3 as an Agent into the memory of the native function process of the Android application to be tested;
[0029] Step 4.4: Use dynamic loading technology to inject the shared memory API into the memory of the native function process of the Android application to be tested;
[0030] Step 4.5: The Agent instructs the DBI engine of the fuzz tester to insert probes into the execution code of the native function of the Android application to be tested;
[0031] Step 4.6: After completing dynamic instrumentation, the fuzz tester sends the test cases generated in step 3 to the Socket proxy;
[0032] Step 4.7: The socket proxy exchanges the data in the test case with the remote harness through the shared memory injected in step 4.4;
[0033] Step 4.8: After receiving the test case, Harness retrieves the test case for fuzz testing from the shared memory;
[0034] Step 4.9: After the test case is executed, the probe transfers the coverage data to the DBI engine;
[0035] Step 4.10: At this point, the DBI engine XORs the current program counter value with the value of the previous position to generate a unique identifier, which is used to collect the edge coverage of the program;
[0036] Step 4.11: The DBI engine forwards the coverage data to the harness;
[0037] Step 4.12: The harness writes the overlay data to the shared memory injected in step 4.4;
[0038] Step 4.13: The socket agent extracts coverage data from the shared memory injected in step 4.4;
[0039] Step 4.14: The socket agent sends the coverage data back to the fuzz tester.
[0040] Step 4.15: Test Repeat step 4.2 to ensure accurate execution of the process, thorough analysis and optimal results.
[0041] The advantages and beneficial effects of the present invention are:
[0042] The present invention can automatically analyze the native functions in the application and automatically write auxiliary scripts for these methods while performing security tests on Android native functions, and finally use dynamic binary insertion technology to achieve efficient testing of software defects in Android native functions. The present invention helps to identify and solve errors in Android native functions and build a safer Android ecosystem. BRIEF DESCRIPTION OF THE DRAWINGS
[0043] Figure 1 It is a technical solution architecture diagram of the present invention.
[0044] Figure 2 It is a flow chart of the test case adaptation algorithm.
[0045] For ordinary technicians in this field, other relevant drawings can be obtained based on the above drawings without any creative work. DETAILED DESCRIPTION
[0046] In order to enable those skilled in the art to better understand the technical solution of the present invention, the technical solution of the present invention is further described below in conjunction with specific embodiments.
[0047] An automated testing method for Android native functions based on composite analysis includes the following steps:
[0048] Step 1: Use a combination of dynamic analysis and static analysis to comprehensively extract the native functions of the Android application to be tested, establish a mapping relationship between the native functions of the Android application and the JNI functions, and lay the foundation for the generation of subsequent test programs.
[0049] The JNI function (Java Native Interface) is a mechanism that allows Java code to call and be called by C or C++ code. It provides a way to connect the Java Virtual Machine (JVM) and native code, so that Java programs can call underlying native libraries, and native code can call methods and objects in Java programs.
[0050] Specifically, first use the shelling tool and disassembly tool to restore the native function library and Java code of the Android application; after obtaining the native function library, use Java parsing to generate an abstract syntax tree (AST), and identify each native function in the Android application and its corresponding library through the generated abstract syntax tree (AST) analysis; according to the type of the native function (including static registration type and dynamic registration type), for each statically registered native function, automatically generate the name of its corresponding JNI function according to the static registration rules; load the .so file associated with each native function, check whether there is a matching JNI function name, if a matching JNI function is found, establish a mapping relationship between the JNI function and the statically registered native function; otherwise, by calling JNI_OnLoad, use low-level interception to determine the mapping relationship between the dynamically registered native function and its JNI function.
[0051] Step 2: Use weighted cyclomatic complexity to evaluate the test priority of each native function of the Android application to be tested.
[0052] In a black box environment, we use Ghidra software (Ghidra is a software reverse engineering framework that includes a set of full-featured high-end software analysis tools that enable users to analyze compiled code on various platforms) to export the control flow graph of the mapped JNI function in step 1. In the weighted cyclomatic complexity evaluation algorithm, we calculate the number of basic block memory operation functions connected by the edges in the obtained control flow graph of the JNI function, and calculate the weighted cyclomatic complexity of each edge E. i Assign weight W i , W iIt is determined by the number of memory operation functions of the two basic blocks connected by each edge. The initial weight W0 is 1. Then, if the number of memory operation functions in a basic block is x, the updated weight W is 1+x. N represents the number of basic blocks in the control flow graph of the JNI function, and n represents the number of edges in the control flow graph of the JNI function. Finally, we give the weighted cyclomatic complexity scoring function formula for native functions to determine the test priority of native functions:
[0053]
[0054] V represents the test priority (level), and G represents the input data flow.
[0055] Step 3: Build a test case adaptation test program for the Android application to be tested.
[0056] The task of the test case adaptation tester is to adapt the test case to the parameter specifications of the native function of the Android application to be tested. Figure 2 The process of adapting the test case to the test program designed by the present invention is as follows:
[0057] (1) Start the test case allocation process;
[0058] (2) Inputting the native functions and test case set of the Android application to be tested, wherein the test case set (Samples) is provided by the fuzz tester and includes an initial data set for testing;
[0059] (3) The parameters of the native function of the Android application to be tested are divided into value type parameters and reference type parameters. The value type parameters refer to parameters of basic data types, such as integer or floating point type; the reference type parameters refer to complex data structures such as objects or arrays;
[0060] (4) Directly assign test cases to value type parameters. Since the data type and length of these value type parameters are pre-defined, it can be ensured that the assigned test cases match the value type parameters;
[0061] (5) Use the length of the remaining test cases as a random seed to provide randomness for the test case allocation of reference type parameters;
[0062] (6) Generate a random allocation ratio based on the random seed so as to evenly allocate the remaining test cases to each reference type parameter;
[0063] (7) Divide the remaining test cases into reference type parameters according to the generated random allocation ratio to ensure that each reference type parameter has corresponding test case data;
[0064] (8) Check whether there are any remaining unassigned test cases. This step serves as a decision point to determine whether all test cases have been assigned;
[0065] (9) If there are any remaining test cases, assign them all to the last reference type parameter, thereby ensuring that all test data is fully utilized without omission;
[0066] (10) End the test case allocation process.
[0067] The above test case adaptation test program can ensure that each parameter obtains a suitable test case, thereby improving the efficiency and effect of fuzz testing.
[0068] Step 4. Finally, shared memory is used on the Android platform to implement coverage-guided fuzz testing of the Android application under test.
[0069] In this step, the probe is inserted into the execution code of the native function of the Android application to be tested through dynamic insertion technology; then the edge coverage is collected using XOR (exclusive OR) technology. XOR is a binary operation that compares two bits. The result is 1 only when the two bits are different (1 if different, 0 if the same). In the context of the program counter, the use of XOR can help generate a unique identifier that represents the transition from a specific code location (the value of the previous program counter) to another location (the value of the current program counter). In this step, XOR is used to calculate the current program counter value and the value of the previous location, thereby collecting edge coverage instead of block coverage. The specific implementation steps of the present invention for coverage-guided fuzz testing of the Android application to be tested are as follows:
[0070] (1) First, arrange the test order of the native functions of the Android application to be tested according to the test priority generated in step 2;
[0071] (2) Use the mapping relationship established in step 1 to pass the JNI function to the fuzz tester for instrumentation;
[0072] (3) According to the test sequence, the test case adaptation test program constructed in step 3 is inserted as an Agent into the memory of the native function process of the Android application to be tested;
[0073] (4) Using dynamic loading technology, the shared memory API is injected into the memory of the native function process of the Android application to be tested;
[0074] (5) The agent instructs the DBI engine of the fuzz tester to insert probes into the execution code of the native function of the Android application to be tested (the DBI engine can dynamically insert the process by monitoring and controlling all executed instructions);
[0075] (6) After completing the dynamic instrumentation, the fuzz tester sends the test case generated in step 3 to the Socket proxy;
[0076] (7) The socket proxy exchanges the data in the test case with the remote harness through the shared memory injected in step (4);
[0077] (8) After receiving the test case, Harness retrieves the test case for fuzz testing from the shared memory;
[0078] (9) After the test case is executed, the probe transmits the coverage data to the DBI engine;
[0079] (10) At this point, the DBI engine performs an XOR calculation on the current program counter value and the value of the previous position to generate a unique identifier, which is used to collect the edge coverage of the program;
[0080] (11) The DBI engine forwards the coverage data to the harness;
[0081] (12) The harness writes the overlay data into the shared memory injected in step (4);
[0082] (13) The socket agent extracts coverage data from the shared memory injected in step (4);
[0083] (14) The socket agent sends the coverage data back to the fuzz tester;
[0084] (15) Testing Repeat step (2) to ensure accurate execution of the process, thorough analysis and optimal results.
[0085] Through these steps, the present invention executes a large number of test cases in a system with limited resources and improves the efficiency of fuzz testing.
[0086] The present invention is described above by way of example. It should be noted that, without departing from the core of the present invention, any simple deformation, modification or other equivalent replacement that can be made by those skilled in the art without inventive effort falls within the protection scope of the present invention.
Claims
1. An automated testing method for Android native functions based on composite analysis, characterized in that: The following steps are involved: Step 1: Use a combination of dynamic analysis and static analysis to fully extract the native functions of the Android application to be tested, and establish a mapping relationship between the native functions of the Android application and the JNI functions; Step 2, using weighted cyclomatic complexity to evaluate the test priority of each native function of the Android application to be tested; In step 2, in a black box environment, the control flow graph of the mapped JNI function in step 1 is exported by Ghidra software. According to the number of two basic block memory operation functions connected by the edges in the obtained control flow graph of the JNI function, each edge E i Assign weight W i , use N to represent the number of basic blocks in the control flow graph of the JNI function, n to represent the number of edges in the control flow graph of the JNI function, and determine the test priority of the native function according to the following weighted cyclomatic complexity scoring function formula of the native function: V represents the test priority, and G represents the input data flow; Step 3, building a test case adaptation test program for the Android application to be tested; Step 3 includes the following steps: Step 3.1: Start the test case assignment process; Step 3.2: Input the native functions and test case set of the Android application to be tested, where the test case set is provided by the fuzz tester and includes an initial data set for testing; Step 3.3: Divide the parameters of the native function of the Android application to be tested into value type parameters and reference type parameters; Step 3.4: Assign test cases directly to value type parameters; Step 3.5: Use the length of the remaining test cases as a random seed to provide randomness for the test case assignment of reference type parameters; Step 3.6: Generate a random allocation ratio based on the random seed to evenly distribute the remaining test cases to each reference type parameter; Step 3.7: Divide the remaining test cases into reference type parameters according to the generated random allocation ratio, ensuring that each reference type parameter has corresponding test case data; Step 3.8: Check if there are any remaining unassigned test cases; Step 3.9: If there are any remaining test cases, assign them all to the last reference type parameter; Step 3.10: End the test case allocation process; Step 4, arrange the test order of the native functions of the Android application to be tested according to the test priority generated in step 2, pass the JNI function to the fuzz tester using the mapping relationship established in step 1, and according to the test order, insert the test case adaptation test program constructed in step 3 as an Agent into the memory of the native function process of the Android application to be tested, and use shared memory on the Android platform to test the Android application to be tested.
2. The method for automated testing of Android native functions based on composite analysis according to claim 1, characterized in that: In step 1, first use the shelling tool and disassembly tool to restore the native function library and Java code of the Android application; After obtaining the native function library, use Java parsing to generate an abstract syntax tree, and identify each native function in the Android application and its corresponding library through the generated abstract syntax tree analysis; according to the type of the native function, for each statically registered native function, automatically generate the name of its corresponding JNI function according to the static registration rules; load the .so file associated with each native function, check whether there is a matching JNI function name, if a matching JNI function is found, establish a mapping relationship between the JNI function and the statically registered native function; otherwise, by calling JNI_OnLoad, use low-level interception to determine the mapping relationship between the dynamically registered native function and its JNI function.
3. The method for automated testing of Android native functions based on composite analysis according to claim 1, characterized in that: Step 4 includes the following steps: Step 4.1: First, arrange the test order of the native functions of the Android application to be tested according to the test priority generated in step 2; Step 4.2: Use the mapping relationship established in step 1 to pass the JNI function to the fuzz tester for instrumentation; Step 4.3: According to the test sequence, insert the test case adaptation test program constructed in step 3 as an Agent into the memory of the native function process of the Android application to be tested; Step 4.4: Use dynamic loading technology to inject the shared memory API into the memory of the native function process of the Android application to be tested; Step 4.5: The Agent instructs the DBI engine of the fuzz tester to insert probes into the execution code of the native function of the Android application to be tested; Step 4.6: After completing dynamic instrumentation, the fuzz tester sends the test cases generated in step 3 to the Socket proxy; Step 4.7: The socket proxy exchanges the data in the test case with the remote harness through the shared memory injected in step 4.4; Step 4.8: After receiving the test case, Harness retrieves the test case for fuzz testing from the shared memory; Step 4.9: After the test case is executed, the probe transfers the coverage data to the DBI engine; Step 4.10: At this point, the DBI engine XORs the current program counter value with the value of the previous position to generate a unique identifier, which is used to collect the edge coverage of the program; Step 4.11: The DBI engine forwards the coverage data to the harness; Step 4.12: The harness writes the overlay data to the shared memory injected in step 4.4; Step 4.13: The socket agent extracts coverage data from the shared memory injected in step 4.4; Step 4.14: The socket agent sends the coverage data back to the fuzz tester. Step 4.15: Test Repeat step 4.2 to ensure accurate execution of the process, thorough analysis and optimal results.
Citation Information
Patent Citations
Android application vulnerability detection method and system based on function control flow
CN105677574A
Rapid heterogeneous language communication programming method
CN116028029A