1 dt命令:
dt _peb 直接显示
lkd> dt _peb nt!_PEB +0x000 InheritedAddressSpace : UChar +0x001 ReadImageFileExecOptions : UChar +0x002 BeingDebugged : UChar +0x003 SpareBool : UChar +0x004 Mutant : Ptr32 Void +0x008 ImageBaseAddress : Ptr32 Void ···················dt -b _peb 递归式显示
lkd> dt -b _peb nt!_PEB +0x000 InheritedAddressSpace : UChar +0x001 ReadImageFileExecOptions : UChar +0x002 BeingDebugged : UChar +0x003 SpareBool : UChar +0x004 Mutant : Ptr32 +0x008 ImageBaseAddress : Ptr32 +0x00c Ldr : Ptr32 +0x010 ProcessParameters : Ptr32 +0x014 SubSystemData : Ptr32 +0x018 ProcessHeap : Ptr32 +0x01c FastPebLock : Ptr32 +0x020 FastPebLockRoutine : Ptr32 +0x024 FastPebUnlockRoutine : Ptr32 +0x028 EnvironmentUpdateCount : Uint4B +0x02c KernelCallbackTable : Ptr32 +0x030 SystemReserved : Uint4B +0x034 AtlThunkSListPtr32 : Uint4B +0x038 FreeList : Ptr32 +0x03c TlsExpansionCounter : Uint4B +0x040 TlsBitmap : Ptr32 +0x044 TlsBitmapBits : Uint4B +0x04c ReadOnlySharedMemoryBase : Ptr32 +0x050 ReadOnlySharedMemoryHeap : Ptr32 +0x054 ReadOnlyStaticServerData : Ptr32 +0x058 AnsiCodePageData : Ptr32 +0x05c OemCodePageData : Ptr32 +0x060 UnicodeCaseTableData : Ptr32 +0x064 NumberOfProcessors : Uint4B +0x068 NtGlobalFlag : Uint4B +0x070 CriticalSectionTimeout : _LARGE_INTEGER +0x000 LowPart : Uint4B +0x004 HighPart : Int4B +0x000 u : __unnamed +0x000 LowPart : Uint4B +0x004 HighPart : Int4B +0x000 QuadPart : Int8B +0x078 HeapSegmentReserve : Uint4B ···········································dt -r0 _peb 不显示子类型
dt -r1 _peb 显示一级子类型 还没依次
下面是显示 搜索的字符串
dt _teb -ny Client
lkd> dt _teb -ny client//不分大小写 nt!_TEB +0x020 ClientId : _CLIENT_ID
dt exe文件名!!变量名 //可以显示变量 也可以直接dt 变量名
!pcr //查看CPU PCR内容
dt nt!_KPCR xxxxxx //可以观察PCR
dt _heap 或者 dt ntdll!_heap//查看_peb 中的ProcessHeap
lkd> dt _heap nt!_HEAP +0x000 Entry : _HEAP_ENTRY +0x008 Signature : Uint4B +0x00c Flags : Uint4B +0x010 ForceFlags : Uint4B +0x014 VirtualMemoryThreshold : Uint4B +0x018 SegmentReserve : Uint4B +0x01c SegmentCommit : Uint4B +0x020 DeCommitFreeBlockThreshold : Uint4B `````````````````````````````````````dt _peb @$peb //取当前的PEB
dt PEB_LDR_DATA//查看PEB_LDR_DATA结构
//查看_LIST_ENTRY
lkd> dt _LIST_ENTRY nt!_LIST_ENTRY +0x000 Flink : Ptr32 _LIST_ENTRY +0x004 Blink : Ptr32 _LIST_ENTRY
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
按MSDN解释是: Each item in the list is a pointer to an LDR_DATA_TABLE_ENTRY structure,双向循环链表吧,从一个方向开始,不停的循环,就回到初始位了,就相当于遍历了一次也就是只是上面这个 _LIST_ENTRY是只想LDR_DATA_TABLE_ENTRY结构的
后面可以将这个_LIST_ENTRY结构的地址以ldr_data_table_entry结构显示
lkd> dt _ldr_data_table_entry nt!_LDR_DATA_TABLE_ENTRY +0x000 InLoadOrderLinks : _LIST_ENTRY +0x008 InMemoryOrderLinks : _LIST_ENTRY +0x010 InInitializationOrderLinks : _LIST_ENTRY +0x018 DllBase : Ptr32 Void +0x01c EntryPoint : Ptr32 Void +0x020 SizeOfImage : Uint4B +0x024 FullDllName : _UNICODE_STRING +0x02c BaseDllName : _UNICODE_STRING +0x034 Flags : Uint4B +0x038 LoadCount : Uint2B +0x03a TlsIndex : Uint2B +0x03c HashLinks : _LIST_ENTRY +0x03c SectionPointer : Ptr32 Void +0x040 CheckSum : Uint4B +0x044 TimeDateStamp : Uint4B +0x044 LoadedImports : Ptr32 Void +0x048 EntryPointActivationContext : Ptr32 Void +0x04c PatchInformation : Ptr32 Void
LIST_ENTRY InLoadOrderModuleList; //按加载顺序
LIST_ENTRY InMemoryOrderModuleList; //按内存顺序
LIST_ENTRY InInitializationOrderModuleList;//按初始化顺序
为什么有三个list:其实三个都一样,顺序不同而已.
//查看 cmdline
lkd> dt _peb @$peb nt!_PEB +0x000 InheritedAddressSpace : 0 '' +0x001 ReadImageFileExecOptions : 0 '' +0x002 BeingDebugged : 0 '' +0x003 SpareBool : 0 '' +0x004 Mutant : 0xffffffff Void +0x008 ImageBaseAddress : 0x01000000 Void +0x00c Ldr : 0x00191e90 _PEB_LDR_DATA +0x010 ProcessParameters : 0x00020000 _RTL_USER_PROCESS_PARAMETERS +0x014 SubSystemData : (null) ``````````````````
lkd> dt 0x00020000 _RTL_USER_PROCESS_PARAMETERS nt!_RTL_USER_PROCESS_PARAMETERS +0x000 MaximumLength : 0x1000 +0x004 Length : 0xb34 +0x008 Flags : 0x2001 +0x00c DebugFlags : 0 +0x010 ConsoleHandle : (null) +0x014 ConsoleFlags : 0 +0x018 StandardInput : (null) +0x01c StandardOutput : 0x00010001 Void +0x020 StandardError : (null) +0x024 CurrentDirectory : _CURDIR +0x030 DllPath : _UNICODE_STRING "C:Program FilesDebugging Tools for Windows (x86);C:WINDOWSsystem32;C:WINDOWSsystem;C:WINDOWS;.;C:WINDOWSsystem32;C:WINDOWS;C:WINDOWSSystem32Wbem;C:Program FilesMicrosoft Platform SDK for Windows XP SP2Bin.;C:Program FilesMicrosoft Platform SDK for Windows XP SP2BinWinNT.;C:Program FilesMicrosoft Visual StudioCommonToolsWinNT;C:Program FilesMicrosoft Visual StudioCommonMSDev98Bin;C:Program FilesMicrosoft Visual StudioCommonTools;C:Program FilesMicrosoft Visual StudioVC98in;C:Program FilesMicrosoft Platform SDK for Windows XP SP2Bin.;C:Program FilesMicrosoft Platform SDK for Windows XP SP2BinWinNT." +0x038 ImagePathName : _UNICODE_STRING "C:Program FilesDebugging Tools for Windows (x86)windbg.exe" +0x040 CommandLin ``````````````````````
调试器用户经常会需要查看在启动调试目标时使用了哪些命令行参数,这个信息是保存在PEB中的,可以通过!peb来获取,这个命令将解析PEB并给出完整的命令行,所有已加载DLL的位置,以及环境变量等.
http://blog.csdn.net/hgy413/article/details/8490918 学习!peb 中找出 dt _peb @$peb 中 推 出 命令行参数等信息怎么来的
将 InLoadOrderModuleList 地址 换为_LIST_ENTRY 然后子结构都可以用 _ldr_data_table_entry 表示 看到 DLLPATH 和BASE,里面还有 InLoadOrderLinks : _LIST_ENTRY 又用_ldr_data_table_entry表示找出下一个 _ldr_data_table_entry 反复往下弄 找出全部 DLLPATH 和BASE 最后发现返回到第一个DLLPATH 和BASE ,那么证明这个事一个循环链表
每个进程对应一个EPROCESS结构
dt _eprocess //查看EPROCESS结构
!process 0 0 //得到进程的列表
PROCESS 85e80c20 SessionId: 0 Cid: 0a08 Peb: 7ffd7000 ParentCid: 03b8 DirBase: 0c0c0540 ObjectTable: e2db9bc8 HandleCount: 2880. Image: explorer.exe `````````````````查看 85e80c20 解析EPROCESS
dt _eprocess 85e80c20
lkd> dt _eprocess 85e80c20 nt!_EPROCESS +0x000 Pcb : _KPROCESS +0x06c ProcessLock : _EX_PUSH_LOCK +0x070 CreateTime : _LARGE_INTEGER 0x1cee669`bb688c8e +0x078 ExitTime : _LARGE_INTEGER 0x0 +0x080 RundownProtect : _EX_RUNDOWN_REF +0x084 UniqueProcessId : 0x00000a08 Void +0x088 ActiveProcessLinks : _LIST_ENTRY [ 0x8630c630 - 0x86056790 ] +0x090 QuotaUsage : [3] 0x5058 +0x09c QuotaPeak : [3] 0x73d0 ```````````````` +0x174 ImageFileName : [16] "explorer.exe"dd 85e80c20 + 0x88 得到下一个EPROCESS 的进程链表
要得到下一个EPROCESS的地址 必须减去0x88 才能得到
lkd> dd 85e80c20+0x88 85e80ca8 8630c630 86056790 00005058 000641cc 85e80cb8 0000200f 000073d0 0008a8b4 00002588 85e80cc8 0000200f 12af8000 0ddad000 8630c65c 85e80cd8 860567bc 00000000 e150bf68 e2db9bc8 85e80ce8 e302b94f 00000001 ee01b670 0000000b 85e80cf8 00040001 00000000 85e80d00 85e80d00 85e80d08 00000000 0003e034 00000001 ee01b670 85e80d18 00000011 00040001 00000000 85e80d24
dt _eprocess (8630c630-0x88)
lkd> dt _eprocess (8630c630-0x88) nt!_EPROCESS +0x000 Pcb : _KPROCESS +0x06c ProcessLock : _EX_PUSH_LOCK +0x070 CreateTime : _LARGE_INTEGER 0x1cee669`bbb27574 +0x078 ExitTime : _LARGE_INTEGER 0x0 +0x080 RundownProtect : _EX_RUNDOWN_REF +0x084 UniqueProcessId : 0x000009e4 Void +0x088 ActiveProcessLinks : _LIST_ENTRY [ 0x86239c98 - 0x85e80ca8 ] +0x090 QuotaUsage : [3] 0x7f8 +0x09c QuotaPeak : [3] 0x7f8 `````````````````` +0x174 ImageFileName : [16] "wscntfy.exe"
2 ln 命令
ln (List Nearest Symbols) The ln command displays the symbols at or near the given address. Syntax ln Address
eg:
lkd>
rdmsr 176
msr[176] = 00000000`8053e540
lkd> ln 8053e540
(8053e540) nt!KiFastCallEntry | (8053e649) nt!KiServiceExit
Exact matches:
nt!KiFastCallEntry = <no type information>
!idt The !idt extension displays the interrupt service routines (ISRs) for a specified interrupt dispatch table (IDT). Syntax !idt IDT !idt [-a] !idt -? Parameters IDT Specifies the IDT to display. -a When IDT is not specified, the debugger displays the IDTs of all processors on the target computer in an abbreviated format. If -a is specified, the ISRs for each IDT are also displayed. -? Displays help for this extension in the Debugger Command window.
!idt -a 2e //显示终端2E的处理函数ISR
lkd> !idt 2e Dumping IDT: 2e: 8053e481 nt!KiSystemService
int 2e 会执行 KiSystemService 做了一些准备后又会转到 KiFastCallEntry
int 2e 和 sysenter 是差不多的
3 dd dw db命令
·························································
typedef struct _SYSTEM_SERVICE_TABLE //sst 服务描述表 { PVOID ServiceTableBase; //这个指向系统服务函数地址表 PULONG ServiceCounterTableBase; ULONG NumberOfService; //服务函数的个数 ULONG ParamTableBase; }SYSTEM_SERVICE_TABLE,*PSYSTEM_SERVICE_TABLE;
typedef struct _SERVICE_DESCRIPTOR_TABLE //服务描述表 SDT = SSDT { SYSTEM_SERVICE_TABLE ntoskrnel; //ntoskrnl.exe的服务函数 SYSTEM_SERVICE_TABLE win32k; //win32k.sys的服务函数,(gdi.dll/user.dll的内核支持) SYSTEM_SERVICE_TABLE NotUsed1; SYSTEM_SERVICE_TABLE NotUsed2; }SYSTEM_DESCRIPTOR_TABLE,*PSYSTEM_DESCRIPTOR_TABLE;·························································
typedef struct _ServiceDescriptorTable { unsigned int* ServiceTableBase; //System Service Dispatch Table 的基地址 unsigned int* ServiceCounterTable; //包含着 SSDT 中每个服务被调用次数的计数器。这个计数器一般由sysenter 更新。 unsigned int NumberOfServices;//由 ServiceTableBase 描述的服务的数目。 unsigned char* ParamTableBase; //包含每个系统服务参数字节数表的基地址-系统服务参数表 }*PServiceDescriptorTable;
lkd> dd KeServiceDescriptorTable 80553fa0 80502b8c 00000000 0000011c 80503000 //ntoskrnl.导出 KeServiceDescriptorTable只有一个SST 80553fb0 00000000 00000000 00000000 00000000 80553fc0 00000000 00000000 00000000 00000000 80553fd0 00000000 00000000 00000000 00000000 //其他三个SST未使用 80553fe0 00002710 bf80c0b6 00000000 00000000 80553ff0 f7adaa80 f7249b60 86155580 806e2f40 80554000 00000000 00000000 a99b7e04 00000506 80554010 7ee976c4 01ceeb6e 00000000 00000000
lkd> dd KeServiceDescriptorTableShadow //指派给GUI线程使用 80553f60 80502b8c 00000000 0000011c 80503000 //ntoskrnl.exe 80553f70 bf999b80 00000000 0000029b bf99a890 //win2k.sys 80553f80 00000000 00000000 00000000 00000000 //其余两个SST未使用 80553f90 00000000 00000000 00000000 00000000 80553fa0 80502b8c 00000000 0000011c 80503000 80553fb0 00000000 00000000 00000000 00000000 80553fc0 00000000 00000000 00000000 00000000 80553fd0 00000000 00000000 00000000 00000000
lkd> dd KiServiceTable 80502b8c 8059a948 805e7db6 805eb5fc 805e7de8 //80502b8c 是上面SDT的ServiceTable 80502b9c 805eb636 805e7e1e 805eb67a 805eb6be 80502bac 8060cdfe 8060db50 805e31b4 805e2e0c 80502bbc 805cbde6 805cbd96 8060d424 805ac5ae 80502bcc 8060ca3c 8059edbe 805a6a00 805cd8c4 80502bdc 80500828 8060db42 8056ccd6 8053600e 80502bec 806060d4 805b2c3a 805ebb36 8061ae56 80502bfc 805f0028 8059b036 8061b0aa 8059a8e8跟踪 ntdll!ZwCreateFile 设置的索引为25
lkd> ln poi(KiServiceTable + 4*25) (8056f27c) nt!NtCreateFile | (8056f2b6) nt!NtCreateNamedPipeFile Exact matches: nt!NtCreateFile = <no type information>
Native API 总结:
1) ntdll.dll 中ZwXxx 和 NtXxx 函数都是导向ntoskrnl.exe 的Stub函数
2)ntoskrnl.exe 中 ZwXxx 函数也是Stub函数,导向 ntoskrnl.exe的NtXxx函数
3) ntoskrnl.exe 中 NtXxx 函数是所有 Stub 的目的地,是真正做事情的函数
4 poi 命令
poi Pointer-sized data from the specified address. The pointer size is 32 bits or 64 bits. In kernel debugging, this size is based on the processor of the target computer. In user-mode debugging on an Itanium-based computer, this size is 32 bits or 64 bits, depending on the target application. Therefore, poi is the best operator to use if you want pointer-sized data.
5 bp 下断点命令
bp $exentry //对载入windbg的EXE程序入口点设断点
对指定代码行下断
先要在这个函数中下断 然后 bl查看 14 e b2211490 [z:eooks驱动开发source_code新建文件夹kb_sniff_mpkb_sniffmp.c @ 17] 0001 (0001) Kb_sniffMp!search_irq1 然后就这样下断 kd> bp `Kb_sniffMp!z:eooks驱动开发source_code新建文件夹kb_sniff_mpkb_sniffmp.c:53` //这里 注意 ` 还有 `模块!C文件路径:多少行`
bl X //查看断点
bd X //禁止断点
be X //恢复断点
ba //内存断点
ba r 1 xxxxx //在xxxx下读字节的内存读写断点
e (execute) Breaks into the debugger when the CPU retrieves an instruction from the specified address. r (read/write) Breaks into the debugger when the CPU reads or writes at the specified address. w (write) Breaks into the debugger when the CPU writes at the specified address. i (i/o) (Microsoft Windows XP and later versions, kernel mode only, x86-based systems only) Breaks into the debugger when the I/O port at the specified Address is accessed.
6 s 搜索命令
s -a 00400000 999999 "Wrong" //搜索以ASCII码形式存在 从A 开始 B字节内搜索
Shift+F11 跳出函数
7 a //修改指令
首先,输入a,Enter 然后,输入要修改成的指令 最后,Enter,结束//多少字节要enter几回
8 ~~[xx] //查看线程ID xx 是属于现在用户调试状态下的哪个