微小的"手动"创建ELF赋予段错误 [英] Tiny "manually" created ELF giving segmentation fault
问题描述
从的移植可执行的和Windows产品,我想创建一个小的 ELF 可执行文件的 NASM 的中的的Linux(Ubuntu的AMD64) 的。我的小件code看起来是这样的:
位64
;其中的可执行文件链接默认的虚拟地址
_START_VAD EQU为0x400000;在这里,我通过写字节的头字节
ELF_HEADER:
.ident_magic DB 0x7F的,ELF
.ident_class DB 2
.ident_data DB 1
.ident_version DB 1
.ident_osabi 0分贝
.ident_abiversion 0分贝
;垫用零,直到我们有标识符16字节
倍16 - $ + ELF_HEADER 0分贝
.object_type DW 2
功能的机器DW 0x3E的
.version DD 1
.entry_point DQ _START_VAD + START
.progr_header DQ PROGRAM_HEADER
.sect_header DQ SECTIONS_HEADER
.proc_flags DD 0
.header_size DW ELF_HEADER_END - ELF_HEADER
.progr_header_size DW 56
.progr_header_entries DW 3
.sect_header_size DW 64
.sect_header_entries DW 4
.sect_header_index DW 3
ELF_HEADER_END:PROGRAM_HEADER:
HEADER_SEGMENT_HEADER:
HEADER_SEGMENT_SIZE EQU PROGRAM_HEADER_END - PROGRAM_HEADER
.header_segment_type DD 6
.header_segment_flag DD为0x1 |为0x4
.header_segment_offs DQ PROGRAM_HEADER
.header_segment_vadr DQ _START_VAD + PROGRAM_HEADER
.header_segment_padr DQ _START_VAD + PROGRAM_HEADER
.header_segment_file DQ HEADER_SEGMENT_SIZE
.header_segment_mems DQ HEADER_SEGMENT_SIZE
.header_segment_alig DQ 8 INTE preTER_SEGMENT_HEADER:
INTERP_SEGMENT_SIZE EQU INTER preTER_SEGMENT_END - INTER preTER_SEGMENT
.interp_segment_type DD 3
.interp_segment_flag DD为0x4
.interp_segment_offs DQ INTER preTER_SEGMENT
.interp_segment_vadr DQ _START_VAD + INTER preTER_SEGMENT
.interp_segment_padr DQ _START_VAD + INTER preTER_SEGMENT
.interp_segment_file DQ INTERP_SEGMENT_SIZE
.interp_segment_mems DQ INTERP_SEGMENT_SIZE
.interp_segment_alig DQ 1 code_SEGMENT_HEADER:
code_SEGMENT_SIZE EQU START_END - ELF_HEADER
。code_segment_type DD 1
。code_segment_flag DD为0x1 |为0x4
。code_segment_offs DQ 0
。code_segment_vadr DQ _START_VAD
。code_segment_padr DQ _START_VAD
。code_segment_file DQ code_SEGMENT_SIZE
。code_segment_mems DQ code_SEGMENT_SIZE
。code_segment_alig DQ 0x200000
PROGRAM_HEADER_END:INTER preTER_SEGMENT:
.inte preter_path分贝/lib64/ld-linux-x86-64.so.2,0
INTER preTER_SEGMENT_END:开始:
MOV RAX,1; SYS_WRITE
MOV RDI,1;标准输出
MOV RSI,_START_VAD +消息;消息地址
MOV RDX,长度;消息字符串长度
系统调用 MOV RAX,60; sys_exit
MOV RDI,0;返回0(成功)
系统调用 信息:
DB你好,世界!,0x0A的;消息和换行符
长度:EQU $ -message;消息长度计算
START_END:SECTIONS_STRING_TABLE:
NULL_SECTION_NAME:0分贝
STR_TABLE_SECTION_NAME:DB.shstrtab,0
INTERP_SECTION_NAME:DB.interp,0
TEXT_SECTION_NAME:DB的.text,0
SECTIONS_STRING_TABLE_END:SECTIONS_HEADER:
RESERVED_SECTION:
.reserved_sh_name DD 0
.reserved_type DD 0
.reserved_flags DQ 0
.reserved_vaddr DQ 0
.reserved_offs DQ 0
.reserved_size DQ 0
.reserved_link DD 0
.reserved_info DD 0
.reserved_alig DQ 0
.reserved_ents DQ 0INTER preTER_SECTION:
.reserved_sh_name DD INTERP_SECTION_NAME - SECTIONS_STRING_TABLE
.reserved_type DD 1
.reserved_flags DQ 0X2
.reserved_vaddr DQ _START_VAD + INTER preTER_SEGMENT
.reserved_offs DQ INTER preTER_SEGMENT
.reserved_size DQ INTER preTER_SEGMENT_END - INTER preTER_SEGMENT
.reserved_link DD 0
.reserved_info DD 0
.reserved_alig DQ 1
.reserved_ents DQ 0TEXT_SECTION:
.reserved_sh_name DD TEXT_SECTION_NAME - SECTIONS_STRING_TABLE
.reserved_type DD 1
.reserved_flags DQ 0X2 |为0x4
.reserved_vaddr DQ _START_VAD + START
.reserved_offs DQ START
.reserved_size DQ START_END - START
.reserved_link DD 0
.reserved_info DD 0
.reserved_alig DQ 16
.reserved_ents DQ 0 STRINGTABLE_SECTION:
.reserved_sh_name DD STR_TABLE_SECTION_NAME - SECTIONS_STRING_TABLE
.reserved_type DD 3
.reserved_flags DQ 0
.reserved_vaddr DQ 0
.reserved_offs DQ SECTIONS_STRING_TABLE
.reserved_size DQ SECTIONS_STRING_TABLE_END - SECTIONS_STRING_TABLE
.reserved_link DD 0
.reserved_info DD 0
.reserved_alig DQ 1
.reserved_ents DQ 0
SECTIONS_HEADER_END:
我这个转换与NASM的ELF文件,并得到这个信息的 READELF
魔术:7F 45 4C 46 02 01 01 00 00 00 00 00 00 00 00 00
类别:ELF64
数据:2的补,小尾数
版本:1(电流)
OS / ABI:UNIX - 系统V
ABI版本:0
类型:EXEC(可执行文件)
机床:Advanced Micro Devices公司X86-64
版本:为0x1
入口地址:0x400104
程序头开始:64(字节到文件)
节头的开始:363(字节到文件)
标志:为0x0
这个头的大小:64(字节)
程序头的尺寸:56(字节)
程序头数:3
节头的大小:64(字节)
节头数:4
节头字符串表指数:3节标题:
[NR名称类型地址偏移
大小EntSize标志链接信息对齐
[0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[1] .interp PROGBITS 00000000004000e8 000000e8
000000000000001c 0000000000000000 A 0 0 1
[2]的.text PROGBITS 0000000000400104 00000104
000000000000004e 0000000000000000 AX 0 0 16
[3] .shstrtab STRTAB 0000000000000000 00000152
0000000000000019 0000000000000000 0 0 1
关键标志:
W(写),A(ALLOC),X(执行),M(合并),S(串),L(大)
I(信息),L(链接顺序),G(组),T(TLS),E(排除),X(未知)
O(额外OS处理所需)O(OS特定),P(处理器专用)还有在这个文件中没有节组。程序头:
型胶印VirtAddr PhysAddr
FileSiz MemSiz标记对齐
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000000a8 0x00000000000000a8 - [R E 8
INTERP 0x00000000000000e8 0x00000000004000e8 0x00000000004000e8
0x000000000000001c 0x000000000000001c,R 1
[请求程序间preTER:/lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x0000000000000152 0x0000000000000152řË200000 科段映射:
段段...
00
01 .interp
02 .interp的.text有此文件中没有动态部分。还有在这个文件中没有重定位。还有在这个文件中没有放卷部分。没有此文件中的版本信息。
其中
我不知道,如果是正确的,特别是LOAD段和它的大小。
当我运行此我得到分段错误(核心转储)
。调试器会告诉我更多:
警告:在0x7ffff7ffa000在加入符号文件系统提供的DSO没有发现任何可装入节计划接收信号SIGSEGV,分割过错。
0x00007ffff7de5be2在?? ()从/lib64/ld-linux-x86-64.so.2
(GDB)
我不知道是什么段或部分缺失或什么偏移/地址是错误的。也许有人在ELF和Linux装载机更多的经验会给我轻轻一推,因为我真的卡住了。
我不知道是什么段或部分缺失或什么偏移/地址是错误的。
块引用>您的二进制文件
PT_INTERP
段,这让Linux内核认为这是一个动态链接二进制文件。但它没有PT_DYNAMIC
段,其中LD-linux的
预计。删除所有引用
INTER preTER_ {段,SECTION}
和调整程序标题和章节的匝数这个变成一个完全静态二进制,即工作:NASM t.s
./t
你好,世界!readelf -lŧELF文件类型是EXEC(可执行文件)
切入点0x4000b0
有2个节目标题,开始偏移64程序头:
型胶印VirtAddr PhysAddr
FileSiz MemSiz标记对齐
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x0000000000000070 0x0000000000000070 - [R E 8
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x00000000000000fe 0x00000000000000feřË200000 科段映射:
段段...
00
01的.textComing from Portable Executable and Windows I am trying to create a tiny ELF executable with NASM in Linux (Ubuntu AMD64). My little piece of code looks like this:
BITS 64 ; The default virtual address where the executable is linked _START_VAD equ 0x400000 ; Here I write the header byte by byte ELF_HEADER: .ident_magic db 0x7f, "ELF" .ident_class db 2 .ident_data db 1 .ident_version db 1 .ident_osabi db 0 .ident_abiversion db 0 ; Pad with zeros until we have 16 bytes for the identifier times 16-$+ELF_HEADER db 0 .object_type dw 2 .machine dw 0x3e .version dd 1 .entry_point dq _START_VAD + START .progr_header dq PROGRAM_HEADER .sect_header dq SECTIONS_HEADER .proc_flags dd 0 .header_size dw ELF_HEADER_END - ELF_HEADER .progr_header_size dw 56 .progr_header_entries dw 3 .sect_header_size dw 64 .sect_header_entries dw 4 .sect_header_index dw 3 ELF_HEADER_END: PROGRAM_HEADER: HEADER_SEGMENT_HEADER: HEADER_SEGMENT_SIZE equ PROGRAM_HEADER_END - PROGRAM_HEADER .header_segment_type dd 6 .header_segment_flag dd 0x1 | 0x4 .header_segment_offs dq PROGRAM_HEADER .header_segment_vadr dq _START_VAD + PROGRAM_HEADER .header_segment_padr dq _START_VAD + PROGRAM_HEADER .header_segment_file dq HEADER_SEGMENT_SIZE .header_segment_mems dq HEADER_SEGMENT_SIZE .header_segment_alig dq 8 INTEPRETER_SEGMENT_HEADER: INTERP_SEGMENT_SIZE equ INTERPRETER_SEGMENT_END - INTERPRETER_SEGMENT .interp_segment_type dd 3 .interp_segment_flag dd 0x4 .interp_segment_offs dq INTERPRETER_SEGMENT .interp_segment_vadr dq _START_VAD + INTERPRETER_SEGMENT .interp_segment_padr dq _START_VAD + INTERPRETER_SEGMENT .interp_segment_file dq INTERP_SEGMENT_SIZE .interp_segment_mems dq INTERP_SEGMENT_SIZE .interp_segment_alig dq 1 CODE_SEGMENT_HEADER: CODE_SEGMENT_SIZE equ START_END - ELF_HEADER .code_segment_type dd 1 .code_segment_flag dd 0x1 | 0x4 .code_segment_offs dq 0 .code_segment_vadr dq _START_VAD .code_segment_padr dq _START_VAD .code_segment_file dq CODE_SEGMENT_SIZE .code_segment_mems dq CODE_SEGMENT_SIZE .code_segment_alig dq 0x200000 PROGRAM_HEADER_END: INTERPRETER_SEGMENT: .intepreter_path db "/lib64/ld-linux-x86-64.so.2", 0 INTERPRETER_SEGMENT_END: START: mov rax, 1 ; sys_write mov rdi, 1 ; stdout mov rsi, _START_VAD + message ; message address mov rdx, length ; message string length syscall mov rax, 60 ; sys_exit mov rdi, 0 ; return 0 (success) syscall message: db 'Hello, world!',0x0A ; message and newline length: equ $-message ; message length calculation START_END: SECTIONS_STRING_TABLE: NULL_SECTION_NAME: db 0 STR_TABLE_SECTION_NAME: db ".shstrtab", 0 INTERP_SECTION_NAME: db ".interp", 0 TEXT_SECTION_NAME: db ".text", 0 SECTIONS_STRING_TABLE_END: SECTIONS_HEADER: RESERVED_SECTION: .reserved_sh_name dd 0 .reserved_type dd 0 .reserved_flags dq 0 .reserved_vaddr dq 0 .reserved_offs dq 0 .reserved_size dq 0 .reserved_link dd 0 .reserved_info dd 0 .reserved_alig dq 0 .reserved_ents dq 0 INTERPRETER_SECTION: .reserved_sh_name dd INTERP_SECTION_NAME - SECTIONS_STRING_TABLE .reserved_type dd 1 .reserved_flags dq 0x2 .reserved_vaddr dq _START_VAD + INTERPRETER_SEGMENT .reserved_offs dq INTERPRETER_SEGMENT .reserved_size dq INTERPRETER_SEGMENT_END - INTERPRETER_SEGMENT .reserved_link dd 0 .reserved_info dd 0 .reserved_alig dq 1 .reserved_ents dq 0 TEXT_SECTION: .reserved_sh_name dd TEXT_SECTION_NAME - SECTIONS_STRING_TABLE .reserved_type dd 1 .reserved_flags dq 0x2 | 0x4 .reserved_vaddr dq _START_VAD + START .reserved_offs dq START .reserved_size dq START_END - START .reserved_link dd 0 .reserved_info dd 0 .reserved_alig dq 16 .reserved_ents dq 0 STRINGTABLE_SECTION: .reserved_sh_name dd STR_TABLE_SECTION_NAME - SECTIONS_STRING_TABLE .reserved_type dd 3 .reserved_flags dq 0 .reserved_vaddr dq 0 .reserved_offs dq SECTIONS_STRING_TABLE .reserved_size dq SECTIONS_STRING_TABLE_END - SECTIONS_STRING_TABLE .reserved_link dd 0 .reserved_info dd 0 .reserved_alig dq 1 .reserved_ents dq 0 SECTIONS_HEADER_END:
I convert this into an ELF file with NASM and get this info with READELF:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x400104 Start of program headers: 64 (bytes into file) Start of section headers: 363 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 3 Size of section headers: 64 (bytes) Number of section headers: 4 Section header string table index: 3 Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [ 0] NULL 0000000000000000 00000000 0000000000000000 0000000000000000 0 0 0 [ 1] .interp PROGBITS 00000000004000e8 000000e8 000000000000001c 0000000000000000 A 0 0 1 [ 2] .text PROGBITS 0000000000400104 00000104 000000000000004e 0000000000000000 AX 0 0 16 [ 3] .shstrtab STRTAB 0000000000000000 00000152 0000000000000019 0000000000000000 0 0 1 Key to Flags: W (write), A (alloc), X (execute), M (merge), S (strings), l (large) I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown) O (extra OS processing required) o (OS specific), p (processor specific) There are no section groups in this file. Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040 0x00000000000000a8 0x00000000000000a8 R E 8 INTERP 0x00000000000000e8 0x00000000004000e8 0x00000000004000e8 0x000000000000001c 0x000000000000001c R 1 [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000 0x0000000000000152 0x0000000000000152 R E 200000 Section to Segment mapping: Segment Sections... 00 01 .interp 02 .interp .text There is no dynamic section in this file. There are no relocations in this file. There are no unwind sections in this file. No version information found in this file.
of which I am not sure if is correct, specially the LOAD segment and its size. When I run this I get
Segmentation Fault (core dumped)
. A debugger will tell me more:warning: no loadable sections found in added symbol-file system-supplied DSO at 0x7ffff7ffa000 Program received signal SIGSEGV, Segmentation fault. 0x00007ffff7de5be2 in ?? () from /lib64/ld-linux-x86-64.so.2 (gdb)
I don't know what segments or sections are missing or what offsets/addresses are wrong. Maybe someone with more experience in ELF and Linux loaders will give me a little push because I am really stuck.
解决方案I don't know what segments or sections are missing or what offsets/addresses are wrong.
Your binary has
PT_INTERP
segment, which makes the Linux kernel think it's a dynamically linked binary. But it has noPT_DYNAMIC
segment, whichld-linux
expects.Removing all references to
INTERPRETER_{SEGMENT,SECTION}
and adjusting number of program headers and sections turns this into a fully-static binary, that works:nasm t.s ./t Hello, world! readelf -l t Elf file type is EXEC (Executable file) Entry point 0x4000b0 There are 2 program headers, starting at offset 64 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040 0x0000000000000070 0x0000000000000070 R E 8 LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000 0x00000000000000fe 0x00000000000000fe R E 200000 Section to Segment mapping: Segment Sections... 00 01 .text
这篇关于微小的"手动"创建ELF赋予段错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!