Bagikan melalui


Contoh Program Perintah Debugger

Bagian berikut ini menjelaskan program perintah debugger.

Menggunakan Token .foreach

Contoh berikut menggunakan token .foreach untuk mencari nilai WORD 5a4d. Untuk setiap nilai 5a4d yang ditemukan, debugger menampilkan 8 nilai DWORD, dimulai dari alamat tempat DWORD 5a4d ditemukan.

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

Contoh berikut menggunakan token .foreach untuk mencari nilai WORD 5a4d. Untuk setiap nilai 5a4d yang ditemukan, debugger menampilkan 8 nilai DWORD, dimulai 4 byte sebelum alamat tempat DWORD 5a4d ditemukan.

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

Contoh berikut menampilkan nilai yang sama.

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

Catatan Jika Anda ingin beroperasi pada nama variabel di bagian OutCommands dari perintah, Anda harus menambahkan spasi setelah nama variabel. Misalnya, dalam contoh sebelumnya, ada ruang antara tempat variabel dan operator pengurangan.

Opsi -[1] bersama dengan perintah s (Search Memory) menyebabkan outputnya hanya menyertakan alamat yang ditemukannya, bukan nilai yang ditemukan di alamat tersebut.

Perintah berikut menampilkan informasi modul verbose untuk semua modul yang terletak di rentang memori dari 0x77000000 hingga 0x7F000000.

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

Opsi 1m bersama dengan perintah lm (List Loaded Modules) menyebabkan outputnya hanya menyertakan alamat modul, bukan deskripsi lengkap modul.

Contoh sebelumnya menggunakan token ${ } (Alias Interpreter) untuk memastikan alias diganti meskipun berada di samping teks lain. Jika perintah tidak menyertakan token ini, tanda kurung pembuka yang ada di sebelah mencegah penggantian alias. Perhatikan bahwa token ${} berfungsi pada variabel yang digunakan dalam .foreach dan pada alias benar.

Berjalan di Daftar Proses

Contoh berikut berjalan melalui daftar proses mode kernel dan menampilkan nama yang dapat dieksekusi untuk setiap entri dalam daftar.

Contoh ini harus disimpan sebagai file teks dan dijalankan dengan perintah $$>< (Jalankan File Skrip). Perintah ini memuat seluruh file, mengganti semua pengembalian pengangkutan dengan titik koma, dan menjalankan blok yang dihasilkan. Perintah ini memungkinkan Anda menulis program yang dapat dibaca dengan menggunakan beberapa baris dan indentasi, alih-alih harus menekan seluruh program ke satu baris.

Contoh ini mengilustrasikan fitur-fitur berikut:

  • Pseudo-register $t 0, $t 1, dan $t 2 digunakan sebagai variabel dalam program ini. Program ini juga menggunakan alias bernama Procc dan $ImageName.

  • Program ini menggunakan evaluator ekspresi MASM. Namun, token @@c++( ) muncul satu kali. Token ini menyebabkan program menggunakan evaluator ekspresi C++ untuk mengurai ekspresi dalam tanda kurung. Penggunaan ini memungkinkan program untuk menggunakan token struktur C++ secara langsung.

  • Bendera ? digunakan dengan perintah r (Registers ). Bendera ini menetapkan nilai yang ditik ke pseudo-register $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
}

Berjalan di Daftar LDR_DATA_TABLE_ENTRY

Contoh berikut berjalan melalui daftar LDR_DATA_TABLE_ENTRY mode pengguna dan menampilkan alamat dasar dan jalur lengkap setiap entri daftar.

Seperti contoh sebelumnya, program ini harus disimpan dalam file dan dijalankan dengan perintah $$>< (Jalankan File Skrip).

Contoh ini mengilustrasikan fitur-fitur berikut:

  • Program ini menggunakan evaluator ekspresi MASM. Namun, di dua tempat, token @@c++( ) muncul. Token ini menyebabkan program menggunakan evaluator ekspresi C++ untuk mengurai ekspresi dalam tanda kurung. Penggunaan ini memungkinkan program untuk menggunakan token struktur C++ secara langsung.

  • Bendera ? digunakan dengan perintah r (Registers ). Bendera ini menetapkan nilai yang ditik ke pseudo-registers $t 0 dan $t 1. Dalam isi perulangan, $t 1 memiliki tipe ntdll!_LDR_DATA_TABLE_ENTRY\*, sehingga program dapat membuat referensi anggota langsung.

  • Alias bernama pengguna $Base dan $Mod digunakan dalam program ini. Tanda dolar mengurangi kemungkinan bahwa alias ini telah digunakan sebelumnya dalam sesi debugger saat ini. Tanda-tanda dolar tidak diperlukan. Token ${/v: } menafsirkan alias secara harfiah, mencegahnya diganti jika ditentukan sebelum skrip dijalankan. Anda juga dapat menggunakan token ini bersama dengan blok apa pun untuk mencegah definisi alias sebelum blok tersebut digunakan.

  • Token .block digunakan untuk menambahkan langkah penggantian alias tambahan. Penggantian alias terjadi satu kali untuk seluruh skrip ketika dimuat dan satu kali ketika setiap blok dimasukkan. Tanpa token .block dan kurung kurawalnya, perintah .echo tidak menerima nilai alias $Mod dan $Base yang ditetapkan di baris sebelumnya.

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