编译汇编程序以扁平状二进制包括外来“F”字符不以其它格式
我正在用汇编程序存在:编译汇编程序以扁平状二进制包括外来“F”字符不以其它格式
xor eax, eax ; make eax equal to 0
push eax ; pushes null
push 0x68732f2f ; pushes /sh (//)
push 0x6e69622f ; pushes /bin
mov ebx, esp ; passes the first argument
push eax ; empty third argument
mov edx, esp ; passes the third argument
push eax ; empty second argument
mov ecx, esp ; passes the second argument
mov al, 11 ; execve system call #11
int 0x80 ; makes an interrupt
当使用nasm
为平坦编译-form二进制文件,我在程序的十六进制表示中看到无关的f
字符。我期待看到:
0000000: 31c0 5068 2f2f 7368 682f 6269 6e89 e350 1.Ph//shh/bin..P
0000010: 89e2 5089 e1b0 0bcd 80 ..P......
但真正看到:
0000000: 6631 c066 5066 682f 2f73 6866 682f 6269 f1.fPfh//shfh/bi
0000010: 6e66 89e3 6650 6689 e266 5066 89e1 b00b nf..fPf..fPf....
0000020: cd80 ..
奇怪的是,当我尝试以其他格式,如ELF-32使用nasm
编译我的程序,我看到了十六进制表示我我希望(尽管许多其他十六进制的我也许不应该在我的解决方案包括):
0000000: 7f45 4c46 0101 0100 0000 0000 0000 0000 .ELF............
0000010: 0100 0300 0100 0000 0000 0000 0000 0000 ................
0000020: 4000 0000 0000 0000 3400 0000 0000 2800 @.......4.....(.
0000030: 0500 0200 0000 0000 0000 0000 0000 0000 ................
0000040: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000050: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000060: 0000 0000 0000 0000 0100 0000 0100 0000 ................
0000070: 0600 0000 0000 0000 1001 0000 1900 0000 ................
0000080: 0000 0000 0000 0000 1000 0000 0000 0000 ................
0000090: 0700 0000 0300 0000 0000 0000 0000 0000 ................
00000a0: 3001 0000 2100 0000 0000 0000 0000 0000 0...!...........
00000b0: 0100 0000 0000 0000 1100 0000 0200 0000 ................
00000c0: 0000 0000 0000 0000 6001 0000 3000 0000 ........`...0...
00000d0: 0400 0000 0300 0000 0400 0000 1000 0000 ................
00000e0: 1900 0000 0300 0000 0000 0000 0000 0000 ................
00000f0: 9001 0000 1000 0000 0000 0000 0000 0000 ................
0000100: 0100 0000 0000 0000 0000 0000 0000 0000 ................
0000110: 31c0 5068 2f2f 7368 682f 6269 6e89 e350 1.Ph//shh/bin..P
0000120: 89e2 5089 e1b0 0bcd 8000 0000 0000 0000 ..P.............
0000130: 002e 7465 7874 002e 7368 7374 7274 6162 ..text..shstrtab
0000140: 002e 7379 6d74 6162 002e 7374 7274 6162 ..symtab..strtab
0000150: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000160: 0000 0000 0000 0000 0000 0000 0000 0000 ................
0000170: 0100 0000 0000 0000 0000 0000 0400 f1ff ................
0000180: 0000 0000 0000 0000 0000 0000 0300 0100 ................
0000190: 0073 6865 6c6c 7370 6177 6e2e 6173 6d00 .shellspawn.asm.
对于什么,我试图完成,我想我必须使用一台形式的二进制文件。
我的问题:这是什么f
字符来自什么,它是什么意思;我如何删除它?
NASM version 2.10.09 compiled on Dec 29 2013
xxd V1.10 27oct98 by Juergen Weigert
nasm -f bin
一个更深入的答案设置默认模式为16位。在该模式下,32位操作数大小指令(如xor eax,eax
或push eax
)必须用0x66
操作数大小前缀进行编码。有关操作数大小和地址大小的模式与前缀的对比见this table。 (f
是0x66
,以ASCII)。另请参阅x86标记wiki中的x86手册链接。另请参阅how to disassemble flat binaries,采用16,32或64位模式。
-f elf
为-felf32
的同义词,所以其定位的32位模式。 -felf64
靶向64位模式下(其中push eax
不是encodeable)。
请参阅NASM手册中的section 6.1:BITS 32
告知汇编程序汇编程序为32位模式,根据输出文件格式覆盖缺省值。 IDK,如果有一个命令行选项可以生成32位代码的平面二进制文件。我在手册页或--help中看不到一个。如果由于某种原因,您确实不想更改源代码,则可以使用-felf
并使用ld --oformat binary
链接平面二进制文件。见How to generate plain binaries like nasm -f bin with the GNU GAS assembler?
啊,文档意味着BITS 32
是唯一的方法:
使用BITS指令最可能的原因是在一个平面的二进制文件中写入32位或64位代码;你的实际代码
代码审查:
如果你只是想指针传递给NULL作为第二和第三指定参数时,为什么不能让他们都指向第一push eax
结果(这也是字符串结束符)?即xor-zero/push/mov edx, esp
/mov ecx, esp
。
此外,the man page说,你其实可以传递一个的argv = NULL和envp = NULL(但警告说,这并不便携,不依赖于它)。所以你可以只需要xor edx,edx
/push edx
/.../mov ecx,edx
/lea eax, [edx+11]
。
我用'BITS 32'去了,现在hex代表我想要的方式。谢谢! – jakenberg
我前言本有,我不是100%肯定这一点,但...
据This website,它是一个操作数大小覆盖前缀。我要去猜测,汇编正在加倍小心,或者是设置为32位汇编输出,这是剩下的有趣的尝试,并确保您xor
和mov
指令是正确的尺寸。它似乎实际上不会影响运行时,如果该网站是正确的,所以也许只是额外的窗饰。
我会仔细检查传入NASM标志,以确保你不小心告诉它做的比预期的举动。
或者希望从铁道部近86 ASM编码器:)
感谢您对Michael的帮助。我的nasm用法如下:'nasm shellspawn.asm'。我试过比这更具体,但我得到了相同的结果。我会继续研究这条大道 – jakenberg
这不是一个“额外谨慎”的问题。在32位代码中,0x66操作数大小意味着16位操作数大小,所以您必须正确地获取模式。但是,是的,@jakenberg'-fbin'的默认值是16位模式。您可以使用“BITS 32”指令。我不确定是否有NASM选项将模式设置为32位,同时仍然制作平面二进制文件。 –
谢谢彼得。我在'.asm'文件的顶部放置了'BITS 32',我不再看到大小操作数前缀。从你们两个人那里学到了一些东西! – jakenberg
如果您只是想将指针传递给NULL作为第二个和第三个参数,为什么不让它们都指向第一个'push eax'结果(这也是字符串终止符)?即xor-zero/push /'mov edx,esp' /'mov ecx,esp'。另外,[man page](http://man7.org/linux/man-pages/man2/execve.2.html)说你实际上可以传递一个argv = NULL和envp = NULL(但是警告它不是可移植的并不依赖于它)。所以你可以只用'edx,edx' /'push edx'/... /'mov ecx,edx' /'lea eax,[edx + 11]'。 –