KeBugCheckExWINDOWS执行崩溃的函式,使计算机蓝屏,需要ring0级特权才能调用
基本介绍
- 外文名KeBugCheckEx
- 函式类型WINDOWS执行崩溃的函式
- 调用等级ring0级特权
- 返回类型VOID
简介
KeBugCheckEx是WINDOWS执行崩溃的函式
返回类型VOID
参数列表(DWORD, UINT, UINT, UINT, UINT)
该函式接受一个错误检查代码(bug check code),以及四个根据停止代码来解释的参数。KeBugCheckEx禁止了该系统处理器上的所有中断后,将显示器切换到低分辩率的VGA图形模式下,绘製一个蓝色背景,然后显示此停止代码,几乎WINDOWS支持的所有视频卡都实现了这种模式。
第一个错误检查代码是一个8位16进制数,后4个是整型数参数,将出现在死亡蓝屏中以帮助程式设计师了解错误细节。
此函式为KeBugCheck在WINNT以上的扩充版本。
计算程式
如果想使用此函式,必须申请RING0级特权,示例代码如下
#include<Windows.h>#include<Ntsecapi.h>#include<Aclapi.h>#pragmacomment(lib,"ntdll.lib") //CopyFromDDK#pragmacomment(lib,"Kernel32.lib")#pragmacomment(lib,"Advapi32.lib")//------------------数据类型声明开始--------------------//typedefstruct_SYSTEM_MODULE_INFORMATION{ ULONGReserved[2]; PVOIDBase; ULONGSize; ULONGFlags; USHORTIndex; USHORTUnknown; USHORTLoadCount; USHORTModuleNameOffset; CHARImageName[256];}SYSTEM_MODULE_INFORMATION,PSYSTEM_MODULE_INFORMATION;typedefstruct_OBJECT_ATTRIBUTES{ ULONGLength; HANDLERootDirectory; PUNICODE_STRINGObjectName; ULONGAttributes; PVOIDSecurityDescriptor; PVOIDSecurityQualityOfService;}OBJECT_ATTRIBUTES,POBJECT_ATTRIBUTES;typedefenum_SECTION_INHERIT{ ViewShare=1, ViewUnmap=2}SECTION_INHERIT;typedefstruct_MY_PROCESS_INFO{ ULONGPID; ULONGKPEB; ULONGCR3; CHARName[16]; ULONGReserved;}MY_PROCESS_INFO,PMY_PROCESS_INFO;typedeflongNTSTATUS;//------------------数据类型声明结束--------------------////---------------------预定义开始-----------------------//#defineNT_SUCCESS(Status)((NTSTATUS)(Status)>=0)#defineSTATUS_SUCCESS 0x00000000#defineSTATUS_UNSUCCESSFUL 0xC0000001#defineSTATUS_NOT_IMPLEMENTED 0xC0000002#defineSTATUS_INFO_LENGTH_MISMATCH0xC0000004#defineSTATUS_INVALID_PARAMETER 0xC000000D#defineSTATUS_ACCESS_DENIED 0xC0000022#defineSTATUS_BUFFER_TOO_SMALL 0xC0000023#defineOBJ_KERNEL_HANDLE 0x00000200#defineSystemModuleInformation 11#defineInitializeObjectAttributes(p,n,a,r,s){\ /注意,由于php标籤过滤,以下6行缺少续行符\/ (p)->Length=sizeof(OBJECT_ATTRIBUTES); (p)->RootDirectory=r; (p)->Attributes=a; (p)->ObjectName=n; (p)->SecurityDescriptor=s; (p)->SecurityQualityOfService=NULL; }//---------------------预定义结束-----------------------////------------------NativeAPI声明开始------------------//NTSYSAPIVOIDNTAPIRtlInitUnicodeString( PUNICODE_STRINGDestinationString, PCWSTRSourceString );NTSYSAPINTSTATUSNTAPIZwQuerySystemInformation( ULONGSystemInformationClass, PVOIDSystemInformation, ULONGSystemInformationLength, PULONGReturnLength );NTSYSAPINTSTATUSNTAPIZwOpenSection( OUTPHANDLESectionHandle, INACCESS_MASKDesiredAccess, INPOBJECT_ATTRIBUTESObjectAttributes );NTSYSAPINTSTATUSNTAPIZwMapViewOfSection( INHANDLESectionHandle, INHANDLEProcessHandle, INOUTPVOIDBaseAddress, INULONGZeroBits, INULONGCommitSize, INOUTPLARGE_INTEGERSectionOffsetOPTIONAL, INOUTPULONGViewSize, INSECTION_INHERITInheritDisposition, INULONGAllocationType, INULONGProtect );NTSYSAPINTSTATUSNTAPIZwUnmapViewOfSection( INHANDLEProcessHandle, INPVOIDBaseAddress );NTSYSAPINTSTATUSNTAPIZwClose( INHANDLEHandle );NTSYSAPINTSTATUSNTAPINtVdmControl( INULONGControlCode, INPVOIDControlData );//------------------NativeAPI声明结束------------------////------------------全局变数定义开始--------------------//NTSTATUS(NTAPIpfnNtVdmControl)( INULONGControlCode, INPVOIDControlData );BOOLEAN(NTAPIpfnPsGetVersion)( PULONGMajorVersionOPTIONAL, PULONGMinorVersionOPTIONAL, PULONGBuildNumberOPTIONAL, PUNICODE_STRINGCSDVersionOPTIONAL );HANDLE(NTAPIpfnPsGetCurrentProcessId)( );PVOID(NTAPIpfnMemcpy)( INVOIDUNALIGNEDDestination, INCONSTVOIDUNALIGNEDSource, INSIZE_TLength );ULONG(_cdeclpfnDbgPrint)( INPCHARFormat, ... );ULONGpPsInitialSystemProcess;//------------------全局变数定义结束--------------------////获取指定模组的基址PVOIDGetModuleBase(PCSTRname){ NTSTATUSstatus; PVOIDpBuffer,pModule; ULONGnRetSize,i,n; PSYSTEM_MODULE_INFORMATIONpmi; pBuffer=LocalAlloc(LPTR,0x1000); if(NULL==pBuffer) { printf("LocalAlloc[0]Failed:%d\n",GetLastError()); returnNULL; }0x1000,&nRetSize); if(STATUS_INFO_LENGTH_MISMATCH==status) { //缓冲区太小,重新分配 LocalFree(pBuffer); pBuffer=LocalAlloc(LPTR,nRetSize); if(NULL==pBuffer) { printf("LocalAlloc[1]Failed:%d\n",GetLastError()); returnNULL; } nRetSize,&nRetSize); } if(!NT_SUCCESS(status)) { printf("ZwQuerySystemInformationFailed:%d\n",LsaNtStatusToWinError(status)); LocalFree(pBuffer); returnNULL; } pmi=(PSYSTEM_MODULE_INFORMATION)((ULONG)pBuffer+4); n=(ULONG)pBuffer; pModule=NULL; //搜寻指定的模组名,获取基址 for(i=0;i<n;i++) { if(!_stricmp(pmi->ImageName+pmi->ModuleNameOffset,name)) { pModule=pmi->Base; break; } pmi++; } LocalFree(pBuffer); returnpModule;}//获取\Device\PhysicalMemory的可读写句柄HANDLEOpenPhysicalMemory(){ DWORDdwRet; NTSTATUSstatus; UNICODE_STRINGname; OBJECT_ATTRIBUTESoa; EXPLICIT_ACCESSea; PSECURITY_DESCRIPTORpSD; PACLpDacl=NULL; PACLpNewDacl=NULL; HANDLEhSection=NULL; HANDLEhSectionRet=NULL; RtlInitUnicodeString(&name,L"\\Device\\PhysicalMemory"); InitializeObjectAttributes(&oa,&name,OBJ_KERNEL_HANDLE,NULL,NULL); //以可读写Section许可权打开PhysicalMemory status=ZwOpenSection(&hSectionRet,SECTION_MAP_READ|SECTION_MAP_WRITE,&oa); if(NT_SUCCESS(status))gotoFreeAndExit;//打开成功,直接返回 if(status!=STATUS_ACCESS_DENIED) { //错误,但非许可权不足,打开失败 printf("ZwOpenSection[0]Failed:%d\n",LsaNtStatusToWinError(status)); hSectionRet=NULL; gotoFreeAndExit; }//以可读写ACL许可权打开PhysicalMemory status=ZwOpenSection(&hSection,READ_CONTROL|WRITE_DAC,&oa); if(!NT_SUCCESS(status)) { printf("ZwOpenSection[1]Failed:%d\n",LsaNtStatusToWinError(status)); gotoFreeAndExit; } //获取PhysicalMemory的DACL dwRet=GetSecurityInfo(hSection NULL,NULL,&pDacl,NULL,&pSD); if(dwRet!=ERROR_SUCCESS) { printf("GetSecurityInfoFailed:%d\n",dwRet); gotoFreeAndExit; } //创建一个ACE,允许当前用户读写PhysicalMemory ZeroMemory(&ea,sizeof(EXPLICIT_ACCESS)); ea.grfAccessPermissions=SECTION_MAP_READ|SECTION_MAP_WRITE; ea.grfAccessMode=GRANT_ACCESS; ea.grfInheritance=NO_INHERITANCE; ea.Trustee.TrusteeForm=TRUSTEE_IS_NAME; ea.Trustee.TrusteeType=TRUSTEE_IS_USER; ea.Trustee.ptstrName="CURRENT_USER"; //将新的ACE加入DACL dwRet=SetEntriesInAcl(1,&ea,pDacl,&pNewDacl); if(dwRet!=ERROR_SUCCESS) { printf("SetEntriesInAclFailed:%d\n",dwRet); gotoFreeAndExit; } //更新PhysicalMemory的DACL dwRet=SetSecurityInfo(hSection, NULL,NULL,pNewDacl,NULL); if(dwRet!=ERROR_SUCCESS) { printf("SetSecurityInfoFailed:%d\n",dwRet); gotoFreeAndExit; } //以可读写许可权打开PhysicalMemory status=ZwOpenSection(&hSectionRet,SECTION_MAP_READ|SECTION_MAP_WRITE,&oa); if(!NT_SUCCESS(status)) { printf("ZwOpenSection[2]Failed:%d\n",LsaNtStatusToWinError(status)); gotoFreeAndExit; }FreeAndExit: if(pSD)LocalFree(pSD); if(pNewDacl)LocalFree(pNewDacl); if(hSection)ZwClose(hSection); returnhSectionRet;}//将物理记忆体映射到当前进程的用户空间PVOIDMapPhysicalMemory(HANDLEhSection,//物理记忆体的Section句柄 ULONGOffset, //映射起始偏移量,相对于物理记忆体的0地址 ULONGCommitSize//映射範围 ){ NTSTATUSstatus; PVOIDBaseAddress=NULL; LARGE_INTEGERPhysicalAddress={Offset,0}; SIZE_TViewSize=CommitSize; status=ZwMapViewOfSection(hSection,(HANDLE)-1,&BaseAddress,0, CommitSize,&PhysicalAddress,&ViewSize,ViewShare,0,PAGE_READWRITE); if(!NT_SUCCESS(status)) { printf("ZwMapViewOfSectionFailed:%d\n",LsaNtStatusToWinError(status)); returnNULL; } returnBaseAddress;}//在Ring0执行的代码。这里演示如何获取每个进程的PID、KPEB、CR3和ImageNameNTSTATUSRing0Code(ULONGsize, //缓冲区大小 PULONGbuffer) //缓冲区指针,指向调用者分配的快取 //参数个数与NtVdmControl一致,以平衡堆叠{ ULONGBuildNumber; ULONGListOffset; ULONGPIDOffset; ULONGNameOffset; PLIST_ENTRYListHead,ListPtr; PMY_PROCESS_INFOmypi; pfnDbgPrint("RuninRing0!\n");//输出调试信息 pfnPsGetVersion(NULL,NULL,&BuildNumber,NULL); pfnDbgPrint("BuildNumber=%d\n",BuildNumber); switch(BuildNumber) //各版本OS的KPEB结构不同 { case2195: //Win2000 ListOffset=0xa0; PIDOffset=0x9c; NameOffset=0x1fc; break; case2600: //WinXP ListOffset=0x88; PIDOffset=0x84; NameOffset=0x174; break; case3790: //Win2003 ListOffset=0x88; PIDOffset=0x84; NameOffset=0x154; break; default: returnSTATUS_NOT_IMPLEMENTED; } if(size<4)returnSTATUS_BUFFER_TOO_SMALL; size-=4; if(NULL==buffer)returnSTATUS_INVALID_PARAMETER; buffer=0L; //快取的第一个ULONG用于保存进程总数 mypi=(PMY_PROCESS_INFO)(buffer+1); //历遍ActiveProcessLinks ListHead=ListPtr=(PLIST_ENTRY)(pPsInitialSystemProcess+ListOffset); while(ListPtr->Flink!=ListHead) { if(size<sizeof(MY_PROCESS_INFO))returnSTATUS_BUFFER_TOO_SMALL; mypi->KPEB=(ULONG)ListPtr-ListOffset; mypi->PID=(ULONG)(mypi->KPEB+PIDOffset); mypi->CR3=(ULONG)(mypi->KPEB+0x18); pfnMemcpy(mypi->Name,(PVOID)(mypi->KPEB+NameOffset),16); (buffer)++; mypi++; size-=sizeof(MY_PROCESS_INFO); ListPtr=ListPtr->Flink; } returnSTATUS_SUCCESS;}//显示进程信息voidListProcessInfo(PULONGbuffer){ ULONGi,n=buffer; PMY_PROCESS_INFOmypi=(PMY_PROCESS_INFO)(buffer+1); printf("PID KPEB CR3 Name\n" "---- -------- -------- ----\n"); for(i=0;i<n;i++) { printf("%-4d %08x %08x %s\n", mypi->PID,mypi->KPEB,mypi->CR3,mypi->Name); mypi++; }}voidmain(){ charKernel="ntoskrnl.exe"; PVOIDpKernel=NULL; HMODULEhKernel=NULL; HANDLEhSection=NULL; charmapping=NULL; PVOIDbuffer=NULL; ULONGoffset; NTSTATUSstatus; charOrigCode[24],HookCode[24]= "\xE8\xFF\xFF\xFF\xFF" //call0xffffffff ;nt!PsGetCurrentProcessId "\x3D\xEE\xEE\xEE\xEE" //cmpeax,0xeeeeeeee ;自己的PID "\x75\x05" //jne$Content$5 "\xE9\xDD\xDD\xDD\xDD" //jmp0xdddddddd ;Ring0Code "\xB8\x01\x00\x00\xC0" //moveax,0xc0000001 ;STATUS_UNSUCCESSFUL "\xC3"; //ret printf("\n-=<RunRing0CodeWithoutDriverDemo>=-\n\n"); //获取系统核心模组ntoskrnl.exe的基址 pKernel=GetModuleBase(Kernel); if(NULL==pKernel)return; if((ULONG)pKernel<0x80000000||(ULONG)pKernel>0x9FFFFFFF) { //模组基址超出直接记忆体映射範围 printf("Error:Kernelmodulebase(%08x)isoutofrange.\n",pKernel); return; } //在用户态载入一份ntoskrnl.exe hKernel=LoadLibrary(Kernel); if(NULL==hKernel) { printf("LoadLibraryFailed:%d\n",GetLastError()); return; } //获取核心例程/变数在用户态的相对位置 if((pfnMemcpy=(PVOID)GetProcAddress(hKernel,"memcpy"))&& (pfnDbgPrint=(PVOID)GetProcAddress(hKernel,"DbgPrint"))&& (pfnNtVdmControl=(PVOID)GetProcAddress(hKernel,"NtVdmControl"))&& (pfnPsGetVersion=(PVOID)GetProcAddress(hKernel,"PsGetVersion"))&& (pfnPsGetCurrentProcessId=(PVOID)GetProcAddress(hKernel,"PsGetCurrentProcessId"))&& (pPsInitialSystemProcess=(PVOID)GetProcAddress(hKernel,"PsInitialSystemProcess"))); else { printf("GetProcAddressFailed:%d\n",GetLastError()); gotoFreeAndExit; } //计算核心例程/变数的实际地址 offset=(ULONG)pKernel-(ULONG)hKernel; (ULONG)pfnMemcpy+=offset; (ULONG)pfnDbgPrint+=offset; (ULONG)pfnNtVdmControl+=offset; (ULONG)pfnPsGetVersion+=offset; (ULONG)pfnPsGetCurrentProcessId+=offset; (ULONG)pPsInitialSystemProcess+=offset; //设定HookCode (ULONG)(HookCode+1)=(ULONG)pfnPsGetCurrentProcessId-(ULONG)pfnNtVdmControl-5; (ULONG)(HookCode+6)=GetCurrentProcessId(); (ULONG)(HookCode+13)=(ULONG)Ring0Code-(ULONG)pfnNtVdmControl-17; //打开物理记忆体Section hSection=OpenPhysicalMemory(); if(NULL==hSection)gotoFreeAndExit; //映射NtVdmControl入口附近的记忆体 offset=(ULONG)pfnNtVdmControl&0x1FFFF000; //转换到物理记忆体页地址 mapping=MapPhysicalMemory(hSection,offset,0x2000); if(NULL==mapping)gotoFreeAndExit; //保存NtVdmControl入口代码 offset=(ULONG)pfnNtVdmControl&0x00000FFF; //页内偏移 memcpy(OrigCode,mapping+offset,24); buffer=LocalAlloc(LPTR,0x1000); if(NULL==buffer) { printf("LocalAllocFailed:%d\n",GetLastError()); gotoFreeAndExit; } memcpy(mapping+offset,HookCode,24); //挂鈎NtVdmControl status=NtVdmControl(0x1000,buffer); //调用NtVdmControl,进入Ring0 memcpy(mapping+offset,OrigCode,24); //还原NtVdmControl入口 if(!NT_SUCCESS(status)) { printf("NtVdmControlFailed:%d\n",LsaNtStatusToWinError(status)); gotoFreeAndExit; } ListProcessInfo(buffer);FreeAndExit: if(buffer!=NULL)LocalFree(buffer); if(mapping!=NULL)ZwUnmapViewOfSection(hSection,mapping); if(hSection!=NULL)ZwClose(hSection); if(hKernel!=NULL)FreeLibrary(hKernel);}