- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv) {
char buff[15];
int auth = 0;
printf("\nEnter password: ");
gets(buff);
if (strcmp(buff, "password") != 0) {
printf("\nAccess denied\n");
} else {
auth = 1;
}
if (auth) {
printf("\nAccess granted\n");
}
return 0;
}
这段代码需要16个字节(用户输入的字符)才能在x86上溢出auth
并打印“Access granted”。在 x64 上,需要 29 个字节才能执行相同的操作。为什么是这样?似乎我的变量之间有一些填充,或者它们之间有其他东西的地址。我不相信这是阴影空间的影响(这是否也适用于 *nix?),因为只保留前 32 个字节 https://en.wikipedia.org/wiki/X86_calling_conventions#Microsoft_x64_calling_convention
请注意,我没有通过任何优化来编译它以避免寄存器内部的东西。
我在 OS X 上使用 GCC 6.2.0。这是 x86 版本的程序集输出:
.cstring
LC0:
.ascii "\12Enter password: \0"
LC1:
.ascii "password\0"
LC2:
.ascii "\12Access denied\0"
LC3:
.ascii "\12Access granted\0"
.text
.globl _main
_main:
LFB1:
pushl %ebp
LCFI0:
movl %esp, %ebp
LCFI1:
pushl %ebx
subl $36, %esp
LCFI2:
call ___x86.get_pc_thunk.bx
L1$pb:
movl $0, -12(%ebp)
subl $12, %esp
leal LC0-L1$pb(%ebx), %eax
pushl %eax
call _printf
addl $16, %esp
subl $12, %esp
leal -27(%ebp), %eax
pushl %eax
call _gets
addl $16, %esp
subl $8, %esp
leal LC1-L1$pb(%ebx), %eax
pushl %eax
leal -27(%ebp), %eax
pushl %eax
call _strcmp
addl $16, %esp
testl %eax, %eax
je L2
subl $12, %esp
leal LC2-L1$pb(%ebx), %eax
pushl %eax
call _puts
addl $16, %esp
jmp L3
L2:
movl $1, -12(%ebp)
L3:
cmpl $0, -12(%ebp)
je L4
subl $12, %esp
leal LC3-L1$pb(%ebx), %eax
pushl %eax
call _puts
addl $16, %esp
L4:
movl $0, %eax
movl -4(%ebp), %ebx
leave
LCFI3:
ret
LFE1:
.section __TEXT,__textcoal_nt,coalesced,pure_instructions
.weak_definition ___x86.get_pc_thunk.bx
.private_extern ___x86.get_pc_thunk.bx
___x86.get_pc_thunk.bx:
LFB2:
movl (%esp), %ebx
ret
LFE2:
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
EH_frame1:
.set L$set$0,LECIE1-LSCIE1
.long L$set$0
LSCIE1:
.long 0
.byte 0x1
.ascii "zR\0"
.byte 0x1
.byte 0x7c
.byte 0x8
.byte 0x1
.byte 0x10
.byte 0xc
.byte 0x5
.byte 0x4
.byte 0x88
.byte 0x1
.align 2
LECIE1:
LSFDE1:
.set L$set$1,LEFDE1-LASFDE1
.long L$set$1
LASFDE1:
.long LASFDE1-EH_frame1
.long LFB1-.
.set L$set$2,LFE1-LFB1
.long L$set$2
.byte 0
.byte 0x4
.set L$set$3,LCFI0-LFB1
.long L$set$3
.byte 0xe
.byte 0x8
.byte 0x84
.byte 0x2
.byte 0x4
.set L$set$4,LCFI1-LCFI0
.long L$set$4
.byte 0xd
.byte 0x4
.byte 0x4
.set L$set$5,LCFI2-LCFI1
.long L$set$5
.byte 0x83
.byte 0x3
.byte 0x4
.set L$set$6,LCFI3-LCFI2
.long L$set$6
.byte 0xc4
.byte 0xc3
.byte 0xc
.byte 0x5
.byte 0x4
.align 2
LEFDE1:
LSFDE3:
.set L$set$7,LEFDE3-LASFDE3
.long L$set$7
LASFDE3:
.long LASFDE3-EH_frame1
.long LFB2-.
.set L$set$8,LFE2-LFB2
.long L$set$8
.byte 0
.align 2
LEFDE3:
.subsections_via_symbols
对于 x64 版本:
.cstring
LC0:
.ascii "\12Enter password: \0"
LC1:
.ascii "password\0"
LC2:
.ascii "\12Access denied\0"
LC3:
.ascii "\12Access granted\0"
.text
.globl _main
_main:
LFB1:
pushq %rbp
LCFI0:
movq %rsp, %rbp
LCFI1:
subq $48, %rsp
movl %edi, -36(%rbp)
movq %rsi, -48(%rbp)
movl $0, -4(%rbp)
leaq LC0(%rip), %rdi
movl $0, %eax
call _printf
leaq -32(%rbp), %rax
movq %rax, %rdi
call _gets
leaq -32(%rbp), %rax
leaq LC1(%rip), %rsi
movq %rax, %rdi
call _strcmp
testl %eax, %eax
je L2
leaq LC2(%rip), %rdi
call _puts
jmp L3
L2:
movl $1, -4(%rbp)
L3:
cmpl $0, -4(%rbp)
je L4
leaq LC3(%rip), %rdi
call _puts
L4:
movl $0, %eax
leave
LCFI2:
ret
LFE1:
.section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support
EH_frame1:
.set L$set$0,LECIE1-LSCIE1
.long L$set$0
LSCIE1:
.long 0
.byte 0x1
.ascii "zR\0"
.byte 0x1
.byte 0x78
.byte 0x10
.byte 0x1
.byte 0x10
.byte 0xc
.byte 0x7
.byte 0x8
.byte 0x90
.byte 0x1
.align 3
LECIE1:
LSFDE1:
.set L$set$1,LEFDE1-LASFDE1
.long L$set$1
LASFDE1:
.long LASFDE1-EH_frame1
.quad LFB1-.
.set L$set$2,LFE1-LFB1
.quad L$set$2
.byte 0
.byte 0x4
.set L$set$3,LCFI0-LFB1
.long L$set$3
.byte 0xe
.byte 0x10
.byte 0x86
.byte 0x2
.byte 0x4
.set L$set$4,LCFI1-LCFI0
.long L$set$4
.byte 0xd
.byte 0x6
.byte 0x4
.set L$set$5,LCFI2-LCFI1
.long L$set$5
.byte 0xc
.byte 0x7
.byte 0x8
.align 3
LEFDE1:
.subsections_via_symbols
最佳答案
我又在考虑这个问题,想起了我在聊天中发给你的编译器标志:
-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).
Warning: When generating code for the x86-64 architecture with SSE extensions disabled, -mpreferred-stack-boundary=3 can be used to keep the stack boundary aligned to 8 byte boundary. Since x86-64 ABI require 16 byte stack alignment, this is ABI incompatible and intended to be used in controlled environment where stack space is important limitation.
因此,15 字节的数组将需要 16 字节的堆栈槽以将其保存在堆栈边界内。
int auth
,假设一个 4 字节的 int
,也需要一个 16 字节的堆栈槽来遵守 gcc
的堆栈边界标志.用gdb
调试程序,我注意到int auth
地址是BSP-0x04
。 BSP-0x04
到 BSP-0x10
正在填充,因此适合堆栈槽。因此,要溢出缓冲区直到到达 int auth
,您需要 15 个字节(缓冲区大小)+ 1 个字节(缓冲区填充)+ 12 个字节(int auth
填充)+ 1 个字节到达 int
。
最后,我跟你提过,我在调试时发现了数组和 int
之间的地址。这可能是内存中残留的一些垃圾:由于程序不关心 int
之前的额外 12 个字节,它可能不会清理它,它可能被用来存储一些内存指针。
下面是 x64 代码程序堆栈的表示。
-------------------------------------------- ------
保存的 RBP
---------------------------------------------- ---- 新的 RBP = 0x7FFFFFFFFDD10
授权
---------------------------------------------- ---- RBP - 0x04 = 0x7FFFFFFFDD0C
auth 12 字节填充
---------------------------------------------- ---- RBP - 0x10 = 0x7FFFFFFFFDD00
buff 1 字节填充
---------------------------------------------- ---- RBP - 0x11 = 0x7FFFFFFFDCFF
增益
---------------------------------------------- ---- RBP - 0x20 = 0x7FFFFFFFDCF0
EDI 的值(value)
---------------------------------------------- ---- RBP - 0x24 = 0x7FFFFFFFDCEC
RSI 值
---------------------------------------------- ---- RBP - 0x30 = 0x7FFFFFFFDCE0 栈顶
关于c - 缓冲区溢出在 x86 上需要 16 个字节,但在 x64 上需要 29 个字节,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41537314/
问题故障解决记录 -- Java RMI Connection refused to host: x.x.x.x .... 在学习JavaRMI时,我遇到了以下情况 问题原因:可
我正在玩 Rank-N-type 并尝试输入 x x .但我发现这两个函数可以以相同的方式输入,这很不直观。 f :: (forall a b. a -> b) -> c f x = x x g ::
这个问题已经有答案了: How do you compare two version Strings in Java? (31 个回答) 已关闭 8 年前。 有谁知道如何在Java中比较两个版本字符串
这个问题已经有答案了: How do the post increment (i++) and pre increment (++i) operators work in Java? (14 个回答)
下面是带有 -n 和 -r 选项的 netstat 命令的输出,其中目标字段显示压缩地址 (127.1/16)。我想知道 netstat 命令是否有任何方法或选项可以显示整个目标 IP (127.1.
我知道要证明 : (¬ ∀ x, p x) → (∃ x, ¬ p x) 证明是: theorem : (¬ ∀ x, p x) → (∃ x, ¬ p x) := begin intro n
x * x 如何通过将其存储在“auto 变量”中来更改?我认为它应该仍然是相同的,并且我的测试表明类型、大小和值显然都是相同的。 但即使 x * x == (xx = x * x) 也是错误的。什么
假设,我们这样表达: someIQueryable.Where(x => x.SomeBoolProperty) someIQueryable.Where(x => !x.SomeBoolProper
我有一个字符串 1234X5678 我使用这个正则表达式来匹配模式 .X|..X|X. 我得到了 34X 问题是为什么我没有得到 4X 或 X5? 为什么正则表达式选择执行第二种模式? 最佳答案 这里
我的一个 friend 在面试时遇到了这个问题 找到使该函数返回真值的 x 值 function f(x) { return (x++ !== x) && (x++ === x); } 面试官
这个问题在这里已经有了答案: 10年前关闭。 Possible Duplicate: Isn't it easier to work with foo when it is represented b
我是 android 的新手,我一直在练习开发一个针对 2.2 版本的应用程序,我需要帮助了解如何将我的应用程序扩展到其他版本,即 1.x、2.3.x、3 .x 和 4.x.x,以及一些针对屏幕分辨率
为什么案例 1 给我们 :error: TypeError: x is undefined on line... //case 1 var x; x.push(x); console.log(x);
代码优先: # CASE 01 def test1(x): x += x print x l = [100] test1(l) print l CASE01 输出: [100, 100
我正在努力温习我的大计算。如果我有将所有项目移至 'i' 2 个空格右侧的函数,我有一个如下所示的公式: (n -1) + (n - 2) + (n - 3) ... (n - n) 第一次迭代我必须
给定 IP 字符串(如 x.x.x.x/x),我如何或将如何计算 IP 的范围最常见的情况可能是 198.162.1.1/24但可以是任何东西,因为法律允许的任何东西。 我要带198.162.1.1/
在我作为初学者努力编写干净的 Javascript 代码时,我最近阅读了 this article当我偶然发现这一段时,关于 JavaScript 中的命名空间: The code at the ve
我正在编写一个脚本,我希望避免污染 DOM 的其余部分,它将是一个用于收集一些基本访问者分析数据的第 3 方脚本。 我通常使用以下内容创建一个伪“命名空间”: var x = x || {}; 我正在
我尝试运行我的test_container_services.py套件,但遇到了以下问题: docker.errors.APIError:500服务器错误:内部服务器错误(“ b'{” message
是否存在这两个 if 语句会产生不同结果的情况? if(x as X != null) { // Do something } if(x is X) { // Do something } 编
我是一名优秀的程序员,十分优秀!