2023-01-11 WP
0x00 T3 CGfsb
题目来源是攻防世界引导模式的第五题,CGfsb。
初探格式化字符串漏洞。
0x01 wp
第一步,checksec
除了没开随机地址什么都开了,32位
第二步,反编译+静态分析
可以看到需要输入两次东西,并且会打印出来,其中的printf(&s)就是格式化字符串漏洞。
这个漏洞,在于printf(&s),前面的fgets让你自己输入东西进入s以后,你就可以控制printf()里面的内容,达到查看内存和修改内存的目的。
(%p是打印地址)
比如你输入aaaa-%p,那么printf(&s)就相当于,
printf("aaaa-%p")
可是正常来写我们都知道,我们是这么写的:
printf("aaaa-%p", a) //就是说,在“……”之后,会有一个参数。
那么没有参数怎么办?直接从栈里面找,其实还是隐性的有后面的参数,只不过直接从栈中索引了。
查看内存使用%s、%c、%p之类的,写入内存使用%n或者%i$n,其中 i 代表一个变量。
其中这个 i 代表着往下索引第几个参数,然后%i$n就代表着向第 i 个参数写入成功打印的个数(比方说打印了‘aaaa’,那么就会写入4)。
如前面所说,直接从栈中索引,这个%i$n也是直接从栈往下索引参数,这么说太抽象,我们看例子。
可以看出他就是把下一个参数的内容作为地址打印出来了
进一步分析!
我们根据ida的伪代码分析到,需要把pwnme的内容修改为8,这样就能cat flag。那么我们要充分利用%i$n写入成功打印字数的功能,成功打印八个字数然后写入pwnme的地址。
这是pwnme的地址,因为没开随即地址,它不会被改变
我们通过输入“aaaa%p-%p……”这一串内容来确认我们第一次输入的前四个字节属于第几个参数。我们可以看到aaaa被转为ascii码被当作三十二位地址打印出来了,就是0x61616161。所以我们可以数一下,我们第一次输入的内容是在第十个参数。
也就是说,我们只需要输入四个字节,再输入pwnme的地址(占四个字节),总共八个字节,就会在pwnme写入8。我们可以开始写exp了。
第三步,写exp
aaaa是第十个参数,所以我们的地址是第十一个参数,所以写入%11$n
注意一开始还要输入一个东西,随便写一下就好。