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 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | #include <fcntl.h> #include <iostream> #include <cstring> #include <cstdlib> #include <unistd.h> using namespace std; class Human{ private: virtual void give_shell(){ system("/bin/sh"); } protected: int age; string name; public: virtual void introduce(){ cout << "My name is " << name << endl; cout << "I am " << age << " years old" << endl; } }; class Man: public Human{ public: Man(string name, int age){ this->name = name; this->age = age; } virtual void introduce(){ Human::introduce(); cout << "I am a nice guy!" << endl; } }; class Woman: public Human{ public: Woman(string name, int age){ this->name = name; this->age = age; } virtual void introduce(){ Human::introduce(); cout << "I am a cute girl!" << endl; } }; int main(int argc, char* argv[]){ Human* m = new Man("Jack", 25); Human* w = new Woman("Jill", 21); size_t len; char* data; unsigned int op; while(1){ cout << "1. use\n2. after\n3. free\n"; cin >> op; switch(op){ case 1: m->introduce(); w->introduce(); break; case 2: len = atoi(argv[1]); data = new char[len]; read(open(argv[2], O_RDONLY), data, len); cout << "your data is allocated" << endl; break; case 3: delete m; delete w; break; default: break; } } return 0; } | cs |
Use After Free 취약점은 Heap 영역의 Allocation/Free에서 발생할 수 있는 취약점입니다. 컴퓨터는 보통 실행 시간을 위해 객체를 Free하고 나더라도 메모리 상에서 객체가 점유하고있던 공간의 값을 없애버리지는 않습니다. 거기에 접근할 수 있는 포인터만 지웁니다. 즉 지워졌다고 생각한 정보가 사실은 지워졌지 않을 수 있습니다. 이것만으로도 안 좋은 상황을 만들어낼 수 있는데 한 술 더 떠 Reallocation을 할 때 만약 이전의 객체와 동일한 크기를 요구한다면 컴퓨터는 실행 시간을 위해 이전의 객체가 점유하던 메모리 영역을 그대로 넘겨줍니다. 즉 새로운 객체는 이전의 영역을 마음대로 조작할 수 있게 되고, 그 상황에서 새로운 객체가 동일한 메모리에 접근했음을 모르는 선량한 사용자가 메모리 값을 참조해 무언가를 실행할 경우 해킹의 가능성이 존재합니다.
위의 코드에서 저희는 introduce() 함수를 실행하거나, 내가 만든 임의의 파일의 값을 새로 생성한 data 객체에 쓰거나, m, w 객체를 제거하는 세 가지 행동을 할 수 있습니다. 공격 시나리오는 아래와 같을 것입니다.
1. free를 이용해 m, w 객체를 Free 시킨다. 이게 선행되지 않으면 객체 내의 값들을 마음대로 바꿀 수 없습니다.
2. after를 이용해 introduce() 함수를 실행할 때 give_shell() 함수가 실행되게끔 한다. 이를 위해서는 코드를 바꾸거나 introduce()를 가리키는 포인터의 값을 바꿔야하는데 딱 봐도 후자가 더 쉬울 것 같네요.
3. use를 통해 introduce() 함수(로 위장된 give_shell() 함수)를 실행한다.
그러면 이제 객체의 크기는 얼마인지, introduce()를 가리키는 포인터의 값은 어떻게 바꿀지 일단 readelf로 싹 긁어서 최대한 뽑을 수 있는 정보를 다 뽑고 부족한게 있다면 동적 분석을 해보겠습니다.
Symbol table '.symtab' contains 119 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000400238 0 SECTION LOCAL DEFAULT 1
2: 0000000000400254 0 SECTION LOCAL DEFAULT 2
3: 0000000000400274 0 SECTION LOCAL DEFAULT 3
4: 0000000000400298 0 SECTION LOCAL DEFAULT 4
5: 00000000004002d8 0 SECTION LOCAL DEFAULT 5
6: 00000000004005f0 0 SECTION LOCAL DEFAULT 6
7: 00000000004008a6 0 SECTION LOCAL DEFAULT 7
8: 00000000004008e8 0 SECTION LOCAL DEFAULT 8
9: 0000000000400958 0 SECTION LOCAL DEFAULT 9
10: 00000000004009d0 0 SECTION LOCAL DEFAULT 10
11: 0000000000400c28 0 SECTION LOCAL DEFAULT 11
12: 0000000000400c40 0 SECTION LOCAL DEFAULT 12
13: 0000000000400de0 0 SECTION LOCAL DEFAULT 13
14: 0000000000401488 0 SECTION LOCAL DEFAULT 14
15: 00000000004014a0 0 SECTION LOCAL DEFAULT 15
16: 0000000000401600 0 SECTION LOCAL DEFAULT 16
17: 0000000000401680 0 SECTION LOCAL DEFAULT 17
18: 00000000004018a4 0 SECTION LOCAL DEFAULT 18
19: 0000000000601de0 0 SECTION LOCAL DEFAULT 19
20: 0000000000601de8 0 SECTION LOCAL DEFAULT 20
21: 0000000000601df8 0 SECTION LOCAL DEFAULT 21
22: 0000000000601e08 0 SECTION LOCAL DEFAULT 22
23: 0000000000601e10 0 SECTION LOCAL DEFAULT 23
24: 0000000000601fe0 0 SECTION LOCAL DEFAULT 24
25: 0000000000601fe8 0 SECTION LOCAL DEFAULT 25
26: 00000000006020c8 0 SECTION LOCAL DEFAULT 26
27: 00000000006020e0 0 SECTION LOCAL DEFAULT 27
28: 0000000000000000 0 SECTION LOCAL DEFAULT 28
29: 0000000000400e0c 0 FUNC LOCAL DEFAULT 13 call_gmon_start
30: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
31: 0000000000601de8 0 OBJECT LOCAL DEFAULT 20 __CTOR_LIST__
32: 0000000000601df8 0 OBJECT LOCAL DEFAULT 21 __DTOR_LIST__
33: 0000000000601e08 0 OBJECT LOCAL DEFAULT 22 __JCR_LIST__
34: 0000000000400e30 0 FUNC LOCAL DEFAULT 13 __do_global_dtors_aux
35: 00000000006023d8 1 OBJECT LOCAL DEFAULT 27 completed.6531
36: 00000000006023e0 8 OBJECT LOCAL DEFAULT 27 dtor_idx.6533
37: 0000000000400ea0 0 FUNC LOCAL DEFAULT 13 frame_dummy
38: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
39: 0000000000601df0 0 OBJECT LOCAL DEFAULT 20 __CTOR_END__
40: 00000000004018a0 0 OBJECT LOCAL DEFAULT 17 __FRAME_END__
41: 0000000000601e08 0 OBJECT LOCAL DEFAULT 22 __JCR_END__
42: 0000000000401450 0 FUNC LOCAL DEFAULT 13 __do_global_ctors_aux
43: 0000000000000000 0 FILE LOCAL DEFAULT ABS uaf.cpp
44: 00000000006023e8 1 OBJECT LOCAL DEFAULT 27 _ZStL8__ioinit
45: 0000000000401124 64 FUNC LOCAL DEFAULT 13 _Z41__static_initializati
46: 0000000000401164 21 FUNC LOCAL DEFAULT 13 _GLOBAL__sub_I_main
47: 0000000000401530 8 OBJECT LOCAL DEFAULT 15 _ZZL18__gthread_active_pv
48: 0000000000601fe8 0 OBJECT LOCAL DEFAULT 25 _GLOBAL_OFFSET_TABLE_
49: 0000000000601de8 0 NOTYPE LOCAL DEFAULT 19 __init_array_end
50: 0000000000601de0 0 NOTYPE LOCAL DEFAULT 19 __init_array_start
51: 0000000000601e10 0 OBJECT LOCAL DEFAULT 23 _DYNAMIC
52: 00000000006020c8 0 NOTYPE WEAK DEFAULT 26 data_start
53: 00000000006020e0 280 OBJECT GLOBAL DEFAULT 27 _ZSt3cin@@GLIBCXX_3.4
54: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSsC1Ev@@GLIBCXX_3.4
55: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSolsEi@@GLIBCXX_3.4
56: 0000000000401440 2 FUNC GLOBAL DEFAULT 13 __libc_csu_fini
57: 00000000004015d0 24 OBJECT WEAK DEFAULT 15 _ZTI3Man
58: 0000000000400de0 0 FUNC GLOBAL DEFAULT 13 _start
59: 0000000000401580 32 OBJECT WEAK DEFAULT 15 _ZTV5Human
60: 0000000000401192 125 FUNC WEAK DEFAULT 13 _ZN5Human9introduceEv
61: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
62: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _Jv_RegisterClasses
63: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _Znam@@GLIBCXX_3.4
64: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZdlPv@@GLIBCXX_3.4
65: 0000000000401488 0 FUNC GLOBAL DEFAULT 14 _fini
66: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitC1Ev@@
67: 0000000000000000 0 FUNC GLOBAL DEFAULT UND read@@GLIBC_2.2.5
68: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_
69: 0000000000000000 0 FUNC GLOBAL DEFAULT UND system@@GLIBC_2.2.5
70: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __cxa_atexit@@GLIBC_2.2.5
71: 000000000040123a 41 FUNC WEAK DEFAULT 13 _ZN5HumanD1Ev
72: 0000000000400ce0 0 FUNC GLOBAL DEFAULT UND _ZNSt8ios_base4InitD1Ev@@
73: 00000000004015e8 7 OBJECT WEAK DEFAULT 15 _ZTS5Human
74: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZStlsISt11char_traitsIcE
75: 0000000000401308 109 FUNC WEAK DEFAULT 13 _ZN5WomanC1ESsi
76: 00000000004014a0 4 OBJECT GLOBAL DEFAULT 15 _IO_stdin_used
77: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSsD1Ev@@GLIBCXX_3.4
78: 00000000004015c8 5 OBJECT WEAK DEFAULT 15 _ZTS3Man
79: 00000000006020c8 0 NOTYPE GLOBAL DEFAULT 26 __data_start
80: 0000000000602200 88 OBJECT WEAK DEFAULT 27 _ZTVN10__cxxabiv117__clas
81: 00000000004015b0 24 OBJECT WEAK DEFAULT 15 _ZTI5Woman
82: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSsC1EPKcRKSaIcE@@GLIBC
83: 0000000000401560 32 OBJECT WEAK DEFAULT 15 _ZTV3Man
84: 0000000000602260 272 OBJECT GLOBAL DEFAULT 27 _ZSt4cout@@GLIBCXX_3.4
85: 000000000040117a 24 FUNC WEAK DEFAULT 13 _ZN5Human10give_shellEv
86: 00000000006020d0 0 OBJECT GLOBAL HIDDEN 26 __dso_handle
87: 0000000000401376 54 FUNC WEAK DEFAULT 13 _ZN5Woman9introduceEv
88: 0000000000601e00 0 OBJECT GLOBAL HIDDEN 21 __DTOR_END__
89: 00000000004013b0 137 FUNC GLOBAL DEFAULT 13 __libc_csu_init
90: 0000000000000000 0 FUNC GLOBAL DEFAULT UND atoi@@GLIBC_2.2.5
91: 0000000000401210 41 FUNC WEAK DEFAULT 13 _ZN5HumanC2Ev
92: 0000000000401210 41 FUNC WEAK DEFAULT 13 _ZN5HumanC1Ev
93: 0000000000401540 32 OBJECT WEAK DEFAULT 15 _ZTV5Woman
94: 0000000000401264 109 FUNC WEAK DEFAULT 13 _ZN3ManC1ESsi
95: 00000000006020d8 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
96: 0000000000602380 88 OBJECT WEAK DEFAULT 27 _ZTVN10__cxxabiv120__si_c
97: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZStlsIcSt11char_traitsIc
98: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSaIcED1Ev@@GLIBCXX_3.4
99: 0000000000401308 109 FUNC WEAK DEFAULT 13 _ZN5WomanC2ESsi
100: 0000000000401264 109 FUNC WEAK DEFAULT 13 _ZN3ManC2ESsi
101: 00000000004015f0 16 OBJECT WEAK DEFAULT 15 _ZTI5Human
102: 0000000000000000 0 NOTYPE WEAK DEFAULT UND pthread_cancel
103: 00000000006023f0 0 NOTYPE GLOBAL DEFAULT ABS _end
104: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSolsEPFRSoS_E@@GLIBCXX
105: 00000000004015a0 7 OBJECT WEAK DEFAULT 15 _ZTS5Woman
106: 0000000000400d60 0 FUNC GLOBAL DEFAULT UND _ZSt4endlIcSt11char_trait
107: 00000000006020d8 0 NOTYPE GLOBAL DEFAULT ABS _edata
108: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSaIcEC1Ev@@GLIBCXX_3.4
109: 0000000000400d80 0 FUNC GLOBAL DEFAULT UND __gxx_personality_v0@@CXX
110: 00000000004012d2 54 FUNC WEAK DEFAULT 13 _ZN3Man9introduceEv
111: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _Znwm@@GLIBCXX_3.4
112: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _Unwind_Resume@@GCC_3.0
113: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSsaSERKSs@@GLIBCXX_3.4
114: 0000000000000000 0 FUNC GLOBAL DEFAULT UND open@@GLIBC_2.2.5
115: 0000000000400ec4 608 FUNC GLOBAL DEFAULT 13 main
116: 0000000000400c28 0 FUNC GLOBAL DEFAULT 11 _init
117: 0000000000000000 0 FUNC GLOBAL DEFAULT UND _ZNSirsERj@@GLIBCXX_3.4
118: 000000000040123a 41 FUNC WEAK DEFAULT 13 _ZN5HumanD2Ev
보고싶은 주소값들이 얼추 다 들어있네요. symbol이 제거가 안되서 편하네요.
이제 Woman->introduce()의 값이 어떻게 저장되는지만 확인하면 될 것 같습니다. gdb로 따라가면서 확인해보겠습니다.
disas main을 해보면 switch문 분기점으로 추정되는 부분을 알 수 있습니다. 이제 저희는 write하는 부분을 보고싶으니 case 2에 해당하는 *main+316에 breakpoint를 걸고 after를 선택해 진행해보겠습니다.
ing
'워게임 > Pwnable.kr' 카테고리의 다른 글
[Pwnable.kr] cmd2 (0) | 2018.01.15 |
---|---|
[Pwnable.kr] cmd1 (0) | 2018.01.15 |
[Pwnable.kr] lotto (0) | 2018.01.15 |
[Pwnable.kr] blackjack (0) | 2018.01.15 |
[Pwnable.kr] coin1 (3) | 2018.01.15 |
[Pwnable.kr] shellshock (0) | 2018.01.15 |