Stack Overflow Attack series: shellcode in linux x86 64-bit attacks get root permissions (1) how to execute functions, shellcoderoot
There are already many examples of stack overflow on the Internet, but it rarely involves 64-bit linux related to the operating system. Recently, I have been researching this, so I wrote a series of blog posts, one is to help you remember, and the other is to help more people explore each other.
Register
The X86-64 has 16 64-bit registers: % rax, % rbx, % rcx, % rdx, % esi, % edi, % rbp, % rsp, % r8, % r9, % r10, % r11, % r12, % r13, % r14, % r15. Where:
% Rax used as function return value
% Rsp Stack pointer register pointing to stack top
% Rdi, % rsi, % rdx, % rcx, % r8, % r9 are used as function parameters, which correspond to 1st parameters, 2nd parameters, and 3rd parameters in sequence.
% Rbx, % rbp, % r12, % r13, % 14, % 15 are used as data storage. before calling the sub-function, callee-save must be saved to the stack.
% R10, % r11 used as data storage before calling caller-save, you must first save the original value to the stack
Stack structure
This is a 32-bit stack address layout ., The difference between 32-bit and 64-bit mainly lies in the difference between registers. The original ebp esp pointer register programming rbp, rsp
Returned address |
|
Address of the previous Stack |
<-- Rbp |
Parameter n |
|
... |
|
Parameter 1 |
<-- Rsp |
Three important pointer registers: rbp, rsp, and rip
Premise: function A now calls function B
Rbp: the starting position of function stack B
Rsp: bottom position of current function stack B
Rip: the address of the currently executed Function
Function entry and return
Three Assembly commands
1. call address
This command is simple, that is, the address for calling the function.
Push % rip: Save the rip address to the stack, which is actually the current running address.
Jmp address: give the address of the next function to rip.
Start address of the previous Stack |
<-- Rbp |
Parameter n of the previous Stack |
|
... |
|
Parameter 1 of the previous Stack |
|
Rip value of the previous Stack |
|
|
<-- Rsp |
The rbp value is saved by pushing % rsp after entering the function.
2. leaveq
Commands are equivalent
Move % rbp % rsp point rsp pointer to rbp
Pop % rbp assigns the value in the stack to rbp, and rsp points to the previous address, that is, rsp now points toReturned address
The address to which the stack runs. |
|
Start address of the previous Stack |
<-- Rbp |
Parameter n of the previous Stack |
|
... |
|
Parameter 1 of the previous Stack |
|
The address to which the previous Stack runs. |
<-- Rsp |
Start address of the previous Stack |
|
Parameter n |
|
... |
|
Parameter 1 |
|
3. ret
Commands are equivalent
Pop % rip: Assign the returned address to rip, and rsp points to the previous address.
The address to which the stack runs. |
|
Start address of the previous Stack |
<-- Rbp |
Parameter n of the previous Stack |
|
... |
|
Parameter 1 of the previous Stack |
<-- Rsp |
The address to which the previous Stack runs. |
|
Start address of the previous Stack |
|
Parameter n |
|
... |
|
Parameter 1 |
|
After 3, you can see that the entire function is exited, And the stack pointer is back to the stack that calls the function. In this way, the complete function call is completed, and the stack-to-stack process is also completed.
Zookeeper