有没有办法在Linux中执行平面二进制映像,使用如下语法:
nasm -f bin -o foo.bin foo.asm
runbinary foo.bin
答案 0 :(得分:9)
Linux内核可以加载几种不同的二进制格式 - ELF只是最常见的,尽管a.out格式也是众所周知的。
支持的二进制格式由哪个binfmt模块加载或编译到内核(它们位于内核配置的Filesystem部分下)来控制。 uClinux BFLT平面格式二进制文件有一个binfmt_flat
非常小 - 它们甚至可以被zlib压缩,这样可以让你的二进制文件更小,所以这可能是一个不错的选择。
看起来nasm本身不支持这种格式,但是如Jim Lewis为ELF所描述的那样,手动添加必要的标题非常容易。有格式here的描述。
答案 1 :(得分:7)
是否有某些原因你不想使用“-f elf”而不是“-f bin”?
我认为Linux不会运行不是ELF格式的二进制文件。我找不到将平面二进制文件转换为ELF的工具,但你可以通过将ELF信息放在foo.asm中来作弊, 使用here描述的技术:
我们可以看一下ELF 规范,和 /usr/include/linux/elf.h,和 标准创建的可执行文件 工具,弄清楚我们的空洞 ELF可执行文件应该是这样的。但, 如果你是不耐烦的类型,你可以 只需使用我在这里提供的那个:
BITS 32 org 0x08048000 ehdr: ; Elf32_Ehdr db 0x7F, "ELF", 1, 1, 1, 0 ; e_ident times 8 db 0 dw 2 ; e_type dw 3 ; e_machine dd 1 ; e_version dd _start ; e_entry dd phdr - $$ ; e_phoff dd 0 ; e_shoff dd 0 ; e_flags dw ehdrsize ; e_ehsize dw phdrsize ; e_phentsize dw 1 ; e_phnum dw 0 ; e_shentsize dw 0 ; e_shnum dw 0 ; e_shstrndx ehdrsize equ $ - ehdr phdr: ; Elf32_Phdr dd 1 ; p_type dd 0 ; p_offset dd $$ ; p_vaddr dd $$ ; p_paddr dd filesize ; p_filesz dd filesize ; p_memsz dd 5 ; p_flags dd 0x1000 ; p_align phdrsize equ $ - phdr _start: ; your program here filesize equ $ - $$
此图片包含ELF标头, 将文件标识为Intel 386 可执行文件,没有节头 表和程序头表 包含一个条目。说入口 指示程序加载器加载 将整个文件存入内存(它是 程序的正常行为 包括其ELF标题和程序 内存图像中的标头表) 从内存地址0x08048000开始 (这是默认地址 要加载的可执行文件,并开始 在_start执行代码,其中 程序后立即出现 标头表。没有.data段,没有 .bss段,没有评论 - 什么都没有 但是必需品。
所以,让我们加入我们的小程序:
; tiny.asm org 0x08048000 ; ; (as above) ; _start: mov bl, 42 xor eax, eax inc eax int 0x80 filesize equ $ - $$
并尝试一下:
$ nasm -f bin -o a.out tiny.asm $ chmod +x a.out $ ./a.out ; echo $? 42
答案 2 :(得分:0)
最低限度,Linux将需要弄清楚可执行文件的格式,并且它将从第一个字节中获取该格式。例如,如果该脚本将是#!,则 shebang 。如果是ELF,则为0x7F'E''L''F'。这些魔术数字将通过查找确定处理程序。
因此,您将需要一个带有公认魔术数字的标头。您可以在 / proc / sys / fs / binfmt_misc 中获得shebang支持的格式的列表。 (很不幸)a little trickier是获取本机二进制格式的列表。
bFLT可能是一个不错的选择。确实,这是一种流行的嵌入式可执行格式。但是您也可以将ELF压得很远。 This article得到了一个ELF可执行文件,最小为45个字节。就是说,您将主要通过手动而不是工具来压缩它。