Error[8]: Undefined offset: 1, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

有关C语言中字符串入栈的理解 C语言中字符串的入栈

写在前面
对于C语言中变量入栈的顺序实际上需要具体情况具体分析,不同 *** 作系统下的编译器可能对此有不同的解释,即使对于同一个C的编译器而言,参数设定的不同也会导致编译器调整局部变量的入栈顺序,例如一种栈溢出的防护方案下,int类型的变量可能始终是最后入栈的。

本次实践利用的编译器版本是Windows下的64位编译器: x86_64-pc-cygwin-version 11.2.0

我们在test.c中编写如下代码,申请一个局部的字符数组,然后退出。

#include 
int main() {
    char str[5] = "abcdef";
    return 0;
}

在命令行编译输出汇编代码:

gcc -S test.c -o test.asm

得到如下的汇编代码(AT&T)

	.file	"test.c"
	.text
	.def	__main;	.scl	2;	.type	32;	.endef
	.globl	main
	.def	main;	.scl	2;	.type	32;	.endef
	.seh_proc	main
main:
	pushq	%rbp
	.seh_pushreg	%rbp
	movq	%rsp, %rbp
	.seh_setframe	%rbp, 0
	subq	, %rsp
	.seh_stackalloc	48
	.seh_endprologue
	call	__main
	movl	84234849, -7(%rbp)
	movw	213, -3(%rbp)
	movb	[+++], -1(%rbp)
	movl	[+++], %eax
	addq	, %rsp
	popq	%rbp
	ret
	.seh_endproc
	.ident	"GCC: (GNU) 11.2.0"

代码分析:

main之前的内容在说明函数入口与文件信息,暂时不讨论

.seh_*相关的伪指令是Windows提供的一套结构异常化处理的例程,可以暂时不讨论。

不过从指令名字上我们其实也能简单地了解它们在做什么,例如seh_stackalloc 48就是为堆栈段分配了48字节的空间。

详情可以查阅:https://sourceware.org/legacy-ml/binutils/2009-08/msg00193.html

抛开上述影响因素后,我们来看我们关心的部分,call __main指令之后的内容:

movl $1684234849, -5(%rbp)

转16进制后,左边立即数为 6463 6261H,即“abcd”的端序

movw $26213, -3(%rbp)

转16进制后,左边立即数为66 65H,即“ef”的端序

movb $0, -1(%rbp)

将‘’压入栈

因此我们的栈空间为

总结一下:将字符串压栈时,连续储存,开头的字符对应低地址,结尾字符对应高地址。

从这个原理上我们再理解一下熟知的缓冲区溢出攻击,如果攻击者输入的字符串大于申请的缓冲区长度,末尾多出来的字符串在栈内会向高地址延伸,覆盖掉栈中原有的数据。

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 165, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
Error[8]: Undefined offset: 2, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

有关C语言中字符串入栈的理解 C语言中字符串的入栈

写在前面
对于C语言中变量入栈的顺序实际上需要具体情况具体分析,不同 *** 作系统下的编译器可能对此有不同的解释,即使对于同一个C的编译器而言,参数设定的不同也会导致编译器调整局部变量的入栈顺序,例如一种栈溢出的防护方案下,int类型的变量可能始终是最后入栈的。

本次实践利用的编译器版本是Windows下的64位编译器: x86_64-pc-cygwin-version 11.2.0

我们在test.c中编写如下代码,申请一个局部的字符数组,然后退出。

#include 
int main() {
    char str[5] = "abcdef";
    return 0;
}

在命令行编译输出汇编代码:

gcc -S test.c -o test.asm

得到如下的汇编代码(AT&T)

	.file	"test.c"
	.text
	.def	__main;	.scl	2;	.type	32;	.endef
	.globl	main
	.def	main;	.scl	2;	.type	32;	.endef
	.seh_proc	main
main:
	pushq	%rbp
	.seh_pushreg	%rbp
	movq	%rsp, %rbp
	.seh_setframe	%rbp, 0
	subq	, %rsp
	.seh_stackalloc	48
	.seh_endprologue
	call	__main
	movl	84234849, -7(%rbp)
	movw	213, -3(%rbp)
	movb	, -1(%rbp)
	movl	[+++], %eax
	addq	, %rsp
	popq	%rbp
	ret
	.seh_endproc
	.ident	"GCC: (GNU) 11.2.0"

代码分析:

main之前的内容在说明函数入口与文件信息,暂时不讨论

.seh_*相关的伪指令是Windows提供的一套结构异常化处理的例程,可以暂时不讨论。

不过从指令名字上我们其实也能简单地了解它们在做什么,例如seh_stackalloc 48就是为堆栈段分配了48字节的空间。

详情可以查阅:https://sourceware.org/legacy-ml/binutils/2009-08/msg00193.html

抛开上述影响因素后,我们来看我们关心的部分,call __main指令之后的内容:

movl $1684234849, -5(%rbp)

转16进制后,左边立即数为 6463 6261H,即“abcd”的端序

movw $26213, -3(%rbp)

转16进制后,左边立即数为66 65H,即“ef”的端序

movb $0, -1(%rbp)

将‘’压入栈

因此我们的栈空间为

总结一下:将字符串压栈时,连续储存,开头的字符对应低地址,结尾字符对应高地址。

从这个原理上我们再理解一下熟知的缓冲区溢出攻击,如果攻击者输入的字符串大于申请的缓冲区长度,末尾多出来的字符串在栈内会向高地址延伸,覆盖掉栈中原有的数据。

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 165, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
有关C语言中字符串入栈的理解_随笔_内存溢出

有关C语言中字符串入栈的理解

有关C语言中字符串入栈的理解,第1张

有关C语言中字符串入栈的理解 C语言中字符串的入栈

写在前面
对于C语言中变量入栈的顺序实际上需要具体情况具体分析,不同 *** 作系统下的编译器可能对此有不同的解释,即使对于同一个C的编译器而言,参数设定的不同也会导致编译器调整局部变量的入栈顺序,例如一种栈溢出的防护方案下,int类型的变量可能始终是最后入栈的。

本次实践利用的编译器版本是Windows下的64位编译器: x86_64-pc-cygwin-version 11.2.0

我们在test.c中编写如下代码,申请一个局部的字符数组,然后退出。

#include 
int main() {
    char str[5] = "abcdef";
    return 0;
}

在命令行编译输出汇编代码:

gcc -S test.c -o test.asm

得到如下的汇编代码(AT&T)

	.file	"test.c"
	.text
	.def	__main;	.scl	2;	.type	32;	.endef
	.globl	main
	.def	main;	.scl	2;	.type	32;	.endef
	.seh_proc	main
main:
	pushq	%rbp
	.seh_pushreg	%rbp
	movq	%rsp, %rbp
	.seh_setframe	%rbp, 0
	subq	, %rsp
	.seh_stackalloc	48
	.seh_endprologue
	call	__main
	movl	84234849, -7(%rbp)
	movw	213, -3(%rbp)
	movb	, -1(%rbp)
	movl	, %eax
	addq	, %rsp
	popq	%rbp
	ret
	.seh_endproc
	.ident	"GCC: (GNU) 11.2.0"

代码分析:

main之前的内容在说明函数入口与文件信息,暂时不讨论

.seh_*相关的伪指令是Windows提供的一套结构异常化处理的例程,可以暂时不讨论。

不过从指令名字上我们其实也能简单地了解它们在做什么,例如seh_stackalloc 48就是为堆栈段分配了48字节的空间。

详情可以查阅:https://sourceware.org/legacy-ml/binutils/2009-08/msg00193.html

抛开上述影响因素后,我们来看我们关心的部分,call __main指令之后的内容:

movl $1684234849, -5(%rbp)

转16进制后,左边立即数为 6463 6261H,即“abcd”的端序

movw $26213, -3(%rbp)

转16进制后,左边立即数为66 65H,即“ef”的端序

movb $0, -1(%rbp)

将‘’压入栈

因此我们的栈空间为

总结一下:将字符串压栈时,连续储存,开头的字符对应低地址,结尾字符对应高地址。

从这个原理上我们再理解一下熟知的缓冲区溢出攻击,如果攻击者输入的字符串大于申请的缓冲区长度,末尾多出来的字符串在栈内会向高地址延伸,覆盖掉栈中原有的数据。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/4752202.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-09
下一篇 2022-11-08

发表评论

登录后才能评论

评论列表(0条)

保存