欢迎光临
我们一直在努力

WIN32_模块

1. 动态链接库

  • 动态链接库(DLL)

    • 动态链接库(Dynamic-Link Library,简称DLL)是一种包含可由多个程序同时使用的代码和数据的文件。DLL允许程序共享代码,从而减少内存使用和磁盘空间占用,同时使得程序的更新和维护更加方便。
  • 导出函数

    • 在DLL中,导出函数是可以被其他程序或DLL调用的函数。为了使函数能够被导出,需要在函数定义前加上特定的关键字,如__declspec(dllexport)。
  • 导入库

    • 导入库(Import Library)是一个特殊的库文件,它包含了指向DLL中导出函数的符号信息。当编译器链接一个程序时,它会使用导入库来解析对DLL中函数的引用。导入库通常与DLL文件一起提供,以便程序能够正确地加载和调用DLL中的函数。
  • 代码重用

    • 动态链接库(DLL)允许不同的程序共享同一代码库。这意味着,如果多个程序需要执行相同的任务,它们可以调用同一个DLL中的函数,而不是每个程序都包含该函数的副本。这样可以减少磁盘空间的使用,并且在内存中只需要一个代码副本,从而提高了内存的使用效率。
  • 模块化

    • DLL提供了一种模块化的编程方式,使得程序的结构更加清晰。每个DLL可以看作是一个独立的模块,负责特定的功能。这种模块化的设计使得程序的开发、测试和维护更加容易,因为可以单独更新或修复某个DLL,而不需要重新编译整个程序。
  • 内存效率

    • 当多个程序使用同一个DLL时,Windows操作系统通常会在内存中只加载该DLL的一个副本。这意味着,即使多个程序都在运行,它们也共享同一个DLL的物理内存副本。这种共享机制减少了内存的消耗,提高了系统的整体性能。

2. 导出未文档化函数使用

在这里插入图片描述

  • 该练习通过动态加载ntdll.dll,手动获取未公开原生 API NtOpenProcess 的函数地址,搭配OBJECT_ATTRIBUTES、CLIENT_ID等 Windows 内核对象结构体,指定目标进程 PID 并调用接口打开进程,最后依次关闭句柄、释放模块,完整演示了原生 Native API 的动态调用流程,同时也熟悉了底层进程操作相关结构体与权限参数的使用。

3. 动态库的环境配置

  • 在这里插入图片描述
    2.
    在这里插入图片描述

    3.1 DLL入口函数

    在这里插入图片描述

    3.2 输出结果

    在这里插入图片描述


    4. 数据导出的样式以及错误处理

    4.1 注意事项

    在这里插入图片描述

    当我们通过解决方案创建新建项目的时候需要有几点注意事项:

    • 函数前缀需要加上:__declspec(dllexport)
    • 当我们重新运行会把.dll文件带入到本项目的DEBUG目录下,如图:

    在这里插入图片描述

    拖到PE查看导出表信息:

    在这里插入图片描述
    可以看到导出里面有一个类似乱码中夹在了ADD名字的一个东西,这在CPP中是典型的函数重载风格,如果我们不想要这样的话,需要在前面加上extern "C"。

    在这里插入图片描述

    重新回到PE查看导出表信息:

    在这里插入图片描述
    结果:可以发现跟我们写的函数一模一样,所以当我们需要导出哪个函数的时候这样extern "C" _declspec(dllexport)前缀就必不可少。

    4.2 模块定义文件(*.def)

    在这里插入图片描述
    如果我们在没有明确写出这个函数是导出函数的时候,则这个函数不能在导出表查看,但是当我们通过.def下面明确哪些函数为导出函数的时候,则一样可以达到以上效果。

    在这里插入图片描述

    在这里插入图片描述


    5. 导入表对接导出数据

    在这里插入图片描述
    本练习实现动态加载 DLL 并调用内部导出函数,完整演示 Windows 动态链接库的基础调用流程,同时涉及 C/C++ 编译特性、函数指针、DLL 导出规则等核心知识点:

    • 核心功能流程

      • 程序通过 LoadLibrary 加载指定路径下的 DLLTEST_14.dll,获取模块句柄;再借助 GetProcAddress 根据函数名查找 DLL 内 ADD 导出函数地址;利用函数指针完成函数调用,执行两数相加逻辑;最后通过 FreeLibrary 释放 DLL 模块,回收系统资源。
    • 关键语法与类型

      • 使用 typedef 定义函数指针类型 PFNADD,严格匹配目标函数的返回值、__cdecl 调用约定与参数列表,是动态调用 DLL 函数的标准写法。
    • DLL 导出名称两大解决方案(解决 C++ 名字修饰问题)

      • 方式一: DLL 代码添加 extern “C”,编译阶段关闭 C++ 名字修饰,导出名与源码函数名保持一致;

      • 方式二: 使用 .def 模块定义文件,在链接阶段强制指定导出名称,无需修改源码,兼容 C++ 语法与函数重载。

      • 两种方式均可保证 GetProcAddress 通过原始函数名正常查找接口。

    • 重点注意事项

      • 调用约定必须前后统一,否则会造成栈失衡、程序崩溃;
      • 需逐层判断 DLL 加载、函数地址获取是否成功,增加代码健壮性;
      • C++ 默认会对函数名进行修饰,是动态查找导出函数的常见坑点。
    • 应用场景

      • 该模式适用于延迟加载模块、按需调用接口、逆向分析、注入开发等 Windows 底层开发、逆向安全场景。

    6. 模块名称与遍历模块

    在这里插入图片描述

    输出结果:

    在这里插入图片描述

    6.1 通过跨进程形式获取自身主模块完整地址

    在这里插入图片描述

    • 该练习先获取当前进程 ID,再通过OpenProcess打开自身进程并赋予查询、内存读取权限,接着借助GetModuleFileNameEx,结合进程句柄与当前程序主模块句柄,读取主模块完整路径并打印输出,演示了通过进程句柄结合跨进程接口获取本进程模块路径的完整流程。

    6.2 获取当前指定模块基名称

    在这里插入图片描述

    该练习通过LoadLibrary加载指定路径下的 DLL 模块,再分别获取当前进程主模块句柄与已加载的 DLL 模块句柄,随后调用GetModuleBaseName,传入当前进程伪句柄与主模块句柄,从进程中读取主模块的文件名并打印,完整演示了 Windows 环境下模块加载、句柄获取与模块名称读取的流程。

    6.3 检索指定进程的可执行文件的名称

    在这里插入图片描述

    6.4 遍历模块

    在这里插入图片描述

    输出结果:

    在这里插入图片描述

    • 本案例通过 Toolhelp 快照机制 实现系统全进程与进程内所有模块的枚举,程序首先创建系统进程快照,遍历获取每一个进程的 PID,通过 PID 打开进程并获取合法进程句柄,再针对每一个进程单独创建模块快照,逐一遍历该进程下的所有模块信息,通过跨进程 API GetModuleFileNameEx 读取各模块的完整磁盘路径并打印输出,完整演示了 Windows 系统先进程枚举、再逐进程枚举模块的标准流程,同时规范完成进程句柄与快照句柄的释放,规避资源泄漏问题,实现了系统进程与加载模块的批量遍历查询功能。

    本章完~

    赞(0)
    未经允许不得转载:171主机测评 » WIN32_模块
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址