Aracılığıyla paylaş


Hata Ayıklayıcı Komut Programları Örnekleri

Aşağıdaki bölümlerde hata ayıklayıcı komut programları açıklanmaktadır.

.foreach Belirtecini Kullanma

Aşağıdaki örnek, 5a4d WORD değerlerini aramak için .foreach belirtecini kullanır. Bulunan her 5a4d değeri için hata ayıklayıcı, 5a4d DWORD'ünün bulunduğu adreste başlayarak 8 DWORD değeri görüntüler.

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

Aşağıdaki örnek, 5a4d WORD değerlerini aramak için .foreach belirtecini kullanır. Bulunan her 5a4d değeri için hata ayıklayıcı, 5a4d DWORD'un bulunduğu adresten 4 bayt önce başlayan 8 DWORD değeri görüntüler.

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

Aşağıdaki örnekte aynı değerler görüntülenir.

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

Not Komutun OutCommands bölümündeki değişken adı üzerinde çalışmak istiyorsanız, değişken adından sonra bir boşluk eklemeniz gerekir. Örneğin, hazırlama örneğinde, yerleştir değişkeni ile çıkarma işleci arasında bir boşluk vardır.

-[1] (Arama Belleği) komutuyla birlikte seçeneği, çıkışının bu adreslerde bulunan değerleri değil yalnızca bulduğu adresleri içermesine neden olur.

Aşağıdaki komut, 0x77000000 ile 0x7F000000 arasındaki bellek aralığında bulunan tüm modüller için ayrıntılı modül bilgilerini görüntüler.

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

lm (Yüklenen Modülleri Listele) komutuyla birlikte 1m seçeneği, çıkışının modüllerin tam açıklamasını değil yalnızca modüllerin adreslerini içermesine neden olur.

Yukarıdaki örnekte, diğer adların başka bir metnin yanında olsalar bile değiştirildiğinden emin olmak için ${ } (Diğer Ad Yorumlayıcı)belirtecikullanılır. Komut bu belirteci içermiyorsa, yer yanındaki açma parantezi diğer adın değiştirilmesini engeller. ${} belirtecinin .foreach ve gerçek diğer adlarda kullanılan değişkenler üzerinde çalıştığını unutmayın.

İşlem Listesini Yürüme

Aşağıdaki örnek, çekirdek modu işlem listesinde yol gösterir ve listedeki her girişin yürütülebilir adını görüntüler.

Bu örnek bir metin dosyası olarak depolanmalı ve $$>< (Betik Dosyasını Çalıştır) komutuyla yürütülmelidir. Bu komut dosyanın tamamını yükler, tüm satır başı dönüşlerini noktalı virgülle değiştirir ve sonuçta elde edilen bloğu yürütür. Bu komut, tüm programı tek bir satıra sıkıştırmak yerine birden çok satır ve girinti kullanarak okunabilir programlar yazmanızı sağlar.

Bu örnekte aşağıdaki özellikler gösterilmektedir:

  • $t 0, $t 1ve $t 2 sahte yazmaçlar bu programda değişken olarak kullanılır. Program ayrıca Procc ve $ImageNameadlı diğer adları da kullanır.

  • Bu program MASM ifade değerlendiricisini kullanır. Ancak @@c++( ) belirteci bir kez görünür. Bu belirteç, programın ifadeyi parantez içinde ayrıştırmak için C++ ifade değerlendiricisini kullanmasına neden olur. Bu kullanım, programın doğrudan C++ yapı belirteçlerini kullanmasını sağlar.

  • ? bayrağı r (Yazmaçlar) komutuyla kullanılır. Bu bayrak, sahte kayıt$t 2'ye türlenmiş değerler atar.

$$  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 Listesini Yürüme

Aşağıdaki örnek, kullanıcı modu LDR_DATA_TABLE_ENTRY listesinde yol gösterir ve her liste girdisinin temel adresini ve tam yolunu görüntüler.

Yukarıdaki örnekte olduğu gibi, bu program da bir dosyaya kaydedilmeli ve $$>< (Betik Dosyasını Çalıştır) komutuyla yürütülmelidir.

Bu örnekte aşağıdaki özellikler gösterilmektedir:

  • Bu program MASM ifade değerlendiricisini kullanır. Ancak iki yerde @@c++( ) belirteci görüntülenir. Bu belirteç, programın ifadeyi parantez içinde ayrıştırmak için C++ ifade değerlendiricisini kullanmasına neden olur. Bu kullanım, programın doğrudan C++ yapı belirteçlerini kullanmasını sağlar.

  • ? bayrağı r (Yazmaçlar) komutuyla kullanılır. Bu bayrak, $t 0 ve $t 1sahte kayıtlara türlenmiş değerler atar. Döngünün gövdesinde, $t 1 ntdll!_LDR_DATA_TABLE_ENTRY\* türüne sahiptir, böylece program doğrudan üye başvuruları yapabilir.

  • Bu programda $Base ve $Mod kullanıcı tarafından adlandırılmış diğer adlar kullanılır. Dolar işaretleri, bu diğer adların daha önce geçerli hata ayıklayıcı oturumunda kullanılma olasılığını azaltır. Dolar işaretleri gerekli değildir. ${/v: } belirteci diğer adı tam anlamıyla yorumlayarak betik çalıştırılmadan önce tanımlanmışsa değiştirilmesini önler. Blok kullanılmadan önce diğer ad tanımlarını önlemek için bu belirteci herhangi bir blokla birlikte de kullanabilirsiniz.

  • ek bir diğer ad değiştirme adımı eklemek için .block belirteci kullanılır. Diğer ad değiştirme, yüklendiğinde betiğin tamamı için bir kez ve her blok girildiğinde bir kez gerçekleşir. .block belirteci ve küme ayraçları olmadan, .echo komutu önceki satırlarda atanan $Mod ve $Base diğer adlarının değerlerini almaz.

$$ 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}
}