Memory security vulnerability fuzzing method combined with dynamic analysis
By inserting pointer metadata and function definitions, storing pointer metadata using hash tables and secondary tree structures, and instrumenting abstract syntax tree nodes, the coverage instrumentation of dynamic analysis code is skipped, thus solving the performance overhead of dynamic analysis tools and the ineffectiveness of fuzz testing, and achieving efficient memory vulnerability discovery.
Patent Information
- Application Number
- CN202411372498.4
- Authority / Receiving Office
- CN · China
- Patent Type
- Patents(China)
- Current Assignee / Owner
- Filing Date
- 2024-09-29
- Publication Date
- 2025-11-28
- Estimated Expiration
- 2044-09-29
AI Technical Summary
Existing dynamic analysis tools suffer from severe performance degradation in memory management, invalid coverage information, and the inability of fuzzing tools to efficiently detect memory errors.
By inserting pointer metadata into type and function definitions, storing pointer metadata using hash tables and secondary tree structures, instrumenting abstract syntax tree nodes, skipping coverage instrumentation of dynamically analyzed code, and guiding fuzz testing with minimum pointer boundary distance and memory allocation peaks.
It improves the performance of fuzzing and the efficiency of memory vulnerability discovery, ensures the accuracy of coverage information, and efficiently collects memory security-related information as guiding information for fuzzing.
Smart Images

Figure CN119473869B_ABST
Abstract
Description
TECHNICAL FIELD
[0001] The present application relates to the technical field of computer software, and particularly relates to a memory security vulnerability fuzzy testing method combined with dynamic analysis. BACKGROUND
[0002] C language is widely used in the development of embedded software and system software, and has the ability to control the underlying memory. However, because of the lack of detection of the legality of memory access, C programs are prone to cause memory security errors during running. In the CVE (Common Vulnerabilities and Exposures) report, common memory security errors include buffer overflow, pointer use after free, double free and memory leak, and memory security error is one of the most dangerous software errors in the CVE report.
[0003] Nowadays, more and more technologies focus on detecting the memory security of software systems, and the dynamic analysis technology refers to extracting and analyzing the state information in the target program during the running of the program. These information can be pointer values, safe upper and lower bounds of pointers, memory allocation size, etc. By checking whether these information meet the memory security conditions during the running of the program, the memory security vulnerabilities can be detected.
[0004] Fuzzy testing technology is a software testing technology, which automatically or semi-automatically generates program inputs at the bit level, provides the mutated program inputs as parameters to the target program for multiple running, monitors the state of the program during the running of the program, and finally outputs the test cases that can make the program crash. Testers can locate program vulnerabilities by analyzing the test cases that make the program crash and the context state when the program crashes.
[0005] Combining dynamic analysis technology with fuzzy testing can generate program inputs that trigger memory vulnerabilities. Dynamic analysis technology can report memory security errors that do not cause program crashes as program exceptions, which can assist fuzzy testing tools to generate corresponding test cases. At the same time, coverage-guided fuzzy testing tools generate test cases with higher program coverage as much as possible, which can improve the shortcomings of dynamic analysis technology that relies on program inputs.
[0006] However, when using existing dynamic analysis tools to assist coverage-guided fuzzy testing, serious performance loss will be caused due to the increase of memory management time. The fuzzy testing tool will perform coverage instrumentation on the additional code generated by the dynamic analysis tool, resulting in invalid coverage information. In addition, blindly improving the code coverage of test cases cannot effectively find memory security errors in the program.
[0007] The main problems existing in the prior art are analyzed as follows:
[0008] 1) Dynamic analysis tools use shadow space, which causes serious performance loss
[0009] The existing dynamic analysis tool uses a large volume of virtual memory as a shadow space to store pointer metadata, which is offset from the original program memory space, and uses a red zone to mark the entire shadow space during the original program initialization to represent the memory available state, so when combined with the thread forking server mode of the fuzz testing, a large number of page faults will occur, increasing the memory management time and seriously reducing the running performance of the fuzz testing.
[0010] 2) The code inserted by the dynamic analysis tool causes invalid coverage information
[0011] The existing dynamic analysis tool needs to perform code instrumentation on the original program to detect memory errors, so new functions and branch jumps that are unrelated to the original program logic will be generated. The coverage-guided fuzz testing will perform coverage instrumentation on these new functions and branch jumps, generating invalid coverage information, which will have a serious negative impact on exploring new branch code paths.
[0012] 3) The code coverage guide used by the fuzz testing tool is not good at discovering memory errors
[0013] The existing coverage-guided fuzz testing blindly explores new program execution paths without considering how to efficiently trigger memory safety errors in the code, so the fuzz testing needs additional information to guide the process of collecting and mutating test cases. SUMMARY
[0014] The purpose of the present application is to provide a memory safety vulnerability fuzz testing method combined with dynamic analysis, which can efficiently discover memory vulnerabilities in the target program and improve the error detection ability and running performance of the fuzz testing.
[0015] Technical solution: A memory safety vulnerability fuzz testing method combined with dynamic analysis, comprising the following steps:
[0016] S1, open the source code file of the program to be tested, and insert type definitions and function definitions in the source code file for dynamic analysis;
[0017] S2, pre-process the source code of the program to be tested using a compiler, and then parse the source code of the program to be tested using the compiler;
[0018] S3, traverse the abstract syntax tree and instrument the nodes thereof to detect memory errors during program execution, and maintain shared memory variables of the minimum pointer boundary distance and the memory allocation peak value;
[0019] S4, compile the instrumented source code to obtain assembly code;
[0020] S5, coverage instrumentation is performed on the assembled code, and the code inserted in the previous step for dynamic analysis is skipped;
[0021] S6, the assembled code after instrumentation is assembled and linked to obtain an executable file,
[0022] S7, the executable file is subjected to fuzz testing, and the coverage provided by dynamic analysis, the minimum pointer boundary distance, and the memory allocation peak value are used as feedback information to guide the fuzz testing;
[0023] S8, the fuzz testing is run, and a program input file that causes the target program to have a memory safety error is output.
[0024] Further, the source code inserted in step S1 for dynamic analysis includes the following steps:
[0025] S11, a type definition of pointer metadata is inserted, and the structure type of the pointer metadata includes the start address and end address of the memory space pointed to by the pointer variable, the address of the pointer variable, and the state of the memory space;
[0026] S12, a type definition of a data structure for maintaining the pointer metadata is inserted, and the data structure includes a hash table and a two-level tree, both of which use the address value of the pointer variable as an index value; in the two-level tree, the 26th to 48th bits from the low bit of the index value are used as a first-level index value, and the 4th to 25th bits are used as a second-level index value; the initial capacity of the first-level table and the second-level table is 2^23 and 2^22, respectively, each element in the first-level table is a pointer to the second-level table, and each element in the second-level table is a pointer to the pointer metadata;
[0027] S13, a function definition for maintaining the pointer metadata is inserted, and in the process of program running, the pointer metadata is inserted into the hash table or the two-level tree when a pointer variable is created, and dynamic expansion is performed when the capacity is insufficient;
[0028] S14, a function definition for memory safety detection is inserted, and the difference between the current pointer value and the legal start address corresponding to the pointer metadata, and the difference between the pointer value and the legal end address corresponding to the pointer metadata are updated, and the minimum difference is kept as the minimum pointer boundary distance, which is used to judge whether there is a tendency to have a pointer out-of-bound error;
[0029] S15, a wrapper function definition of a memory allocation library function is inserted, and after the wrapper function executes the memory allocation library function, it is judged whether the execution is successful according to the function return value: if the execution is successful, the total value of the memory allocated when the program runs to this point is updated, and the global memory allocation peak value is updated with the total value of the memory allocated, which is used to judge whether there is a tendency to have a large memory allocation, and finally the return value of the memory allocation library function is returned; if the execution is not successful, no operation is performed.
[0030] Further, the specific processing logic for storing the pointer metadata is as follows:
[0031] In the hash table mode, the address value of the pointer variable is used as the index value, and the linked address method is used to handle conflicts. When the number of table elements exceeds three times the number of buckets, the number of buckets is expanded to twice.
[0032] In the two-level tree mode, the 26th to 48th bits of the low bits of the address value of the pointer variable are used as the first-level index value, and the 4th to 25th bits are used as the second-level index value. When the second-level table corresponding to the first-level index value is missing, the second-level table is created and the pointer metadata is inserted into the second-level table.
[0033] Further, the step S3 traverses the abstract syntax tree and inserts the nodes, including the following steps:
[0034] S31, the main function entry of the program is inserted, which is used to obtain the shared memory of the fuzz testing and establish inter-process communication with the fuzz testing;
[0035] S32, the definition and initialization statements of the pointer variable are inserted, which are used to create pointer metadata and insert the pointer metadata into the hash table or the two-level tree;
[0036] S33, the pointer dereference, array subscript access, and member access statements of the structure pointer variable are inserted, which are used to detect memory errors, and update the minimum difference between the pointer value and the legal starting address of the pointer metadata, and the minimum difference between the pointer value and the legal ending address of the pointer metadata. The minimum difference is stored in the shared memory variable of the fuzz testing as the minimum pointer boundary distance;
[0037] S34, the function call statements of memory allocation and memory release are inserted, which are replaced by the corresponding wrapper function calls, which are used to maintain the pointer metadata of the heap type pointer variable, and update the maximum memory value that has been allocated, which is stored in the shared memory variable of the fuzz testing as the memory allocation peak value.
[0038] Further, the step S5 skips the previously inserted code for dynamic analysis, including pointer metadata operation functions, normal wrapper functions, and inline wrapper library functions; including the following steps:
[0039] S51, the insertion of the pointer metadata operation function is skipped by recognizing the function name prefix of the inserted pointer metadata operation function and the.LFE in the assembly code representing the end of the function body. <num>an identifier is used to skip coverage instrumentation of the code between the function name and the end identifier;
[0040] S52, skip instrumentation of normal wrapper functions; the normal wrapper functions pass the function return value of the pointer type and the pointer metadata of the function parameters to the original function for memory safety check during execution of the original function, pass the end and call the original function to get the return value, and then return the return value of the original function;
[0041] S53, skip instrumentation of inline wrapper library functions; by identifying whether the source of the inline code block belongs to the source file for dynamic analysis, skip coverage instrumentation of the inline code block in the source file for dynamic analysis.
[0042] Further, the coverage provided by dynamic analysis, the minimum pointer boundary distance, and the memory allocation peak value are used as feedback information to guide the fuzz testing in step S7, including the following steps:
[0043] S71, collect test cases and add them to the seed queue: first, according to the coverage information provided by the fuzz testing, it is judged whether a new program execution path is found during the program running process:
[0044] If there is a new program execution path, the test case is directly added to the seed queue;
[0045] If there is no new program execution path, it is judged whether a number of pointers are closer to the legal upper and lower bounds of their pointer metadata during the running process, and whether a higher memory allocation peak value is generated during the running process: if a number of pointers are closer to the legal upper and lower bounds of their pointer metadata, or a higher memory allocation peak value is generated, the test case is added to the seed queue; if there are no pointers closer to the legal upper and lower bounds of their pointer metadata, and no higher memory allocation peak value is generated, the test case is discarded;
[0046] S72, simplify the seed queue: if the test case can be added to the seed queue through the judgment of the coverage, the minimum pointer boundary distance, and the memory allocation peak value, replace the test case in the seed queue with the same execution path as the test case, and the minimum pointer boundary distance is greater or the memory allocation peak value is lower;
[0047] S73, evaluate the seeds in the seed queue: calculate the excellent degree of the seeds using the execution time consumption, file size, minimum pointer boundary distance, and memory allocation peak value, retain the excellent seeds in the seed queue, further simplify the seed queue, and leave for subsequent mutation.
[0048] Compared with the prior art, the present application has the following remarkable effects:
[0049] 1、The application adopts a dynamic expansion hash table, a tree data structure to store pointer metadata, only applies heap memory to store pointer metadata when the program runs to the pointer creation position, and only accesses the pointer metadata when the program runs to the pointer operation position, thereby reducing memory management time consumption and improving the running performance of the fuzz testing;
[0050] 2、The application identifies the code inserted by the dynamic analysis tool in the coverage insertion stage, does not perform coverage insertion on the code, and guarantees accurate original program coverage information;
[0051] 3、The application collects the program input that causes the pointer in the program to be closer and closer to the legal upper and lower bounds and the allocated memory value to be larger and larger as a value seed, and repeatedly performs the above operation after simplifying and mutating the seed queue, thereby efficiently detecting memory errors. Since the dynamic analysis tool has the ability to analyze the runtime state of the program, the memory safety related information can be collected as the guidance information of the fuzz testing;
[0052] 4、The application uses the minimum pointer boundary distance and the memory allocation peak value as additional feedback information to guide the fuzz testing, and improves the efficiency of generating program input capable of triggering the memory vulnerability. BRIEF DESCRIPTION OF DRAWINGS
[0053] Figure 1 The figure is a schematic diagram of the overall flow of the application. DETAILED DESCRIPTION
[0054] The application will be further described in detail below in combination with the drawings and specific embodiments.
[0055] The application provides a memory safety vulnerability fuzz testing method combined with dynamic analysis, and a flowchart is shown as Figure 1 The method comprises the following steps:
[0056] Step 1, open the source code file of the program to be tested, and insert the type definition and function definition source code used for dynamic analysis in the source code file, including the following steps:
[0057] Step 11, insert the type definition of the pointer metadata. The structure type of the pointer metadata includes the starting address and ending address of the memory space pointed to by the pointer variable, the address of the pointer variable, and the state of the memory space, wherein the state of the memory space is used to judge whether the memory space is initialized.
[0058] In this embodiment, the code of the structure type definition of the pointer metadata is as follows, wherein PRFptr_addr is a pointer variable address type:
[0059]
[0060]
[0061] Step 12, insert the type definition of the data structure for maintaining the pointer metadata. The data structure includes a hash table and a two-level tree, both of which use the address value of the pointer variable as the index value; in the two-level tree, the 26th to 48th bits from the low bit of the index value are used as the primary index value, and the 4th to 25th bits are used as the secondary index value. The initial capacities of the primary table and the secondary table are 2^23 and 2^22 respectively. Each element in the primary table is a pointer to the secondary table, and each element in the secondary table is a pointer to the pointer metadata.
[0062] In this embodiment, the code for the type definition of the hash table and the two-level tree is as follows, where PRFpmd is the pointer metadata type, and PRFtrie_primary_entries and PRFtrie_secondary_entries are the capacities of the primary table and the secondary table respectively:
[0063]
[0064] Step 13, insert the function definition for maintaining the pointer metadata. The pointer metadata can be maintained using one of the two modes of the hash table and the two-level tree. During the program running process, when a pointer variable is created, the pointer metadata is inserted into the hash table or the two-level tree, and dynamic expansion is performed when the capacity is insufficient.
[0065] In the two modes of the hash table and the two-level tree, the specific processing logic for storing the pointer metadata is as follows:
[0066] (A1) Hash table: use the address value of the pointer variable as the index value, use the chain address method to handle conflicts, and when the number of table elements exceeds three times the number of buckets, expand the number of buckets to twice. The function declaration for inserting elements is as follows:
[0067] PRFpmd*PRFhashtbl_insert_pmd(PRFhashtbl*tbl, PRFpmd*pmd);
[0068] In the embodiment, the function code for inserting elements into the hash table is as follows: the address of the pointer variable is used as the index value, which is converted into the subscript of the hash table by using the hash function PRFhashtbl_hash, the elements in the bucket corresponding to the subscript are traversed, it is judged whether there is a pointer metadata with the same index value, if yes, the pointer metadata is replaced, if not, the pointer metadata is directly inserted. When the pointer metadata is inserted, it is judged whether a new bucket is inserted, if yes, the number of used buckets is increased by 1. It is judged whether the number of elements in the current hash table is greater than three times the number of used buckets: if yes, the number of buckets is expanded to twice, and the elements of the hash table are migrated to the expanded hash table; if not, no operation is performed. Wherein PRFpmd is a pointer metadata type, the ptra member of PRFpmd is a pointer variable address:
[0069]
[0070] (A2) Two-level tree: the 26th to 48th bits of the low bits of the pointer variable address value are used as the first-level index value, and the 4th to 25th bits are used as the second-level index value. When the two-level table corresponding to the first-level index value is missing, the two-level table is created and the pointer metadata is inserted into the two-level table. The function declaration for inserting elements is as follows, wherein PRFptr_addr is a pointer variable address type:
[0071] PRFpmd*PRFtrie_insert_pmd_ptr(PRFpmd**tbl,PRFptr_addr ptra);
[0072] In the embodiment, the function code for inserting elements into the two-level tree is as follows:
[0073]
[0074]
[0075] Step 14, insert the memory safety detection function definition. The memory safety detection function checks whether the current pointer value is within the legal head address and end address range of the corresponding pointer metadata, and updates the difference between the current pointer value and the legal head address and end address of the corresponding pointer metadata (i.e. updates the difference between the current pointer value and the head address, and the difference between the current pointer value and the end address), respectively. The minimum difference is kept as the minimum pointer boundary distance, which is used to judge whether there is a tendency of pointer out-of-bounds. The function declaration is as follows:
[0076] void*PRFcheck_dpv(const PRFpmd*pmd,const void*ptr,size_t size,const char*file_name,unsigned line,unsigned column);
[0077] In the embodiment, the memory safety detection function code is as follows:
[0078]
[0079]
[0080] Step 15, insert the definition of the wrapper function of the memory allocation library function. The wrapper function executes the memory allocation library function, and then judges whether the execution is successful according to the return value of the function: if successful, updates the total value of the memory allocated when the program runs to this place, and updates the global memory allocation peak value with the total value of the memory allocated, which is used to judge whether there is a tendency of allocating too much memory, and finally returns the return value of the memory allocation library function; if not successful, no operation is performed. The wrapper function declarations of memory allocation and memory release are as follows:
[0081] void*PRFmalloc(PRFpmd*ret_pmd,size_t size);
[0082] void PRFfree(PRFpmd*ptr_pmd,void*ptr);
[0083] In the embodiment, the wrapper function code of memory allocation and memory release is as follows:
[0084]
[0085] Step 2, pre-process the source code of the program to be tested by using the compiler, including macro replacement and header file import, and then parse the source code of the program to be tested by using the compiler, including lexical analysis, syntax analysis, semantic analysis and abstract syntax tree generation.
[0086] Step 3, traverse the abstract syntax tree and insert a stake in the node thereof, so as to detect memory errors during program running, and maintain the shared memory variables of the minimum pointer boundary distance and the memory allocation peak value.
[0087] Step 31, insert a stake in the program main function entrance, which is used for obtaining the shared memory of the fuzz test and establishing inter-process communication with the fuzz test.
[0088] Step 32, insert a stake in the definition and initialization statement of the pointer variable, which is used for creating pointer metadata and inserting the pointer metadata into the hash table or the binary tree.
[0089] In the embodiment, the function code to be inserted is as follows:
[0090] void test(){
[0091] int *ptr = malloc ( sizeof ( int ) ) ;
[0092] }
[0093] The function code after the insertion is as follows, in which the PRFpmd_tbl_create function creates a hash table or a two-level tree and inserts the pointer metadata:
[0094] void test(){
[0095] int *ptr = PRFmalloc ( PRFpmd_tbl_create ( ( PRFptr_addr ) & ptr ), sizeof ( int ) ) ;
[0096] }
[0097] Step 33, the pointer dereferencing, array subscript access, and member access statement of the structure pointer variable are inserted, which is used to detect memory errors and update the minimum difference between the pointer value and the start address of the pointer metadata and the minimum difference between the pointer value and the end address of the pointer metadata. The minimum difference is stored as the minimum pointer boundary distance in the shared memory variable of the fuzz test.
[0098] In this embodiment, the function code to be inserted is as follows:
[0099] void test ( int *ptr ) {
[0100] int num = *ptr;
[0101] }
[0102] The function code after the insertion is as follows, in which the PRFcheck_dpv function adds the pointer value to the size of the object pointed to by the pointer to determine whether it is within the legal upper and lower bounds of the pointer metadata to determine memory safety. It also determines whether the pointer value of the pointer dereferencing is closer to the legal upper and lower bounds of the pointer. If so, the smaller pointer boundary distance is updated to the shared memory variable of the fuzz test:
[0103]
[0104] Step 34, the function call statements of memory allocation and memory release are inserted and replaced with the corresponding wrapper function calls, which are used to maintain the pointer metadata of the heap type pointer variable and update the maximum memory value that has been allocated. The maximum memory value is stored as the memory allocation peak in the shared memory variable of the fuzz test.
[0105] In this embodiment, the function code to be inserted is as follows:
[0106]
[0107] The function code after the insertion is as follows, where the PRFmalloc function performs the malloc function to allocate memory, and judges whether the current allocated memory value is greater than the memory allocation peak value at this time of program running, and updates the memory allocation peak value to the shared memory variable of the fuzz testing. The PRFfree function performs the free function to release the memory space, and updates the current allocated memory value:
[0108]
[0109] Step 4, the compiled assembly code is obtained by compiling the source code after the insertion.
[0110] Step 5, the coverage insertion is performed on the assembly code, and the codes inserted for dynamic analysis in the foregoing are skipped, that is, the following three kinds of codes need to be skipped: pointer metadata operation function, normal wrapper function, and inline wrapper library function, and the specific processing logic is as follows:
[0111] (B1) skip the insertion of the pointer metadata operation function. The pointer metadata operation function maintains the pointer metadata by using a hash table or a binary tree, which involves operations such as inserting, modifying, and releasing the pointer metadata, and checks the memory error. The function name prefix of the inserted pointer metadata operation function and the.LFE in the assembly code representing the end of the function body are recognized. <num>an end marker to skip coverage instrumentation of the code between the function name and the end marker.
[0112] In this embodiment, if the coverage instrumentation is performed on the code inserted for dynamic analysis in the foregoing, the resultant code is as follows, in which the coverage instrumentation is performed at the beginning of the PRFcheck function; the coverage instrumentation is performed at the jnb unconditional jump; and the coverage instrumentation is performed at the.L3853 conditional jump destination basic block:
[0113]
[0114]
[0115] The code from the function name to the.LFE221 marker representing the end of the function body can be identified as the inserted code for dynamic analysis by identifying the inserted function name prefix PRF. If the coverage instrumentation is not performed on the code inserted for dynamic analysis in the foregoing, the resultant code is as follows:
[0116]
[0117] (B2) Skip the instrumentation of the normal wrapper function. The normal wrapper function passes the pointer type function return value and the pointer metadata of the function parameters to the original function for the original function to perform the memory safety check during the execution, passes the end and calls the original function to obtain the return value, and then returns the return value of the original function. The method of skipping the coverage instrumentation of the normal wrapper function is the same as that of the pointer metadata operation function, that is, by identifying the function name prefix and the.LFE representing the end of the function body. <num>an end identifier to skip coverage instrumentation of the code between the function name and the end identifier.
[0118] (B3) Skip instrumentation of inline wrapper library functions. Inline wrapper library functions are preset wrapper functions of system functions. Since they are inline functions, they are embedded into the original program after compilation and become part of the original program code, and the wrapper function name cannot be obtained. However, the assembly code displays the source file origin of the inline code block with a.loc identifier. By identifying whether the origin of the inline code block belongs to the source file used for dynamic analysis, coverage instrumentation of the inline code block in the source file used for dynamic analysis is skipped.
[0119] In this embodiment, if the coverage instrumentation is performed on the inline wrapper library function code inserted in the front, the result code after the coverage instrumentation is as follows:
[0120]
[0121] Since the file name and file ID mapping relationship is stored in the header of the assembly file, it can be known from the ID after the.loc identifier whether the basic block code comes from the source file used for dynamic analysis. If the coverage instrumentation is not performed on the inline wrapper library function code, the result code obtained is as follows:
[0122]
[0123] Step 6, assemble and link the instrumented assembly code to obtain an executable file.
[0124] Step 7, perform fuzz testing on the executable file, and use the coverage provided by dynamic analysis, the minimum pointer boundary distance, and the memory allocation peak value as feedback information to guide the fuzz testing. The guiding part is specifically divided into three steps: collecting test cases to add to the seed queue, simplifying the seed queue, and evaluating the seeds in the seed queue.
[0125] Step 71, collect test cases to add to the seed queue. First, according to the coverage information provided by the fuzz testing, it is judged whether a new program execution path is found in the program running process:
[0126] If there is a new program execution path, the test case is directly added to the seed queue;
[0127] If there is no new program execution path, it is judged whether there are several pointers that are closer to the legal upper and lower bounds of their pointer metadata in the running process, and whether a higher memory allocation peak value is generated in the running process: if there are several pointers that are closer to the legal upper and lower bounds of their pointer metadata, or a higher memory allocation peak value is generated, the test case is added to the seed queue; if there is no higher memory allocation peak value generated, and there is no higher memory allocation peak value generated, the test case is discarded.
[0128] Step 72, refine the seed queue. If the test case can be added to the seed queue through the coverage, minimum pointer distance, and memory allocation peak indicators, replace the test case in the seed queue with the same execution path as the current test case, and the minimum pointer distance is greater or the memory allocation peak is lower.
[0129] In this embodiment, the minimum pointer distance is used as an indicator to collect test cases into the seed queue, and the function code for refining the seed queue is as follows:
[0130] int save_if_interesting(FILE*case){
[0131] / *if found new path, hnb is 1* /
[0132] hnb=has_new_bits(case);
[0133] / *if found smaller pointer distance, hnm is 1* /
[0134] hnm=has_new_min(case);
[0135] if(!hnb&&!hnm)
[0136] return 0;
[0137] / *replace seed which has same path by new seed* /
[0138] delete_same_path(case);
[0139] add_to_queue(case);
[0140] }
[0141] Step 73, evaluate the seeds in the seed queue. Use execution time, file size, minimum pointer distance, and memory allocation peak to calculate the excellent degree of the seeds, keep the excellent seeds in the seed queue, further refine the seed queue, and leave it for subsequent mutation.
[0142] In this embodiment, the code of the seed evaluation indicator function is as follows, where the smaller the value of the fav_factor variable represents the better the current seed:
[0143]
[0144]
[0145] Step 8, run the fuzz test, output the program input file that causes the target program to have a memory safety error.
[0146] The technical features of the above embodiments can be combined in any manner. For brevity, not all possible combinations of the technical features in the above embodiments are described, but it should be understood that any combination of the technical features is within the scope of the present disclosure as long as the combination does not result in contradictions.
[0147] The above embodiments only express several implementation manners of the present application, and the description is relatively specific and detailed, but it should not be understood as a limitation on the scope of the application. It should be pointed out that, for ordinary skilled persons in the art, several modifications and improvements can be made without departing from the concept of the present application, and these are within the protection scope of the present application.< / num> < / num> < / num>
Claims
1. A fuzz testing method for memory security vulnerabilities combining dynamic analysis, characterized in that, The method comprises the following steps: S1, opening a source code file of a program to be tested, inserting type definition and function definition source code for dynamic analysis in the source code file; S2, preprocessing the source code of the program to be tested by using a compiler, and then parsing the source code of the program to be tested by using the compiler; S3, traversing an abstract syntax tree and inserting a probe into a node of the abstract syntax tree, so as to detect a memory error during program running, and maintaining a shared memory variable of a minimum pointer boundary distance and a memory allocation peak value; S4, compiling the source code after the probe to obtain assembly code; S5, performing coverage insertion into the assembly code, and skipping the code inserted in the front for dynamic analysis; S6, assembling and linking the assembly code after the probe to obtain an executable file, S7, performing fuzz testing on the executable file, and using coverage, a minimum pointer boundary distance and a memory allocation peak value provided by dynamic analysis as feedback information to guide the fuzz testing; S8, running the fuzz testing, and outputting a program input file causing a memory safety error of the target program; The type definition and function definition source code inserted in step S1 for dynamic analysis comprise the following steps: S11, inserting type definition of pointer metadata, the structure type of the pointer metadata comprising a first address and a last address of a memory space pointed by a pointer variable, an address of the pointer variable, and a state of the memory space; S12, inserting type definition of a data structure for maintaining the pointer metadata, the data structure comprising a hash table and a two-level tree, both of which use an address value of the pointer variable as an index value; in the two-level tree, the 26th to 48th bits from a low bit of the index value are used as a first-level index value, and the 4th to 25th bits are used as a second-level index value; an initial capacity of the first-level table and the second-level table is 2^23 and 2^22 respectively, each element in the first-level table is a pointer to the second-level table, and each element in the second-level table is a pointer to the pointer metadata; S13, inserting function definition for maintaining the pointer metadata, inserting the pointer metadata into the hash table or the two-level tree when a pointer variable is created during program running, and dynamically expanding the capacity when the capacity is insufficient; S14, inserting function definition for memory safety detection, updating a difference between a current pointer value and a legal first address of corresponding pointer metadata, a difference between the pointer value and a legal last address of the corresponding pointer metadata, and retaining a minimum difference as a minimum pointer boundary distance, which is used for judging whether there is a tendency of pointer out-of-bound; S15, inserting definition of a wrapping function of a memory allocation library function, the wrapping function judging whether the memory allocation library function is successfully executed according to a return value of the function: if yes, updating a total value of memory allocated when the program runs to this place, and updating a global memory allocation peak value with the total value of the memory allocated, which is used for judging whether there is a tendency of allocating too large memory, and finally returning the return value of the memory allocation library function; if not, not performing any operation; In step S7, the coverage, the minimum pointer boundary distance and the memory allocation peak value provided by dynamic analysis are used as feedback information to guide the fuzz testing, which comprises the following steps: S71, collect test cases to join the seed queue: first, according to the coverage information provided by the fuzz testing, it is judged whether new program execution path is found in the program running process: If there is a new program execution path, the test case is directly added to the seed queue; If there is no new program execution path, it is judged whether a number of pointers are closer to the legal upper and lower bounds of their pointer metadata, and whether a higher memory allocation peak value is generated in the running process: if a number of pointers are closer to the legal upper and lower bounds of their pointer metadata, or a higher memory allocation peak value is generated, the test case is added to the seed queue; if there are no a number of pointers closer to the legal upper and lower bounds of their pointer metadata, and no higher memory allocation peak value is generated, the test case is discarded; S72, simplify the seed queue: if the test case can join the seed queue through the judgment of coverage, minimum pointer boundary distance and memory allocation peak value, replace the test case in the seed queue with the same execution path as the test case, and the minimum pointer boundary distance is greater or the memory allocation peak value is lower; S73, evaluate the seeds in the seed queue: use the execution time, file size, minimum pointer boundary distance and memory allocation peak value to calculate the excellent degree of the seeds, keep the excellent seeds in the seed queue, further simplify the seed queue, and leave it for subsequent mutation.
2. The method of claim 1, wherein the method is performed by a computer system. The specific processing logic of the pointer metadata is as follows: In the hash table mode, the address value of the pointer variable is used as the index value, and the linked address method is used to handle the conflict. When the number of table elements reaches more than three times the number of buckets, the number of buckets is expanded to twice. In the two-level tree mode, the 26th to 48th bits of the low bits of the pointer variable address value are used as the first index value, and the 4th to 25th bits are used as the second index value. When the second table corresponding to the first index value is missing, the second table is created and the pointer metadata is inserted into the second table.
3. The method of claim 1, wherein the method further comprises: In step S3, the abstract syntax tree is traversed and the nodes thereof are instrumented, including the following steps: S31, instrument the program main function entry for obtaining the shared memory of the fuzz testing and establishing inter-process communication with the fuzz testing; S32, instrument the definition and initialization statements of the pointer variable, for creating pointer metadata and inserting the pointer metadata into the hash table or two-level tree; S33, instrument the pointer dereferencing, array subscript access, and member access statements of the structure pointer variable, for detecting memory errors, and updating the minimum difference between the pointer value and the legal starting address of the pointer metadata, and the minimum difference between the pointer value and the legal ending address of the pointer metadata, storing the minimum difference as the minimum pointer boundary distance in the shared memory variable of the fuzz testing; S34, instrument the function call statements of memory allocation and memory release, replace them with the corresponding wrapper function calls, for maintaining the pointer metadata of the heap type pointer variable, and updating the maximum memory value that has been allocated, storing the maximum memory value as the memory allocation peak value in the shared memory variable of the fuzz testing.
4. The method of claim 1, wherein the method further comprises: The code inserted in the foregoing step S5 for dynamic analysis includes a pointer metadata operation function, a normal wrapper function, and an inline wrapper library function, and comprises the following steps: S51, skip the instrumentation of the pointer metadata operation function, by recognizing the function name prefix of the instrumented pointer metadata operation function,.LFE in the assembly code representing the end of the function body <num>identifying a start mark and an end mark to skip coverage instrumentation of code between the function name and the end mark;< / num> S52, skipping instrumentation of the normal wrapper function; the normal wrapper function passes pointer metadata of a function return value and a function parameter of a pointer type to the original function for memory safety checking during execution of the original function, passes an end mark, and calls the original function to obtain a return value, and then returns the return value of the original function; S53, skipping instrumentation of the inline wrapper library function; by identifying whether the source of the inline code block belongs to a source file for dynamic analysis, coverage instrumentation of the inline code block in the source file for dynamic analysis is skipped.
Citation Information
Patent Citations
Binary program bug testing method and device and readable storage medium
CN111581106A
Method for dynamically analyzing memory security of program containing specific statement
CN116126705A