逆向工程核心原理 Chapter24 | DLL卸载

news2024/11/24 18:57:57

DLL卸载技术的学习。

DLL卸载原理

DLL注入(Injection)是将DLL强制加载进进程的技术。

DLL卸载(Ejection)则是将强制插入进程的DLL弹出的技术。

两者的原理都十分类似,都用CreateRemoteThread来实现:

  • Injection:驱使目标进程调用LoadLibrary() API
  • Ejection:驱使目标进程调用FreeLibrary()API

具体到传参,

HANDLE CreateRemoteThread(
  [in]  HANDLE                 hProcess,
  [in]  LPSECURITY_ATTRIBUTES  lpThreadAttributes,
  [in]  SIZE_T                 dwStackSize,
  [in]  LPTHREAD_START_ROUTINE lpStartAddress,
  [in]  LPVOID                 lpParameter,
  [in]  DWORD                  dwCreationFlags,
  [out] LPDWORD                lpThreadId
);

就是将FreeLibrary()的API地址传给lpStartAddress参数,将待卸载的DLL字符串地址,传给lpParameter

但卸载相比注入,有个细节点要注意:

在这里插入图片描述

DLL卸载代码实现

照着教程的写一遍。

EjectDll.cpp

#include<Windows.h>
#include<iostream>
#include<tchar.h>
#include<TlHelp32.h>
using namespace std;

#define PROC_NAME (L"notepad.exe")
#define DLL_NAME (L"Dll1.dll")

DWORD FindProcessID(LPCTSTR szProcessName) {
	DWORD dwPid = 0xFFFFFFFF;
	HANDLE hSnapshot;
	BOOL bMore;
	PROCESSENTRY32 pe;

	// 获取当前系统快照snapshot
	pe.dwSize = sizeof(PROCESSENTRY32);
	hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);

	// 查找进程
	bMore = Process32First(hSnapshot, &pe);
	// 遍历
	for (; bMore; bMore = Process32Next(hSnapshot, &pe)) {
		if (!_tcsicmp(szProcessName, (LPCTSTR)pe.szExeFile)) {
			dwPid = pe.th32ProcessID;
			break;
		}
	}
	CloseHandle(hSnapshot);
	return dwPid;
}

BOOL SetPrivilege(LPCTSTR lpszPrivilege,BOOL bEnablePrivilege) {
	TOKEN_PRIVILEGES tp;
	HANDLE hToken;
	LUID luid;

	if (!OpenProcessToken(GetCurrentProcess(),
		TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
		cerr << "OpenProcessToken ERROR: " << GetLastError() << "\n";
		return FALSE;
	}
	if (!LookupPrivilegeValue(
		NULL, // on local system
		lpszPrivilege, // privilege to lookup
		&luid
	)) {
		cerr << "LookupPrivilegeValue ERROR: " << GetLastError() << "\n";
		return FALSE;
	}

	tp.PrivilegeCount = 1;
	tp.Privileges[0].Luid = luid;
	if (bEnablePrivilege) {
		tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	}
	else {
		tp.Privileges[0].Attributes = 0;
	}

	if (!AdjustTokenPrivileges(
		hToken,
		FALSE,
		&tp, // new state
		sizeof(TOKEN_PRIVILEGES),
		(PTOKEN_PRIVILEGES)NULL,
		(PDWORD)NULL
	)) {
		cerr << "AdjustTokenPrivileges ERROR: " << GetLastError() << "\n";
		return FALSE;
	}
	if (GetLastError() == ERROR_NOT_ALL_ASSIGNED) {
		cerr << "The token does not have the specified privilege!\n";
		return FALSE;
	}
	
	return TRUE;
}

BOOL EjectDll(DWORD dwPid,LPCTSTR szDllName) {
	BOOL bMore = FALSE, bFound = FALSE;
	HANDLE hSnapshot, hProcess, hThread;
	HMODULE hModule = NULL;
	MODULEENTRY32 me = { sizeof(me) };
	LPTHREAD_START_ROUTINE pThreadProc;

	// dwPid: notepad.exe进程的PID
	// 使用 TH32CS_SNAPMODULE参数,获取加载到notepad.exe进程的DLL名称
	hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPid);
	bMore = Module32First(hSnapshot, &me);
	// 遍历所有模块
	for (; bMore; bMore = Module32Next(hSnapshot, &me) ){
		if (!_tcsicmp((LPCTSTR)me.szModule, szDllName) ||
			!_tcsicmp((LPCTSTR)me.szExePath, szDllName )){
			bFound = TRUE;
			break;
		}
	}
	if (!bFound) {
		CloseHandle(hSnapshot);
		return FALSE;
	}
	if (!(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid))) {
		cerr << "OpenProcess failed!\n";
		return FALSE;
	}

	hModule = GetModuleHandle(L"kernel32.dll");
	pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hModule, "FreeLibrary");
	hThread = CreateRemoteThread(
		hProcess,
		NULL,
		0,
		pThreadProc,
		me.modBaseAddr,
		0,
		NULL
	);
	WaitForSingleObject(hThread, INFINITE);
	CloseHandle(hThread);
	CloseHandle(hProcess);
	CloseHandle(hSnapshot);
	return TRUE;
}

int _tmain(int argc, TCHAR* argv[]) {
	DWORD dwPid = 0xFFFFFFFF;
	dwPid = FindProcessID(PROC_NAME);
	if (dwPid == 0xFFFFFFFF) {
		cerr << "No process " << PROC_NAME << "!\n";
		return 1;
	}
	cout << "PID: " << dwPid << "\n";

	// 更改privilege
	if (!SetPrivilege(SE_DEBUG_NAME, TRUE))
		return 1;

	// Eject Dll
	if (EjectDll(dwPid, DLL_NAME))
		cout << "Success!\n";
	else
		cout << "Failed!\n";
	
	return 1 ^ 1;
}

学到了一大堆WIN32 API

  • CreateToolhelp32Snapshot

    获取指定进程以及这些进程使用的堆、模块和线程的快照。

    HANDLE CreateToolhelp32Snapshot(
      [in] DWORD dwFlags,
      [in] DWORD th32ProcessID
    );
    

    在这里插入图片描述

  • Module32First

    检索与进程关联的第一个模块的相关信息。

    BOOL Module32First(
      [in]      HANDLE          hSnapshot,
      [in, out] LPMODULEENTRY32 lpme
    );
    

    在这里插入图片描述

  • OpenProcessToken

    OpenProcessToken 函数打开与进程关联的访问令牌。

    BOOL OpenProcessToken(
      [in]  HANDLE  ProcessHandle,
      [in]  DWORD   DesiredAccess,
      [out] PHANDLE TokenHandle
    );
    
  • LookupPrivilegeValue

    LookupPrivilegeValue 函数检索指定系统上用于本地表示指定特权名称 (LUID) 本地唯一标识符。

    BOOL LookupPrivilegeValueW(
      [in, optional] LPCWSTR lpSystemName,
      [in]           LPCWSTR lpName,
      [out]          PLUID   lpLuid
    );
    

    在这里插入图片描述

  • AdjustTokenPrivileges

    AdjustTokenPrivileges 函数启用或禁用指定访问令牌中的特权。 启用或禁用访问令牌中的特权需要TOKEN_ADJUST_PRIVILEGES访问权限。

    BOOL AdjustTokenPrivileges(
      [in]            HANDLE            TokenHandle,
      [in]            BOOL              DisableAllPrivileges,
      [in, optional]  PTOKEN_PRIVILEGES NewState,
      [in]            DWORD             BufferLength,
      [out, optional] PTOKEN_PRIVILEGES PreviousState,
      [out, optional] PDWORD            ReturnLength
    );
    

源码分析

1. 获取进程中加载的DLL信息

hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,dwPid)

接触进程快照最初是在分析恶意代码的时候,很多都是用这种方式来注入/Kill杀软。

这里用快照获取MODULE信息,后面我们找ProcessPID那儿可以看到这个也可以获得PROCESS信息。

(用TH32CS_SNAPALL就行)

获取到MODULE和PROCESS后,就用Module32First/Module32Next进行模块(DLL)遍历。

找到跟szDllName匹配的后,用me的modBaseAddr成员获取DLL加载的地址。

2. 为什么要SetPrivilege?

教程只字没提这个点,但我觉得这个点挺重要的,感觉有点bypassUAC的影子。(maybe?)

在这里插入图片描述

但是我们DLL注入的时候没这么写啊?

我把那段调用SetPrivilege的代码注释掉,再运行:

在这里插入图片描述

发现还是成功的。~

这也验证了我的想法:

DLL注入和DLL卸载理论上应该是同等权限,DLL注入我们并没有提权,DLL卸载理应也不需要。

(其实应该是notepad.exe进程的权限不高,所以我们不需要高权限,如果是系统进程就不一样了)

但这个函数确实教会了SetPrivilege的WINAPI写法,从token中隐隐能看到bypassUAC这些的影子了。

UPD.
后面又翻了翻MS的文档:
在这里插入图片描述
这就有理可依了。

效果

先运行上次写的DllInject,向notepad.exe注入Dll1.dll,

在这里插入图片描述

process monitor查看:

在这里插入图片描述

然后编译运行EjectDll.cpp

在这里插入图片描述

成功实现DLL卸载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2101020.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

拼图软件推荐哪个好?日常拼图用这5个就够了

夏日悠长&#xff0c;暑假悄然过去&#xff0c;那些阳光灿烂的日子&#xff0c;是不是已经装满了你的相机和手机&#xff1f; 现在&#xff0c;是时候把这些珍贵的记忆碎片&#xff0c;用创意的拼图方式&#xff0c;编织成一本独一无二的暑假相册了&#xff01; 那么&#xf…

聚鼎装饰画:怎么做好一家装饰画店铺

在当今这个讲究美学和个性化的时代&#xff0c;拥有一家装饰画店铺无疑蕴含着巨大的潜力。然而&#xff0c;要想在这个竞争激烈的市场中崭露头角&#xff0c;不仅需要对艺术有着深厚的理解&#xff0c;还需要具备一定的商业头脑。本文将探讨几个关键的策略&#xff0c;帮助装饰…

行业首家!百度智能云通过中国信通院「H5 端人脸识别安全能力」测评

2024 年 6 月&#xff0c;在中国信通院组织的 H5 端人脸识别产品安全能力评测中&#xff0c;百度智能云「H5 实时活体检测产品-V3.0」在人脸识别算法安全能力、人脸数据传输安全能力、H5 端应用安全能力、身份认证业务安全能力、安全管理能力 5 个方面表现优异&#xff0c;相应…

NameNode 的 Web 界面

http://127.0.0.1:50070/ 图片显示的是Hadoop的Web界面导航栏。导航栏包含以下选项&#xff1a; Hadoop&#xff1a;Hadoop的主页。Overview&#xff1a;集群的概览信息。Datanodes&#xff1a;数据节点的状态和信息。Datanode Volume Failures&#xff1a;数据节点的卷故障信…

SAP B1 三大基本表单标准功能介绍-物料主数据(下)

背景 在 SAP B1 中&#xff0c;科目表、业务伙伴主数据、物料主数据被称为三大基本表单&#xff0c;其中的标准功能是实施项目的基础。本系列文章将逐一介绍三大基本表单各个字段的含义、须填内容、功能等内容。 附上 SAP B1 10.0 的帮助文档&#xff1a;SAP Business One 10…

给大模型加上“记忆”,深入探索 Mem0 项目

背景介绍 在之前的软件应用中&#xff0c;我们总会在应用中保留大量的用户历史操作记录&#xff0c;方便用户下次使用时可以快速查看和复用&#xff0c;甚至基于这些用户记录可以为用户提供个性化的服务。而这些记录往往都保存在传统的结构化或非结构化数据库中。 在大模型的…

高校为什么需要AIGC大数据实验室?

AIGC大数据实验室是一个专注于人工智能生成内容&#xff08;AIGC&#xff09;和大数据相关技术研究、开发与应用的创新实验平台。 AIGC主要研究方向包括&#xff1a;AIGC技术创新、大数据处理与分析、AIGC 与大数据融合应用。 AIGC 技术创新&#xff1a;探索如何利用人工…

企业微信hook协议接口,聚合群聊客户管理工具开发

服务提供了丰富的API和SDK&#xff0c;可以在企微的功能之上进行应用开发和功能扩展 自建应用可以调用企微hook或协议提供的接口来实现数据交互&#xff0c;可以直接调用hook或协议接口提供的功能来进行消息的发送与接收、用户管理、应用管理等操作&#xff0c;通过接口可以实…

线性代数教材书籍推荐

INTRODUCTION TO LINEAR ALGEBRA, 线性代数导论&#xff0c;GILBERT STRANG &#xff0c;有第六版中译本&#xff0c;网上也有第五版英文电子版&#xff0c;个人认为讲理论最好的教材 Practical Linear Algebra for Data Science&#xff0c;From Core Concepts to Applicatio…

相机常见名词详解

本文主要参考超人视觉课程做的笔记&#xff0c;有讲解不太懂的&#xff0c;又做了详细的解释 1、物距&#xff1a;物体到镜片的距离&#xff1b; 2、像距&#xff1a;像到镜片的距离&#xff1b; 3、焦距&#xff1a;镜片到焦点的距离&#xff1b; (1)二倍焦距以外&#xff…

LLM指令微调实践与分析

重磅推荐专栏: 《大模型AIGC》 《课程大纲》 《知识星球》 本专栏致力于探索和讨论当今最前沿的技术趋势和应用领域,包括但不限于ChatGPT和Stable Diffusion等。我们将深入研究大型模型的开发和应用,以及与之相关的人工智能生成内容(AIGC)技术。通过深入的技术解析和实践经…

毛辊清洗机的优势:

毛辊清洗机作为一种高效的清洗设备&#xff0c;在食品加工、农产品处理等多个领域得到了广泛应用。其主要优点可以归纳如下&#xff1a; 一、清洗效率高 有效容积大&#xff1a;毛辊清洗机设计有足够大的清洗空间&#xff0c;能够一次性处理大量的物料&#xff0c;如土豆、胡…

智能视频监控平台LntonAIServer安防监控视频平台视频质量诊断功能使用说明

LntonAIServer视频质量诊断功能是一种先进的技术&#xff0c;旨在通过智能分析来评估和优化视频流的质量。这种功能通常集成在视频传输和管理平台中&#xff0c;以提供对视频内容的实时监控和质量控制。以下是关于LntonAIServer视频质量诊断功能的使用说明阐述&#xff1a; 首…

【C++从练气到飞升】19---哈希:哈希冲突 | 哈希函数 | 闭散列 | 开散列

&#x1f388;个人主页&#xff1a;库库的里昂 ✨收录专栏&#xff1a;C从练气到飞升 &#x1f389;鸟欲高飞先振翅&#xff0c;人求上进先读书&#x1f389; 目录 ⛳️推荐 一、unordered 系列关联式容器 二、unordered_map 1.1 unordered_map 介绍 1.2 unordered_map 的…

COD论文笔记 BiRefNet

本质还是一个 U 型编码器解码器结构的分割模型。 我可以考虑将©和(d)结合&#xff0c;即对解码器的输入不进行 patchify,同时在各个阶段引入梯度参考信息 最近的相关工作&#xff0c;中间监督、额外先验(频率&#xff0c;梯度&#xff0c;边缘等)取得不错效果 作者观察到…

Elasticsearch简单介绍

1、 Elasticsearch简介 Elasticsearch 是一个分布式的、基于 RESTful API 的搜索和分析引擎&#xff0c;广泛用于大规模的数据存储和快速检索。它最初由 Shay Banon 于 2010 年开发&#xff0c;是开源的&#xff0c;并且是 Elastic Stack&#xff08;通常称为 ELK Stack&#…

ERP系统与WMS仓储管理系统在库存管理中的不同作用

在当今复杂多变的企业环境中&#xff0c;大型企业对于信息系统的依赖日益加深&#xff0c;特别是在库存管理与供应链优化方面。企业资源规划ERP系统与WMS仓储管理系统作为两大核心系统&#xff0c;各自扮演着不可或缺的角色&#xff0c;并通过紧密协作&#xff0c;共同推动企业…

MuseTalk模型构建指南

一、介绍 MuseTalk 是由腾讯团队开发的先进技术&#xff0c;它是一个实时的音频驱动唇部同步模型。该模型能够根据输入的音频信号&#xff0c;自动调整数字人物的面部图像&#xff0c;使其唇形与音频内容高度同步。 二、特点 多语言支持&#xff1a;该模型支持多种语言&…

为何我建议你学会Queue集合

先赞后看&#xff0c;南哥助你Java进阶一大半 PriorityQueue的底层数据结构就如andrewlock.net网站提供的图一样&#xff0c;虽然PriorityQueue是一个平衡二叉堆&#xff0c;但JDK底层的实现却是&#xff1a;一个普普通通的二维数组&#xff01;&#xff01; 我是南哥&#xff…

计算机网络 数据链路层2

ALOHA:想发就发 CSMA 载波监听多路访问协议 CS&#xff1a;载波监听&#xff0c;在发送数据之前检测总线上是否有其他计算机在发送数据 1-坚持CSMA:主机想发送消息&#xff0c;需要监听信道&#xff1b; 信道空闲则直接传输信息&#xff1b; 信道忙碌则一直监听&#xff0c;直…