内存空间中的句柄,指针,对象,类
视频地址:https://www.bilibili.com/video/av55204486
句柄(Handle)
网上有很多对于句柄的解释,如果是刚刚接触句柄,看完各种各样的解释很容易蒙圈了。这里我们换个角度想,为什么要获取句柄?我们在对文件,注册表,窗口等进行操作时,都需要调用系统提供的api函数,而这些api函数大多都需要传入句柄作为参数。就是因为句柄,系统才知道你猥琐的是哪个文件,哪个注册表项或者哪个窗口。
这里通过调试看看句柄长什么样子的,如图代码获取了3个不同的句柄,分别是文件句柄,dll句柄和注册表句柄
直接在vs下调试并查看对应句柄的情况,可以看到文件句柄hFile和注册表句柄hKey都是用了一个数值来代表,这个值可以当做是句柄的索引,至于这个值是如何与文件和注册表项联系起来,这里就不详细展开,感兴趣的同学可以搜句柄表来查看具体的转换过程。而对于获取dll模块的句柄hMod,我们可以看到获取到了内存中具体的值,如果用过OD调试程序,对于这个地址应该不陌生,这是程序中dll模块的基址。可能看到这里就有疑惑了,为啥这个句柄不是用一个51,52的数值来标识,而是获取到了一个具体的值?这里有个区别就是,前面的hFile,hKey是这个程序外部的东西,并没有在自身空间中加载起来,所以就只能通过一个索引来表示,而dll模块是加载到了程序本身的内存空间中,所以用基址来作为句柄。
指针
对于初学C/C++的人来说,指针是个很神奇的东西,下面用一段代码来看看指针是个啥。
可能看到前面的代码就有人开始晕了,我们一个个看,“GeekFZ_QKSword”是定义的一个字符串,在内存空间中就是一串数据了。根据局部变量显示的地址查看一下字符串所在的内存空间。
p是我们定义的指向字符串的指针,我这里直接打印出对于p,*p,&p,来看看对指针不同操作的区别。首先我们知道p定义为了指针,那么p保存的值是什么呢?通过打印的结果可以看到,这里就是前面字符串开始的地址,p的值保存的就是字符串的内存地址;*p就是取p指向地址的值,我们查看打印结果可以看到字符“G”;&p是取p的地址,这里保存的就是p这个指针的内存空间地址,查看p的地址可以看到它保存的值就是字符串的地址
这里用一张图来梳理一下前面的内容
对象和类
在学习C++的时候,类和对象往往会让人觉得抽象,那么现在看看它们在内存空间中的样子。代码如图
对于类和对象,很多教程都会说类是抽象的,对象是类的实例化。那么首先对比一下类在实例化和没有实例化的情况。这里用IDA分别对比两种情况的不同。可以从图中看出,在没有实例化的情况下,类是不会被编译到程序中,夸张的形容就是你程序写了一千个类,如果没有实例化它们,那么这一千个类都不会编译到你写的程序中。在类经过实例化后,我们可以从IDA的Structure窗口中查看到我们定义的变量
从上面图中还可以看出两个问题,一就是IDA这里把类中的定义变量识别出结构体,这是因为类和结构体虽然概念不一样,但是从反汇编看是没有区别的。二是我们定义的成员函数去哪里了?毕竟结构体中不存在成员函数的说法,类中定义的一些变量成员会被IDA识别为结构体,但是对于成员函数来说,其实就和普通的函数一样在程序中直接调用,而区分类的成员函数和普通函数的方法,最简单就是通过函数调用方式是否为thiscall来判断。
谦谦君子,卑以自牧