首先写一个很简单的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[] == 0xE9)// 判断是否为虚拟函数地址,E9为jmp指令
{
int disp = *(int*)(funaddr + );//获取跳转指令的偏移量
realaddr += + 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[] == 0xE9){ //因为
UCHAR* fa = funcaddr + ;//指针移后一位,从e9到 3f.
int* as = (int*)(fa); //取指针=处的int数据(共4个字节),实际上这里就是一个跳转地址。
int disp = *as; //取指针的内容
realaddr += + disp;//在main地址的基础上+JMP main所占的字节+要正向跳转的字节数
}

vc 获取函数名称真实地址的更多相关文章

  1. JavaScript函数之实际参数对象(arguments) / callee属性 / caller属性 / 递归调用 / 获取函数名称的方法

    函数的作用域:调用对象 JavaScript中函数的主体是在局部作用域中执行的,该作用域不同于全局作用域.这个新的作用域是通过将调用对象添加到作用域链的头部而创建的(没怎么理解这句话,有理解的亲可以留 ...

  2. 利用PE数据目录的导入表获取函数名及其地址

    PE文件是以64字节的DOS文件头开始的(IMAGE_DOS_HEADER),接着是一段小DOS程序,然后是248字节的 NT文件头(IMAGE_NT_HEADERS),NT的文件头位置由IMAGE_ ...

  3. web服务器获取请求客户端真实地址的方法

    服务器获取客户端或者网页的请求,获取IP时需要注意,因为一个请求到达服务器之前,一般都会经过一层或者多层代理服务器,比如反向代理服务器将http://192.168.1.10:port/ 的URL反向 ...

  4. NodeJs获取函数名称和函数操作整理

    var aa = function () { log("xxxx"); }; aa(); var model = {}; model.test = function () { lo ...

  5. VC 获取多个mac地址

    转载请注明来源:https://www.cnblogs.com/hookjc/ #include <IPHlpApi.h>#include <iostream>#pragma ...

  6. 【Python】—— 获取当前运行函数名称和类方法名称

    原文出处: python笔记19-获取当前运行函数名称和类方法名称 获取函数名称 1.在函数外部获取函数名称,用.__name__获取 2.函数内部获取当前函数名称,用sys._getframe(). ...

  7. python笔记19-获取当前运行函数名称和类方法名称

    前言 写完代码之后,一般为了方便查看日志,可以在日志输出中加入当前运行的函数名称或类和方法名称,以便于代码报错的时候能快速找到报错的是哪个函数或方法. 那么如何获取当前运行函数(或方法)的名称呢? 获 ...

  8. 基于WMI获取本机真实网卡物理地址和IP地址

    using System; using System.Collections.Generic; using System.Management; using System.Runtime.Intero ...

  9. 旧书重温:0day2【4】动态获取函数地址

    通过以上3篇文章的学习,我们已经可以获取到kernel32.dll的地址了下一步 我们就是获取几个重要的函数 1.GetProcAddress 2.LoadLibrary 有了这两个函数很多函数都可以 ...

随机推荐

  1. HttpClient不同版本超时时间的设置

    引自 https://www.cnblogs.com/hisunhyx/p/5028391.html 3.X是这样的 HttpClient client=new DefaultHttpClient() ...

  2. python datetime处理时间(转)

    Python提供了多个内置模块用于操作日期时间,像calendar,time,datetime.time模块,它提供 的接口与C标准库time.h基本一致.相比于time模块,datetime模块的接 ...

  3. 前m大的数

    前m大的数 Time Limit: 1000 MS Memory Limit: 32768 KB 64-bit integer IO format: %I64d , %I64u Java class ...

  4. hdu 4825(Trie)

    Xor Sum Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)Total S ...

  5. 【矩阵乘法】CDOJ1610 黑红梅方

    考虑用4^n-不存在连续4个相同的. f(i,j,k,l)表示以i为结尾的序列,最后三位分别是j,k,l时的方案. 可以转移,写一个64*64的转移矩阵. 貌似可以优化?……未完待续. #includ ...

  6. CSS3新增属性2

    阴影 box-shadow:水平偏移 垂直偏移; 偏移可以负值 box-shadow:水平偏移 垂直偏移 颜色; box-shadow:水平偏移 垂直偏移 模糊值 颜色; /*最常见的*/ box-s ...

  7. python学习第九十天:vue补习2

    Vue 八.重要指令 v-bind <!-- 值a --> <div v-bind:class='"a"'></div> <!-- 变量a ...

  8. Idea集成svn

    Idea集成svn 既然要使用svn,首先需要下载一个 svn的客户端,到这里下载对应的安装程序:http://subversion.apache.org/packages.html#windows ...

  9. 将springboot配置文件中的值注入到静态变量

    SpringBoot配置文件分为.properties和.yml两种格式,根据启动环境的不同获取不同环境的的值. spring中不支持直接注入静态变量值,利用spring的set注入方法注入静态变量 ...

  10. Sql实现行列转换

    从MS Sql Server 2005微软就推出了pivot和unpivot实现行列转换,这极大的方便了我们存储数据和呈现数据.今天就对这两个关键字进行分析,结合实例讲解如何存储数据,如何呈现数据. ...