Debug source code glibc và MeePwn CTF Quals 2018 — house_of_card

lofiboy
tradahacking
Published in
5 min readJul 27, 2018

Tiện thể viết writeup cho house_of_card thì mình cũng share cách mình debug source code glibc luôn .

Debug source code glibc

Đầu tiên là mình phải check versions glibc.

root@3232d3975981:~# ldd --version
ldd (Ubuntu GLIBC 2.23-0ubuntu10) 2.23
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Roland McGrath and Ulrich Drepper.

Download source glibc và giải nén.

root@3232d3975981:~# wget https://ftp.gnu.org/gnu/glibc/glibc-2.23.tar.bz2
root@3232d3975981:~# tar xvf glibc-2.23.tar.bz2

Sau khi giải nén source code thì bạn tạo 2 folder là build 2.23. Bởi vì glibc không thể compile trong folder chứa source nên phải build nó đến folder khác. Folder 2.23 là nơi glibc được install.

root@3232d3975981:~# ls
2.23 build glibc-2.23 glibc-2.23.tar.bz2

Đây là bước Configuring .

root@3232d3975981:~/build# ../glibc-2.23/configure --prefix=/root/2.23 CFLAGS="-g -g3 -ggdb -gdwarf-4 -Og -Wno-uninitialized -Wno-error" CXXFLAGS="-g -g3 -ggdb -gdwarf-4 -Og -Wno-uninitialized -Wno-error"

Cuối cùng là compileinstall.

root@3232d3975981:~/build# make -j8 && make install

Sau khi compile install xong thì có thể sử dụng glibc bằng cách là export LD_LIBRARY_PATH=/root/2.23/lib .

root@3232d3975981:/home/ctf/solutions_by_me/meepwn_2018/house_of_card# export LD_LIBRARY_PATH=/root/2.23/lib
root@3232d3975981:/home/ctf/solutions_by_me/meepwn_2018/house_of_card# ldd house_of_card
linux-vdso.so.1 => (0x00007ffff7ffa000)
libseccomp.so.2 => /lib/x86_64-linux-gnu/libseccomp.so.2 (0x00007ffff798e000)
libc.so.6 => /root/2.23/lib/libc.so.6 (0x00007ffff75ff000)
/lib64/ld-linux-x86-64.so.2 (0x00007ffff7dd7000)

Còn cách khác là export trong file solved.py.

from pwn import *local = Falseif local:
r = process(['./house_of_card'],env {"LD_LIBRARY_PATH":"/root/2.23/lib"})
else:
r = remote('178.128.87.12', 31336 )

Bây giờ debug trong malloc() thử 😏

 RDI  0x80
RSI 0x7ffff7b8e780 (_IO_stdfile_1_lock) ◂— 0x0
R8 0x7ffff7fed700 ◂— 0x7ffff7fed700
R9 0x0
R10 0x5555555559c8 ◂— jae 0x555555555a2f /* 'Description:\n' */
R11 0x246
R12 0x7ffff7b8d710 (stdin) —▸ 0x7ffff7b8c8e0 (_IO_2_1_stdin_) ◂— 0xfbad208b
R13 0x80
R14 0x80
R15 0x7fffffffecd0 ◂— 0x555500383231 /* '128' */
*RBP 0x80
*RSP 0x7fffffffec70 —▸ 0x7fffffffecd0 ◂— 0x555500383231 /* '128' */
*RIP 0x7ffff7876067 (malloc+9) ◂— mov rax, qword ptr [rip + 0x315e8a]
─────────────────────────────[ DISASM]──────────────────────────────
0x555555554b90 jmp qword ptr [rip + 0x202412] <0x7ffff787605e>

0x7ffff787605e <malloc> push rbp
0x7ffff787605f <malloc+1> push rbx
0x7ffff7876060 <malloc+2> sub rsp, 8
0x7ffff7876064 <malloc+6> mov rbp, rdi
► 0x7ffff7876067 <malloc+9> mov rax, qword ptr [rip + 0x315e8a]
0x7ffff787606e <malloc+16> mov rax, qword ptr [rax]
0x7ffff7876071 <malloc+19> test rax, rax
0x7ffff7876074 <malloc+22> je malloc+36 <0x7ffff7876082>

0x7ffff7876076 <malloc+24> mov rsi, qword ptr [rsp + 0x18]
0x7ffff787607b <malloc+29> call rax
─────────────────────────[ SOURCE (CODE) ]──────────────────────────
2903 {
2904 mstate ar_ptr;
2905 void *victim;
2906
2907 void *(*hook) (size_t, const void *)
► 2908 = atomic_forced_read (__malloc_hook);
2909 if (__builtin_expect (hook != NULL, 0))
2910 return (*hook)(bytes, RETURN_ADDRESS (0));
2911
2912 arena_get (ar_ptr, bytes);
2913
─────────────────────────[ STACK ]────────────────────────────-─────
00:0000│ rsp 0x7fffffffec70 —▸ 0x7fffffffecd0 ◂— 0x555500383231 /* '128' */
01:0008│ 0x7fffffffec78 ◂— 0x0
02:0010│ 0x7fffffffec80 —▸ 0x5555555558f0 ◂— push r15
03:0018│ 0x7fffffffec88 —▸ 0x555555555232 ◂— mov r15, rax
04:0020│ 0x7fffffffec90 ◂— 'new note'
05:0028│ 0x7fffffffec98 ◂— 0x0
... ↓
──────────────────────────────────[ BACKTRACE ]─────────────────────
► f 0 7ffff7876067 malloc+9
f 1 555555555232
f 2 555555555867
f 3 7ffff7822c09 __libc_start_main+385
pwndbg>

Mọi người có thể print value của các biến cho dễ debug.

pwndbg> p __malloc_hook 
$1 = (void *(*)(size_t, const void *)) 0x7ffff7877255 <malloc_hook_ini>

Vậy ok rồi 👌

house_of_card

Đầu tiên vô lúc nào cũng phải check mitigation 👊

root@3232d3975981:/home/ctf/solutions_by_me/meepwn_2018/house_of_card# checksec house_of_card
[*] '/home/ctf/solutions_by_me/meepwn_2018/house_of_card/house_of_card'
Arch: amd64-64-little
RELRO: Full RELRO
Stack: Canary found
NX: NX enabled
PIE: PIE enabled
FORTIFY: Enabled

Chương trình có 3 chức năng là new note, edit notedel note .

root@3232d3975981:/home/ctf/solutions_by_me/meepwn_2018/house_of_card# ./house_of_card 
============ 📚 Notes 📚 ============
1. New Note
2. Edit Note
3. Del Note
4. Quit

1. New 📓

Đầu tiên chương trình sẽ cho nhập name với tối đa là 63 kí tự. Nếu gặp kí tự ‘\n’ sẽ thay bằng kí tự ‘\x00’ và ko nhập nữa.

              +--------------------------+
NAME[64] | A | A | A | ... | A |\x00|
+--------------------------+
0 1 2 62 63

Tiếp theo là nhập chiều dài của chuỗi description . Chiều dài của description phải 0x1000 ≥ len ≥ 0x80. Sau đó chuỗi description được cấp phát với malloc(len) .

              +--------------------------+
HEAP | DESCRIPTION | TOP_CHUNK |
+--------------------------+

Sau khi nhập description thì sẽ cấp phát 1 vùng nhớ có chiều dài len + 68 mình sẽ gọi vùng nhớ này là content .content lưu trữ name[64] ➕ len ➕ description[len].

              +-------------------------------------+
HEAP | DESCRIPTION | CONTENT |TOP_CHUNK |
+-------------------------------------+
+----------------------------------------+
CONTENT | NAME[64] | LEN | DESCRIPTION[LEN] |
+----------------------------------------+
0 -> 63 64 -> 67 68 -> LEN + 67

Sau khi copy qua content thì vùng nhớ description bị 🆓.

              +-----------------------------+
HEAP | FREE | CONTENT |TOP_CHUNK |
+-----------------------------+

Cuối cùng là cấp phát 1 vùng nhớ có chiều dài 0️⃣ ❌ 1️⃣ 8️⃣ mình sẽ gọi vùng nhớ này là note . Vì chương trình lưu trữ các note dưới dạng danh sách liên kết đôi (Doubly Linked List) nên sẽ có note trước là fdnote sau là bk .

               +-------------------------------------+
NOTE1 | CONTENT | FD = NOTE1 | BK = NOTE2 |
+-------------------------------------+

+-------------------------------------+
NOTE2 | CONTENT | FD = NOTE1 | BK = NULL |
+-------------------------------------+

Dưới đây là heap sau khi tạo 1 note mới.

              +---------------------------------------+
HEAP | NOTE1 | FREE | CONTENT1 | TOP_CHUNK |
+---------------------------------------+

2. Edit 📓

edit note có thể thay đổi name, len và description. Trong trường hợp nếu len mới > len cũ sẽ xảy ra 1 lỗi heap overflow bởi vì chiều dài của chuỗi descriptionlen mà mình có thể nhập là len + 68.

          +------------------------------------------------------+
CONTENT | NAME[64] | LEN | DESCRIPTION[LEN] | OVERFLOW |
+------------------------------------------------------+
0 -> LEN - 1 LEN -> LEN + 67

3. Del 📓

Gọi note được chọn remove là ❌ và danh sách liên kết lưu các notenotes. Đầu tiên ❌sẽ được remove khỏi notes , tiếp theo lần lượt là content và ❌sẽ được 🆓.

               +-------------------------------------+
NOTE1 | CONTENT | FD = NOTE1 | BK = NOTE3 |
+-------------------------------------+

+-------------------------------------+
FREE | FREE | FD = NOTE1 | BK = NOTE3 | REMOVE NOTE2
+-------------------------------------+
+-------------------------------------+
NOTE3 | CONTENT | FD = NOTE1 | BK = NULL |
+-------------------------------------+

4. Exploit

Đã tìm được 🐞 rồi bây giờ lên kế hoạch để exploit thôi 😏

Ý tưởng là sẽ overflow qua content của note nằm sau description mà mình đang edit. Sau đó là mình có quyền write tùy ý rồi 👍

       +--------------------------------------------------------+
HEAP | ... |NAME[64]|LEN|DESCRIPTION[LEN]| OVERFLOW | FD | BK |
+--------------------------------------------------------+
0 -> LEN - 1 LEN -> LEN + 7

Dưới đây là payload.

Cuối cùng là gửi lời chân thành cảm ơn đến các anh trong team Meepwn đã làm ra những challenge thật là thú vị và bổ ích .Cảm ơn mọi người đã bỏ thời gian đọc bài viết của mình 😃

Links tham khảo

--

--