-
-
[原创]无路远征——GLIBC2.37后时代的IO攻击之道(三)house_of_借刀杀人
-
2023-2-9 12:48 16246
-
为了说明下一个利用链,继续水一篇。
致敬house_of_pig
xctf 2021 final
同名题目提出了一种利用方式,是在calloc
的情况下,巧妙利用连续执行malloc、memcpy、free
,将提前布置在tcache
中的堆块申请出来,并赋值利用。关键代码如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | ...... char * old_buf = fp - >_IO_buf_base; size_t old_blen = _IO_blen (fp); ...... new_buf = malloc (new_size); if (new_buf = = NULL) { / * __ferror(fp) = 1 ; * / return EOF; } if (old_buf) { memcpy (new_buf, old_buf, old_blen); / / 赋值函数 free (old_buf); / * Make sure _IO_setb won't try to delete _IO_buf_base. * / fp - >_IO_buf_base = NULL; } ...... |
可以看出,在memcpy (new_buf, old_buf, old_blen);
过程中,old_buf
和old_blen
都是可控的。那么理论上我们将tcache
指向任意地址就可以实现任意地址写,但同时面临3个问题。
- 任意地址写之后如何控制执行流?在
house_of_pig
中,使用的是控制hook
,2.34以后hook
取消,又要如何控制执行流。 - 在不控制
free_hook
的情况下,因为要执行free (old_buf);
,必须确保fp->_IO_buf_base
能够被正常free。 - 控制执行流时如何控制参数?
house of 借刀杀人
在IO中,由于要处理宽字符的原因,有很多memcpy、memmove
等内存函数覆写函数,但想利用好它们却非常困难。以_IO_default_xsputn
为例,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | size_t _IO_default_xsputn ( FILE * f, const void * data, size_t n) { const char * s = (char * ) data; size_t more = n; if (more < = 0 ) return 0 ; for (;;) { / * Space available. * / if (f - >_IO_write_ptr < f - >_IO_write_end) { size_t count = f - >_IO_write_end - f - >_IO_write_ptr; / / count 在计算后还需要一个判断 if (count > more) count = more; if (count > 20 ) { / / 此处为可以覆写的位置。 / / 困难 1 :执行后程序流无法控制。 / / 困难 2 :s 和 n 均不可控 f - >_IO_write_ptr = __mempcpy (f - >_IO_write_ptr, s, count); s + = count; } else if (count) { char * p = f - >_IO_write_ptr; ssize_t i; for (i = count; - - i > = 0 ; ) * p + + = * s + + ; f - >_IO_write_ptr = p; } more - = count; } if (more = = 0 || _IO_OVERFLOW (f, (unsigned char) * s + + ) = = EOF) break ; more - - ; } return n - more; } |
从上面代码中可以看出此处调用的memcpy
与house_of_pig
中略有不同,在__mempcpy (f->_IO_write_ptr, s, count)
中,目标地址可控,源地址不可控,count
虽然是计算得来,但由于有需要判断,也是不可控。也就是说我能控制写入的地址,但无法控制写入什么。与house_of_pig
相比,此种手段的优势在于不需要调用malloc
,就可以指定要写入的地址。当然,要利用这个手段,我们还有2个问题需要解决。
- 对于执行流问题,这个比较简单,因为
__mempcpy
也符合house_of_秦月汉关
的攻击条件,我们可以将,重新返回执行__mempcpy (f->_IO_write_ptr, s, count);
,也可以执行_IO_OVERFLOW (f, (unsigned char) *s++)
中的相关路径。 - 关于参数控制的问题,因为我们在执行FSOP时传入参数中只有
FILE *f
可控,所以在f->_IO_write_ptr = __mempcpy (f->_IO_write_ptr, s, count);
这个代码中,s是不可控的。也就是说只能修改任意地址,但不能控制写入的值。那么我们怎么控制size_t _IO_default_xsputn (FILE *f, const void *data, size_t n)
这个函数的三个参数呢?
下一篇文章将介绍如何绕过和利用。
[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。
赞赏
他的文章
看原图