错误:垃圾`0x7f'使用Gas组装后表达

时间:2017-06-22 02:33:57

标签: assembly x86 gas intel-syntax

我尝试编写64位shellcode来读取名为' / proc / flag'的文件。但是,当我编译程序集时,我发现了一些随机错误,并且不知道它为什么会出现。

这是我的汇编文件readflag.S

.intel_syntax noprefix
.global _start
.type _start, @function
_start:
  mov     dword [rsp], '/pro'     /* build filename on stack */
  mov     dword [rsp+4],  'c/fl'
  push    'ag'
  pop     rcx
  mov     [rsp+8], ecx
  lea     rdi, [rsp]              /* rdi now points to filename '/proc/flag' */
  xor     rsi, rsi                /* rsi contains O_RDONLY, the mode with which we'll open the file */
  xor     rax, rax
  inc     rax
  inc     rax                     /* syscall open = 2 */
  syscall
  mov     rbx, rax                /* filehandle of opened file */
  lea     rsi, [rsp]              /* rsi is the buffer to which we'll read the file */
  mov     rdi, rbx                /* rbx was the filehandle */
  push    byte 0x7f              /* read 127 bytes. if we stay below this value, the generated opcode will not contain null bytes */
  pop     rdx
  xor     rax, rax                /* syscall read = 0 */
  syscall
  lea     rsi, [rsp]              /* the contents of the file were on the stack */
  xor     rdi, rdi
  inc     rdi                     /* filehandle; stdout! */
  mov     rdx, rax                /* sys_read() returns number of bytes read in rax, so we move it to rdx */
  xor     rax, rax
  inc     rax
  syscall                     /* syscall write = 1 */
  push    byte 60                /* some bytes left... */
  pop     rax                     /* exit cleanly */
  syscall

这些是我编译程序集时遇到的错误:

readflag.S: Assembler messages:
readflag.S:7: Error: junk `pro10mov dword [rsp+4]' after expression
readflag.S:21: Error: junk `0x7f' after expression
readflag.S:33: Error: junk `60' after expression
objcopy: 'readflag.o': No such file

我认为push byte 60被认为是英特尔语法中的有效指令。我不确定错误来自哪里。非常感谢任何帮助。

2 个答案:

答案 0 :(得分:4)

指定.intel_syntax noprefix选项时,指示Gnu汇编程序将使用MASM语法。你所写的实际上是NASM语法,它在很多方面类似于MASM语法,但在其他方面略有不同。

有关差异的完整讨论,请参阅this section of the NASM manual 有关NASM与MASM语法的快速概述,请参阅this document (此第二个文档曾经以更易读的HTML格式在线托管,here,但链接已关闭,遗憾的是我无法在Wayback Machine中找到副本。)

需要在代码中更改的重要事项是,您需要在每个大小说明符后面包含PTR指令。因此,例如,而不是:

    mov     dword [rsp],   '/pro'
    mov     dword [rsp+4], 'c/fl'

你需要写:

    mov     dword ptr [rsp],   '/pro'
    mov     dword ptr [rsp+4], 'c/fl'

此外,虽然MASM语法通常会写入带有尾随h的十六进制常量,而不是前导0x,但Gas的“MASM”模式不支持此功能,您需要使用C样式0x表示法,即使使用英特尔语法。

  

我认为push byte 60被认为是英特尔语法中的有效指令。

不,不是真的。堆栈中唯一可以PUSHPOP的大小值是处理器的本机寄存器宽度。因此,在32位二进制文​​件中,必须推送和弹出32位值,而在64位二进制文​​件中,必须推送和弹出64位值。 * 这意味着这些代码行是技术错误:

push    'ag'
push    byte ptr 0x7f
push    byte ptr 60

MASM将为后两条具有明确指定大小的指令提供有关无效操作数大小的警告,但它会隐式地将这些常量扩展为64位值并仍然成功汇编。我假设Gnu汇编程序也可以执行此自动值扩展,因此您应该删除size指令:

push    'ag'
push    0x7f
push    60

__
* 从技术上讲,您可以使用操作数大小覆盖前缀,以便在32位和64位模式下将16位立即数推送到堆栈。但你真的不应该这样做,因为它错误地堆栈,造成性能问题(如果你与其他语言编译的代码互操作,打破了ABI)。在写入16位代码时,只将16位值压入堆栈。如果要在32位或64位模式下推送16位值,只需让汇编器将其扩展为32位或64位。

答案 1 :(得分:-1)

这是GAS的错误语法。您必须使用movl'/ pro',[rsp] 另外,使用** $ ** xx将实际值xx移至某个位置。请参阅此处的完整语法。

https://en.wikibooks.org/wiki/X86_Assembly/GAS_Syntax