首先写一个很简单的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. codis 的dashboard服务无法启动 提示pid已经运行

    ps -rf|grep pid号 ,一直查询不到,进程并没有运行, 后来在Zookeeper中发现get /zk/codis/db_gdata/dashboard 这个中存在着pid,连接到zooke ...

  2. 关于hadoop处理大量小文件情况的解决方法

    小文件是指那些size比HDFS的block size(默认64m)小的多的文件.任何一个文件,目录和bolck,在HDFS中都会被表示为一个object存储在namenode的内存中,每一个obje ...

  3. Bzoj1015/洛谷P1197 [JSOI2008]星球大战(并查集)

    题面 Bzoj 洛谷 题解 考虑离线做法,逆序处理,一个一个星球的加入.用并查集维护一下连通性就好了. 具体来说,先将被消灭的星球储存下来,先将没有被消灭的星球用并查集并在一起,这样做可以路径压缩,然 ...

  4. Elasticsearch match_phrase用法

    目前有用到的用法如下: post /index_name/_search { "query" : { "match_phrase": { "nickn ...

  5. AGC 012 C - Tautonym Puzzle

    题面在这里! 神仙构造啊qwqwq. 窝一开始只想到一个字符串长度是 O(log(N)^2) 的做法:可以发现一段相同的长度为n的字符串的贡献是 2^(n-1)-1 ,可以把它看成类二进制,枚举用了多 ...

  6. BZOJ 2157 旅游(树链剖分+线段树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2157 [题目大意] 支持修改边,链上查询最大值最小值总和,以及链上求相反数 [题解] ...

  7. github之怎么上传本地项目

    github之怎么上传本地项目 以前都是在自己磁盘上的某个目录下,然后打开git bash,来进行把本地的一些文件推到远程github上. 之前的方法步骤: 1.在github上new一个库,然后gi ...

  8. 使用phpExcel实现Excel数据的导入导出(完全步骤)

    使用phpExcel实现Excel数据的导入导出(完全步骤)   很多文章都有提到关于使用phpExcel实现Excel数据的导入导出,大部分文章都差不多,或者就是转载的,都会出现一些问题,下面是本人 ...

  9. 错误:Caused by:org.apache.spark.SparkException: Kryo serialization failed: Buffer overflow.Available: 0, required: 21. To avoid this,

    这个是写入Redis时用的序列化器,然后错误提示是超过了大小限制,把配置调大即可. .set("spark.kryoserializer.buffer.max","128 ...

  10. [网络安全]NTP反射型DDOS攻击PPT

    给运维小组培训的NTP反射型DDOS攻击的PPT