共用方式為


應用程式驗證程式 - 常見問題 (常見問題)

一般問題

以下是應用程式驗證器的一般使用方式所收到的問題清單。

什麼是應用程式驗證器?

應用程式驗證器是一種執行時間驗證工具,可用來尋找 Microsoft Windows 應用程式中的 Bug。 因為它是執行時間工具,因此必須練習應用程式程式碼,才能進行驗證。 因此,良好的測試涵蓋範圍相當重要。

應用程式驗證器的一般使用案例是針對感興趣的應用程式啟用它, (請參閱下列問題,以瞭解如何執行該) ,然後執行您為應用程式撰寫的所有測試。 您將會收到偵錯工具中斷或驗證程式記錄專案形式中找到之任何 Bug 的通知。

如何?卸載應用程式驗證器?

若要卸載應用程式驗證程式,請按一下 [開始]、選取 [新增或移除程式]、[移除程式]、按一下 [應用程式驗證程式],然後按一下 [移除] 來存取控制台。

如何?啟動應用程式驗證器嗎?

安裝應用程式驗證器之後,您可以在程式清單中存取它,或在命令列上輸入Appverif.exe來啟動它。 若要這樣做,請移至命令提示字元或 [啟動] 功能表的 [執行] 方塊。 輸入 appverif.exe,然後按 Enter 鍵。 這會啟動應用程式驗證器。

Appverifer.exe二進位檔會安裝在系統目錄中,並用來進行工具設定。

記錄儲存在哪裡?

記錄會儲存在 %USERPROFILE%\AppVerifierLogs 中

如果在使用應用程式驗證器時發生問題,該怎麼辦?

請確定您執行的是最新版本。 請考慮在不同的電腦上或甚至是 Windows 版本上嘗試相同的應用程式。

應用程式驗證器是否驗證 Managed 程式碼?

AppVerifier 會關心作業系統與應用程式之間的介面。 因此,除非您的 Managed 程式碼針對必須對堆積、控制碼、重大區段等的原生 API 執行 Interop。您的測試案例不會讓您與已驗證的介面互動。

建議您利用 Managed 偵錯小幫手來驗證您的 Managed 程式碼。 如需詳細資訊,請參閱 使用 Windows 偵錯工具對 Managed 程式碼進行偵錯。

偵錯工具問題

以下是有關偵錯工具的問題清單。

為什麼收到錯誤,告知我需要偵錯工具?

應用程式驗證器內的 [基本] 驗證層會要求您在偵錯工具下執行應用程式。 如果您在選取測試之前沒有與應用程式相關聯的偵錯工具,您會收到一個對話方塊,提醒您必須在偵錯工具下執行應用程式,才能取得記錄的資訊。

如何?偵錯工具下執行我的應用程式?

請參閱偵錯工具安裝和設定主題 -使用 Windows 偵錯消費者入門

如何?測試堆疊擴充,而不需任何其他檢測?

一般而言,堆疊擴充應該確實與其他驗證層隔離,包括堆積。 原因如下:每個驗證層「Thunks」API 或具有一些常式的匯出點。

例如,對 CreateFileA 的呼叫將會是 appvocre 的呼叫!NS_SecurityChecks::CreateFileA,這可能會呼叫 appvcore!NS_FillePaths::CreateFileA,可能呼叫 kernel32!CreateFileA,可能會呼叫驗證器!AVrfpNtCreateFile,將會呼叫 ntdll!NtCreateFile。 您可以看到檢測已新增 3 個更多「堆疊」函式呼叫,其中每一個函式呼叫可能會耗用更多堆疊。

在下列案例中,LH-verifier.dll是每個 DllMain 的「Thunking」,而「已檢測」堆積程式碼路徑將會新增更多堆疊使用量。 由於來自偵錯工具的插入執行緒不會使用IMAGE_NT_HEADERS預設值,因此初始認可的堆疊將無法完成執行緒的 APC 狀態, (APC 狀態的執行緒執行初始化程式碼) 。

如果您想要使用 Stack-Ckecs,則可能是 FirstChanceAccessViolation 時應該使用的唯一其他驗證層。

使用 !avrf 擴充功能時,我收到「此程式未啟用應用程式驗證程式...」

收到的完整錯誤: Application verifier is not enabled for this process. Use appverif.exe tool to enable it.

您可能只啟用填充碼驗證層,以及/或已啟用「純」模式的堆積。 以下是一些可能的原因。

測試案例問題

以下是針對不同測試案例所收到的問題清單。

如何在我的服務上啟用應用程式驗證程式,但不能啟用其他驗證程式?

在 System32 目錄中建立svchost.exe複本,並呼叫 「Mysvchost.exe」複本。

使用 regedit 開啟 HKLM\System\CurrentControlSet\Services\MyService。

編輯 「ImagePath」 值,其會像 「%SystemRoot%\system32\svchost.exe -k myservice」 一樣,並將svchost.exe變更為 「Mysvchost.exe」。

將 「Mysvchost.exe」 新增至 AppVerifier 清單,並檢查所需的測試。

重新開機。

如何?從 WOW64 下執行的 32 位應用程式啟動的 64 位應用程式上執行應用程式驗證程式?

簡單版本:在指定的應用程式上啟用驗證器設定的黃金規則是符合工具和目標進程的位性。 也就是說:針對在 WoW64) 下執行的 32 位 (應用程式使用 32 位appverif.exe,並針對原生 64 位原生目標使用 64 位AppVerif.exe。

長版本:應用程式驗證器設定是「核心」設定和「填充碼」設定的適當聯集。

核心設定 - 核心設定會儲存在 [影像檔執行選項] 底下。

從啟動應用程式讀取 「偵錯工具」值。 因此,如果您想要讓 32 位devenv.exe啟動 64 位my.exe並在偵錯工具下執行,則必須在 WoW6432Node 底下使用 32 位登錄機碼。 32 位進程的其他值會從兩個位置讀取,這兩個位置都是原生 IFEO 和 WoW6432Node。

原因如下:在 WoW 下執行的 32 位進程是執行 Wow64 模擬迴圈的 64 位進程。 因此,每個 32 位進程都是 64 位進程,然後是 32 位進程。 64 位 IFEO 會在Wow64cpu.dll程式碼上啟用驗證器,而 32 位 IFEO 則會在 32 位程式碼上啟用驗證器。

從使用者的觀點來看,verifier.dll會在 64 位世界中載入兩次 (一次,一次位於 32 位世界) 。 由於大部分的人並不關心驗證wow64cpu.dll,所以 32 位進程最可接受的行為是只驗證 32 位部分。 這就是為什麼「一律符合位」的黃金規則適用的原因。

如何?偵錯在非互動式視窗月臺中執行的服務

若要偵錯在非互動式視窗月臺中執行的服務,請執行下列 (僅適用于您使用 ntsd/windbg) :

在 HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File 執行選項下,將機碼新增至登錄。 此機碼的名稱應該是進程名稱 (service.exe) 。

建立稱為偵錯工具的REG_SZ值,並將此值設定為偵錯工具所在的路徑。 它必須包含完整路徑,而不只是偵錯工具的名稱。 此命令應該包含 –server 選項,以及偵錯工具應該接聽的特定埠或埠範圍。 例如,c:\debuggers\ntsd.exe –server tcp:port=5500:5600 –g – G。

使用 –remote 選項執行偵錯工具,以連線到偵錯工具伺服器。 例如:windbg.exe –remote tcp:=localhost,port=55xx,其中 'xx' 是一些從 00 到 99 的數位,如果您在伺服器上使用範圍。

AppVerifier 是否進行洩漏偵測? 在 Windows 7 和更新版本下,有一個流失檢查選項,會在進程流失記憶體時偵測到。 在先前的作業系統下,AppVerifier 不會測試應用程式是否有洩漏偵測,但會尋找其他記憶體問題。

針對安全性考慮,建議使用哪些測試?

  • 堆積
  • 處理
  • 鎖定
  • 堆疊 (僅適用于可關閉電腦) 的服務與重要程式

請記住,過時的APICalls 只會針對它看到的每個呼叫發出警告,該 API 在 MSDN 中列為過時或已被取代。 如果應用程式切換至新的 API 很重要,您應該依案例決定。 某些 API 有危險性,有些 API 只是由較新的 API 取代,而且有更多選項。 如需詳細資訊,請參閱撰寫安全程式碼的「危險 API」一節。

對於需要高度可靠的應用程式,例如服務和伺服器程式,您也應該啟用 Stacks 檢查。 這會藉由停用堆疊成長,檢查堆疊認可大小是否足夠。 如果應用程式立即結束堆疊溢位,這表示應用程式必須以較大的堆疊認可大小重新編譯。 如果您是測試人員,並在使用 Stacks 檢查時遇到應用程式的問題,請提出 Bug、將它指派給您的開發人員,並持續進行測試。

測試特定問題

以下是測試相關問題的清單。 按一下問題以查看回應:

重要區段外泄是否很重要?

每當洩漏重要區段時,就會洩漏下列內容:事件控制碼、少量的核心集區和小型堆積配置。 如果進程結束時,這些會清除。

如果您的程式應該長時間保持運作,這些流失可能會讓您受到影響。 由於修正程式在 99% 的案例中非常簡單, (開發人員只忘記呼叫 RtlDeleteCriticalSection) 您應該加以解決。

我們是否可以以程式設計方式處理堆疊溢位?

在初始執行緒函式中建立例外狀況處理常式不保證會攔截可能引發的潛在堆疊溢位。 這是因為分派例外狀況的程式碼也需要一些堆疊,才能在目前的啟用記錄上執行。 由於我們剛剛失敗堆疊延伸模組,因此我們很可能會在嘗試分派第一個堆疊時,逐步執行已認可的堆疊結尾,並引發第二個例外狀況。 雙重錯誤例外狀況會無條件地終止進程。

LoaderLock 測試提供呼叫 DestroyWindow 的錯誤。 為什麼無法在 DllMain 中呼叫 DestroyWindow? 您不會控制要卸離的執行緒。 如果它與建立視窗的執行緒不同,您就無法終結視窗。 因此,您會洩漏視窗,而下次視窗收到訊息時,因為 Wndproc 已卸載而損毀。

您必須先終結視窗,才能取得進程中斷連結。 危險不是將卸載 user32。 危險在於您正在卸載。 因此,視窗收到的下一個訊息會損毀進程,因為 user32 會將訊息傳遞給您的 Wndproc,而該訊息不再存在。

Microsoft Windows 作業系統具有線程親和性。 進程中斷連結不會。 載入器鎖定不是真正的大問題;問題為 Dllmain。 進程中斷連結是 DLL 上次執行程式碼的時間。 您必須先移除所有專案,才能返回。 但是,由於 Windows 具有線程親和性,因此如果您位於錯誤的執行緒上,就無法清除視窗。

如果有人已安裝全域勾點 (,載入器鎖定會進入圖片,例如 spy++ 正在執行) 。 在此情況下,您會輸入潛在的死結案例。 同樣地,解決方案是在取得 process-detach 之前終結視窗。

增加初始堆疊認可來避免溢位是否昂貴?

當您認可堆疊時,您只是保留頁面檔案空間。 沒有任何效能影響。 實際上不會使用任何實體記憶體。 如果您實際觸碰到您認可的堆疊空間,則只會發生額外的成本。 但即使您未事先認可堆疊,仍會發生此情況。

讓我們看看讓所有服務在svchost.exe點防護中執行的成本為何。 在測試電腦上,我收到總共 139 個執行緒的 9 個svchost.exe進程。 如果我們在 32K 上為每個執行緒設定預設堆疊,我們大約需要 32K x 200 ~ 6.4 Mb 的頁面檔案空間,才能預先認可所有堆疊。

這是支付可靠性費用相當小的價格。

保留堆疊大小呢?

有一些有趣的專案,例如 IA64/AMD64 上的例外狀況分派,需要「非預期」的額外堆疊。 RPC 背景工作執行緒上可能會發生一些處理,其堆疊需求超過合理的測量嘗試。

首先,您應該瞭解進程中所有線程集區。 NT-Thread-Pool,具有 alertable-wait-threads 有時很特殊,例如,如果您使用 SQL 中的資料庫元件,它會在使用者 APC 目標執行緒上使用可警示的睡眠。 這可能會造成巢狀呼叫的問題。

一旦您知道所有線程集區,請瞭解如何控制其堆疊需求。 例如,RPC 會讀取堆疊認可的登錄機碼。 WDM 幫浦執行緒會從映射取得該執行緒。 若為其他執行緒集區,可能會有所不同。

當您所有線程都清楚時,您可以採取一些動作。 只有執行緒出現且經常發生時,沒有龐大的保留空間,才有助於位址空間片段。 如果您的控制項中有一個穩定的執行緒集區,您可能也會有減少保留空間的優點。 這確實有助於節省堆積的位址空間,以及為使用者節省位址空間。

是否有建議如何為 LINKER_STACKCOMMITSIZE=挑選正確的大小?

視 CPU) 而定,頁面大小應該 (4k/8k 來區分值。 以下是一些判斷您需要大小的指導方針:

  1. 將任何具有潛在未系結深度的遞迴函式 (或至少使用者難以理解的高深度) 轉換為反復式。

  2. 減少 alloca 使用量。 使用堆積或 safealloca。

  3. 執行預製,並檢查堆疊大小降低 (假設為 8k) 。 修正標示為使用太多堆疊的函式。

  4. 將堆疊認可設定為 16k。

  5. 在偵錯工具下執行許多測試,並檢查應用程式驗證器的「堆疊」。

  6. 當您看到堆疊溢位判斷最差的感應器並加以修正時。 (請參閱步驟 5.)

  7. 當您無法再增加 8k 的堆疊使用量時。 如果 > 64k 發生錯誤,請減少回 64k,並查看步驟 6。 否則,請移至步驟 5。

堆積測試的記憶體需求為何?

如需完整的堆積測試,您需要 256 MB 的 RAM 和至少 1GB 的頁面檔案。 針對一般堆積測試,您至少需要 128 MB 的 RAM。 沒有特定的處理器或磁片需求。

為什麼我收到ALL_ACCESS停止?

任何使用_ALL_ACCESS的應用程式都會轉譯它正在存取的物件,因為稽核記錄不會反映您實際對物件所做的動作,而只會反映您要求對物件執行的動作。

此條件會建立更具開發性攻擊的偽裝。 掃描進行中攻擊活動的系統管理員,對於要求金鑰 X 上ALL_ACCESS的人員不會有任何錯誤,因為特定應用程式一律會執行此動作。 系統管理員會認為「人員可能只是執行Word」。 系統管理員無法告訴駭客已滲透我的帳戶,而現在探查系統來判斷我擁有的存取權,他可以惡意利用該存取權。 可能性是無窮無盡的。

ALL_ACCESS的 ACL 問題在於您必須一律獲得授權。 如果我們想要一天拒絕您刪除特定金鑰的存取權,則我們無法存取。 即使您並未實際刪除金鑰,我們還是會中斷您的應用程式,因為您會要求刪除存取權。

為什麼我無法從堆積取得任何記錄並鎖定測試?

這些測試是在 (內建的驗證層,而不是封裝) ,並在偵錯工具中回報錯誤。 如果您執行已啟用這些測試的應用程式,而且沒有當機,則不會回報任何問題。

如果您遇到當機,則必須在偵錯工具下執行,或將應用程式傳遞給開發人員,以更仔細地測試。

為什麼錯誤插入無法運作?

錯誤插入機率已根據客戶意見反應,在 AppVerifier 組建中變更為 2007 年 2 月之後發行的每百萬個元件。 因此,0n20000 的機率為 2%,0n500000 為 50%,依此類錯。

!avrf –flt 偵錯工具延伸模組可用來變更偵錯工具中即時的機率。 不過,應該開啟程式的低資源模擬檢查,才能運作。

!avrf 偵錯工具延伸模組是偵錯工具套件隨附的一部分exts.dll。 支援機率變更的 !avrf 變更位於最新的偵錯工具套件中。 如果您遇到錯誤插入的問題,請更新偵錯工具和 AppVerifier 套件。

為何流失驗證器不會報告特定資源流失?

載入 DLL 或 EXE 模組時,流失驗證器不會報告任何資源流失。 卸載模組時,如果模組配置的任何資源尚未釋放,流失驗證器就會發出停止。

若要檢查載入 DLL 或 EXE 所配置的資源,請使用 !avrf -leak 偵錯工具擴充功能。

另請參閱

應用程式驗證器 - 概觀

應用程式驗證器 - 功能

應用程式驗證器 - 測試應用程式

應用程式驗證器 - 應用程式驗證器內的測試

應用程式驗證器 - 停止程式碼和定義

應用程式驗證器 - 偵錯應用程式驗證器停止