我正在研究用汇编编写的程序:
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
作为平面二进制文件进行编译时,我在程序的十六进制表示中看到了无关的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
答案 0 :(得分:2)
nasm -f bin
将默认模式设置为16位。在该模式下,32位操作数大小的指令(如xor eax,eax
或push eax
)必须使用0x66
操作数大小前缀进行编码。有关操作数大小和地址大小,请参阅模式与前缀的this table。 ( f
是{/ 1>} {/ 1>}。另请参阅x86标记wiki中x86手册的链接。另请参阅16,32或64位模式下的how to disassemble flat binaries。
0x66
是-f elf
的同义词,因此其定位为32位模式。 -felf32
以64位模式为目标(-felf64
无法编码)。
请参阅NASM手册中的section 6.1:push eax
告诉汇编程序汇编程序使用32位模式,根据输出文件格式覆盖默认值。 IDK,如果有一个命令行选项,使用32位代码生成平面二进制文件。我在手册页或--help中没有看到一个。如果由于某种原因您确实不想更改来源,可以使用BITS 32
并使用-felf
链接平面二进制文件。见How to generate plain binaries like nasm -f bin with the GNU GAS assembler?
啊,文档暗示ld --oformat binary
是唯一的方法:
使用BITS指令的最可能原因是在平面二进制文件中写入32位或64位代码;
您实际代码的代码审核:
如果您只想将指针传递给NULL作为第2和第3个args,为什么不将它们都指向第一个BITS 32
结果(也是字符串终止符)?即xor-zero / push / push eax
/ mov edx, esp
。
此外,the man page表示您实际上可以传递argv = NULL和envp = NULL(但警告它不可移植且不依赖它)。所以你可以mov ecx, esp
/ xor edx,edx
/ ... / push edx
/ mov ecx,edx
。
答案 1 :(得分:0)
我在此序言中,我并非100%肯定这一点,但......
根据This website,它是一个操作数大小覆盖前缀。我猜测汇编程序是非常谨慎的,或者它可能是为32位汇编程序输出而设置的,并且尝试确保xor
和mov
这是很有趣的说明书的大小正确。它似乎实际上不会影响运行时,如果该站点是正确的,那么可能只是额外的橱窗装饰。
我会仔细检查传入nasm的标志,以确保你不会意外地告诉它进行移动而不是你期望。
或者希望从最近的x86 asm编码器获得更深入的答案:)