首页
社区
课程
招聘
[求助]保护进程蓝掉了。。
发表于: 2010-11-30 23:10 5457

[求助]保护进程蓝掉了。。

2010-11-30 23:10
5457
#include <ntddk.h>
#include "struct.h"

//int pos_CreateFile;     /* 保存这些函数的服务号 */
int pos_ReadVirtualMemory;
int pos_NtOpenProcess;
int pos_NtWriteVirtualMemory;

UNICODE_STRING uProcessName;
UNICODE_STRING MyuProcessName;
ANSI_STRING aProcessName;

//特殊的值,目标进程的ID
DWORD	dwTargetProcessID;//初始化

#define MY_CONTROL_CODE   0x4021
#define IOCTL_SET_TARGET_PROCESS_ID   (ULONG)CTL_CODE( FILE_DEVICE_UNKNOWN, MY_CONTROL_CODE, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA )

//一些常量定义
#define EPROCESS_SIZE           1  
#define PEB_OFFSET              2  
#define FILE_NAME_OFFSET        3  
#define PROCESS_LINK_OFFSET     4  
#define PROCESS_ID_OFFSET       5  
#define EXIT_TIME_OFFSET        6  
 
DWORD GetPlantformDependentInfo ( DWORD dwFlag )   
{    
	DWORD current_build;    
	DWORD ans = 0;
	
	PsGetVersion(NULL, NULL,¤t_build, NULL);    
	switch ( dwFlag )   
	{    
	case EPROCESS_SIZE:    
		if (current_build == 2195) ans = 0 ;        // 2000,当前不支持2000,下同   
		if (current_build == 2600) ans = 0x25C;     // xp   
		if (current_build == 3790) ans = 0x270;     // 2003   
		break;    
	case PEB_OFFSET:    
		if (current_build == 2195)  ans = 0;    
		if (current_build == 2600)  ans = 0x1b0;    
		if (current_build == 3790)  ans = 0x1a0;   
		break;    
	case FILE_NAME_OFFSET:    
		if (current_build == 2195)  ans = 0;    
		if (current_build == 2600)  ans = 0x174;    
		if (current_build == 3790)  ans = 0x164;   
		break;    
	case PROCESS_LINK_OFFSET:    
		if (current_build == 2195)  ans = 0;    
		if (current_build == 2600)  ans = 0x088;    
		if (current_build == 3790)  ans = 0x098;   
		break;    
	case PROCESS_ID_OFFSET:    
		if (current_build == 2195)  ans = 0;    
		if (current_build == 2600)  ans = 0x084;    
		if (current_build == 3790)  ans = 0x094;   
		break;    
	case EXIT_TIME_OFFSET:    
		if (current_build == 2195)  ans = 0;    
		if (current_build == 2600)  ans = 0x078;    
		if (current_build == 3790)  ans = 0x088;   
		break;    
	}    
	return ans;    
}  


CHAR *TerminateName = "demo.exe";      //这里就是我们的进程名   
UCHAR *PsGetProcessImageFileName( IN PEPROCESS Process );   
  
BOOLEAN IsProtect(CHAR *temp)            //判断正在结束的进程是否是我们要保护的进程   
{   
    ULONG len = strcmp(TerminateName, temp);   
    if(!len)   
        return TRUE;   
    return FALSE;   
} 


NTSTATUS NewNtOpenProcess(PHANDLE  ProcessHandle,
						  ACCESS_MASK  DesiredAccess,
						  POBJECT_ATTRIBUTES  ObjectAttributes,
						  PCLIENT_ID  ClientId)
{
	NTSTATUS ntStatus;
	DWORD dwProcessId = NULL;
        CHAR *pName;        //接受进程的进程名
    
    ntStatus = ((ZWCREATEFILE)(OldNtOpenProcess))(
		ProcessHandle,
		DesiredAccess,
		ObjectAttributes,
		ClientId);

      pName = (CHAR*)PsGetProcessImageFileName(process); 
      
	if((ClientId != NULL))
	{
		dwProcessId = (HANDLE)ClientId->UniqueProcess;
                
               
       if(IsProtect(pName)) //判断是否是我们要保护的进程,是则返回权限不足,否则调用原函数结束进程   
           {   
          if(process != PsGetCurrentProcess())   
               {   
                
			dwTargetProcessID=(DWORD)PsGetCurrentProcessId();//获得进程id
			 
               }   
           } 
		if (dwProcessId == dwTargetProcessID)//一
		{
			ntStatus = STATUS_ACCESS_DENIED;
		}

	}
	return ntStatus;
}

NTSTATUS
NewNtWriteVirtualMemory(IN HANDLE ProcessHandle,
								 IN PVOID BaseAddress,
								 IN PVOID Buffer,
								 IN ULONG BufferLength,
								 OUT PULONG ReturnLength OPTIONAL)
{
	NTSTATUS ntStatus;
	NTSTATUS	ret;
	PVOID		pEprocess;
	DWORD		dwProcessId;
        CHAR *pName;        //接受进程的进程名

	ntStatus = ((NTWRITEVIRTUALMEMORY)(OldNtWriteVitualMemory)) (
		ProcessHandle,
		BaseAddress,
		Buffer,
		BufferLength,
        ReturnLength);

	pEprocess = NULL;
	dwProcessId = GetPlantformDependentInfo(PROCESS_ID_OFFSET); 
	ret = ObReferenceObjectByHandle(ProcessHandle , 0, NULL, KernelMode, &pEprocess, NULL);
	if(STATUS_SUCCESS == ret)
	{
		dwProcessId = *(DWORD*)((BYTE*)pEprocess+dwProcessId); //被扫描进程的PID

           if(IsProtect(pName)) //判断是否是我们要保护的进程,是则返回权限不足,否则调用原函数结束进程   
           {   
               if(process != PsGetCurrentProcess())   
                {   
                 
			dwTargetProcessID=(DWORD)PsGetCurrentProcessId();//获得进程id
			 
               }   
           } 




		if (dwProcessId == dwTargetProcessID)//二
		{
			if(dwTargetProcessID == (DWORD)PsGetCurrentProcessId()) 
			{
				goto Next;
			}
			return STATUS_ACCESS_DENIED;
		}
	}

Next:
	return ntStatus;
}

NTSTATUS
NewNtReadVirtualMemory(
					  IN HANDLE ProcessHandle,
					  IN PVOID BaseAddress,
					  OUT PVOID Buffer,
					  IN ULONG BufferLength,
					  OUT PULONG ReturnLength OPTIONAL
					  )
{
	NTSTATUS	ret;
	PVOID		pEprocess;   //通过进程句柄得到ID
	PVOID		pExplorer_Eprocess;  //过滤掉桌面进程explorer时用到的一个EPROCESS类型临时变量
	DWORD		dwCurrentPID;  //当前ProcessHandle句柄对应的进程号

	DWORD dwProcessId;
	DWORD dwFileName;
	CHAR *pName;        //接受进程的进程名
	pEprocess = NULL;

	dwProcessId = GetPlantformDependentInfo(PROCESS_ID_OFFSET);    
    dwFileName  = GetPlantformDependentInfo(FILE_NAME_OFFSET);

	ret = ObReferenceObjectByHandle(ProcessHandle , 0, NULL, KernelMode, &pEprocess, NULL);
	if(STATUS_SUCCESS == ret)
	{
		//DbgPrint("the caller ProcessName is %s\n",(PUCHAR)((BYTE*)pEprocess + dwFileName));
		dwCurrentPID = *(DWORD*)((BYTE*)pEprocess+dwProcessId);         //得到被扫描的进程的PID

                 if(IsProtect(pName)) //判断是否是我们要保护的进程,是则返回权限不足,否则调用原函数结束进程   
           {   
               if(process != PsGetCurrentProcess())   
                {   
                 
			dwTargetProcessID=(DWORD)PsGetCurrentProcessId();//获得进程id
			 
               }   
           } 



		if(dwCurrentPID == dwTargetProcessID)   //dwTargetProcessID                 //如果被扫描的进程PID跟预定的一样,那么就开始bypass//3333333333
		{	
			DbgPrint("call NtReadVirtualMemory!Target Process is %d.  The Caller is %d\n",dwTargetProcessID, PsGetCurrentProcessId());

			if(dwTargetProcessID == (DWORD)PsGetCurrentProcessId())  //排除自己调用NtReadVirtualMemory来读取自己内存的情况
			{
				DbgPrint("call NtReadVirtualMemory by myself\n");
				goto Next;
			}
				pExplorer_Eprocess = PsGetCurrentProcess();	//得到当前进程eprocess结构

				RtlInitUnicodeString(&uProcessName,L"explorer.exe");
				RtlInitAnsiString(&aProcessName,(PUCHAR)((BYTE*)pExplorer_Eprocess + dwFileName));
				RtlAnsiStringToUnicodeString(&MyuProcessName,&aProcessName,TRUE);
				DbgPrint("call NtReadVirtualMemory by %wZ ---%wZ\n",&MyuProcessName,&uProcessName);

				if(RtlCompareUnicodeString(&uProcessName,&MyuProcessName, TRUE) == 0)  //不区分大小写的对比!
				{
					DbgPrint("call NtReadVirtualMemory by explorer process\n"); //排除explorer调用NtReadVirtualMemory来读取自己内存的情况
					goto Next;
				}
				DbgPrint("call NtReadVirtualMemory by other process %d\n",PsGetCurrentProcessId());
				//排除了自己对自己的内存操作,桌面进程对所关心的进程的操作之外,其他的一切进程对多关心的进程进行操作,一律pass
				ret = ((NTREADVIRTUALMEMORY)(OldNtReadVirtualMemory))(
					ProcessHandle,
					BaseAddress,
					L"Is By PopSky",      //自定义的垃圾数据
					BufferLength,
					ReturnLength
					);
				return ret;
		}
	}
Next:
	ret = ((NTREADVIRTUALMEMORY)(OldNtReadVirtualMemory))(
		ProcessHandle,
		BaseAddress,
		Buffer,
		BufferLength,
		ReturnLength
		);
	return ret;
}
/////////////////////////////////////////////////////////////////         --          --     
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//     --     -      -     -- 
//+                                                           +//     --      -   -       -- 
//+          下面2个函数用于得到部分SDT函数的地址             +//      --       -        --  
//+                                                           +//       -     sudami     -   
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//        --            --    
/////////////////////////////////////////////////////////////////          --        --  
//                                                                           --    --
//		                                                                        --
DWORD GetDllFunctionAddress (
					   char* lpFunctionName, 
					   PUNICODE_STRING pDllName
					   )
{
	HANDLE hThread, hSection, hFile, hMod;
	SECTION_IMAGE_INFORMATION sii;
	IMAGE_DOS_HEADER* dosheader;
	IMAGE_OPTIONAL_HEADER* opthdr;
	IMAGE_EXPORT_DIRECTORY* pExportTable;
	DWORD* arrayOfFunctionAddresses;
	DWORD* arrayOfFunctionNames;
	WORD* arrayOfFunctionOrdinals;
	DWORD functionOrdinal;
	DWORD Base, x, functionAddress;
	char* functionName;
	STRING ntFunctionName, ntFunctionNameSearch;
	PVOID BaseAddress = NULL;
	SIZE_T size=0;

	OBJECT_ATTRIBUTES oa = {sizeof oa, 0, pDllName, OBJ_CASE_INSENSITIVE};

	IO_STATUS_BLOCK iosb;

	//_asm int 3;
	ZwOpenFile(&hFile, FILE_EXECUTE | SYNCHRONIZE, &oa, &iosb, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT);

	oa.ObjectName = 0;

	ZwCreateSection(&hSection, SECTION_ALL_ACCESS, &oa, 0,PAGE_EXECUTE, SEC_IMAGE, hFile);

	ZwMapViewOfSection(hSection, NtCurrentProcess(), &BaseAddress, 0, 1000, 0, &size, (SECTION_INHERIT)1, MEM_TOP_DOWN, PAGE_READWRITE);

	ZwClose(hFile);

	hMod = BaseAddress;

	dosheader = (IMAGE_DOS_HEADER *)hMod;

	opthdr =(IMAGE_OPTIONAL_HEADER *) ((BYTE*)hMod+dosheader->e_lfanew+24);

	pExportTable =(IMAGE_EXPORT_DIRECTORY*)((BYTE*) hMod + opthdr->DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT]. VirtualAddress);

	arrayOfFunctionAddresses = (DWORD*)( (BYTE*)hMod + pExportTable->AddressOfFunctions);

	arrayOfFunctionNames = (DWORD*)( (BYTE*)hMod + pExportTable->AddressOfNames);

	arrayOfFunctionOrdinals = (WORD*)( (BYTE*)hMod + pExportTable->AddressOfNameOrdinals);

	Base = pExportTable->Base;

	RtlInitString(&ntFunctionNameSearch, lpFunctionName);

	for(x = 0; x < pExportTable->NumberOfFunctions; x++) {
		functionName = (char*)( (BYTE*)hMod + arrayOfFunctionNames[x]);

		RtlInitString(&ntFunctionName, functionName);

		functionOrdinal = arrayOfFunctionOrdinals[x] + Base - 1; 
		functionAddress = (DWORD)( (BYTE*)hMod + arrayOfFunctionAddresses[functionOrdinal]);
		if (RtlCompareString(&ntFunctionName, &ntFunctionNameSearch, TRUE) == 0) {
			ZwClose(hSection);
			return functionAddress;
		}
	}

	ZwClose(hSection);
	return 0;
}

VOID IoTimeRoutine(
				   IN PDEVICE_OBJECT DeviceObject,
				   IN PVOID Context )
{
	int cnt = 0;
	DbgPrint("IoTimerRoutine() is Called!\n");
}


NTSTATUS
DispatchCreate(
	IN PDEVICE_OBJECT		DeviceObject,
	IN PIRP					Irp
	)
{
	NTSTATUS status = STATUS_SUCCESS;

    Irp->IoStatus.Information = 0;

	//dprintf("[KsBinSword] IRP_MJ_CREATE\n");

    Irp->IoStatus.Status = status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return status;
}

NTSTATUS
DispatchClose(
	IN PDEVICE_OBJECT		DeviceObject,
	IN PIRP					Irp
	)
{
	NTSTATUS status = STATUS_SUCCESS;
    //DbgBreakPoint();
    Irp->IoStatus.Information = 0;

	//dprintf("[KsBinSword] IRP_MJ_CLOSE\n");

    Irp->IoStatus.Status = status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return status;
}

NTSTATUS
DispatchDeviceControl(
	IN PDEVICE_OBJECT		DeviceObject,
	IN PIRP					Irp
	)
{
	NTSTATUS                    status = STATUS_SUCCESS;
	ULONG						controlCode;
	PIO_STACK_LOCATION			irpStack;
	HANDLE						hEvent;
	OBJECT_HANDLE_INFORMATION	objHandleInfo;
	ULONG                       outputLength, inputLength;
	PVOID                       inputBuffer;
	
	irpStack = IoGetCurrentIrpStackLocation(Irp);
	outputLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
	inputLength=irpStack->Parameters.DeviceIoControl.InputBufferLength;
	controlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
	switch(controlCode)
	{
	case IO_PROTECT:
		//dwTargetProcessID = (HANDLE)irpStack->Parameters.DeviceIoControl.Type3InputBuffer;
		break;
	default:
		break;
	}
	
	Irp->IoStatus.Status = STATUS_SUCCESS;
	Irp->IoStatus.Information = 0;
	IoCompleteRequest(Irp, IO_NO_INCREMENT);
	
	return status;
}
// 驱动入口
NTSTATUS DriverEntry( IN PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath )
{
	NTSTATUS ntStatus = STATUS_SUCCESS;
    PDEVICE_OBJECT Device;
    UNICODE_STRING DeviceName, DeviceLink;  //设备名,符号链接名

    DbgPrint("[MyDriver] DriverEntry\n");

    RtlInitUnicodeString(&DeviceName, L"\\Device\\MyDriver");         //初始化设备名
    RtlInitUnicodeString(&DeviceLink, L"\\DosDevices\\MyDriver");  //初始化符号链接名

    /* IoCreateDevice 生成设备对象 */
    ntStatus = IoCreateDevice(DriverObject,         //生成设备的驱动对象
                              0,                    //设备扩展区内存大小
                              &DeviceName,          //设备名,\Device\MyDriver
                              FILE_DEVICE_UNKNOWN,  //设备类型
                              0,                    //填写0即可
                              FALSE,                //必须为FALSE
                              &Device);             //设备对象指针返回到DeviceObject中
    if (!NT_SUCCESS(ntStatus))
    {
        DbgPrint("[MyDriver] IoCreateDevice FALSE: %.8X\n", ntStatus);
        return ntStatus;  //生成失败就返回
    }
    else
        DbgPrint("[MyDriver] IoCreateDevice SUCCESS\n");

    /* IoCreateSymbolicLink 生成符号链接 */
    ntStatus = IoCreateSymbolicLink(&DeviceLink, &DeviceName);
    if (!NT_SUCCESS(ntStatus))
    {
        DbgPrint("[MyDriver] IoCreateSymbolicLink FALSE: %.8X\n", ntStatus);
        IoDeleteDevice(Device);  //删除设备
        return ntStatus;
    }
    else
        DbgPrint("[MyDriver] IoCreateSymbolicLink SUCCESS\n");

    Device->Flags &= ~DO_DEVICE_INITIALIZING;  //设备初始化完成标记

    DriverObject->MajorFunction[IRP_MJ_CREATE]         = DispatchCreate;
    DriverObject->MajorFunction[IRP_MJ_CLOSE]          = DispatchClose;
    DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
    DriverObject->DriverUnload                         = OnUnload;

	Hook();    //SSDT hook
    return ntStatus;
}
// 驱动卸载
VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
{
	UNICODE_STRING dosDeviceName;

	Unhook();

    RtlInitUnicodeString(&dosDeviceName, L"\\DosDevices\\MyDriver");

    IoDeleteSymbolicLink(&dosDeviceName);

	if (DriverObject->DeviceObject != NULL)
    {
        IoDeleteDevice(DriverObject->DeviceObject);  //删除设备
    }
}

//   此处修改SSDT中的NtCreateFile服务地址
VOID Hook()
{
	UNICODE_STRING dllName;
	DWORD          functionAddress;
	DWORD		   NtOpenProcessAddress;
	DWORD		   NtWriteVirtualMemoryAddress;
	int            position;
	int			   NtOpenProcessposition;
	int			   NtWriteVirtualMemoryposinion;
	PDEVICE_OBJECT pDeviceObject = NULL;

	RtlInitUnicodeString( &dllName, L"\\Device\\HarddiskVolume1\\Windows\\System32\\ntdll.dll" );

	//获取NtReadVirtualMemory的服务号完毕!
	functionAddress					 = GetDllFunctionAddress("NtReadVirtualMemory", &dllName);
	NtOpenProcessAddress			 = GetDllFunctionAddress("NtOpenProcess", &dllName);
	NtWriteVirtualMemoryAddress		 = GetDllFunctionAddress("NtWriteVirtualMemory", &dllName);
	position						 = *((WORD*)( functionAddress + 1 ));
	NtOpenProcessposition			 = *((WORD*)( NtOpenProcessAddress + 1 ));
	NtWriteVirtualMemoryposinion	 = *((WORD*)( NtWriteVirtualMemoryAddress + 1 ));
	pos_ReadVirtualMemory			 = position;
	pos_NtOpenProcess				 = NtOpenProcessposition;
	pos_NtWriteVirtualMemory		 = NtWriteVirtualMemoryposinion;
	//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

	OldNtReadVirtualMemory = (NTREADVIRTUALMEMORY) (*(((PServiceDescriptorTableEntry)KeServiceDescriptorTable)->ServiceTableBase + pos_ReadVirtualMemory));  //得到NtReadVirtualMemory函数的原始

地址
	OldNtOpenProcess	   = (ZWCREATEFILE) (*(((PServiceDescriptorTableEntry)KeServiceDescriptorTable)->ServiceTableBase + pos_NtOpenProcess));
	OldNtWriteVitualMemory = (NTWRITEVIRTUALMEMORY) (*(((PServiceDescriptorTableEntry)KeServiceDescriptorTable)->ServiceTableBase + pos_NtWriteVirtualMemory));
	DbgPrint( "Address of Real OldNtReadVirtualMemory: 0x%08X\n", OldNtReadVirtualMemory );
	// 去掉内存保护
	__asm
	{
		cli
			mov     eax, cr0
			and     eax, not 10000h
			mov     cr0, eax
	}

	(NTREADVIRTUALMEMORY) (*(((PServiceDescriptorTableEntry)KeServiceDescriptorTable)->ServiceTableBase + pos_ReadVirtualMemory)) = NewNtReadVirtualMemory;
	(ZWCREATEFILE) (*(((PServiceDescriptorTableEntry)KeServiceDescriptorTable)->ServiceTableBase + pos_NtOpenProcess)) = NewNtOpenProcess;//SSDT HOOK NtReadVirtualMemory
	(NTWRITEVIRTUALMEMORY) (*(((PServiceDescriptorTableEntry)KeServiceDescriptorTable)->ServiceTableBase + pos_NtWriteVirtualMemory)) = NewNtWriteVirtualMemory;
	DbgPrint(" Address of NewNtReadVirtualMemory: 0x%08X\n", NewNtReadVirtualMemory );

	// 恢复内存保护
	__asm
	{
		mov     eax, cr0
			or     eax, 10000h
			mov     cr0, eax
			sti
	}
}

//////////////////////////////////////////////////////
VOID Unhook()
{
	__asm
	{
		cli
			mov     eax, cr0
			and     eax, not 10000h
			mov     cr0, eax
	}

	// 还原SSDT
	(NTREADVIRTUALMEMORY) (*(((PServiceDescriptorTableEntry)KeServiceDescriptorTable)->ServiceTableBase + pos_ReadVirtualMemory)) = OldNtReadVirtualMemory;
	(ZWCREATEFILE) (*(((PServiceDescriptorTableEntry)KeServiceDescriptorTable)->ServiceTableBase + pos_NtOpenProcess)) = OldNtOpenProcess;
	(NTWRITEVIRTUALMEMORY) (*(((PServiceDescriptorTableEntry)KeServiceDescriptorTable)->ServiceTableBase + pos_NtWriteVirtualMemory)) = OldNtWriteVitualMemory;
	__asm
	{
		mov     eax, cr0
			or     eax, 10000h
			mov     cr0, eax
			sti
	}
	DbgPrint("Unhook");
}


编译是通过的
但是加载就蓝屏了。。。

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 68
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
你调试下 不就知道蓝屏蓝在哪句上了么。。
2010-12-1 11:46
0
雪    币: 6092
活跃值: (654)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
3
我还是没找到原因
不过代码框架换了
现在的代码跟exe通讯
不需要这么麻烦了
2010-12-1 13:14
0
雪    币: 170
活跃值: (90)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
4
不想看代码
2010-12-1 14:29
0
雪    币: 596
活跃值: (449)
能力值: ( LV12,RANK:320 )
在线值:
发帖
回帖
粉丝
5
看到了sudami
2010-12-1 14:30
0
雪    币: 6092
活跃值: (654)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
6
帮我看下错误吧 谢谢了
http://bbs.pediy.com/showthread.php?p=898258#post898258
2010-12-3 17:43
0
游客
登录 | 注册 方可回帖
返回
//