好友
阅读权限20
听众
最后登录1970-1-1
|
绿林科技
发表于 2013-7-20 23:38
本帖最后由 绿林科技 于 2013-7-20 23:44 编辑
时间:2013年7月21日星期日
作者:绿林科技
本次主要绕过了一下函数
HookNtOpenProcess();
HookNtReadVirtualMemory();
HookNtWriteVirtualMemory();
HookNtClose();
HookNtProtectVirtualMemory();
HookPsSuspendThread();
HookNtGetContextThread();
HookNtQueryPerformanceCounter();
HookNtSetContextThread();
HookKiAttachProcess();
HookNtDeviceIoControlFile();
大家调试的时候都可以知道,盛*大游戏(泡泡堂)的外壳是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()
{
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;
SC_HANDLE hServiceDDK=NULL;
hServiceMgr = ::OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if( hServiceMgr == NULL )
{
m_DriverINFORMATION.SetWindowTextW(L"打开服务失败!");
bRet = FALSE;
goto BeforeLeave;
}
else
{
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,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL );
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;
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;
ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
ULONG info = 0;
switch (code)
{
case IOCTL_TEST1:
{
KdPrint(("IOCTL_TEST1\n"));
GameProcessID = (int)cbin;
HookNtOpenProcess();
HookNtReadVirtualMemory();
HookNtWriteVirtualMemory();
HookNtClose();
HookNtProtectVirtualMemory();
HookPsSuspendThread();
HookNtGetContextThread();
HookNtQueryPerformanceCounter();
HookNtSetContextThread();
HookKiAttachProcess();
HookNtDeviceIoControlFile();
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位的系统。
下面贴上附件:
driver.rar
(50 KB, 下载次数: 70)
DriverProtect.rar
(134.36 KB, 下载次数: 63)
|
|