修改 fin_array
复制本地路径 | 在线编辑
有时我们有一次任意写的机会, 但总会感觉似乎威力不够, 此时可以通过修改 fin_array 来实现任意写.
fin_array 在 _libc_csu_fini 中, 这个函数会在 main 函数结束后执行.
下面以 pwnable.tw 的 3x17 题目为例.
__int64 _libc_csu_fini()
{
signed __int64 index; // rbx
// 右移 3 位的目的: 除以 8
// (4B4100 - 4B40F0) / 8 = 2,所以该函数一共执行 2 次子函数: fin_arr[1], fin_arr[0]
if ( (&unk_4B4100 - (_UNKNOWN *)off_4B40F0) >> 3 )
{
// 0x4B40F0 为 fin_array 存放位置
// 通过代码可发现, 逆序执行, 先执行 fin_arr[1]
index = ((&unk_4B4100 - (_UNKNOWN *)off_4B40F0) >> 3) - 1;
do
off_4B40F0[index--]();
while ( index != -1 );
}
return sub_48E32C();
}
注意
fin_array 是逆序执行, 由于 main 函数中我们有一次任意写的机会, 所以采用如下方法:
- 程序执行
main, 需要把fin_array[1]更改为main函数,fin_array[0]改为libc_csu_fin函数. - 程序执行
libc_csu_fin, 执行fin_array[1]即main, 我们有一次任意写的机会, 此时可以修改任意地址内容. - 之后执行
fin_array[0]即libc_csu_fin, 通过上面代码可知, 会再一次执行fin_array[1]即main. - 执行完
fin_array[1]后又执行fin_array[0]即libc_csu_fin, 程序不断循环, 每一次都可以修改一次内存. - 当内存全部修改完毕, 在
main函数中将fin_array[0]修改为退出函数.
需要注意的是, 我们的任意写机会要能够一次性将 fin_array[1] 和 fin_array[0] 都修改掉, 否则无法进入上面的循环.