From leaking canary to Heap tcache poisoning 从泄漏的金丝雀到堆缓存中毒
Intro介绍
I competed on CSAW CTF 2023, and I solved multiple challenges e.g. from pwn, incident response and reverse engineering. In this post I will explain more about the pwn category which I previously solved all the 3 challenges on this category. 我参加了 CSAW CTF 2023 的比赛,并解决了来自 pwn、事件响应和逆向工程的多重挑战。在这篇文章中,我将解释更多关于 pwn 类别的信息,我之前解决了这个类别的所有 3 个挑战。
List of challenges挑战清单
unlimited subway无限地铁
Super Secure Heap超级安全堆
double zer0 dilemma双泽0困境
Unlimited Subway无限地铁
Binary info:二进制信息:
unlimited_subway: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, BuildID[sha1]=a91c8ae32dffbdc3a706e70158ae362900e2b4de, for GNU/Linux 3.2.0, with debug_info, not stripped
Canary : ✓
NX : ✓
PIE : ✘
Fortify : ✘
RelRO : Partial
Solver求解
In this challenge a binary is provided for further assessment. After analyzing the binary, I found a buffer overflow on exit functional which allowed user to set their own size and input the data to stack. 在此挑战中,提供了一个二进制文件以供进一步评估。在分析二进制文件后,我发现了退出功能的缓冲区溢出,允许用户设置自己的大小并输入要堆叠的数据。
The binary has canary protection and I need to leak the canary value first. At this point I found out that the view function have arbitrary read memory which allowed an access to read the canary value from the binary as long we know the index of the canary value. 二进制文件具有金丝雀保护,我需要先泄漏金丝雀值。在这一点上,我发现视图函数具有任意读取内存,只要我们知道金丝雀值的索引,它就允许访问从二进制文件中读取金丝雀值。
Since the function leaked only 1 byte each time it gets called, we need to leak the canary which have 4 bytes length, then we can trigger the buffer overflow and overwrite the canary and %eip to print_flag which give us the flag we’re looking. Here are the full exploit details of that challenge 由于该函数每次被调用时仅泄漏 1 个字节,因此我们需要泄漏具有 4 个字节长度的金丝雀,然后我们可以触发缓冲区溢出并覆盖金丝雀, %eipprint_flag 并给我们正在寻找的标志。以下是该挑战的完整漏洞利用详细信息
Super Secure Heap超级安全堆
Binary info:二进制信息:
super_secure_heap: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=7ab5b212ea5cca28863c19afbc5887a6da6ceec3, for GNU/Linux 3.2.0, not stripped
Canary : ✓
NX : ✓
PIE : ✓
Fortify : ✘
RelRO : Full
Solver求解
In this challenge we’re given a binary that contains use after free vulnerability. The binary have a function called secure_stuff and it will encrypt the string before inserted to heap segment. But if we input data to key our input will not be encrypted. 在这个挑战中,我们得到了一个包含漏洞的 use after free 二进制文件。二进制文件有一个调用 secure_stuff 的函数,它将在插入堆段之前加密字符串。但是,如果我们输入数据到密钥,我们的输入将不会加密。
the delete function will only check the index and will not check whether the index is allocated or not. This function can be used to trigger use after free vulnerability. 该 delete 函数只会检查索引,不会检查索引是否已分配。此功能可用于触发 use after free 漏洞。
now our goal is to leak the libc address. In order to leak the libc address we can allocate huge memory size then free the memory, the libc address will be stored inside heap chunks. 现在我们的目标是泄露 libc 地址。为了泄漏libc地址,我们可以分配巨大的内存大小,然后释放内存,libc地址将存储在堆块中。
now we can leak the libc address by adding new allocation and our new allocation will be pointed to libc address stored inside the heap chunks. 现在我们可以通过添加新分配来泄漏 libc 地址,我们的新分配将指向存储在堆块中的 libc 地址。
After I got the libc leak, our goal is to write __libc_system address to __free_hook and trigger the RCE by freeing the chunk that has /bin/sh string stored inside the heap. As I able to allocate memory for keys and content array, I can poison the tcache list by overwriting the fd or bk pointer to __free_hook address until it lists on tcache 在我得到libc泄漏后,我们的目标是通过释放堆中存储 /bin/sh 字符串的块来写入 __libc_system 地址 __free_hook 并触发RCE。由于我能够为键和内容数组分配内存,因此我可以通过覆盖指向地址的 __free_hook fd 或 bk 指针来毒害 tcache 列表,直到它在 tcache 上列出
now I have abritrary write memory and I can write __libc_system address on __free_hook . By allocating new memory on heap, it will automatically set our __free_hook address as a heap memory, then I modified the value using set function to trigger arbitrary write memory. 现在我有 abritrary 写入内存,我可以在 上 __free_hook 写入 __libc_system 地址。通过在堆上分配新内存,它会自动将我们的 __free_hook 地址设置为堆内存,然后我使用 function 修改 set 值以触发任意写入内存。
In order to finish exploit I triggered the __libc_system function by freeing a chunk which have /bin/sh string on it. 为了完成漏洞利用,我通过释放一个带有 /bin/sh 字符串的块来触发该功能 __libc_system 。
Here is my exploit code 这是我的漏洞利用代码
run the exploit and we got the flag 运行漏洞利用,我们得到了标志
Double Zer0 Dilemma双泽0困境
Binary Info二进制信息
double_zer0_dilemma: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=d0f73d6da7c5ff209f9b2a6b51a52f86448c97ec, for GNU/Linux 3.2.0, not stripped
Canary : ✘
NX : ✓
PIE : ✘
Fortify : ✘
RelRO : Partial
Solver求解
In this challenge it was given several files (Dockerfile and binary), after I precisely read the Dockerfile I found out the Dockerfile that can disable the ASLR protection 在这个挑战中,它被提供了几个文件(Dockerfile 和二进制文件),在我精确阅读 Dockerfile 后,我发现了可以禁用 ASLR 保护的 Dockerfile
RUN sysctl kernel.randomize_va_space=0
Now we have arbitrary write on the play function, but we have to set the correct address since the address will be added to the current address and dived with 2. Now our goal is to overwrite printf function and overwrite the value of 0x0808B090 with /bin/sh\x00 to obtain the RCE. 现在我们对 play 函数进行了任意写入,但我们必须设置正确的地址,因为该地址将被添加到当前地址并用 2 潜水。现在我们的目标是覆盖函数并覆盖 printf with /bin/sh\x00 的值 0x0808B090 以获得 RCE。
We need to align the address calculation first before sending the payload. Here’s my exploit code 在发送有效负载之前,我们需要先对齐地址计算。这是我的漏洞利用代码
run the exploit and we got the flag 运行漏洞利用,我们得到了标志