A method of processing software code and an electronic device

By constructing a control flow graph and performing function splitting and aggregation, the control flow and calling relationships of the software code are changed, solving the problems of significant performance impact or insufficient countermeasure capabilities in existing technologies. This enables the protection of software security and intellectual property rights by resisting code comparison techniques without reducing performance.

CN114003868BActive Publication Date: 2026-01-23INST OF COMPUTING TECH CHINESE ACAD OF SCI
View PDF 2 Cites 0 Cited by

Patent Information

Application Number
CN202111300044.2
Authority / Receiving Office
CN · China
Patent Type
Patents(China)
Current Assignee / Owner
Filing Date
2021-11-04
Publication Date
2026-01-23
Estimated Expiration
2041-11-04

AI Technical Summary

Technical Problem

Existing code comparison techniques, such as code encryption and obfuscation, suffer from significant performance impact or insufficient countermeasure capabilities, making it difficult to effectively protect software security and intellectual property.

Method used

By constructing a control flow graph of the software code, we can perform function splitting and aggregation to change the structure of the control flow graph and function call graph. Splitting breaks a function into multiple functions, and aggregation combines multiple functions into one function, thus reconstructing data dependencies to change the call relationships.

Benefits of technology

While ensuring program performance, it effectively combats code comparison techniques based on control flow graphs and function call graphs, increases the difficulty of analysis, and protects the intellectual property rights of software code.

✦ Generated by Eureka AI based on patent content.

Smart Images

  • Figure CN114003868B_ABST
    Figure CN114003868B_ABST
Patent Text Reader

Abstract

Embodiments of the present application provide a method for processing software code and an electronic device, the method comprising: obtaining software code to be processed, and constructing a control flow graph of the software code; and performing splitting processing and / or aggregation processing on selected functions in the software code according to the control flow graph and a preset processing logic to change an original structure of the control flow graph, wherein the splitting processing is to split one function into multiple functions, and to change a control flow relationship within a function into a function-to-function calling relationship, and the aggregation processing is to aggregate multiple functions into one function. Thus, the technical solution can not increase a large number of irrelevant instructions to seriously affect program performance like existing code obfuscation techniques, but can effectively resist code comparison techniques based on control flow graph and / or function call graph analysis by changing the control flow graph and the calling relationship in the original software code (equivalent to changing the function call graph) while guaranteeing program performance.
Need to check novelty before this filing date? Find Prior Art

Description

TECHNICAL FIELD

[0001] The present application relates to the field of software security, in particular to the field of anti-code comparison technology and anti-reverse analysis, and more particularly to a method for processing software code and an electronic device. BACKGROUND

[0002] With the rapid development of computer technology, software has been integrated into all aspects of people's lives. While software brings convenience to people's lives, it also poses a security risk. After releasing software, different users have different concerns. Among them, ordinary users often only focus on its function and performance, while malicious users (malicious attackers) threaten computer security and user privacy by exploiting software vulnerabilities. Once exploited maliciously, it will cause huge economic losses. In addition, the core algorithm and code logic of commercial software, as a kind of intellectual property, are often analyzed by reverse analysis personnel, and even illegally reused. Therefore, the importance of software security and intellectual property protection is self-evident.

[0003] When the source code of the software cannot be directly obtained, it is often necessary to understand the function and behavior of the software through reverse engineering. Reverse engineering is an important means for reverse analysis personnel to find software vulnerabilities and analyze core algorithms, and is a lengthy and time-consuming process. The success or failure of reverse analysis depends heavily on the experience and expertise of the reverse analysis personnel, and as the size of the software being reversed grows, the difficulty of reverse analysis also increases.

[0004] Code comparison technology can quickly find similarities or differences in disassembled code. Security researchers and engineers can use code comparison technology to analyze vulnerability repair code in patch programs, or analyze multiple versions of executable programs and reuse the analysis results to prevent repeated analysis of the same or similar executable files. However, similarly, it also provides a shortcut for reverse engineers to perform reverse engineering. For example, given a binary file and a repository containing analyzed and annotated code, reverse engineers can speed up the analysis process by applying code reuse detection to the binary file to identify similar or similar code in the repository, and then only focus on new functions or components of the binary file.

[0005] Existing code comparison technology can be divided into two categories. One is based on function-based information, such as text comparison, morpheme comparison, metric comparison, abstract syntax tree, call graph and control flow graph, execution sequence, etc. Among them, Google Bindiff, a disassembly tool developed by Google, is a widely used binary comparison software based on graph analysis. The other is to apply machine learning methods to code comparison technology, such as converting disassembled code sequences into word vectors and using natural language processing techniques to analyze code similarity.

[0006] In order to resist the code comparison technology, protect the software security and software intellectual property, the existing code comparison countermeasures mainly include two categories. One is code encryption technology, also known as code shell technology. It encrypts the code and data in the program to resist analysis and comparison tools. Specifically, the code encryption technology encrypts the code and data of the executable file and inserts the corresponding decryption logic. The decryption logic is executed first to remove the encryption of the code and data after the program is loaded. Common code shell tools such as UPX shell tool encrypt and compress the executable file and provide a de-shelled program to decompress and decrypt at runtime. This shell method has many deficiencies when resisting code comparison technology based on graph analysis. First, it is an independent tool. Users need to process the published executable file with the UPX shell tool to obtain the protected file, which undoubtedly reduces the user experience. Secondly, the de-shelling methods for various shell technologies are very mature today. For example, the IDA Pro disassembler provides various plugins for de-shelling of different shell technologies. Even if de-shelling fails, the code will be decrypted after being loaded into the memory. If the entire memory image is dumped at this time using a memory dump tool, the code is still in plaintext form, and code comparison tools can still be used for analysis.

[0007] The other common technology is code obfuscation technology. For example, the O-LLVM open source tool is implemented based on the LLVM framework and can obscure the code of the target program through different obfuscation methods to increase the difficulty of reverse analysis. The three different obfuscation methods of O-LLVM are: instruction replacement, control flow forgery, and control flow flattening. Instruction replacement replaces one instruction with one or more instructions with the same effect. The goal of this obfuscation technology is to replace simple instructions (such as addition, subtraction, or Boolean operators) with functionally equivalent but more complex instruction sequences. Control flow forgery complicates the control flow graph without changing the code execution logic. This method ensures the execution of true branches by adding opaque predicates and conditional jump instructions and randomly selects and fills garbage instructions on false branches. Control flow flattening moves all basic blocks within the code to the inside of a switch statement, converting the original jump into a data-driven jump. O-LLVM can resist analysis of control flow graphs and instruction sequences, but it has the disadvantage of introducing a large number of redundant instructions, resulting in a huge running overhead of the generated executable file, nearly 25 times the overhead. Moreover, O-LLVM does not change the function call relationship, so its ability to resist function call graph analysis is basically zero.

[0008] As can be seen, the existing code obfuscation technology has a large impact on program performance and is essentially difficult to resist existing analysis technology. SUMMARY

[0009] Therefore, the purpose of the present application is to overcome the defects of the prior art, and provide a method for processing software code and an electronic device.

[0010] The purpose of the present application is achieved by the following technical solutions:

[0011] According to a first aspect of the present application, a method for processing software code is provided, comprising: obtaining software code to be processed, and constructing a control flow graph of the software code; and performing splitting processing and / or aggregation processing on selected functions in the software code according to the control flow graph and a preset processing logic to change the original structure of the control flow graph, wherein the splitting processing is to split one function into multiple functions, and to change the control flow relationship within the function into a calling relationship between functions, and the aggregation processing is to aggregate multiple functions into one function. It should be understood that the selected specific functions in the splitting processing and the aggregation processing are not required to be completely consistent.

[0012] In some embodiments of the present application, the splitting processing is performed first, and then the aggregation processing is performed on the corresponding functions in the software code. It should be understood that the objects involved in the corresponding functions after the aggregation processing are substantially different from the objects involved in the corresponding functions before the splitting processing due to the splitting processing.

[0013] In some embodiments of the present application, the splitting processing comprises: splitting one original function into multiple functions, wherein one function retains the original function name, and the other functions are respectively assigned unique function names; and changing the control flow relationship before splitting into a calling relationship between functions based on the retained original function name and the unique function names obtained by the other functions.

[0014] In some embodiments of the present application, the splitting processing comprises: adding a Caller function in the split functions for temporary variables and / or global variables that are not defined in the split other functions, so as to pass the required temporary variables and / or global variables from the function with the retained original function name corresponding to the current split other function through the Caller function when executing; and redefining the scalar in the split other functions according to the value recorded in the corresponding original function.

[0015] In some embodiments of the present application, the splitting processing comprises: obtaining a user-specified splitting granularity when splitting, so as to control the splitting granularity of the corresponding subtree, loop, branch, basic block, instruction or combination thereof.

[0016] In some embodiments of the present application, the splitting processing comprises: randomly rearranging the positions of the split functions in the software code.

[0017] In some embodiments of the present application, the aggregation processing comprises: collecting aggregation reference information in the current software code, which comprises the calling relationship between functions, whether the functions are related to recursion; and performing aggregation processing on the functions in the current software code according to the aggregation reference information, while ignoring the functions related to recursion.

[0018] In some embodiments of the present application, the aggregation reference information further comprises whether the functions are related to loops, and the aggregation processing comprises: analyzing the hotness of each function according to a hot code analysis technique, and performing aggregation processing on the functions related to loops with hotness lower than a first threshold and the functions not related to loops with hotness lower than a second threshold, wherein the first threshold is less than or equal to the second threshold.

[0019] In some embodiments of the present application, the aggregation processing comprises: aggregating at least two functions into one aggregated function, assigning a unique function name to the aggregated function, and assigning a unique branch label within the aggregated function to each of the at least two functions before aggregation; and modifying the call to the function before aggregation in the calling function which needs to directly call a branch in the aggregated function into a call to the aggregated function and the branch.

[0020] In some embodiments of the present application, the aggregation processing comprises: aggregating at least two functions into one aggregated function, assigning a unique function name to the aggregated function, and assigning a unique branch label within the aggregated function to each of the at least two functions before aggregation; performing byte alignment processing on all functions to make part of the bits in the function pointer idle; inserting a predetermined assignment function in the caller which needs to indirectly call a function to add the calling control information into the function pointer of the caller, wherein the calling control information comprises an indication of whether the called function is an aggregated function and a branch label within the aggregated function; and inserting parsing code for parsing the calling control information at all indirect calling points, wherein when the aggregated function needs to be indirectly called is parsed, the required parameters and the branch label recorded in the pointer are passed to the called aggregated function through the parsing code.

[0021] According to a second aspect of the present application, there is provided an electronic device comprising: one or more processors; and a memory, wherein the memory is configured to store executable instructions; and the one or more processors are configured to implement the steps of the method of the first aspect by executing the executable instructions.

[0022] Compared with the prior art, the present application has the following advantages:

[0023] The application provides a method for processing software code, which comprises the following steps: obtaining software code to be processed; constructing a control flow graph of the software code; and performing splitting processing and / or aggregation processing on selected functions in the software code according to the control flow graph and preset processing logic to change the original structure of the control flow graph, wherein the splitting processing is to split one function into multiple functions and change the control flow relationship in the function into inter-function calling relationship, and the aggregation processing is to aggregate multiple functions into one function. Thus, the technical scheme can not increase a large number of irrelevant instructions to seriously affect program performance like the existing code obfuscation technology, but can effectively resist code comparison technology based on control flow graph and / or function call graph analysis by changing the control flow graph and calling relationship in the original software code (equivalent to changing the function call graph) while guaranteeing program performance. BRIEF DESCRIPTION OF DRAWINGS

[0024] The embodiments of the application will be further described below with reference to the accompanying drawings, in which:

[0025] Figure 1 A flowchart of the method for processing software code according to the embodiments of the application;

[0026] Figure 2 Principle diagrams of the method for processing software code according to the embodiments of the application before and after splitting processing;

[0027] Figure 3 Principle diagrams of the method for processing software code according to the embodiments of the application before and after aggregation processing;

[0028] Figure 4 A diagram of indirect calling of the method for processing software code according to the embodiments of the application;

[0029] Figure 5 A diagram of the effect of inserting non-transparent predicates of the method for processing software code according to the embodiments of the application;

[0030] Figure 6 A diagram of the effect of combining two optional deep obfuscation modes of the method for processing software code according to the embodiments of the application;

[0031] Figure 7 A diagram of the system for processing software code according to the embodiments of the application implementing splitting processing;

[0032] Figure 8 A diagram of the system for processing software code according to the embodiments of the application implementing aggregation processing;

[0033] Figure 9 A diagram of the system for processing software code according to the embodiments of the application implementing splitting processing first and then aggregation processing DETAILED DESCRIPTION

[0034] For the purpose of the present application, the technical solutions and advantages are more clear and explicit, the following will be further described in detail by specific embodiments in combination with the drawings. It should be understood that the specific embodiments described herein are only used to explain the present application, and are not used to limit the present application.

[0035] As mentioned in the background section, currently the main countermeasures against code comparison technology are code encryption technology and code obfuscation technology. Among them, code encryption technology is easy to be cracked because there are various mature decryption means and / or tools at present. Code obfuscation technology realizes obfuscation through instruction replacement, control flow forgery and control flow flattening, which will introduce a large number of redundant instructions, although it can resist the analysis of control flow graph and instruction sequence, but at the same time it also makes the running overhead of the generated executable file huge, and does not change the calling relationship of the function, so its countermeasure ability to function call graph analysis is basically zero. Therefore, referring to Figure 1 , the present application provides a method for processing software code, which comprises the following steps: obtaining software code to be processed, constructing a control flow graph of the software code; according to the control flow graph and a preset processing logic, selected functions in the software code are subjected to splitting processing and / or aggregation processing to change the original structure of the control flow graph, wherein the splitting processing is to split one function into multiple functions, and to change the control flow relationship within the function into the calling relationship between functions, and the aggregation processing is to aggregate multiple functions into one function. Thus, this technical solution can not increase a large number of irrelevant instructions as the existing code obfuscation technology does to seriously affect the program performance, but due to the change of the control flow graph and the calling relationship in the original software code (equivalent to the change of the function call graph), it can effectively countermeasure the code comparison technology based on the analysis of the control flow graph and / or the function call graph while guaranteeing the program performance.

[0036] Before specifically introducing the embodiments of the present application, some terms used therein are explained as follows:

[0037] Basic block refers to a sequence of instructions executed in sequence. Among them, the control flow can only enter at the first statement of the basic block and stay at the last statement, without stopping or branching.

[0038] Control flow graph (CFG), also called control flow chart, represents the possible flow direction of all basic blocks in the software code (program) or process. Control flow graph can reflect the real-time execution process of a program or process. Control flow graph is an abstract representation of a program or process, which is an abstract data structure used in the compiler, maintained internally by the compiler, and represents all paths that will be traversed during the execution of a program or process.

[0039] Intra-function control flow refers to the logical order of instruction execution within a function in software code.

[0040] Call graph (CG) refers to a directed graph representing the calling relationship between functions in software code.

[0041] Loop refers to a loop structure. The loop structure is a logical structure set in software code due to the need to repeatedly execute a certain function. Commonly, there are loops according to the number of times and loops according to conditions.

[0042] Branch refers to a branch structure.

[0043] Dominated subtree refers to a subtree of a domination tree. For example, a subset extracted from a domination tree corresponding to a function is a dominated subtree of the domination tree. The domination tree refers to a tree formed by basic blocks and the domination relationship between the basic blocks.

[0044] The splitting processing is to split one function into multiple functions, and to convert the intra-function control flow relationship into the inter-function calling relationship. In other words, the splitting processing is to split one function into multiple functions, and to convert the intra-function control flow relationship into the inter-function calling relationship.

[0045] The aggregation processing is to aggregate multiple functions into one function, and to convert the inter-function calling relationship into the intra-function control flow relationship.

[0046] The applicant found in the research process of code obfuscation that the existing code obfuscation technology has a great impact on the performance of the program, and is essentially difficult to resist the existing analysis technology, which is not conducive to protecting the intellectual property rights of the program publisher. Therefore, the applicant conceives a method for processing software code, which splits one function in the software code into multiple functions through splitting processing, and then aggregates the corresponding functions through aggregation processing after the splitting processing, so as to change the structure of the control flow graph and the structure of the function call graph, without excessively reducing the performance of the program, but better resisting the existing analysis technology. The program publisher can process the software source code (i.e. the software code to be processed) after each change, and then publish the corresponding program (processed software code, machine code) by using the method of the present application. Therefore, the control flow graph and the function call graph of the program published each time are obfuscated relative to the source code, which increases the analysis difficulty of the analyst, so as to better protect the intellectual property rights of the program publisher. In addition, the implementer can also only perform the splitting processing on the software code to be processed and publish the program, or only perform the aggregation processing and publish the program, so as to change the intra-function control flow and the inter-function calling graph, which also has a certain obfuscation strength.

[0047] The following will be described in turn for the corresponding technical embodiments of the splitting processing, the aggregation processing and the combination of the two.

[0048] According to one embodiment of the present application, the present application can achieve the purpose of confusion by splitting processing of some functions in the software code. Preferably, the present application provides a method for processing software code, comprising: obtaining the software code to be processed, constructing a control flow graph of the software code; according to the control flow graph and a preset processing logic, splitting processing is performed on selected functions in the software code to change the original structure of the control flow graph, wherein the splitting processing is to split one function into multiple functions, and to change the control flow relationship within the function into the function-to-function calling relationship. The splitting processing includes adding calling relationship between the multiple functions split out from one function or the multiple functions split from one function to rebuild data dependency, so as to maintain the software function unchanged. Wherein, constructing the control flow graph of the software code comprises: performing lexical analysis and syntax analysis on the software code to be processed, and constructing an abstract syntax tree; according to the node type and connection relationship in the abstract syntax tree, constructing the control flow graph of the software code. The technical scheme of this embodiment can at least achieve the following beneficial technical effects: the core idea of function splitting is to split one function into multiple functions, and to change the control flow relationship within the function into the function-to-function calling relationship, which changes the original control flow graph and blurs the calling relationship between processes, thereby effectively resisting the code comparison technology based on the control flow graph and / or the function call graph analysis, and protecting the intellectual property rights of the software code owner.

[0049] According to one embodiment of the present application, for the splitting granularity in the splitting processing, the splitting granularity can be set according to the self-defined processing logic, so as to selectively split the corresponding functions according to different needs. Preferably, the splitting processing includes: when splitting, obtaining the splitting granularity specified by the user, so as to split the granularity corresponding to the sub-tree, the loop, the branch, the basic block, the instruction or the combination thereof. For example, the structure region corresponding to the branch, the loop, the basic block or the combination thereof in the control flow graph is split out. For another example, according to the control flow graph, multiple sub-dominant trees are randomly divided from one dominant tree, and the code segment (structure region) related to the extracted sub-dominant tree is split out. If it is a combination of several granularities, the order of the several splitting granularities existing in the combination can be self-defined, and the splitting of the corresponding granularities is performed in the specified order. If the order is not specified, the splitting order of the corresponding granularities is randomly allocated. The technical scheme of this embodiment can at least achieve the following beneficial technical effects: the cross-granularity splitting technology proposed in the present application can effectively resist the code comparison technology, can effectively resist the code comparison technology, and can achieve the purpose of considering performance, the performance overhead of the normal application program can be ignored, and has the advantages of low confusion cost and flexible implementation.

[0050] According to one embodiment of the present application, when performing the splitting processing, it is not necessary to select all the functions to be processed. The proportion of the functions to be processed can be set according to the self-defined processing logic, so as to avoid that too many functions are split to excessively affect the program performance. Preferably, the splitting processing comprises: when performing the splitting processing, obtaining the function splitting proportion specified by the user, multiplying the function splitting proportion by the total number of the functions currently contained in the software code to obtain the splitting number, and using the splitting number to limit the number of the functions to be processed. For example, a number of functions can be randomly selected as the functions to be processed according to the splitting number, so as to split the selected functions.

[0051] According to one embodiment of the present application, for the functions selected to be processed (equivalent to pre-selection), it is not necessary to actually process all the selected functions. Some structures in the selected functions have different execution frequencies, i.e., some structures can be frequently used and have high frequencies, while some structures can be less frequently used. If the splitting is not differentiated, the performance can be affected. Therefore, preferably, the splitting processing comprises: when performing the splitting processing, analyzing the frequencies of the code segments of the corresponding granularity in the functions to be processed, and splitting the functions containing the code segments with the frequencies lower than the splitting frequency threshold. In this way, the program performance can be further guaranteed. The frequency can be defined by the implementer according to the specific situation. For example, in a simplified definition, it is assumed that the frequencies of all the code segments of the corresponding granularity are represented by the frequencies of the basic blocks at the entrances of the code segments, i.e., the frequency of a dominator tree is represented by the frequency of the basic block at the entrance, and the frequencies of the code segments corresponding to the branches and loops are the same.

[0052] According to one embodiment of the present application, the splitting processing comprises: when performing the splitting processing, obtaining the splitting granularity, the function splitting proportion, the splitting frequency threshold or the combination thereof specified by the user, and selecting the functions to be split according to the splitting granularity, the function splitting proportion, the splitting frequency threshold or the combination thereof specified by the user. The splitting processing comprises: for different splitting granularities, the corresponding function splitting proportion and / or the splitting frequency threshold can be independently set. Therefore, during the splitting process, the splitting scheme can be adjusted according to the actual experience or requirement, so as to achieve better program performance and better meet the obfuscation requirements of different users.

[0053] According to one embodiment of the present application, in the splitting process, other structure regions (code fragments) split from one original function (for generating other functions, i.e. new functions) need to be respectively assigned with unique function names. After splitting, the function corresponding to the header of the original function retains the original function name. In order to change the structure of the control flow graph and the function call graph, based on the retained original function name and the unique function names obtained by the other functions, the data dependency is reconstructed, and the function of the software code is kept unchanged. The reconstruction of the data dependency includes changing the control flow relationship before splitting into the calling relationship between functions.

[0054] An illustrative function and its split function example are given below. The function includes the operations of allocating local variables, parameter judgment, opening a file, loop calculation, closing a file, etc. After splitting, it can be seen that new function names are added to the new other functions, and the control flow relationship is changed into the calling relationship between functions:

[0055] Suppose the original function before splitting is:

[0056]

[0057]

[0058] Another example can be seen in Figure 2 , which shows a function splitting effect diagram of a dominating sub-tree level. Suppose that three dominating sub-trees in the original function Bar can be split, then new functions Bar_2 and Bar_3 are split out, and the control flow relationship in the function is changed into the calling relationship between functions.

[0059] According to one embodiment of the present application, in the splitting process, in order to ensure the correctness of program execution, after splitting the function, the reconstruction of the data dependency also includes the correction and reconstruction of the affected variables and constants. For example, due to the fact that part of the code in the original function is extracted to form a new function, the life cycle of some registers and stack variables in the original function will change, and therefore some variables need to be passed and redefined. The temporary variables and / or global variables not defined in the split function need to be passed from the function with the retained original function name corresponding to the current split function by the Caller function; some scalars (constants, etc.) in the original function need to be redefined in the split function.

[0060] According to one embodiment of the present application, during the splitting process, the split functions can be added with prologue and epilogue instructions uniformly by the splitting logic. However, since the split functions are essentially code segments extracted from the original function, in order to reduce the impact of the extracted code segments on the performance of the program, the prologue and epilogue instructions of the split functions can be removed to reduce the number of new instructions introduced by the function splitting. Thus, the performance of the processed software code is guaranteed.

[0061] According to one embodiment of the present application, the positions of the newly generated other functions in the code layout are still adjacent to the function with the original function name. In order to further increase the degree of confusion, after the splitting process, the positions of the functions in the software code can be randomly rearranged. Therefore, preferably, the method for processing the software code comprises: performing random rearrangement according to the definition of the function range for random rearrangement in the preset processing logic, and the function range for random rearrangement includes: only randomly rearranging the split other functions, randomly rearranging all the functions after the splitting process, or randomly rearranging all the current functions. Wherein, randomly rearranging all the functions after the splitting process means randomly rearranging the positions of the functions with the original function name and the split other functions in the software code. After the splitting process, the random rearrangement can further improve the confusion degree to confuse the analyzers; the function rearrangement process randomly rearranges the positions of all the sub-functions, and the code layout after the rearrangement has a great difference from the original code layout, so that the chaotic calling relationship can greatly increase the analysis difficulty of the analyzers.

[0062] According to one embodiment of the present application, the present application can also perform aggregation processing on the corresponding functions according to the control flow graph to change the control flow graph and the function call graph through the aggregation processing, and achieve the purpose of confusion. The method for processing the software code comprises: performing aggregation processing on selected functions in the software code according to the control flow graph and the preset processing logic to change the original structure of the control flow graph, and the aggregation processing is to aggregate multiple functions into one function and to change the inter-function calling relationship of the multiple functions into intra-function control flow relationship. During the aggregation processing, aggregation reference information is collected, and the collection of the aggregation reference information is mainly for the preparation of function aggregation, wherein all the calling relationships of the functions are collected, and a mapping table is created to record the callers and the called functions. In addition, some information is additionally recorded, including whether the calling statement is in a loop and whether the calling statement can produce recursion. When selecting the aggregation functions, two functions that produce recursion are not selected (i.e. functions that are not related to recursion are selected) to avoid new recursive calls to cause the performance of the program to decrease. During the aggregation processing, after the aggregation function is constructed, the code corresponding to the original functions aggregated into the aggregation function is deleted.

[0063] According to one embodiment of the present application, when performing the aggregation, the aggregation can not be performed on all the functions irrelevant to recursion. The proportion of the functions involved in the aggregation can be set according to the self-defined processing logic, so as to avoid that too many functions are aggregated to excessively affect the program performance. Preferably, the aggregation includes: when performing the aggregation, a user-specified function aggregation proportion is obtained, the function aggregation proportion is multiplied by the number of the functions irrelevant to recursion currently contained in the software code to obtain an aggregation number, and the aggregation number is used to limit the number of the functions involved in the aggregation. For example, a number of functions can be randomly selected from all the functions irrelevant to recursion according to the aggregation number as the functions involved in the aggregation, so that the aggregation is performed on the functions.

[0064] According to one embodiment of the present application, when performing the aggregation, the functions related to loop and the functions irrelevant to loop can also be processed based on the hotness. Preferably, the hotness of each function is analyzed according to the hot code analysis technology, and the aggregation is performed on the functions related to loop with the hotness lower than a first threshold and the functions irrelevant to loop with the hotness lower than a second threshold, wherein the first threshold is less than or equal to the second threshold. More preferably, the first threshold is less than the second threshold. In this way, the number of the functions related to loop involved in the aggregation can be reduced, so as to reduce the influence of too many functions related to loop on the program performance. For example, for the functions related to loop, the number of times of calling the functions and the execution frequency of the internal basic blocks are analyzed by using the hot code analysis technology, and the codes with the execution times (representing the hotness of the functions, which is the product of the number of times of calling the functions and the execution frequency of each basic block) lower than a certain threshold are selected into a set of functions to be aggregated, so that the influence of the overhead caused by the aggregation can be reduced. Similarly, for the functions irrelevant to loop, the functions with the hotness lower than a certain threshold can also be selected into the set of functions to be aggregated. Subsequently, a predetermined number of functions are randomly selected from the functions in the set of functions to be aggregated, the function bodies of the selected functions are copied into different branches of a newly created aggregated function, and a control parameter is used to determine the branch to which the function should flow when the function is called.

[0065] After the aggregate function is constructed, the call point of the original function before aggregation needs to be replaced by the call of the aggregate function. The call of the function is divided into two forms: direct call and indirect call. Direct call is to call the function explicitly through the function name, and the function name represents the function address. Calling the function name is equivalent to directly accessing the function with the function address. Indirect call is to implicitly call the function through the function pointer. The function pointer may experience multi-level propagation of assignment, operation and access. It can not only be intra-module propagation, but also inter-module propagation relationship, such as callback function. In other words, the indirect call point calls the function through the function pointer, and needs to know which function the function pointer points to, so as to replace it with the corresponding aggregate function. If the propagation path of the function pointer is short, such as the next instruction is indirect call after the previous instruction assigns the function pointer, it is easy to know which function is called through static analysis. However, if the propagation path of the function pointer is long and crosses functions or even modules, it is very difficult to analyze the pointer. Moreover, the static analysis overhead is very large, and it is not worth the cost to achieve aggregation in this way. It can be seen that the biggest difference between direct call and indirect call is that direct call can statically determine the called function, while indirect call often cannot know which function the current function pointer points to. Function aggregation needs to replace the called function with the aggregate function at the call point. The case of indirect call undoubtedly increases the difficulty of aggregation, because if there is no way to determine the target of indirect call, it is more impossible to find the aggregate function corresponding to the target. Due to the complexity of indirect call, the present application processes the direct call and the indirect call separately.

[0066] According to one embodiment of the present application, for the case that the call point is direct call, the call of the original function is directly replaced by the call of the aggregate function and the corresponding branch. The corresponding aggregate function and branch are found according to the function name of the called aggregate function and the branch label (which is equivalent to the function name of the called aggregate function and the branch label form the control parameter).

[0067] An illustrative aggregation process is shown in Figure 3 The function Foo and the function Bar are aggregated into the function Fusion,

[0068] According to one embodiment of the present application, for the case that the call point is indirect, the function pointer needs to be processed to ensure the feasibility of the indirect call and the program performance. As mentioned above, the difficulty of the indirect call problem is that the aggregate function to be replaced cannot be determined at the indirect call point. Therefore, the present application advances the time point of the replacement. Although the function pointer can be calculated and propagated over a long distance, there must be an initial assignment point for each function pointer. By resolving the function of the assignment point, the corresponding aggregate function is found and replaced. Subsequently, no matter how the function pointer is propagated, it still points to the aggregate function. However, similar to the direct call, the aggregate function needs control parameters to determine the control flow within the aggregate function. However, the control parameters cannot be directly replaced at the call point as in the direct call, because the call point cannot know which function it calls and cannot determine the value of the control parameters. Therefore, the information of the control parameters (i.e. call control information) is recorded in the function pointer, and then the call control information is resolved at the call point and passed to the call instruction.

[0069] According to one embodiment of the present application, the problem of the indirect call is solved by using a tag pointer (i.e. function pointer). For example, first, all the functions are processed to be 16-byte aligned, and then the lower 4 bits in the function pointer are idle, so that the lower 2 bits can be used to record the call control information. The 0th bit and the 1st bit of the function pointer are used to record the call control information. The 1st bit is called aggregate indication bit (or called Ctrl Sign, CS bit), which indicates whether the function at the address is processed by the aggregation. The 0th bit is called branch indication bit (or called Ctrl Bit, CB bit, used to record the branch tag), which indicates the branch (position) of the function in the corresponding aggregate function. It should be understood that this is only an example, and the number of bits occupied by the call control information can be increased, and more branch indication bits can be added to indicate the branches corresponding to more than two functions aggregated in an aggregate function.

[0070] As an example, a schematic process of the indirect call is shown in Figure 4 . In which, the combine_ptr() function (corresponding to the predetermined assignment function) is responsible for adding the call control information (or called tag information) into the function pointer, i.e. Figure 4 in the ctrl_tag of the function pointer. Figure 4 The 0, 1, 63 in the upper part of the function pointer in the upper right corner indicate the corresponding bit positions in the function pointer.

[0071] For example, when the program executes the bar function, the corresponding call control information is 11, and in the subsequent data flow propagation, the call control information assigned in the function pointer f is also propagated together. Subsequently, the resolution code is inserted at all indirect call points, which is used to extract the call control information, and the CS bit is checked by the extract_sign() function in the resolution code. If the CS bit is 1, it indicates that the function to be called (the called function) is processed by the aggregation, and the execution will continue Figure 4 The right branch of the flow chart (ctrl = extract_ctrl(f), val = extract_value(f), tmp = val(ctrl, c, d)), in which the CB bit (ctrl parameter) in the function pointer is extracted by the extract_ctrl() function, and the function pointer is extracted by the extract_value() function. Finally, the function pointer is called, and the CB bit (ctrl parameter) and the parameters required for calculation (here, c and d) are passed into the called function.

[0072] For example, when the program executes the bar function, the corresponding call control information is 00, and the extract_sign() function in the resolution code finds that the CS bit in the function pointer of the indirect call is 0, which indicates that the called function is not processed by the aggregation, and the execution will continue Figure 4 The left branch of the flow chart, i.e., the original call statement: / / origin call tmp = f(c, d).

[0073] According to an embodiment of the present application, in the function processed by the aggregation, further deep confusion can be performed. Preferably, the aggregation processing further includes adding a non-transparent predicate in the basic block inside the aggregation function to modify the unconditional jump instruction into a conditional branch instruction composed of the non-transparent predicate (here, it is equivalent to the basic block level deep confusion). For example, see Figure 5 In the above-mentioned aggregation processing, the function pointer f is replaced by the function pointer f aggregated by the aggregation processing, and the function pointer f aggregated by the aggregation processing is used to call the function. Figure 3On the basis of the above, some non-transparent predicates are added to increase the degree of confusion. The number or proportion of non-transparent predicates inserted in each aggregation function can be set by the user and added to the processing logic. In addition, another deeper confusion can also be performed, and preferably, the aggregation processing further includes: after finding the basic blocks that do not interfere with each other in function after internal instruction overlap in the aggregation function, the instructions in the found basic blocks are overlapped in sequence to form a new basic block (or harmless basic block, which is a deep confusion at the instruction level here). For example, for two basic blocks belonging to different original functions before aggregation, in the aggregated function, if they do not interfere with each other and do not destroy the running result of the program, the two basic blocks can be combined into one basic block. Similarly, the number or proportion of basic blocks in each aggregation function that are subjected to deep confusion at the instruction level can be set by the user and added to the processing logic. The above two deep confusion methods can be used in combination, for example, see Figure 6 , which shows the schematic effect after the combination of the two optional deep confusion methods.

[0074] The purpose of the present application is to solve the problems of poor confusion effect, excessive performance overhead, insufficient ability to resist machine learning methods, and other problems of existing code reuse detection countermeasures. In order to better achieve the confusion effect and protect the intellectual property rights of the program publisher, according to an embodiment of the present application, the present application can combine the splitting processing and the aggregation processing; for example, the splitting processing can be performed first, and then the aggregation processing is performed. The present application achieves double confusion of function call graph and control flow graph by dynamically splitting and aggregating functions. The splitting processing of the function splits one function into multiple functions, replaces the control flow relationship within the function with the calling relationship between functions, and achieves double confusion of function call graph and control flow graph. The aggregation processing of the function aggregates at least two functions (the user can set the number of functions before aggregation corresponding to an aggregation function) into one function, modifies the calling target of the calling point, and more completely destroys the existing calling relationship. These processes do not add a large number of useless instructions for confusion as in the prior art, thereby achieving better confusion effect while reducing the impact on program performance.

[0075] The following shows the schematic effect after the splitting processing and the aggregation processing of a short piece of software code to be processed.

[0076] The schematic software code to be processed is as follows:

[0077]

[0078]

[0079] After the splitting processing of the above software code to be processed, the following is obtained:

[0080]

[0081]

[0082] After the splitting processing, the aggregation processing is performed, and the following is obtained:

[0083]

[0084]

[0085] According to an embodiment of the present application, the method of the present application can be implemented at the compiling time, so as to complete the obfuscation processing based on the method of the present application in the process of converting the high-level language into the corresponding machine language.

[0086] According to an embodiment of the present application, the present application further provides a system for processing software code, comprising: a front-end module, configured to acquire the software code to be processed, and to construct a control flow graph of the software code; a splitting module, configured to selectively perform splitting processing on the corresponding functions in the software code according to the control flow graph and a preset processing logic, so as to change the original structure of the control flow graph, wherein the data dependency is reconstructed by increasing the calling relationship; and an aggregation module, configured to selectively perform aggregation processing on the corresponding functions in the software code according to the control flow graph and the preset processing logic, so as to change the original structure of the control flow graph, wherein the data dependency is reconstructed by adjusting the calling relationship.

[0087] According to an embodiment of the present application, the open-source LLVM (Low Level Virtual Machine) compiler framework can be used to implement the above-mentioned method and system. It should be understood that, although the implementation is based on the LLVM open-source compiler framework here, the technical logic therein can be adaptively transplanted to other compiler frameworks, such as GCC, TCC, ICC, LCC, and domestic compiler LOONGCC, etc.

[0088] LLVM compiler framework is a set of modular, reusable compiler and toolchain technologies. Traditional compilers such as GCC (GNU Compiler Collection) are usually divided into a front-end, an optimizer, and a back-end. The front-end is responsible for parsing the source code and checking syntax-level errors, and building an abstract syntax tree (AST). The optimizer is responsible for code optimization on the AST or other intermediate representations. The back-end is responsible for generating binary code for the corresponding platform. LLVM is also divided into these three stages, but unlike the traditional compiler coupling design, its front-end, terminal, and back-end are highly separated modules, and it provides a unified intermediate representation (LLVM Intermediate Representation, LLVM IR) for all languages and platforms. The optimizer only optimizes the IR, and the IR is represented as IR' after processing.

[0089] Most of the logic of LLVM is to handle compilation optimization and code generation, and these functions are composed of a Pass. Pass means "pass" (some places also call it pipeline), a Pass will traverse a pass of IR, process all functions in the module to generate new IR, and enter the next Pass. For example, the middle-end optimization will go through the loop unrolling, function in-situ, dead code elimination, and other Passes in turn. The back-end optimization and code generation will go through the instruction selection, register allocation and optimization, instruction emission, and other Passes in turn.

[0090] According to an example of the present application, if splitting processing is to be performed, and the user sets the processing logic to sequentially split the loop, split the basic block, and randomly rearrange; the splitting module will be implemented in the middle-end, see Figure 7 The splitting module is implemented by the Pass corresponding to the execution of loop splitting, basic block splitting, and random rearrangement.

[0091] According to an example of the present application, if aggregation processing is to be performed, see Figure 8 The aggregation module is implemented by the Pass corresponding to the collection of aggregation reference information and aggregation processing.

[0092] According to one example of the present application, a process of splitting and aggregating is implemented by using the LLVM compiler framework in the process of compiling the high-level C / C++ language into the low-level X86 ELF / PE language at the compiling time. First, a configuration file is passed in, which contains the source file of the software code and the predetermined processing logic. The LLVM compiler framework parses the source file of the software code, checks the syntax-level errors and constructs the control flow graph by using the C / C++ front end (i.e., the front-end module). Then, the processed software code, i.e., the obfuscated binary file, is obtained by sequentially passing through the middle-end optimizer and the X86 back end. The middle-end optimizer integrates the splitting module for performing the splitting process and the aggregation module for performing the aggregation process. In the LLVM compiler, if the hotness is to be determined based on the hot code analysis technique, the estimated frequency can be used as the hotness based on the BlockFrequencyInfo.cpp in the LLVM compiler.

[0093] It should be noted that although the above describes the steps in a specific order, it does not mean that the steps must be performed in the above specific order. In fact, some of the steps can be performed concurrently or even in a changed order, as long as the desired function can be achieved.

[0094] The present application can be a system, a method, and / or a computer program product. The computer program product can include a computer readable storage medium (or media) having computer readable program instructions thereon for causing a processor to carry out aspects of the present application.

[0095] The computer readable storage medium can be a tangible device that can retain and store instructions for use by an instruction execution device. The computer readable storage medium can be, for example, but is not limited to, an electronic storage device, a magnetic storage device, an optical storage device, an electromagnetic storage device, a semiconductor storage device, or any suitable combination of the foregoing. More specific examples (a non-exhaustive list) of the computer readable storage medium include the following: a portable computer diskette, a hard disk, a random access memory (RAM), a read-only memory (ROM), an erasable programmable read-only memory (EPROM or Flash memory), a static random access memory (SRAM), a portable compact disc read-only memory (CD-ROM), a digital versatile disk (DVD), a memory stick, a floppy disk, a mechanically encoded device such as punch-cards or punched tape, a magnetically encoded device such as magnetic strip cards, an optically encoded device such as a compact disc (CD) or DVD, and / or any suitable combination of the foregoing. A computer readable storage medium can be any tangible device or medium that can retain and store instructions for use by an instruction execution device.

[0096] Having described various embodiments of the application, it is to be understood that the above description is meant not to limit and not to encompass all of the possible embodiments covered by the claims. Many modifications and variations of this application can be apparent to those of ordinary skill in the art without departing from the spirit and scope of the described embodiments. It is intended that the scope of the application should only be limited by the appended claims.

Claims

1. A method for processing software code, characterized in that, include: Obtain the software code to be processed and construct the control flow graph of the software code; Based on the control flow graph and preset processing logic, selected functions in the software code are split and / or aggregated to change the original structure of the control flow graph. The splitting process involves splitting a function into multiple functions and transforming the control flow relationship within a function into a calling relationship between functions. The splitting process includes: splitting an original function into multiple functions, where one function retains the original function name and assigns unique function names to the other functions; and based on the retained original function name and the unique function names obtained by the other functions, changing the control flow relationship before splitting into a calling relationship between functions. The aggregation process involves combining multiple functions into a single function. This aggregation process includes: collecting aggregation reference information from the current software code, including call relationships between functions and whether functions are related to recursion; and performing aggregation processing on the functions in the current software code based on the aggregation reference information, ignoring functions related to recursion.

2. The method according to claim 1, characterized in that, The corresponding functions in the software code are first split and then aggregated.

3. The method according to claim 1 or 2, characterized in that, The splitting process also includes: For undefined temporary and / or global variables in the other split functions, add a Caller function to the split functions so that, during execution, the required temporary and / or global variables can be passed from the corresponding functions (which retain the original function names) of the currently split functions; and For the scalar values ​​in the other functions that are split off, redefine them based on the values ​​recorded in their corresponding original functions.

4. The method according to claim 1 or 2, characterized in that, The splitting process includes: obtaining the user-specified splitting granularity during splitting, and splitting at the granularity corresponding to the subtree, loop, branch, basic block, instruction, or combination thereof.

5. The method according to claim 1 or 2, characterized in that, The splitting process includes: randomly rearranging the positions of the split functions in the software code.

6. The method according to claim 1 or 2, characterized in that, The aggregation reference information also includes: whether the function is related to a loop; the aggregation process includes: Based on the hot code analysis technology, the popularity of each function is analyzed. Functions related to loops with popularity below the first threshold and functions unrelated to loops with popularity below the second threshold are aggregated. The first threshold is less than or equal to the second threshold.

7. The method according to claim 1 or 2, characterized in that, The polymerization process includes: Aggregate at least two functions into an aggregate function, assign a unique function name to the aggregate function, and assign a unique branch label to each of the at least two functions before aggregation within the aggregate function; Modify the function that needs to directly call a branch of the aggregate function to call the function before aggregation, and change it to call the aggregate function and its branches.

8. The method according to claim 1 or 2, characterized in that, The polymerization process includes: Aggregate at least two functions into an aggregate function, assign a unique function name to the aggregate function, and assign a unique branch label to each of the at least two functions before aggregation within the aggregate function; Perform byte alignment on all functions to leave some bits in the function pointers idle; A predefined assignment function is inserted into the caller that needs to indirectly call a function to add call control information to the caller's function pointer. The call control information includes an indication of whether the called function is an aggregate function and a branch label within the aggregate function. Parsing code is inserted at all indirect call points to parse the call control information. When an indirect call to an aggregate function is encountered, the parsing code passes the required parameters and the branch labels recorded in the pointer to the called aggregate function.

9. A computer-readable storage medium, characterized in that, It contains a computer program that can be executed by a processor to implement the steps of the method according to any one of claims 1 to 8.

10. An electronic device, characterized in that, include: One or more processors; as well as Memory, wherein the memory is used to store executable instructions; The one or more processors are configured to implement the steps of the method according to any one of claims 1 to 8 by executing the executable instructions.

Citation Information

Patent Citations

  • Software obfuscation device, software obfuscation method, and program

    JP2012234248A

  • Global control flow treatment of predicated code

    US5937195A