一种Reflective DLL注入后的DLL卸载处理

2024-03-25 21:28

本文主要是介绍一种Reflective DLL注入后的DLL卸载处理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

概念

Reflective DLL injection,即反射型DLL注入,是一种库注入技术,其中采用反射编程的概念来执行将库从内存加载到主机进程中的操作。因此,该库负责通过实现最小的可移植可执行(PE)文件加载器来加载自身。然后,它可以通过与主机系统和进程的最小交互来控制它将如何加载并与主机交互。
反射DLL注入是一种允许攻击者从内存注入,而不是从磁盘文件将DLL注入目标进程的技术。

概述

假设我们在主机进程中执行代码,并且我们希望注入的库已写入主机进程中内存的任意位置,反射 DLL 注入的工作原理如下:

  • 执行通过 CreateRemoteThread() 或小型引导 shellcode 传递到库的 ReflectiveLoader 函数,该函数是库导出表中的导出函数。
  • 由于库的图像当前存在于内存中的任意位置,ReflectiveLoader 将首先计算其自己的图像在内存中的当前位置,以便能够解析其自己的标头以供稍后使用。
  • 然后ReflectiveLoader将解析主机进程kernel32.dll导出表,以计算加载程序所需的三个函数的地址,即LoadLibraryA、GetProcAddress和VirtualAlloc。
  • ReflectiveLoader 现在将分配一个连续的内存区域,它将继续加载自己的图像。该位置并不重要,因为加载程序稍后会正确地重新定位图像。
  • 库的标头和节被加载到内存中的新位置。
  • 然后 ReflectiveLoader 将处理新加载的图像导入表副本,加载任何其他库并解析它们各自的导入函数地址。
  • 然后 ReflectiveLoader 将处理新加载的图像重定位表副本。
  • 然后 ReflectiveLoader 将使用 DLL_PROCESS_ATTACH 调用其新加载的图像的入口点函数 DllMain。该库现已成功加载到内存中。
  • 最后,ReflectiveLoader 将返回执行到调用它的初始引导 shellcode,或者如果通过 CreateRemoteThread 调用它,则线程将终止。
    参考代码:Reflective DLL Injection

需求

在某些业务场景下,希望在被注入进程退出时进行一些额外的操作。一般情况下,在一个进程中,通过LoadLibrary或者通过CreateRemoteThread方式LoadLibrary的DLL,在进程退出时都会调用DLL的DLL_PROCESS_DETACH方法,这样可以在此时做一些清理工作。
通过反射注入的DLL,因为在内存中自己实现对DLL的映射加载,没有调用系统API LoadLibrary函数,导致进程退出时,注入的DLL中的DLL_PROCESS_DETACH不会触发,无法实现后期的清理动作。
大致流程

方案

当调用LoadLibrary加载DLL时,基本流程如下:
在这里插入图片描述
Peb->Ldr->InInitializationOrderModuleList记录了加载后的DLL相关信息,包含DLL的DllMain方法,即:EntryPoint方法,最后触发DLL中的DLL_PROCESS_ATTACH。

当调用FreeLibrary时,基本流程如下:
在这里插入图片描述
这里,通过遍历InInitializationOrderModuleList链表,当卸载某一系统dll时,Hook掉它的EntryPoint方法,即可实现在进程退出时进行后期的清理工作

		pListHeader = &pLdr->InInitializationOrderModuleList;pListEntry = (PLIST_ENTRY64)pListHeader->Flink;for (;;){if ( pListEntry == pListHeader ){break;}ldrDataTable = CONTAINING_RECORD(pListEntry, LDR_DATA_TABLE_ENTRY64, InInitializationOrderModuleList);if ( _wcsicmp((PWCHAR)ldrDataTable->BaseDllName.Buffer, L"kernel32.dll") == 0 ){// Found itldrDataTable->EntryPoint = (ULONG64)DllMainDummy;break;}pListEntry = (PLIST_ENTRY64)pListEntry->Flink;}
BOOL APIENTRY DllMainDummy( HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved )
{WCHAR Name[MAX_PATH] = {0};GetModuleFileNameW(hModule, Name, MAX_PATH);switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:wprintf(L"DllMainDummy: Hooked DLL_PROCESS_ATTACH, %ws \r\n", Name);break;case DLL_PROCESS_DETACH:wprintf(L"DllMainDummy: Hooked DLL_PROCESS_DETACH, %ws \r\n", Name);FreeLibrary(hModule);break;}return TRUE;
}

此时,当进程退出时,就会卸载kernel32.dll,调用kernel32.dll中的DLL_PROCESS_DETACH分支,此时的kernel32.dll中EntryPoint已经被Hook掉了,就会触发我们的DllMainDummy方法。

这篇关于一种Reflective DLL注入后的DLL卸载处理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/846292

相关文章

Java字符串处理全解析(String、StringBuilder与StringBuffer)

《Java字符串处理全解析(String、StringBuilder与StringBuffer)》:本文主要介绍Java字符串处理全解析(String、StringBuilder与StringBu... 目录Java字符串处理全解析:String、StringBuilder与StringBuffer一、St

浅析Java中如何优雅地处理null值

《浅析Java中如何优雅地处理null值》这篇文章主要为大家详细介绍了如何结合Lambda表达式和Optional,让Java更优雅地处理null值,感兴趣的小伙伴可以跟随小编一起学习一下... 目录场景 1:不为 null 则执行场景 2:不为 null 则返回,为 null 则返回特定值或抛出异常场景

如何将Python彻底卸载的三种方法

《如何将Python彻底卸载的三种方法》通常我们在一些软件的使用上有碰壁,第一反应就是卸载重装,所以有小伙伴就问我Python怎么卸载才能彻底卸载干净,今天这篇文章,小编就来教大家如何彻底卸载Pyth... 目录软件卸载①方法:②方法:③方法:清理相关文件夹软件卸载①方法:首先,在安装python时,下

深入理解Apache Kafka(分布式流处理平台)

《深入理解ApacheKafka(分布式流处理平台)》ApacheKafka作为现代分布式系统中的核心中间件,为构建高吞吐量、低延迟的数据管道提供了强大支持,本文将深入探讨Kafka的核心概念、架构... 目录引言一、Apache Kafka概述1.1 什么是Kafka?1.2 Kafka的核心概念二、Ka

resultMap如何处理复杂映射问题

《resultMap如何处理复杂映射问题》:本文主要介绍resultMap如何处理复杂映射问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录resultMap复杂映射问题Ⅰ 多对一查询:学生——老师Ⅱ 一对多查询:老师——学生总结resultMap复杂映射问题

Python FastAPI+Celery+RabbitMQ实现分布式图片水印处理系统

《PythonFastAPI+Celery+RabbitMQ实现分布式图片水印处理系统》这篇文章主要为大家详细介绍了PythonFastAPI如何结合Celery以及RabbitMQ实现简单的分布式... 实现思路FastAPI 服务器Celery 任务队列RabbitMQ 作为消息代理定时任务处理完整

Linux系统中卸载与安装JDK的详细教程

《Linux系统中卸载与安装JDK的详细教程》本文详细介绍了如何在Linux系统中通过Xshell和Xftp工具连接与传输文件,然后进行JDK的安装与卸载,安装步骤包括连接Linux、传输JDK安装包... 目录1、卸载1.1 linux删除自带的JDK1.2 Linux上卸载自己安装的JDK2、安装2.1

C#使用SQLite进行大数据量高效处理的代码示例

《C#使用SQLite进行大数据量高效处理的代码示例》在软件开发中,高效处理大数据量是一个常见且具有挑战性的任务,SQLite因其零配置、嵌入式、跨平台的特性,成为许多开发者的首选数据库,本文将深入探... 目录前言准备工作数据实体核心技术批量插入:从乌龟到猎豹的蜕变分页查询:加载百万数据异步处理:拒绝界面

Linux卸载自带jdk并安装新jdk版本的图文教程

《Linux卸载自带jdk并安装新jdk版本的图文教程》在Linux系统中,有时需要卸载预装的OpenJDK并安装特定版本的JDK,例如JDK1.8,所以本文给大家详细介绍了Linux卸载自带jdk并... 目录Ⅰ、卸载自带jdkⅡ、安装新版jdkⅠ、卸载自带jdk1、输入命令查看旧jdkrpm -qa

Springboot处理跨域的实现方式(附Demo)

《Springboot处理跨域的实现方式(附Demo)》:本文主要介绍Springboot处理跨域的实现方式(附Demo),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不... 目录Springboot处理跨域的方式1. 基本知识2. @CrossOrigin3. 全局跨域设置4.