Linux下NASM小型x86 ELF二进制可修改预留内存问题排查
解决NASM极简ELF中.bss段写入段错误的问题
核心原因
你用的极简ELF(类似teensy的小二进制)默认程序头可能没正确处理.bss段:要么加载器没为.bss分配可写内存,要么内存权限被设为只读,导致写入操作触发段错误。
具体修复步骤
修正ELF程序头的内存大小与权限
极简ELF通常只有一个PT_LOAD程序头,必须确保:p_flags包含PF_W(可写)权限,一般设为7(PF_R | PF_W | PF_X)p_memsz要包含.bss段的大小,因为.bss在二进制中是0长度,加载器需要知道要额外分配多少内存并清零。
示例程序头修改:
phdr: dd 1 ; PT_LOAD dd 0 ; 文件偏移 dd $$ ; 虚拟地址 dd $$ ; 物理地址 dd filesize ; 文件大小(.text+.data的总长度) dd filesize + 342 ; 内存大小 = 文件大小 + .bss的19*18字节 dd 7 ; 权限:读+写+执行 dd 0x1000 ; 对齐正确声明.bss段
单独声明.bss段,不要和.text/.data混放:section .text ; 你的代码、预定义字符串等放在这里 ... section .bss printable: resb 19*18 ; 预留342字节的可写内存确保地址访问正确
如果是静态链接的绝对地址,直接用printable符号即可;如果是位置无关代码,需要通过基址计算(比如用ebx获取程序基址后偏移)。示例写入代码:; 把printable缓冲区填满字符'X' mov edi, printable mov ecx, 19*18 mov al, 'X' rep stosb ; 打印缓冲区内容 mov eax, 4 mov ebx, 1 mov ecx, printable mov edx, 19*18 int 0x80
关键说明
- 原错误中操作
string1也段错误,大概率是因为string1放在了只读的.text段里,.text段默认权限是执行+只读,写入自然会报错——只有.bss和.data段应该设为可写。 - 极简ELF没有链接器帮你处理段属性,必须手动在程序头中指定内存权限和大小,加载器才会正确分配可写的.bss内存。
内容的提问来源于stack exchange,提问作者Alexander B
相关产品推荐
相关产品推荐

