程序集执行 /bin/bash (x64)

Gou*_*jon 0 64-bit assembly system-calls execve

我是 asm 的新手,我正在尝试对 /bin/bash 执行系统调用。但是我目前遇到以下问题:

我的代码适用于第一个参数长度小于 8 个字节的任何 execve 调用,即 "/bin/sh" 或 "/bin/ls" :

.section .data

    name: .string "/bin/sh"

.section .text

.globl _start

_start:
    #third argument of execve, set to NULL
    xor %rdx, %rdx 

    #push nullbyte to the stack
    pushq %rdx 

    #push /bin/sh to the stack
    pushq name 

    #copy stack to rdi, 1st arg of execve
    mov %rsp, %rdi 

    #copy 59 to rax, defining syscall number for execve  
    movq $59, %rax 

    #3rd arg of execve set to NULL
    movq $0, %rsi 

    syscall
Run Code Online (Sandbox Code Playgroud)

令我困惑的是我无法使用它

name: .string "/bin/bash"
Run Code Online (Sandbox Code Playgroud)

我试图将字符串分成几部分,将“/ bash”然后“/ bin”pushq到堆栈,似乎没有任何东西可以让它工作,并且每次我都会收到“非法指令”错误。我究竟做错了什么?

非工作代码:

.section .data

    name: .string "/bin/bash"

.section .text

.globl _start

_start:
    #third argument of execve, set to NULL
    xor %rdx, %rdx 

    #push nullbyte to the stack
    pushq %rdx 

    #push /bin/sh to the stack
    pushq name 

    #copy stack to rdi, 1st arg of execve
    mov %rsp, %rdi 

    #copy 59 to rax, defining syscall number for execve  
    movq $59, %rax 

    #3rd arg of execve set to NULL
    movq $0, %rsi 

    syscall
Run Code Online (Sandbox Code Playgroud)

其他非工作代码:

.section .data

.section .text

.globl _start

_start:
    #third argument of execve, set to NULL
    xor %rdx, %rdx 

    #push nullbyte to the stack
    pushq %rdx 

    #push /bin/bash to the stack
    pushq $0x68
    pushq $0x7361622f
    pushq $0x6e69622f

    #copy stack to rdi, 1st arg of execve
    mov %rsp, %rdi 

    #copy 59 to rax, defining syscall number for execve  
    movq $59, %rax 

    #3rd arg of execve set to NULL
    movq $0, %rsi 

    syscall
Run Code Online (Sandbox Code Playgroud)

Jes*_*ter 5

您似乎完全糊涂了,无法列出所有错误。不过,这里有一份不完整的清单:

  1. 您将 esi 设置为零的含义argvNULL
  2. push nullbyte to the stack实际上是一个NULL用于终止argv数组的指针(它不是一个终止字符串的零字节)。
  3. 您需要将文件名的地址作为argv[0]. 您不需要将字符串复制到堆栈中。

这是一个固定版本:

.section .data

    name: .string "/bin/bash"

.section .text

.globl _start

_start:
    # third argument of execve is envp, set to NULL
    xor %rdx, %rdx 

    # push NULL to the stack, argv terminator
    pushq %rdx 

    # first argument to execve is the file name
    leaq name, %rdi

    # also argv[0]
    push %rdi

    # second argument to execve is argv
    mov %rsp, %rsi

    #copy 59 to rax, defining syscall number for execve  
    movq $59, %rax 
    syscall
Run Code Online (Sandbox Code Playgroud)

还有一个从代码在堆栈上创建字符串的版本,没有零字节:

.section .text

.globl _start

_start:
    # third argument of execve is envp, set to NULL
    xor %rdx, %rdx 

    # zero terminator
    push %rdx

    # space for string
    sub $16, %rsp

    # end is aligned to the zero terminator
    movb $0x2f, 7(%rsp)        # /
    movl $0x2f6e6962, 8(%rsp)  # bin/
    movl $0x68736162, 12(%rsp) # bash

    # first argument to execve is the file name
    leaq 7(%rsp), %rdi

    # push NULL to the stack, argv terminator
    pushq %rdx 

    # also argv[0]
    push %rdi

    # second argument to execve is argv
    mov %rsp, %rsi

    # copy 59 to rax, defining syscall number for execve
    # avoid zero byte
    xor %eax, %eax
    movb $59, %al 
    syscall
Run Code Online (Sandbox Code Playgroud)

  • 不,一次不是 32 位值。32 位值被放置在堆栈零扩展这导致额外的零被放置在堆栈上,这就是它无法这样做的原因。 (2认同)
  • 这就是为什么我推荐使用 `movabsq` 到寄存器并推送完整的 64 位寄存器的原因。碰巧我作为评论发布的内容是针对错误的字符串。如果您正在执行 shell 代码,您将不得不避免在流中包含任何 0x00 字节,因此在堆栈上构建字符串会涉及到最后一个字节和 NUL。我很确定您正在做的是最终将其编码为 shell 漏洞利用,因此人们会尝试从编码的指令中避免字节流中的 0x00。 (2认同)