忙了一周,结束了,继续
https://adworld.xctf.org.cn/task/answer?type=pwn&number=2&grade=0&id=5058&page=1
第六题是这样的,呃,这个题有点是考眼神了
题目伪码是这样的
三个关键函数,都在如上,还有一个特殊函数输出flag的
好了,可以开始分析了。
这题绝对是考眼神的
仔细看了一下,main 函数其实没有发现问题。
login函数也是中规中矩限制了长度,
最后看到 check_passwd 函数,可以发现有一个细微的小问题,
就是strlen的返回值,赋给了一个 int8,也就是取值范围是0~255啊,
但是前面login函数接收的时候,实际上是可以接收409个字符的,
而超过255个字符长度的话,int8会被溢出,又回到从0开始的情况。
这里是不是可能就会有问题呢。
继续看check_passwd 函数,可以发现,最后有个strcpy,竟然没有限制长度,
没有用strncpy,问题可能就是这里了。
看一下 check_passwd 函数的局部变量内存布局,可以发现,dest 变量长度11字节,
加上var_9变量长度9字节(说法可能不准确,但是内存布局是这样),
局部变量的下面,是老的ebp,老的ebp下面是返回地址。也就是说,覆盖11+9+4个字节之后,就是老的返回地址了,
只要我能把老的返回地址替换成 what_is_this 的函数地址,它会自动给我输出一个flag。
按照这个思路先做一下。
整理一下信息,
密码最多可以输入409个字符,
输入 4~8 个字符或者输入 4 + 256 ~ 8 + 256 个字符也会被认为正确,(260 ~ 264)
需要覆盖第 11 + 9 + 4 个字节之后的 4 个字节。
信息整理完了,那么就开干吧。
需要拼接一个这样的字符串,‘a’ *(11 + 9 + 4) + 劫持地址 + ............ 直到263 个字符填满
写代码,劫持地址是 what_is_this 的地址
代码就是这样
1 # a = process("./b59204f56a0545e8a22f8518e749f19f") 2 a = remote('124.126.19.106', 51227) 3 4 payload = 'a' * (11 + 9 + 4) + int322str(0x0804868B) + 'a' * (263 - 11 - 9 - 4 - 4) 5 a.sendlineafter('choice:', '1') 6 a.recvuntil("username: ") 7 a.sendline('aaaa') 8 a.recvuntil('passwd: ') 9 print(payload) 10 a.sendline(payload) 11 12 a.interactive()
效果
这个,真的好像来找茬了。