用户操作
[即时聊天] [发私信] [加为好友]
雷鹏ID:whinah
20346次访问,排名5852好友2人,关注者6
嵌入式两年,安全两年,现今搜索
whinah的文章
原创 43 篇
翻译 0 篇
转载 0 篇
评论 13 篇
最近评论
whinah:客气、客气,这个RPC之后我也再没继续深入。打造一个稳定而强大的基础设施需要太大的精力。目前我们使用ICE,有兴趣可以去关心一下。前不久我在boost sandbox 中看到了一个rpc,没细看,估计在参数传递方面和我的设计思想差不多,不过它底层用的是boost.asio。
zm0011:在开发网络通讯程序中很有用,正想自己写一个,竟然百度出来了。顺便看了一下老兄的其它文章,数量不多但水平比较高,而且涉足的领域很多哦,从WIN到LINUX、从C++壳到数据库都有。希望能看到你奉献更多的好东东,谢谢!
whinah:这里只考虑了简单性,atl 这种手工打造虚表的方法的确可以节省存储空间,但是繁琐了一些。
nico:有没有考虑过 ATL/WTL 里用到模拟虚函数?

template <class T>
class foo
{
int& get_n()
{
T* pT = (T*)this;
return pT->n;
}
}

class bar : foo<……
whinah:如果真要实际使用这种技术,字符串文字量也必须经过地址转换,如:
convert_address("string literal")
文章分类
    收藏
      相册
      我的相册
      存档
      软件项目交易
      订阅我的博客
      XML聚合  FeedSky
      订阅到鲜果
      订阅到Google
      订阅到抓虾
      订阅到BlogLines
      订阅到Yahoo
      订阅到GouGou
      订阅到飞鸽
      订阅到Rojo
      订阅到newsgator
      订阅到netvibes

      原创 使用" 参数化基类" 和" 成员函数指针" 模拟实现虚函数--在实际中的应用收藏

      新一篇: 按序号索引二叉树的应用 | 旧一篇: 使用" 参数化基类" 和" 成员函数指针" 模拟实现虚函数

      // 使用" 参数化基类" " 成员函数指针" 模拟实现虚函数--在实际中的应用。

      #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 ;

              this-> x2 = x2 ;

              context->printf("ConcreteClass1::Func1\n");

              context->printf("x1=%d, x2=%d\n\n", x1, x2);

              return 0;

          }

          int Func2(int x1, int x2 , int x3)

          {

              this-> x1 = x1 ;

              this-> x2 = x2 ;

              this-> x3 = x3 ;

              context->printf("ConcreteClass1::Func2\n");

              context->printf("x1=%d, x2=%d, x3=%d\n\n", x1, x2, x3);

              return 0;

          }

      };

       

      class ConcreteClass2

      {

      private :

          const Context* context;

          int x1, x2 , x3;

      public :

          ConcreteClass2(const Context* context)

          {

              this->context = context;

          }

          int Func1(int x1, int x2 )

          {

              this-> x1 = x1 ;

              this-> x2 = x2 ;

              context->printf("ConcreteClass2::Func1\n");

              context->printf("x1=%d, x2=%d\n\n", x1, x2);

              return 0;

          }

          int Func2(int x1, int x2 , int x3)

          {

              this-> x1 = x1 ;

              this-> x2 = x2 ;

              this-> x3 = x3 ;

              context->printf("ConcreteClass2::Func2\n");

              context->printf("x1=%d, x2=%d, x3=%d\n\n", x1, x2, x3);

              return 0;

          }

      };

       

      template <class ConcreteClass>

      class InstantialClass :

          // "BaseClass" must be first base class, otherwise,

          // function pointer convert in "BaseClass::assign()" may be not valid!

          public BaseClass, // interface inherit, multi inherit is not allowed!!

          protected ConcreteClass // implementation inherit, multi inherit is allowed

      {

          // it is a guide line that do not hold any data member in this class!!

          //

          // if 'BaseClass' is not the first base class for 'this' class,

          // and data member is defined here,

          // and these data member will be modified,

          // it will error at runtime!

          // you can reverse the inherit order of

          // BaseClass and ConcreteClass, and try!!

          //

          int x1, x2 , x3;

      public :

          // must delegate these member functions...

          int Func1(int x1, int x2 ) { return ConcreteClass::Func1 (x1, x2); }

          int Func2(int x1, int x2 , int x3)

          {

              this-> x1 = x1 ;

              this-> x2 = x2 ;

              this-> x3 = x3 ;

              return ConcreteClass::Func2 (x1, x2, x3 );

          }

       

          InstantialClass(const Context* context)

              : ConcreteClass(context)

          {

          // must assign these member function pointers...

          //  BaseClass::pFunc1 = (TFunc1)(Func1);

          //  int v = _MSC_VER;

      #if _MSC_VER >= 1310 // vc2003

              assign(pFunc1, Func1);

              assign(pFunc2, Func2);

      #else // in vc6, vc6 template support is not perfect!!

              pFunc1 = (TFunc1)Func1;

              pFunc2 = (TFunc2)Func2;

      #endif

          // if use C Style cast in assign, follow line can be compiled,

          // but will error at runtime, because pointer to ConcreteClass

          // is different from to 'this'!!

          // pointer to 'BaseClass' is equal to 'this'..

          // so, do not write such code,

          // must delegate 'ConcreteClass::Func2' to 'this->Func2'.

          // assign(pFunc2, ConcreteClass::Func2);

          }

      };

       

      template InstantialClass<ConcreteClass1>;

      template InstantialClass<ConcreteClass2>;

       

      int imp_entry(const Context* context)

      {

          InstantialClass<ConcreteClass1> v1(context);

          InstantialClass<ConcreteClass2> v2(context);

          BaseClass* p1 = &v1;

          BaseClass* p2 = &v2;

       

          p1-> Func1(1111 , 2222);

          p2-> Func1(1111 , 2222);

          p1-> Func2(1111 , 2222, 3333);

          p2-> Func2(1111 , 2222, 3333);

       

          p1-> Func1(1111 , 2222);

          p2-> Func1(1111 , 2222);

          p1-> Func2(1111 , 2222, 3333);

          p2-> Func2(1111 , 2222, 3333);

       

          return 0;

      }

       

      // template instantiation generated functions were not

      // lie in 'entry()' and 'end_address()'.

      // this is a problem, we must guess the actual codes size.

      //

      // it looks as if this is not a good solution for small shell codes.

      //

      // but in my shell code, I put all code in a PE file,

      // and relocate the whole code section of the PE file.

      // so, this is good idea for shell code.

      // this technic is a good solution for virus,

      // ---- if you want write virus in C++ and use virtual function!

      void end_address() {}

       

      int main(int argc , char* argv[])

      {

          Context context;

          context.printf = printf;

       

          typedef int (*T_entry)(const Context* context);

          unsigned char codeBuffer[16*1024];

          size_t codeSize = (unsigned char*)end_address - (unsigned char*)entry;

          size_t guessedCodeSize = sizeof(codeBuffer);

      //  memcpy(codeBuffer, (void*)entry, codeSize); // run error!!

          memcpy(codeBuffer, (void*)entry, guessedCodeSize); // run ok!!

       

      //  entry(&context);

          ((T_entry)(void*)codeBuffer)(&context);

       

          return 0;

      }

       

       

       

      发表于 @ 2005年12月02日 23:01:00|评论(loading...)|编辑

      新一篇: 按序号索引二叉树的应用 | 旧一篇: 使用" 参数化基类" 和" 成员函数指针" 模拟实现虚函数

      评论