现在我要介绍一种基于栈溢出的题型,但是这种题目没有直接给你一个形如
system()
{
binsh//这里意思就是一个直接提权的后门函数,但是我不记得具体长什么样
//反正IDA会给注释
}
的后门函数。但是题目中还是出现了system函数以及binsh字符串
这里我们最终目的还是让这个system函数执行binsh。问题就是如何将binsh传给system函数。这一点我们最后来讲解
看看例题BUUCTF的jarvisoj_level2。首先在IDA里随便逛逛,收集信息
main函数看到vuln函数和system函数,没什么东西。进vuln函数看。
看到一个read函数,能读进整整0x100个字节。而只给buf安排了0x88个字节。很明确存在栈溢出。
在shift加f12看到有一个binsh字符串,可以利用
双击看看binsh字符串的地址0x804A024
这里可以ctrl+x碰碰运气,要是有一个直接调用binsh的system函数就更方便了,但是很显然没有。
现在理一理思路,我们有system函数,也可以看到他的地址。我们有binsh,也可以看到他的地址。我们这里需要利用32的传参方式,通过栈传参,那么我们就可以把binsh的地址写在程序的栈上,并让system函数去读他。
但是这里还有一个细节,为什么我们给system传的参数是binsh的地址,传/bin/sh
的字符串可以吗。我们看看system函数原型。
他的参数是一个const char*,是一个指针(下面的ptr是pointer,也再次印证了我们的观点。所以我们要传的应该是一个地址。
现在思路就很明确了,先传入足够多的垃圾字符,用system函数的地址覆盖原函数的返回地址,最后由于32位传参是通过栈的特性,system会从栈的下一位读取一个字节的数据并将其作为一个储存字符串的地址处理。所以我们在这之后就可以加上/bin/sh的地址。
exp如图