# Pwning in C++ - ở bài viết này mình sẽ đi qua vấn đề exploit trên binary được compiled bằng source C++ (cpp) - và giải thích bằng tiếng mẹ đẻ cho thân thuộc =)))) > sai xót ở đâu thì comment hay inbox cho mình sửa nhe ## Overview - Virtual Function Table - Vtable Hijacking ([ref in C](https://hackmd.io/@trhoanglan04/bof_advanced_level#fake-vtable)) - Vector & String - New & Delete - Copy constructor & assignment operator ## Virtual Function Table - là key mechanism để hỗ trợ polymorphism (tính đa hình) trong C++ - với mỗi class có virtual function (hàm ảo), tuỳ theo class inheritance (phân cấp) mà compiler sẽ tạo 1 hoặc nhiều virtual function table - examble: ```cpp #include <iostream> using namespace std; class Person { public : virtual void speak(){;} virtual void phd(){;} private : int a; }; class Stu : public Person { public : virtual void speak(){;} virtual void pwn(){;} private : int b; }; int main(void){ Person *ddaa = new Person(); Stu *meh = new Stu(); ddaa->speak(); meh->speak(); meh->pwn(); return 0; } ``` - sau khi `new` 2 objects **Person** và **Stu** ![image](https://hackmd.io/_uploads/ByHM-kYX0.png) > vtable của class con Stu sẽ kế thừa **phd()** từ class cha Person > **vfptr** viết tắt của **V**irtual **F**unction **ptr**(Pointer) > **NOTE** : **vfptr** is writeable - khi call `ddaa->speak()` ```c vfptr == *ddaa //(get vfptr) call *vfptr //(Person::speak(ddaa)) ``` ![image](https://hackmd.io/_uploads/ByihU1Ym0.png) - khi call `meh->speak()` ```c vfptr == *meh //(get vfptr) call *vfptr //(Stu::speak(meh)) ``` ![image](https://hackmd.io/_uploads/SkDLD1YQR.png) - khi call `meh->pwn()` ```c vfptr == *meh //(get vfptr) call *(vfptr+0x10) //(Stu::pwn(meh)) ``` ![image](https://hackmd.io/_uploads/Sy0GuyKm0.png) ### Vtable Hijacking - cần thoả mãn 1 số vulnerability trên Heap: > UAF, Heap Overflow, ... - Poison vtable and hijack the **vfptr** - example: ![image](https://hackmd.io/_uploads/SJAb91YXA.png) > ow **vfptr** of vtable in ddaa (target) > hijack **vfptr** of vtable in meh (point to target) - khi call `meh->speak()` ```c vfptr == *meh //(get vfptr) call *vfptr // call shellcode(meh) ``` ![image](https://hackmd.io/_uploads/BJ8p51Y7R.png) ===> ==PWNED== > nếu NX enable, thay bằng one_gadget hoặc other available value place ## Vector & String ### Vector #### overview - là 1 mảng động (dynamic array) - phân bổ trên phân đoạn heap (allocated in heap segment) - linh hoạt hơn mảng trong code C > khi không đủ chỗ trống, tạo `new` vector size gấp đôi và space cũ sẽ trả về hệ thống (system) #### remmember - member: - `_M_start` : vector start position - **vector::begin()** - `_M_finish` : vector end position - **vector::end()** - `_M_end_of_strorage` : last position of the container - if `_M_finish == _M_end_of_storage` in `push_back()` - alloca new space for vector - use for check enough space for element - member function - `.push_back()` : add new element into the end of the vector - `.pop_back()` : remove the last element of vector - `.insert()` : insert an element into n's position of the vector - `.erase()` : remove n elements from vector ### Vector Layout ![image](https://hackmd.io/_uploads/SJMyllYm0.png) - khi `.push_back()` : ![image](https://hackmd.io/_uploads/BJbIWlKQA.png) > `_M_finish == _M_end_of_storage` ![image](https://hackmd.io/_uploads/HkAxxgtmR.png) > -> blue block will be deleted first ![image](https://hackmd.io/_uploads/Sk6EZxt7A.png) > -> new vector will be create > ---> old value will be copied ![image](https://hackmd.io/_uploads/BJGQfgtQA.png) >similar (for example) ![image](https://hackmd.io/_uploads/HyaVzeYXA.png) > pwn is end function in class - khi `.pop_back()` ![image](https://hackmd.io/_uploads/HytIXlYQA.png) > call destructor of pwn string ### String #### overview - là 1 mảng kí tự động (dynamic char array) - an toàn hơn mảng chuỗi (string array) > tất cả bộ nhớ sẽ phân bổ động (dynamically allocated) để giảm khả năng xuất hiện BOF - khi **input** được gọi, bộ nhớ liên tục tái phân bổ (reallocated) cho user đến khi kết thúc > kích thước phù hợp sẽ được return > dễ hiểu là `cin >> ` bao nhiêu sẽ malloc bấy nhiêu #### remmember - member: - `size` : length of string - `capacity` : capacity of string space - `reference count` : refcnt - strings is incremented whenever other elements refer to it - if other elements are no longer referenced ---> reduced - `reference < 0` : space will be deleted - `value` : store the string content - member function: - `length()` : string size - `capacity()` : current string space capacity - `c_str()` : get C string equivalent ### String Layout - examble: ![image](https://hackmd.io/_uploads/SJK3UlYmR.png) ![a](https://hackmd.io/_uploads/B1d4PeK7A.png) ![b](https://hackmd.io/_uploads/SykSwlK7A.png) ![d](https://hackmd.io/_uploads/BkotulYQR.png) - thu được công thức cho capacity là: - cấp số nhân 2 lớn hơn và gần size nhất > cho đến khi input kết thúc - khi `.push_back()` : ![image](https://hackmd.io/_uploads/BJzSjoFQ0.png) > 1 push_back = 1 reference > ---> **refcnt** = 1 ![r](https://hackmd.io/_uploads/r1D-12YQC.png) > 2 push_back = 2 reference > ---> **refcnt** = 2 - khi `.pop_back()` : ![p](https://hackmd.io/_uploads/S1WU-hK7R.png) > 1 pop_back will decrease **refcnt** > call str destructor nhưng không xoá space ![q](https://hackmd.io/_uploads/HJYAM2tX0.png) > next pop_back will let **refcnt** = 0 > call str destructor nhưng không xoá space ![y](https://hackmd.io/_uploads/HycFNnt70.png) > vẫn call destructor nhưng lần này vì **refcnt** < 0 nên sẽ xoá space ## New & Delete - mặc định trong C++, `new` và `delete` vẫn dựa vào **malloc()** và **free()** để handle memory management - nhưng `new` và `delete` có thể bị overloaded > ---> do memory management by itself - sự khác nhau lớn nhất là `new` và `delete` là sẽ call constructor/destructor, trong khi **malloc()** và **free()** chỉ thực hiện cấu hình bộ nhớ đơn giản - **NOTE**: cố gắng không mix `malloc/free` với `new/delete` > không thì 1 số tình huống unpredictable sẽ xảy ra ### New - `operator new` - tương tự như **malloc()** - đơn giản là cấu hình không gian bộ nhớ > nhưng nếu cấu hình fail > ---> an exception will be entered trong khi **malloc()** return NULL - a bit like a wrapper above **malloc()** - constructor ### Delete - destructor - `operator delete` - tương tự như **free()** - giải phóng không gian bộ nhớ - a bit like a wrapper on **free()** ### compare - memory function matching: | Configuration function | Dismiss fuction | |:----------------------:|:------------------:| | new | delete | | new [] | delete [] | | operator new | operator delete | | operator new [] | operator delete [] | | malloc | free | ## Copy & Assignment - BUG examble: ```c #include <iostream> #include <string> #include <vector> #include <string.h> using namespace std; class Stu{ public : Stu():name(NULL),id(0){} Stu(string str, int stuid){ name = new char[str.length()+1]; strcpy(name,str.c_str()); id = stuid; } void putinfo(){ cout << id << ":" << name << endl; } ~Stu(){ delete [] name; } private : int id; char *name; }; int main(void) { vector<Stu> stulist ; Stu student = Stu("orange",1337); stulist.push_back(student); stulist[0].putinfo(); return 0; } ``` ![image](https://hackmd.io/_uploads/HyhzK6tm0.png) #### Copy constructor - C++ dùng copy constructor khi copying objects - khi member của 1 class có indicator, cần phải implement it yourself - nếu không được defined, default copy constructor sẽ được dùng - shadow copy #### Assignment operator - khi C++ thực hiện toán tử "=", object sẽ sử dụng assignment operator function (hàm toán tử gán) - khi member của 1 class có indicator, cần phải implement it yourself - nếu không được defined, default copy constructor sẽ được dùng - shadow copy ### shadow copy - chỉ copy ptr - content remain the same as the original one ![image](https://hackmd.io/_uploads/r1ZEz6YQA.png) ### deep copy - allocate mới - content pointed to by pointer will also be copied ![image](https://hackmd.io/_uploads/SyMHG6tmR.png) ### analyse BUG - call constructor ```c Stu student = Stu("orange",1337); /* Stu(string str, int stuid){ name = new char[str.length()+1]; strcpy(name,str.c_str()); id = stuid; } */ ``` ![image](https://hackmd.io/_uploads/SyL-haKmA.png) - khi `.push_back()` : ```c stulist.push_back(student); ``` ![image](https://hackmd.io/_uploads/H1Vi3aKmC.png) - khi hết chức năng class ---> call destructor ```c ~Stu(){ delete [] name; ``` ![image](https://hackmd.io/_uploads/H1el_RaYmC.png) - và chính vector cũng sẽ call destructor chính nó > content nó return ===> **DOUBLE FREE** # ref - https://fr.slideshare.net/slideshow/pwning-in-c-basic/58370781 > của Angleboy luôn chất lượng - https://www.youtube.com/watch?v=BnMnozsSPmw > video about operator - https://www.youtube.com/watch?v=PXcRe-W2w7s&t=1036s > Rule of Three - https://www.youtube.com/watch?v=E4MWxaUy3zo > Rule of Five