lon*_*ack 0 assembly x86-64 nasm elf
我是汇编新手,从我了解到的情况.code
与 相同.text
,但下面的代码将使用.code
.
segment .data
msg db "hello, world", 0xa
len equ $ - msg
section .text
global _start
_start:
mov edx, len
mov ecx, msg
mov ebx, 1
mov eax, 4
int 0x80
mov ebx, 0
mov eax, 1
int 0x80
Run Code Online (Sandbox Code Playgroud)
nasm -f elf64 -o hello.o hello.s
ld -s -o hello hello.o
hello, world
sed -i s/.text/.code/ ./hello.s
nasm -f elf64 -o hello.o hello.s
ld -s -o hello hello.o
./stack.sh: line 8: 4621 Segmentation fault (core dumped) ./hello
Run Code Online (Sandbox Code Playgroud)
事实上,我不认为这有什么不同。为什么会出现这种情况?
在具有标准工具链 (GNU Binutils ld
) 的 Linux 上,.text
是一个“特殊”节名称,它得到特殊处理(默认情况下具有执行权限),但.code
事实并非如此。(其他特殊部分包括.data
(writeable) 和.bss
(writable nobits),并且所有部分的默认对齐方式 > 1。)
section .text
NASM ELF/Linux 相当于 Windows MASM.code
指令,但这并不意味着Linux 工具可以识别.code
指令或节名称1。
section .code
与 没有什么不同section xyz123
;它只是使用默认值noexec
nowrite
。 请参阅NASM 文档中表格other
底部的条目。
用于readelf -a hello
查看节(链接)和段(程序加载器)属性,明显缺少任何X
地方。
脚注1:事实上,我认为Windows可执行文件仍然使用实际的节名称.text
。至少 GNUobjdump -d
仍然说代码在该.text
部分中。所以MASM.code
指令是切换到该.text
部分的快捷方式。
有趣的事实:如果您将其构建为 32 位代码(您应该这样做,因为它仅使用 32 位int 0x80
系统调用),这确实会“意外”正确运行,就像在从 16 位错误移植时使用的情况section .code
一样MASM 代码到 Linux NASM。
或者,如果您在较旧的内核上运行 64 位代码。
原因是,在没有明确指定PT_GNU_STACK
注释的情况下,内核对 32 位可执行文件使用向后兼容假设,并使用READ_IMPLIES_EXEC
影响每个页面的用法:可执行文件 .data 部分的 Linux 默认行为在 5.4 和 5.9 之间发生了变化?。较旧的内核甚至对于 64 位可执行文件也会这样做,在这种情况下,较新的内核仅使堆栈本身可执行。
添加section .note.GNU-stack noalloc noexec nowrite progbits
到源代码会使其出现应有的段错误,即使构建为 32 位可执行文件时也是如此。( nasm -felf32
/ ld -melf_i386 -o foo foo.o
)。看到这个答案。
另请参阅有关旧情况的项目中包含程序集文件时来自 mmap 的意外 exec 权限。
归档时间: |
|
查看次数: |
378 次 |
最近记录: |