【问题标题】:Get rid of useless string constants from assembly source file in a compiled binary从已编译二进制文件中的汇编源文件中删除无用的字符串常量
【发布时间】:2021-11-03 19:58:57
【问题描述】:

我正在使用 NASM 版本 2.14.02 和 GNU ld 2.34 在 64 位 Linux 上编译程序集文件(例如,hello world)。

我想(基本上只是为了好玩)生成一个尽可能小的可执行文件。但是,在实用程序生成的可执行文件中,有一些字符串对于可执行文件绝对没有意义(如源文件的名称、节名等)。我该如何摆脱它们?

这是我的工作:

$ cat hello_world_32.s
SECTION .rodata
    msg:        db 'Hello world!',0xA
    msg_len:    equ $-msg

SECTION .text
    global _start

_start:
    mov eax, 4
    mov ebx, 1
    mov ecx, msg
    mov edx, msg_len
    int 0x80

    mov eax, 1
    xor ebx, ebx
    int 0x80
$ nasm -f elf32 -o hello_world.o hello_world_32.s
$ ld --nmagic -m elf_i386 -o hello_world hello_world.o
$ ./hello_world              
Hello world!
$ grep hello_world_32.s hello_world
Binary file hello_world matches
$ grep .text hello_world
Binary file hello_world matches
$ grep .rodata hello_world
Binary file hello_world matches
$

这是xxd hello_world的输出:

00000000: 7f45 4c46 0101 0100 0000 0000 0000 0000  .ELF............
00000010: 0200 0300 0100 0000 6080 0408 3400 0000  ........`...4...
00000020: 9001 0000 0000 0000 3400 2000 0100 2800  ........4. ...(.
00000030: 0600 0500 0100 0000 6000 0000 6080 0408  ........`...`...
00000040: 6080 0408 2d00 0000 2d00 0000 0500 0000  `...-...-.......
00000050: 1000 0000 0000 0000 0000 0000 0000 0000  ................
00000060: b804 0000 00bb 0200 0000 b980 8004 08ba  ................
00000070: 0d00 0000 cd80 b801 0000 0031 dbcd 8000  ...........1....
00000080: 4865 6c6c 6f20 776f 726c 6421 0a00 0000  Hello world!....
00000090: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000000a0: 0000 0000 6080 0408 0000 0000 0300 0100  ....`...........
000000b0: 0000 0000 8080 0408 0000 0000 0300 0200  ................
000000c0: 0100 0000 0000 0000 0000 0000 0400 f1ff  ................
000000d0: 1200 0000 8080 0408 0000 0000 0000 0200  ................
000000e0: 1600 0000 0d00 0000 0000 0000 0000 f1ff  ................
000000f0: 2300 0000 6080 0408 0000 0000 1000 0100  #...`...........
00000100: 1e00 0000 8d90 0408 0000 0000 1000 0200  ................
00000110: 2a00 0000 8d90 0408 0000 0000 1000 0200  *...............
00000120: 3100 0000 9090 0408 0000 0000 1000 0200  1...............
00000130: 0068 656c 6c6f 5f77 6f72 6c64 5f33 322e  .hello_world_32.
00000140: 7300 6d73 6700 6d73 675f 6c65 6e00 5f5f  s.msg.msg_len.__
00000150: 6273 735f 7374 6172 7400 5f65 6461 7461  bss_start._edata
00000160: 005f 656e 6400 002e 7379 6d74 6162 002e  ._end...symtab..
00000170: 7374 7274 6162 002e 7368 7374 7274 6162  strtab..shstrtab
00000180: 002e 7465 7874 002e 726f 6461 7461 0000  ..text..rodata..
00000190: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000001a0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
000001b0: 0000 0000 0000 0000 1b00 0000 0100 0000  ................
000001c0: 0600 0000 6080 0408 6000 0000 1f00 0000  ....`...`.......
000001d0: 0000 0000 0000 0000 1000 0000 0000 0000  ................
000001e0: 2100 0000 0100 0000 0200 0000 8080 0408  !...............
000001f0: 8000 0000 0d00 0000 0000 0000 0000 0000  ................
00000200: 0400 0000 0000 0000 0100 0000 0200 0000  ................
00000210: 0000 0000 0000 0000 9000 0000 a000 0000  ................
00000220: 0400 0000 0600 0000 0400 0000 1000 0000  ................
00000230: 0900 0000 0300 0000 0000 0000 0000 0000  ................
00000240: 3001 0000 3600 0000 0000 0000 0000 0000  0...6...........
00000250: 0100 0000 0000 0000 1100 0000 0300 0000  ................
00000260: 0000 0000 0000 0000 6601 0000 2900 0000  ........f...)...
00000270: 0000 0000 0000 0000 0100 0000 0000 0000  ................

如何去除可执行文件中不需要的字符串?是否有某种方法可以只编译指令而忽略所有其他指令?

【问题讨论】:

  • 你试过链接器的-s开关吗?
  • nasm -fbin 进行“平面二进制”输出,没有围绕它的 ELF 元数据。如果您在 .asm 文件中使用db 手动定义 ELF 标头(并在一些无关字段中塞入一些机器代码),您可以制作一个非常小的静态 ELF 二进制文件。 muppetlabs.com/~breadbox/software/tiny/teensy.html
  • 我不是 elf 格式方面的专家,但我想说它们是正确加载程序所必需的。
  • 在编程中,准确地知道你到底想要什么是非常重要的,尤其是当你告诉计算机该做什么时。在与其他人类程序员交流时,这也是一件有用的事情,他们往往会准确地注意到你所说的话。
  • 不管怎样,你可能想试试FASM;它可以输出完整的 ELF 可执行文件(不仅仅是 .o),没有任何部分只是 ELF 程序头。所以它可以运行,但是在上面使用 GDB 很痛苦。但它很小。

标签: assembly nasm ld


【解决方案1】:

有些字符串对于 可执行文件(如源文件名、节名等 其他)。

确实,那些字符串 对可执行文件本身毫无意义,但它们对于程序的加载器却是必不可少的。转储中可见的部分和符号名称不是在程序的源文本中定义的字符串,它们是ELF specification 所需的元数据。程序段 .data.text 的名称写在另一个称为 .shstrtab 的特殊段中。这个特殊部分在加载时被丢弃。

如果您使用nasm -f bin 而不是nasm -f elf32 组装,您可以摆脱所有元数据,但您将无法再使用./hello_world 执行您的程序。您必须编写另一个程序(您自己的加载程序)来分配内存,将二进制文件复制到内存并在其入口点跳转。

【讨论】:

  • 文本部分的名称对于要加载的程序完全相关,仅适用于 objdumpgdb 之类的内容来查找 .text 部分。 ELF 节标头与 ELF program 标头分开,ELF program 标头定义了内核映射到 execve 上的内存的程序 segments。这就是为什么 muppetlabs.com/~breadbox/software/tiny/teensy.html 末尾的最小可执行文件在其手动组装的 ELF 标头中不包含任何 db 字符串,实际上根本没有 ELF 节标头,就像 FASM 的静态二进制输出模式一样.
  • What's the difference of section and segment in ELF file format。如果有办法从现有二进制文件中删除节标题,则 IDK;也许是stripobjcopy
猜你喜欢
  • 2011-02-21
  • 1970-01-01
  • 2017-12-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-30
相关资源
最近更新 更多