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[] == 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 获取函数名称真实地址的更多相关文章
- JavaScript函数之实际参数对象(arguments) / callee属性 / caller属性 / 递归调用 / 获取函数名称的方法
函数的作用域:调用对象 JavaScript中函数的主体是在局部作用域中执行的,该作用域不同于全局作用域.这个新的作用域是通过将调用对象添加到作用域链的头部而创建的(没怎么理解这句话,有理解的亲可以留 ...
- 利用PE数据目录的导入表获取函数名及其地址
PE文件是以64字节的DOS文件头开始的(IMAGE_DOS_HEADER),接着是一段小DOS程序,然后是248字节的 NT文件头(IMAGE_NT_HEADERS),NT的文件头位置由IMAGE_ ...
- web服务器获取请求客户端真实地址的方法
服务器获取客户端或者网页的请求,获取IP时需要注意,因为一个请求到达服务器之前,一般都会经过一层或者多层代理服务器,比如反向代理服务器将http://192.168.1.10:port/ 的URL反向 ...
- NodeJs获取函数名称和函数操作整理
var aa = function () { log("xxxx"); }; aa(); var model = {}; model.test = function () { lo ...
- VC 获取多个mac地址
转载请注明来源:https://www.cnblogs.com/hookjc/ #include <IPHlpApi.h>#include <iostream>#pragma ...
- 【Python】—— 获取当前运行函数名称和类方法名称
原文出处: python笔记19-获取当前运行函数名称和类方法名称 获取函数名称 1.在函数外部获取函数名称,用.__name__获取 2.函数内部获取当前函数名称,用sys._getframe(). ...
- python笔记19-获取当前运行函数名称和类方法名称
前言 写完代码之后,一般为了方便查看日志,可以在日志输出中加入当前运行的函数名称或类和方法名称,以便于代码报错的时候能快速找到报错的是哪个函数或方法. 那么如何获取当前运行函数(或方法)的名称呢? 获 ...
- 基于WMI获取本机真实网卡物理地址和IP地址
using System; using System.Collections.Generic; using System.Management; using System.Runtime.Intero ...
- 旧书重温:0day2【4】动态获取函数地址
通过以上3篇文章的学习,我们已经可以获取到kernel32.dll的地址了下一步 我们就是获取几个重要的函数 1.GetProcAddress 2.LoadLibrary 有了这两个函数很多函数都可以 ...
随机推荐
- Java工具类-转换字符编码
package common; /** *字符串处理公用类 */ public class DealString { /** * 转换字符编码 由“iso-8859-1”西文转换为简体中文 */ pu ...
- CodeForces 734F Anton and School
位运算. 两个数的和:$A+B=(AandB)+(AorB)$,那么$b[i]+c[i]=n*a[i]+suma$.可以解出一组解,然后再按位统计贡献验证一下. #pragma comment(lin ...
- Oracle concat
如果要进行多个字符串的拼接的话,可以使用多个CONCAT()函数嵌套使用,上面的SQL可以如下改写:SELECT CONCAT(CONCAT(CONCAT('工号为',FNumber),'的员工姓名为 ...
- 子查询在DELETE语句中的应用
子查询在DELETE 中唯一可以应用的位置就是WHERE 子句,使用子查询可以完成复杂的数据删除控制.其使用方式与SELECT 语句中的子查询基本相同,而且也可以使用相关子查询等高级的特性.下面的SQ ...
- 删除Kali Linux多余的系统架构
删除Kali Linux多余的系统架构 现在大家通常安装的都是Kali Linux 64位操作系统,其架构为amd64.如果要安装运行32位的程序(如wine32),则必须添加32位架构i386. ...
- Visual Studio找不到adb.exe错误解决
Visual Studio找不到adb.exe错误解决 错误信息:Cannot find adb.exe in specified SDK path.出现这种情况,是因为没有安装Android SDK ...
- 高效的 itertools 模块(转)
原文地址:http://python.jobbole.com/87380/ 我们知道,迭代器的特点是:惰性求值(Lazy evaluation),即只有当迭代至某个值时,它才会被计算,这个特点使得迭代 ...
- [BZOJ4455][ZJOI2016]数星星(容斥DP)
4455: [Zjoi2016]小星星 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 707 Solved: 419[Submit][Status] ...
- [ARC 066] Tutorial
Link: ARC 066 传送门 C: 如果存在可行方案则答案为$2^{n/2}$ #include <bits/stdc++.h> using namespace std; #defi ...
- Problem D: 零起点学算法83——数组中删数
#include<stdio.h> int main(void) { int n,i,t,x,flag; while(scanf("%d",&n)!=EOF) ...