xKa*_*tsu 0 linux assembly x86-64 elf
我一直在使用 NASM 编写 ELF 二进制文件,并创建了一个打开只读标志的段。运行程序会导致段错误。我在 replit 中测试了该程序,它运行得很好,所以有什么问题?我在 .rodata 部分创建了一个带有 hello world 字符串的常规 NASM hello world 程序,并且运行良好。我用 readelf 检查了二进制文件以确保字符串在只读段中。
我想出的唯一解决方案是在 Rodata 段中设置可执行标志,以便它具有读取/执行权限,但这很糟糕,我希望 Rodata 段是只读的。
这是 ELF-64 hello world 的代码。
; hello.asm
[bits 64]
[org 0x400000]
fileHeader:
db 0x7F, "ELF"
db 2 ; ELF-64
db 1 ; little endian
db 1 ; ELF version
db 0 ; System V ABI
db 0 ; ABI version
db 0, 0, 0, 0, 0, 0, 0 ; unused
dw 2 ; executable object file
dw 0x3E ; x86-64
dd 1 ; ELF version
dq text ; entry point
dq 64 ; program header table offset
dq nullSection - $$ ; section header table offset
dd 0 ; flags
dw 64 ; size of file header
dw 56 ; size of program header
dw 3 ; program header count
dw 64 ; size of section header
dw 4 ; section header count
dw 3 ; section header string table index
nullSegment:
times 56 db 0
textSegment:
dd 1 ; loadable segment
dd 0x4 ; read / execute permissions
dq text - $$ ; segment offset
dq text ; virtual address of segment
dq 0 ; physical address of segment
dq textSize ; size of segment in file
dq textSize ; size of segment in memory
dq 0x1000 ; alignment
rodataSegment:
dd 1 ; loadable segment
dd 0x4 ; read permission (setting this flag to 0x5 causes the program to run just fine)
dq rodata - $$ ; segment offset
dq rodata ; virtual address of segment
dq 0 ; physical address of segment
dq rodataSize ; size of segment in file
dq rodataSize ; size of segment in memory
dq 0x1000 ; alignment
text:
mov rax, 1
mov rdi, 1
mov rsi, message
mov rdx, messageLength
syscall
mov rax, 60
xor rdi, rdi
syscall
textSize equ $ - text
rodata:
message db "Hello world!", 0xA, 0
messageLength equ $ - message
rodataSize equ $ - rodata
stringTable:
db 0
db ".text", 0
db ".rodata", 0
db ".shstrtab", 0
stringTableSize equ $ - stringTable
nullSection:
times 64 db 0
textSection:
dd 1 ; index into string table
dd 1 ; program data
dq 0x6 ; occupies memory & executable
dq text ; virtual address of section
dq text - $$ ; offset of section in file
dq textSize ; size of section in file
dq 0 ; unused
dq 0x1000 ; alignment
dq 0 ; unused
rodataSection:
dd 7 ; index into string table
dd 1 ; program data
dq 0x2 ; occupies memory
dq rodata ; virtual address of section
dq rodata - $$ ; offset of section in file
dq rodataSize ; size of section in file
dq 0 ; unused
dq 0x1000 ; no alignment
dq 0 ; unused
stringTableSection:
dd 15 ; index into string table
dd 3 ; string table
dq 0 ; no attributes
dq stringTable ; virtual address of section
dq stringTable - $$ ; offset of section in file
dq stringTableSize ; size of section in file
dq 0 ; unused
dq 0 ; no alignment
dq 0 ; unused
Run Code Online (Sandbox Code Playgroud)
replitHello.asm: https://hastebin.com/ujanoguveq.properties // 它应该几乎是同一行
这是最小的 nasm hello world 程序。
; helloNasm.asm
section .text
global _start
_start:
mov rax, 1
mov rdi, 1
mov rsi, message
mov rdx, messageLength
syscall
mov rax, 60
xor rdi, rdi
syscall
section .rodata
message db "Hello NASM!", 0xA, 0
messageLength equ $ - message
Run Code Online (Sandbox Code Playgroud)
textSegment:
dd 1 ; loadable segment
dd 0x4 ; read / execute permissions
Run Code Online (Sandbox Code Playgroud)
我假设你的意思0x5是上面的标志。
修复后,我看到以下部分:
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
NULL 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 0
LOAD 0x0000e8 0x00000000004000e8 0x0000000000000000 0x000025 0x000025 R E 0x1000
LOAD 0x00010d 0x000000000040010d 0x0000000000000000 0x00000e 0x00000e R 0x1000
Run Code Online (Sandbox Code Playgroud)
这要求内核mmap在同一地址 ( 0x400000)执行两个s 。这些mmaps 中的第二个映射到第一个,结果如下/proc/$pid/maps:
00400000-00401000 r--p 00000000 fe:02 22548440 /tmp/t
7ffff7ff9000-7ffff7ffd000 r--p 00000000 00:00 0 [vvar]
7ffff7ffd000-7ffff7fff000 r-xp 00000000 00:00 0 [vdso]
7ffffffdd000-7ffffffff000 rw-p 00000000 00:00 0 [stack]
Run Code Online (Sandbox Code Playgroud)
如您所见,程序文本不可执行,因此程序SIGSEGV在第一条指令上运行:
(gdb) run
Starting program: /tmp/t
Program received signal SIGSEGV, Segmentation fault.
0x00000000004000e8 in ?? ()
(gdb) x/i $pc
=> 0x4000e8: mov $0x1,%eax
Run Code Online (Sandbox Code Playgroud)
要解决此问题,您必须将其中一个段移动到不同的页面(正如 Jester 正确指出的那样)。
另请注意,部分是完全不必要的(只有部分很重要)。特别是A X在该.text部分中设置标志对任何事情都没有影响。
| 归档时间: |
|
| 查看次数: |
61 次 |
| 最近记录: |