Method for preventing ROP (Return Oriented Programming) attack
By generating and adding PAC to the return address in pipeline mode, the high development cost and compatibility problems of preventing ROP attacks in the prior art are solved, effective protection of existing programs is achieved, and software security is improved.
Patent Information
- Application Number
- CN202511001263.9
- Authority / Receiving Office
- CN · China
- Patent Type
- Applications(China)
- Current Assignee / Owner
- Filing Date
- 2025-07-21
- Publication Date
- 2025-08-19
- Estimated Expiration
- 2045-07-21
AI Technical Summary
The existing methods to prevent return-oriented programming ROP attacks have high development costs, compatibility problems, and require extensive hardware and software updates, making it difficult to effectively implement in existing programs.
By identifying the target instructions in the function call in pipeline mode, generating and adding a pointer authentication code (PAC) to the return address, using the instruction bypass unit to obtain the return address, stack pointer and key, generating a return address carrying the PAC to prevent ROP attacks.
Without recompiling existing programs, the security of the software is improved, ROP attacks are prevented, and the protection capabilities of the system are enhanced.
Smart Images

Figure CN120509013A_ABST
Abstract
Description
Technical Field
[0001] The present application relates to the technical field of computer instruction processing, and in particular to a method for preventing return-oriented programming (ROP) attacks. Background Art
[0002] With the rapid development of computer technology, software security issues are becoming increasingly serious. In particular, malicious attacks against pointers, such as Return-Oriented Programming (ROP) attacks, pose a serious threat to system security.
[0003] Currently, ARM has introduced the Pointer Authentication Code (PAC) function in the ARMv8.3 version. This function takes advantage of the fact that the 64-bit architecture does not require the use of the full 64-bit address space. It embeds an authentication code in the unused bits to authenticate a pointer, and effectively prevents malicious attacks through the signature and verification mechanism.
[0004] However, the introduction of the PAC function faces many challenges. For example, existing software written in high-level programming languages needs to be recompiled to adapt to the new PAC instruction set, which not only increases development costs but also may cause compatibility issues. Secondly, for assembly language, developers need to manually add PAC-related instructions, a process that increases development difficulty and workload. Thirdly, only newer hardware implements the PAC function, and existing hardware that does not implement the PAC function cannot benefit from it. In addition, the full implementation of the PAC function requires close cooperation among many manufacturers. From hardware manufacturers to software developers, every link needs to be updated and adapted accordingly, which makes coordination difficult and limits the speed of advancement. Summary of the Invention
[0005] The present application provides a method for preventing return-oriented programming (ROP) attacks, which is used to prevent ROP attacks by generating a PAC and adding the PAC to a return address.
[0006] In a first aspect, an embodiment of the present application provides a method for preventing ROP attacks, the method comprising: when processing instructions in pipeline mode, if a first target instruction in a function call is identified, pausing the pipeline; the first target instruction is a first setting instruction that causes a stack pointer to point to a caller stack frame before and after execution; or, the first target instruction is a second setting instruction that causes a stack pointer to point to a callee stack frame before and after execution; the before and after execution are before and / or after execution; obtaining a return address, the stack pointer, and a key of the function call through an instruction bypass unit, and generating a PAC based on the return address, the context corresponding to the stack pointer, and the key; adding the PAC to a reserved bit of the return address to obtain a return address carrying the PAC; the return address carrying the PAC is used to prevent ROP attacks against the return address; after the instruction bypass unit completes execution, restoring the pipeline according to the target address indicated by the instruction bypass unit.
[0007] Using the above method, when the preset first target instruction is identified, the return address, the context corresponding to the stack pointer, and the key are obtained to generate a PAC. The PAC is then added to the reserved bits to obtain a return address carrying the PAC. Because this return address carries the PAC, it cannot be used normally. Therefore, only after the return address is stripped of the PAC and the signature is successfully verified can it be used as a valid address. In this way, by completely bypassing the instruction, existing programs can be protected by the PAC without recompiling them, curbing ROP attacks and improving software security.
[0008] In one possible implementation, obtaining the return address of a function call through an instruction bypass unit includes: reading the return address of the function call from the top of a stack or reading the return address of the function call from a return address register; after obtaining the return address carrying the PAC, further including: writing the return address carrying the PAC to the top of the stack or the return address register through the instruction bypass unit.
[0009] In one possible implementation, before restoring the pipeline according to the target address indicated by the instruction bypass unit, it also includes: executing the first target instruction through the instruction bypass unit; the target address is the address of the next instruction corresponding to the first target instruction, or the address of the jump target of the first target instruction.
[0010] In one possible implementation, restoring the pipeline according to the target address indicated by the instruction bypass unit includes: after restoring the pipeline, skipping instruction recognition and directly executing the first target instruction, and the target address indicated by the instruction bypass unit is the address of the first target instruction.
[0011] In one possible implementation, the instruction is identified as the first target instruction in the following manner, including: (1) if a stack that grows from top to bottom is used, then an instruction that satisfies either of the following two conditions is determined to be the first target instruction: (a) if the opcode in the instruction is an immediate addition opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is a negative value; (b) if the opcode in the instruction is an immediate subtraction opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is a positive value; (2) if a stack that grows from bottom to top is used, then any of the following two conditions is determined to be satisfied. A conditional instruction is a first target instruction: (a) the opcode in the instruction is an immediate addition opcode, the source register is a stack pointer register, the destination register is a stack pointer register, and the immediate value is a positive value; (b) the opcode in the instruction is an immediate subtraction opcode, the source register is a stack pointer register, the destination register is a stack pointer register, and the immediate value is a negative value; the stack that grows from top to bottom is a stack with a bottom at a high address and a top at a low address; the stack that grows from bottom to top is a stack with a bottom at a low address and a top at a high address; the high address is a memory address with a larger address value; and the low address is a memory address with a smaller address value.
[0012] In one possible implementation, the first setting instruction is an instruction in which the stack pointer points to the caller stack frame before execution and points to the callee stack frame after execution; obtaining the stack pointer through the instruction bypass unit includes: before the first setting instruction is executed, reading the stack pointer stored in the stack pointer register through the instruction bypass unit; the context corresponding to the stack pointer is the stack pointer.
[0013] In a possible implementation, the first setting instruction is a jump instruction for a function call; obtaining the stack pointer through an instruction bypass unit includes: reading the stack pointer stored in a stack pointer register through the instruction bypass unit, and the context corresponding to the stack pointer is the stack pointer.
[0014] In one possible implementation, the second setting instruction is an instruction in which the stack pointer points to the caller stack frame before execution and points to the callee stack frame after execution; obtaining the stack pointer through the instruction bypass unit includes: before the first setting instruction is executed, reading the stack pointer stored in the stack pointer register through the instruction bypass unit; the context corresponding to the stack pointer is the stack pointer calculated based on the size of the stack pointer and the stack frame, and is updated after the second setting instruction is executed.
[0015] In one possible implementation, the second setting instruction is an instruction for backing up the return address stored in the return address register to the stack; obtaining the stack pointer through the instruction bypass unit includes: reading the stack pointer stored in the stack pointer register through the instruction bypass unit, and the context corresponding to the stack pointer is the stack pointer.
[0016] In one possible implementation, an instruction is identified as a first target instruction in the following manner, including: (1) if a stack that grows from top to bottom is used, determining an instruction that satisfies the following conditions as the first target instruction: the opcode in the instruction is a memory storage opcode, the source register is a return address register, the memory base register is a stack pointer register, and the offset is a positive value; (2) if a stack that grows from bottom to top is used, determining an instruction that satisfies the following conditions as the first target instruction: the opcode in the instruction is a memory storage opcode, the source register is a return address register, the memory base register is a stack pointer register, and the offset is a negative value; The stack that grows from top to bottom is a stack with the bottom at a high address and the top at a low address; the stack that grows from bottom to top is a stack with the bottom at a low address and the top at a high address; the high address is a memory address with a larger address value; the low address is a memory address with a smaller address value.
[0017] In a second aspect, the present application provides a method for preventing return-oriented programming (ROP) attacks, the method comprising: when processing instructions in pipeline mode, if a second target instruction in a function call is identified, pausing the pipeline, the second target instruction being a third setting instruction that causes the stack pointer before and after execution to point to the caller's stack frame, or the second target instruction being a fourth setting instruction that causes the stack pointer before and after execution to point to the callee's stack frame; the before and after execution being before and / or after execution; obtaining a return address carrying a PAC, the stack pointer, and a key through an instruction bypass unit, and generating a PAC to be verified based on the return address stripped of the PAC, the context corresponding to the stack pointer, and the key; if the PAC is the same as the PAC to be verified, resuming the pipeline at the target address indicated by the instruction bypass unit; if the PAC is different from the PAC to be verified, triggering an exception, the exception indicating a ROP attack on the return address.
[0018] Using this method, when the preset second target instruction is identified, the return address, stack pointer, and key carrying the PAC are retrieved to generate a PAC to be verified. If the PAC to be verified matches the PAC, it can be determined that the return address carrying the PAC has not been attacked. This completely bypasses the instruction, allowing existing programs to be protected by PAC without recompiling, thus preventing ROP attacks and improving software security.
[0019] In one possible implementation, obtaining a return address carrying the PAC through an instruction bypass unit includes: reading the return address carrying the PAC from a stack top or a return address register; the method further includes: if the PAC is the same as the PAC to be verified, writing the return address stripped of the PAC to the stack top or the return address register.
[0020] In one possible implementation, before restoring the pipeline at the target address indicated by the instruction bypass unit, it also includes: executing the target instruction through the instruction bypass unit; the target address is the address of the next instruction corresponding to the second target instruction, or the address of the jump target corresponding to the second target instruction.
[0021] In one possible implementation, restoring the pipeline at the target address indicated by the instruction bypass unit includes: after restoring the pipeline, skipping instruction recognition and directly executing the second target instruction, and the target address indicated by the instruction bypass unit is the address of the second target instruction.
[0022] In one possible implementation, the instruction is identified as the second target instruction in the following manner, including: (1) if a stack that grows from top to bottom is used, then an instruction that satisfies either of the following two conditions is determined to be the second target instruction: (a) the opcode in the instruction is an immediate addition opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is a positive value; (b) the opcode in the instruction is an immediate subtraction opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is a negative value; (2) if a stack that grows from bottom to top is used, then an instruction that satisfies either of the following two conditions is determined to be the second target instruction. A conditional instruction is a first target instruction: (a) the opcode in the instruction is an immediate addition opcode, the source register is a stack pointer register, the destination register is a stack pointer register, and the immediate value is a negative value; (b) the opcode in the instruction is an immediate subtraction opcode, the source register is a stack pointer register, the destination register is a stack pointer register, and the immediate value is a positive value; the stack that grows from top to bottom is a stack with a bottom at a high address and a top at a low address; the stack that grows from bottom to top is a stack with a bottom at a low address and a top at a high address; the high address is a memory address with a larger address value; and the low address is a memory address with a smaller address value.
[0023] In one possible implementation, the third setting instruction is an instruction in which the stack pointer points to the callee stack frame before execution and points to the caller stack frame after execution; obtaining the stack pointer through the instruction bypass unit includes: before the third setting instruction is executed, reading the stack pointer stored in the stack pointer register through the instruction bypass unit; the context corresponding to the stack pointer is the stack pointer calculated based on the size of the stack pointer and the stack frame, and is updated after the execution of the third setting instruction.
[0024] In one possible implementation, the third setting instruction is a jump instruction for function return; obtaining the stack pointer through the instruction bypass unit includes: reading the stack pointer stored in the stack pointer register through the instruction bypass unit; the context corresponding to the stack pointer is the stack pointer.
[0025] In one possible implementation, the fourth setting instruction is an instruction in which the stack pointer points to the callee stack frame before execution and points to the caller stack frame after execution; obtaining the stack pointer through the instruction bypass unit includes: before the fourth setting instruction is executed, reading the stack pointer stored in the stack pointer register through the instruction bypass unit; the context corresponding to the stack pointer is the stack pointer.
[0026] In one possible implementation, the fourth setting instruction is an instruction for restoring the return address stored on the stack to the return address register; obtaining the stack pointer through the instruction bypass unit includes: before the third setting instruction is executed, reading the stack pointer stored in the stack pointer register through the instruction bypass unit; the context corresponding to the stack pointer is the stack pointer.
[0027] In one possible implementation, an instruction is identified as a second target instruction in the following manner, including: (1) if a stack that grows from top to bottom is used, an instruction that satisfies the following conditions is determined to be the second target instruction: the opcode in the instruction is a memory load opcode, the target register is a return address register, the memory base register is a stack pointer register, and the offset is a positive value; (2) if a stack that grows from bottom to top is used, an instruction that satisfies the following conditions is determined to be the second target instruction: the opcode in the instruction is a memory load opcode, the target register is a return address register, the memory base register is a stack pointer register, and the offset is a negative value; the stack that grows from top to bottom is a stack with a bottom at a high address and a top at a low address; the stack that grows from bottom to top is a stack with a bottom at a low address and a top at a high address; the high address is a memory address with a larger address value; and the low address is a memory address with a smaller address value.
[0028] In a third aspect, the present application provides a device for preventing return-oriented programming (ROP) attacks, the device comprising a memory for storing computer programs or instructions; and a processor for calling the computer programs or instructions stored in the memory to execute a method as in any possible implementation of the first and second aspects. BRIEF DESCRIPTION OF THE DRAWINGS
[0029] In order to more clearly illustrate the technical solutions in the embodiments of the present application, the following briefly introduces the drawings required for use in the description of the embodiments. Obviously, the drawings described below are only some embodiments of the present application. For ordinary technicians in this field, other drawings can be obtained based on these drawings without paying any creative labor.
[0030] Figure 1 A flowchart of a method for preventing ROP attacks provided in an embodiment of the present application; Figure 2 A flowchart of a method for preventing ROP attacks provided in an embodiment of the present application; Figure 3 A schematic diagram of a PAC signature and verification process provided in an embodiment of the present application; Figure 4 A schematic diagram of another PAC signing and verification process provided in an embodiment of the present application; Figure 5 A schematic diagram of another PAC signing and verification process provided in an embodiment of the present application; Figure 6 A schematic diagram of the structure of a device for preventing ROP attacks provided in an embodiment of the present application. DETAILED DESCRIPTION
[0031] To make the objectives, technical solutions, and advantages of this application more clear, this application will be further described in detail below with reference to the accompanying drawings. Obviously, the embodiments described are only some of the embodiments of this application, not all of them. Based on the embodiments in this application, all other embodiments obtained by ordinary technicians in this field without making any creative efforts are within the scope of protection of this application.
[0032] The present application provides a method for preventing ROP attacks, which is used to prevent ROP attacks by generating a PAC and adding the PAC to the return address, thereby improving the security of the software.
[0033] To facilitate understanding, some terms involved in this application are first explained.
[0034] The stack is an area in virtual memory used to store function states and local or temporary variables within a function during a function call. The stack is a last-in, first-out system, and the address at the top of the stack is called the stack pointer. Generally speaking, a stack grows from top to bottom. In other words, the address at the bottom of the stack is larger than the address at the top of the stack (i.e., the stack pointer). When the stack grows from top to bottom, the address at the bottom of the stack is the starting address of the stack, and the address at the top of the frame is the stack pointer. Whenever a new element needs to be pushed onto the stack, it is always pushed at the top of the stack, causing the stack pointer to point to a lower address. The stack in this application can also grow from bottom to top, and this application does not limit the stack growth method.
[0035] Stack frame: During a function call, a new stack frame is generated for each function call, and the current stack frame is released each time the function returns. Therefore, a stack frame is a stack area associated with a particular function call. For a given function, the stack frame size required is fixed. For the same function, when it is called multiple times, the stack frames occupied may not be located at the same address. If a function appears multiple times in a call chain at a given moment, it will occupy different stack frames each time it is called. For example, consider functions A, B, and C, and the following call chain: A -> B -> C -> B -> B -> C. Assuming the stack grows from top to bottom, the stack frames from top to bottom are: the stack frame for function A, the stack frame for the first call to function B, the stack frame for the first call to function C, the stack frame for the second call to function B, the stack frame for the third call to function B, and the stack frame for the second call to function C. Somewhere in the stack frame is stored the address to which the current function will return after execution completes.
[0036] Stack Pointer and Stack Pointer Register: The stack pointer indicates the address of the top of the stack, equivalent to the address of the top of the current stack frame. The stack pointer register is a register that stores the stack pointer. Reading the stack pointer register tells you the current address of the top of the stack; writing to the stack pointer register updates the address of the top of the stack after pushing or popping data from the stack. In particular, the stack pointer value changes with function calls, as stack frames are created and released during the call. Some instruction set architectures (ISAs), such as instruction set architectures (ISAs), automatically manage the stack pointer register. Specifically, dedicated instructions are provided to move the stack pointer with each push or pop of data. Other ISAs manage the stack pointer register manually, requiring additional instructions to update the stack pointer register before or after pushing or popping data. In these cases, the stack pointer register is typically updated after or before a batch of data is pushed or popped, rather than after each push or pop.
[0037] ROP: A crucial attack technique in computer security, it exploits existing code snippets within a program and cleverly combines them to achieve desired functionality. Attackers can construct ROP chains to execute arbitrary code, such as opening backdoors and stealing data. ROP can also bypass security mechanisms, such as writable XOR executables and stack non-executables.
[0038] PAC: Leveraging the fact that the 64-bit architecture doesn't require the full 64-bit address space, it embeds an authentication code in unused bits to authenticate a pointer and verify the validity of the authentication before using the pointer. This prevents certain malicious attacks and improves software security. PAC calculations use a specific algorithm that accepts three input parameters: a pointer (here, the original pointer before the PAC is embedded), a context, and a key. It produces a single output: the PAC, or Pointer Authentication Code.
[0039] The PAC is calculated using the algorithm described above and embedded into the corresponding pointer. A pointer containing a PAC cannot be used directly, so new instructions are provided to verify the PAC and recover the pointer. Since the algorithm is reproducible, one only needs to strip the PAC from the pointer containing the PAC, then use the algorithm again to calculate the PAC based on the PAC-stripped pointer, the context, and the key. The two PACs can then be compared for equality. If they are equal, the PAC verification passes, and the pointer is modified to the PAC-stripped form, making it valid for subsequent use. If they are not equal, the PAC verification fails, and the pointer remains invalid. Alternatively, if it was not already in an invalid form, such as a pointer without a PAC, this step will convert it to an invalid form, causing an exception when it is subsequently used.
[0040] Figure 1 The flowchart of a method for preventing ROP attacks provided in an embodiment of the present application can be executed by a CPU that processes instructions in pipeline mode. The method is used to add PAC to the reserved bit of the return address to obtain a return address carrying PAC, such as Figure 1 As shown, the process includes the following steps: Step 101 : When the CPU processes instructions in pipeline mode, if it recognizes the first target instruction in a function call, it pauses the pipeline.
[0041] In step 102, the CPU obtains the return address, stack pointer, and key of the function call through the instruction bypass unit, and generates a PAC based on the context corresponding to the return address and stack pointer and the key; the PAC is added to the reserved bits of the return address to obtain a return address carrying the PAC.
[0042] Step 103: After the instruction bypass unit completes execution, the CPU restores the pipeline according to the target address indicated by the instruction bypass unit.
[0043] Specifically, the first target instruction is a first setting instruction that causes the stack pointer to point to the caller's stack frame before and after execution, or the first target instruction is a second setting instruction that causes the stack pointer to point to the callee's stack frame before and after execution, and before and after execution are before and / or after execution. After identifying the first target instruction, the instruction bypass unit obtains the return address, stack pointer, and key of the function call, generates a PAC based on the context and key corresponding to the return address and stack pointer, and embeds the PAC into the reserved bits in the return address to obtain a return address carrying the PAC. The return address carrying the PAC is used to prevent ROP attacks against the return address. After the instruction bypass unit completes execution, the pipeline is restored according to the target address indicated by the instruction bypass unit.
[0044] In the embodiments of the present application, the return address of a function call is the pointer in the PAC algorithm. For the Class A instruction set architecture (ISA), which is generally a Complex Instruction Set Computer (CISC) architecture, the jump instruction used for function calls inserts the return address at the top of the stack. In this case, the data stored at the top of the stack is the return address. There are also jump instructions for function returns that directly read the return address from the top of the stack and jump to it, which is also known as a function return. In the Class A ISA, there is no return address register as described below. The jump instruction used for function calls also updates the stack pointer register (i.e., the stack pointer points to the caller's stack frame before execution and to the callee's stack frame after execution) and is also used to load the return address stored on the stack. The jump instruction used for function returns also updates the stack pointer register (i.e., the stack pointer points to the callee's stack frame before execution and to the caller's stack frame after execution) and is also used to load the return address stored on the stack. In the following text, these instructions are described separately, but in the Class A instruction set architecture, the instruction bypass behaviors of the jump instructions used for function calls, instructions for updating the stack pointer register (that is, instructions with the front stack pointer pointing to the caller's stack frame and the back stack pointer pointing to the callee's stack frame; or instructions with the front stack pointer pointing to the callee's stack frame and the back stack pointer pointing to the caller's stack frame), and instructions for loading the return address stored on the stack (or instructions for loading the return address stored on the stack) should be combined and understood. Similarly, the instruction bypass behaviors of the jump instructions used for function returns and instructions that also update the stack pointer register should be combined and understood.
[0045] In the B-class instruction set architecture (ISA), typically a reduced instruction set computer (RISC) architecture, function call instructions write the return address to a specific register, called the return address register. The data stored in this register is the return address. The prologue of a non-leaf function contains an instruction that copies the data in this register to the top of the stack. The data stored on the top of the stack is the return address. The epilogue of a non-leaf function contains an instruction that restores the return address from the top of the stack to a specific register. The data stored in this register is then used as the return address. Subsequently, an instruction uses this register to jump, representing the function return. While restoring the return address to another register is possible, the calling convention generally requires that the return address be restored to the return address register in the function epilogue. The jump instruction used for function calls in the B-class ISA does not update the stack pointer register; similarly, the jump instruction used for function returns in the B-class ISA does not update the stack pointer register.
[0046] In an embodiment of the present application, different types of pointers are allowed to use different keys to enhance security. For the same type of pointer, multiple different keys are available for selection. At the same time, user mode cannot access the value of the key to ensure security. Only kernel mode and higher privileged modes can access the currently effective key through special instructions. A control register can be defined to store the currently effective key, which allows the key to be accessed and modified by kernel space. Generally speaking, the kernel randomly generates a new key when starting a new program and backs up / restores it during context switching. Randomly generated keys can prevent replay attacks.
[0047] The instruction bypass unit generates different keys for different Address Space Identifiers (ASIDs). Generally, when the kernel switches processes, it simultaneously manipulates the CPU's control registers, thereby modifying the current ASID. Therefore, generating different keys for different ASIDs can achieve key isolation between processes. However, the range of ASID values is limited. In typical practice, the maximum is only 1024 or several thousand. In many use cases, the number of running processes does not exceed the ASID range, and key isolation between processes is sufficient. However, when the number of running processes exceeds the ASID range, some processes are forced to share ASIDs, resulting in insufficient key isolation between processes. Therefore, to enhance security in such situations and implement sufficient key isolation, the next implementation is provided.
[0048] A pair of instructions are designed and added to the matching list. These instructions were previously undefined or reserved. Because they were previously undefined or reserved, existing programs will not have these instructions. Executing these instructions causes a bypass. The instruction bypass unit first verifies the CPU's privileged state. If it is in user mode, an exception is raised and the program does not proceed. If it is in kernel mode or a higher privileged state, the program continues. The instructions are then parsed. One instruction reads the currently configured key and writes it to the register or memory address specified by the instruction. The other instruction reads the key from the register or memory address specified by the instruction and sets it as the current key. Thus, when switching processes, the kernel can use the first instruction to back up the previous process's key and then use the second instruction to configure the key for the next process to be executed. If a process is starting for the first time, the kernel generates a unique key using some method and configures it using the second instruction.
[0049] For PAC, the following restriction can optionally be implemented: all binary bits cannot be all 1s or all 0s. In other words, the PAC algorithm is restricted from outputting all 1s or all 0s. This ensures that a pointer with PAC, unless verified by the PAC, will always be considered an illegal address by the Memory Management Unit (MMU), making it impossible to use it directly or causing an exception if used.
[0050] It's also worth noting that many programming languages have the concept of function calls. Every function call involves a caller and a callee, and the passing of parameters and return values requires a common convention to specify how these parameters are passed. This is the calling convention. The calling convention creates function prologues and epilogues. The prologue is the sequence of instructions at the beginning of a function, while the epilogue is the sequence of instructions at the end. Based on the above explanations, the stack pointer value changes during a function call. However, as long as the program executes normally, the stack pointer value is guaranteed to be the same when entering a function (i.e., the prologue) and returning from the function (i.e., the epilogue) at the end of the function call.
[0051] MIPS64 is a type of instruction set called Class B. Taking MIPS64 as an example and the stack growing from top to bottom, a typical function prologue and epilogue are described in assembly language as follows, where the lines starting with / / are explanations of the instructions: / / Register 31 contains the return address, which is written by the caller of the function when calling the function.
[0052] / / Prolog
[0053] / / Update the stack pointer register ( sp), subtract the stack frame size (FRAME_SIZE) from its value, that is, push the top of the stack down.
[0054] / / Among them, the stack frame size must be large enough to accommodate the registers to be backed up, and also large enough to accommodate the local variables used by the function, which will not be repeated here.
[0055] daddiu sp, sp,-FRAME_SIZE
[0056] / / Will 31 The return address stored in the register is pushed to the bottom of the current stack frame
[0057] sd 31,FRAME_SIZE-8( sp)
[0058] / / There may be other instructions for backing up other registers, which are omitted here.
[0059] <...Function body...>
[0060] / / Epilogue epilog
[0061] / / Pop the return address from the bottom of the current stack frame to 31 registers.
[0062] / / ld rt,offset( base) will be added from offset( base) (inclusive) until offset+8( base) (excluding) is stored in the register rt in.
[0063] ld 31,FRAME_SIZE-8( sp)
[0064] / / Update the stack pointer register ( sp), add its value to the stack frame size (FRAME_SIZE), that is, push the top of the stack back to its original position, / / In fact, it restores the value of the stack pointer register.
[0065] daddiu sp, sp,FRAME_SIZE
[0066] / / Jump to 31 Execution continues at the address stored in the register.
[0067] jr 31
[0068] nop
[0069] The above code shows that the stack pointer register has the same value at the following times: before the first daddiu instruction (i.e., before the function prologue) and after the second daddiu instruction. At this time, the stack pointer register has the old value, pointing to the top of the caller's stack frame. Between the first daddiu instruction and the second daddiu instruction (i.e., between these two instructions), the stack pointer register has the new value, pointing to the top of the stack frame of the current function (i.e., the callee).
[0070] Therefore, when signing the PAC, there are two situations: determining the context corresponding to the stack pointer according to the old value of the stack pointer register and determining the context corresponding to the stack pointer according to the new value of the stack pointer register.
[0071] (1) Determine the context corresponding to the stack pointer based on the old value of the stack pointer register
[0072] There are two appropriate times to use the old value of the stack pointer register to determine the context corresponding to the stack pointer. The first appropriate time is the first daddiu instruction in the above code. This daddiu instruction is used to update the stack pointer register by subtracting the callee's stack frame size from its value. Before the execution of this instruction, the stack pointer points to the top of the caller's stack frame (equivalent to the old value in the stack pointer register). After the execution of this instruction, the stack pointer points to the top of the callee's stack frame (equivalent to the new value in the stack pointer register). The second appropriate time is not reflected in the above assembly code, because MIPS has a series of instructions such as jal / jalr / bal specifically for function calls. These instructions write the return address to the function at the same time as the jump. 31 register, so jal / jalr / bal etc. instructions are the second appropriate time. Both of these instructions are first target instructions.
[0073] For the first appropriate opportunity, the first setting instruction is an instruction in which the stack pointer points to the caller's stack frame before execution (equivalent to the value in the stack pointer register being the old value), and the stack pointer points to the callee's stack frame after execution (equivalent to the value in the stack pointer register being the new value). The stack pointer is obtained through the instruction bypass unit, including reading the stack pointer stored in the stack pointer register through the instruction bypass unit before the first setting instruction is executed, and the context corresponding to the stack pointer is the stack pointer.
[0074] Specifically, the first setting instruction is the first daddiu instruction in the above code. When the first setting instruction is recognized, the instruction bypass unit has two possible complete bypass modes.
[0075] (1) The first complete bypass method at the first appropriate time
[0076] One way is to complete the PAC signature in the instruction bypass unit and simulate the execution of this instruction, that is, the instruction bypass unit completes the The PAC signature of the return address on register 31 and the The rewriting of the sp register is understandable, but the daddiu instruction has not yet been completed. sp register, so its value is still the old value, which can be used to sign The rewriting of the sp register is the behavior of the daddiu instruction itself, that is, The sp register value is decremented to the new value. Of course, it is not necessary to perform these two steps one after the other. They can be performed simultaneously as long as the PAC signature is The old value of the sp register can be used. At this time, the daddiu instruction itself has been completely simulated by the instruction bypass unit, so the target address indicated by the instruction bypass unit after execution should be set to the address of the next instruction.
[0077] Specifically, the stack pointer register value is read as context, namely, the value of the stack pointer register before the first "daddiu" instruction is executed. The return address is read from the top of the stack for class A instruction set architectures and from the return address register for class B instruction set architectures. The PAC signature is generated using the current key and the PAC algorithm. The PAC is embedded in the reserved bits of the return address. Then, for class A instruction set architectures, the return address with the PAC is written to the top of the stack; for class B instruction set architectures, the return address with the PAC is written to the return address register. Execution is then simulated according to the behavior that the instruction was originally intended to execute. The pipeline is resumed at the target address indicated by the instruction bypass unit. The target address is the address of the instruction following the first set instruction (i.e., the first "daddiu" instruction in this example).
[0078] (2) The second complete bypass method at the first appropriate time
[0079] Another approach is to only perform the 31 The PAC signature of the return address on the register is obtained at this time The value of the sp register is still the old value, use it and rewrite 31 register, since this daddiu instruction is not simulated by the instruction bypass unit, the target address indicated by the instruction bypass unit after execution should be set to the address of this daddiu instruction. This makes this daddiu instruction temporarily skip an instruction match, so that the instruction is executed normally, and finally the instruction is completed through normal execution. Rewriting of sp register.
[0080] Specifically, the stack pointer register value is read as context (i.e., the value of the stack pointer register before the first daddiu instruction is executed). The return address is read from the top of the stack for class A instruction set architectures and from the return address register for class B instruction set architectures. The PAC signature is generated using the current key and the PAC algorithm. The PAC is embedded in the reserved bits of the return address. Then, for class A instruction set architectures, the return address with the PAC is written to the top of the stack; for class B instruction set architectures, the return address with the PAC is written to the return address register. The pipeline is resumed at the target address indicated by the instruction bypass unit. The target address is the address of the first setup instruction (i.e., the first daddiu instruction in this example), effectively skipping instruction recognition and directly executing the first setup instruction.
[0081] In one possible implementation, if a stack that grows from top to bottom is used, an instruction is identified as the first target instruction in the following manner: if the opcode in the instruction is an immediate addition opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is a negative value, then the instruction is the first target instruction; or if the opcode in the instruction is an immediate subtraction opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is a positive value, then the instruction is the first target instruction. A stack that grows from top to bottom is a stack with a high address at the bottom and a low address at the top, where the high address is a memory address with a larger address value; the low address is a memory address with a smaller address value.
[0082] Because instructions with the same purpose have different names in different instruction set architectures, this application does not limit the specific names of opcodes. This application embodiment uses the MIPS64 instruction set architecture, and takes the stack growing from top to bottom and the opcode being an immediate addition opcode as an example. Therefore, in the MIPS64 instruction set architecture, the opcode in the instruction is DADDIU (an immediate addition opcode), and the immediate value is a negative value.
[0083] Specifically, since the daddiu instruction itself can also be used for ordinary calculation purposes, this use is not what we want to match. We only want to match its The sp register (stack pointer register) is decremented. Therefore, when using mask matching, the matching opcode is DADDIU and the matching source register domain is sp, matching destination register domain is However, the immediate value cannot be matched because the value filled there is the stack frame size, which is different for different functions. The matching items are shown in Table 1: Table 1
[0084] Here, 1 indicates that the bit is 1, 0 indicates that the bit is 0, and x indicates that the bit can have any value. As can be seen from Table 1, bits masked as 1 participate in the match, while bits masked as 0 do not. This also applies to the subsequent tables and will not be repeated here.
[0085] Since in the function's prologue, either no stack frame is allocated, or once a stack frame is allocated, the top of the stack must be pushed down (since this example uses a top-down growing stack), when we need to further subdivide the match, we hope to only match the case where the top of the stack is pushed down, that is, When sp is decremented, the immediate value must be filled with a negative number. Note that according to the instruction definition of daddiu, the immediate value filled in is actually a signed number. That is, its highest bit can be used to determine the sign of the immediate value. When it is 1, the immediate value must be negative, otherwise it must be non-negative. Examples of matching items are shown in Table 2:
[0086] Table 2
[0087] In one possible implementation, if the AArch64 (also called ARM64 or Arm A64) instruction set architecture is used, and the stack grows from top to bottom, and the opcode is an immediate subtraction opcode, then the opcode in the instruction is SUB (and it is an immediate subtraction opcode), and the immediate value is a positive value. For example, if the matching item in this example is described in AArch64 assembly language, it is SUB SP, SP, # ; Among them, SUB indicates that the matching opcode is an immediate subtraction opcode, SP is the stack pointer register of AArch64, the first SP indicates that the matching destination register is the stack pointer register, and the second SP indicates that the matching source register is the stack pointer register, # Indicates matching of positive immediate values.
[0088] In one possible implementation, if a stack that grows from the bottom up is used, an instruction that satisfies either of the following two conditions is determined to be the first target instruction: (a) the opcode in the instruction is an immediate addition opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is positive; (b) the opcode in the instruction is an immediate subtraction opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is negative. A stack that grows from the bottom up is a stack with a low address at the bottom and a high address at the top. The high address is the memory address with the larger address value; the low address is the memory address with the smaller address value. The specific matching method will not be described in detail here.
[0089] For the second appropriate opportunity, the first setting instruction is a jump instruction for function call, and the stack pointer is obtained through the instruction bypass unit, including reading the stack pointer stored in the stack pointer register through the instruction bypass unit, and the context corresponding to the stack pointer is the stack pointer.
[0090] The jump instruction used for function call can be described as: writing the return address to the top of the stack (for class A instruction set architecture) or writing to the return address register (for class B instruction set architecture), and then jumping to the target address.
[0091] Specifically, the first setting instruction may be an instruction such as jal / jalr / bal. When the first setting instruction is recognized, the instruction bypass unit has a complete bypass mode.
[0092] (3) The second method of complete bypass at the right time
[0093] Because jal / jalr / bal and other instructions specifically used for function calls will rewrite 31 (i.e. the return address register of the MIPS architecture), so it cannot be executed as is, but must be more or less simulated by the instruction bypass unit. Before writing the return address to register 31, the PAC signature is completed first. The value of the sp register is still the old value, use it, and write it using the signed return address 31 registers, and the rest of the behavior is consistent with the original instruction behavior.
[0094] Specifically, the instruction is simulated and executed to obtain the return address (including: partially simulating the execution of the instruction so that the return address is written to the top of the stack for the Class A instruction set architecture or to the return address register for the Class B instruction set architecture, then reading the return address from the top of the stack for the Class A instruction set architecture or from the return address register for the Class B instruction set architecture without branching; or partially simulating the execution of the instruction to directly obtain the return address but not yet writing the return address to the top of the stack or the return address register, nor branching). The value of the stack pointer register is read as context, combined with the current key, to complete the PAC signature and generate the PAC. The PAC is embedded in the reserved bits of the return address. Then, for the Class A instruction set architecture, the return address with the PAC is written to the top of the stack; for the Class B instruction set architecture, the return address with the PAC is written to the return address register. Because the above operation has already written the return address (with PAC) to the expected target location (for class A ISA: the top of the stack; for class B ISA: the return address register), the only remaining un-emulated behavior for this type of instruction is the jump to the jump target (the function to be called). Therefore, the pipeline is resumed at the target address indicated by the instruction bypass unit. The target address is the jump target address of the first set instruction (i.e., the jal / jalr / bal instruction in this example).
[0095] When using a mask to match these instructions, you only need to match the opcode, because these instructions will always write the return address to the top of the stack (for class A instruction set architectures) or the return address register (for class B instruction set architectures), regardless of the values in other fields. The opcodes of these instructions vary, with some using a single opcode and others using multiple opcodes. You should match enough opcode levels until you can determine the instruction type. This is also common to the other timings and methods described above and below, so I won't go into detail here.
[0096] (2) Determine the context corresponding to the stack pointer based on the new value of the stack pointer register
[0097] There are two appropriate times to use the new value of the stack pointer register to determine the context corresponding to the stack pointer. The first appropriate time is the first daddiu instruction in the above code. The daddiu instruction is used to update the stack pointer register and subtract the callee's stack frame size from its value. Before the instruction is executed, the stack pointer points to the top of the caller's stack frame (equivalent to the value in the stack pointer register being the old value). After the instruction is executed, the stack pointer points to the top of the callee's stack frame (equivalent to the value in the stack pointer register being the new value). The second appropriate time is the sd instruction in the above assembly code, which is used to The value of register 31 is backed up to the stack. These two instructions are the first target instructions.
[0098] For the first appropriate timing, the second setting instruction is an instruction in which the stack pointer points to the caller's stack frame before execution (equivalent to the value in the stack pointer register being the old value) and the stack pointer points to the callee's stack frame after execution (equivalent to the value in the stack pointer register being the new value). Obtaining the stack pointer through the instruction bypass unit includes, before the second setting instruction is executed, reading the stack pointer stored in the stack pointer register through the instruction bypass unit, and the context corresponding to the stack pointer is the stack pointer updated after the second setting instruction is executed, which is calculated based on the size of the stack pointer and the stack frame.
[0099] Specifically, the second setting instruction is the first daddiu instruction in the above code. When the second setting instruction is recognized, the instruction bypass unit has two possible complete bypass modes.
[0100] (1) The first complete bypass method at the first appropriate time
[0101] One way is to simulate the execution of this instruction in the instruction bypass unit and complete the PAC signature, that is, the instruction bypass unit completes the The rewriting of the sp register is the behavior of the daddiu instruction itself, that is, The sp register value is decremented to become the new value, and The PAC signature of the return address on register 31, because at this time The sp register has been changed to the new value, so it can be used to sign. Of course, it is not necessary to perform these two steps one after the other. The two steps can be performed at the same time as long as the PAC signature is The new value of the sp register can be used. At this time, the daddiu instruction itself has been completely simulated by the instruction bypass unit, so the target address indicated by the instruction bypass unit after execution should be set to the address of the next instruction.
[0102] Specifically, the execution is simulated according to the behavior that the instruction was originally intended to execute. The stack pointer register value is read as context, or the updated stack pointer register value is calculated as context. This is the value of the stack pointer register after the first "daddiu" instruction is executed. For class A instruction set architectures, the return address is read from the top of the stack; for class B instruction set architectures, the return address is read from the return address register. Using the current key, a PAC signature is generated using the PAC algorithm. The PAC is embedded into the reserved bits of the return address. Then, for class A instruction set architectures, the return address with the PAC is written to the top of the stack; for class B instruction set architectures, the return address with the PAC is written to the return address register. The pipeline is resumed at the target address indicated by the instruction bypass unit. The target address is the address of the instruction following the second set instruction (i.e., the first "daddiu" instruction in this example), effectively resuming normal execution from the next instruction.
[0103] (2) The second complete bypass method at the first appropriate time
[0104] Another way is that the instruction bypass unit only completes the The PAC signature of the return address on register 31 is obtained at this time The value of the sp register is actually the old value. Therefore, it is necessary to parse the daddiu instruction to obtain the stack frame size. The value of sp is subtracted from the stack frame size before being fed into the algorithm and rewritten 31 register, the recovery address after bypassing should be set to the address of this daddiu instruction, so that this daddiu instruction temporarily skips an instruction match, so that the instruction can be completed through normal execution. Rewriting of sp register.
[0105] Specifically, the updated stack pointer register value is calculated as context (but the stack pointer register is not actually updated). Specifically, the stack pointer register value after the first "daddiu" instruction is calculated. The return address is read from the top of the stack for Class A architectures and from the return address register for Class B architectures. The PAC signature is generated using the current key and the PAC algorithm. The PAC is embedded in the reserved bits of the return address. Then, for Class A architectures, the return address with the PAC is written to the top of the stack; for Class B architectures, it is written to the return address register. The pipeline is resumed at the target address indicated by the instruction bypass unit. The target address is the address of the second set instruction (the first "daddiu" instruction in this example), effectively skipping instruction recognition and directly executing the second target instruction.
[0106] How to match the first daddiu instruction has been described above and will not be repeated here.
[0107] For the second appropriate opportunity, the second setting instruction is an instruction for backing up the return address stored in the return address register to the stack, and obtaining the stack pointer through the instruction bypass unit, including reading the stack pointer stored in the stack pointer register through the instruction bypass unit, and the context corresponding to the stack pointer is the stack pointer.
[0108] Specifically, the second setting instruction may be the sd instruction in the above assembly code. When the second setting instruction is recognized, the instruction bypass unit has two complete bypass modes.
[0109] (3) The first complete bypass method at the second appropriate time
[0110] One way is to complete the PAC signature in the instruction bypass unit and simulate the execution of this instruction, because the above sd instruction is used for backup The value of register 31 is put on the stack, so the instruction bypass unit completes the 31 register (i.e. the return address register of the MIPS architecture) and back up the return address (with PAC) to the stack. In this process, write to the specified location on the stack Before the return address stored in register 31, the PAC signature is completed first. The value of the sp register is already the new value, which is used and written to the specified location on the stack using the signed return address.
[0111] Specifically, the stack pointer register's value is read as context, the return address is read from the return address register, and the current key is used to complete the PAC signature, generating the PAC. The PAC is embedded in the reserved bits of the return address, and the return address with the PAC is then written to the memory address specified by the instruction, typically the top of the stack. Since the instruction's intended action (writing the return address to the memory address specified by the instruction) has already been fully completed in the instruction bypass unit, the pipeline resumes at the target address indicated by the instruction bypass unit. The target address is the address of the instruction following the second set instruction (the sd instruction in this example).
[0112] (4) The second complete bypass method at the second appropriate time
[0113] Another approach is to only perform the 31 The PAC signature of the return address on the register is obtained at this time The value of the sp register is already the new value, use it, and overwrite 31 register, since this sd instruction is not simulated by the instruction bypass unit, the target address indicated by the instruction bypass unit after execution should be set to the address of this sd instruction. This makes this sd instruction temporarily skip an instruction match, so that the instruction is executed normally, and finally the instruction is completed through normal execution. The return address (already carrying PAC) in register 31 (i.e., the return address register of the MIPS architecture) is written to the specified location on the stack.
[0114] Specifically, the stack pointer register value is read as context, the return address is read from the return address register, and the current key is used to complete the PAC signature to generate the PAC. The PAC is embedded in the reserved bits of the return address, and the return address with the PAC is then written to the return address register. The pipeline is resumed at the target address indicated by the instruction bypass unit. The target address is the address of the second set instruction (i.e., the sd instruction in this example), effectively skipping instruction recognition and directly executing the second set instruction.
[0115] If a top-down stack is used, an instruction is identified as the first target instruction by the following method: the instruction's opcode is a memory store opcode, the source register is the return address register, the memory base register is the stack pointer register, and the offset is a positive value. A top-down stack is one in which the bottom of the stack is at a high address and the top of the stack is at a low address, where the high address is the memory address with the larger address value, and the low address is the memory address with the smaller address value.
[0116] Specifically, since instructions with the same purpose may have different names in different instruction set architectures, this application does not limit the specific names of opcodes. This application embodiment uses the MIPS64 instruction set architecture, and takes the stack as an example, where it grows from top to bottom. Therefore, in the MIPS64 instruction set architecture, the opcode in the instruction is SD (a memory storage opcode), and the offset is a positive value.
[0117] Specifically, when using mask matching for this type of instruction, the sd instruction is a memory access instruction that uses a base register plus an immediate offset for addressing. It reads the data stored in the source register and writes it to the memory address determined by the addressing mode. If data is to be written to the stack, the base register should be sp, and if the data to be written is the return address, the source register should be 31. In this case, the matching item must match both the instruction as sd and the source register used by the instruction as 31, and also match the base register used by the instruction sp. Examples of matching items are shown in Table 3: Table 3
[0118] Furthermore, considering that when accessing data in the stack, the data should be located in the stack rather than outside the stack, and the memory address range occupied by the stack can be expressed from the bottom of the stack to the top of the stack, and considering The address stored in the sp register points to the top of the stack. Since this example uses a top-down stack, the target address of a legal memory access to the stack must be higher than the top of the stack. When sp is used as the base register, the offset must be a positive integer to place the target memory address on the stack rather than outside it. Since the offset in the above instruction is a signed integer, to make this offset a positive integer, its highest bit must be 0. Therefore, a preferred match is shown in Table 4: Table 4
[0119] In one possible implementation, if a bottom-up stack is used, the instruction is identified as the first target instruction in the following manner: the opcode in the instruction is a memory store opcode, the source register is the return address register, the memory base register is the stack pointer register, and the offset is a negative value. A bottom-up stack is one where the bottom is at a low address and the top is at a high address; the high address is the memory address with the larger address value, and the low address is the memory address with the smaller address value. Specifically, taking the MIPS64 instruction set architecture and the bottom-up stack as an example, the opcode in the instruction is SD (a memory store opcode) and the offset is a negative value. The matching example is similar to Table 4, except that the binary number in bit 15, which represents the sign of the immediate value, is 0.
[0120] Figure 2 This is a flowchart of a method for preventing ROP attacks provided by an embodiment of the present application. This flowchart can be executed by a CPU that processes instructions in pipeline mode. The method is used to determine whether the PAC to be verified is the same as the PAC carried by the return address. Figure 2 As shown, the process includes the following steps: Step 201 : When the CPU processes instructions in pipeline mode, if it recognizes the second target instruction in the function call, it pauses the pipeline.
[0121] In step 202, the CPU obtains the return address, stack pointer, and key carrying the PAC through the instruction bypass unit, and generates a PAC to be verified based on the context corresponding to the return address and stack pointer stripped of the PAC and the key.
[0122] Step 203: If the PAC is the same as the PAC to be verified, the CPU resumes the pipeline at the target address indicated by the instruction bypass unit; if the PAC is different from the PAC to be verified, an exception is triggered.
[0123] Specifically, the second target instruction is a third setting instruction that causes the stack pointer to point to the caller's stack frame before and after execution, or the second target instruction is a fourth setting instruction that causes the stack pointer to point to the callee's stack frame before and after execution, and before and after execution are before and / or after execution. After identifying the second target instruction, the instruction bypass unit obtains the return address, stack pointer, and key that carry the PAC, and generates a PAC to be verified based on the return address stripped of the PAC, the context corresponding to the stack pointer, and the key. If the PAC is the same as the PAC to be verified, the pipeline is restored at the target address indicated by the instruction bypass unit; if the PAC is different from the PAC to be verified, an exception is triggered, and the exception represents a ROP attack on the return address. When verifying the PAC, there are two situations: determining the context corresponding to the stack pointer based on the old value of the stack pointer register and determining the context corresponding to the stack pointer based on the new value of the stack pointer register.
[0124] (1) Determine the context corresponding to the stack pointer based on the old value of the stack pointer register
[0125] There are two suitable occasions to use the old value of the stack pointer register to determine the context corresponding to the stack pointer. The first suitable occasion is the second daddiu instruction in the above code, which is the instruction used to restore the stack pointer register. Simply use the restored stack pointer register value as the context to perform signature verification in the bypass and modify it accordingly. The second suitable time is the jr instruction mentioned above, which is the actual use of 31 register, at this time, it is only necessary to use the restored stack pointer register value as the context in the bypass to perform signature verification and modify the jump target address accordingly.
[0126] For the first appropriate timing, the third setting instruction is an instruction in which the stack pointer points to the callee's stack frame before execution (equivalent to the value in the stack pointer register being the new value) and the stack pointer points to the caller's stack frame after execution (equivalent to the value in the stack pointer register being the old value). The stack pointer is obtained through the instruction bypass unit, including: before the third setting instruction is executed, reading the stack pointer stored in the stack pointer register through the instruction bypass unit, and the context corresponding to the stack pointer is the stack pointer updated after the execution of the third setting instruction, which is calculated based on the size of the stack pointer and the stack frame.
[0127] Specifically, the third setting instruction is the second daddiu instruction in the above code. When the third setting instruction is recognized, the instruction bypass unit has two possible complete bypass modes.
[0128] (1) The first complete bypass method at the first appropriate time
[0129] One way is to simulate the execution of this instruction in the instruction bypass unit and complete the PAC signature verification, that is, the instruction bypass unit completes the verification. The rewriting of the sp register is the behavior of the daddiu instruction itself, that is, The sp register value is restored to the old value after incrementing, and 31 PAC signature of the return address on register, because at this time The sp register has been restored to its old value, so it can be used for signature verification; of course, it is not necessary to perform these two steps one after the other, the two steps can be performed at the same time, as long as the PAC signature is used The old value of the sp register can be used. At this time, the daddiu instruction itself has been completely simulated by the instruction bypass unit, so the target address indicated by the instruction bypass unit after execution should be set to the address of the next instruction.
[0130] Specifically, the instruction is simulated according to its intended behavior (this will cause the stack pointer register to be updated, so after the simulated execution, the value in the stack pointer register has been restored to its old value). For class A instruction set architectures, the return address with the PAC is read from the top of the stack; for class B instruction set architectures, the return address with the PAC is read from the return address register. The PAC is stripped from the return address to obtain the original return address. The stack pointer register value is read as context, or the stack pointer register value after the instruction is updated is calculated as context. Using the current key, the original return address is used to generate a new PAC. This is then compared with the previously stripped PAC. If the two match, the original return address is written to the top of the stack for class A instruction set architectures, and to the return address register for class B instruction set architectures. Otherwise, the return address with the PAC is maintained or an invalid address is written. Optionally, an exception can be raised if the comparison is inconsistent, without proceeding to the next step. The pipeline is restored at the target address indicated by the instruction bypass unit, where the target address is the address of the next instruction corresponding to the third setting instruction (ie, the second daddiu instruction in this example).
[0131] (2) The second complete bypass method at the first appropriate time
[0132] Another way is that the instruction bypass unit only completes the 31 The PAC signature of the return address on the register is obtained at this time The value of the sp register is actually a new value. Therefore, it is necessary to parse the daddiu instruction to obtain the stack frame size. The stack frame size is added to the value of sp (equivalent to calculating the old value of the stack pointer register) before the PAC signature is verified and rewritten according to the verification result. 31 register, the recovery address after bypassing should be set to the address of this daddiu instruction. This makes this daddiu instruction temporarily skip an instruction match, so that the instruction is executed normally, and finally the instruction is completed by normal execution. Rewriting of sp register.
[0133] Specifically, for the A-type instruction set architecture, the return address with the PAC is read from the top of the stack, and for the B-type instruction set architecture, the return address with the PAC is read from the return address register.
[0134] The PAC is stripped from the return address to obtain the original return address. The updated stack pointer register value is calculated as context, and combined with the current key, the PAC is regenerated using the original return address. This is compared with the previously stripped PAC. If the comparison is consistent, for class A instruction set architectures, the original return address is written to the top of the stack; for class B instruction set architectures, the original return address is written to the return address register. Otherwise, the return address with the PAC is maintained or an illegal address is written. Optionally, an exception can be directly raised if the comparison is inconsistent, without proceeding to the next step. The pipeline is restored at the target address indicated by the instruction bypass unit. The target address is the address of the third set instruction (i.e., the second daddiu instruction in this example), which is equivalent to skipping instruction recognition and directly executing the third set instruction.
[0135] In one possible implementation, if a stack that grows from top to bottom is used, the instruction is identified as the second target instruction in the following manner: if the opcode in the instruction is an immediate addition opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is positive, then the instruction is the second target instruction; or if the opcode in the instruction is an immediate subtraction opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is negative, then the instruction is the second target instruction. A stack that grows from top to bottom is a stack with a high address at the bottom and a low address at the top, where the high address is the memory address with the larger address value; the low address is the memory address with the smaller address value.
[0136] The embodiment of the present application takes the MIPS64 instruction set architecture, and takes the stack growing from top to bottom and the opcode being an immediate addition opcode as an example. Therefore, in the MIPS64 instruction set architecture, the opcode in the instruction is DADDIU (an immediate addition opcode), and the immediate value is a positive value.
[0137] Specifically, since at the end of the function, either the stack frame is not released or the top of the stack is pushed up once the stack frame is released (since this example uses a top-down growing stack), here, we hope to only match the case where the top of the stack is pushed up, that is, When sp is incremented, the immediate value must be filled with a positive number. According to the instruction definition of daddiu, its highest bit can be used to determine the sign of the immediate value. The highest bit of the immediate value must be 0. The matching items are shown in Table 5: Table 5
[0138] In one possible implementation, if a stack that grows from the bottom up is used, an instruction that satisfies either of the following two conditions is determined to be the second target instruction: (a) the opcode in the instruction is an immediate addition opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is negative; (b) the opcode in the instruction is an immediate subtraction opcode, the source register is the stack pointer register, the destination register is the stack pointer register, and the immediate value is positive. A stack that grows from the bottom up is a stack with a low address at the bottom and a high address at the top; a high address is a memory address with a larger address value, and a low address is a memory address with a smaller address value. The specific matching method will not be described in detail here.
[0139] For the second appropriate opportunity, the third setting instruction is a jump instruction for function return, and the stack pointer is obtained through the instruction bypass unit, including reading the stack pointer stored in the stack pointer register through the instruction bypass unit, and the context corresponding to the stack pointer is the stack pointer.
[0140] Specifically, the third setting instruction may be a jr instruction. When the third setting instruction is recognized, the instruction bypass unit has a complete bypass mode.
[0141] (3) The second method of complete bypass at the right time
[0142] Because the jr instruction itself will use 31 (the return address register in the MIPS architecture), but before the PAC signature check is completed, because the reserved bits are occupied by the PAC, its value is still an illegal address. Therefore, it cannot be executed as is, but must be simulated by the instruction bypass unit more or less. In this process, before the jump, the PAC signature is completed first, and the The value of the sp register has been restored to its old value by the previous daddiu instruction. After the signature verification passes, the return address stripped of the PAC is used for jumping. If the signature verification fails, an exception is caused. The rest of the behavior is consistent with the original instruction behavior.
[0143] Specifically, for the A-type instruction set architecture, the return address with the PAC is read from the top of the stack; for the B-type instruction set architecture, the return address with the PAC is read from the return address register. The PAC is stripped from the return address to obtain the original return address. The value of the stack pointer register is read as context, and the original return address is used in conjunction with the current key to regenerate the PAC. The original return address is compared with the previously stripped PAC. If the comparison is consistent, the original return address is used as the jump target address. Otherwise, the return address with the PAC is maintained as the jump target address, or an invalid address is used as the jump target address. Optionally, if the comparison is inconsistent, an exception can be directly raised without proceeding to the next step. Furthermore, in addition to the jump, the original behavior of the instruction is simulated. These two steps can be performed sequentially or simultaneously. Since the original behavior of this instruction has been fully completed in the instruction bypass unit, the pipeline is restored at the target address indicated by the instruction bypass unit. The target address is the address of the jump target of the third set instruction (i.e., the jr instruction in this example).
[0144] The jr instruction is an instruction that reads the address stored in the source register and jumps to the address. If you want to jump to the return address, the source register should be the return address register (for the MIPS instruction set architecture, it is 31). In this case, the matching item must match both the instruction as jr and the source register used by the instruction as 31, in order to determine that the instruction is a jump instruction for function return (it is worth noting that some instruction set architectures do not require the jump instruction for function return to specify a register in the instruction. For such instruction set architectures, only the opcode needs to be matched, which will not be explained in detail). Also note that the jr instruction uses a two-level opcode, so two levels of opcodes must be matched to determine that the instruction is jr. Examples of matching items are shown in Table 6: Table 6
[0145] (2) Determine the context corresponding to the stack pointer based on the new value of the stack pointer register
[0146] There are two suitable times to use the new value of the stack pointer register to determine the context corresponding to the stack pointer. The first suitable time is the second daddiu instruction mentioned above, which is the instruction used to restore the stack pointer register. Simply use the current value of the stack pointer register (the value before the instruction is executed) in the bypass, rather than the value after the restoration, as the context to perform signature verification and modify accordingly. The second suitable time is the ld instruction in the above code, which is used to pop the return address from the bottom of the current stack frame to 31 register, in this case, we only need to use the current value of the stack pointer register as the context to perform the signature verification in the bypass and write the return address after the signature verification to 31 hits.
[0147] For the first appropriate timing, the fourth setting instruction is an instruction in which the stack pointer points to the callee stack frame before execution (equivalent to the value in the stack pointer register being the new value), and after execution, the stack pointer points to the caller stack frame (equivalent to the value in the stack pointer register being the old value). Obtaining the stack pointer through the instruction bypass unit includes, before the fourth setting instruction is executed, reading the stack pointer stored in the stack pointer register through the instruction bypass unit, and the context corresponding to the stack pointer is the stack pointer.
[0148] Specifically, the fourth setting instruction is the second daddiu instruction in the above code. When the second setting instruction is recognized, the instruction bypass unit has two possible complete bypass modes.
[0149] (1) The first complete bypass method at the first appropriate time
[0150] One way is to complete the PAC signature verification in the instruction bypass unit and simulate the execution of this instruction, that is, the instruction bypass unit completes the verification. 31 PAC signature of the return address on register, which has not been rewritten at this time sp register, so its value is still the new value and can be used for signature verification. The rewriting of the sp register is the behavior of the daddiu instruction itself, that is, The sp register value is incremented and restored to its old value. Of course, it is not necessary to perform these two steps one after the other. They can be performed simultaneously as long as the PAC signature verification is performed using The new value of the sp register can be used. At this time, the daddiu instruction itself has been completely simulated by the instruction bypass unit, so the recovery address should be set to the address of the next instruction.
[0151] Specifically, for the A-type instruction set architecture, the return address with the PAC is read from the top of the stack; for the B-type instruction set architecture, the return address with the PAC is read from the return address register. The PAC is stripped from the return address to obtain the original return address. The value of the stack pointer register before the update is read as context, and the original return address is regenerated using the current key. The PAC is compared with the previously stripped PAC. If the comparison is consistent, the original return address is written to the top of the stack for the A-type instruction set architecture and to the return address register for the B-type instruction set architecture. Otherwise, the return address with the PAC remains unchanged or an invalid address is written. Optionally, if the comparison is inconsistent, an exception can be directly raised without proceeding to the next step. In addition, execution is simulated according to the behavior that the instruction should have originally executed. The pipeline is restored at the target address indicated by the instruction bypass unit. The target address is the address of the instruction next to the fourth set instruction (i.e., the second daddiu instruction in this example), which is equivalent to resuming normal execution from the next instruction.
[0152] (2) The second complete bypass method at the first appropriate time
[0153] Another way is that the instruction bypass unit only completes the 31 The PAC signature of the return address on the register is obtained at this time The value of the sp register is still the new value, which can be used for PAC signature verification and rewritten according to the verification result. 31 register. The recovery address after bypassing should be set to the address of this daddiu instruction, so that this daddiu instruction temporarily skips an instruction match, so that the instruction can be completed through normal execution. Rewriting of sp register.
[0154] Specifically, for the A-type instruction set architecture, the return address with the PAC is read from the top of the stack; for the B-type instruction set architecture, the return address with the PAC is read from the return address register. The PAC is stripped from the return address to obtain the original return address. The value of the stack pointer register is read as context, and the original return address is used in conjunction with the current key to regenerate the PAC. This is compared with the previously stripped PAC. If the comparison is consistent, the original return address is written to the top of the stack for the A-type instruction set architecture, and to the return address register for the B-type instruction set architecture. Otherwise, the return address with the PAC is maintained or an invalid address is written. Optionally, if the comparison is inconsistent, an exception can be directly raised without proceeding to the next step. The pipeline is restored at the target address indicated by the instruction bypass unit. The target address is the address of the fourth set instruction (i.e., the second daddiu instruction in this example), which is equivalent to skipping instruction recognition and directly executing the fourth set instruction.
[0155] How to match the second daddiu instruction has been described above and will not be repeated here.
[0156] For the second appropriate opportunity, the fourth setting instruction is an instruction for restoring the return address stored on the stack to the return address register, and obtaining the stack pointer through the instruction bypass unit, including, before the third setting instruction is executed, reading the stack pointer stored in the stack pointer register through the instruction bypass unit, and the context corresponding to the stack pointer is the stack pointer.
[0157] Specifically, the fourth setting instruction may be an ld instruction in the above assembly code. When the fourth setting instruction is identified, the instruction bypass unit has two complete bypass modes.
[0158] (3) The first complete bypass method at the second appropriate time
[0159] One way is to complete the PAC signature in the instruction bypass unit and simulate the execution of this instruction, because the above ld instruction is used to pop the return address from the current stack to 31 register, so the instruction bypass unit completes the PAC signature of the return address in the stack and writes the return address (the original return address, with PAC stripped) to the return address register (i.e. MIPS 31). In this process, 31 Before writing the return address to the register, the PAC signature is completed first. The value of the sp register is still the new value, use it, and write the return address into the register according to the signature verification result. 31 registers, and the rest of the behavior is consistent with the original instruction behavior.
[0160] Specifically, the return address restoration behavior is removed, and the instruction is simulated according to the behavior it was originally intended to perform. The return address with the PAC is read from the memory address specified by the instruction (generally the top of the stack). The PAC in the return address is stripped to obtain the original return address. The value of the stack pointer register is read as context, and the PAC is regenerated using the original return address in combination with the current key. The original return address is compared with the previously stripped PAC. If the comparison is consistent, the original return address is written to the return address register. Otherwise, the return address with the PAC is maintained as is or an illegal address is written. Optionally, an exception can be directly raised if the comparison is inconsistent without proceeding to the next step. Since the behavior that this instruction was originally intended to perform (writing the return address to the return address register) has been fully completed in the instruction bypass unit, the pipeline is restored at the target address indicated by the instruction bypass unit. The target address is the address of the next instruction corresponding to the fourth setting instruction (i.e., the ld instruction in this example).
[0161] (4) The second complete bypass method at the second appropriate time
[0162] Another way is to complete the PAC signature of the return address in the stack in the instruction bypass unit. The value of the sp register is still the new value, which is used and the return address in the stack is rewritten according to the signature verification result. Since this ld instruction is not simulated by the instruction bypass unit, the target address indicated by the instruction bypass unit after execution should be set to the address of this ld instruction. This makes this ld instruction temporarily skip an instruction match, so that the instruction is executed normally, and finally the instruction completes the writing of the return address in the stack to the ld instruction through normal execution. 31 Register (i.e., the return address register of the MIPS architecture).
[0163] Specifically, the return address with PAC is read from the memory address specified by the instruction (generally the top of the stack). The PAC in the return address is stripped to obtain the original return address. The value of the stack pointer register is read as the context, and the PAC is regenerated using the original return address in combination with the current key. The original return address is compared with the previously stripped PAC. If the comparison is consistent, the original return address is written to the memory address specified by the instruction (generally the top of the stack). Otherwise, the return address with PAC is maintained as it is or an illegal address is written. Optionally, an exception can be directly triggered when the comparison is inconsistent without going to the next step. The pipeline is restored at the target address indicated by the instruction bypass unit. The target address is the address of the fourth setting instruction (i.e., the ld instruction in this example), which is equivalent to skipping instruction recognition and directly executing the fourth setting instruction.
[0164] If a top-down growing stack is used, an instruction is identified as a second target instruction in the following manner: if the opcode in the instruction is a memory load opcode, the target register is the return address register, the memory base register is the stack pointer register, and the offset is a positive value, then the instruction is a second target instruction.
[0165] The embodiment of the present application uses the MIPS64 instruction set architecture, and takes the stack growing from top to bottom as an example. Therefore, in the MIPS64 instruction set architecture, the opcode in the instruction is LD (belonging to the memory load opcode), and the offset is a positive value.
[0166] Specifically, when using mask matching for this type of instruction, the ld instruction is a memory access instruction that uses a base register plus an immediate offset to access data. It reads data from a specific memory address and writes it to the target register. If data is to be read from the stack, the base register should be sp. In this case, the matching item must match both the instruction ld and the target register used by the instruction. 31, and also match the base register used by the instruction sp. Examples of matching items are shown in Table 7: Table 7
[0167] Furthermore, considering that when accessing data in the stack, the data should be located in the stack rather than outside the stack, and the memory address range occupied by the stack can be expressed from the bottom of the stack to the top of the stack, and considering The address stored in the sp register points to the top of the stack. Since this example uses a top-down stack, the target address of a legal memory access to the stack must be higher than the top of the stack. When sp is used as the base register, the offset must be a positive integer to place the target memory address on the stack rather than outside it. Since the offset in the above instruction is a signed integer, to make this offset a positive integer, its highest bit must be 0. Therefore, the matching items are shown in Table 8: Table 8
[0168] In one possible implementation, if a bottom-up stack is used, an instruction that satisfies the following conditions is determined to be the second target instruction: the opcode in the instruction is a memory load opcode, the target register is the return address register, the memory base register is the stack pointer register, and the offset is a negative value. A bottom-up stack is a stack with a low address at the bottom and a high address at the top; the high address is the memory address with the larger address value; the low address is the memory address with the smaller address value. Specifically, taking the MIPS64 instruction set architecture and the stack growing from the bottom up as an example, in the MIPS64 instruction set architecture, the opcode in the instruction is LD (a memory load opcode) and the offset is a negative value. The matching example is similar to Table 8, except that the binary number representing the positive or negative sign of the immediate value in bit 15 is 1.
[0169] Therefore, as mentioned above, the PAC signature can be placed in the reserved bits of the pointer. Figure 3 A schematic diagram of a PAC signing and verification process provided in an embodiment of the present application. To implement PAC, we must define which bit fields of the pointer are used to embed the PAC, and we must ensure that no additional information is lost during this process. Specifically, the valid bits of the pointer cannot be used, and the identification of the high / low address cannot be lost, or at least the lost information can be recovered.
[0170] The reserved bits and high / low address identifiers of existing pointers are actually two sides of the same coin. This is due to the following two rules that generally apply simultaneously: when the highest bit is 1, it indicates a high address (kernel space address), and when the lowest bit is 0, it indicates a low address (user space address). Every bit from the highest bit to the most significant bit is a reserved bit. All reserved bits must be synchronized with the highest bit to the same binary value; otherwise, the pointer is invalid, meaning it is an illegal memory address or a non-canonical memory address. In other words, the highest bit and the reserved bits must be all 1s or all 0s to prevent it from being a valid address.
[0171] Therefore, as long as a pointer is legal, not only its highest bit but also any reserved bits are related to the high / low address. Therefore, the highest bit and the reserved bits can be collectively referred to as the reserved bit and the high / low address identifier.
[0172] Based on this, the present invention provides a method for redefining the pointer bit field, which can embed the PAC without losing any existing valid information. That is, the original use of the valid bits is not changed, and the reserved bits and high / low address identifiers are reallocated.
[0173] In a possible implementation, at least one bit is used as a high / low address identifier, and the position and length may not be limited. The remaining bits are used to embed the PAC. Figure 4Another PAC signature and verification process diagram provided in this application embodiment, from Figure 4 As can be seen from the figure, the highest bit can be used as a high / low address identifier, and the remaining reserved bits are all used to embed PAC.
[0174] Figure 5 This is a schematic diagram of another PAC signing and verification process provided by an embodiment of the present application. In one possible implementation, all bits of the pointer are used to embed the PAC. During PAC verification, since the original pointer must be restored first, the possible values of the reserved bits and the high / low address identifiers can be exhaustively enumerated when restoring the original pointer. There are actually only two possible values: either all 1s or all 0s. If either value results in a successful PAC verification, the original high / low address identifier values are restored, thus confirming the correct value of the original pointer.
[0175] Figure 6 Schematic diagram of a device 6000 for preventing ROP attacks provided in an embodiment of the present application. Figure 6 As shown, it includes at least one processor 601 and a memory 602 connected to the at least one processor 601. The specific connection medium between the processor 601 and the memory 602 is not limited in the embodiment of the present application. Figure 6 For example, the processor 601 and the memory 602 are connected via a bus. The bus can be divided into an address bus, a data bus, a control bus, and the like.
[0176] In an embodiment of the present application, the memory 602 stores instructions that can be executed by at least one processor 601. The at least one processor 601 can implement the steps of the above-mentioned method for preventing ROP attacks by executing the instructions stored in the memory 602.
[0177] The processor 601 is the control center of the computer device. It can connect the various parts of the computer device using various interfaces and lines, and perform resource settings by running or executing instructions stored in the memory 602 and calling data stored in the memory 602. Optionally, the processor 601 may include one or more processing units. The processor 601 may integrate an application processor and a modem processor. The application processor mainly processes the operating system, user interface, and application programs, while the modem processor mainly processes wireless communications. It is understood that the modem processor may not be integrated into the processor 601. In some embodiments, the processor 601 and the memory 602 may be implemented on the same chip. In some embodiments, they may also be implemented on separate chips.
[0178] The processor 601 can be a general-purpose processor, such as a central processing unit (CPU), a digital signal processor, an application-specific integrated circuit (ASIC), a field-programmable gate array or other programmable logic device, a discrete gate or transistor logic device, or a discrete hardware component, and can implement or execute the various methods, steps, and logic block diagrams disclosed in the embodiments of this application. A general-purpose processor can be a microprocessor or any conventional processor. The steps of the methods disclosed in the embodiments of this application can be directly implemented as being executed by a hardware processor, or can be executed by a combination of hardware and software modules in the processor.
[0179] Memory 602, as a non-volatile computer-readable storage medium, can be used to store non-volatile software programs, non-volatile computer executable programs, and modules. Memory 602 may include at least one type of storage medium, such as flash memory, a hard disk, a multimedia card, a card-type memory, random access memory (RAM), static random access memory (SRAM), programmable read-only memory (PROM), read-only memory (ROM), electrically erasable programmable read-only memory (EEPROM), magnetic storage, a magnetic disk, an optical disk, and the like. Memory 602 is any other medium that can be used to carry or store desired program code in the form of instructions or data structures and can be accessed by a computer, but is not limited thereto. Memory 602 in the embodiments of the present application may also be a circuit or any other device capable of performing a storage function, used to store program instructions and / or data.
[0180] Those skilled in the art will appreciate that the embodiments of the present application may be provided as methods, systems, or computer program products. Therefore, the present application may take the form of an entirely hardware embodiment, an entirely software embodiment, or an embodiment combining software and hardware. Furthermore, the present application may take the form of a computer program product implemented on one or more computer-usable storage media (including but not limited to magnetic disk storage, CD-ROM, optical storage, etc.) containing computer-usable program code.
[0181] The present application is described with reference to the flowcharts and / or block diagrams of the methods, devices (systems), and computer program products according to the present application. It should be understood that each process and / or block in the flowchart and / or block diagram, as well as the combination of processes and / or blocks in the flowchart and / or block diagram, can be implemented by computer program instructions. These computer program instructions can be provided to a processor of a general-purpose computer, a special-purpose computer, an embedded processor, or other programmable data processing device to produce a machine, so that the instructions executed by the processor of the computer or other programmable data processing device generate instructions for implementing the processes in the flowchart and / or block diagram. Figure 1 a process or multiple processes and / or boxes Figure 1 A device that provides the functions specified in a block or multiple blocks.
[0182] These computer program instructions may also be stored in a computer readable memory that can direct a computer or other programmable data processing device to work in a specific manner, so that the instructions stored in the computer readable memory produce an article of manufacture comprising an instruction device, which implements the process Figure 1 a process or multiple processes and / or boxes Figure 1 The function specified in one or more boxes.
[0183] These computer program instructions can also be loaded onto a computer or other programmable data processing device so that a series of operational steps are executed on the computer or other programmable device to produce a computer-implemented process, thereby providing the instructions executed on the computer or other programmable device for implementing the process. Figure 1 a process or multiple processes and / or boxes Figure 1 A step that specifies a function in one or more boxes.
[0184] Obviously, those skilled in the art may make various changes and modifications to this application without departing from the spirit and scope of this application. Thus, if these modifications and variations of this application fall within the scope of the claims of this application and their equivalents, this application is intended to include these modifications and variations.
Claims
1. A method for preventing return-oriented programming (ROP) attacks, characterized in that: The method comprises: When processing instructions in pipeline mode, if a first target instruction in a function call is identified, the pipeline is paused; the first target instruction is a first setting instruction that causes a stack pointer to point to a caller's stack frame before and after execution; or the first target instruction is a second setting instruction that causes a stack pointer to point to a callee's stack frame before and after execution; the before and after execution are before and / or after execution; The instruction bypass unit obtains the return address of the function call, the stack pointer, and the key, and generates a pointer authentication code (PAC) based on the return address, the context corresponding to the stack pointer, and the key; the PAC is added to the reserved bits of the return address to obtain a return address carrying the PAC; the return address carrying the PAC is used to prevent ROP attacks targeting the return address; After the instruction bypass unit completes execution, the pipeline is restored according to the target address indicated by the instruction bypass unit.
2. The method according to claim 1, characterized in that The first setting instruction is an instruction that sets the stack pointer to point to the caller's stack frame before execution and to point to the callee's stack frame after execution; Obtaining the stack pointer through an instruction bypass unit includes: Before the first setting instruction is executed, reading the stack pointer stored in the stack pointer register through an instruction bypass unit; The context corresponding to the stack pointer is the stack pointer.
3. The method according to claim 1, characterized in that The first setting instruction is a jump instruction for function call; Obtaining the stack pointer through an instruction bypass unit includes: The stack pointer stored in the stack pointer register is read through an instruction bypass unit, and the context corresponding to the stack pointer is the stack pointer.
4. The method according to claim 1, wherein The second setting instruction is an instruction that sets the stack pointer to point to the caller's stack frame before execution and to point to the callee's stack frame after execution; Obtaining the stack pointer through an instruction bypass unit includes: Before the second setting instruction is executed, reading the stack pointer stored in the stack pointer register through an instruction bypass unit; The context corresponding to the stack pointer is a stack pointer that is calculated based on the size of the stack pointer and the stack frame and is updated after the second setting instruction is executed.
5. The method according to claim 1, wherein The second setting instruction is an instruction for backing up the return address stored in the return address register onto the stack; Obtaining the stack pointer through an instruction bypass unit includes: The stack pointer stored in the stack pointer register is read through an instruction bypass unit, and the context corresponding to the stack pointer is the stack pointer.
6. A method for preventing return-oriented programming (ROP) attacks, characterized in that: The method comprises: When processing instructions in pipeline mode, if a second target instruction in a function call is identified, the pipeline is paused, where the second target instruction is a third setting instruction that causes a stack pointer to point to a caller's stack frame before and after execution, or a fourth setting instruction that causes a stack pointer to point to a callee's stack frame before and after execution; the before and after execution being before and / or after execution; Obtaining, through an instruction bypass unit, a return address carrying a pointer authentication code (PAC), the stack pointer, and a key, and generating a PAC to be verified based on the return address stripped of the PAC, the context corresponding to the stack pointer, and the key; If the PAC is the same as the PAC to be verified, the pipeline is restored at the target address indicated by the instruction bypass unit; if the PAC is different from the PAC to be verified, an exception is triggered, and the exception indicates a ROP attack on the return address.
7. The method according to claim 6, characterized in that The third setting instruction is an instruction that sets the stack pointer to the callee stack frame before execution and the stack pointer to the caller stack frame after execution; Obtaining the stack pointer through an instruction bypass unit includes: Before the third setting instruction is executed, reading the stack pointer stored in the stack pointer register through an instruction bypass unit; The context corresponding to the stack pointer is a stack pointer that is calculated based on the size of the stack pointer and the stack frame and is updated after the third setting instruction is executed.
8. The method according to claim 6, characterized in that The third setting instruction is a jump instruction for function return; Obtaining the stack pointer through an instruction bypass unit includes: Reading the stack pointer stored in the stack pointer register through an instruction bypass unit; The context corresponding to the stack pointer is the stack pointer.
9. The method according to claim 6, characterized in that The fourth setting instruction is an instruction that sets the stack pointer to the callee stack frame before execution and the stack pointer to the caller stack frame after execution; Obtaining the stack pointer through an instruction bypass unit includes: Before the fourth setting instruction is executed, reading the stack pointer stored in the stack pointer register through an instruction bypass unit; The context corresponding to the stack pointer is the stack pointer.
10. The method according to claim 6, characterized in that The fourth setting instruction is an instruction for restoring the return address stored on the stack to the return address register; Obtaining the stack pointer through an instruction bypass unit includes: Before the third setting instruction is executed, reading the stack pointer stored in the stack pointer register through an instruction bypass unit; The context corresponding to the stack pointer is the stack pointer.
Citation Information
Patent Citations
A stack overflow attack protection system and method
CN109033821A
Call path dependent authentication
CN111052115A
Program pipeline control method, processing device and storage medium
CN115994348A
Pointer integrity protection method and device, equipment and storage medium
CN116502219A
Pointer authentication
CN119452357A