// 使用" 参数化基类" 和" 成员函数指针" 模拟实现虚函数--在实际中的应用。
#include <stdio.h>
#include <string.h>
/*
病毒或许可以使用这种技术有效地实现,不过这是我在写 Windows PE 文件
加壳程序的时候总结出来的技术。当然可以被用在恶意程序上,任何事情总有两面性!
***注意***
在 VC 中测试时,必须去掉“启用增量连接”,即(/INCREMENTAL:NO)
如果在 ShellCode 或者 Virus 中使用该技术,字符串文字量(string literal)
也必须进行地址转化,即:convert_address("string literal").
使用 "参数化基类 "和 "成员函数指针 "模拟实现虚函数。
可能大家都以为只有疯子才会这么干,好好的虚函数干吗不用,而偏要拐弯抹角地
搞得这么复杂,但有时候这可能是最好地选择。举个例子吧,我写 Windows PE 文件
加壳程序的时候,遇到一个问题:
1. 我开发了一个框架,可以只用 C++ 来写 "壳程序 ",大家很难想到吧!
2. 但不能使用一些 C++ 功能:虚函数,异常处理,还有 switch-case 语句
3. C++ 异常处理可以不用,但是不能使用虚函数可能太过苛刻。
当我看了 "generative programming"以后,觉得 "参数化继承 "
或许可以满足这个需求,模拟实现虚函数。
以下是使用 "参数化继承 "实现虚函数的框架,以及要注意的事项。
BaseClass 显然,实际上是 "抽象基类 ",因为如果实例化
"InstantialClass<ConcreteClass>" 时,ConcreteClass 中
必须定义响应的 "虚函数 ",否则编译就报错。如果相应的
BaseClass 和 InstantialClass 定义正确无误(从代码可以
看到,这很简单,但比较麻烦,必须注意一些细节)。因此
ConcreteClass 编译期错误不会被推迟到运行时才发现,
而使用其它方式模拟,就很难有这个保证。
其实,如果了解 C++ 的底层对象模型,这些需要注意的细节
很容易理解!
//-------
另外有一种 C 语言模拟 C++ 虚函数的方法,可以在我以前
(2002年 )一篇文章中看到。
*/
struct Context
{
int (*printf)(const char *, ...);
// other external fuctions...
};
// construct these codes...
int entry(const Context* context)
{
int imp_entry(const Context* context);
return imp_entry(context);
}
template< typename AddressType >
AddressType convert_address(AddressType address)
{
// if used in shell code, this must return another valid address.
#define SUPPORT_RECLOCATION
#ifdef SUPPORT_RECLOCATION
__asm {
call LL
LL: pop eax
sub eax, offset LL
add eax, address
mov address, eax
}
#endif
return address;
}
class BaseClass
{
#define DEFINE_VIRTUAL(ret , name, param_list, call_list ) \
protected : \
typedef ret (BaseClass ::*T## name) param_list ; \
T## name p ##name; \
public : \
ret name param_list \
{ return ( this->*this ->p## name)call_list ; }
//////////////////////////////////////////////////////////////////////////
// expansion of :
/* DEFINE_VIRTUAL(int, Func1,
(int x1, int x2),
( x1, x2)
);
*/
protected :
typedef int (BaseClass ::*TFunc1)( int x1 , int x2);
TFunc1 pFunc1;
public :
int Func1(int x1, int x2 )
{
return ( this->*this ->pFunc1)( x1, x2 );
// return (this->*pFunc1)(x1, x2); // can be simplified as this line.
}
// end expansion
//////////////////////////////////////////////////////////////////////////
DEFINE_VIRTUAL( int, Func2 ,
(int x1, int x2, int x3 ),
( x1 , x2 , x3 )
);
public :
template< typename BaseFuncType , typename ConcreteFuncType>
void assign(BaseFuncType & x, ConcreteFuncType y )
{
// if use C Style cast like "(BaseFunType)(y)", it is danger!!
// any member function can be assigned to x!!
// x = convert_address((BaseFuncType)(y)); // danger!!
x = convert_address(static_cast <BaseFuncType>(y));
}
BaseClass()
{
pFunc1 = 0;
pFunc2 = 0;
}
};
class ConcreteClass1
{
private :
const Context* context;
int x1, x2 , x3;
public :
ConcreteClass1(const Context* context)
{
this->context = context;
}
int Func1(int x1, int x2)
{
this-> x1 = x1 ;
FONT-SIZE: 9pt; FONT-FAMILY: "Courier New"; mso-font-k
分享到:
相关推荐
第3章 函数-------------------------------------------------------------102 3.1 简介------------------------------------------------------------102 3.2 C++程序组件----------------------------------...
- 虚函数表和虚基类指针增加了对象的大小; - RTTI(运行时类型信息)需要额外的空间和时间; - 多重继承可能会导致“菱形问题”。 ### 技术部分 #### Item25: 虚拟化构造函数和非成员函数 - **定义**:虚拟化...
6. **虚函数和动态联编**:虚函数是实现多态的关键,通过对象指针或引用调用虚函数可以实现动态绑定,即运行时确定函数调用。 7. **派生类和基类关系**:派生类可以继承基类的成员,包括公有、保护和私有成员。基类...
要模拟实现信号/槽,我们可以使用多态、虚函数和回调函数等C++特性。下面是一个简单的实现思路: 1. **定义信号接口**:创建一个基类`SignalBase`,其中包含一个用于连接槽的成员函数,如`connect`。这个函数通常会...
虚函数可以在基类中声明,并可以在派生类中重写,以便实现特定的行为。虚函数可以在类的内部或外部定义,只要在类声明中声明为虚函数即可。因此,A、B选项错误,D选项正确。C选项虽然在技术上是可行的,但在实践中...
- 私有成员在基类中只能被基类的成员函数访问,不能在派生类中直接访问。公有和保护成员的访问权限则根据继承方式有所不同。 6. **派生类与基类的关系**: - 派生类是基类的特化或具体化,它可以扩展基类的功能。...
【计算机二级C++知识点】 ...这些知识点涵盖了C++中的类与对象、继承、运算符重载、构造函数、条件判断、循环结构以及指针和数组的使用。对于准备计算机二级C++考试的人来说,理解并掌握这些内容至关重要。
18. **虚函数调用**:动态多态性通常通过基类对象指针调用虚函数来实现,这样可以调用到实际对象所属类的对应函数。 19. **指针变量**:`*p`表示指针变量的值,即它指向的变量的地址;`p`本身是变量,存储了地址,...
在MFC(Microsoft Foundation Classes)库中,虚函数的使用尤为关键,因为它涉及到消息响应和成员函数的重载。通过重写虚函数,开发者可以定制系统的行为,满足特定需求。 对于vtable的分析,我们可以理解到,每个...
在本模拟试题中,涉及了C++的一些核心概念和特性,以下是相关知识点的详细说明: 1. 构造函数和析构函数: - 构造函数用于在创建对象时初始化对象的状态,它可以重载,即一个类可以有多个构造函数,每个函数有不同...
在派生类中调用基类成员函数时,应使用基类名和作用域解析运算符(::)来调用基类的成员函数(C)。在C++中,派生类对象可以调用基类的public成员函数,但是必须明确指出是基类的作用域。 9. 虚析构函数和多态 当...
- 成员函数实现周长和面积的计算。 #### 三、实验2:运算符重载 1. **成员函数重载运算符** - 示例: 重载`++`和`--`运算符,用于`Point`类实例的自增自减操作。 2. **友元函数重载运算符** - 示例: 重载`==`...
覆盖是指派生类重新实现基类中的虚函数;而隐藏是指派生类中存在与基类同名的成员函数,但并不构成覆盖。 **8.3 参数的缺省值** - **知识点**: 缺省参数的使用。 - **详细解释**: 函数参数可以设置缺省值,这样在...
- **虚函数**(virtual function)允许动态绑定,即在运行时确定调用哪个函数,这在多态性中至关重要。 - **纯虚函数**(pure virtual function)定义为`virtual void func() = 0;`,使得基类成为一个抽象类,无法...
静态多态性在编译时通过函数重载实现,而动态多态性在运行时通过虚函数和基类指针或引用实现。 4. 默认参数:在构造函数中可以设置默认参数,如`A(int i=4, int j=0)`。如果没有提供参数,将使用默认值。在`A x(1);...