Windows DLL在目标进程中的描述(1)

研究背景

         一个偶然的机会,被同班同学找去一起研究windows内核。由于这个学期刚刚开始学习操作系统这么课,所以抱着试试的心理就参加这个Windows内核研究小组。原老师给我们一些学习的宝贵资料:Windows Research Kernel包括源码、文档、范例的一张光盘(仅供中国各大高校研究性教学使用),深入解析windows操作系统第四版(潘爱民议,电子工业出版社)。我们知道这些资料(尤其是windows源码)是十分宝贵的,网上的一些高手们想研究windows内核都是通过反汇编猜测的。而现在我们手中这张教学光盘不仅仅提供了windows源代码,而且我们只要双击一下微软给的批处理文件,就可以轻松搭建好整个研究环境,批处理文件主要执行了设置环境变量,拷贝相关资料从光盘到本地磁盘C,安装Windbg,安装Virtual PC等等。有时候会提示缺少setx.exe文件(该文件主要负责设置环境变量),只要上网下载一个setx.exe拷贝到C:/windows/system32文件夹下即可。有时候也会出现自动安装windbgvirtual PC失败的情况,不要紧自己手动安装也可以。具体步骤请见光盘附带的文档《Get Started With WRK》。

      原老师大概给我分配了这学期的研究方向:写一个系统调用,将进程的运行时状态保存在文件中,必要的时候可以还原回去并继续执行。具体到我个人,主要是负责记录目标进程加载了哪些DLL,再次运行的时候可以再次加载这些DLL

Windows进程相关数据结构简介

         Linux上每一个进程都有一个进程控制块,与进程或线程有关的信息大都存储在这个数据结构中。而windows则有所不同。首先windows的进程和线程各有不同的数据结构来描述,从概念上把进程和线程分离开。其次,windows又把本可集中存储的进程数据结构也拆分成好几个对象,有的在系统空间里,有的在用户空间里。

         系统空间里与进程有关的数据结构有:

1.       EPROCESS:即struct_EPROCESS,表示windows里的一个进程。E表示executive,执行体的意思。

2.       KPROCESS:是EPROCESS内的一个部分,也就是常说的PCB

3.       WIN32PROCESS:用户空间有个“windows子系统”的服务进程csrss。这个服务进程为windows中的每个应用进程都维持着一个数据结构,其中包含了一些与窗口和图形界面的信息。而有关窗口和图形界面的操作,原来也是由csrss在客户进程的请求下完成的。后来为了提高效率,把这部分功能移到了内核中,与此相应的数据结构也移动到了内核中,就成了现在的WIN32PROCESS

用户空间里与进程有关的数据结构:

1.       如上所述,由于将WIN32PROCESS移进内核空间以后,csrss仍然需要为每个进程保留一些信息。所以csrss内部仍有一些与进程有关的数据结构。

2.       PEBProcess Environment Block 即进程环境块。其中记录着进程的运行参数,映像装入地址等等信息。PEB在用户空间中的位置是固定的,总是在0x7ffdf000

以上就是windows中与进程相关的数据结构。可以看出,与我所研究的DLL加载信息应该存储在PEB中。下面再简单介绍一下windowsDLL原理。

Windows DLL基本原理

         Windows系统平台上提供了一种完全不同的较有效的编程和运行环境,你可以将独立的程序模块创建为较小的DLL(Dynamic Linkable Library)文件,并可对它们单独编译和测试。在运行时,只有当EXE程序确实要调用这些DLL模块的情况下,系统才会将它们装载到内存空间中。这种方式不仅减少了EXE文件的大小和对内存空间的需求,而且使这些DLL模块可以同时被多个应用程序使用。Microsoft Windows自己就将一些主要的系统功能以DLL模块的形式实现。例如IE中的一些基本功能就是由DLL文件实现的,它可以被其它应用程序调用和集成。一般来说,DLL是一种磁盘文件(通常带有DLL扩展名,是标准win32可执行文件-“PE”格式),它由全局数据、服务函数和资源组成,在运行时被系统加载到进程的虚拟空间中,成为调用进程的一部分。如果与其它DLL之间没有冲突,该文件通常映射到进程虚拟空间的同一地址上。DLL模块中包含各种导出函数,用于向外界提供服务。Windows在加载DLL模块时将进程函数调用与DLL文件的导出函数相匹配。

         Win32环境中,每个进程都复制了自己的读/写全局变量。如果想要与其它进程共享内存,必须使用内存映射文件或者声明一个共享数据段。DLL模块需要的堆栈内存都是从运行进程的堆栈中分配出来的。DLL现在越来越容易编写,在下面您将会看到我用一个C语言编写的DLL程序。

         DLL文件中包含一个导出函数表(存在于PE.edata节中)。这些导出函数由它们的符号名和称为标识号的整数与外界联系起来。函数表中还包含了DLL中函数的地址。当应用程序加载DLL模块时时,它并不知道调用函数的实际地址,但它知道函数的符号名和标识号。动态链接过程在加载的DLL模块时动态建立一个函数调用与函数地址的对应表。如果重新编译和重建DLL文件,并不需要修改应用程序,除非你改变了导出函数的符号名和参数序列。

简单的DLL文件只为应用程序提供导出函数,比较复杂的DLL文件除了提供导出函数以外,还调用其它DLL文件中的函数。

         应用程序导入函数与DLL文件中的导出函数进行链接有两种方式:隐式链接和显式链接。所谓的隐式链接是指在应用程序中不需指明DLL文件的实际存储路径,程序员不需关心DLL文件的实际装载(由编译器自动完成地址分配)。而显式链接与此相反。采用隐式链接方式,程序员在建立一个DLL文件时,链接程序会自动生成一个与之对应的LIB导入文件。该文件包含了每一个DLL导出函数的符号名和可选的标识号,但是并不含有实际的代码。LIB文件作为DLL的替代文件被编译到应用程序项目中。当程序员通过静态链接方式编译生成应用程序时,应用程序中的调用函数与LIB文件中导出符号相匹配,这些符号或标识号进入到生成的EXE文件中。LIB文件中也包含了对应的DLL文件名(但不是完全的路径名),链接程序将其存储在EXE文件内部。当应用程序运行过程中需要加载DLL文件时,Windows根据这些信息发现并加载DLL,然后通过符号名或标识号实现对DLL函数的动态链接。显式链接方式对于集成化的开发语言比较适合。有了显式链接,程序员就不必再使用导入文件,而是直接调用Win32 LoadLibary()函数,并指定DLL的路径作为参数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值