Author: rix (rix@securiweb.net)
Backend Note: This article comes from the "Smashing C VPTRS" in Phrack56. As most foreign hackers, technical principles and applications are more detailed, but the source code provided seems to always have a problem. This may be because they feel that the readers should study and debug themselves to better master these technologies. Maybe I will do this later. ; Test environment: operating system: Red Hat 6.1 (i386) Nuclear version: Kernel 2.2.14 Core Patch: None Non-Executable Stack Patch (By Solar Design) C Compiler: GCC --- [Preface]] - ------------------------------------- to the current, the buffer overflower I have mastered is For C programming languages. Although C language programming is almost ubiquitous in UNIX systems, more and more C programs have begun. For most cases, C-language overflow technology is also applicable for C languages, but the object-oriented characteristics of C also results in new buffer overflow technologies. The following is analyzed in the X86 Linux system and the C GNU compiler. --- [[Basis-Simple C Program] ------------------------------------ - I don't want to waste time here to explain too much C language foundation. If you don't know anything about C or object-oriented programming technology, please find this book to see this.
Before you continue to look down, please confirm that you have mastered or understand the following C terms: 1, class (class) 2, Object (object) 3, method (method) 4, Virtual (virtual) 5, Inherit (inherited) 6, DeriVATIVE, then read the following two programs, confirm that you understand the meaning and effect of each statement: // bo1.cpp // C foundation program #include
Object [1] -> PrintBuffer ();} The following is BO2.CPP compiled run results: [Backend @ isbase test]> ./bo2myclass1: string1myclass2: string2 [backnd @ isbase test]> Retreat again, continue When you look down, I am sure that you read the above procedures, especially the object virtual method PrintBuffer (). Unlike the setBuffer () method, the PrintBuffer method must declare and implement in the base class baseclass derived type myclass1 and myclass2. This makes the setBuffer and PrintBuffer methods vary in runtime. --- [[[C virtual pointer (Virtual Pointer, VPTR)] --------------------------------- ----- We know that a virtual method and a non-virtual method are that the call to the non-virtual method is determined when compiling (commonly referred to as "static binding"), but the call of the virtual method is The program is determined (commonly referred to as "dynamic binding"). The baseclass base class and its derived class in the above example are some explanations for dynamic binding mechanisms. The compiler first checks the declaration of the BaseClass base class when compiling. In this case, the compiler first retains 32 bytes for private variables, followed by non-virtual method setBuffer () and specifies the corresponding call address (static binding process), and finally check the virtual method. When PrintBuffer (), dynamic binding processing will be done, ie, 4 bytes assigned in the class to store pointers for the virtual method. The structure is as follows: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbvvvv Description: b Variable buffer is occupied. V Virtual method pointer is occupied. This pointer is often referred to as "VPTR" (Virtual Pointer), which points to one of the function portions in a "vTable" structure. Every class has a vTable. As shown in the figure below: Object [0]: bbbbbbbbbbbbbbbbbbbbbbbbbbbbvvvvv = == | ---------------------------- | -> vtable_myclass1: iiiiiiiiiiiippppppobject [1]: bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbwwww = == | ------------------------------ | -> vtable_myclass2: iiiiiiiiiiiiiiiiqqqq Description: B variable buffer occupied. V Point VPTR pointer to vtable_myclass1. W point to VPTR pointer to vtable_myclass2. I Other Use of data p myclass1 object instance's address pointer's address pointer. Q Myclass2 object instance's address pointer of the printbuffer () method. We can find that the VPTR is behind the Buffer variable in the process memory.
That is, it is possible to overwrite the content of VPTR when calling the dangerous strcpy () function! According to RIX research test, for Visual C 6.0 on the Windows platform, VPTR is located in the starting position of the object, so the technique mentioned here is unable to generate. This is very different from GNU C .
--- [[Analyzed VPTR] -------------------------------------- under Linux Of course, use GDB to analyze: [Backend @ isbase test]> gcc -o bo2 bo2.cpp [Backend @ isbase test]> GDB bo2GNu gdb 4.18copyright 1998 Free Software Foundation, Inc.gdb is Free Software, Covered by the gnu General Public License, and you arewelcome to change it and / or distribute copies of it under certain conditions.Type "show copying" to see the conditions.There is absolutely no warranty for GDB. Type "show warranty" for details.This GDB was Configured as "i386-redhat-linux" ... (GDB) Disassemble MAINDUMP OF Assusser code for function main: 0x8049400
Main 61>: MOV% EAX,% EAX0X804943F
: MOV 0xffffffc (% EBP),% EDX0X804949A
: NOP End of Assembler Dump. (GDB) The following is an explanation for assembly code for the program: 0x8049400
(Gdb) disassemble __9BaseClassDump of assembler code for function __9BaseClass: 0x804c958 <__ 9BaseClass>: push% ebp0x804c959 <__ 9BaseClass 1>: mov% esp,% ebp0x804c95b <__ 9BaseClass 3>: mov 0x8 (% ebp),% edx register EDX now Sticker points to allocated 36 bytes of a pointer ("this" pointer). 0x804c95e <__ 9baseclass 6>: MOVL $ 0x804e01c, 0x20 (% EDX) Store 0x804e01c to EDX 0x20 (= EDX 32). Let's take a look at the 0x804e01c address memory data: (GDB) x 0x804e01c0x804e01c <__ vt_9baseclass>: 0x00000000 You can see the address stored to EDX 0x20 (ie the VPTR position of the object) is a vTable address of base class baseclass. Now return to the constructor of MyClass1 object: 0x804c91c <__ 8myclass1 16>: MOVL $ 0x804e010, 0x20 (% EBX) stores the 0x804e010 to EBX 0x20 (ie VPTR). Similarly let's take a look at the 0x804E010 address memory data: (GDB) x 0x804e0100x804e010 <__ vt_8myclass1>: 0x00000000 Now we know that VPTR is rewritten, then its content is a VTable address of MyClass1 object. When returning to the main () function, the register EAX stores the pointer in the memory. 0x8049420