Skip to content

Feed to Win

September 28, 2019 / Exploit

Câu chuyện về GDB

Dạo gần đây mình bắt đầu nghiêm túc tìm hiểu về heap exploitation. Ắt hẳn bạn nào mới tìm hiểu về exploit trên linux đều thường sử dụng GDB. Tuy nhiên, heap exploitation khá là chua so với stack exploitation :)) Bạn phải biết sử dụng GDB nâng cao hơn chút, ngoài việc chỉ biết các lệnh b, c, x, n, s, p. Bài viết của mình nhằm mục đích bôi trơn, giảm độ chua khi debug một chương trình (bao gồm glibc). Tất nhiên mình chỉ là một newbie nên mình cũng chỉ chia sẻ được một chút thôi 😀

Hiện tại có rất nhiều plugin hỗ trợ cho gdb như peda, pwndbg, gef,... Mình thì chỉ sử dụng mỗi peda, nhưng gần đây mình muốn tìm hiểu thêm heap exploitation nên cài thêm pwngdb. Cả pwndbg và gef cũng đều hỗ trợ cho việc phân tích heap nhưng 2 cái đó có nhiều tính năng quá, trình mình cùi nên không biết xài 🙁

Debug with source

GDB có tính năng ánh xạ lệnh asm tại địa chỉ 0xAAAA sẽ tương ứng với dòng lênh C nào trong file source. Tuy nhiên không phải lúc nào GDB cũng có thể ánh xạ được, bạn phải có source code và debug symbols của chương trình. Nếu bạn có source code của chương trình, khi compile bằng gcc hoặc g++ thêm option -g để có debug symbols.
Ví dụ mình có chương trình sau:

1
2
3
4
5
6
#include <stdio.h>
 
int main() {
    printf("Hello world!");
    return 0;
}

Tiến hành compile và debug bằng gdb

1
2
gcc -m32 -g -o helloworld helloworld.c
gdb helloworld -ex "b hellworld.c:4" -ex "r"

GDB sẽ hiển thị kiểu như này

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
[----------------------------------registers-----------------------------------]
EAX: 0xf7fb6dbc --> 0xffffcf6c --> 0xffffd170 ("LC_PAPER=de_CH.UTF-8")
EBX: 0x0
ECX: 0xffffced0 --> 0x1
EDX: 0xffffcef4 --> 0x0
ESI: 0xf7fb5000 --> 0x1afdb0
EDI: 0xf7fb5000 --> 0x1afdb0
EBP: 0xffffceb8 --> 0x0
ESP: 0xffffceb0 --> 0xf7fb53dc --> 0xf7fb61e0 --> 0x0
EIP: 0x804841c (<main+17>:  sub    esp,0xc)
EFLAGS: 0x282 (carry parity adjust zero SIGN trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x8048416 <main+11>: mov    ebp,esp
   0x8048418 <main+13>: push   ecx
   0x8048419 <main+14>: sub    esp,0x4
=> 0x804841c <main+17>: sub    esp,0xc
   0x804841f <main+20>: push   0x80484c0
   0x8048424 <main+25>: call   0x80482e0 <[email protected]>
   0x8048429 <main+30>: add    esp,0x10
   0x804842c <main+33>: mov    eax,0x0
[------------------------------------stack-------------------------------------]
0000| 0xffffceb0 --> 0xf7fb53dc --> 0xf7fb61e0 --> 0x0
0004| 0xffffceb4 --> 0xffffced0 --> 0x1
0008| 0xffffceb8 --> 0x0
0012| 0xffffcebc --> 0xf7e1d637 (<__libc_start_main+247>:   add    esp,0x10)
0016| 0xffffcec0 --> 0xf7fb5000 --> 0x1afdb0
0020| 0xffffcec4 --> 0xf7fb5000 --> 0x1afdb0
0024| 0xffffcec8 --> 0x0
0028| 0xffffcecc --> 0xf7e1d637 (<__libc_start_main+247>:   add    esp,0x10)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
 
Breakpoint 1, main () at helloworld.c:4
4       printf("Hello world!");
gdb-peda$

Để ý dòng thứ 16, 33 và 34. Lệnh tại địa chỉ 0x804841c tương ứng với printf("Hello world!") (tất nhiên còn một số lệnh phía sau nó cũng tương ứng với printf)
Còn nếu không có source code thì sao? Ví dụ như bạn muốn debug glibc như mình :v Đơn giản thôi, Ubuntu cung cấp sẵn gói debug symbols và source code luôn rồi, bạn chỉ cần cài đặt là được.

1
2
3
$ sudo apt install libc6-dbg
$ sudo apt install libc6-dbg:i386 # cài gói debug symbols của 32-bit nếu máy bạn 64-bit
$ sudo apt install libc6-source

Giờ thử debug glibc của fastbin_dup_consolidate.c trong https://github.com/shellphish/how2heap

1
gdb fastbin_dup_consolidate -ex "b fastbin_dup_consolidate.c:12" -ex "r" -ex "s"

Thì sẽ ra thế này:

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
40
41
42
[----------------------------------registers-----------------------------------]
RAX: 0x0
RBX: 0x0
RCX: 0x7ffff7b04200 (<__openat_2+16>:   cmp    eax,0x410000)
RDX: 0x0
RSI: 0x7ffff7dd1b40 --> 0x602000 --> 0x0
RDI: 0x400
RBP: 0x7fffffffdc60 --> 0x400790 (<__libc_csu_init>:    push   r15)
RSP: 0x7fffffffdc28 --> 0x4006c0 (<main+122>:   mov    QWORD PTR [rbp-0x18],rax)
RIP: 0x7ffff7a91130 (<__GI___libc_malloc>:  push   rbp)
R8 : 0x602010 --> 0x0
R9 : 0x7ffff7dd2500 --> 0x7ffff7b9b997 --> 0x636d656d5f5f0043 ('C')
R10: 0x8b8
R11: 0x7ffff7a914f0 (<__GI___libc_free>:    push   r13)
R12: 0x400550 (<_start>:    xor    ebp,ebp)
R13: 0x7fffffffdd40 --> 0x1
R14: 0x0
R15: 0x0
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x7ffff7a91120 <__malloc_check_init+96>: mov    DWORD PTR [rip+0x34269e],0x0        # 0x7ffff7dd37c8 <disallow_malloc_check>
   0x7ffff7a9112a <__malloc_check_init+106>:    ret    
   0x7ffff7a9112b:  nop    DWORD PTR [rax+rax*1+0x0]
=> 0x7ffff7a91130 <__GI___libc_malloc>: push   rbp
   0x7ffff7a91131 <__GI___libc_malloc+1>:   push   rbx
   0x7ffff7a91132 <__GI___libc_malloc+2>:   sub    rsp,0x8
   0x7ffff7a91136 <__GI___libc_malloc+6>:   mov    rax,QWORD PTR [rip+0x33fdb3]        # 0x7ffff7dd0ef0
   0x7ffff7a9113d <__GI___libc_malloc+13>:  mov    rax,QWORD PTR [rax]
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffdc28 --> 0x4006c0 (<main+122>:  mov    QWORD PTR [rbp-0x18],rax)
0008| 0x7fffffffdc30 --> 0x0
0016| 0x7fffffffdc38 --> 0x602010 --> 0x0
0024| 0x7fffffffdc40 --> 0x602060 --> 0x0
0032| 0x7fffffffdc48 --> 0x400550 (<_start>:    xor    ebp,ebp)
0040| 0x7fffffffdc50 --> 0x7fffffffdd40 --> 0x1
0048| 0x7fffffffdc58 --> 0x0
0056| 0x7fffffffdc60 --> 0x400790 (<__libc_csu_init>:   push   r15)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
__GI___libc_malloc (bytes=0x400) at malloc.c:2902
2902    malloc.c: No such file or directory.
gdb-peda$

Dòng 40, 41 báo lỗi vì mình chưa chỉ cho GDB biết file malloc.c nằm ở đâu. Giả sử source code glibc của mình ở ~/glibc-2.23 thì chỉ cần thêm lệnh directory ~/glibc-2.23/malloc cho GDB tìm file malloc.c

1
gdb fastbin_dup_consolidate -ex "b fastbin_dup_consolidate.c:12" -ex "r" -ex "directory ~/glibc-2.23/malloc" -ex "s"

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
40
41
42
[----------------------------------registers-----------------------------------]
RAX: 0x0
RBX: 0x0
RCX: 0x7ffff7b04200 (<__openat_2+16>:   cmp    eax,0x410000)
RDX: 0x0
RSI: 0x7ffff7dd1b40 --> 0x602000 --> 0x0
RDI: 0x400
RBP: 0x7fffffffdc60 --> 0x400790 (<__libc_csu_init>:    push   r15)
RSP: 0x7fffffffdc28 --> 0x4006c0 (<main+122>:   mov    QWORD PTR [rbp-0x18],rax)
RIP: 0x7ffff7a91130 (<__GI___libc_malloc>:  push   rbp)
R8 : 0x602010 --> 0x0
R9 : 0x7ffff7dd2500 --> 0x7ffff7b9b997 --> 0x636d656d5f5f0043 ('C')
R10: 0x8b8
R11: 0x7ffff7a914f0 (<__GI___libc_free>:    push   r13)
R12: 0x400550 (<_start>:    xor    ebp,ebp)
R13: 0x7fffffffdd40 --> 0x1
R14: 0x0
R15: 0x0
EFLAGS: 0x202 (carry parity adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x7ffff7a91120 <__malloc_check_init+96>: mov    DWORD PTR [rip+0x34269e],0x0        # 0x7ffff7dd37c8 <disallow_malloc_check>
   0x7ffff7a9112a <__malloc_check_init+106>:    ret    
   0x7ffff7a9112b:  nop    DWORD PTR [rax+rax*1+0x0]
=> 0x7ffff7a91130 <__GI___libc_malloc>: push   rbp
   0x7ffff7a91131 <__GI___libc_malloc+1>:   push   rbx
   0x7ffff7a91132 <__GI___libc_malloc+2>:   sub    rsp,0x8
   0x7ffff7a91136 <__GI___libc_malloc+6>:   mov    rax,QWORD PTR [rip+0x33fdb3]        # 0x7ffff7dd0ef0
   0x7ffff7a9113d <__GI___libc_malloc+13>:  mov    rax,QWORD PTR [rax]
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffdc28 --> 0x4006c0 (<main+122>:  mov    QWORD PTR [rbp-0x18],rax)
0008| 0x7fffffffdc30 --> 0x0
0016| 0x7fffffffdc38 --> 0x602010 --> 0x0
0024| 0x7fffffffdc40 --> 0x602060 --> 0x0
0032| 0x7fffffffdc48 --> 0x400550 (<_start>:    xor    ebp,ebp)
0040| 0x7fffffffdc50 --> 0x7fffffffdd40 --> 0x1
0048| 0x7fffffffdc58 --> 0x0
0056| 0x7fffffffdc60 --> 0x400790 (<__libc_csu_init>:   push   r15)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
__GI___libc_malloc (bytes=0x400) at malloc.c:2902
2902    {
gdb-peda$

Vậy là xong, chúng ta đã biết tại địa chỉ ứng với dòng source code nào, sau đó mở lên đối chiếu thôi, dễ debug hơn hẳn :v

Reverse debug

Đây là một tính năng cực bá của GDB từ bản 7.0 :)) Có khi nào trong lúc debug bạn lỡ tay ấn c, n hoặc s liên tục rồi tự dưng chương trình kết thúc. Và bạn vừa nhận ra bạn đã bỏ qua những đoạn code quan trọng :)) Cái này mình gặp hoài, và thường thì mình sẽ set thêm breakpoint và ấn r để chương trình chạy từ đầu :v Nhưng không, GDB có khả năng chạy ngược, tức là bạn có thể trở về địa chỉ trước đó mà bạn đã lở bỏ qua. Chi tiết nằm ở http://www.sourceware.org/gdb/wiki/ProcessRecord/Tutorial Vì cái này đơn giản nên mình chẳng giải thích gì, các bạn tự làm theo là được :))
UPDATE: mình mới biết được một số tool cho phép record và replay debugging như Mozilla’s rr, Microsoft’s TTD, MIT Lincoln Lab’s PANDA và GeoHot’s QIRA từ bài viết Timeless Debugging of Complex Software

Ngoài ra gdb có thể chạy python script (chắc ai cũng biết :p), bạn có thể tham khảo các API tại đây. Mình cũng từng sử dụng API để tự động đặt toàn bộ breakpoint trong bảng GOT để xem có ai gọi đến để mình ghi đè địa chỉ đó :v

Post navigation

Previous Post:

Build PyQt5 in Python2.7 32-bit

Next Post:

Writeups ISITDTU

One comment

  1. Pingback: cheap nfl jerseys with free shipping

Comments are closed.

Recent Posts

  • SVATTT2019
  • flag_check – AceBear CTF 2019
  • Writeups MatesCTF Round 3
  • Writeups ISITDTU
  • Câu chuyện về GDB

Recent Comments

  • cheap nfl jerseys with free shipping on Câu chuyện về GDB

Archives

  • December 2019
  • April 2019
  • February 2019
  • July 2018
  • June 2018
  • April 2018
  • March 2018
  • February 2018

Categories

  • CTF
  • Exploit
  • RE
  • Uncategorized

Meta

  • Log in
  • Entries feed
  • Comments feed
  • WordPress.org
© 2021 Feed to Win - Powered by SimplyNews