Chinaunix首页 | 论坛 | 博客
  • 博客访问: 990896
  • 博文数量: 158
  • 博客积分: 4380
  • 博客等级: 上校
  • 技术积分: 2367
  • 用 户 组: 普通用户
  • 注册时间: 2006-09-21 10:45
文章分类

全部博文(158)

文章存档

2012年(158)

我的朋友

分类: C/C++

2012-11-14 16:39:22

#pragma warning(disable:4786)
#include
#include
using namespace std;

// 这个函数取得函数fun的函数体首位地址[return value:*ppend)
void* GetFunAddr( void* fun, void** ppend = 0 )
{
    void* pbegin = fun;
#ifdef _DEBUG
    pbegin = (unsigned*)( (unsigned)pbegin + (((*(unsigned*)pbegin)>>8)+5) );
#endif
    if( 0 != ppend )
    {
        unsigned char* p = (unsigned char*)pbegin;
        for( ; *p!=(unsigned char)0xC3; ++p ); // C3 == __asm ret, 这其实不对,应该只找操作码,跳过操作数
        *ppend = ++p;
    }
    return pbegin;
}
// 将函数体代码保存到数组中 // 这段代码没有考虑fun中其他函数的调用,也没有考虑重定向问题,仅仅是一个演示
const vector GetFunObject( void* fun )
{
    void* pb = 0;
    void* pe = 0;
    pb = GetFunAddr( fun, &pe );
    return vector( (unsigned char*)pb, (unsigned char*)pe );
}
// 这是个演示函数
int test( int a, int b )
{
    return a+b;
}

void main()
{
    typedef (*TEST)(int,int);

    vector testobj = GetFunObject(test);
    TEST p = (TEST)&testobj[0];
    int a = (*p)( 1, 2 );
    cout << "1+2=" << a << endl;
}
阅读(1105) | 评论(4) | 转发(0) |
给主人留下些什么吧!~~

网友评论2012-11-14 16:41:57

邓子国
// C3 == __asm ret, 这其实不对,应该只找操作码,跳过操作数
呵呵,刚刚找到一个反汇编引擎代码,呵呵,不过如果用上,这个函数就太大啦

网友评论2012-11-14 16:41:40

邓子国
C3只是对于cdecl或无参数的stdcall,且只有“单出口”的函数有用,对有参数的stdcall,返回时用ret xxxx,机器码为c2xxxx,呵呵。
另外,如果有call lbMessageBoxA,而lbMessageBoxA处又有jmp dword ptr [xxx]之类的中转列表,呵呵...
另to周星星:如果函数体以16字节或其他align了,那么你可能会多保存一些NOP。

网友评论2012-11-14 16:41:15

周星星
还有用c3查找结束不是太通用,c3是ms的编译器产生的,一般我用这个方法
static test()
{
}
static empty()
{
}
lengthoftest=(char*)empty - (char*)test;

网友评论2012-11-14 16:40:24

周星星
1.pbegin = (unsigned*)( (unsigned)pbegin + (((*(unsigned*)pbegin)>>8)+5) );
如果是在动态库里,你忽略了pBegin的高位,函数地址就错了
2. 如果在test前面加static不就很简单的得到函数地址了,不用计算