The following code contains an 8 bytes buffer.
以下代码包含8字节缓冲区。
void vuln() {
char buffer[8];
gets(buffer);
printf("%s",buffer);
}
int main() {
vuln();
return 0;
}
So, only 8 bytes of stack is expected to be reserved for this buffer. But the disassembly shows 16 bytes being reserved.
因此,预计只为该缓冲区保留8个字节的堆栈。但反汇编显示保留了16个字节。
(gdb)
Dump of assembler code for function vuln:
0x000000000040057d <+0>: push %rbp
0x000000000040057e <+1>: mov %rsp,%rbp
0x0000000000400581 <+4>: sub $0x10,%rsp
0x0000000000400585 <+8>: lea -0x10(%rbp),%rax
0x0000000000400589 <+12>: mov %rax,%rdi
0x000000000040058c <+15>: callq 0x400480 <gets@plt>
0x0000000000400591 <+20>: lea -0x10(%rbp),%rax
0x0000000000400595 <+24>: mov %rax,%rsi
0x0000000000400598 <+27>: mov $0x400644,%edi
0x000000000040059d <+32>: mov $0x0,%eax
0x00000000004005a2 <+37>: callq 0x400450 <printf@plt>
0x00000000004005a7 <+42>: leaveq
0x00000000004005a8 <+43>: retq
End of assembler dump.
Some actions are to be perform based on the expected size of the buffer on the stack in an automated script. But this crippled the script. May I know the reason why 16 bytes were allocated for the buffer so that I can incorporate it in the script ?
某些操作将根据自动脚本中堆栈上缓冲区的预期大小执行。但是这使剧本瘫痪了。我可以知道为缓冲区分配16个字节的原因,以便我可以将其合并到脚本中吗?
3 个解决方案
#1
2
The x86-64 ELF psABI requires the stack pointer to be aligned: section 3.2.2 ("The Stack Frame") says
x86-64 ELF psABI要求堆栈指针对齐:第3.2.2节(“堆栈帧”)说
... The end of the input argument area shall be aligned on a 16 byte boundary. In other words, the value (
%rsp
− 8) is always a multiple of 16 when control is transferred to the function entry point. The stack pointer,%rsp
, always points to the end of the latest allocated stack frame....输入参数区域的末尾应在16字节边界上对齐。换句话说,当控制转移到函数入口点时,值(%rsp-8)始终是16的倍数。堆栈指针%rsp始终指向最新分配的堆栈帧的末尾。
Your function allocates 8 bytes on the stack and then calls a one-argument function, gets
; that function's one argument is passed in registers, so to maintain the ABI requirement, the compiler has to move the stack pointer down an additional 8 bytes before it makes the function call.
你的函数在堆栈上分配8个字节,然后调用单参数函数,得到;该函数的一个参数在寄存器中传递,因此为了保持ABI要求,编译器必须在进行函数调用之前将堆栈指针向下移动8个字节。
#2
1
As @Zack put in his answer, x86-64 ABI requires 16 bytes stack alignment. If you are using gcc
on x86 or x86_64 by default stack is 16 bytes aligned.
正如@Zack提出的那样,x86-64 ABI需要16字节的堆栈对齐。如果您在x86或x86_64上使用gcc,则默认情况下堆栈是16字节对齐的。
From gcc
documentation:
来自gcc文档:
-mpreferred-stack-boundary=num Attempt to keep the stack boundary aligned to a 2 raised to num byte boundary. If -mpreferred-stack-boundary is not specified, the default is 4 (16 bytes or 128 bits).
-mpreferred-stack-boundary = num尝试保持堆栈边界对齐2到num字节边界。如果未指定-mpreferred-stack-boundary,则默认值为4(16字节或128位)。
https://gcc.gnu.org/onlinedocs/gcc/i386-and-x86-64-Options.html
See the documentation further, if SSE is disabled gcc
may align stack to 8 bytes (and thus violate ABI requirements).
进一步参见文档,如果SSE被禁用,gcc可能会将堆栈对齐到8个字节(因此违反了ABI要求)。
#3
0
You can't control what the compiler will do on the stack. You also can't control the order of variables on the stack. The compiler is also allowed to introduce padding so to better align things in memory (although not inside arrays: this is strictly forbidden). In certain cases it won't even allocate variables on stack, but in registers instead.
您无法控制编译器在堆栈上执行的操作。您也无法控制堆栈上变量的顺序。编译器也允许引入填充,以便更好地对齐内存中的内容(尽管不在数组内部:这是严格禁止的)。在某些情况下,它甚至不会在堆栈上分配变量,而是在寄存器中分配变量。
If you has specific needs on assembly level, do it in assembly.
如果您在装配级别有特定需求,请在装配中执行。
#1
2
The x86-64 ELF psABI requires the stack pointer to be aligned: section 3.2.2 ("The Stack Frame") says
x86-64 ELF psABI要求堆栈指针对齐:第3.2.2节(“堆栈帧”)说
... The end of the input argument area shall be aligned on a 16 byte boundary. In other words, the value (
%rsp
− 8) is always a multiple of 16 when control is transferred to the function entry point. The stack pointer,%rsp
, always points to the end of the latest allocated stack frame....输入参数区域的末尾应在16字节边界上对齐。换句话说,当控制转移到函数入口点时,值(%rsp-8)始终是16的倍数。堆栈指针%rsp始终指向最新分配的堆栈帧的末尾。
Your function allocates 8 bytes on the stack and then calls a one-argument function, gets
; that function's one argument is passed in registers, so to maintain the ABI requirement, the compiler has to move the stack pointer down an additional 8 bytes before it makes the function call.
你的函数在堆栈上分配8个字节,然后调用单参数函数,得到;该函数的一个参数在寄存器中传递,因此为了保持ABI要求,编译器必须在进行函数调用之前将堆栈指针向下移动8个字节。
#2
1
As @Zack put in his answer, x86-64 ABI requires 16 bytes stack alignment. If you are using gcc
on x86 or x86_64 by default stack is 16 bytes aligned.
正如@Zack提出的那样,x86-64 ABI需要16字节的堆栈对齐。如果您在x86或x86_64上使用gcc,则默认情况下堆栈是16字节对齐的。
From gcc
documentation:
来自gcc文档:
-mpreferred-stack-boundary=num Attempt to keep the stack boundary aligned to a 2 raised to num byte boundary. If -mpreferred-stack-boundary is not specified, the default is 4 (16 bytes or 128 bits).
-mpreferred-stack-boundary = num尝试保持堆栈边界对齐2到num字节边界。如果未指定-mpreferred-stack-boundary,则默认值为4(16字节或128位)。
https://gcc.gnu.org/onlinedocs/gcc/i386-and-x86-64-Options.html
See the documentation further, if SSE is disabled gcc
may align stack to 8 bytes (and thus violate ABI requirements).
进一步参见文档,如果SSE被禁用,gcc可能会将堆栈对齐到8个字节(因此违反了ABI要求)。
#3
0
You can't control what the compiler will do on the stack. You also can't control the order of variables on the stack. The compiler is also allowed to introduce padding so to better align things in memory (although not inside arrays: this is strictly forbidden). In certain cases it won't even allocate variables on stack, but in registers instead.
您无法控制编译器在堆栈上执行的操作。您也无法控制堆栈上变量的顺序。编译器也允许引入填充,以便更好地对齐内存中的内容(尽管不在数组内部:这是严格禁止的)。在某些情况下,它甚至不会在堆栈上分配变量,而是在寄存器中分配变量。
If you has specific needs on assembly level, do it in assembly.
如果您在装配级别有特定需求,请在装配中执行。