共用方式為


偵錯工具命令程式範例

下列各節說明偵錯工具命令程式。

使用 .foreach 權杖

下列範例會使用 .foreach 權杖來搜尋 5a4d 的 WORD 值。 針對找到的每個 5a4d 值,偵錯工具會顯示 8 個 DWORD 值,從找到 5a4d DWORD 的位址開始。

0:000> .foreach (place { s-[1]w 77000000 L?4000000 5a4d }) { dc place L8 } 

下列範例會使用 .foreach 權杖來搜尋 5a4d 的 WORD 值。 針對找到的每個 5a4d 值,偵錯工具會顯示 8 個 DWORD 值,從找到 5a4d DWORD 位址之前的 4 個位元組開始。

0:000> .foreach (place { s-[1]w 77000000 L?4000000 5a4d }) { dc place -0x4 L8 } 

下列範例會顯示相同的值。

0:000> .foreach (place { s-[1]w 77000000 L?4000000 5a4d }) { dc ( place -0x4 ) L8 } 

注意 如果您想要在命令的 OutCommands 部分中操作變數名稱,則必須在變數名稱後面加上空格。 例如,在前置範例中,變數 位置 與減法運算子之間有一個空格。

-[1]選項連同s (Search Memory) 命令會導致其輸出只包含其找到的位址,而不是在這些位址找到的值。

下列命令會顯示所有位於記憶體範圍中之模組的詳細資訊模組資訊,從0x77000000到0x7F000000。

0:000> .foreach (place { lm1m }) { .if ((${place} >= 0x77000000) & (${place} <= 0x7f000000)) { lmva place } } 

1m選項與lm (List Loaded Modules) 命令會導致其輸出只包含模組的位址,而不是模組的完整描述。

上述範例會使用 ${ } (別名解譯器) 權杖,以確保即使別名位於其他文字旁邊也一樣。 如果命令未包含此權杖,則旁的左 括弧會防止 別名取代。 請注意, $ {} token 適用于.foreach和 true 別名中使用的變數。

逐步執行程式清單

下列範例會逐步解說核心模式進程清單,並顯示清單中每個專案的可執行檔名稱。

此範例應該儲存為文字檔,並使用 $$ >< (執行腳本檔案) 命令來執行。 此命令會載入整個檔案、以分號取代所有歸位字元,並執行產生的區塊。 此命令可讓您使用多行和縮排來撰寫可讀取的程式,而不需要將整個程式壓縮成單行。

此範例說明下列功能:

  • $t 0$t 1$t 2虛擬暫存器會作為此程式中的變數使用。 此程式也會使用名為 Procc$ImageName 的別名。

  • 此程式使用 MASM 運算式評估工具。 不過, @@c++ ( ) 權杖會出現一次。 此權杖會使程式使用 C++ 運算式評估工具剖析括弧內的運算式。 此用法可讓程式直接使用 C++ 結構權杖。

  • 旗標會與r (Registers) 命令搭配使用。 此旗標會將具類型的值指派給虛擬緩存 器 $t 2

$$  Get process list LIST_ENTRY in $t0.
r $t0 = nt!PsActiveProcessHead

$$  Iterate over all processes in list.
.for (r $t1 = poi(@$t0);
      (@$t1 != 0) & (@$t1 != @$t0);
      r $t1 = poi(@$t1))
{
    r? $t2 = #CONTAINING_RECORD(@$t1, nt!_EPROCESS, ActiveProcessLinks);
    as /x Procc @$t2

 $$  Get image name into $ImageName.
 as /ma $ImageName @@c++(&@$t2->ImageFileName[0])

 .block
    {
        .echo ${$ImageName} at ${Procc}
    }

    ad $ImageName
    ad Procc
}

逐步執行LDR_DATA_TABLE_ENTRY清單

下列範例會逐步解說使用者模式LDR_DATA_TABLE_ENTRY清單,並顯示每個清單專案的基底位址和完整路徑。

如同上述範例,此程式應該儲存在檔案中,並使用 $$ >< (執行腳本檔案) 命令來執行。

此範例說明下列功能:

  • 此程式使用 MASM 運算式評估工具。 不過,在兩個位置中, @@c++ ( ) 權杖隨即出現。 此權杖會使程式使用 C++ 運算式評估工具剖析括弧內的運算式。 此用法可讓程式直接使用 C++ 結構權杖。

  • 旗標會與r (Registers) 命令搭配使用。 此旗標會將具類型的值指派給虛擬暫存器 $t 0$t 1。 在迴圈本文中, $t 1 具有 ntdll!_LDR_DATA_TABLE_ENTRY\*類型,因此程式可以進行直接成員參考。

  • 此程式中會使用使用者命名別名 $Base$Mod 。 貨幣符號可減少先前在目前偵錯工具會話中使用這些別名的可能性。 不需要貨幣符號。 ${/v: } Token 會常解譯別名,避免在腳本執行之前定義別名時加以取代。 您也可以將此權杖與任何區塊一起使用,以防止在區塊使用之前使用別名定義。

  • .block Token 可用來新增額外的別名取代步驟。 載入別名時,會針對整個腳本進行一次別名取代,並在輸入每個區塊時發生一次。 如果沒有 .block Token 及其大括弧, .echo 命令就不會接收上一行中指派 之$Mod$Base 別名的值。

$$ Get module list LIST_ENTRY in $t0.
r? $t0 = &@$peb->Ldr->InLoadOrderModuleList
 
$$ Iterate over all modules in list.
.for (r? $t1 = *(ntdll!_LDR_DATA_TABLE_ENTRY**)@$t0;
 (@$t1 != 0) & (@$t1 != @$t0);
      r? $t1 = (ntdll!_LDR_DATA_TABLE_ENTRY*)@$t1->InLoadOrderLinks.Flink)
{
    $$ Get base address in $Base.
 as /x ${/v:$Base} @@c++(@$t1->DllBase)
 
 $$ Get full name into $Mod.
 as /msu ${/v:$Mod} @@c++(&@$t1->FullDllName)
 
 .block
    {
        .echo ${$Mod} at ${$Base}
    }
 
    ad ${/v:$Base}
    ad ${/v:$Mod}
}