Binary code-oriented static taint analysis system and method
By constructing an enhanced data dependency graph and introducing an on-demand micro-symbol execution mechanism, the memory address of binary code is finely decomposed and quantitatively evaluated, solving the problem of insufficient memory access precision in static analysis of binary code and realizing efficient and accurate taint propagation analysis.
Patent Information
- Authority / Receiving Office
- CN · China
- Patent Type
- Applications(China)
- Current Assignee / Owner
- Filing Date
- 2025-12-29
- Publication Date
- 2026-04-03
AI Technical Summary
Existing binary code static analysis schemes lack precision when handling memory access and cannot effectively identify complex dynamic addressing, leading to taint propagation, false alarm explosions, or missed detections, which seriously affects the accuracy and efficiency of the analysis.
By constructing an enhanced data dependency graph and introducing an on-demand micro-symbol execution mechanism, memory address expressions are finely decomposed and quantitatively evaluated, path-sensitive taint propagation iterations are performed, and the final taint state table is generated.
It effectively identifies complex dynamic memory addressing, avoids broken taint chains and false alarm explosions, significantly optimizes resource allocation of the analysis engine, and improves analysis accuracy and efficiency.
Smart Images

Figure CN121786833A_ABST
Abstract
Description
Technical Field
[0001] This application relates to the field of intelligent analysis, and more specifically, to a static taint analysis system and method for binary code. Background Technology
[0002] With the increasingly severe cybersecurity situation, automated analysis of binary programs has become a core method for vulnerability detection and security auditing. In many practical applications, such as security assessments of third-party commercial software, supply chain security audits, or reverse engineering of unknown malicious code, analysts often cannot obtain the source code. Therefore, building an efficient and accurate static taint analysis scheme for binary code is of great importance and technical significance for deeply mining vulnerabilities (such as information leakage and buffer overflows) within data structures without source code.
[0003] Existing binary code static analysis schemes typically employ instruction lifting techniques to translate assembly instructions into intermediate language, and then perform data flow analysis on this basis. However, when processing release binary files in real-world industrial environments, the analysis accuracy is severely limited. Because these files are usually stripped of symbols, lacking variable names, type information, and memory layout descriptions, the accuracy of memory alias analysis is low. Current mainstream mechanisms exhibit a rigid binary approach when handling memory accesses, simply dividing memory operations into fully deterministic and fully ambiguous categories. This approach ignores the widespread structural correlation between base addresses and offsets in memory address expressions. This leads to analysis engines either over-approximating dynamic addressing (such as adding constant offsets to base registers), causing taint propagation and a bombardment of false positives, or ignoring ambiguous accesses, resulting in broken taint propagation chains and severe missed detections. This lack of memory access determination capability makes static analysis overly reliant on computationally expensive symbolic execution engines. If the path becomes complex and computation fails, it severely impacts the final accuracy and efficiency of the analysis, becoming a core bottleneck restricting the practical application of current binary static analysis tools.
[0004] Therefore, an optimized static taint analysis method for binary code is desired. Summary of the Invention
[0005] To address the aforementioned technical problems, this application provides a static taint analysis system and method for binary code.
[0006] According to one aspect of this application, a static taint analysis method for binary code is provided, comprising: Obtain the target binary file to be analyzed; The target binary file to be analyzed is subjected to binary code lifting and control flow graph construction to obtain intermediate language code and control flow graph; Based on taint rules, we construct intra-function data dependency graphs and mark taint sources on intermediate language code and control flow graphs to obtain data dependency graphs and a list of pending work. An enhanced data dependency graph is obtained by performing memory alias resolution based on on-demand microsymbol execution on the data dependency graph, the list of pending work, and the control flow graph. Path-sensitive taint propagation iterations are performed on the work list to be processed and the enhanced data dependency graph to obtain a taint state table.
[0007] According to another aspect of this application, a static taint analysis system for binary code is provided, comprising: The target binary file acquisition module is used to acquire the target binary file to be analyzed. The binary code lifting and control flow graph construction module is used to lift and construct the control flow graph of the target binary file to be analyzed in order to obtain intermediate language code and control flow graph. The Intra-Function Data Dependency Graph Construction and Tag Marking module is used to construct and tag intra-function data dependency graphs and taint sources based on taint rules to obtain data dependency graphs and a list of pending work items from intermediate language code and control flow graphs. The memory alias resolution module is used to perform memory alias resolution on data dependency graphs, pending work lists, and control flow graphs based on on-demand micro-symbol execution to obtain enhanced data dependency graphs; The taint propagation iteration module is used to perform path-sensitive taint propagation iteration on the work list to be processed and the enhanced data dependency graph to obtain the taint state table.
[0008] Compared to existing technologies, this application provides a static taint analysis system and method for binary code. Through binary lifting and control flow graph construction, it introduces an on-demand micro-symbolic execution mechanism on top of basic data flow analysis. Specifically, for memory ambiguity nodes in the data dependency graph, it achieves refined alias resolution through reverse instruction slicing and constraint solving, thereby generating an enhanced data dependency graph. Based on this, path-sensitive taint propagation iterations are performed to generate the final taint state table. This approach not only effectively identifies complex dynamic memory addressing, avoiding taint chain breaks and false alarm explosions caused by ignoring ambiguity or excessive approximation, but also significantly optimizes the resource allocation of the analysis engine. Attached Figure Description
[0009] The above and other objects, features, and advantages of this application will become more apparent from the more detailed description of the embodiments of this application in conjunction with the accompanying drawings. The drawings are provided to further illustrate the embodiments of this application and form part of the specification. They are used together with the embodiments of this application to explain this application and do not constitute a limitation thereof. In the drawings, the same reference numerals generally represent the same components or steps.
[0010] Figure 1 This is a flowchart of a static taint analysis method for binary code according to an embodiment of this application; Figure 2 This is a schematic diagram of the data flow of a static taint analysis method for binary code according to an embodiment of this application; Figure 3 This is a block diagram of a static taint analysis system for binary code according to an embodiment of this application. Detailed Implementation
[0011] Hereinafter, exemplary embodiments according to this application will be described in detail with reference to the accompanying drawings. Obviously, the described embodiments are merely some embodiments of this application, and not all embodiments of this application. It should be understood that this application is not limited to the exemplary embodiments described herein.
[0012] As indicated in this application and claims, unless the context clearly indicates otherwise, the words "a," "an," "an," and / or "the" are not specifically singular and may include plural forms. Generally speaking, the terms "comprising" and "including" only indicate the inclusion of explicitly identified steps and elements, which do not constitute an exclusive list, and the method or apparatus may also include other steps or elements.
[0013] While this application makes various references to certain modules of the systems according to embodiments of this application, any number of different modules can be used and run on user terminals and / or servers. The modules described are merely illustrative, and different aspects of the systems and methods may use different modules.
[0014] Flowcharts are used in this application to illustrate the operations performed by the system according to embodiments of this application. It should be understood that the preceding or following operations are not necessarily performed in exact order. Instead, various steps can be processed in reverse order or simultaneously as needed. Furthermore, other operations can be added to these processes, or one or more steps can be removed from them.
[0015] In the technical solution of this application, a static taint analysis method for binary code is proposed. Figure 1 This is a flowchart of a static taint analysis method for binary code according to an embodiment of this application. Figure 2This is a system architecture diagram of a static taint analysis method for binary code according to an embodiment of this application. Figure 1 and Figure 2 As shown, the static taint analysis method for binary code according to an embodiment of this application includes the following steps: S1, obtaining the target binary file to be analyzed; S2, performing binary code lifting and control flow graph construction on the target binary file to be analyzed to obtain intermediate language code and control flow graph; S3, based on taint rules, performing intra-function data dependency graph construction and taint source marking on the intermediate language code and control flow graph to obtain data dependency graph and a list of pending work; S4, performing memory alias resolution based on on-demand microsymbol execution on the data dependency graph, the list of pending work, and the control flow graph to obtain an enhanced data dependency graph; S5, performing path-sensitive taint propagation iteration on the list of pending work and the enhanced data dependency graph to obtain a taint state table.
[0016] Specifically, S1 involves acquiring the target binary file to be analyzed. It should be understood that, given the severe cybersecurity situation, analysts often cannot obtain the program's source code for practical applications such as third-party commercial software security assessments, supply chain security audits, or reverse engineering of unknown malicious code. Therefore, it is essential to first acquire the target binary file so that, without source code, automated methods can be used to perform vulnerability detection and security auditing, thereby uncovering deep-seated security vulnerabilities within data structures, such as information leakage or buffer overflows. The target binary file refers to a collection of code that has been compiled and linked, and can be directly executed by computer hardware or a virtual machine. In actual industrial environments, these files are often optimized release versions, the core characteristic of which is the removal of debugging symbols, resulting in a lack of semantic information from high-level languages during analysis.
[0017] In practice, the analysis engine first retrieves the target file to be evaluated from the storage medium or network environment and loads its binary data stream into memory. Next, the system parses the file header to identify its specific execution format (such as ELF or PE format) and, based on the characteristics of industrial release versions, determines whether the file has undergone symbol stripping. Since such files typically lack variable names, type information, and memory layout descriptions, the retrieval process also includes locating the various code and data segments within the file, laying the foundation for subsequent instruction promotion and control flow graph construction.
[0018] Specifically, S2 involves performing binary code uplifting and control flow graph construction on the target binary file to be analyzed to obtain intermediate language code and a control flow graph. It should be understood that the original target binary file is a byte stream composed of machine instructions for a specific hardware architecture (such as x86, ARM, etc.). Its semantics are highly coupled with specific registers, addressing modes, and hardware flags, and it lacks variable names, type information, and structured control flow information found in high-level languages. To perform in-depth security auditing and vulnerability discovery without source code, it is necessary to first shield the underlying hardware differences, abstract complex assembly instructions into a unified, platform-independent semantic expression through code uplifting, and establish an execution skeleton that reflects the program's logical topology. This provides the necessary data foundation and logical carrier for subsequent construction of intra-function data dependency graphs, execution of on-demand micro-symbol execution, and path-sensitive taint propagation.
[0019] In practice, the first step is to perform binary disassembly and parsing of the target binary file to obtain the assembly instruction sequence. During this process, a disassembler can load the target binary file, parse its file format (e.g., PE or ELF), and identify the code segments. Then, based on the target file's instruction set architecture (e.g., x86 or ARM), the engine decodes the machine instructions byte-by-byte, starting from the beginning address of the code segment, converting them into a human-readable assembly instruction sequence. This process ensures an accurate mapping from machine code to assembly mnemonics, preparing for subsequent semantic enhancement.
[0020] Next, the assembly instruction sequence is subjected to intermediate language enhancement and SSA normalization to obtain intermediate language code. In this process, the input assembly instruction sequence is first traversed line by line, and each assembly instruction is decomposed and converted into one or more semantically equivalent intermediate language instructions according to predefined mapping rules. For example, a complex x86 instruction "add[rax], rcx" (meaning: add the value of the RCX register to the value stored at the memory address pointed to by the RAX register, and then write the result back to that memory address) is decomposed into three more basic and semantically clear intermediate language instruction sequences during promotion: the first instruction corresponds to a memory load operation, loading the value pointed to by RAX into a temporary variable, denoted as "t1 = load(rax)"; the second instruction corresponds to an addition operation, adding the value of the temporary variable t1 to the value of the RCX register, and storing the result in another temporary variable, denoted as "t2 = add t1, rcx"; the third instruction corresponds to a memory store operation, storing the addition result t2 back to the address pointed to by RAX, denoted as "store(rax, t2)". In this way, the input-output relationship of each operation node becomes clearly visible, greatly facilitating subsequent data flow analysis.
[0021] Furthermore, based on intermediate language enhancement, the generated intermediate code undergoes further data flow normalization to convert it into a static single assignment (SSA) form. The core requirement of SSA is that each variable in the program must have one and only one definition point. Implementing SSA normalization involves two main operations: renaming and inserting a Phi function. The renaming operation is performed on all variables in the original intermediate code that are repeatedly assigned values. Specifically, the analyzer traverses the control flow graph, and whenever it encounters a reassignment of an existing variable, it creates a new version of that variable (usually by adding a version index) and updates all subsequent uses of that variable to this new version. Inserting a Phi function handles the uncertainty of variable values that may occur at control flow merging points. A Phi function is a special instruction located at the beginning of a basic block, selecting a variable version as its value based on the actual execution path. Specifically, at merging points in the control flow graph with multiple predecessor basic blocks, for variables used after that point, if different versions arrive at that point along different paths, a Phi function needs to be inserted at the beginning of the basic block at that merging point. For example, at the conditional node of a loop structure (a basic block with multiple predecessors), for variables updated within the loop body, a `Phi` function needs to be inserted to merge the initial value version before the loop and the updated version within the loop body. Formally, this is represented as a function whose parameters are variable versions from different predecessor basic blocks, and whose output depends on the actual execution path. This transformation process ensures that the definition source of any variable value used at any point in the program is syntactically unique and unambiguous, thus providing a fundamental guarantee for constructing precise definition-use chains and data dependency graphs.
[0022] Next, the intermediate language code is divided into basic blocks and a control flow graph is constructed to obtain the control flow graph. That is, basic blocks are identified based on the code sequence that has been converted to intermediate language and standardized to SSA form. A basic block is the largest continuous sequence of instructions, where only the first instruction can be the entry point and only the last instruction can be the exit point. In practice, the intermediate language instruction sequence is scanned, and the target instruction of each jump instruction and the instructions following the jump instruction are marked as the start of a basic block, thus dividing the instruction sequence into multiple basic blocks. After the basic block division is completed, the control flow graph is constructed. The control flow graph is a directed graph where nodes are basic blocks and edges represent control flow transitions. Specifically, the jump instructions at the end of each basic block (such as conditional branches, unconditional jumps, function returns, etc.) are analyzed to determine the target basic blocks that the basic block may jump to, and corresponding directed edges are added to the graph. This process ultimately generates a control flow graph depicting all possible execution paths within a function.
[0023] Specifically, S3, based on taint rules, constructs an intra-function data dependency graph and marks taint sources on the intermediate language code and control flow graph to obtain a data dependency graph and a list of pending tasks. It should be understood that traditional binary code static analysis exhibits a rigid binary approach when handling memory access, simply dividing memory operations into two categories: fully deterministic and fully ambiguous. This ignores the widespread structural correlation between base addresses and offsets, making it highly susceptible to taint propagation or chain breaks when facing dynamic addressing. Therefore, in the technical solution of this application, by constructing an intra-function data dependency graph and introducing quantified memory classification labels, a fine-grained evaluation of memory access determinism is achieved, thus striking a balance between accuracy and efficiency, and providing logical support for subsequent efficient and accurate field-sensitive taint analysis.
[0024] In practice, the process begins with instruction traversal and definition of the control flow graph, followed by chain analysis to obtain the definition, and finally, the use of linked lists. It's understandable that when processing release binary files in industrial environments, the lack of variable names, type information, and memory layout descriptions due to the typical symbol stripping process severely limits analysis accuracy. To construct an efficient and accurate static taint analysis solution, the internal data flow logic of the program must first be clarified. By traversing and defining the control flow graph and using chain analysis, the relationship between the source of data generation and its consumption destination can be extracted from the underlying intermediate language code. This solves the problem of insufficient memory access judgment capabilities caused by a lack of semantic information, prevents breaks in the taint propagation chain, and provides the core logical framework for subsequently constructing the data dependency graph within functions.
[0025] In this process, firstly, the system acquires the control flow graph (CFG) generated in the preceding steps. Based on this, it performs sequential or recursive instruction traversal on each basic block in the graph according to the program's execution logic. During the traversal of the intermediate language code, the system performs definition-use chain analysis for each intermediate instruction. Specifically, the analysis engine identifies the "definition" operation (i.e., write to registers or memory addresses) and "use" operation (i.e., read from registers or memory addresses) in each instruction. Next, the system uses a data flow analysis algorithm to trace the lifecycle of variables across the boundaries of basic blocks, matching and connecting the definition point of each variable with all its possible use points. In this way, the system transforms the scattered intermediate language instructions into a list with directed connections, ultimately obtaining a definition-use linked list. This linked list meticulously records the trajectory of all data flow within the function and serves as direct input for constructing the data dependency graph based on the intermediate language code.
[0026] Next, a data dependency graph is constructed based on intermediate language code and definitions using linked lists. It should be understood that, due to the lack of semantic information and the highly dynamic nature of memory access in raw binary code, traditional binary rigid classification methods often simply divide complex memory operations into completely deterministic or completely ambiguous categories. This ignores the widespread structural correlation between base addresses and offsets, easily leading to taint propagation interruptions or false alarm explosions in the analysis engine when facing dynamic addressing. To achieve efficient and accurate static taint analysis, this application establishes a logical carrier for value passing between program variables by constructing a data dependency graph (DDG). Specifically, by combining SSA-normalized intermediate language code with detailed definitions using linked lists, the system can accurately trace the source and destination of each operand across basic block boundaries, thus providing a core topological foundation for subsequent quantification of memory address determinism and execution of on-demand micro-symbolic execution.
[0027] In this process, the intermediate language code produced by the preceding steps and transformed by Static Single Assignment (SSA), along with the definition-use list reflecting variable definitions and reference relationships, are first acquired. The system then creates graph nodes based on each intermediate language instruction as the basic unit and initiates a traversal mechanism. During traversal, the analysis engine, based on the records in the definition-use list, establishes directed edges from each variable's "definition" point to all its possible "use" points, thereby transforming the flat instruction sequence into a graph structure reflecting data flow relationships. In particular, for nodes involving memory access, the system pre-applies a pattern matching algorithm to semantically transform the memory operands, deconstructing them from raw address strings into a structured expression. Through this deconstruction, when constructing the data dependency graph, the system can separate static components (such as constant shifts) and dynamic components (such as base registers) in the address expression, ensuring that data dependency edges not only connect register operations but also encompass memory operation units with structured relationships. This construction method ensures that the graph structure can accurately depict the data dependency logic inside the program, laying the data support for subsequent calculation of relational affine scores and execution of ternary classification decisions.
[0028] Furthermore, the data dependency graph is classified and ambiguously labeled by memory operation nodes to obtain a labeled data dependency graph. It should be understood that the classification strategy of the binary code static analysis process exhibits a rigid binary approach when handling memory accesses. Specifically, in the address type determination stage, memory operations are simply divided into two categories: fully deterministic and fully ambiguous. This approach ignores the widespread semi-deterministic memory access patterns between the two, failing to delve into and utilize a crucial special relationship: the structural association between the base address and the offset. However, in real binary programs, many field accesses to data structures on the heap or stack are represented by a dynamic base address register plus a static constant offset, such as [RAX + 8]. Traditional mechanisms rely on the dynamic register RAX, directly classifying such accesses as fully ambiguous, losing static information (i.e., constant offset + 8), and failing to recognize the potential strong structural association between [RAX + 8] and [RAX + 4]. Treating all such accesses as completely ambiguous not only causes the analysis engine to prematurely abandon precise static derivations but also leads to over-reliance on the computationally expensive symbolic execution engine in subsequent steps. If symbolic execution times out or fails due to path complexity, it directly triggers interruptions or excessive propagation of taints, severely impacting the final accuracy and efficiency of the analysis. The root cause lies in the mechanism's failure to destructure memory address expressions and quantify their inherent determinism.
[0029] To address the aforementioned issues, this application introduces a memory access classification mechanism based on address structure decomposition and relational affine score. By performing fine decomposition and quantitative evaluation of memory address expressions, it achieves a ternary classification of memory access, thereby significantly improving the accuracy and efficiency of the analysis.
[0030] In this process, firstly, the memory operands of each node are extracted from the data dependency graph, and the memory address expressions of the node's memory operands are deconstructed to obtain structured address expressions. It should be understood that the original flattened address strings cannot support subsequent quantitative analysis. Therefore, in the technical solution of this application, a pattern matching algorithm, namely the structure function Deconstruct, is applied to transform the input memory operands... Decomposed into a structured address expression containing four standard components: base register, index register, scaling factor, and static shift. This process can be expressed by the following formula:
[0031] By separating static components (such as constant displacements) from dynamic components (such as base address registers) in address expressions, the analysis can go beyond simple dynamic or non-dynamic binary judgments, enabling more refined evaluation and determination.
[0032] Next, a relational affine score is applied to the structured address expression to obtain a relational affine score. That is, a continuous score is used to quantify the predictability or determinism of the address. Specifically, the relational affine score is determined by combining the static structural features of the address expression with the tightness of its dynamic part's association with the program context. This process is expressed by the following formula:
[0033] in, and These represent the weighting coefficients for the displacement component and the base address component, respectively, and are used to adjust the contribution of different factors to the total score. For indicator functions. When a structured address expression... Its value is 1 when it contains a non-zero static displacement, and 0 otherwise. It is an exponentially decaying function, where This is the attenuation factor. Represents the distance of data flow, that is, from a known memory anchor point on the data dependency graph. (Such as the initial value of the stack pointer) is propagated to the current base address register. The minimum number of instruction steps required. Indicates from function context All known memory anchors Among (such as stack frame base address, global data area base address), select the one with the highest correlation to the base address register.
[0034] This step mathematically models the intuition of program analysis: the predictability of a memory address depends not only on whether it contains a constant offset (reflected by indicator function terms), but also on the data flow distance between its dynamic base address and stable memory regions (such as stack frames) in the program. The closer the data flow distance, the more likely the base address is to be calculated with a small offset based on pointers in stable regions, and the more predictable its behavior. The exponential decay function aptly simulates this characteristic of weakening correlation with increasing distance. Ultimately, a quantitative index that accurately reflects the degree of address determinism is generated as the basis for classification decisions.
[0035] Furthermore, based on relational affine fractions, a ternary classification and enhanced labeling based on a fractional threshold is performed on the structured address expression to obtain memory node labels. That is, by utilizing the quantization results of the preceding steps, a more intelligent and refined classification decision is made. Specifically, two thresholds are set. and Based on the range of the score, the memory operation node is assigned an enhanced memory node label with richer semantics. This process can be expressed by the following formula:
[0036] in, This represents the final generated enhanced memory node tag. This represents the global absolute address. and These represent the base address and offset extracted from the address expression, respectively. and These represent the high and low classification thresholds, respectively. This means that for scores between... and Memory accesses between nodes are no longer simply ambiguous, but rather structured. This marker enables the subsequent taint propagation engine to perform efficient relational reasoning: if the base address If the memory location is contaminated, the engine can directly and cost-effectively deduce that the memory cell located at [B+O] is also contaminated, without needing to initiate heavyweight symbolic execution. Only when the score is below... Only when an address is highly dynamic and has a very weak association with any stable region is it marked as completely ambiguous and left to be handled by subsequent ultimate means.
[0037] In summary, this mechanism achieves a better balance between accuracy and efficiency in binary static taint analysis by transforming the rigid binary classification of memory access into a refined, quantitative ternary evaluation system. Specifically, by introducing relative addressing categories, it accurately characterizes the inherent correlations among accesses to a large number of data structures, effectively avoiding taint propagation errors caused by over-approximation and reducing false positives and false negatives. Furthermore, by handling the vast majority of memory accesses with structural characteristics through lightweight relational reasoning, this mechanism significantly reduces reliance on expensive symbolic execution engines, saving substantial computational resources. Ultimately, the implementation of this mechanism makes efficient and accurate field-sensitive taint analysis of binary code possible, providing solid technical support for in-depth mining of vulnerabilities (such as information leakage and buffer overflows) within data structures without source code.
[0038] Subsequently, based on taint rules, taint source matching is performed on the labeled data dependency graph to obtain a list of pending tasks. It should be understood that in a binary analysis scenario without source code, in order to deeply uncover vulnerabilities within the data structure (such as information leakage, buffer overflows, etc.), the analysis engine must clearly define the initial input points of tainted data. By performing taint source matching on the data dependency graph that has already undergone preliminary quantification and labeling of memory aliases, the abstract binary instruction logic can be combined with specific security audit requirements (taint rules). This provides an initial trigger set for subsequent path-sensitive taint propagation iterations, ensuring that the analysis process covers all potential risk entry points while leveraging the structural relationships within the graph to reduce the blind spots in subsequent analysis.
[0039] In this process, firstly, the system acquires the labeled data dependency graph generated in the previous steps. The memory operation nodes in this graph have been ternary-classified based on relational affine scores, meaning each node carries an enhanced memory node label. Next, the analysis engine loads pre-defined taint rules, which define semantic features such as network reception, file reading, or specific system calls. Subsequently, the system traverses all nodes in the labeled data dependency graph, performing pattern matching between the node's opcode and operand semantics and the taint rules. When a taint source node matching the rules is found, the system marks it as initially tainted and adds it to a dynamically maintained list of pending tasks. This ensures that even during the taint source matching phase, structurally related dynamic memory entry points are captured, and the resulting list of pending tasks serves as the sole input for subsequent propagation iterations.
[0040] Specifically, in step S4, memory alias resolution based on on-demand micro-symbolic execution is performed on the data dependency graph, the list of pending work items, and the control flow graph to obtain an enhanced data dependency graph. It should be understood that in the basic data dependency graph constructed in the previous step, for memory access nodes marked as "ambiguous" (e.g., operations with low address determinism due to register indirect addressing), the analysis engine cannot statically determine the specific memory address they access, nor can it determine whether two different ambiguous accesses might point to the same memory location (i.e., the existence of memory aliases). This uncertainty directly leads to a decrease in the accuracy of taint propagation: conservative analysis may over-propagate taints to memory locations that should not be tainted, resulting in false positives; or it may fail to identify the true taint propagation through alias paths, resulting in false negatives. By introducing the on-demand micro-symbolic execution mechanism, the system can dynamically and purposefully perform in-depth symbolic reasoning on specific ambiguous memory accesses, resolve potential memory alias relationships, and feed these newly discovered relationships back into the data dependency graph, thereby generating a more accurate and information-rich enhanced data dependency graph, clearing obstacles for subsequent high-precision taint propagation.
[0041] In practice, firstly, based on the data dependency graph, ambiguous node propagation detection and micro-execution triggering are performed on the list of work items to be processed to identify target ambiguous nodes. Specifically, the analyzer operates based on the existing data dependency graph and the list of work items to be processed. The mechanism is triggered when a tainted state propagates along the edges of the data dependency graph, i.e., to a memory operation node marked as "ambiguous" (e.g., a store instruction with an unknown target address), or when data marked as a tainted source is about to be stored at an ambiguous address. At this point, the ambiguous memory node is identified as a target ambiguous node requiring further analysis. This on-demand triggering strategy ensures that symbolic execution, a heavy analytical tool, is only applied to critical nodes that have a real impact on taint propagation, avoiding the huge computational overhead of full-program symbolic execution.
[0042] Next, based on the control flow graph, reverse instruction slicing is performed on the target ambiguous node to obtain an instruction slice. Specifically, the analyzer starts from the target ambiguous node and traces backward along the edges of the control flow graph, collecting only instructions that have direct or indirect data dependencies on calculating the ambiguous memory address value. For example, if the ambiguous address is [eax], the slice will include all instructions that affect the current value of the eax register, but will exclude instructions unrelated to the calculation of the eax value. The resulting instruction slice contains the minimum set of instructions required to understand and solve the ambiguous address, greatly reducing the scope of code that needs to be analyzed for subsequent symbolic execution and improving efficiency.
[0043] Next, constraint generation and SMT (Satisfiability Modulo Theory) solving are performed on the instruction slices to obtain a set of possible addresses. Specifically, the analyzer assigns symbolic values to the initial inputs (such as function parameters and global variables) in the instruction slice, and then simulates the execution of each instruction in the slice, but does not perform calculations on the specific values; instead, it records the symbolic expressions and path constraints represented by the instruction operations. For example, for a conditional branch instruction, execution is divided into two paths, and the path conditions are recorded for each. Finally, for the target ambiguity node (such as a memory operation), the analyzer collects all constraints that may affect its address value. These constraints are combined into a logical formula. Subsequently, a satisfiability modular theory solver is used to solve this complex logical formula. The task of the SMT solver is to determine whether there are variable assignments that satisfy all constraints. If so, it may return one or more specific solutions (i.e., possible specific memory address values or ranges of values), or prove that there is no solution under the current constraints. This process formally explores all possible execution results of the target ambiguity node in the current program context.
[0044] Subsequently, pseudo-variable mapping is performed on the possible address set based on the data dependency graph to obtain an enhanced data dependency graph. It should be understood that the SMT solver might return concrete address values (such as 0x4000) or constrained symbolic expressions, while a static data dependency graph requires dependency edges between nodes. Therefore, the analyzer creates pseudo-variables to represent these concrete or symbolic memory addresses obtained through the solver. Then, in the data dependency graph, the analyzer adds new dependency edges: for example, if the parser discovers an ambiguous store instruction `store [eax]`, and `[eax]` in `tainted_data` might point to the address of a global variable `global_var`, then a data dependency edge from the `tainteddata` to the load instruction node of `global_var` is added to the data dependency graph. In this way, the dynamically inferred alias relationships are statically solidified into the enhanced data dependency graph. This enhanced graph not only contains the original data dependencies but also includes key memory alias information resolved through micro-symbolic execution, enabling subsequent taint propagation to more accurately follow these newly discovered paths.
[0045] Specifically, in step S5, path-sensitive taint propagation iteration is performed on the work list to be processed and the enhanced data dependency graph to obtain a taint state table. It should be understood that simply identifying taint sources and constructing the data dependency graph does not directly answer the core security question of which sensitive operations (i.e., taint sinks) are ultimately affected by tainted data. The taint propagation iteration acts as a bridge connecting taint sources and taint sinks, tracing the propagation path of taints by simulating data flow. The path-sensitive nature is crucial for reducing false positives, as it distinguishes the differences in taint states across different execution paths, avoiding the confusion of taint states on paths that cannot be executed simultaneously. For example, data on one path may be contaminated, while data on another path may be cleaned; path-sensitive analysis can accurately capture this difference. This step iteratively processes the work list, utilizing the precise data flow and alias information provided by the enhanced data dependency graph to ultimately generate a detailed taint state table, providing direct evidence for security vulnerability assessment.
[0046] In practice, the first step involves selecting propagation nodes and predecessor indices from the work list to be processed and the enhanced data dependency graph to obtain the current node and its predecessor node set. Specifically, a current node is selected from the work list to be processed according to a certain strategy (such as first-in, first-out). Then, based on the enhanced data dependency graph, the set of predecessor nodes on all data streams is identified, i.e., those operation nodes whose computation results are directly used as inputs to the current node. For example, for an addition instruction node, its predecessor node is the node that provides the two addends. This step determines the possible sources of tainted data flowing into the current node.
[0047] Next, based on the current taint state table, taint state calculations based on transfer functions are performed on the current node and the set of predecessor nodes to obtain new taint states. In this process, firstly, based on the current taint state table, transfer function evaluations based on instruction semantics are performed on the current node and the set of predecessor nodes to obtain a path taint result set. For the current node and each of its predecessor nodes, the parser defines a transfer function according to the instruction semantics (operation type) of the current node. This function describes how the output taint state changes after the input taint state passes through this instruction. For example, for an arithmetic addition instruction, the transfer function is usually defined as "the output taint state is the logical OR of the taint states of the input operands," meaning that if any addend is tainted, the sum is also tainted. For a deliberate taint cleansing operation (such as assigning a constant to a variable), its transfer function may reset the output taint state to "untainted." This process generates a path taint result set for all possible predecessor paths of the current node, containing different taint state results obtained from different predecessor nodes after calculation using transfer functions. Secondly, the path taint result set is aggregated to obtain a new taint state. Since the current node may receive data from multiple predecessor nodes, these taint state results from different paths are further merged into a unified new taint state for this node. Specifically, the path taint result set is aggregated with the following formula:
[0048] in, Predecessor node The input taint status already recorded in the current system status table. Indicates from node To the node The evaluation results of the transfer function, For logical AND operator, It is the set of predecessor nodes.
[0049] Next, state aggregation and change detection are performed on the new taint state and the current taint state table to obtain an updated taint state table. That is, the new taint state calculated in the previous step is compared with the old taint state recorded for that node in the current taint state table. If the new state has changed compared to the old state (e.g., from "untainted" to "tainted", or the taint label set has been updated), the node's state is considered to have changed. Once a change is detected, the state corresponding to that node in the taint state table is first updated to the new taint state. Then, all successor nodes of that node (i.e., all nodes in the enhanced data dependency graph that depend on the calculation result of the current node) are added to the pending work list. This is because a change in the current node's state may affect the state of its successor nodes, requiring recalculation. This process is repeated until the pending work list is empty, indicating that the taint state no longer changes and the system has reached a stable state. At this point, the final taint state table represents the stable taint information for each node in the program when the analysis is complete.
[0050] In summary, the static taint analysis method for binary code according to the embodiments of this application is explained. It introduces an on-demand micro-symbolic execution mechanism on top of basic data flow analysis through binary lifting and control flow graph construction. Specifically, for memory ambiguity nodes in the data dependency graph, it achieves refined alias resolution through reverse instruction slicing and constraint solving, thereby generating an enhanced data dependency graph. Based on this, path-sensitive taint propagation iterations are performed to generate the final taint state table. This approach not only effectively identifies complex dynamic memory addressing and avoids taint chain breaks and false alarm explosions caused by ignoring ambiguity or excessive approximation, but also significantly optimizes the resource allocation of the analysis engine.
[0051] Furthermore, a static taint analysis system for binary code is also provided.
[0052] Figure 3 This is a block diagram of a static taint analysis system for binary code according to an embodiment of this application. Figure 3As shown, the static taint analysis system 300 for binary code according to an embodiment of this application includes: a target binary file acquisition module 310, used to acquire the target binary file to be analyzed; a binary code lifting and control flow graph construction module 320, used to perform binary code lifting and control flow graph construction on the target binary file to be analyzed to obtain intermediate language code and control flow graph; an intra-function data dependency graph construction and taint source marking module 330, used to perform intra-function data dependency graph construction and taint source marking on the intermediate language code and control flow graph based on taint rules to obtain a data dependency graph and a work list to be processed; a memory alias resolution module 340, used to perform memory alias resolution based on on-demand microsymbol execution on the data dependency graph, the work list to be processed, and the control flow graph to obtain an enhanced data dependency graph; and a taint propagation iteration module 350, used to perform path-sensitive taint propagation iteration on the work list to be processed and the enhanced data dependency graph to obtain a taint state table.
[0053] As described above, the binary-code-oriented static taint analysis system 300 according to embodiments of this application can be implemented in various wireless terminals, such as servers with binary-code-oriented static taint analysis algorithms. In one possible implementation, the binary-code-oriented static taint analysis system 300 according to embodiments of this application can be integrated into the wireless terminal as a software module and / or a hardware module. For example, the binary-code-oriented static taint analysis system 300 can be a software module in the operating system of the wireless terminal, or it can be an application developed for the wireless terminal; of course, the binary-code-oriented static taint analysis system 300 can also be one of many hardware modules of the wireless terminal.
[0054] Alternatively, in another example, the binary-oriented static taint analysis system 300 and the wireless terminal can also be separate devices, and the binary-oriented static taint analysis system 300 can be connected to the wireless terminal via wired and / or wireless networks, and transmit interactive information in accordance with an agreed data format.
[0055] The various embodiments of this disclosure have been described above. These descriptions are exemplary and not exhaustive, nor are they limited to the disclosed embodiments. Many modifications and variations will be apparent to those skilled in the art without departing from the scope and spirit of the described embodiments. The terminology used herein is chosen to best explain the principles, practical application, or improvement of the technology in the market, or to enable others skilled in the art to understand the embodiments disclosed herein.
Claims
1. A static taint analysis method for binary code, characterized in that, include: Obtain the target binary file to be analyzed; The target binary file to be analyzed is subjected to binary code lifting and control flow graph construction to obtain intermediate language code and control flow graph; Based on taint rules, we construct intra-function data dependency graphs and mark taint sources on intermediate language code and control flow graphs to obtain data dependency graphs and a list of pending work. An enhanced data dependency graph is obtained by performing memory alias resolution based on on-demand microsymbol execution on the data dependency graph, the list of pending work, and the control flow graph. Path-sensitive taint propagation iterations are performed on the work list to be processed and the enhanced data dependency graph to obtain a taint state table.
2. The static taint analysis method for binary code according to claim 1, characterized in that, The target binary file to be analyzed undergoes binary code lifting and control flow graph construction to obtain intermediate language code and control flow graph, including: The target binary file to be analyzed is subjected to binary disassembly and parsing to obtain the assembly instruction sequence; Intermediate language enhancement and SSA normalization are performed on the assembly instruction sequence to obtain intermediate language code; The intermediate language code is divided into basic blocks and a control flow graph is constructed to obtain the control flow graph.
3. The static taint analysis method for binary code according to claim 1, characterized in that, Based on taint rules, an intra-function data dependency graph is constructed and taint sources are marked on the intermediate language code and control flow graph to obtain a data dependency graph and a list of pending works, including: Perform instruction traversal and definition of the control flow graph - use chain analysis to obtain the definition - use linked lists; Based on intermediate language code and definitions - using linked lists to build a data dependency graph; Classify and ambiguity-label the memory operation nodes of the data dependency graph to obtain a labeled data dependency graph; Based on taint rules, taint source matching is performed on the labeled data dependency graph to obtain a list of pending jobs.
4. The static taint analysis method for binary code according to claim 3, characterized in that, The data dependency graph is classified and ambiguously labeled by classifying the memory operation nodes to obtain a labeled data dependency graph, including: Extract the memory operation count for each node from the data dependency graph; The memory address expressions of the node's memory operands are destructured to obtain structured address expressions; Relational affine fraction mapping is performed on structured address expressions to obtain relational affine fractions; Based on relational affine fractions, ternary classification and enhanced labeling based on fractional thresholds are performed on structured address expressions to obtain memory node labels.
5. The static taint analysis method for binary code according to claim 1, characterized in that, An enhanced data dependency graph is obtained by performing memory alias resolution based on on-demand micro-symbol execution on the data dependency graph, the list of pending work items, and the control flow graph, including: Based on the data dependency graph, the list of tasks to be processed is subjected to ambiguous node propagation detection and micro-execution triggering to obtain the target ambiguous node; Based on the control flow graph, reverse instruction slice extraction is performed on target ambiguous nodes to obtain instruction slices; Constraint generation and SMT solution are performed on instruction slices to obtain a set of possible addresses; An enhanced data dependency graph is obtained by mapping pseudo-variables to the set of possible addresses based on the data dependency graph.
6. The static taint analysis method for binary code according to claim 1, characterized in that, Path-sensitive taint propagation iterations are performed on the work list to be processed and the enhanced data dependency graph to obtain a taint state table, including: The process involves selecting propagation nodes and predecessor indices for the work list and the enhanced data dependency graph to obtain the current node and the set of predecessor nodes. Based on the current taint state table, perform taint state calculation based on the transfer function on the current node and the set of predecessor nodes to obtain the new taint state. The new taint status and the current taint status table are aggregated and change detected to obtain an updated taint status table.
7. The static taint analysis method for binary code according to claim 1, characterized in that, Based on the current taint state table, perform taint state calculations on the current node and the set of predecessor nodes using a transfer function to obtain a new taint state, including: Based on the current taint state table, a transfer function evaluation based on instruction semantics is performed on the current node and the set of predecessor nodes to obtain the path taint result set. The path taint result set is aggregated with taint states to obtain new taint states.
8. The static taint analysis method for binary code according to claim 7, characterized in that, Aggregating taint states in the path taint result set to obtain new taint states includes: aggregating taint states in the path taint result set using the following formula: ; in, Predecessor node The input taint status already recorded in the current system status table. Indicates from node To the node The evaluation results of the transfer function, For logical AND operator, It is the set of predecessor nodes.
9. A static taint analysis system for binary code, characterized in that, include: The target binary file acquisition module is used to acquire the target binary file to be analyzed. The binary code lifting and control flow graph construction module is used to lift and construct the control flow graph of the target binary file to be analyzed in order to obtain intermediate language code and control flow graph. The Intra-Function Data Dependency Graph Construction and Tag Marking module is used to construct and tag intra-function data dependency graphs and taint sources based on taint rules to obtain data dependency graphs and a list of pending work items from intermediate language code and control flow graphs. The memory alias resolution module is used to perform memory alias resolution on data dependency graphs, pending work lists, and control flow graphs based on on-demand micro-symbol execution to obtain enhanced data dependency graphs; The taint propagation iteration module is used to perform path-sensitive taint propagation iteration on the work list to be processed and the enhanced data dependency graph to obtain the taint state table.