覆盖.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)


