覆盖.fini_array函数指针
函数说明
.fini_array
函数指针其实是一个数组指针,其中存有一系列函数指针,这些函数是main
函数执行完后才会自动触发。同理,在.init_array
中的函数是在main
函数之前就触发,一般是用来初始化程序运行的条件。
我们的利用一般是覆盖.fini_array
中函数指针,使main
函数执行完后控制程序执行流到后门函数。
原理调试
这里有一个test程序,用来看看.fini_array
原理:
|
这两行分别定义了函数属性:start函数定义为构造函数,stop函数定义为析构函数。
构造函数在main
之前执行,析构函数则在main
之后。
static void start(void) __attribute__ ((constructor)); |
看看程序的运行结果:
用objdunp -h main
查看一下.fini_array
和.init_array
的地址:
进入gdb中调试查看:
可以看到,他们分别存了start
和stop
函数指针。
举个例子:.fini_array
中存有:0x401120和0x4011b7,其中0x4011b7就是stop
函数地址,0x401120是我们的利用重点,下面注重讲解。
利用分析
重写一个程序,我们不再绑定start
和stop
函数的属性,只是将他们设置为静态函数。
|
编译运行:
现在已经不会执行start
和stop
函数了,我们猜测在.fini_array
和.init_array
中已经没有这两个函数地址了。
调试看看:
用objdunp -h main
查看一下.fini_array
和.init_array
的地址:
上gdb:
可以看到第二个地址并不是stop
函数地址。
其实这里主要发挥作用的就是0x401120这个函数,这就是__do_global_dtors_aux
,在程序结束时,__do_global_dtors_aux
也就是0x0000000000401120
这个函数指针会被实现。
利用时,我们只需要就这个地址覆盖为后门函数即可:
看到返回地址在_dl_fini+526
,所以可以得出结论,.fini_array
区节的第一个函数指针在程序结束时,由_dl_fini
函数调用,所以我们可加以利用。在未开启PIE的情况下,只需实现一个任意地址写,将.fini_array
区节的第一个函数指针改写成后门地址或者one_gadgets,在程序结束时便能控制流程:
至此,函数利用完成。
感谢重写.fini_array函数指针 | Note (gitbook.io)