Windows驱动反调试的一种手段

news2024/12/25 13:47:31

Windows驱动反调试的一种手段

今天要介绍的是eprocess的0xbc位置
+0x0bc DebugPort : Ptr32 Void

DebugPort是在用windowsapi调试方式时候所使用的数据结构指针,那么如果我们能够循环清空这个值的话,就可以做到大部分windows调试api都无法正确调试进程

效果如下:
在这里插入图片描述
驱动代码:

#include <ntddk.h>
//#include <ntifs.h>
#define NTSTRSAFE_LIB
#include <ntstrsafe.h>
#include <intrin.h>

extern NTSTATUS PsLookupProcessByProcessId(
	  HANDLE    ProcessId,
	PEPROCESS* Process
);

PDEVICE_OBJECT g_pDev = NULL;
UNICODE_STRING devName = { 0 };
UNICODE_STRING symName = { 0 };
DWORD32 g_idtNum = 0;
PVOID sharedMem;
BOOLEAN g_LoopDelDebugportRun = FALSE;
HANDLE g_LoopDelProcessThreadHandle = 0;

VOID Unload(PDRIVER_OBJECT pDriver) {
	KdPrint(("unload"));
	if (g_LoopDelDebugportRun) {
		LARGE_INTEGER time = { 0 };
		time.QuadPart = -100 * 10 * 1000 * 10;//10秒
		g_LoopDelDebugportRun = FALSE;
		KeWaitForSingleObject(&g_LoopDelProcessThreadHandle, Executive, KernelMode,
			FALSE, &time);
		ZwClose(g_LoopDelProcessThreadHandle);
	}
	IoDeleteSymbolicLink(&symName);
	IoDeleteDevice(g_pDev);

}

typedef struct _IDTR {
	UINT16 limit;
	UINT16 base_low;
	UINT16 base_hight;
}IDTR, *PIDTR;
#define DEVICE_OBJECT_NAME L"\\Device\\systest"
#define DEVICE_LINK_NAME L"\\??\\systest"
#define MAKE_WORD(a,b) ((a) + (b << 16))
#define MAKE_BASE(a) (DWORD32)(((a >> 32) & 0x00000000ffff0000) + ((a & 0x000000000000ffff)))
#define IOCTL_SYS_INJECTIDT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, \
										METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SYS_MAKE_SHAREDPAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, \
										METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SYS_HIDEPROCESS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, \
										METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SYS_DELDEBUGPORT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, \
										METHOD_BUFFERED, FILE_ANY_ACCESS)



VOID LoopDelDebugport(PVOID context)
{
	LARGE_INTEGER time = { 0 };
	time.QuadPart = -100 * 10 * 1000 * 3;//3秒
	g_LoopDelDebugportRun = TRUE;
	PUINT32 port = context;
	while (g_LoopDelDebugportRun)
	{
		*port = 0x0;
		KeDelayExecutionThread(KernelMode, FALSE, &time);
	}
	PsTerminateSystemThread(0);//销毁内核对象
}

NTSTATUS DelProcDebport(UINT32 pid)
{
	PEPROCESS pEprocess = NULL;
	_asm {
		mov eax, fs: [0x124]
		mov eax, [eax + 0x220]
		mov pEprocess, eax
	}
	PLIST_ENTRY listHead = (PLIST_ENTRY)((PUCHAR)pEprocess + 0x88);
	if (listHead == NULL)
		return STATUS_UNSUCCESSFUL;
	PLIST_ENTRY next = listHead;
	//DbgBreakPoint();
	do
	{
		pEprocess = (PEPROCESS)((PUCHAR)next - 0x88);
		DWORD32 cpid = *(PDWORD32)((PUCHAR)pEprocess + 0x84);
		if (cpid == pid) {
			LPSTR name = NULL;
			name = (PUCHAR)pEprocess + 0x174;
			KdPrint(("该进程名称: %s\n", name));
			PVOID context = (PVOID)((PUCHAR)pEprocess + 0xbc);
			NTSTATUS status = PsCreateSystemThread(&g_LoopDelProcessThreadHandle,
				0, NULL, NULL, NULL, LoopDelDebugport, context);
			if (!NT_SUCCESS(status)) {
				KdPrint(("创建循环清空debugpoprt线程失败!\r\n"));
				return status;
			}
			KdPrint(("触发反调试线程成功!\n"));
			return STATUS_SUCCESS;
		}
		next = next->Flink;
	} while (next != NULL && listHead != next);
	return STATUS_UNSUCCESSFUL;
}

NTSTATUS DeviceControl(PDEVICE_OBJECT pDev, PIRP pIrp)
{
	NTSTATUS status = STATUS_SUCCESS;
	ULONG_PTR Informaiton = 0;
	ULONG ioControlCode = 0;
	PVOID input = NULL;
	ULONG inputLen = 0;
	PVOID output = NULL;
	ULONG outputLen = 0;
	PIO_STACK_LOCATION pIoStackLocation = IoGetCurrentIrpStackLocation(pIrp);
	ioControlCode = pIoStackLocation->Parameters.DeviceIoControl.IoControlCode;
	input = pIrp->AssociatedIrp.SystemBuffer;
	output = pIrp->AssociatedIrp.SystemBuffer;
	inputLen = pIoStackLocation->Parameters.DeviceIoControl.InputBufferLength;
	outputLen = pIoStackLocation->Parameters.DeviceIoControl.OutputBufferLength;
	switch (ioControlCode)
	{
	case IOCTL_SYS_DELDEBUGPORT:
	{
		DWORD32* data = (PDWORD32)input;
		UINT32 pid = data[0];
		status = DelProcDebport(pid);
		if (!NT_SUCCESS(status)) {
			KdPrint(("failed del process debugport!\n"));
		}
		break;
	}
	default:
		break;
	}
	pIrp->IoStatus.Status = status;
	pIrp->IoStatus.Information = Informaiton;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return status;
}

NTSTATUS PassFunc(PDEVICE_OBJECT pDev, PIRP pIrp)
{
	pIrp->IoStatus.Information = 0;
	pIrp->IoStatus.Status = STATUS_SUCCESS;
	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver, PUNICODE_STRING pRegPath) {
	NTSTATUS status = STATUS_SUCCESS;
	
	
	pDriver->DriverUnload = Unload;
	for (size_t i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
	{
		pDriver->MajorFunction[i] = PassFunc;
	}
	pDriver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceControl;
	do
	{
		KdPrint(("begin\r\n"));
		//创建设备对象
		
		RtlInitUnicodeString(&devName, DEVICE_OBJECT_NAME);
		status = IoCreateDevice(pDriver, 0, &devName, FILE_DEVICE_UNKNOWN, 0, FALSE, &g_pDev);
		if (!NT_SUCCESS(status)) {
			KdPrint(("Create Dev Object Failed!\r\n"));
			break;
		}
		RtlInitUnicodeString(&symName, DEVICE_LINK_NAME);
		status = IoCreateSymbolicLink(&symName, &devName);
		if (!NT_SUCCESS(status)) {
			KdPrint(("Create Sym Link Failed!\r\n"));
			IoDeleteDevice(g_pDev);
			break;
		}
		g_pDev->Flags |= DO_BUFFERED_IO;

	} while (FALSE);
	
	

	
	return status;
}

三环代码:

// test1.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <windows.h>
#define DEVICE_LINK_NAME L"\\\\.\\systest"
#define IOCTL_SYS_INJECTIDT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, \
										METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SYS_MAKE_SHAREDPAGE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, \
										METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SYS_HIDEPROCESS CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, \
										METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SYS_DELDEBUGPORT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, \
										METHOD_BUFFERED, FILE_ANY_ACCESS)
int _tmain(int argc, _TCHAR* argv[])
{
	HANDLE devHandle = CreateFile(DEVICE_LINK_NAME,
		GENERIC_READ | GENERIC_WRITE,
		FILE_SHARE_READ|FILE_SHARE_WRITE,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);
	if (devHandle == NULL || devHandle == INVALID_HANDLE_VALUE) {
		printf("open dev failed\n");
		return 0;
	}
	UINT32 pid = GetCurrentProcessId();
	DWORD returnLen = 0;
	BOOL IsOK = DeviceIoControl(devHandle,
		IOCTL_SYS_DELDEBUGPORT,
		&pid,
		sizeof(pid),
		&pid,
		sizeof(pid),
		&returnLen,
		NULL);
	
	CloseHandle(devHandle);
	devHandle = NULL;
	while(true){
		printf("test\n");
		Sleep(1000);
	}

	return 0;
}


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

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

相关文章

机器学习算法基础--聚类问题的评价指标

1.聚类问题指标评价的意义 聚类算法是非监督学习最常用的一种方法&#xff0c;性能度量是衡量学习模型优劣的指标&#xff0c;也可作为优化学习模型的目标函数。聚类性能度量根据训练数据是否包含标记数据分为两类&#xff0c;一类是将聚类结果与标记数据进行比较&#xff0c;称…

【Axure】常见元件、常用交互效果

产品结构图 以微信为例&#xff0c;根据页面层级制作 动态面板 动态面板的作用&#xff1a;动态面板是一个可视区域&#xff0c;如果要把控件放进去&#xff0c;要全部放进去&#xff0c;放多少显示多少 文本框 隐藏边框方法&#xff1a;先拉一个矩形&#xff0c;去掉部分…

uniapp项目实践总结(二十五)苹果 ios 平台 APP 打包教程

导语:当你的应用程序开发完成后,在上架 ios 应用商店之前,需要进行打包操作,下面就简单介绍一下打包方法。 目录 准备工作注册账号生成证书打包配置准备工作 在打包之前,请保证你的 uniapp 应用程序编译到 ios 模拟器或者是真机调试基座环境下是可以正常运行的,苹果打包…

记录一次阿里云服务器ECS上启动的portainer无法访问的问题

如下图&#xff0c;在阿里云ECS服务器上安装并启动了portainer&#xff0c;但是在自己电脑上访问不了远程的portainer。 最后发现是要在网络安全组里开放9000端口号&#xff0c;具体操作如下&#xff1a; 在云服务器管理控制台点击左侧菜单中的网络与安全-安全组&#xff0c;然…

国庆day2---select实现服务器并发

select.c&#xff1a; #include <myhead.h>#define ERR_MSG(msg) do{\fprintf(stderr,"__%d__:",__LINE__);\perror(msg);\ }while(0)#define IP "192.168.1.3" #define PORT 8888int main(int argc, const char *argv[]) {//创建报式套接字socketi…

Java笔记五(数组)

目录 数组 数组声明创建 数组初始化的三种初始化类型&#xff1a; 静态初始化 动态初始化 数组的默认初始化 数组的四个基本特点 数组边界 数组的使用 示例一&#xff1a;计算所有的元素和以及查找最大元素 示例二&#xff1a;For-Each循环 示例三&#xff1a;数组作…

[NOIP2011 提高组] 选择客栈

[NOIP2011 提高组] 选择客栈 题目描述 丽江河边有 n n n 家很有特色的客栈&#xff0c;客栈按照其位置顺序从 1 1 1 到 n n n 编号。每家客栈都按照某一种色调进行装饰&#xff08;总共 k k k 种&#xff0c;用整数 0 ∼ k − 1 0 \sim k-1 0∼k−1 表示&#xff09;&am…

【论文笔记】SVDM: Single-View Diffusion Model for Pseudo-Stereo 3D Object Detection

原文链接&#xff1a;https://arxiv.org/abs/2307.02270 1. 引言 目前的从单目相机生成伪传感器表达的方法依赖预训练的深度估计网络。这些方法需要深度标签来训练深度估计网络&#xff0c;且伪立体方法通过图像正向变形合成立体图像&#xff0c;会导致遮挡区域的像素伪影、扭…

初识Java 12-1 流

目录 Java 8对流的支持 流的创建 随机数流 int类型的区间范围 generate() iterate() 流生成器 Arrays 正则表达式 本笔记参考自&#xff1a; 《On Java 中文版》 ||| 流的概念&#xff1a;流是一个与任何特定的存储机制都没有关系的元素序列。 流与对象的成批处理有关…

CSP-J第二轮试题-2021年-3题

文章目录 参考&#xff1a;总结 [CSP-J 2021] 网络连接题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 样例 #2样例输入 #2样例输出 #2 样例 #3样例输入 #3样例输出 #3 样例 #4样例输入 #4样例输出 #4 提示答案1答案2 现场真题注意事项 参考&#xff1a; https://www…

使用 MyBatis 进行批量插入操作

使用 MyBatis 进行批量插入操作 批量插入是在数据库中同时插入多条记录的操作&#xff0c;通常用于提高数据插入的效率&#xff0c;特别是在需要大量数据导入或初始化时。MyBatis是一款流行的Java持久层框架&#xff0c;它提供了简单而强大的方式来执行批量插入操作。本文将介…

【数据结构】树的概念理解和性质推导(保姆级详解,小白必看系列)

目录 一、前言 &#x1f34e; 为什么要学习非线性结构 ---- 树&#xff08;Tree&#xff09; &#x1f4a6; 线性结构的优缺点 &#x1f4a6; 优化方案 ----- 树&#xff08;Tree&#xff09; &#x1f4a6; 树的讲解流程 二、树的概念及结构 &#x1f350; 树的概念 &…

vue + openlayer 按路径移动

示例 创建一个方形的规矩&#xff0c;并让点按轨迹移动。效果如下: 源代码 <template><div><div id"map" class"map"></div><button id"start-animation" ref"startButton">Start Animation</bu…

【Python】基于OpenCV人脸追踪、手势识别控制的求实之路FPS游戏操作

【Python】基于OpenCV人脸追踪、手势识别控制的求实之路FPS游戏操作 文章目录 手势识别人脸追踪键盘控制整体代码附录&#xff1a;列表的赋值类型和py打包列表赋值BUG复现代码改进优化总结 py打包 视频&#xff1a; 基于OpenCV人脸追踪、手势识别控制的求实之路FPS游戏操作 手…

Cursor不要太好用,看图见真相

看图见真相: Cursor安装地址: https://www.cursor.so/

02_静态链接和简单宕机分享

ARM64寄存器 Arm64提供31个64bit通用寄存器 汇编用x表示64位宽 w32位宽 X0~X7: 用于传递子程序参数和结果&#xff0c;使用时不需要保存&#xff0c;多余参数采用堆栈传递&#xff0c;64位返回结果采用x0表示&#xff0c;128位 返回结果采用X1:X0 表示。 X24到x28 看得出来子…

C++容器之unordered_map、unordered_set的底层剖析

文中源码以上传至Gitee 目录 序列式容器和关联式容器unordered_set和unordered_map 哈希表概念 哈希函数与哈希冲突常用的哈希函数直接定址法除留余数法 哈希冲突处理方案开放定址法链地址法开放定地址法和链地址法对比 开放定址法实现链地址法实现unordered_map和unordered_s…

什么是SQL注入(SQL Injection)?如何预防它

什么是 SQL 注入&#xff08;SQL Injection&#xff09;&#xff1f;如何预防它&#xff1f; SQL注入&#xff08;SQL Injection&#xff09;是一种常见的网络安全漏洞&#xff0c;攻击者通过在应用程序的输入中插入恶意SQL代码来执行未经授权的数据库操作。SQL注入攻击可能导…

CSP-J第二轮试题-2020年-4题

文章目录 参考&#xff1a;总结 [CSP-J2020] 方格取数题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 样例 #2样例输入 #2样例输出 #2 提示样例 1 解释 样例 2 解释 数据规模与约定 答案1 现场真题注意事项 参考&#xff1a; P7074 [CSP-J2020] 方格取数 总结 本系…

Docker 自动化部署(实践)

常用命令 docker search jenkins查看需要的jenkins镜像源 docker pull jenkins/jenkins 拉取jenkins镜像 docker images查看下载的镜像源 docker ps 查看包含启动以及未启动的容器 docker ps -a查看启动的容器 docker rm 容器id/容器名称 删除容器 docker rm -f 容器id/容器名…