简介:大家好我是小江,放假的我在家实在是太无聊了,经常看别人博客文章也学到了不少知识,所以呢我决定自己弄了个博客来记录下自己的点点滴滴,在写文章的同时我会
尽量给大家写的详细点,把一些知识带给初学者,一起学习。
好了废话不多说了 我们直接进入主题,最近在一个论坛看到一个简单而又有趣的程序
代码如下:
#include <stdio.h>
int main()
{
const short int c1 = 49920;
const int c2 = 1073742008;
int (*pf)() = (int (*)())&c2;
printf("%c%c ", *(char*)pf()-19, *((char*)pf()+1)-49);
return 0;
}
==========================这是一条华丽的分割线================================
我相信有大部分人都不理解这段代码的运行原理;
这段代码丢进VC++里面的运行结果是 :)
在Turbo3.0中 这段代码是显示的结果是 Abnormal program termination(程序异常终止)
这里每个编译器的字节都是不同的 不如说Turbo3.0 short(短整型) 内存占用字节为:2B,
在VC++中 short 占用的字节为 4B 跟 int 的大小是一样的。
本次分析采用的编译器是VC++6.0
分析过程:
我们先从const(限定符) 开始吧;
const short int c1 = 49920;
const int c2 = 1073742008;
这是两个局部变量 我们将它转换为16进制,用于后面的分析
C1=0xC300,C2=0X400000b8
我们再来看看它们各自在内存的地址
C1地址为:0019FF3C,C2=0019FF38;我们可以很清楚的看到c2到c1的字节数为4B
这两个变量占据了连续的空间,这里给变量赋值后,从0x0019ff38开始内存单元的存储字节码为:B8 00 00 40 00 C3
对应的汇编码为:0040102E mov dword ptr [ebp-8],400000h 看下图
我们继续分析下一句
int (*pf)() = (int (*)())&c2;
(int (*)());这里定义了一个函数指针 参数为NULL 而且返回值为int类型,这里的函数指针pf指向上面的汇编码,这就是这段语句的执行过程
接着分析下面 printf("%c%c ", *(char*)pf()-19, *((char*)pf()+1)-49);
*(char*)pf()-19 这段代码分析:刚刚我们函数指针pf() 是指向汇编码0x400000,然后(char*)再把汇编码转换成字符型指针来指向它的地址,最后在用他的地址减去个19然后再取这个地址的值,因为char在内存占用的字节数位1B因此从这个地址取一个字节。*(char*)pf()-19 其实就是从0x400000内存地址取出的字节内容再减去19。
接下来的一句:*((char*)pf()+1)-49代表的意思是从0x400000 + 1的地址取出一个字节内容在减去49。
下面我们打开编译器找到0x400000的地址以及字节内容 如图
熟悉PE文件结构的朋友一定知道,对于exe文件0x400000是内存加载的基地址。
也就是说,0x400000 字节的内容对应的是0x4D,0x400001 字节的内容对应的是0x5A.
这是我们常说的pe文件起始的两个字节,"MZ"
0x400000地址=0x4D
0x400001地址=0x5A
刚刚上面说到
①:*(char*)pf()-19 其实就是从0x400000内存地址取出的字节内容再减去19。
②:*((char*)pf()+1)-49代表的意思是从0x400000 + 1的地址取出一个字节内容在减去49。
①:0x4D-19=58
②:0x5A-49=41
最后按%c输出得到的结果是::)
别看代码少,这段代码知识点应用还是比较广泛的。
这段代码就分析到这里了,不喜勿喷,最后谢谢大家的阅读。