ELF文件字符串编码机制及明文密码演示异常问题咨询
解答:编译器优化导致的字符串片段与指令混叠,及ELF字符串编码解析
嘿,我来帮你拆解这两个问题!
一、为什么hexdump里出现了奇怪的字符?
你看到的那些“H”“E”之类的“奇怪字符”,其实不是字符串本身的问题,而是编译器做了字符串常量的寄存器加载优化,导致字符串片段和汇编指令的机器码混在了一起,被grep误打误撞匹配显示出来了。
具体来说,你的字符串"a big refreshing lemonade"长度是23字节,在x86_64架构下,编译器会把长字符串拆成多个64位(8字节)的立即数,用movabsq这类指令直接加载到64位寄存器里——这种方式比从内存读取更快,能提升程序执行效率。这些立即数就嵌在.text段的机器码中。
举个例子看你的hexdump输出:
- 000006c0行的
48 b8 61 20 62 69 67 20 72 65:48是x86_64标识64位指令的前缀,它的ASCII值正好是'H';b8是movabsq的操作码;后面的61 20 62 69 67 20 72 65就是字符串片段"a big re"的ASCII字节。 - 后面的
48 ba 66 72 65 73 68 69 6e 67:48同样是64位指令前缀,ba是movabsq的变种操作码,后面的字节对应"freshing"。
那些“H”“E”本质是指令机器码对应的ASCII字符,和字符串本身无关,只是grep匹配到lem片段后,把附近的指令字节也一并显示了而已。
二、ELF文件中的字符串是如何编码的?
ELF文件里的字符串存储分三种主要场景,编码默认是ASCII兼容的UTF-8(C语言中char类型默认对应ASCII,现代编译器也支持UTF-8):
- 只读数据段(.rodata)中的普通字符串:对于常规字符串常量,编译器通常会把它们放到
.rodata段里,以null字节\0结尾(符合C字符串的要求)。这个段里的内容是纯字符串字节序列,没有指令混杂,用strings a.out命令可以直接提取出来。 - 代码段(.text)中的优化后字符串片段:就像你遇到的情况,当字符串长度适合拆分(比如能分成完整的64位块),编译器会做寄存器内联优化,把字符串拆成多个64位立即数嵌入到
.text段的指令中,避免运行时从内存读取。这种情况下字符串片段会和指令机器码混在一起,但本质还是ASCII/UTF-8编码的字节。 - 字符串表(.strtab/.dynstr)中的符号字符串:ELF的符号表(比如函数名、变量名)对应的字符串会存在
.strtab(静态链接产物)或.dynstr(动态链接产物)段里,同样是以null字节分隔的ASCII/UTF-8字符串序列,用于调试或动态链接时查找符号。
如果你想直接查看程序里的所有字符串,推荐用strings a.out命令,它会自动过滤出ELF文件中所有可打印的字符串,不会混进指令机器码的字符。
内容的提问来源于stack exchange,提问作者nowox
相关产品推荐
相关产品推荐

