首页
学习
活动
专区
圈层
工具
发布
21 篇文章
1
《coredump问题原理探究》Linux x86版6.3节有成员变量的类coredump例子
2
《coredump问题原理探究》Linux x86版6.5节虚函数的coredump例子
3
《coredump问题原理探究》Linux x86版6.8节多继承coredump例子
4
《coredump问题原理探究》Linux x86版7.2节vector coredump例子
5
《coredump问题原理探究》Linux x86版7.4节List coredump例子
6
《coredump问题原理探究》Linux x86版7.6节 Map coredump例子
7
《coredump问题原理探究》Linux x86版5.9节C风格数据结构内存布局之联合体
8
《coredump问题原理探究》Linux x86版6.1节C++风格数据结构内存布局之无成员变量的类
9
《coredump问题原理探究》Linux x86版6.2节C++风格数据结构内存布局之有成员变量的类
10
《coredump问题原理探究》Linux x86版4.5节函数的逆向之coredump例子
11
《coredump问题原理探究》Linux x86版5.1节C风格数据结构内存布局之引言
12
《coredump问题原理探究》Linux x86版5.2节C风格数据结构内存布局之基本数据类型
13
《coredump问题原理探究》Linux x86版5.3节C风格数据结构内存布局之数组
14
《coredump问题原理探究》Linux x86版5.4节C风格数据结构内存布局之数组coredump例子
15
《coredump问题原理探究》Linux x86版5.5节C风格数据结构内存布局之基本数据类型构成的结构体
16
《coredump问题原理探究》Linux x86版5.6节C风格数据结构内存布局之复合类型构成的结构体
17
《coredump问题原理探究》Linux x86版5.7节C风格数据结构内存布局之结构体数组
18
《coredump问题原理探究》Linux x86版5.8节C风格数据结构内存布局之结构体数组结构体coredump
19
《coredump问题原理探究》Linux x86版3.5节栈布局之-fomit-frame-pointer编译选项
20
《coredump问题原理探究》Linux x86版3.6节栈布局之gcc内嵌关键字
21
《coredump问题原理探究》Linux x86版3.8节栈布局之栈溢出coredump例子

《coredump问题原理探究》Linux x86版6.8节多继承coredump例子

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://cloud.tencent.com/developer/article/1344552

下面看一个coredump的例子:

代码语言:javascript
复制
(gdb) bt
#0  0x08048662 in xuzhina_dump_c06_s5_ex_child::inheritFrom(char*, int) ()
#1  0x08048609 in main ()

先看一下xuzhina_dump_c06_s5_ex_child::inheritFrom的汇编:

代码语言:javascript
复制
(gdb) disassemble 0x08048662
Dump of assembler code for function _ZN28xuzhina_dump_c06_s5_ex_child11inheritFromEPci:
   0x08048640 <+0>:     push   %ebp
   0x08048641 <+1>:     mov    %esp,%ebp
   0x08048643 <+3>:     sub    $0x18,%esp
   0x08048646 <+6>:     mov    0x8(%ebp),%eax
   0x08048649 <+9>:     mov    (%eax),%eax
   0x0804864b <+11>:    mov    (%eax),%eax
   0x0804864d <+13>:    mov    0x8(%ebp),%edx
   0x08048650 <+16>:    mov    0xc(%ebp),%ecx
   0x08048653 <+19>:    mov    %ecx,0x4(%esp)
   0x08048657 <+23>:    mov    %edx,(%esp)
   0x0804865a <+26>:    call   *%eax
   0x0804865c <+28>:    mov    0x8(%ebp),%eax
   0x0804865f <+31>:    mov    0xc(%eax),%eax
=> 0x08048662 <+34>:    mov    (%eax),%eax
   0x08048664 <+36>:    mov    0x8(%ebp),%edx
   0x08048667 <+39>:    lea    0xc(%edx),%ecx
   0x0804866a <+42>:    mov    0x10(%ebp),%edx
   0x0804866d <+45>:    mov    %edx,0x4(%esp)
   0x08048671 <+49>:    mov    %ecx,(%esp)
   0x08048674 <+52>:    call   *%eax
   0x08048676 <+54>:    mov    0x8(%ebp),%eax
   0x08048679 <+57>:    movl   $0x1,0x14(%eax)
   0x08048680 <+64>:    leave  
   0x08048681 <+65>:    ret    
End of assembler dump.

代码语言:javascript
复制
   0x0804865c <+28>:    mov    0x8(%ebp),%eax
   0x0804865f <+31>:    mov    0xc(%eax),%eax
=> 0x08048662 <+34>:    mov    (%eax),%eax
   0x08048664 <+36>:    mov    0x8(%ebp),%edx
   0x08048667 <+39>:    lea    0xc(%edx),%ecx
   0x0804866a <+42>:    mov    0x10(%ebp),%edx
   0x0804866d <+45>:    mov    %edx,0x4(%esp)
   0x08048671 <+49>:    mov    %ecx,(%esp)
   0x08048674 <+52>:    call   *%eax

可以知道来看,eax是一个虚函数表指针

由崩溃指令来看,eax所指向地址非法,而eax是由this加上0xc偏移值得到,this放在ebp+0x8

看一下this所指向的内容

代码语言:javascript
复制
(gdb) x /x $ebp+8 
0xbff59da0:     0x08c03008
(gdb) x /8x 0x08c03008
0x8c03008:      0x08048798      0x6c6c6548      0x726f576f      0x6854646c
0x8c03018:      0x73497369      0x69766544      0x0000006c      0x00020fe1

由于这个地址0x08c03008下一个单元0x08c0300c及后续几个单元的每个字节都少于0x80,有可能是ascii码.

而且还可以由

代码语言:javascript
复制
(gdb) i r eax
eax            0x6854646c       1750361196

看到eax的值放在0x8c03014这个单元。

看一下0x08c0300c开始的是不是字符串:

代码语言:javascript
复制
(gdb) x /s 0x08c0300c
0x8c0300c:       "HelloWorldThisIsDevil"
(gdb) x /s 0x8c03014
0x8c03014:       "ldThisIsDevil"

可见,确实是有一个字符串在里面,且this+0xc这个虚函数表指针刚好是字符串” ldThisIsDevil”.说明刚好是被前面的成员变量覆盖了.为什么被覆盖了?

在xuzhina_dump_c06_s5_ex!xuzhina_dump_c06_s5_ex_child::inheritFrom这个函数里,有两处调用.先看一下前一个调用是什么,有没有可能把这个虚函数表指针给覆盖掉,如果没有,就看一下main函数有没有调用这个类的其它成员函数了.

由这一段指令

代码语言:javascript
复制
   0x08048646 <+6>:     mov    0x8(%ebp),%eax
   0x08048649 <+9>:     mov    (%eax),%eax
   0x0804864b <+11>:    mov    (%eax),%eax
   0x0804864d <+13>:    mov    0x8(%ebp),%edx
   0x08048650 <+16>:    mov    0xc(%ebp),%ecx
   0x08048653 <+19>:    mov    %ecx,0x4(%esp)
   0x08048657 <+23>:    mov    %edx,(%esp)
   0x0804865a <+26>:    call   *%eax

可以知道,这个函数是从第一个虚函数表取出来的第一个函数.

代码语言:javascript
复制
(gdb) x /x $ebp+8 
0xbff59da0:     0x08c03008
(gdb) x /4x 0x08c03008
0x8c03008:      0x08048798      0x6c6c6548      0x726f576f      0x6854646c
(gdb) x /4x 0x08048798
0x8048798 <_ZTV28xuzhina_dump_c06_s5_ex_child+8>:       0x08048614      0x08048640      0xfffffff4      0x08048800

从上面可以看到,是调用了setName这个函数,有一个参数.这个参数的值在xuzhina_dump_c06_s5_ex_child::inheritFrom由ebp+c传入.

看一下ebp+c的内容:

代码语言:javascript
复制
(gdb) x /x $ebp+0xc
0xbff59da4:     0xbff5a672
(gdb) x /s 0xbff5a672
0xbff5a672:      "HelloWorldThisIsDevil"

由这可以推断,是由xuzhina_dump_c06_s5_ex_father::setName这个函数导致第二个虚函数表指针被改写的.

看一下xuzhina_dump_c06_s5_ex_father::setName做了什么事情:

代码语言:javascript
复制
(gdb) disassemble _ZN29xuzhina_dump_c06_s5_ex_father7setNameEPc
Dump of assembler code for function _ZN29xuzhina_dump_c06_s5_ex_father7setNameEPc:
   0x08048614 <+0>:     push   %ebp
   0x08048615 <+1>:     mov    %esp,%ebp
   0x08048617 <+3>:     sub    $0x18,%esp
   0x0804861a <+6>:     mov    0x8(%ebp),%eax
   0x0804861d <+9>:     lea    0x4(%eax),%edx
   0x08048620 <+12>:    mov    0xc(%ebp),%eax
   0x08048623 <+15>:    mov    %eax,0x4(%esp)
   0x08048627 <+19>:    mov    %edx,(%esp)
   0x0804862a <+22>:    call   0x8048490 <strcpy@plt>
   0x0804862f <+27>:    leave  
   0x08048630 <+28>:    ret    
End of assembler dump.

通过逆向上面的汇编,可以得到这一个函数是参数1的值一个字符一个字符地复制到这个对象的第一个成员变量(this+4)里.在这个coredump里,参数1的值是”HelloWorldThisIsDevil”,长度为21,由第一个参数开始,即(+4).而这个对象的第二个虚函数表指针位于+c的位置,刚好被” ldThisIsDevil”来覆盖.

源代码如下:

代码语言:javascript
复制
  1 #include <string.h>
  2 class xuzhina_dump_c06_s5_ex_father
  3 {
  4     private:
  5         char m_name[8];
  6     public:
  7         virtual void setName( char* name )
  8         {
  9             strcpy( m_name, name );
 10         }
 11 };
 12 
 13 class xuzhina_dump_c06_s5_ex_mother
 14 {
 15     private:
 16         int m_nature;
 17     public:
 18         virtual void setNature( int nature )
 19         {
 20             m_nature = nature;
 21         }
 22 };
 23 
 24 class xuzhina_dump_c06_s5_ex_child: public xuzhina_dump_c06_s5_ex_father,
 25     public xuzhina_dump_c06_s5_ex_mother
 26 {
 27     private:
 28         int m_sweet;
 29     public:
 30         virtual void inheritFrom( char* lastName, int nature )
 31         {
 32             setName( lastName );
 33             setNature( nature );
 34             m_sweet = 1;
 35         }
 36 };
 37
38 int main( int argc, char* argv[] )
 39 {
 40     if ( argc < 2 )
 41     {
 42         return -1;
 43     }
 44 
 45     xuzhina_dump_c06_s5_ex_child* child = new xuzhina_dump_c06_s5_ex_child;
 46     child->inheritFrom( argv[1], 1 );
 47 
 48     return 0;
 49 }
下一篇
举报
领券