Error: junk `0x7f' after expression when assembling using Gas
Error: junk `0x7f' after expression when assembling using Gas
我正在尝试编写一个 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
被认为是 Intel 语法中的有效指令。我不确定错误来自哪里。非常感谢任何帮助。
当您指定 .intel_syntax noprefix
选项时,您指示 Gnu assembler 您将使用 MASM 语法。你写的实际上是 NASM 语法,它在很多方面类似于 MASM 语法,但在其他方面略有不同。
有关差异的完整讨论,请参阅 this section of the NASM manual。
有关 NASM 与 MASM 语法的快速概述,请参阅 this document.
(这第二个文档以前在线托管,格式更易读 HTML,here,但是 link 已经下线了,很遗憾我找不到复制到 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
表示法,即使在使用 Intel 语法时也是如此。
I thought push byte 60
was considered a valid instruction in Intel syntax.
不,不是真的。您可以从堆栈中 PUSH
和 POP
的唯一大小值是处理器的本机寄存器宽度。因此,在 32 位二进制文件中,您必须压入和弹出 32 位值,而在 64 位二进制文件中,您必须压入和弹出 64 位值。* 这意味着这些行代码在技术上是错误的:
push 'ag'
push byte ptr 0x7f
push byte ptr 60
MASM 将向您发出关于后两条指令的无效操作数大小的警告,这些指令具有明确指定的大小,但它会隐式地将这些常量扩展为 64 位值并且仍然 assemble 成功。我假设 Gnu assembler 也可以执行此自动值扩展,因此您应该删除大小指令:
push 'ag'
push 0x7f
push 60
__
* 从技术上讲,您可以使用操作数大小覆盖前缀来允许您在 32 位和 64 位模式下将 16 位立即数压入堆栈.但你真的不应该这样做,因为它会使堆栈错位,造成性能问题(而且,如果你与用其他语言编译的代码进行互操作,则会破坏 ABI)。编写 16 位代码时,仅将 16 位值压入堆栈。如果要在 32 位或 64 位模式下推送 16 位值,只需让 assembler 将其相应地扩展到 32 位或 64 位即可。
这是 GAS 的错误语法。你必须使用 movl '/pro', [rsp]
另外,使用 **$**xx 将实际值 xx 移动到一个位置。请参阅此处的完整语法。
我正在尝试编写一个 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
被认为是 Intel 语法中的有效指令。我不确定错误来自哪里。非常感谢任何帮助。
当您指定 .intel_syntax noprefix
选项时,您指示 Gnu assembler 您将使用 MASM 语法。你写的实际上是 NASM 语法,它在很多方面类似于 MASM 语法,但在其他方面略有不同。
有关差异的完整讨论,请参阅 this section of the NASM manual。
有关 NASM 与 MASM 语法的快速概述,请参阅 this document.
(这第二个文档以前在线托管,格式更易读 HTML,here,但是 link 已经下线了,很遗憾我找不到复制到 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
表示法,即使在使用 Intel 语法时也是如此。
I thought
push byte 60
was considered a valid instruction in Intel syntax.
不,不是真的。您可以从堆栈中 PUSH
和 POP
的唯一大小值是处理器的本机寄存器宽度。因此,在 32 位二进制文件中,您必须压入和弹出 32 位值,而在 64 位二进制文件中,您必须压入和弹出 64 位值。* 这意味着这些行代码在技术上是错误的:
push 'ag'
push byte ptr 0x7f
push byte ptr 60
MASM 将向您发出关于后两条指令的无效操作数大小的警告,这些指令具有明确指定的大小,但它会隐式地将这些常量扩展为 64 位值并且仍然 assemble 成功。我假设 Gnu assembler 也可以执行此自动值扩展,因此您应该删除大小指令:
push 'ag'
push 0x7f
push 60
__
* 从技术上讲,您可以使用操作数大小覆盖前缀来允许您在 32 位和 64 位模式下将 16 位立即数压入堆栈.但你真的不应该这样做,因为它会使堆栈错位,造成性能问题(而且,如果你与用其他语言编译的代码进行互操作,则会破坏 ABI)。编写 16 位代码时,仅将 16 位值压入堆栈。如果要在 32 位或 64 位模式下推送 16 位值,只需让 assembler 将其相应地扩展到 32 位或 64 位即可。
这是 GAS 的错误语法。你必须使用 movl '/pro', [rsp] 另外,使用 **$**xx 将实际值 xx 移动到一个位置。请参阅此处的完整语法。