zoukankan      html  css  js  c++  java
  • [vc] 获取函数名称真实地址

        首先写一个很简单的main函数:

    int main(){
        printf("main的地址(?):%08x",main);
    }


    单步调试,可得知 main函数的真实入口地址是:00be91a0

      然而我们控制台输出的值是

    为什么会出现这样的差别呢?院子里有一篇大牛写的有关注入的文章:http://www.cnblogs.com/fanzhidongyzby/archive/2012/08/30/2664287.html,里面就提到了这个问题。

    其中提到一个解析真实地址的算法:

    //将函数地址转换为真实地址
    unsigned int getFunRealAddr(LPVOID fun)
    {
        unsigned int realaddr = (unsigned int)fun;//虚拟函数地址
        // 计算函数真实地址
        unsigned char* funaddr = (unsigned char*)fun;
        if (funaddr[0] == 0xE9)// 判断是否为虚拟函数地址,E9为jmp指令
        {
            int disp = *(int*)(funaddr + 1);//获取跳转指令的偏移量
            realaddr += 5 + disp;//修正为真实函数地址
        }
        return realaddr;
    }

    相信新手朋友都和我一样为这段代码怎么来的摸不着头脑。特此我单步调试研究了一番,才大致明白原理:

    main函数名的地址其实就是一个 Jmp xxx的指令,

    从vs的反汇编调试代码可以看出,第一个参数main入栈,对应汇编代码就是 push 0be135Ch ,这个入栈的数字,其实就是刚刚控制台输出的那个地址。所以很显然这个地址就是函数main的“函数名”所在的地址(其实在汇编里应该是不存在 “main”这样的字符串的,之所以可能可以在vs或在od这样的调试器里看到,是这些调试器通过经验推断出来的结果。)。然后 我们在地址栏里输入 0be135Ch这个地址,就可以跳到 相对的位置处。

    jmp 对应的汇编码为 E9, 而后面的4个字节"3F 7E 00 00",实际上是倒序的相对地址 0x00007e3f.也就是我们看到是main。当然这个地址只是代码的相对位置,如果运行之后,就要加上当前模块的基址才是绝对地址。

    那么既然,这个“main”的位置只是一个跳转指令(JMP),肯定是跳转到了jmp后面跟的这个地址的位置了,也就是说这个地址就是真正的main函数的地址了。

    当然,0be135Ch是从e9 3F 7E 00 00这条指令开始算的。也就是说,从e9 3F 7E 00 00的位置开始算,跳过去0x00007e3f个字节,就到了真正的main函数入口处。

    所以真正的地址就是

    0be135Ch+5(指令占的字节数 JMP main)+0x00007e3f=00be91a0.

    所以我们再回到函数部分来。

        UINT realaddr = (UINT)main;// 拆箱转换成 unsigned int 数据。代表main函数名所代表的地址
        unsigned char* funcaddr = (UCHAR*)main; //这里是获取main地址所在的字节内容,其内容为“e9 3F 7E 00 00”(JMP main),所以只要判断前面的字节指令是否是e9就知道是不是真实地址了,如果是Jmp(e9)的话就不是真正的地址。
        if (funcaddr[0] == 0xE9){  //因为 
            UCHAR* fa = funcaddr + 1;//指针移后一位,从e9到 3f.
            int* as = (int*)(fa); //取指针=处的int数据(共4个字节),实际上这里就是一个跳转地址。
            int disp = *as; //取指针的内容
            realaddr += 5 + disp;//在main地址的基础上+JMP main所占的字节+要正向跳转的字节数
        }
  • 相关阅读:
    conda使用
    onedrive共享文件的下载
    生物信息软件安装(不定时更新)
    if 的常见问题解析
    C语言常见的误区
    流程控制
    C语言中的运算符
    scanf的具体用法
    代码的规范
    printf中的x%及用法
  • 原文地址:https://www.cnblogs.com/uu102/p/4695026.html
Copyright © 2011-2022 走看看