Этот раздел предназначен для описания различных трюков WinDbg. Некоторые их них полезны, некоторые очень полезны. Большинство я использую при динамическом анализе различных руткитов, однако, не стоит забывать о том, что WinDbg можно использовать как дебаггер приложений пользовательского режима. Сам дебаггер содержит громадное количество команд, но используется очень малая их часть. Поэтому будем считать, что этот раздел я пишу сам для себя как справочник, чтобы не забыть. Данная страница будет пополняться по мере того, как я вспомню о том, что сюда надо написать :) Повествование будет вестись в виде вопросов и ответов. И когда-нибудь я разобью все это на подразделы, но не сейчас (это предложение исчезнет в случае реализации).
В: Как правильно прописать путь до символов от Microsoft?
О: Находясь в WinDbg нажмите Ctrl-S и вставьте туда c:\symserver;SRV*c:\symserver*http://msdl.microsoft.com/download/symbols
В: Чтобы проверить что-нибудь очень быстро, например, какое-либо смещение или получить недокументированную структуру приходится запускать виртуальную машину, а потом WinDbg. Можно как-нибудь быстрее?
О: Да. Запоминайте: windbg.exe, Ctrl-K, Local, Enter. Вы запустили WinDbg локально на своей реальной машине. Учтите, что структуры будут верны для вашей версии операционной системы. В Windows Vista необходимо предварительно выполнить команду bcdedit -debug on из cmd, запущенного под администратором и перегрузиться.
В: Можно ли создать дамп-файл не уводя машину в BSOD?
О: Можно. Для этого необходимо использовать команду .dump. Например, чтобы создать дамп-файл памяти ядра необходимо выполнить .dump /f c:\kernel.dmp. Кстати, если вы собираетесь делать это по COM-порту (или виртуальному pipe-порту в виртуальной машине), то приготовьтесь ждать, очень долго ждать.
В: Как записать в файл произвольный фрагмент памяти?
О: Сделать это можно командой .writemem. Например, .writemem c:\dumpnt.exe 0x804d7000 L?20d000. Знак вопроса необходим для того, чтобы WinDbg не проверял размер записываемых данных.
В: А записать в память из файла можно?
О: Используйте команду .readmem.
В: Как искать и находить в памяти строчку или определенную последовательность байт?
О: Это можно сделать с помощью команды s. Для поиска ANSI-строки необходимо использовать ключ -a, для UNICODE-строки -u:
lkd> s -a nt L?20d000 «PAGE»
804d72f0 50 41 47 45 00 00 00 00-ef f8 0d 00 00 20 09 00 PAGE……… ..
804d7318 50 41 47 45 4c 4b 00 00-10 e5 00 00 00 20 17 00 PAGELK……. ..
804d7340 50 41 47 45 56 52 46 59-a6 ea 00 00 00 10 18 00 PAGEVRFY……..
804d7368 50 41 47 45 57 4d 49 00-ff 16 00 00 00 00 19 00 PAGEWMI………
804d7390 50 41 47 45 4b 44 00 00-93 3d 00 00 00 20 19 00 PAGEKD…=… ..
804d73b8 50 41 47 45 53 50 45 43-21 0e 00 00 00 60 19 00 PAGESPEC!….`..
804d73e0 50 41 47 45 48 44 4c 53-b8 1d 00 00 00 70 19 00 PAGEHDLS…..p..
804d7430 50 41 47 45 44 41 54 41-b8 15 00 00 00 50 1a 00 PAGEDATA…..P..
804d7458 50 41 47 45 43 4f 4e 53-40 30 00 00 00 70 1a 00 PAGECONS@0…p..
804d7480 50 41 47 45 4b 44 00 00-21 c0 00 00 00 b0 1a 00 PAGEKD..!…….
804d74a8 50 41 47 45 43 4f 4e 53-8c 01 00 00 00 80 1b 00 PAGECONS……..
804d74d0 50 41 47 45 4c 4b 43 4f-88 00 00 00 00 90 1b 00 PAGELKCO……..
804d74f8 50 41 47 45 56 52 46 43-49 34 00 00 00 a0 1b 00 PAGEVRFCI4……
804d7520 50 41 47 45 56 52 46 44-48 06 00 00 00 e0 1b 00 PAGEVRFDH…….
804f285f 50 41 47 45 57 68 00 10-00 00 53 e8 51 3a 05 00 PAGEWh….S.Q:..
804f3936 50 41 47 45 68 00 10 00-00 53 8b f8 e8 79 29 05 PAGEh….S…y).
805ac98b 50 41 47 45 74 50 3d 2e-65 64 61 74 49 3d 49 4e PAGEtP=.edatI=IN
805adba0 50 41 47 45 74 19 81 f9-2e 65 64 61 74 11 85 c0 PAGEt….edat…
806c3548 50 41 47 45 5f 46 41 55-4c 54 5f 57 49 54 48 5f PAGE_FAULT_WITH_
806c35df 50 41 47 45 53 5f 41 56-41 49 4c 41 42 4c 45 0d PAGES_AVAILABLE.
806c362c 50 41 47 45 5f 46 41 55-4c 54 5f 49 4e 5f 4e 4f PAGE_FAULT_IN_NO
806c363d 50 41 47 45 44 5f 41 52-45 41 0d 0a 00 00 00 18 PAGED_AREA……
806c3b53 50 41 47 45 53 0d 0a 00-00 20 00 00 00 4b 45 52 PAGES…. …KER
806c3b6f 50 41 47 45 5f 45 52 52-4f 52 0d 0a 00 18 00 00 PAGE_ERROR……
806c3bce 50 41 47 45 5f 45 52 52-4f 52 0d 0a 00 00 10 01 PAGE_ERROR……
806c51f7 50 41 47 45 53 5f 49 4e-5f 50 52 4f 43 45 53 53 PAGES_IN_PROCESS
Для поиска последовательности байт необходимо использовать ключ -b:
lkd> s -b nt L?20d000 8b ff 55 8b ec 33 c0 50 50 50 ff 75 30
80579084 8b ff 55 8b ec 33 c0 50-50 50 ff 75 30 ff 75 2c ..U..3.PPP.u0.u,
В: Как посмотреть структуру, чтобы раскрывались входящие в нее структуры?
О: Необходимо использовать команду dt с ключом -r[глубина рекурсии] (в примере я использовал значение 2, хотя обычно хватает и 1):
lkd> !object \Driver\beep Object: 88c87c28 Type: (84d902c0) Driver ObjectHeader: 88c87c10 (old version) HandleCount: 0 PointerCount: 3 Directory Object: 8b675718 Name: Beep lkd> dt nt!_DRIVER_OBJECT 88c87c28 -r2 +0x000 Type : 4 +0x002 Size : 168 +0x004 DeviceObject : 0x88d6f990 _DEVICE_OBJECT +0x000 Type : 3 +0x002 Size : 0x110 +0x004 ReferenceCount : 0 +0x008 DriverObject : 0x88c87c28 _DRIVER_OBJECT +0x000 Type : 4 +0x002 Size : 168 +0x004 DeviceObject : 0x88d6f990 _DEVICE_OBJECT +0x008 Flags : 0x12 +0x00c DriverStart : 0x8ef22000 +0x010 DriverSize : 0x7000 +0x014 DriverSection : 0x88d6f480 +0x018 DriverExtension : 0x88c87cd0 _DRIVER_EXTENSION +0x01c DriverName : _UNICODE_STRING "\Driver\Beep" +0x024 HardwareDatabase : 0x82957e68 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM" +0x028 FastIoDispatch : (null) +0x02c DriverInit : 0x8ef26005 long Beep!GsDriverEntry+0 +0x030 DriverStartIo : 0x8ef23248 void Beep!BeepStartIo+0 +0x034 DriverUnload : 0x8ef23364 void Beep!BeepUnload+0 +0x038 MajorFunction : [28] 0x8ef23186 long Beep!BeepOpen+0 +0x00c NextDevice : (null) +0x010 AttachedDevice : (null) +0x014 CurrentIrp : (null) +0x018 Timer : (null) +0x01c Flags : 0x44 +0x020 Characteristics : 0x100 +0x024 Vpb : (null) +0x028 DeviceExtension : 0x88d6fa48 +0x02c DeviceType : 1 +0x030 StackSize : 1 '' +0x034 Queue : +0x000 ListEntry : _LIST_ENTRY [ 0x0 - 0x0 ] +0x000 Wcb : _WAIT_CONTEXT_BLOCK +0x05c AlignmentRequirement : 0 +0x060 DeviceQueue : _KDEVICE_QUEUE +0x000 Type : 20 +0x002 Size : 20 +0x004 DeviceListHead : _LIST_ENTRY [ 0x88d6f9f4 - 0x88d6f9f4 ] +0x00c Lock : 0 +0x010 Busy : 0 '' +0x074 Dpc : _KDPC +0x000 Type : 0x13 '' +0x001 Importance : 0x1 '' +0x002 Number : 0 +0x004 DpcListEntry : _LIST_ENTRY [ 0x0 - 0x0 ] +0x00c DeferredRoutine : 0x8ef2333c void Beep!BeepTimeOut+0 +0x010 DeferredContext : 0x88d6f990 +0x014 SystemArgument1 : (null) +0x018 SystemArgument2 : (null) +0x01c DpcData : (null) +0x094 ActiveThreadCount : 0 +0x098 SecurityDescriptor : 0x8b674548 +0x09c DeviceLock : _KEVENT +0x000 Header : _DISPATCHER_HEADER +0x0ac SectorSize : 0 +0x0ae Spare1 : 0 +0x0b0 DeviceObjectExtension : 0x88d6faa0 _DEVOBJ_EXTENSION +0x000 Type : 13 +0x002 Size : 0 +0x004 DeviceObject : 0x88d6f990 _DEVICE_OBJECT +0x008 PowerFlags : 0 +0x00c Dope : (null) +0x010 ExtensionFlags : 0x800 +0x014 DeviceNode : (null) +0x018 AttachedTo : (null) +0x01c StartIoCount : 0 +0x020 StartIoKey : 0 +0x024 StartIoFlags : 0 +0x028 Vpb : (null) +0x02c DependentList : _LIST_ENTRY [ 0x88d6facc - 0x88d6facc ] +0x034 ProviderList : _LIST_ENTRY [ 0x88d6fad4 - 0x88d6fad4 ] +0x0b4 Reserved : (null) +0x008 Flags : 0x12 +0x00c DriverStart : 0x8ef22000 +0x010 DriverSize : 0x7000 +0x014 DriverSection : 0x88d6f480 +0x018 DriverExtension : 0x88c87cd0 _DRIVER_EXTENSION +0x000 DriverObject : 0x88c87c28 _DRIVER_OBJECT +0x000 Type : 4 +0x002 Size : 168 +0x004 DeviceObject : 0x88d6f990 _DEVICE_OBJECT +0x008 Flags : 0x12 +0x00c DriverStart : 0x8ef22000 +0x010 DriverSize : 0x7000 +0x014 DriverSection : 0x88d6f480 +0x018 DriverExtension : 0x88c87cd0 _DRIVER_EXTENSION +0x01c DriverName : _UNICODE_STRING "\Driver\Beep" +0x024 HardwareDatabase : 0x82957e68 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM" +0x028 FastIoDispatch : (null) +0x02c DriverInit : 0x8ef26005 long Beep!GsDriverEntry+0 +0x030 DriverStartIo : 0x8ef23248 void Beep!BeepStartIo+0 +0x034 DriverUnload : 0x8ef23364 void Beep!BeepUnload+0 +0x038 MajorFunction : [28] 0x8ef23186 long Beep!BeepOpen+0 +0x004 AddDevice : (null) +0x008 Count : 0 +0x00c ServiceKeyName : _UNICODE_STRING "Beep" +0x000 Length : 8 +0x002 MaximumLength : 0xa +0x004 Buffer : 0x88c70640 "Beep" +0x014 ClientDriverExtension : (null) +0x018 FsFilterCallbacks : (null) +0x01c DriverName : _UNICODE_STRING "\Driver\Beep" +0x000 Length : 0x18 +0x002 MaximumLength : 0x18 +0x004 Buffer : 0x88c53368 "\Driver\Beep" +0x024 HardwareDatabase : 0x82957e68 _UNICODE_STRING "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM" +0x000 Length : 0x5a +0x002 MaximumLength : 0x5c +0x004 Buffer : 0x8286b760 "\REGISTRY\MACHINE\HARDWARE\DESCRIPTION\SYSTEM" +0x028 FastIoDispatch : (null) +0x02c DriverInit : 0x8ef26005 long Beep!GsDriverEntry+0 +0x030 DriverStartIo : 0x8ef23248 void Beep!BeepStartIo+0 +0x034 DriverUnload : 0x8ef23364 void Beep!BeepUnload+0 +0x038 MajorFunction : [28] 0x8ef23186 long Beep!BeepOpen+0
В: Как в структуре посмотреть какую-либо входящую в нее структуру отдельно?
О: Для просмотра структур используется команда dt. Поле нужно указывать после имени модуля и названия самой структуры:
lkd> dt nt!_OBJECT_TYPE poi(PsProcessType) TypeInfo.
+0×060 TypeInfo :
+0×000 Length : 0x4c
+0×002 UseDefaultObject : 0 »
+0×003 CaseInsensitive : 0 »
+0×004 InvalidAttributes : 0xb0
+0×008 GenericMapping : _GENERIC_MAPPING
+0×018 ValidAccessMask : 0x1f0fff
+0x01c SecurityRequired : 0×1 »
+0x01d MaintainHandleCount : 0 »
+0x01e MaintainTypeList : 0 »
+0×020 PoolType : 0 ( NonPagedPool )
+0×024 DefaultPagedPoolCharge : 0×1000
+0×028 DefaultNonPagedPoolCharge : 0x2a8
+0x02c DumpProcedure : (null)
+0×030 OpenProcedure : (null)
+0×034 CloseProcedure : (null)
+0×038 DeleteProcedure : 0x8094bb7a void nt!PspProcessDelete+0
+0x03c ParseProcedure : (null)
+0×040 SecurityProcedure : 0x809732e4 long nt!SeDefaultObjectMethod+0
+0×044 QueryNameProcedure : (null)
+0×048 OkayToCloseProcedure : (null)
В: А можно как-нибудь разыменовывать указатель?
О: Да, используйте команду poi(см. выше).
В: Для WinDbg есть различные дополнения. Как ими управлять?
О: Все очень просто. Для того, чтобы посмотреть список загруженных дополнений воспользуйтесь командой .chain. Для выгрузки и загрузки используйте .unload и .load соответственно.
В: Как во время отладки в режиме ядра загрузить символы пользовательского пространства?
О: Используйте .reload /user. Также используйте эту команду, если хотите увидеть стэк вызовов (k) в пользовательском пространстве текущего потока.
В: Можно как-нибудь искать MZ/PE модули в памяти по PE-заголовку?
О: Для поиска можно воспользоваться командой s, но проще использовать замечательную команду .imgscan. Модуль она не всегда определяет, да в большинстве случаев это и не нужно.
lkd> .imgscan /r poi(MmSystemRangeStart) L10000000
MZ at 8016a000 – size 13900
MZ at 802c7000 – size d000
MZ at 8032c000 – size 8c600
MZ at 8051f000 – size b000
Name:
MZ at 80573000 – size 11000
MZ at 80800000 – size 25c000
Name: ntoskrnl.exe
MZ at 80a5c000 – size 2c000
Name: HAL.dll
MZ at 815e8000 – size 7400
MZ at 81637000 – size 2f000
MZ at 8171d000 – size 38000
MZ at 81878000 – size ff000
MZ at 819f5000 – size 26000
ReadVirtual: 819effa8 not properly sign extended
ReadVirtual: 819effa9 not properly sign extended
Name:MZ at 8a806000 – size a000
MZ at 8a814000 – size ad000
Name: MZђ
В: Как получить детальную информацию о модуле, его заголовках, секциях и т.д. по его адресу?
О: Есть две замечательные команды: !lmi и !dh. Рекомендую их использовать именно в таком порядке.
lkd> ? nt
Evaluate expression: -2107363328 = 82643000
lkd> !lmi 82643000
Loaded Module Info: [82643000]
Module: ntkrpamp
Base Address: 82643000
Image Name: ntkrpamp.exe
Machine Type: 332 (I386)
Time Stamp: 4a77feb3 Tue Aug 04 13:26:11 2009
Size: 3b9000
CheckSum: 370777
Characteristics: 122 perf
Debug Data Dirs: Type Size VA Pointer
CODEVIEW 25, ebf18, eb718 RSDS – GUID: {143D55DD-4AC9-42A4-93AC-D9DF136B9EF5}
Age: 2, Pdb: ntkrpamp.pdb
CLSID 4, ebf14, eb714 [Data not mapped]
Image Type: MEMORY – Image read successfully from loaded memory.
Symbol Type: PDB – Symbols loaded successfully from symbol server.
c:\symserver\ntkrpamp.pdb\143D55DD4AC942A493ACD9DF136B9EF52\ntkrpamp.pdb
Load Report: public symbols , not source indexed
c:\symserver\ntkrpamp.pdb\143D55DD4AC942A493ACD9DF136B9EF52\ntkrpamp.pdb
Команда !dh показывает более детальную информацию об образе со всеми заголовками и т.д.
lkd> !dh 82643000
File Type: EXECUTABLE IMAGE
FILE HEADER VALUES
14C machine (i386)
16 number of sections
4A77FEB3 time date stamp Tue Aug 04 13:26:11 20090 file pointer to symbol table
0 number of symbols
E0 size of optional header
122 characteristics
Executable
App can handle >2gb addresses
32 bit word machineOPTIONAL HEADER VALUES
10B magic #
8.00 linker version
2EFA00 size of code
BB200 size of initialized data
3600 size of uninitialized data
EC4B0 address of entry point
1000 base of code
—– new —–
00400000 image base
1000 section alignment
200 file alignment
1 subsystem (Native)
6.00 operating system version
6.00 image version
6.00 subsystem version
3B9000 size of image
800 size of headers
370777 checksum
00040000 size of stack reserve
00002000 size of stack commit
00100000 size of heap reserve
00001000 size of heap commit
0 DLL characteristics
2FF000 [ F674] address [size] of Export Directory
36A348 [ 8C] address [size] of Import Directory
36C000 [ 34170] address [size] of Resource Directory
0 [ 0] address [size] of Exception Directory
36D400 [ 1C48] address [size] of Security Directory
3A1000 [ 17B28] address [size] of Base Relocation Directory
EBEDC [ 38] address [size] of Debug Directory
0 [ 0] address [size] of Description Directory
0 [ 0] address [size] of Special Directory
0 [ 0] address [size] of Thread Storage Directory
C0D20 [ 40] address [size] of Load Configuration Directory
0 [ 0] address [size] of Bound Import Directory
1000 [ 264] address [size] of Import Address Table Directory
0 [ 0] address [size] of Delay Import Directory
0 [ 0] address [size] of COR20 Header Directory
0 [ 0] address [size] of Reserved DirectorySECTION HEADER #1
.text name
EAF3D virtual size
1000 virtual address
EB000 size of raw data
800 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
68000020 flags
Code
Not Paged
(no align specified)
Execute ReadDebug Directories(2)
Type Size Address Pointer
cv 25 ebf18 eb718 Format: RSDS, guid, 2, ntkrpamp.pdb
( 10) 4 ebf14 eb714SECTION HEADER #2
_PAGELK name
861 virtual size
EC000 virtual address
A00 size of raw data
EB800 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
68000020 flags
Code
Not Paged
(no align specified)
Execute ReadSECTION HEADER #3
POOLCODE name
19DB virtual size
ED000 virtual address
1A00 size of raw data
EC200 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
68000020 flags
Code
Not Paged
(no align specified)
Execute ReadSECTION HEADER #4
POOLMI name
BAD virtual size
EF000 virtual address
C00 size of raw data
EDC00 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
68000020 flags
Code
Not Paged
(no align specified)
Execute ReadSECTION HEADER #5
.data name
4638C virtual size
F0000 virtual address
8800 size of raw data
EE800 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
C8000040 flags
Initialized Data
Not Paged
(no align specified)
Read WriteSECTION HEADER #6
ALMOSTRO name
C9C virtual size
137000 virtual address
C00 size of raw data
F7000 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
C8000040 flags
Initialized Data
Not Paged
(no align specified)
Read WriteSECTION HEADER #7
SPINLOCK name
E84 virtual size
138000 virtual address
0 size of raw data
0 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
C8000080 flags
Uninitialized Data
Not Paged
(no align specified)
Read WriteSECTION HEADER #8
PAGE name
18EB06 virtual size
139000 virtual address
18EC00 size of raw data
F7C00 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
60000020 flags
Code
(no align specified)
Execute ReadSECTION HEADER #9
PAGELK name
14412 virtual size
2C8000 virtual address
14600 size of raw data
286800 file pointer to raw data
8290B000 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
60000020 flags
Code
(no align specified)
Execute ReadSECTION HEADER #A
PAGEKD name
4419 virtual size
2DD000 virtual address
4600 size of raw data
29AE00 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
60000020 flags
Code
(no align specified)
Execute ReadSECTION HEADER #B
PAGEVRFY name
16D9B virtual size
2E2000 virtual address
16E00 size of raw data
29F400 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
60000020 flags
Code
(no align specified)
Execute ReadSECTION HEADER #C
PAGEHDLS name
1D8A virtual size
2F9000 virtual address
1E00 size of raw data
2B6200 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
60000020 flags
Code
(no align specified)
Execute ReadSECTION HEADER #D
PAGEBSS name
48 virtual size
2FB000 virtual address
0 size of raw data
0 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
C0000080 flags
Uninitialized Data
(no align specified)
Read WriteSECTION HEADER #E
PAGEVRFB name
23C0 virtual size
2FC000 virtual address
0 size of raw data
0 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
C0000080 flags
Uninitialized Data
(no align specified)
Read WriteSECTION HEADER #F
.edata name
F674 virtual size
2FF000 virtual address
F800 size of raw data
2B8000 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
40000040 flags
Initialized Data
(no align specified)
Read OnlySECTION HEADER #10
PAGEDATA name
802C virtual size
30F000 virtual address
8200 size of raw data
2C7800 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
C0000040 flags
Initialized Data
(no align specified)
Read WriteSECTION HEADER #11
PAGEKDD name
C015 virtual size
318000 virtual address
C200 size of raw data
2CFA00 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
C0000040 flags
Initialized Data
(no align specified)
Read WriteSECTION HEADER #12
PAGEVRFC name
3608 virtual size
325000 virtual address
3600 size of raw data
2DBC00 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
40000040 flags
Initialized Data
(no align specified)
Read OnlySECTION HEADER #13
PAGEVRFD name
CE8 virtual size
329000 virtual address
E00 size of raw data
2DF200 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
C0000040 flags
Initialized Data
(no align specified)
Read WriteSECTION HEADER #14
INIT name
41436 virtual size
32A000 virtual address
41600 size of raw data
2E0000 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
E2000020 flags
Code
Discardable
(no align specified)
Execute Read WriteSECTION HEADER #15
.rsrc name
34170 virtual size
36C000 virtual address
34200 size of raw data
321600 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
40000040 flags
Initialized Data
(no align specified)
Read OnlySECTION HEADER #16
.reloc name
17B28 virtual size
3A1000 virtual address
17C00 size of raw data
355800 file pointer to raw data
0 file pointer to relocation table
0 file pointer to line numbers
0 number of relocations
0 number of line numbers
42000040 flags
Initialized Data
Discardable
(no align specified)
Read Only
В: Как получить информацию о запущенных процессах в системе?
О: Для этого необходимо использовать команду !process. При отладке в пользовательском режиме необходимо использовать команду .tlist.
Перечислим все процессы в системе !process 0 0:
lkd> !process 0 0
**** NT ACTIVE PROCESS DUMP ****
PROCESS 8494ed90 SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000
DirBase: 00122000 ObjectTable: 8b201e88 HandleCount: 3367.
Image: SystemPROCESS 889c5cf8 SessionId: none Cid: 01f4 Peb: 7ffdd000 ParentCid: 0004
DirBase: bbc26020 ObjectTable: 8b2f5038 HandleCount: 28.
Image: smss.exePROCESS 87f27d90 SessionId: 0 Cid: 027c Peb: 7ffd7000 ParentCid: 0270
DirBase: bbc26060 ObjectTable: 96a266b0 HandleCount: 796.
Image: csrss.exePROCESS 88dd4d90 SessionId: 0 Cid: 02b0 Peb: 7ffdf000 ParentCid: 0270
DirBase: bbc260a0 ObjectTable: 96bdff18 HandleCount: 106.
Image: wininit.exePROCESS 88bab520 SessionId: 1 Cid: 02b8 Peb: 7ffdf000 ParentCid: 02a8
DirBase: bbc26040 ObjectTable: 96bf6050 HandleCount: 744.
Image: csrss.exe
В: Как переключиться в контекст конкретного процесса?
О: Используйте команду .process (не путайте с командой !process).
lkd> .process
Implicit process is now 85330020
lkd> .process /r/p 87f27d90
Implicit process is now 87f27d90
Loading User Symbols
…………..
В: А как переключиться «регистровый» контекст произвольного потока?
О: Во время отладки в ядре вам доступны те регистры, которые связаны с текущим потоком, который вы отлаживаете. Используйте команду .thread для переключения в «регистровый» контекст другого потока.
В: Какие есть команды для получения информации об объектах?
О: Я перечислю самые полезные на мой взгляд: !object, !devobj, !devstack, !drvobj
Команда !object показывает информацию о системном объекте. Например так:
lkd> !object 0x860ad988
Object: 860ad988 Type: (84d902c0) Driver
ObjectHeader: 860ad970 (old version)
HandleCount: 0 PointerCount: 5
Directory Object: 8b671350 Name: atapi
Или так:
lkd> !object \Device\Harddisk0
Object: 8d2d1c50 Type: (84d491a0) Directory
ObjectHeader: 8d2d1c38 (old version)
HandleCount: 1 PointerCount: 6
Directory Object: 8b6133a8 Name: Harddisk0Hash Address Type Name
—- ——- —- —-
21 86b0eac8 Device DR0
33 8d2e29f8 SymbolicLink Partition0
34 8b673e40 SymbolicLink Partition1
35 8b671e30 SymbolicLink Partition2
Команда !devobj показывает детальную информацию о структуре DEVICE_OBJECT:
lkd> !devobj \Device\Harddisk0\DR0
Device object (86b0eac8) is for:
DR0 \Driver\disk DriverObject 86674718
Current Irp 00000000 RefCount 0 Type 00000007 Flags 00000050
Vpb 86674198 Dacl 8b735a6c DevExt 86b0eb80 DevObjExt 86b0efc0 Dope 86674130
ExtensionFlags (0×00000800)
Unknown flags 0×00000800
AttachedDevice (Upper) 86b0e7b8 \Driver\partmgr
AttachedTo (Lower) 860ad2d0 \Driver\ACPI
Device queue is not busy.
А команда !devstack показывает в удобном виде стек устройства:
lkd> !devstack 860ad2d0
!DevObj !DrvObj !DevExt ObjectName
86b0e7b8 \Driver\partmgr 86b0e870
86b0eac8 \Driver\disk 86b0eb80 DR0
> 860ad2d0 \Driver\ACPI 8519b6b8
85b66028 \Driver\iaStor 85b660e0 IAAStorageDevice-0
!DevNode 85b2f280 :
DeviceInst is «IDE\DiskST9320421AS_____________________________SD13____\4″30b36239″0″0.0.0″
ServiceName is «disk»
В свою очередь, команда !drvobj покажет детальную информацию о структуре DRIVER_OBJECT:
lkd> .reload /f classpnp.sys
lkd> !drvobj 86674718 2
Driver object (86674718) is for:
\Driver\disk
DriverEntry: 8afd0bbc disk!GsDriverEntry
DriverStartIo: 00000000
DriverUnload: 8afedab2 CLASSPNP!ClassUnload
AddDevice: 8afec4e9 CLASSPNP!ClassAddDeviceDispatch routines:
[00] IRP_MJ_CREATE 8afd9d24 CLASSPNP!ClassGlobalDispatch
[01] IRP_MJ_CREATE_NAMED_PIPE 8266b9d2 nt!IopInvalidDeviceRequest
[02] IRP_MJ_CLOSE 8afd9d24 CLASSPNP!ClassGlobalDispatch
[03] IRP_MJ_READ 8afd9d24 CLASSPNP!ClassGlobalDispatch
[04] IRP_MJ_WRITE 8afd9d24 CLASSPNP!ClassGlobalDispatch
[05] IRP_MJ_QUERY_INFORMATION 8266b9d2 nt!IopInvalidDeviceRequest
[06] IRP_MJ_SET_INFORMATION 8266b9d2 nt!IopInvalidDeviceRequest
[07] IRP_MJ_QUERY_EA 8266b9d2 nt!IopInvalidDeviceRequest
[08] IRP_MJ_SET_EA 8266b9d2 nt!IopInvalidDeviceRequest
[09] IRP_MJ_FLUSH_BUFFERS 8afd9d24 CLASSPNP!ClassGlobalDispatch
[0a] IRP_MJ_QUERY_VOLUME_INFORMATION 8266b9d2 nt!IopInvalidDeviceRequest
[0b] IRP_MJ_SET_VOLUME_INFORMATION 8266b9d2 nt!IopInvalidDeviceRequest
[0c] IRP_MJ_DIRECTORY_CONTROL 8266b9d2 nt!IopInvalidDeviceRequest
[0d] IRP_MJ_FILE_SYSTEM_CONTROL 8266b9d2 nt!IopInvalidDeviceRequest
[0e] IRP_MJ_DEVICE_CONTROL 8afd9d24 CLASSPNP!ClassGlobalDispatch
[0f] IRP_MJ_INTERNAL_DEVICE_CONTROL 8afd9d24 CLASSPNP!ClassGlobalDispatch
[10] IRP_MJ_SHUTDOWN 8afd9d24 CLASSPNP!ClassGlobalDispatch
[11] IRP_MJ_LOCK_CONTROL 8266b9d2 nt!IopInvalidDeviceRequest
[12] IRP_MJ_CLEANUP 8266b9d2 nt!IopInvalidDeviceRequest
[13] IRP_MJ_CREATE_MAILSLOT 8266b9d2 nt!IopInvalidDeviceRequest
[14] IRP_MJ_QUERY_SECURITY 8266b9d2 nt!IopInvalidDeviceRequest
[15] IRP_MJ_SET_SECURITY 8266b9d2 nt!IopInvalidDeviceRequest
[16] IRP_MJ_POWER 8afd9d24 CLASSPNP!ClassGlobalDispatch
[17] IRP_MJ_SYSTEM_CONTROL 8afd9d24 CLASSPNP!ClassGlobalDispatch
[18] IRP_MJ_DEVICE_CHANGE 8266b9d2 nt!IopInvalidDeviceRequest
[19] IRP_MJ_QUERY_QUOTA 8266b9d2 nt!IopInvalidDeviceRequest
[1a] IRP_MJ_SET_QUOTA 8266b9d2 nt!IopInvalidDeviceRequest
[1b] IRP_MJ_PNP 8afd9d24 CLASSPNP!ClassGlobalDispatch
В: Каким образом запускать скрипты, которые поддерживает отладчик?
О: Для начала сохраните скрипт в текстовом файле. Потом используйте команды:
$< Filename
$>< Filename
$$< Filename
$$>< Filename
$$>a< Filename [arg1 arg2 arg3 ... ]
Разницу в командах смотрите в документации.
В: Какие есть команды для того, чтобы посмотреть структуры PEB и TEB?
О: Есть такие команды. Это !peb и !teb.
kd> !process 81631158
PROCESS 81631158 SessionId: 0 Cid: 0790 Peb: 7ffd5000 ParentCid: 0750
DirBase: 062c0200 ObjectTable: e1980568 HandleCount: 28.
Image: calc.exe
VadRoot 815a9ea0 Vads 51 Clone 0 Private 119. Modified 0. Locked 0.
DeviceMap e19b5d88
Token e1b6d818
ElapsedTime 00:00:15.484
UserTime 00:00:00.015
KernelTime 00:00:00.156
QuotaPoolUsage[PagedPool] 57956
QuotaPoolUsage[NonPagedPool] 2040
Working Set Sizes (now,min,max) (641, 50, 345) (2564KB, 200KB, 1380KB)
PeakWorkingSetSize 641
VirtualSize 27 Mb
PeakVirtualSize 34 Mb
PageFaultCount 664
MemoryPriority BACKGROUND
BasePriority 8
CommitCharge 194THREAD 815aa228 Cid 0790.0794 Teb: 7ffdf000 Win32Thread: e1b75490 WAIT: (WrUserRequest) UserMode Non-Alertable
8146d020 SynchronizationEvent
Not impersonating
DeviceMap e19b5d88
Owning Process 0 Image:
Attached Process 81631158 Image: calc.exe
Wait Start TickCount 4717 Ticks: 13 (0:00:00:00.203)
Context Switch Count 142 LargeStack
UserTime 00:00:00.000
KernelTime 00:00:00.203
Win32 Start Address calc!WinMainCRTStartup (0×01012475)
Start Address kernel32!BaseProcessStartThunk (0x7c8106f5)
Stack Init f801d000 Current f801cc20 Base f801d000 Limit f8018000 Call 0
Priority 12 BasePriority 8 PriorityDecrement 2 DecrementCount 16
ChildEBP RetAddr
f801cc38 80500cd6 nt!KiSwapContext+0x2e (FPO: [Uses EBP] [0,0,4])
f801cc44 804f9d62 nt!KiSwapThread+0×46 (FPO: [0,0,0])
f801cc6c bf802f52 nt!KeWaitForSingleObject+0x1c2 (FPO: [5,5,4])
WARNING: Frame IP not in any known module. Following frames may be wrong.
f801cd4c 8053d638 0xbf802f52
f801cd4c 0007fee8 nt!KiFastCallEntry+0xf8 (FPO: [0,0] TrapFrame-EDITED @ f801ccec)
f801cd64 00000000 0x7fee8
kd> .process /r/p 81631158
Implicit process is now 81631158
.cache forcedecodeuser done
Loading User Symbols
…………………
kd> !peb
PEB at 7ffd5000
InheritedAddressSpace: No
ReadImageFileExecOptions: No
BeingDebugged: No
ImageBaseAddress: 01000000
Ldr 001a1e90
Ldr.Initialized: Yes
Ldr.InInitializationOrderModuleList: 001a1f28 . 001a2bd0
Ldr.InLoadOrderModuleList: 001a1ec0 . 001a2bc0
Ldr.InMemoryOrderModuleList: 001a1ec8 . 001a2bc8
Base TimeStamp Module
1000000 3b7d8410 Aug 18 00:52:32 2001 C:\WINDOWS\system32\calc.EXE
7c900000 4802a12c Apr 14 04:11:24 2008 C:\WINDOWS\system32\ntdll.dll
7c800000 4802a12c Apr 14 04:11:24 2008 C:\WINDOWS\system32\kernel32.dll
7c9c0000 4802a111 Apr 14 04:10:57 2008 C:\WINDOWS\system32\SHELL32.dll
77dd0000 4802a0b2 Apr 14 04:09:22 2008 C:\WINDOWS\system32\ADVAPI32.dll
77e70000 4802a106 Apr 14 04:10:46 2008 C:\WINDOWS\system32\RPCRT4.dll
77fe0000 4802a11b Apr 14 04:11:07 2008 C:\WINDOWS\system32\Secur32.dll
77f10000 4802a0be Apr 14 04:09:34 2008 C:\WINDOWS\system32\GDI32.dll
7e410000 4802a11b Apr 14 04:11:07 2008 C:\WINDOWS\system32\USER32.dll
77c10000 4802a188 Apr 14 04:12:56 2008 C:\WINDOWS\system32\msvcrt.dll
77f60000 4802a116 Apr 14 04:11:02 2008 C:\WINDOWS\system32\SHLWAPI.dll
5cb70000 4802a114 Apr 14 04:11:00 2008 C:\WINDOWS\system32\ShimEng.dll
6f880000 4802a098 Apr 14 04:08:56 2008 C:\WINDOWS\AppPatch\AcGenral.DLL
76b40000 4802a13c Apr 14 04:11:40 2008 C:\WINDOWS\system32\WINMM.dll
774e0000 4802a111 Apr 14 04:10:57 2008 C:\WINDOWS\system32\ole32.dll
77120000 4802a112 Apr 14 04:10:58 2008 C:\WINDOWS\system32\OLEAUT32.dll
77be0000 4802a117 Apr 14 04:11:03 2008 C:\WINDOWS\system32\MSACM32.dll
77c00000 4802a11d Apr 14 04:11:09 2008 C:\WINDOWS\system32\VERSION.dll
769c0000 4802a11c Apr 14 04:11:08 2008 C:\WINDOWS\system32\USERENV.dll
5ad70000 4802a11e Apr 14 04:11:10 2008 C:\WINDOWS\system32\UxTheme.dll
773d0000 4802a094 Apr 14 04:08:52 2008 C:\WINDOWS\WinSxS\x86_Microsoft.Windows.Common-Controls_6595b64144ccf1df_6.0.2600.5512_x-ww_35d4ce83\comctl32.dll
SubSystemData: 00000000
ProcessHeap: 000a0000
ProcessParameters: 00020000
WindowTitle: ‘C:\WINDOWS\system32\calc.EXE’
ImageFile: ‘C:\WINDOWS\system32\calc.EXE’
CommandLine: ‘»C:\WINDOWS\system32\calc.EXE» ‘
DllPath: ‘C:\WINDOWS\system32;C:\WINDOWS\system32;C:\WINDOWS\system;C:\WINDOWS;.;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem’
Environment: 00010000
=::=::\
=C:=C:\
ALLUSERSPROFILE=C:\Documents and Settings\All Users
APPDATA=C:\Documents and Settings\sww\Application Data
CLIENTNAME=Console
CommonProgramFiles=C:\Program Files\Common Files
COMPUTERNAME=SWW-3DF7AD85928
ComSpec=C:\WINDOWS\system32\cmd.exe
FARHOME=C:\Far
FARLANG=English
FP_NO_HOST_CHECK=NO
HOMEDRIVE=C:
HOMEPATH=\Documents and Settings\sww
LOGONSERVER=\\SWW-3DF7AD85928
NUMBER_OF_PROCESSORS=1
OS=Windows_NT
Path=C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH
PROCESSOR_ARCHITECTURE=x86
PROCESSOR_IDENTIFIER=x86 Family 6 Model 23 Stepping 8, GenuineIntel
PROCESSOR_LEVEL=6
PROCESSOR_REVISION=1708
ProgramFiles=C:\Program Files
SESSIONNAME=Console
SystemDrive=C:
SystemRoot=C:\WINDOWS
TEMP=C:\DOCUME~1\sww\LOCALS~1\Temp
TMP=C:\DOCUME~1\sww\LOCALS~1\Temp
USERDOMAIN=SWW-3DF7AD85928
USERNAME=sww
USERPROFILE=C:\Documents and Settings\sww
windir=C:\WINDOWS
kd> !teb 7ffdf000
TEB at 7ffdf000
ExceptionList: 0007ff10
StackBase: 00080000
StackLimit: 0007d000
SubSystemTib: 00000000
FiberData: 00001e00
ArbitraryUserPointer: 00000000
Self: 7ffdf000
EnvironmentPointer: 00000000
ClientId: 00000790 . 00000794
RpcHandle: 00000000
Tls Storage: 00000000
PEB Address: 7ffd5000
LastErrorValue: 1309
LastStatusValue: c0000034
Count Owned Locks: 0
HardErrorMode: 0
Данные команды крайне полезны при анализе дампа. Не забывайте про них.
В: Как получить имя модуля по адресу внутри него?
О: Прочтите статью «Адрес модуля в WinDbg» и/или воспользуйтесь командой lma или предоставленным скриптом.
$$ pointer to modules list r $t0 = nt!PsLoadedModuleList .echo "Section Start End Name" .for ( r $t1 = poi(@$t0); (@$t1 != 0) & (@$t1 != @$t0); r $t1 = poi(@$t1) ) { r? $t2 = #CONTAINING_RECORD( @$t1, nt!_LDR_DATA_TABLE_ENTRY, InLoadOrderLinks ); as /x ${/v:$Section} @$t2 $$ Get image name into $DriverName as /msu ${/v:$DriverName} @@c++(&@$t2->BaseDllName) $$ Get image base into $Start as /x ${/v:$Start} @@c++(@$t2->DllBase) $$ Get image base + image size into $End as /x ${/v:$End} ( @@c++(@$t2->DllBase) + @@c++(@$t2->SizeOfImage) ) .block { .echo ${$Section}: ${$Start}: ${$End}: ${$DriverName} } ad ${/v:$End} ad ${/v:$Start} ad ${/v:$DriverName} ad ${/v:$Section} }
В: Что такое мэппинг драйверов в WinDbg и как этим пользоваться?
О: Читайте в отдельной статье.
В: А есть вообще полезные команды в WinDbg?
О: Конечно. Самая лучшая из них – .cls :)
Полезные скрипты при динамическом анализе руткитов (взято с разрешения авторов из статьи «Обнаружение руткитов режима ядра с помощью отладчика»).
Скрипт для перечисления некоторых колбеков ядра:
.echo Create Process Notifiers: $$ нотификаторы на создание процессов r $t0 = nt!PspCreateProcessNotifyRoutine $$ перебираем EX_CALLBACK элементы массива .for (r $t2 = 0; @$t2 < 8; r $t2 = @$t2 + 1) { $$ отбрасываем младшие 3 бита, $$ которые хранят количество ссылок на указатель r $t3 = @@c++((*(long *)(@$t0 + @$t2 * 4)) & 0xfffffff8); .if (@$t3) { $$ если указатель не равен нулю, $$ выводим поле Function из EX_CALLBACK_ROUTINE_BLOCK dps @@c++((long *)(@$t3 + 4)) L 1 } } .echo Create Thread Notifiers: $$ нотификаторы на создание потоков r $t0 = nt!PspCreateThreadNotifyRoutine .for (r $t2 = 0; @$t2 < 8; r $t2 = @$t2 + 1) { r $t3 = @@c++((*(long *)(@$t0 + @$t2 * 4)) & 0xfffffff8); .if (@$t3) { dps @@c++((long *)(@$t3 + 4)) L 1 } } .echo Load Image Notifiers: $$ нотификаторы на загрузку исполняемых образов r $t0 = nt!PspLoadImageNotifyRoutine .for (r $t2 = 0; @$t2 < 8; r $t2 = @$t2 + 1) { r $t3 = @@c++((*(long *)(@$t0 + @$t2 * 4)) & 0xfffffff8); .if (@$t3) { dps @@c++((long *)(@$t3 + 4)) L 1 } } .echo Registry Callbacks: $$ нотификаторы на события системного реестра r $t0 = nt!CmpCallBackVector .for (r $t2 = 0; @$t2 < 0x64; r $t2 = @$t2 + 1) { r $t3 = @@c++((*(long *)(@$t0 + @$t2 * 4)) & 0xfffffff8); .if (@$t3) { dps @@c++((long *)(@$t3 + 4)) L 1 } }
Скрипт, проверяющий ServiceTable существующих потоков в системе:
$$ указатель на список процессов r $t0 = nt!PsActiveProcessHead $$ перечисляем активные процессы .for (r $t1 = poi(@$t0); (@$t1 != 0) & (@$t1 != @$t0); r $t1 = poi(@$t1)) { r? $t2 = #CONTAINING_RECORD(@$t1, nt!_EPROCESS, ActiveProcessLinks); as /x ${/v:$Procc} @$t2 $$ Get image name into $ImageName. as /ma ${/v:$ImageName} @@c++(&@$t2->ImageFileName[0]) .block { .echo ${$Procc}: ${$ImageName} .echo Active threads: } $$ указатель на список активных потоков этого процесса r? $t3 = (nt!_LIST_ENTRY *)&@$t2->ThreadListHead; $$ перечисляем потоки .for (r $t4 = poi(@$t3); (@$t4 != 0) & (@$t4 != @$t3); r $t4 = poi(@$t4)) { r? $t5 = #CONTAINING_RECORD(@$t4, nt!_ETHREAD, ThreadListEntry) r? $t5 = (nt!_KTHREAD *)@$t5 $$ получаем значение KTHREAD::ServiceTable r $t6 = @@c++(@$t5->ServiceTable) r $t7 = nt!KeServiceDescriptorTable r $t8 = nt!KeServiceDescriptorTableShadow as /x ${/v:$Kthread} @$t5 as /x ${/v:$SDT} @$t6 .block { .echo ${$Kthread} ServiceTable = ${$SDT} } $$ проверяем значение .if ((@$t6 != @$t7) & (@$t6 != @$t8)) { .block { .echo !!! Changed value of KTHREAD::ServiceTable } } ad ${/v:$Kthread} ad ${/v:$SDT} } ad ${/v:$ImageName} ad ${/v:$Procc} }

присоединяйся
http://kdar.codeplex.com/
Интересный проект, спасибо. Как будет время я более подробно гляну скрипты, сдается мне, что там не все учитывается (на мой беглый взгляд).
Да, можно многое приделать. То, что там выложено – это труд пары-тройки вечеров, времени то маловато. Изначально писал ради статьи в блоге, прикола ради, но оказалось, что тема не такая уж и шуточная. А сейчас вообще появились грандиозные планы перевести движок на более удобный скрипт ( питон или луа – есть заготовка, выполняет в отладчике луа скрипт и дает ему простейший интерфейс, пока из двух функций – опять же время не дает третью приделать ) и вот тогда…. . А пока это все существует по программе «доказать невозможность искать руткиты по дампам ядра» :)
Вот и у Краша такая же идея – зафигачить в WinDbg питон, на котором уж всяко будет писать удобнее :) А по дампам ядра очень даже ищутся руткиты ядра.