欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]Win 7下过盛*大,H*S驱动保护

[原创]Win 7下过盛*大,H*S驱动保护



        大家调试的时候都可以知道,盛*大游戏(泡泡堂)的外壳是Themida,可以用OD创建进程,但不能附加游戏,本来想只用一个驱动文件来过保护的,但在Win 7的HOOK里判断进程名,会出问题,导致系统奔溃,而这在Win XP却不会,个人比较郁闷!
        所以用了另一个办法来判断指定进程,就是进程的PID,这个比较唯一。Ring 3创建进程,并挂起进程,然后安装驱动,向驱动传递游戏的进程PID,然后驱动就执行HOOK,通过进程PID来判断是否要跳转。
        功能,可以用CE打开进程,读取,修改进程,用CE的调试器附加进程。
        最后说明下,这个必须在Win 7下,且你的SSDT表是干净的,没有腾讯的QQProtect.sys这个驱动文件在执行,SSDT没有被HOOK。可以用安全工具把QQProtect.sys由系统引导启动设置成手动启动。
下面贴上代码:
Ring 3层的MFC程序:
安装驱动的函数:


void CDriverProtectDlg::OnBnClickedButton2()

{

	// TODO: 在此添加控件通知处理程序代码

	InstallCWinThread = AfxBeginThread(InstallDriverThread,this);

}


安装驱动的函数:

BOOL CDriverProtectDlg::LoadNTDriver(wchar_t* lpszDriverName, wchar_t* lpszDriverPath)

{

	wchar_t szDriverImagePath[256];

	::GetFullPathNameW(strPath,256,szDriverImagePath,NULL);

	BOOL bRet = FALSE;

	SC_HANDLE hServiceMgr=NULL;//SCM管理器的句柄

	SC_HANDLE hServiceDDK=NULL;//NT驱动程序的服务句柄

	hServiceMgr = ::OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);

	if( hServiceMgr == NULL )

	{

		m_DriverINFORMATION.SetWindowTextW(L"打开服务失败!");

		bRet = FALSE;

		goto BeforeLeave;

	}

	else

	{

		////OpenSCManager成功

		m_DriverINFORMATION.SetWindowTextW(L"OpenSCManager成功!");

	}

	//创建驱动所对应的服务

	hServiceDDK = CreateServiceW(hServiceMgr,lpszDriverName,lpszDriverName,SERVICE_ALL_ACCESS,SERVICE_KERNEL_DRIVER,SERVICE_DEMAND_START,SERVICE_ERROR_IGNORE,szDriverImagePath,NULL,NULL,NULL,NULL,NULL);

	DWORD dwRtn;

	//判断服务是否失败

	if (hServiceDDK == NULL)

	{

		dwRtn = GetLastError();

		if (dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_EXISTS)

		{

			//由于其他原因创建服务失败

			strError.Format(L"%d",dwRtn);

			m_DriverINFORMATION.SetWindowTextW(L"由于其他原因创建服务失败!" + strError);

			bRet = FALSE;

			goto BeforeLeave;

		}

		else

		{

			m_DriverINFORMATION.SetWindowTextW(L"服务创建失败,是由于服务已经创立过!");

		}

		// 驱动程序已经加载,只需要打开  

		hServiceDDK=::OpenServiceW(hServiceMgr,lpszDriverName, SERVICE_ALL_ACCESS);

		if( hServiceDDK == NULL )  

		{

			//如果打开服务也失败,则意味错误

			dwRtn = GetLastError();  

			strError.Format(L"%d",dwRtn);

			m_DriverINFORMATION.SetWindowTextW(L"如果打开服务也失败,则意味错误!" + strError);

			bRet = FALSE;

			goto BeforeLeave;

		}

		else

		{

			m_DriverINFORMATION.SetWindowTextW(L"打开服务成功!");

		}

	}

	else  

	{

		m_DriverINFORMATION.SetWindowTextW(L"创建服务成功!");

	}

	bRet= ::StartServiceW( hServiceDDK, NULL, NULL );  

	if( !bRet ) 

	{

		DWORD dwRtn = GetLastError();

		if( dwRtn != ERROR_IO_PENDING && dwRtn != ERROR_SERVICE_ALREADY_RUNNING )  

		{  

			strError.Format(L"%d",dwRtn);

			m_DriverINFORMATION.SetWindowTextW(L"开启此项服务失败!");

			bRet = FALSE;

			goto BeforeLeave;

		}  

		else

		{

			if( dwRtn == ERROR_IO_PENDING )  

			{  

				//设备被挂住

				m_DriverINFORMATION.SetWindowTextW(L"设备被挂住!");

				bRet = FALSE;

				goto BeforeLeave;

			} 

			else  

			{  

				//服务已经开启

				m_DriverINFORMATION.SetWindowTextW(L"打开服务失败,因为服务已经开启!");

				bRet = TRUE;

				goto BeforeLeave;

			}  

		}

	}

	bRet = TRUE;

BeforeLeave:

	//离开前关闭打开的句柄

	if(hServiceDDK)

	{

		CloseServiceHandle(hServiceDDK);

	}

	if(hServiceMgr)

	{

		CloseServiceHandle(hServiceMgr);

	}

	return bRet;

}


安装驱动的线程:

// 安装驱动的线程函数

UINT __cdecl CDriverProtectDlg::InstallDriverThread(LPVOID pParam)

{

	CDriverProtectDlg* pDlg = NULL;

	pDlg = (CDriverProtectDlg*)pParam;

	pDlg->UpdateData(TRUE);

	if (pDlg->strPath.IsEmpty())

	{

		AfxMessageBox(L"请选择驱动路径!");

		return 0;

	}

	if (pDlg->strrGamePath.IsEmpty())

	{

		AfxMessageBox(L"请选择游戏路径!");

		return 0;

	}

	if (!pDlg->LoadNTDriver(L"HelloDDK",pDlg->strPath.GetBuffer()))

	{

		pDlg->UnloadNTDriver(L"HelloDDK");

		pDlg->LoadNTDriver(L"HelloDDK",pDlg->strPath.GetBuffer());

	}

	HANDLE hDevice = 

		::CreateFileW(L"\\\\.\\HelloDDK",

		GENERIC_READ | GENERIC_WRITE,

		0,		// share mode none

		NULL,	// no security

		OPEN_EXISTING,

		FILE_ATTRIBUTE_NORMAL,

		NULL );		// no template

	if (hDevice == INVALID_HANDLE_VALUE)

	{

		pDlg->m_DriverINFORMATION.SetWindowTextW(L"打开驱动错误!");

		return 1;

	}

	DWORD Pid = pDlg->TransferProcessID(pDlg->strrGamePath.GetBuffer());

	int a = (int)Pid;

	UCHAR* InputBuffer = new UCHAR[a];

	UCHAR* OutputBuffer= new UCHAR[a];

	BOOL bRet;

	DWORD dwOutput;

	//输入缓冲区作为输入,输出缓冲区作为输出

	bRet = DeviceIoControl(hDevice, IOCTL_TEST1, InputBuffer, a, OutputBuffer, a, &dwOutput, NULL);

	if (bRet)

	{

		pDlg->m_DriverINFORMATION.SetWindowTextW(L"开启保护成功!");

	}

	CloseHandle(hDevice);

	delete []InputBuffer;

	delete []OutputBuffer;

	//AfxEndThread(0);

	ResumeThread(pDlg->ProcessMainThread);

	pDlg = NULL;

	return 0;

}


ring 0层的驱动函数的代码:
DeviceIoControl的派遣函数:

#pragma PAGEDCODE

NTSTATUS HelloDDKDeviceIOControl(IN PDEVICE_OBJECT pDevObj,

								 IN PIRP pIrp)

{

	NTSTATUS status = STATUS_SUCCESS;

	KdPrint(("Enter HelloDDKDeviceIOControl\n"));

	//得到当前堆栈

	PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);

	//得到输入缓冲区大小

	ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength;

	//得到输出缓冲区大小

	ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength;

	//得到IOCTL码

	ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;

	ULONG info = 0;

	switch (code)

	{						// process request

		case IOCTL_TEST1:

		{

			KdPrint(("IOCTL_TEST1\n"));

			GameProcessID = (int)cbin;

			//KIRQL oldirql;

			//ASSERT(KeGetCurrentIrql()<=DISPATCH_LEVEL);

			//KeRaiseIrql(DISPATCH_LEVEL,&oldirql);

			HookNtOpenProcess();

			HookNtReadVirtualMemory();

			HookNtWriteVirtualMemory();

			HookNtClose();

			HookNtProtectVirtualMemory();

			HookPsSuspendThread();

			HookNtGetContextThread();

			HookNtQueryPerformanceCounter();

			HookNtSetContextThread();

			HookKiAttachProcess();

			HookNtDeviceIoControlFile();

			//KeLowerIrql(oldirql);

			//缓冲区方式IOCTL

			//显示输入缓冲区数据

 			UCHAR* InputBuffer = (UCHAR*)pIrp->AssociatedIrp.SystemBuffer;


这个为全局变量   int GameProcessID;
下面是绕过的钩子函数(部分):

#include "HookNtDeviceIoControlFile.h"

#include "Function.h"

extern int GameProcessID;

int SrcNtDeviceIoControlFileAddr;

int OldCallNtDeviceIoControlFileAddr;

int NewCallNtDeviceIoControlFileAddr;

int JmpNtDeviceIoControlFileAddr;

int Index;

int NtDeviceIoControlFileAddr;

/*

0x81C7948C    |    55    |    push ebp    |        

0x81C7948D    |    8BEC    |    mov ebp, esp    |        

0x81C7948F    |    6A 01    |    push 1    |        

0x81C79491    |    FF75 2C    |    push dword ptr [ebp+2C]    |        

0x81C79494    |    FF75 28    |    push dword ptr [ebp+28]    |        

0x81C79497    |    FF75 24    |    push dword ptr [ebp+24]    |        

0x81C7949A    |    FF75 20    |    push dword ptr [ebp+20]    |        

0x81C7949D    |    FF75 1C    |    push dword ptr [ebp+1C]    |        

0x81C794A0    |    FF75 18    |    push dword ptr [ebp+18]    |        

0x81C794A3    |    FF75 14    |    push dword ptr [ebp+14]    |        

0x81C794A6    |    FF75 10    |    push dword ptr [ebp+10]    |        

0x81C794A9    |    FF75 0C    |    push dword ptr [ebp+C]    |        

0x81C794AC    |    FF75 08    |    push dword ptr [ebp+8]    |        

0x81C794AF    |    E8 BD90FBFF    |    call 81C32571    |        

0x81C794B4    |    5D    |    pop ebp    |        

0x81C794B5    |    C2 2800    |    retn 28    |  

*/

static __declspec(naked) void MyNtDeviceIoControlFile()

{

	__asm

	{

		push ebp

		mov ebp, esp

		push 1

		push dword ptr [ebp+0x2C]

		push dword ptr [ebp+0x28] 

		push dword ptr [ebp+0x24]

		push dword ptr [ebp+0x20]

		push dword ptr [ebp+0x1C]

		push dword ptr [ebp+0x18]

		push dword ptr [ebp+0x14]

		push dword ptr [ebp+0x10]

		push dword ptr [ebp+0xC]

		push dword ptr [ebp+0x8]

	}

	if (PanDuanProcessID()==GameProcessID)

	{

		__asm

		{

			jmp NewCallNtDeviceIoControlFileAddr

			call OldCallNtDeviceIoControlFileAddr

			jmp JmpNtDeviceIoControlFileAddr

		}

	}

	else

	{

		__asm

		{

			call OldCallNtDeviceIoControlFileAddr

			jmp JmpNtDeviceIoControlFileAddr

		}

	}

}

void HookNtDeviceIoControlFile()

{

	char code[1]={(char)0xE8};

	Index=GetFunctionIndex(ZwDeviceIoControlFile);

	SrcNtDeviceIoControlFileAddr=SearchFeature(GetSSDTFunctionAddr(Index),code,1);

	OldCallNtDeviceIoControlFileAddr=GetCallAddr(SrcNtDeviceIoControlFileAddr);

	NewCallNtDeviceIoControlFileAddr=SrcNtDeviceIoControlFileAddr-1;

	JmpNtDeviceIoControlFileAddr=SrcNtDeviceIoControlFileAddr+4;

	NtDeviceIoControlFileAddr=SSDTHookEngine(Index,(int)MyNtDeviceIoControlFile);

}

void UnHookNtDeviceIoControlFile()

{

	SSDTUnHookEngine(Index,NtDeviceIoControlFileAddr);

}


经研究KiAttachProcess没有检测

#include "HookKiAttachProcess.h"

#include "Function.h"

extern int GameProcessID;

int SrcKiAttachProcessAddr;

int KiMoveApcState;

int KiInSwapSingleProcess;

int HvlLongSpinCountMask;

int HvlEnlightenments;

int HvlNotifyLongSpinWait;

int _imp_KfLowerIrql;

int KiSwapProcess;

int SrcKeStackAttachProcessAddr;

int KeStackAttachProcessCall_1;

int KeStackAttachProcessCall_2;

int SrcKeAttachProcessAddr;

int KeAttachProcessCall_1;

static __declspec(naked) void MyKiAttachProcess()

{

//	if (PanDuanProcessID()==GameProcessID)

//	{

//		__asm

//		{

//			mov     edi,edi

//			push    ebp

//			mov     ebp,esp

//			push    ebx

//			mov     ebx,dword ptr [ebp+8]

//			push    esi

//			mov     esi,eax

//			mov     eax,dword ptr [ebp+10h]

//			push    edi

//			lea     edi,[esi+40h]

//			push    edi

//			call    KiMoveApcState

//			mov     ecx,dword ptr [ebp+10h]

//			mov     dword ptr [edi+4],edi

//			mov     dword ptr [edi],edi

//			lea     eax,[esi+48h]

//			mov     dword ptr [eax+4],eax

//			mov     dword ptr [eax],eax

//			lea     eax,[esi+170h]

//			mov     byte ptr [esi+54h],0

//			mov     byte ptr [esi+55h],0

//			mov     byte ptr [esi+56h],0

//			cmp     ecx,eax

//			jne      KiAttachProcess_52

//KiAttachProcess_3f:

//			mov     dword ptr [esi+168h],eax

//			mov     dword ptr [esi+16Ch],edi

//			mov     byte ptr [esi+134h],1

//KiAttachProcess_52:

//			push    8

//			pop     eax

//			lea     edx,[ebx+74h]

//			lock xadd dword ptr [edx],eax

//			mov     dword ptr [ebp+8],eax

//			mov     eax,dword ptr [ebp+8]

//			test    al,7

//			jne     KiAttachProcess_76

//KiAttachProcess_66:

//			mov     dword ptr [esi+50h],ebx

//			xor     eax,eax

//			add     esi,60h

//			lock and dword ptr [esi],eax

//			push    dword ptr [ecx+10h]

//			jmp     KiAttachProcess_cb

//KiAttachProcess_76:

//			lea     edi,[esi+60h]

//			xor     eax,eax

//			mov     ecx,edi

//			lock and dword ptr [ecx],eax

//			mov     eax,ebx

//			call    KiInSwapSingleProcess

//			and     dword ptr [ebp+8],0

//			jmp     KiAttachProcess_b4

//KiAttachProcess_8d:

//			inc     dword ptr [ebp+8]

//			mov     eax,dword ptr [ebp+8]

//			test    dword ptr [HvlLongSpinCountMask],eax

//			jne     KiAttachProcess_ac

//KiAttachProcess_9b:

//			test    byte ptr [HvlEnlightenments],40h

//			je      KiAttachProcess_ac

//KiAttachProcess_a4:

//			push    eax

//			call    HvlNotifyLongSpinWait

//			jmp     KiAttachProcess_ae

//KiAttachProcess_ac:

//			pause

//KiAttachProcess_ae:

//			mov     eax,dword ptr [edi]

//			test    eax,eax

//			jne     KiAttachProcess_8d

//KiAttachProcess_b4:

//			xor     eax,eax

//			mov     ecx,edi

//			inc     eax

//			xchg    eax,dword ptr [ecx]

//			test    eax,eax

//			jne     KiAttachProcess_8d

//KiAttachProcess_bf:

//			mov     dword ptr [esi+50h],ebx

//			lock and dword ptr [edi],eax

//			mov     eax,dword ptr [ebp+10h]

//			push    dword ptr [eax+10h]

//KiAttachProcess_cb:

//			push    ebx

//			call    KiSwapProcess

//			mov     cl,byte ptr [ebp+0Ch]

//			call    dword ptr [_imp_KfLowerIrql]

//			pop     edi

//			pop     esi

//			pop     ebx

//			pop     ebp

//			ret     0Ch

//		}

//	}

//	else

//	{

//		__asm

//		{

//			jmp	SrcKiAttachProcessAddr

//		}

//	}

	__asm 

	{

		jmp	SrcKiAttachProcessAddr

	}

}

void HookKiAttachProcess()

{

	char code[1]={(char)0xE8};

	SrcKiAttachProcessAddr=Win7GetKiAttachProcessAddr();

	KiMoveApcState = GetCallAddr(SearchFeature(SrcKiAttachProcessAddr,code,1));

	//DbgPrint("SrcKiAttachProcessAddr = %x",SrcKiAttachProcessAddr);

	//DbgPrint("KiMoveApcState = %x",KiMoveApcState);

	KiInSwapSingleProcess = GetCallAddr(SearchFeature(SearchFeature(SrcKiAttachProcessAddr,code,1)+1,code,1));

	//DbgPrint("KiInSwapSingleProcess = %x",KiInSwapSingleProcess);

	HvlLongSpinCountMask=(*((int*)(SrcKiAttachProcessAddr+0x8D+8)));

	//DbgPrint("HvlLongSpinCountMask = %x",HvlLongSpinCountMask);

	HvlEnlightenments=(*((int*)(SrcKiAttachProcessAddr+0x9B+2)));

	//DbgPrint("HvlEnlightenments = %x",HvlEnlightenments);

	HvlNotifyLongSpinWait=GetCallAddr(SearchFeature(SearchFeature(SearchFeature(SrcKiAttachProcessAddr,code,1)+1,code,1)+1,code,1));

	//DbgPrint("HvlNotifyLongSpinWait = %x",HvlNotifyLongSpinWait);

	KiSwapProcess = GetCallAddr(SearchFeature(SearchFeature(SearchFeature(SearchFeature(SrcKiAttachProcessAddr,code,1)+1,code,1)+1,code,1)+1,code,1));

	//DbgPrint("KiSwapProcess = %x",KiSwapProcess);

	_imp_KfLowerIrql=(*((int*)(SrcKiAttachProcessAddr+0xCB+11)));

	//DbgPrint("_imp_KfLowerIrql = %x",_imp_KfLowerIrql);

	SrcKeStackAttachProcessAddr=GetFunCtionAddr(L"KeStackAttachProcess");

	//DbgPrint("SrcKeStackAttachProcessAddr = %x",SrcKeStackAttachProcessAddr);

	KeStackAttachProcessCall_1=SearchFeature(SearchFeature(SearchFeature(SrcKeStackAttachProcessAddr,code,1)+1,code,1)+1,code,1);

	//DbgPrint("KeStackAttachProcessCall_1 = %x",KeStackAttachProcessCall_1);

	KeStackAttachProcessCall_2=SearchFeature(SearchFeature(SearchFeature(SearchFeature(SrcKeStackAttachProcessAddr,code,1)+1,code,1)+1,code,1)+1,code,1);

	//DbgPrint("KeStackAttachProcessCall_2 = %x",KeStackAttachProcessCall_2);

	SrcKeAttachProcessAddr=GetFunCtionAddr(L"KeAttachProcess");

	//DbgPrint("SrcKeAttachProcessAddr = %x",SrcKeAttachProcessAddr);

	KeAttachProcessCall_1=SearchFeature(SearchFeature(SrcKeAttachProcessAddr,code,1)+1,code,1);

	//DbgPrint("KeAttachProcessCall_1 = %x",KeAttachProcessCall_1);

	CallHook(KeStackAttachProcessCall_1,(int)MyKiAttachProcess);

	CallHook(KeStackAttachProcessCall_2,(int)MyKiAttachProcess);

	CallHook(KeAttachProcessCall_1,(int)MyKiAttachProcess);

}

void UnHookKiAttachProcess()

{

	CallHook(KeStackAttachProcessCall_1,SrcKiAttachProcessAddr);

	CallHook(KeStackAttachProcessCall_2,SrcKiAttachProcessAddr);

	CallHook(KeAttachProcessCall_1,SrcKiAttachProcessAddr);

}


工程在Win 7的VS2010编译环境测试通过,因为有硬编码,所以不适合Win XP,因为64位的系统的SSDT表不可写,所以不适合64位的系统。
Visual C/C++,汇编语言,驱动交流群:177822398、 177822108
附注:一直想找个合适的安全类编程开发测试的工作
下面贴上
driver.rar
DriverProtect.rar

上传的附件 driver.rar
DriverProtect.rar

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功