!

我们在写代码的时候,按约定都是把成员数据放到private访问区中,然后在通过相应的函数来存取。那又有什么样的代码可以突破访问权限来直接操作类中private区段中的成员数据呢?

首先,我们想到了指针,对吧~指针可是万能之王,然而也是万恶之源。那我们就先来看看指针如何突破马其诺防线的。

先定义一个测试类

class X
{
private :
    int m_nPrivate;

public :
    X()
    : m_nPrivate( 1)
    { }

template < typename T >
void Func( const T &t) // 类中存在一个模板函数
 { }

    const  int GetValue()
    {
        return m_nPrivate;
    }
};
很简单是吧,私有成员m_nPrivate就是我们的目标。来看看突破代码:
void *p = &x;// 获取类的起始地址,其实也就是m_nPrivate数据成员的地址
int *n = (int *)p;

int tmp = 2; 
*n = tmp; // 改写其值

cout << x.GetValue() << endl; // 输出为2
利用指针偏移
好了,成功突破!我们再来看看其他的方式。

1.伪造者方式
这个伎俩是现将某个有待伪造的类定义复制一份,然后通过该复制后的“赝品”来达到目的,且看
void Hijack(X  &x)
{
    x.m_nPrivate  =  2;
}

class X
{
// 手工添加
friend  : :Hijack(X  &);

// 这里是复制X类定义
private :
    int m_nPrivate;

public :
    X()
    : m_nPrivate( 1)
    {}

template < typename T >
void Func( const T &t)
{}

const  int GetValue()
{
return m_nPrivate;
}
};

类定义覆盖(改写类定义)失败
这个伎俩被VC2008的编译器逮住了,没有编译通过。因为他违反了唯一定义规则(ODR,One Definition Rule)。看来语言律师还是不会放过这种没脑子的造假者!打假、打假,越打越假!
2. 偷窃者方式
偷偷的改变定义类的含义。且看:
# define  private  public // 万恶的宏伎俩啊

void Hijack(X  &x)
{
    x.m_nPrivate  =  2;
}

他的两根手指头很灵活哟。在VC2008成功执行得到。然而他却有两个违背标准的行为:

1)#define 保留字是非法的

2)违反了唯一定义规则(ODR),然而类的底层内存布局没改变,故可行

用#define private public 偷梁换柱


3.骗子方式

// 同X的内存布局,只有一个int型的变量
class BaitSwitch 
{
public :
    int m_nNotPrivate;
};

void Func(X  &x)
{
( reinterpret_cast(x)).m_nNotPrivate = 2;
}
在VC2008上成功运行达到目的,但是却有漏洞:
标准中reinterpret_cast的行为未定义,VC2008允许返回的结果引用。所以也成功让骗子得逞。
仿造相同内存结构的新public类,指针类型转换

4.语言律师方式
律师就是钻法律的漏洞,永远也不会被逮住,他是在钻法律的空子!且看
namespace
{
    struct Y{};
}

template < >
void X : :Func( const Y &)
{
    m_nPrivate  =  2;
}

void Test()
{
    X x;
    cout  << x.GetValue()  << endl;

    x.Func(Y());
    cout  << x.GetValue()  << endl;
}

他能成功主要是利用了X具有一个成员模板的事实,代码完全符合标准,标准也确保这种行为会按照编码者的意图行事。boost和loki中大量运用此手法。
模板编译的过程在实际编译以前...活生生的给X类添加了一个成员函数.
原来,类里面有一个实现了的模板函数!
那么在外面再加一个模板函数,导致模板推演的过程中多出来一个自己写的并且加入了备选组中,所以相当于多了一个重载。
并且由于此函数的参数是匿名空间里面的特定的类别,完全避免了搅乱原本该函数的功能。
高招啊!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值