linux x86 tcp绑定shellcode(GAS语法)bind()不返回零
我想在linux x86架构上做一个tcp绑定shellcode,我使用GAS语法。 我可以成功调用socketcall(SYS_SOCKET),并得到一个文件描述符(这不是NULL) 现在即时通讯尝试使用该fd并进行SYS_BIND调用,我似乎从不是零的绑定返回值(它应该) 。我已经调试过它。一切都只是堆栈,但...linux x86 tcp绑定shellcode(GAS语法)bind()不返回零
这里是注释掉的代码:
.text
.globl _start
_start:
xorl %eax, %eax
xorl %ebx, %ebx
movb $1, %bl
subl $30, %esp
movl %esp, %esi
# array of arguments for socketcall->SYS_SOCKET:
movb $2, 8(%esi)
movb $1, 12(%esi)
movl %eax, 16(%esi)
# load the address of that array in ecx:
leal 8(%esi), %ecx
movb $102, %al
int $0x80
jz exit0 # exit(0) if eax(return value)==0
# ---------------------------------------------------------------------
bind:
movl %eax, %edx # save the file descriptor
xorl %eax, %eax
inc %bl # bl == 2 -> bind
movw $2, 8(%esi) # sa_family == AF_INET
movw $2222, 10(%esi) # sin_port == 2222
movl %eax, 12(%esi) # INADDR_ANY
movl %eax, 16(%esi) # sin_zero
movl %eax, 20(%esi) # sin_zero
addl $16, %eax
pushl %eax # size of struct sockaddr(16) as the third argument of bind,pushed first
leal 8(%esi), %ecx # leal the address of argument array into ecx
pushl %ecx # push it onto the stack
pushl %edx # file descriptor (first argument)
movb $102, %al # socketcall
int $0x80
jnz exit1 # exit(1) if bind() return value is not zero (zero flag is not set)
# ---------------------------------------------------------------------------
exit0:
xorl %eax, %eax
inc %eax
xorl %ebx, %ebx
int $0x80
# --------------------------------------------------------------------------
exit1:
xorl %eax, %eax
inc %eax
xorl %ebx, %ebx
inc %ebx
int $0x80
编译:
as -ggstabs -o sys_socket.o sys_socket.s
链接:
ld -o sys_socket sys_socket.o
栈和之前注册最后的内核中断(GDB):
(gdb) x/8xw $esp
0xbffff5d6: 0x00000007 0xbffff5ea 0x00000010 0x00000000
0xbffff5e6: 0x00000000 0x08ae0002 0x00000000 0x00000000
(gdb) x/1xb 0xbffff5ea
0xbffff5ea: 0x02
(gdb) i r
eax 0xfffffff7 -9
ecx 0xbffff5ea -1073744406
edx 0x7 7
ebx 0x2 2
esp 0xbffff5d6 0xbffff5d6
ebp 0x0 0x0
esi 0xbffff5e2 -1073744414
edi 0x0 0
eip 0x8048099 0x8048099 <bind+40>
eflags 0x202 [ IF ]
cs 0x73 115
ss 0x7b 123
ds 0x7b 123
es 0x7b 123
fs 0x0 0
gs 0x0 0
(gdb)
那么问题出在哪里以及如何正确解决?
在此先感谢。
您将参数数组组装到堆栈上,但您需要传递要使用的系统调用的地址。你应该清理一下你的代码,这很难遵循你正在做的事情。作为一个快速黑客,movl %esp, %ecx
int $0x80
之前似乎工作,虽然不知道,如果你想这样的:
bind(3, {sa_family=AF_INET, sin_port=htons(44552), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
还要注意的是jz
和jnz
不比较eax
到0
自动,那就是你不能直接使用它们在int $0x80
之后。他们只是测试零标志。您必须添加代码才能根据您自己设置eax
,如testl %eax, %eax
。
此外,你应该保持堆栈指针4字节对齐。 subl $30, %esp
是一个非常糟糕的主意。
对于这个调用,你需要在内存中的2件事情。一个是参数数组。你需要传递一个指向ecx
的指针。二,第二个参数本身必须是一个指向sockaddr
结构的指针。
您在由esi+8
指向的内存中构建sockaddr。你的评论不正确地说这是参数数组,但它不是。随后,通过堆栈上的3 push
指令构建参数数组。因此参数数组的地址是esp
,并且esp+4
(第二个参数)的值指向esi+8
,这是您的sockaddr。您错误地使用esi+8
(前8个字节在那里未使用),但至少它是一致的,并且您有足够的内存分配,所以它恰好工作。
还要注意的是端口号预计将在网络(大尾数)字节顺序,这就是为什么你2222
(=0x08AE
)将被解释为44552
(=0xAE08
)。
感谢您的意见。明白了关于jz和subl的观点。我将参数数组的地址加载到ecx中,并将它与SYS_BIND(2)一起传递给socketcall,然后调用中断。我已经将所有东西都推入堆栈,并将102推入eax,然后称为中断。在你说的时候没有得到你的观点:“你需要传递系统调用的地址才能使用。”你能否再解释一下。 – V1R4N64R
更新了答案。 – Jester
和yupp !!!谢谢你的很好的解释。现在我明白为什么它不起作用。我的意思是我应该把'esi + 24'和'leal 8(%esi),%ecx',然后'movl%ecx,28(%esi)'的文件描述符移到'esi + 24'的地址中进入'%ecx'等等...我将你的答案标记为解决方案。再次感谢您的分析和解释。亲切的问候... – V1R4N64R