真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

如何解析Windows內(nèi)核擴(kuò)展機(jī)制

如何解析Windows內(nèi)核擴(kuò)展機(jī)制,很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

創(chuàng)新互聯(lián)專注于榮成企業(yè)網(wǎng)站建設(shè),成都響應(yīng)式網(wǎng)站建設(shè),商城網(wǎng)站開發(fā)。榮成網(wǎng)站建設(shè)公司,為榮成等地區(qū)提供建站服務(wù)。全流程按需求定制開發(fā),專業(yè)設(shè)計,全程項目跟蹤,創(chuàng)新互聯(lián)專業(yè)和態(tài)度為您提供的服務(wù)

近期,我自己寫了一個內(nèi)核模式驅(qū)動器,跟我平時寫的很多代碼一樣,這個驅(qū)動器也存在Bug。 確切來說,這個驅(qū)動器可以防止其他驅(qū)動器正常加載,并導(dǎo)致系統(tǒng)崩潰。

實際上,很多啟動器會默認(rèn)它們的初始化進(jìn)程(DriverEntry)能夠成功執(zhí)行,因此在出現(xiàn)問題時它們是無法正確處理的。j00ru曾在幾年前發(fā)布的博文中提過幾種案例,而且其中有很多都跟目前的Windows版本有關(guān),而我只對其中的一個驅(qū)動器比較感興趣。這里最吸引我的還是“Windows內(nèi)核主機(jī)擴(kuò)展機(jī)制”。

這個驅(qū)動器是Bam.sys(Background Activity Moderator)- Windows 10 v1709(RS3)中新引入的一種驅(qū)動器。當(dāng)它的DriverEntry中途出現(xiàn)問題時,調(diào)用棧會導(dǎo)致系統(tǒng)發(fā)生崩潰:

如何解析Windows內(nèi)核擴(kuò)展機(jī)制

從崩潰信息中我們可以看到,Bam.sys注冊了一個進(jìn)程創(chuàng)建回調(diào),并且在卸載之前忘記注銷它了。接下來,當(dāng)一個進(jìn)程被創(chuàng)建/終止時,系統(tǒng)會嘗試調(diào)用這個回調(diào),并引用舊指針,然后導(dǎo)致系統(tǒng)崩潰。

如何解析Windows內(nèi)核擴(kuò)展機(jī)制

有趣的并不是系統(tǒng)發(fā)生崩潰,而是Bam.sys到底是如何注冊這個回調(diào)的。一般來說,進(jìn)程創(chuàng)建回調(diào)是通過nt!PsSetCreateProcessNotifyRoutine(Ex)注冊的,它會向nt!PspCreateProcessNotifyRoutine數(shù)組中添加這個回調(diào)。接下來,當(dāng)進(jìn)程被創(chuàng)建/終止時,nt!PspCallProcessNotifyRoutines會迭代循環(huán)這個數(shù)組,并調(diào)用所有已注冊的回調(diào)。然而,如果我們在WinDbg中運行“!wdbgark.wa_systemcb /typeprocess“的話,我們將會看到這個數(shù)組中并不存在Bam.sys所使用的回調(diào):

如何解析Windows內(nèi)核擴(kuò)展機(jī)制

原來,Bam.sys使用了另一種機(jī)制來注冊它的回調(diào):

如何解析Windows內(nèi)核擴(kuò)展機(jī)制

如何解析Windows內(nèi)核擴(kuò)展機(jī)制

查看nt!PspCallProcessNotifyRoutines后我們發(fā)現(xiàn),其中有一個指向nt!PspBamExtensionHost的顯示引用。它會使用這種“擴(kuò)展主機(jī)”來檢索所謂的“擴(kuò)展表”,并調(diào)用擴(kuò)展表中的第一個函數(shù),即bam!BampCreateProcessCallback。

在IDA中打開Bam.sys,我們可以直接看到bam!BampCreateProcessCallback,并搜索它的xrefs。幸好它只有一個,就在bam!BampRegisterKernelExtension中:

如何解析Windows內(nèi)核擴(kuò)展機(jī)制

我懷疑Bam!BampCreateProcessCallback并沒有通過常規(guī)的回調(diào)注冊機(jī)制來進(jìn)行注冊。實際上,它被存在了一個名叫Bam!BampKernelCalloutTable的函數(shù)表中,而這個表會和其他參數(shù)一起傳遞給nt!ExRegisterExtension函數(shù)(文檔中未記載)。

唯一一個我找到的跟這個函數(shù)相關(guān)的就是ntosifs.h頭文件,其中包含了nt!ExRegisterExtension函數(shù)的原型以及_EX_EXTENSION_REGISTRATION_1結(jié)構(gòu)體。

nt!ExRegisterExtension函數(shù)原型和_EX_EXTENSION_REGISTRATION_1:

NTKERNELAPINTSTATUS ExRegisterExtension (    _Outptr_ PEX_EXTENSION *Extension,    _In_ ULONG RegistrationVersion,    _In_ PVOID RegistrationInfo); typedefstruct _EX_EXTENSION_REGISTRATION_1 {    USHORT ExtensionId;    USHORT ExtensionVersion;    USHORT FunctionCount;    VOID *FunctionTable;    PVOID *HostInterface;    PVOID DriverObject;}EX_EXTENSION_REGISTRATION_1, *PEX_EXTENSION_REGISTRATION_1;

注意:nt!ExRegisterExtension的偽代碼可在附錄B中找到。

我們可以看到,nt!ExRegisterExtension會搜索名稱匹配RegistrationInfo的主機(jī)。那么問題來了,這些主機(jī)是從哪兒來的呢?

在初始化的過程中,NTOS會多次調(diào)用nt!ExRegisterHost。每次調(diào)用時,它都會傳遞一個結(jié)構(gòu)體來識別列表中預(yù)定義的驅(qū)動器(完整列表可在附錄A中找到)。比如說,Bam.sys會使用下列調(diào)用來初始化一臺主機(jī):

如何解析Windows內(nèi)核擴(kuò)展機(jī)制

nt!ExRegisterHost會分配一個type_HOST_LIST_ENTRY結(jié)構(gòu)體,并使用調(diào)用方提供的參數(shù)來進(jìn)行初始化,然后將其添加到nt!ExpHostList結(jié)尾。_HOST_LIST_ENTRY結(jié)構(gòu)體文檔未記載,它的大致結(jié)構(gòu)如下:

struct_HOST_LIST_ENTRY{    _LIST_ENTRY List;    DWORD RefCount;    USHORT ExtensionId;    USHORT ExtensionVersion;    USHORT FunctionCount; // number ofcallbacks that the extension                          // contains    POOL_TYPE PoolType;   // where this host is allocated    PVOID HostInterface; // table of unexportednt functions,                         // to be used by thedriver to which                         // this extensionbelongs    PVOID FunctionAddress; // optional, rarelyused.                           // This callback iscalled before                           // and after anextension for this                           // host isregistered / unregistered    PVOID ArgForFunction; // will be sent tothe function saved here    _EX_RUNDOWN_REF RundownRef;    _EX_PUSH_LOCK Lock;    PVOID FunctionTable; // a table of thecallbacks that the                         // driver “registers”    DWORD Flags;         // Only uses one bit.                         // Not sure about itsmeaning.}HOST_LIST_ENTRY, *PHOST_LIST_ENTRY;

當(dāng)其中一個預(yù)定義的驅(qū)動器加載時,它會使用nt!ExRegisterExtension注冊一個擴(kuò)展,并提供一個RegistrationInfo結(jié)構(gòu)體,其中包括一個函數(shù)表。這個函數(shù)表會被置入匹配主機(jī)的FunctionTable成員中。這些函數(shù)隨后會被NTOS在特定的場景下調(diào)用,這也就是所謂的回調(diào)了。

之前我們看到了nt!ExRegisterExtension的部分功能會被設(shè)置為RegistrationInfo->HostInterface(包含一個全局變量),并指向主機(jī)結(jié)構(gòu)體中的某些數(shù)據(jù)。

每一個注冊了擴(kuò)展的驅(qū)動器都有一個NTOS設(shè)置的初始化主機(jī),這種主機(jī)包含一個HostInterface,它指向HTOS函數(shù)預(yù)定一個一個表,不同的驅(qū)動器會收到不同的HostInterface,但有些則不會收到。

比如說,Bam.sys收到的就是下面這個HostInterface:

如何解析Windows內(nèi)核擴(kuò)展機(jī)制

實際上,這里所謂的“內(nèi)核擴(kuò)展機(jī)制”即使一種雙向通信端口:驅(qū)動器提供一個“回調(diào)”列表,以供在不同場景下調(diào)用,然后在各自內(nèi)部使用場景中接收不同的函數(shù)集。

下面給出的是Bam.sys的回調(diào)樣本:

BampCreateProcessCallbackBampSetThrottleStateCallbackBampGetThrottleStateCallbackBampSetUserSettingsBampGetUserSettingsHandle

負(fù)責(zé)Bam.sys初始化的主機(jī)預(yù)先“知道”它需要接收包含上面這5個函數(shù)的函數(shù)表。這些函數(shù)必須按照上述順序提供,因此這里是通過索引來調(diào)用的。我們可以看到,nt!PspBamExtensionHost->FunctionTable[4]調(diào)用情況:

如何解析Windows內(nèi)核擴(kuò)展機(jī)制

總而言之,Windows中存在一種機(jī)制,可以用來“擴(kuò)展”NTOS,具體過程是先注冊某些回調(diào)函數(shù),然后接收驅(qū)動可以使用的未導(dǎo)出函數(shù)。我并不清楚這個知識點是否能發(fā)揮實際作用,但覺得這方面內(nèi)容比較有趣,值得與大家分享。希望可以給大家提供幫助,感謝閱讀!

附錄A-NTOS初始化的擴(kuò)展主機(jī)

如何解析Windows內(nèi)核擴(kuò)展機(jī)制

附錄B-函數(shù)偽代碼

ExRegisterExtension.c:

NTSTATUSExRegisterExtension(_Outptr_ PEX_EXTENSION *Extension, _In_ ULONGRegistrationVersion, _In_ PREGISTRATION_INFO RegistrationInfo){       // Validate that version is ok and thatFunctionTable is not sent without FunctionCount or vise-versa.       if ( (RegistrationVersion &0xFFFF0000 != 0x10000) || (RegistrationInfo->FunctionTable == nullptr&& RegistrationInfo->FunctionCount != 0) )       {              return STATUS_INVALID_PARAMETER;       }        // Skipping over some lock-related stuff,             // Find the host with the matchingversion and id.       PHOST_LIST_ENTRY pHostListEntry;       pHostListEntry =ExpFindHost(RegistrationInfo->ExtensionId,RegistrationInfo->ExtensionVersion);        // More lock-related stuff.             if (!pHostListEntry)       {              return STATUS_NOT_FOUND;       }        // Verify that the FunctionCount in thehost doesn't exceed the FunctionCount supplied by the caller.       if (RegistrationInfo->FunctionCount< pHostListEntry->FunctionCount)       {        ExpDereferenceHost(pHostListEntry);              return STATUS_INVALID_PARAMETER;       }        // Check that the number of functions inFunctionTable matches the amount in FunctionCount.       PVOID FunctionTable =RegistrationInfo->FunctionTable;       for (int i = 0; i FunctionCount; i++)       {                   if (RegistrationInfo->FunctionTable[i] == nullptr )              {               ExpDereferenceHost(pHostListEntry);                     returnSTATUS_ACCESS_DENIED;              }       }        // skipping over some more lock-relatedstuff        // Check if there is already an extensionregistered for this host.       if (pHostListEntry->FunctionTable !=nullptr || FlagOn(pHostListEntry->Flags, 1) )       {              // There is something related tolocks here        ExpDereferenceHost(pHostListEntry);              returnSTATUS_OBJECT_NAME_COLLISION;       }        // If there is a callback function forthis host, call it before registering the extension, with 0 as the firstparameter.       if (pHostListEntry->FunctionAddress)       {        pHostListEntry->FunctionAddress(0,pHostListEntry->ArgForFunction);       }        // Set the FunctionTable in the host tothe table supplied by the caller, or to MmBadPointer if a table wasn'tsupplied.       if (RegistrationInfo->FunctionTable ==nullptr)       {              pHostListEntry->FunctionTable= nt!MmBadPointer;       }       else       {              pHostListEntry->FunctionTable= RegistrationInfo->FunctionTable;       }        pHostListEntry->RundownRef = 0;        // If there is a callback function forthis host, call it after registering the extension, with 1 as the firstparameter.       if (pHostListEntry->FunctionAddress)       {        pHostListEntry->FunctionAddress(1,pHostListEntry->ArgForFunction);       }        // Here there is some more lock-relatedstuff        // Set the HostTable of the callingdriver to the table of functions listed in the host.       if (RegistrationInfo->HostTable !=nullptr)       {        *(PVOID)RegistrationInfo->HostTable= pHostListEntry->hostInterface;       }        // Return the initialized host to thecaller in the output Extension parameter.       *Extension = pHostListEntry;       return STATUS_SUCCESS;}

ExRegisterHost.c:

NTSTATUSExRegisterHost(_Out_ PHOST_LIST_ENTRY ExtensionHost, _In_ ULONG Unused, _In_PHOST_INFORMATION HostInformation){       NTSTATUS Status = STATUS_SUCCESS;        // Allocate memory for a newHOST_LIST_ENTRY       PHOST_LIST_ENTRY p =ExAllocatePoolWithTag(HostInformation->PoolType, 0x60, 'HExE');       if (p == nullptr)       {              returnSTATUS_INSUFFICIENT_RESOURCES;       }        //       // Initialize a new HOST_LIST_ENTRY       //       p->Flags &= 0xFE;       p->RefCount = 1;       p->FunctionTable = 0;       p->ExtensionId =HostInformation->ExtensionId;       p->ExtensionVersion =HostInformation->ExtensionVersion;       p->hostInterface =HostInformation->hostInterface;       p->FunctionAddress =HostInformation->FunctionAddress;       p->ArgForFunction =HostInformation->ArgForFunction;                           p->Lock = 0;                          p->RundownRef = 0;                     // Search for an existing listEntry withthe same version and id.       PHOST_LIST_ENTRY listEntry = ExpFindHost(HostInformation->ExtensionId,HostInformation->ExtensionVersion);       if (listEntry)       {              Status =STATUS_OBJECT_NAME_COLLISION;              ExpDereferenceHost(p);              ExpDereferenceHost(listEntry);       }       else       {              // Insert the new HOST_LIST_ENTRYto the end of ExpHostList.              if ( *lastHostListEntry !=&firstHostListEntry )              {                    __fastfail();              }               firstHostListEntry->Prev =&p;              p->Next = firstHostListEntry;              lastHostListEntry = p;               ExtensionHost = p;       }             return Status;}

ExpFindHost.c:

PHOST_LIST_ENTRYExpFindHost(USHORT ExtensionId, USHORT ExtensionVersion){       PHOST_LIST_ENTRY entry;       for (entry == ExpHostList; ; entry =entry->Next)       {              if (entry == &ExpHostList)              {                     return 0;              }                           if ( *(entry->ExtensionId) ==ExtensionId && *(entry->ExtensionVersion) == ExtensionVersion )              {                     break;              }       }InterlockedIncrement(entry->RefCount);       return entry;}

ExpDereferenceHost.c:

voidExpDereferenceHost(PHOST_LIST_ENTRY Host){      if (InterlockedExchangeAdd(Host.RefCount, 0xFFFFFFFF) == 1 )       {                  ExFreePoolWithTag(Host, 0);       }}

附錄C-結(jié)構(gòu)體定義

struct_HOST_INFORMATION{    USHORT ExtensionId;    USHORT ExtensionVersion;    DWORD FunctionCount;    POOL_TYPE PoolType;    PVOID HostInterface;    PVOID FunctionAddress;    PVOID ArgForFunction;    PVOID unk;}HOST_INFORMATION, *PHOST_INFORMATION; struct_HOST_LIST_ENTRY{    _LIST_ENTRY List;    DWORD RefCount;    USHORT ExtensionId;    USHORT ExtensionVersion;    USHORT FunctionCount; // number ofcallbacks that the                          // extension contains    POOL_TYPE PoolType;   // where this host is allocated    PVOID HostInterface;  // table of unexported nt functions,                          // to be used by thedriver to which                          // this extensionbelongs    PVOID FunctionAddress; // optional, rarelyused.                           // This callback iscalled before and                              // after anextension for this host                           // is registered /unregistered    PVOID ArgForFunction; // will be sent tothe function saved here    _EX_RUNDOWN_REF RundownRef;    _EX_PUSH_LOCK Lock;    PVOID FunctionTable;    // a table of the callbacks that                            // the driver“registers”DWORDFlags;                // Only uses oneflag.                            // Not sure about its meaning.}HOST_LIST_ENTRY, *PHOST_LIST_ENTRY;; struct_EX_EXTENSION_REGISTRATION_1{    USHORT ExtensionId;    USHORT ExtensionVersion;    USHORT FunctionCount;    PVOID FunctionTable;    PVOID *HostTable;    PVOID DriverObject;}EX_EXTENSION_REGISTRATION_1,*PEX_EXTENSION_REGISTRATION_1;

看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進(jìn)一步的了解或閱讀更多相關(guān)文章,請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對創(chuàng)新互聯(lián)的支持。


分享名稱:如何解析Windows內(nèi)核擴(kuò)展機(jī)制
網(wǎng)頁地址:http://weahome.cn/article/jgeice.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部