共有回帖数 0 个
-
先看一个类
#include stdio.h
class A
{
private:
char *str;
public:
A(): str("nothing"){};
};
int main()
{
A a;
return 0;
}
如何输出a的私有成员str所指向的字符串"nothing"?可以任意添加代码,但不可以修改这个类。
★★方法一:
在定义A前,加一句“#define private public”。该方法可以欺骗编译器,让它把“private”当作“public”,然后就可以用“a.str”了。
达到了我们的目的,只可惜这个方法有点“左道旁门”。
★★方法二:
a.str的地址就是a的地址,所以用“puts(*(char**)&a);”即可访问a.str。
★方法二变种:
方法二不错,但如果str不是类的第一个成员变量,就会有点麻烦。比如,把A改成如下形式:
class A
{
private:
char d;
char *str;
public:
A(): str("nothing"){};
};
d占一个字节,a.str的地址相对于a的地址,偏移量为1,可以这么用“puts(*(char**)((char*)&a+1));”。这看似不错,但没有考虑字节对齐
问题。为了能高效的访问变量,编译器可能会以空间换时间,采取字节对齐措施。字节对齐后,程序高效了,但对我们而言就麻烦了。str的地
址的偏移量未必是1,可以是2、4、8等,怎么才能获取a.str的偏移量呢?别急,我们可以给该方法打打补丁。
☆方法二变种的补丁:
在定义A前,加一句“#pragma pack(1)”,这行代码可以让编译器按1字节进行对齐,这样以后就可以放心大胆地用“puts(*(char**)(char*)
&a+1));”了。
★★方法三:
方法二的变种打了补丁后,也有了“左道旁门”的“嫌疑”。方法三就显得“高尚”多了。构造一个和A相似的类,但增加了一个非虚成员函数
,用来返回str的地址。
#include stdio.h
class A
{
private:
char *str;
public:
A(): str("nothing"){};
};
class B
{
private:
char *str;
public:
B(): str("nothing"){};
char *get()
{
return str;
}
};
int main()
{
A a;
puts(((B*)(&a))-get());
return 0;
}
★★方法四:
和方法三一样,也是构造一个新的类。但有所不同的是,“private”变成了“public”。B的布局和A相同,即同名变量的偏移量相同。这样,
我们就可以把A实例的指针转化为B*类型,来访问str了。
#include stdio.h
class A
{
private:
char *str;
public:
A(): str("nothing"){};
};
class B
{
public:
char *str;
public:
B(): str("nothing"){};
};
int main()
{
A a;
//或“puts(((B*)(&a))-str);”
puts(reinterpret_castB*(&a)-str);
return 0;
}
以上方法全是我独立想出来的
事情多,忙啊……总算写完了
——————————
3:
是这样的
这个方法只对某些编译器有效……通用性不够高……
比如VS2005可以用
__asm push a.str;
__asm call puts;
楼主 2016-01-23 10:22 回复
Copyright © 2010~2015 直线网 版权所有,All Rights Reserved.沪ICP备10039589号
意见反馈 |
关于直线 |
版权声明 |
会员须知