日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

难译 | windbg 乐趣之道(下)

發布時間:2024/3/13 编程问答 57 豆豆
生活随笔 收集整理的這篇文章主要介紹了 难译 | windbg 乐趣之道(下) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

Yarden Shafir 分享了兩篇非常通俗易懂的,關于 windbg 新引入的調試數據模型的文章。原文鏈接如下:

part1:https://medium.com/@yardenshafir2/windbg-the-fun-way-part-1-2e4978791f9b

part2:https://medium.com/@yardenshafir2/windbg-the-fun-way-part-2-7a904cba5435

本文是第二部分的譯文。同樣在有道詞典、必應詞典、谷歌翻譯的大力幫助下完成,感謝以上翻譯工具,我只是一個搬運工。強烈建議英文好的朋友閱讀原文,因為在翻譯的過程中不可避免的按我的理解做了調整。

第一部分譯文在這里。

以下是譯文!


歡迎來到我試圖讓您享受在 Windows 上調試的第 2 部分(哇,我真是個書呆子)!

在第一部分中,我們已經了解了新調試數據模型的基本知識——使用新對象、使用自定義寄存器、搜索和過濾輸出、聲明匿名類型以及解析列表和數組。在這一部分中,我們將學習如何在 dx 中使用傳統命令(譯注: 原文是 legacy commands,我理解是在引入 dx 之前就存在的一些命令,比如 dt、u 等),了解令人驚嘆的新反匯編器,創建合成方法和類型,查看斷點的奇妙變化,并在調試器中使用文件系統。

聽起來有很多內容。因為確實有很多內容。我們開始吧!

傳統命令(Legacy Commands)

新數據模型完全改變了調試體驗。但有時確實需要使用我們已經習慣的舊命令或擴展(這些功能在 dx 中沒有對應的實現)。

我們仍然可以通過 Debugger.Utility.Control.ExecuteCommand 在 dx 中使用這些舊命令,它讓我們可以將傳統命令作為 dx 查詢的一部分運行。例如,我們可以使用傳統的 u 命令查看第二個棧幀中 RIP 所指向的地址對應的反匯編。

由于 dx 輸出默認是十進制的,而傳統命令只接受十六進制輸入,我們首先需要使用 ToDisplayString("x") 將其轉換為十六進制:

dx?Debugger.Utility.Control.ExecuteCommand("u?"?+?@$curstack.Frames[1].Attributes.InstructionOffset.ToDisplayString("x"))Debugger.Utility.Control.ExecuteCommand("u?"?+?@$curstack.Frames[1].Attributes.InstructionOffset.ToDisplayString("x"))????????????????[0x0]?????:?kdnic!TXTransmitQueuedSends+0x125:[0x1]?????:?fffff807`52ad2b61?4883c430????????add?????rsp,30h[0x2]?????:?fffff807`52ad2b65?5b??????????????pop?????rbx[0x3]?????:?fffff807`52ad2b66?c3??????????????ret[0x4]?????:?fffff807`52ad2b67?4c8d4370????????lea?????r8,[rbx+70h][0x5]?????:?fffff807`52ad2b6b?488bd7??????????mov?????rdx,rdi[0x6]?????:?fffff807`52ad2b6e?488d4b60????????lea?????rcx,[rbx+60h][0x7]?????:?fffff807`52ad2b72?4c8b15d7350000??mov?????r10,qword?ptr?[kdnic!_imp_ExInterlockedInsertTailList?(fffff807`52ad6150)][0x8]?????:?fffff807`52ad2b79?e8123af8fb??????call????nt!ExInterlockedInsertTailList?(fffff807`4ea56590)

另一個有用的傳統命令是 !irp。這個命令為我們提供了大量關于 IRP 的信息,所以沒必要大費周章的使用 dx 重新實現它。

我們將嘗試對 lsass.exe 進程中所有的 IRP 執行 !irp 命令。讓我們看看整個過程:

首先,我們需要找到 lsass.exe 進程的容器。我們已經知道如何使用 Where() 來做到這一點。我們選擇返回的第一個進程。通常應該只有一個 lsass,除非機器上有服務隔離。

譯注: 服務隔離對應的原文是 server silos,在網上找到一個解釋 :A silo in IT is an isolated point in a system where data is kept and segregated from other parts of the architecture.

dx?@$lsass?=?@$cursession.Processes.Where(p?=>?p.Name?==?"lsass.exe").First()

然后,我們需要遍歷進程中每個線程的 IrpList 并獲得 IRP 本身。我們可以很容易地通過前面提到的 FromListEntry() 做到這一點。我們只選取包含 IRP 的線程:

dx?-r4?@$irpThreads?=?@$lsass.Threads.Select(t?=>?new?{irp?=?Debugger.Utility.Collections.FromListEntry(t.KernelObject.IrpList,?"nt!_IRP",?"ThreadListEntry")}).Where(t?=>?t.irp.Count()?!=?0)@$irpThreads?=?@$lsass.Threads.Select(t?=>?new?{irp?=? Debugger.Utility.Collections.FromListEntry(t.KernelObject.IrpList,?"nt!_IRP",?"ThreadListEntry")}).Where(t?=>?t.irp.Count()?!=?0)????????????????[0x384]?????????irp?????????????[0x0]??[Type:?_IRP][<Raw?View>]??[Type:?_IRP]IoStack???????:?Size?=?12,?Current?IRP_MJ_DIRECTORY_CONTROL?/?0x2?for?Device?for?"\FileSystem\Ntfs"CurrentThread?:?0xffffb90a59477080?[Type:?_ETHREAD?*][0x1]??[Type:?_IRP][<Raw?View>]??[Type:?_IRP]IoStack???????:?Size?=?12,?Current?IRP_MJ_DIRECTORY_CONTROL?/?0x2?for?Device?for?"\FileSystem\Ntfs"CurrentThread?:?0xffffb90a59477080?[Type:?_ETHREAD?*]

我們可以在這里停一下,點擊其中一個 IRP 的 IoStack (或者運行 -r5 來查看全部內容)可以得到調用棧信息:

dx?@$irpThreads.First().irp[0].IoStack@$irpThreads.First().irp[0].IoStack??:?Size?=?12,?Current?IRP_MJ_DIRECTORY_CONTROL?/?0x2?for?Device?for?"\FileSystem\Ntfs"[0]??????????????:?IRP_MJ_CREATE?/?0x0?for?{...}?[Type:?_IO_STACK_LOCATION][1]??????????????:?IRP_MJ_CREATE?/?0x0?for?{...}?[Type:?_IO_STACK_LOCATION][2]??????????????:?IRP_MJ_CREATE?/?0x0?for?{...}?[Type:?_IO_STACK_LOCATION][3]??????????????:?IRP_MJ_CREATE?/?0x0?for?{...}?[Type:?_IO_STACK_LOCATION][4]??????????????:?IRP_MJ_CREATE?/?0x0?for?{...}?[Type:?_IO_STACK_LOCATION][5]??????????????:?IRP_MJ_CREATE?/?0x0?for?{...}?[Type:?_IO_STACK_LOCATION][6]??????????????:?IRP_MJ_CREATE?/?0x0?for?{...}?[Type:?_IO_STACK_LOCATION][7]??????????????:?IRP_MJ_CREATE?/?0x0?for?{...}?[Type:?_IO_STACK_LOCATION][8]??????????????:?IRP_MJ_CREATE?/?0x0?for?{...}?[Type:?_IO_STACK_LOCATION][9]??????????????:?IRP_MJ_CREATE?/?0x0?for?{...}?[Type:?_IO_STACK_LOCATION][10]?????????????:?IRP_MJ_DIRECTORY_CONTROL?/?0x2?for?Device?for?"\FileSystem\Ntfs"?[Type:?_IO_STACK_LOCATION][11]?????????????:?IRP_MJ_DIRECTORY_CONTROL?/?0x2?for?Device?for?"\FileSystem\FltMgr"?[Type:?_IO_STACK_LOCATION]

最后,我們將遍歷每個線程,并且遍歷線程中的每個 IRP,并對其執行 Executeccommand !IRP <irp address>。這里我們也需要類型轉換和 ToDisplayString("x") 來匹配傳統命令所期望的格式。( !irp 的輸出很長,所以我們將其截斷,只關注感興趣的數據):

dx?-r3?@$irpThreads.Select(t?=>?t.irp.Select(i?=>?Debugger.Utility.Control.ExecuteCommand("!irp?"?+?((__int64)&i).ToDisplayString("x"))))@$irpThreads.Select(t?=>?t.irp.Select(i?=>?Debugger.Utility.Control.ExecuteCommand("!irp?"?+?((__int64)&i).ToDisplayString("x"))))????????????????[0x384]?????????[0x0]???????????[0x0]????????????:?Irp?is?active?with?12?stacks?11?is?current?(=?0xffffb90a5b8f4d40)[0x1]????????????:??No?Mdl:?No?System?Buffer:?Thread?ffffb90a59477080:??Irp?stack?trace.??[0x2]????????????:??????cmd??flg?cl?Device???File?????Completion-Context[0x3]????????????:??[N/A(0),?N/A(0)]...[0x34]???????????:?Irp?Extension?present?at?0xffffb90a5b8f4dd0:[0x1]???????????[0x0]????????????:?Irp?is?active?with?12?stacks?11?is?current?(=?0xffffb90a5bd24840)[0x1]????????????:??No?Mdl:?No?System?Buffer:?Thread?ffffb90a59477080:??Irp?stack?trace.??[0x2]????????????:??????cmd??flg?cl?Device???File?????Completion-Context[0x3]????????????:??[N/A(0),?N/A(0)]...[0x34]???????????:?Irp?Extension?present?at?0xffffb90a5bd248d0:

!irp 提供給我們的大部分信息都可以通過使用 dx 解析 IRP 并轉儲其 IoStack 獲得。但是有一些信息如果不使用傳統命令則很難獲得。比如, IrpExtension 是否存在及其地址,以及可能與 IRP 關聯的 Mdl 的信息。

反匯編器(Disassembler)

我們以 u 命令為例,下面的例子展示的是:在 dx 中通過 Debugger.Utility.Code.CreateDisassember 和 DisassembleBlock 創建可以遍歷和搜索的反匯編代碼:

dx?-r3?Debugger.Utility.Code.CreateDisassembler().DisassembleBlocks(@$curstack.Frames[1].Attributes.InstructionOffset)Debugger.Utility.Code.CreateDisassembler().DisassembleBlocks(@$curstack.Frames[1].Attributes.InstructionOffset)????????????????[0xfffff80752ad2b61]?:?Basic?Block?[0xfffff80752ad2b61?-?0xfffff80752ad2b67)StartAddress?????:?0xfffff80752ad2b61EndAddress???????:?0xfffff80752ad2b67Instructions????[0xfffff80752ad2b61]?:?add?????????rsp,30h[0xfffff80752ad2b65]?:?pop?????????rbx[0xfffff80752ad2b66]?:?ret[0xfffff80752ad2b67]?:?Basic?Block?[0xfffff80752ad2b67?-?0xfffff80752ad2b7e)StartAddress?????:?0xfffff80752ad2b67EndAddress???????:?0xfffff80752ad2b7eInstructions????[0xfffff80752ad2b67]?:?lea?????????r8,[rbx+70h][0xfffff80752ad2b6b]?:?mov?????????rdx,rdi[0xfffff80752ad2b6e]?:?lea?????????rcx,[rbx+60h][0xfffff80752ad2b72]?:?mov?????????r10,qword?ptr?[kdnic!__imp_ExInterlockedInsertTailList?(fffff80752ad6150)][0xfffff80752ad2b79]?:?call????????ntkrnlmp!ExInterlockedInsertTailList?(fffff8074ea56590)[0xfffff80752ad2b7e]?:?Basic?Block?[0xfffff80752ad2b7e?-?0xfffff80752ad2b80)StartAddress?????:?0xfffff80752ad2b7eEndAddress???????:?0xfffff80752ad2b80Instructions????[0xfffff80752ad2b7e]?:?jmp?????????kdnic!TXTransmitQueuedSends+0xd0?(fffff80752ad2b0c)[0xfffff80752ad2b80]?:?Basic?Block?[0xfffff80752ad2b80?-?0xfffff80752ad2b81)StartAddress?????:?0xfffff80752ad2b80EndAddress???????:?0xfffff80752ad2b81Instructions...

只選擇 Instructions 并將其扁平化顯示,整理后的版本如下:

dx?-r2?Debugger.Utility.Code.CreateDisassembler().DisassembleBlocks(@$curstack.Frames[1].Attributes.InstructionOffset).Select(b?=>?b.Instructions).Flatten()Debugger.Utility.Code.CreateDisassembler().DisassembleBlocks(@$curstack.Frames[1].Attributes.InstructionOffset).Select(b?=>?b.Instructions).Flatten()????????????????[0x0]???????????[0xfffff80752ad2b61]?:?add?????????rsp,30h[0xfffff80752ad2b65]?:?pop?????????rbx[0xfffff80752ad2b66]?:?ret[0x1]???????????[0xfffff80752ad2b67]?:?lea?????????r8,[rbx+70h][0xfffff80752ad2b6b]?:?mov?????????rdx,rdi[0xfffff80752ad2b6e]?:?lea?????????rcx,[rbx+60h][0xfffff80752ad2b72]?:?mov?????????r10,qword?ptr?[kdnic!__imp_ExInterlockedInsertTailList?(fffff80752ad6150)][0xfffff80752ad2b79]?:?call????????ntkrnlmp!ExInterlockedInsertTailList?(fffff8074ea56590)[0x2]???????????[0xfffff80752ad2b7e]?:?jmp?????????kdnic!TXTransmitQueuedSends+0xd0?(fffff80752ad2b0c)[0x3]???????????[0xfffff80752ad2b80]?:?int?????????3[0x4]???????????[0xfffff80752ad2b81]?:?int?????????3...

合成方法(Synthetic Methods)

新調試數據模型提供的另一個功能是允許我們創建并使用自定義函數。語法如下:

0:?kd>?dx?@$multiplyByThree?=?(x?=>?x?*?3)@$multiplyByThree?=?(x?=>?x?*?3)0:?kd>?dx?@$multiplyByThree(5)@$multiplyByThree(5)?:?15

我們也可以創建包含多個參數的函數:

0:?kd>?dx?@$add?=?((x,?y)?=>?x?+?y)@$add?=?((x,?y)?=>?x?+?y)0:?kd>?dx?@$add(5,?7)@$add(5,?7)??????:?12

或者,如果我們真的想要玩的更高端一些,我們可以將這些函數應用到前面的反匯編輸出中,以便找出 ZwSetInformationProcess 函數中所有的內存寫入指令。為此,我們需要對每條指令進行一些檢查,以便知道它是否是內存寫入指令:

  • 指令至少有兩個操作數嗎?

    例如,ret 指令的操作數是 0,而 jmp <address> 指令的操作數是 1。我們只關心將一個值寫入某個位置的情況,這總是需要兩個操作數。為了驗證這一點,我們需要檢查每條指令的 Operands.Count() > 1。

  • 是否是內存引用操作? 我們只對內存寫入操作感興趣,并希望忽略像 mon r10, rcx 這樣的指令。為此,我們將檢查每條指令的 Operands[0].Attributes.IsMemoryReference == true。我們檢查 Operands[0] ,因為它是目的操作數。如果我們想查找內存讀取指令,我們應該檢查源操作數,它在 Operands[1] 中。

  • 目的操作數是輸出嗎?

    我們想過濾掉引用內存但沒有寫入內存的指令。我們將使用 Operands[0].IsOutput == true 進行檢查。

  • 作為最后一個過濾器,我們希望忽略棧內存寫入操作,它看起來像 mov [rsp+0x18],1 或 mov [rbp-0x10],rdx。

    我們將檢查第一個操作數的寄存器,并確保其索引不是 rsp 索引(0x14)或 rbp 索引(0x15)。

我們將編寫一個函數 @$isMemWrite,它接收一個代碼塊并且只返回內存寫入指令(基于上面的檢查)。然后我們可以創建一個反匯編器,反匯編我們的目標函數并且只輸出其中的內存寫入指令:

dx?-r0?@$rspId?=?0x14dx?-r0?@$rbpId?=?0x15dx?-r0?@$isMemWrite?=?(b?=>?b.Instructions.Where(i?=>?i.Operands.Count()?>?1?&&?i.Operands[0].Attributes.IsOutput?&&?i.Operands[0].Registers[0].Id?!=?@$rspId?&&?i.Operands[0].Registers[0].Id?!=?@$rbpId?&&?i.Operands[0].Attributes.IsMemoryReference))dx?-r0?@$findMemWrite?=?(a?=>?Debugger.Utility.Code.CreateDisassembler().DisassembleBlocks(a).Select(b?=>?@$isMemWrite(b)))dx?-r2?@$findMemWrite(&nt!ZwSetInformationProcess).Where(b?=>?b.Count()?!=?0)@$findMemWrite(&nt!ZwSetInformationProcess).Where(b?=>?b.Count()?!=?0)?????????[0xfffff8074ebd23d4][0xfffff8074ebd23e9]?:?mov?????????qword?ptr?[r10+80h],rax[0xfffff8074ebd23f5]?:?mov?????????qword?ptr?[r10+44h],rax[0xfffff8074ebd2415][0xfffff8074ebd2421]?:?mov?????????qword?ptr?[r10+98h],r8[0xfffff8074ebd2428]?:?mov?????????qword?ptr?[r10+0F8h],r9[0xfffff8074ebd2433]?:?mov?????????byte?ptr?gs:[5D18h],al[0xfffff8074ebd25b2][0xfffff8074ebd25c3]?:?mov?????????qword?ptr?[rcx],rax[0xfffff8074ebd25c9]?:?mov?????????qword?ptr?[rcx+8],rax[0xfffff8074ebd25d0]?:?mov?????????qword?ptr?[rcx+10h],rax[0xfffff8074ebd25d7]?:?mov?????????qword?ptr?[rcx+18h],rax[0xfffff8074ebd25df]?:?mov?????????qword?ptr?[rcx+0A0h],rax[0xfffff8074ebd263f][0xfffff8074ebd264f]?:?and?????????byte?ptr?[rax+5],0FDh[0xfffff8074ebd26da][0xfffff8074ebd26e3]?:?mov?????????qword?ptr?[rcx],rax[0xfffff8074ebd26e9]?:?mov?????????qword?ptr?[rcx+8],rax[0xfffff8074ebd26f0]?:?mov?????????qword?ptr?[rcx+10h],rax[0xfffff8074ebd26f7]?:?mov?????????qword?ptr?[rcx+18h],rax[0xfffff8074ebd26ff]?:?mov?????????qword?ptr?[rcx+0A0h],rax[0xfffff8074ebd2708]?:?mov?????????word?ptr?[rcx+72h],ax...

作為另外一個項目,它幾乎結合了上面提到的所有內容 —— 實現 dx 版本的 !apc 。為了簡化,我們只尋找內核 APC。要做到這一點,需要如下幾個步驟:

  • 使用 @$cursession.Processes 遍歷所有進程,以找到這些進程:包含 ?KTHREAD.ApcState.KernelApcPending 值為 1 的線程。

  • 在對應進程中創建一個容器,只包含那些包含掛起內核 APC 的線程,忽略其它線程。

  • 對于每個線程,遍歷 KTHREAD.ApcState.ApcListHead[0] (包含內核 APC)并收集感興趣的信息。可以通過前面介紹的 FromListHead() 方法實現。為了使我們的容器盡可能地與 !apc 相似,我們將只獲取 KernelRoutine 和 RundownRoutine,盡管在你的實現中,你可能會發現其他感興趣的字段。

  • 為了讓容器更容易遍歷,我們將收集進程名、進程 ID、 EPROCESS 地址以及線程 ID 和 ETHREAD 地址。

  • 在我們的實現中,我們創建了幾個輔助函數:

    @$printLn —— 運行傳統命令 ln,以獲取指定地址對應的符號信息。

    **@$extractBetween** —— 提取兩個字符串之間的字符串,用于從 `@$printLn` 的輸出中獲取子字符串。

    **@$printSymbol** —— 傳遞一個地址給 `@$printLn,并且使用 @$extractSymbol` 提取符號名。

    @$apcsForThread —— 找到一個線程中的所有內核 APC,并且創建一個包含 KernelRoutine 和 RundownRoutine 的容器。

在得到所有進程(包含掛起的內核 APC 的線程)后,將其保存到 @$procWithKernelApcs 寄存器中,然后在一個單獨的命令中使用 @$apcsForThread 獲取 APC 信息。我們將 EPPROCESS 和 ETHREAD 指針強制轉換為 void*,這樣當我們顯示最終結果時 dx 就不會顯示整個結構。

這是我解決問題的方法,但也有其他方法,你的方法不一定和我的完全相同!

我想出的腳本是:

dx?-r0?@$printLn?=?(a?=>?Debugger.Utility.Control.ExecuteCommand(“ln?“+((__int64)a).ToDisplayString(“x”)))dx?-r0?@$extractBetween?=?((x,y,z)?=>?x.Substring(x.IndexOf(y)?+?y.Length,?x.IndexOf(z)?—?x.IndexOf(y)?—?y.Length))dx?-r0?@$printSymbol?=?(a?=>?@$extractBetween(@$printLn(a)[3],?“?“,?“|”))dx?-r0?@$apcsForThread?=?(t?=>?new?{TID?=?t.Id,?Object?=?(void*)&t.KernelObject,?Apcs?=?Debugger.Utility.Collections.FromListEntry(*(nt!_LIST_ENTRY*)&t.KernelObject.Tcb.ApcState.ApcListHead[0],?“nt!_KAPC”,?“ApcListEntry”).Select(a?=>?new?{?Kernel?=?@$printSymbol(a.KernelRoutine),?Rundown?=?@$printSymbol(a.RundownRoutine)})})dx?-r0?@$procWithKernelApc?=?@$cursession.Processes.Select(p?=>?new?{Name?=?p.Name,?PID?=?p.Id,?Object?=?(void*)&p.KernelObject,?ApcThreads?=?p.Threads.Where(t?=>?t.KernelObject.Tcb.ApcState.KernelApcPending?!=?0)}).Where(p?=>?p.ApcThreads.Count()?!=?0)dx?-r6?@$procWithKernelApc.Select(p?=>?new?{?Name?=?p.Name,?PID?=?p.PID,?Object?=?p.Object,?ApcThreads?=?p.ApcThreads.Select(t?=>?@$apcsForThread(t))})

它會產生以下輸出:

dx?-r6?@$procWithKernelApc.Select(p?=>?new?{?Name?=?p.Name,?PID?=?p.PID,?Object?=?p.Object,?ApcThreads?=?p.ApcThreads.Select(t?=>?@$apcsForThread(t))})@$procWithKernelApc.Select(p?=>?new?{?Name?=?p.Name,?PID?=?p.PID,?Object?=?p.Object,?ApcThreads?=?p.ApcThreads.Select(t?=>?@$apcsForThread(t))})[0x15b8]????????Name?????????????:?SearchUI.exeLength???????????:?0xcPID??????????????:?0x15b8Object???????????:?0xffffb90a5b1300c0?[Type:?void?*]ApcThreads??????[0x159c]????????TID??????????????:?0x159cObject???????????:?0xffffb90a5b14f080?[Type:?void?*]Apcs????????????[0x0]???????????Kernel???????????:???nt!EmpCheckErrataList???Rundown??????????:???nt!EmpCheckErrataList???[0x1528]????????TID??????????????:?0x1528Object???????????:?0xffffb90a5aa6b080?[Type:?void?*]Apcs????????????[0x0]???????????Kernel???????????:???nt!EmpCheckErrataList???Rundown??????????:???nt!EmpCheckErrataList???[0x16b4]????????TID??????????????:?0x16b4Object???????????:?0xffffb90a59f1e080?[Type:?void?*]Apcs????????????[0x0]???????????Kernel???????????:???nt!EmpCheckErrataList???Rundown??????????:???nt!EmpCheckErrataList???[0x16a0]????????TID??????????????:?0x16a0Object???????????:?0xffffb90a5b141080?[Type:?void?*]Apcs????????????[0x0]???????????Kernel???????????:???nt!EmpCheckErrataList???Rundown??????????:???nt!EmpCheckErrataList???[0x16b8]????????TID??????????????:?0x16b8Object???????????:?0xffffb90a5aab20c0?[Type:?void?*]Apcs????????????[0x0]???????????Kernel???????????:???nt!EmpCheckErrataList???Rundown??????????:???nt!EmpCheckErrataList???[0x1740]????????TID??????????????:?0x1740Object???????????:?0xffffb90a5ab362c0?[Type:?void?*]Apcs????????????[0x0]???????????Kernel???????????:???nt!EmpCheckErrataList???Rundown??????????:???nt!EmpCheckErrataList???[0x1780]????????TID??????????????:?0x1780Object???????????:?0xffffb90a5b468080?[Type:?void?*]Apcs????????????[0x0]???????????Kernel???????????:???nt!EmpCheckErrataList???Rundown??????????:???nt!EmpCheckErrataList???[0x1778]????????TID??????????????:?0x1778Object???????????:?0xffffb90a5b6f7080?[Type:?void?*]Apcs????????????[0x0]???????????Kernel???????????:???nt!EmpCheckErrataList???Rundown??????????:???nt!EmpCheckErrataList???[0x17d0]????????TID??????????????:?0x17d0Object???????????:?0xffffb90a5b1e8080?[Type:?void?*]Apcs????????????[0x0]???????????Kernel???????????:???nt!EmpCheckErrataList???Rundown??????????:???nt!EmpCheckErrataList???[0x17d4]????????TID??????????????:?0x17d4Object???????????:?0xffffb90a5b32f080?[Type:?void?*]Apcs????????????[0x0]???????????Kernel???????????:???nt!EmpCheckErrataList???Rundown??????????:???nt!EmpCheckErrataList???[0x17f8]????????TID??????????????:?0x17f8Object???????????:?0xffffb90a5b32e080?[Type:?void?*]Apcs????????????[0x0]???????????Kernel???????????:???nt!EmpCheckErrataList???Rundown??????????:???nt!EmpCheckErrataList???[0xb28]?????????TID??????????????:?0xb28Object???????????:?0xffffb90a5b065600?[Type:?void?*]Apcs????????????[0x0]???????????Kernel???????????:???nt!EmpCheckErrataList???Rundown??????????:???nt!EmpCheckErrataList???[0x1850]????????TID??????????????:?0x1850Object???????????:?0xffffb90a5b6a5080?[Type:?void?*]Apcs????????????[0x0]???????????Kernel???????????:???nt!EmpCheckErrataList???Rundown??????????:???nt!EmpCheckErrataList

雖然輸出結果沒有 !apc 美觀,但已經很美觀了。

我們還可以將其輸出成表格,顯示相關進程的信息并且可以分別瀏覽每個進程中的 APC:

dx?-g?@$procWithKernelApc.Select(p?=>?new?{?Name?=?p.Name,?PID?=?p.PID,?Object?=?p.Object,?ApcThreads?=?p.ApcThreads.Select(t?=>?@$apcsForThread(t))}) dx-g-procWithKernelApc.Select

但是請等一下,這些包含 nt!EmpCheckErrataList 的 APC 是怎么回事?為什么 SearchUI.exe 里到處都是?這個進程和 erratas 有什么關系?(譯注: 函數 nt!EmpCheckErrataList 中包含 Errata。)

秘密在于實際上并沒有 APC 會調用 nt!EmpCheckErrataList。不,符號也沒有錯。(譯注: 哈哈,感覺作者在跟讀者討論問題)

我們之所以看到這樣的現象,是因為編譯器很智能 —— 當編譯器看到不同的函數具有相同的代碼的時候,編譯器會讓它們全部指向同一段代碼,而不是多次復制這段代碼。你可能會認為這不是一個會經常發生的事情,但讓我們看看 nt!EmpCheckErrataList 的反匯編代碼(這次使用舊辦法):

u?EmpCheckErrataListnt!EmpCheckErrataList: fffff807`4eb86010?c20000??????????ret?????0 fffff807`4eb86013?cc??????????????int?????3 fffff807`4eb86014?cc??????????????int?????3 fffff807`4eb86015?cc??????????????int?????3 fffff807`4eb86016?cc??????????????int?????3

這實際上只是一個存根。它可能是一個尚未實現的函數(EmpCheckErrataList 可能是這種情況),也可能是出于某些原因被故意定義為存根函數。這些 APC 的 KernelRoutine/RundownRoutine 真正對應的函數是 nt!KiSchedulerApcNop,它被故意設計成存根函數,并且已經多年了。我們可以看到它具有相同的代碼并且指向同一地址:

u?nt!KiSchedulerApcNopnt!EmpCheckErrataList: fffff807`4eb86010?c20000??????????ret?????0 fffff807`4eb86013?cc??????????????int?????3 fffff807`4eb86014?cc??????????????int?????3 fffff807`4eb86015?cc??????????????int?????3 fffff807`4eb86016?cc??????????????int?????3

那么為什么我們會看到這么多這樣的 APC 呢?

當一個線程被掛起時,系統會創建一個信號量,并將一個等待該信號量的 APC 發送到該線程。線程將一直等待,直到有人喚醒它,然后系統將釋放信號量,線程將停止等待并恢復運行。APC 本身不需要做很多事情,但它必須有一個 KernelRoutine 和一個 RundownRoutine,所以系統使用了存根。這個存根使用了這些函數(包含存根代碼)中的一個,這次是 nt!EmpCheckErrataList,但在下一個版本中可能是一個不同的函數名。

任何對掛起機制感興趣的人都可以查看 ReactOS。這些函數的代碼發生了一點變化,并且存根函數名從 KiSuspendNop 變成了 KiSchedulerApcNop,但總體設計保持相似。

我跑題了,這不是本篇文章應該討論的內容。讓我們回到 WinDbg,接著講合成類型:

合成類型(Synthetic Types)

在介紹完合成方法后,我們還可以添加自定義的命名類型(named types),并使用它們來解析之前無法解析的數據。

例如,讓我們嘗試打印 PspCreateProcessNotifyRoutine 數組,該數組包含所有已注冊的進程通知例程 —— 這些函數由驅動程序注冊,在進程啟動時會收到一個通知。但是這個數組不包含指向注冊例程的指針。相反,它包含指向未文檔化的結構體 EX_CALLBACK_ROUTINE_BLOCK 的指針。

因此,為了解析這個數組,我們需要確保 WinDbg 認識這個類型 —— 我們需要使用合成類型。我們首先要創建一個頭文件,里面包含我們想要定義的所有類型(我使用 c:\temp\header.h)。在本例中,我們只定義了 EX_CALLBACK_ROUTINE_BLOCK,可以在 ReactOS 中找到它的定義:

typedef?struct?_EX_CALLBACK_ROUTINE_BLOCK {_EX_RUNDOWN_REF?RundownProtect;void*?Function;void*?Context; }?EX_CALLBACK_ROUTINE_BLOCK,?*PEX_CALLBACK_ROUTINE_BLOCK;

現在我們可以讓 WinDbg 加載這個頭文件并將里面的類型添加到 nt 模塊中:

dx?Debugger.Utility.Analysis.SyntheticTypes.ReadHeader("c:\\temp\\header.h",?"nt")Debugger.Utility.Analysis.SyntheticTypes.ReadHeader("c:\\temp\\header.h",?"nt")?????????????????:?ntkrnlmp.exe(header.h)ReturnEnumsAsObjects?:?falseRegisterSyntheticTypeModels?:?falseModule???????????:?ntkrnlmp.exeHeader???????????:?header.hTypes

這會為我們返回一個對象,通過這個對象,我們可以查看添加到此模塊的所有類型。現在,類型已經定義好了,我們可以通過 ?CreateInstance 使用它:

dx?Debugger.Utility.Analysis.SyntheticTypes.CreateInstance("_EX_CALLBACK_ROUTINE_BLOCK",?*(__int64*)&nt!PspCreateProcessNotifyRoutine)Debugger.Utility.Analysis.SyntheticTypes.CreateInstance("_EX_CALLBACK_ROUTINE_BLOCK",?*(__int64*)&nt!PspCreateProcessNotifyRoutine)????????????????RundownProtect???[Type:?_EX_RUNDOWN_REF]Function?????????:?0xfffff8074cbdff50?[Type:?void?*]Context??????????:?0x6e496c4102031400?[Type:?void?*]

需要注意的是 CreateInstance 只接受 __int64 作為輸入,所以任何其他類型都必須強制轉換。提前知道這一點很好,因為返回的錯誤消息并不總是那么容易理解的。

現在如果查看輸出結果,特別是 Context,有些東西似乎很奇怪。實際上,如果我們試圖轉儲 Function,我們會看到它并不指向任何代碼:

dq?0xfffff8074cbdff50 fffff807`4cbdff50??????????`?????????????????`???????? fffff807`4cbdff60??????????`?????????????????`???????? fffff807`4cbdff70??????????`?????????????????`???????? fffff807`4cbdff80??????????`?????????????????`???????? fffff807`4cbdff90??????????`?????????????????`????????

發生了什么?

不是我們強制轉換到 EX_CALLBACK_ROUTINE_BLOCK 出了問題,而是我們轉換的地址有問題。如果我們轉儲 PspCreateProcessNotifyRoutine 中的值,我們可能會看到它的值:

dx?((void**[0x40])&nt!PspCreateProcessNotifyRoutine).Where(a?=>?a?!=?0)((void**[0x40])&nt!PspCreateProcessNotifyRoutine).Where(a?=>?a?!=?0)[0]??????????????:?0xffffb90a530504ef?[Type:?void?*?*][1]??????????????:?0xffffb90a532a512f?[Type:?void?*?*][2]??????????????:?0xffffb90a53da9d5f?[Type:?void?*?*][3]??????????????:?0xffffb90a53da9ccf?[Type:?void?*?*][4]??????????????:?0xffffb90a53e5d15f?[Type:?void?*?*][5]??????????????:?0xffffb90a571469ef?[Type:?void?*?*][6]??????????????:?0xffffb90a5714722f?[Type:?void?*?*][7]??????????????:?0xffffb90a571473df?[Type:?void?*?*][8]??????????????:?0xffffb90a597d989f?[Type:?void?*?*]

所有這些地址的低半字節都是 0xF,而我們知道 x64 機器中的指針總會對齊到 8 字節,通常是 0x10。這是因為我之前過度簡化了 —— 這些不是指向 EX_CALLBACK_ROUTINE_BLOCK 的指針,它們實際上是包含 EX_RUNDOWN_REF 的 EX_CALLBACK 結構體(另一種不在公共符號中的類型)。但是為了使這個示例更簡單,我將把它們當作與 ~0xF 執行操作后的簡單指針,因為這對于我們的目的來說已經足夠好了。如果你選擇寫一個驅動程序來處理 PspCreateProcessNotifyRoutine,請不要使用這個 hack,查看 ReactOS 并正確地做事情。😊

因此,要修復我們的命令,我們只需要在對地址進行強制類型轉換之前將其對齊到 0x10。我們可以像下面這樣做:

<address>?&?0xFFFFFFFFFFFFFFF0

或更好的版本:

<address>?&?~0xF

讓我們在我們的命令中使用它:

dx?Debugger.Utility.Analysis.SyntheticTypes.CreateInstance("_EX_CALLBACK_ROUTINE_BLOCK",?(*(__int64*)&nt!PspCreateProcessNotifyRoutine)?&?~0xf)Debugger.Utility.Analysis.SyntheticTypes.CreateInstance("_EX_CALLBACK_ROUTINE_BLOCK",?(*(__int64*)&nt!PspCreateProcessNotifyRoutine)?&?~0xf)????????????????RundownProtect???[Type:?_EX_RUNDOWN_REF]Function?????????:?0xfffff8074ea7f310?[Type:?void?*]Context??????????:?0x0?[Type:?void?*]

看起來好些了。這次讓我們確認 Function 確實指向了一個函數:

ln?0xfffff8074ea7f310 Browse?module Set?bu?breakpoint(fffff807`4ea7f310)???nt!ViCreateProcessCallback???| (fffff807`4ea7f330)???nt!RtlStringCbLengthW Exact?matches:nt!ViCreateProcessCallback?(void)

看起來好多了!現在我們可以將這種類型轉換定義為一個合成方法,并使用它來獲取數組中所有例程的函數地址:

dx?-r0?@$getCallbackRoutine?=?(a?=>?Debugger.Utility.Analysis.SyntheticTypes.CreateInstance("_EX_CALLBACK_ROUTINE_BLOCK",?(__int64)(a?&?~0xf)))dx?((void**[0x40])&nt!PspCreateProcessNotifyRoutine).Where(a?=>?a?!=?0).Select(a?=>?@$getCallbackRoutine(a).Function)((void**[0x40])&nt!PspCreateProcessNotifyRoutine).Where(a?=>?a?!=?0).Select(a?=>?@$getCallbackRoutine(a).Function)????????????????[0]??????????????:?0xfffff8074ea7f310?[Type:?void?*][1]??????????????:?0xfffff8074ff97220?[Type:?void?*][2]??????????????:?0xfffff80750a41330?[Type:?void?*][3]??????????????:?0xfffff8074f8ab420?[Type:?void?*][4]??????????????:?0xfffff8075106d9f0?[Type:?void?*][5]??????????????:?0xfffff807516dd930?[Type:?void?*][6]??????????????:?0xfffff8074ff252c0?[Type:?void?*][7]??????????????:?0xfffff807520b6aa0?[Type:?void?*][8]??????????????:?0xfffff80753a63cf0?[Type:?void?*]

如果我們能看到符號而不是地址,這會更有趣。我們已經知道如何通過執行傳統命令 ln 來獲取符號,但這一次我們將使用 .printf。

首先,我們將編寫一個輔助函數 @$getsym,它將運行命令 printf "%y", <address>:

dx?-r0?@$getsym?=?(x?=>?Debugger.Utility.Control.ExecuteCommand(".printf\"%y\",?"?+?((__int64)x).ToDisplayString("x"))[0])

然后我們使用這個輔助函數打印每個函數地址對應的符號:

dx?((void**[0x40])&nt!PspCreateProcessNotifyRoutine).Where(a?=>?a?!=?0).Select(a?=>?@$getsym(@$getCallbackRoutine(a).Function))((void**[0x40])&nt!PspCreateProcessNotifyRoutine).Where(a?=>?a?!=?0).Select(a?=>?@$getsym(@$getCallbackRoutine(a).Function))????????????????[0]??????????????:?nt!ViCreateProcessCallback?(fffff807`4ea7f310)[1]??????????????:?cng!CngCreateProcessNotifyRoutine?(fffff807`4ff97220)[2]??????????????:?WdFilter!MpCreateProcessNotifyRoutineEx?(fffff807`50a41330)[3]??????????????:?ksecdd!KsecCreateProcessNotifyRoutine?(fffff807`4f8ab420)[4]??????????????:?tcpip!CreateProcessNotifyRoutineEx?(fffff807`5106d9f0)[5]??????????????:?iorate!IoRateProcessCreateNotify?(fffff807`516dd930)[6]??????????????:?CI!I_PEProcessNotify?(fffff807`4ff252c0)[7]??????????????:?dxgkrnl!DxgkProcessNotify?(fffff807`520b6aa0)[8]??????????????:?peauth+0x43cf0?(fffff807`53a63cf0)

你看,好太多了!

斷點(Breakpoints)

條件斷點(Conditional Breakpoint)

調試時,條件斷點是一個巨大的痛點。在舊的 MASM 語法中,它們幾乎不可用。我花了幾個小時試圖讓它們以我想要的方式工作,但結果是如此糟糕,以至于我甚至不知道我在試圖做什么,更不用說為什么它不過濾任何東西或者如何修復它。

好吧,這些日子已經過去了。我們現在可以在條件斷點中使用 dx 查詢,語法為:bp /w "dx query" <address>。

例如,假設我們正在調試一個 Wow64 進程打開文件的問題。NtOpenProcess 函數一直在被調用,但是我們只關心來自 Wow64 進程的調用,這并不是現代操作系統上的大多數進程(譯注: Wow64 進程指的是運行在 64 位系統上的 32 位進程,64 位進程逐漸成為主流)。因此,為了避免在走狗屎運之前無助的經歷 100 次調試中斷或者避免與 MASM 風格的條件斷點做斗爭,我們可以這樣做:

bp?/w?"@$curprocess.KernelObject.WoW64Process?!=?0" nt!NtOpenProcess

然后讓系統運行起來,當再次中斷時,我們可以檢查它是否奏效:

Breakpoint?3?hit nt!NtOpenProcess: fffff807`2e96b7e0?4883ec38????????sub?????rsp,38hdx?$curprocess.KernelObject.WoW64Process@$curprocess.KernelObject.WoW64Process??:?0xffffc10f5163b390?[Type:?_EWOW64PROCESS?*][+0x000]?Peb??????????????:?0xf88000?[Type:?void?*][+0x008]?Machine??????????:?0x14c?[Type:?unsigned?short][+0x00c]?NtdllType????????:?PsWowX86SystemDll?(1)?[Type:?_SYSTEM_DLL_TYPE]dx?@$curprocess.Name@$curprocess.Name?:?IpOverUsbSvc.exeLength???????????:?0x10

觸發斷點的進程是一個 WoW64 進程!對于那些曾經嘗試過在 MASM 中使用條件斷點的人來說,dx 真是一個大救星。

其它斷點選項(Other Breakpoint Options)

在 Debugger.Utility.Control 下,還有其他一些有趣的斷點選項:

  • SetBreakpointAtSourceLocation —— 允許我們在模塊對應的源文件中設置斷點,語法如下:

    dx Debugger.Utility.Control.SetBreakpointAtSourceLocation("MyModule!myFile.cpp", "172")

  • SetBreakpointAtOffset —— 在函數內部偏移設置斷點 —— dx Debugger.Utility.Control.SetBreakpointAtOffset("NtOpenFile", 8, “nt")

  • SetBreakpointForReadWrite —— 類似于傳統的 ba 命令,但其語法更具可讀性。它允許我們設置斷點,以便在任何讀或寫某個地址時中斷。它的默認配置為 type = Hardware Write 并且 size = 1。(譯注: 原文中的函數名是 SetBreakpointForReadWriteFile,應該是筆誤。)

    比如,讓我們在讀取 Ci!g_CiOptions(一個 4 字節大小的變量)時中斷下來:

dx?Debugger.Utility.Control.SetBreakpointForReadWrite(&Ci!g_CiOptions,?“Hardware?Read”,?0x4)

讓系統繼續運行,斷點幾乎立即命中:

0:?kd>?g Breakpoint?0?hit CI!CiValidateImageHeader+0x51b: fffff807`2f6fcb1b?740c?je?CI!CiValidateImageHeader+0x529?(fffff807`2f6fcb29)

CI!CiValidateImageHeader 在驗證鏡像頭時會讀取此全局變量。在這個特定的示例中,我們將看到讀取這個變量是很頻繁的,修改此變量則加有趣,因為它可以向我們展示篡改簽名驗證的嘗試。

值得注意的是,這些命令不僅僅是設置了一個斷點,實際上會返回給我們一個可以操作的對象,包含屬性 IsEnabled , Condition(允許我們設置一個條件),PassCount(告訴我們這個斷點已經訪問了多少次),還有更多其它屬性。

文件系統(FileSystem)

在 Debugger.Utility 下提供了 FileSystem 模塊,允許我們在調試器中查詢和控制主機上的文件系統(不是正在被調試的機器):

dx?-r1?Debugger.Utility.FileSystemDebugger.Utility.FileSystemCreateFile?[CreateFile(path,?[disposition])?-?Creates?a?file?at?the?specified?path?and?returns?a?file?object.??'disposition'?can?be?one?of?'CreateAlways'?or?'CreateNew']CreateTempFile???[CreateTempFile()?-?Creates?a?temporary?file?in?the?%TEMP%?folder?and?returns?a?file?object]CreateTextReader?[CreateTextReader(file?|?path,?[encoding])?-?Creates?a?text?reader?over?the?specified?file.??If?a?path?is?passed?instead?of?a?file,?a?file?is?opened?at?the?specified?path.??'encoding'?can?be?'Utf16',?'Utf8',?or?'Ascii'.??'Ascii'?is?the?default]CreateTextWriter?[CreateTextWriter(file?|?path,?[encoding])?-?Creates?a?text?writer?over?the?specified?file.??If?a?path?is?passed?instead?of?a?file,?a?file?is?created?at?the?specified?path.??'encoding'?can?be?'Utf16',?'Utf8',?or?'Ascii'.??'Ascii'?is?the?default]CurrentDirectory?:?C:\WINDOWS\system32DeleteFile???????[DeleteFile(path)?-?Deletes?a?file?at?the?specified?path]FileExists???????[FileExists(path)?-?Checks?for?the?existance?of?a?file?at?the?specified?path]OpenFile?????????[OpenFile(path)?-?Opens?a?file?read/write?at?the?specified?path]TempDirectory????:?C:\Users\yshafir\AppData\Local\Temp

我們可以創建文件、打開文件、寫入文件、刪除文件或檢查某個文件是否存在于某個特定路徑中。來看一個簡單的例子,讓我們轉儲當前目錄(C:\Windows\System32)的內容:

dx?-r1?Debugger.Utility.FileSystem.CurrentDirectory.FilesDebugger.Utility.FileSystem.CurrentDirectory.Files????????????????[0x0]????????????:?C:\WINDOWS\system32\07409496-a423-4a3e-b620-2cfb01a9318d_HyperV-ComputeNetwork.dll[0x1]????????????:?C:\WINDOWS\system32\1[0x2]????????????:?C:\WINDOWS\system32\103[0x3]????????????:?C:\WINDOWS\system32\108[0x4]????????????:?C:\WINDOWS\system32\11[0x5]????????????:?C:\WINDOWS\system32\113...[0x44]???????????:?C:\WINDOWS\system32\93[0x45]???????????:?C:\WINDOWS\system32\98[0x46]???????????:?C:\WINDOWS\system32\@AppHelpToast.png[0x47]???????????:?C:\WINDOWS\system32\@AudioToastIcon.png[0x48]???????????:?C:\WINDOWS\system32\@BackgroundAccessToastIcon.png[0x49]???????????:?C:\WINDOWS\system32\@bitlockertoastimage.png[0x4a]???????????:?C:\WINDOWS\system32\@edptoastimage.png[0x4b]???????????:?C:\WINDOWS\system32\@EnrollmentToastIcon.png[0x4c]???????????:?C:\WINDOWS\system32\@language_notification_icon.png[0x4d]???????????:?C:\WINDOWS\system32\@optionalfeatures.png[0x4e]???????????:?C:\WINDOWS\system32\@VpnToastIcon.png[0x4f]???????????:?C:\WINDOWS\system32\@WiFiNotificationIcon.png[0x50]???????????:?C:\WINDOWS\system32\@windows-hello-V4.1.gif[0x51]???????????:?C:\WINDOWS\system32\@WindowsHelloFaceToastIcon.png[0x52]???????????:?C:\WINDOWS\system32\@WindowsUpdateToastIcon.contrast-black.png[0x53]???????????:?C:\WINDOWS\system32\@WindowsUpdateToastIcon.contrast-white.png[0x54]???????????:?C:\WINDOWS\system32\@WindowsUpdateToastIcon.png[0x55]???????????:?C:\WINDOWS\system32\@WirelessDisplayToast.png[0x56]???????????:?C:\WINDOWS\system32\@WwanNotificationIcon.png[0x57]???????????:?C:\WINDOWS\system32\@WwanSimLockIcon.png[0x58]???????????:?C:\WINDOWS\system32\aadauthhelper.dll[0x59]???????????:?C:\WINDOWS\system32\aadcloudap.dll[0x5a]???????????:?C:\WINDOWS\system32\aadjcsp.dll[0x5b]???????????:?C:\WINDOWS\system32\aadtb.dll[0x5c]???????????:?C:\WINDOWS\system32\aadWamExtension.dll[0x5d]???????????:?C:\WINDOWS\system32\AboutSettingsHandlers.dll[0x5e]???????????:?C:\WINDOWS\system32\AboveLockAppHost.dll[0x5f]???????????:?C:\WINDOWS\system32\accessibilitycpl.dll[0x60]???????????:?C:\WINDOWS\system32\accountaccessor.dll[0x61]???????????:?C:\WINDOWS\system32\AccountsRt.dll[0x62]???????????:?C:\WINDOWS\system32\AcGenral.dll...

我們可以選擇刪除其中的一個文件:

dx?-r1?Debugger.Utility.FileSystem.CurrentDirectory.Files[1].Delete()

或者通過 DeleteFile 刪除:

dx?Debugger.Utility.FileSystem.DeleteFile(“C:\\WINDOWS\\system32\\71”)

注意,在這個模塊中,路徑必須使用雙反斜杠("\\"),就像我們自己調用 Win32 API 時一樣。

作為最后一個練習,我們將把在這里學到的東西放在一起 —— 我們將在內核變量上創建一個斷點,從調用棧中獲取訪問它的符號,并將訪問它的符號寫入主機上的一個文件中。

讓我們把它分成幾個步驟:

  • 打開一個文件,以便寫入結果。

  • 創建一個 text writer,我們將使用它寫入文件。

  • 創建訪問變量的斷點。在本例中,我們將選擇 nt!PsInitialSystemProcess 并設置讀斷點。我們將使用舊的 MASM 語法來設置一個斷點,每次斷點命中時,會執行一個 dx 命令并繼續運行:ba r4 <address> "dx <command>; g”

    我們的命令將使用 @$curstack 來獲取訪問該變量的函數地址,然后使用前面編寫的 @$getsym 輔助函數來查找該地址對應的符號。然后使用 text writer 將結果寫入文件。

  • 最后,關閉文件。

整合在一起:

dx?-r0?@$getsym?=?(x?=>?Debugger.Utility.Control.ExecuteCommand(".printf\"%y\",?"?+?((__int64)x).ToDisplayString("x"))[0])dx?@$tmpFile?=?Debugger.Utility.FileSystem.TempDirectory.OpenFile("log.txt")dx?@$txtWriter?=?Debugger.Utility.FileSystem.CreateTextWriter(@$tmpFile)ba?r4?nt!PsInitialSystemProcess?"dx?@$txtWriter.WriteLine(@$getsym(@$curstack.Frames[0].Attributes.InstructionOffset));?g"

我們讓系統想運行多久就運行多久,當我們想停止記錄日志時,我們可以禁用或清除斷點并使用 dx @$tmpFile.Close() 關閉文件。

現在我們可以打開 @$tmpFile 并查看結果:

view-tempFile

就是這樣!記錄關于調試器的信息是多么簡單啊!

這就是我們 WinDbg 系列的全部內容!本系列的所有腳本都將被上傳到 github ,還有一些新的沒有包含在這里的腳本。我鼓勵您進一步研究這個數據模型,因為我們甚至沒有涵蓋它包含的所有不同方法。編寫你自己的工具,并與世界分享它們 :)

譯注: github 地址是 https://github.com/yardenshafir/WinDbg_Scripts)

盡管本指南很長,但這些甚至還不是新數據模型中的所有可能選項。我甚至沒有提到新增的對 ?Javascript 的支持!

你可以在這篇精彩的文章中獲得更多關于在 WinDbg 中使用 Javascript 的信息,以及對令人興奮的 TTD (time travel debugging) 的新支持。

總結

以上是生活随笔為你收集整理的难译 | windbg 乐趣之道(下)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

www视频免费在线观看 | 日韩精品不卡 | 色婷婷精品大在线视频 | 婷婷久久久 | 伊人狠狠色丁香婷婷综合 | 日日躁你夜夜躁你av蜜 | 欧洲精品一区二区 | 蜜臀av网址 | 91日韩免费 | 在线播放日韩av | 97视频免费在线看 | 国产精品久久久久永久免费观看 | 国产精品欧美一区二区三区不卡 | 中日韩欧美精彩视频 | 国产夫妻性生活自拍 | 五月婷婷中文 | 成人国产精品一区 | 日韩免费高清 | 亚洲精品午夜久久久 | av在线一 | 久久国内免费视频 | www.五月婷婷| 黄色免费网战 | 日韩在线视频免费看 | 日本性生活免费看 | 久久人人精品 | 国模视频一区二区三区 | 欧美性黑人 | 97人人添人澡人人爽超碰动图 | 日本中文字幕系列 | 国产日韩精品一区二区三区在线 | 亚洲综合欧美精品电影 | 天天色天天射天天操 | 亚洲午夜久久久久久久久电影网 | 欧美激情视频一区二区三区 | av观看久久久 | 91高清视频 | 一级成人免费视频 | 中国精品一区二区 | 精品久久久久久久久久久久久久久久久久 | 999抗病毒口服液 | 国产成人精品一区二区三区福利 | 国产一级黄色免费看 | 久久av影院 | 欧美日韩中文字幕在线视频 | 黄色免费网站 | 日本精品视频在线观看 | 国产大陆亚洲精品国产 | 国产一区二区精品在线 | 久久国产免费看 | 亚洲精品久久久久中文字幕m男 | 在线免费观看国产精品 | 99久久久国产精品免费观看 | 久久久久在线观看 | 中文字幕精品一区二区三区电影 | 亚洲电影成人 | 成人午夜影院在线观看 | 中文字幕无吗 | 亚洲视频 一区 | 99精品国自产在线 | 88av色| 婷婷激情五月综合 | 免费日韩一区二区三区 | 青青河边草观看完整版高清 | 色黄久久久久久 | 伊人伊成久久人综合网小说 | 国产一区二区三区高清播放 | 久久高清毛片 | 亚洲在线视频免费 | 色婷婷在线视频 | 国产香蕉视频在线观看 | 国产成人精品av | 欧美专区国产专区 | 国产亚洲精品久久久久久 | 午夜av一区二区三区 | 成人免费在线观看电影 | 成人黄色资源 | 亚洲精区二区三区四区麻豆 | 国产亚洲人成网站在线观看 | 91日韩在线专区 | 久久精品免费观看 | 免费成人av在线看 | 成人网看片 | 狠狠操.com| 亚洲精品久久在线 | 成人一级在线观看 | 久久久国产精品一区二区三区 | 又黄又爽的视频在线观看网站 | 欧美一级片在线观看视频 | 手机在线日韩视频 | av片一区二区 | 久久色网站| 国产在线p| 国产69熟| 欧美性色综合 | 日本黄色免费网站 | 亚洲2019精品 | 久久综合99 | 97免费视频在线播放 | 精品国产乱码久久久久久1区二区 | 在线观看成人福利 | 国产原创在线 | 狠狠狠色丁香婷婷综合激情 | 久久久精品小视频 | 成人av电影免费观看 | 国产精品视频一二三 | 国产成年免费视频 | 黄色aa久久 | 国产福利资源 | 日韩精品免费一区二区在线观看 | 成人免费 在线播放 | 夜夜天天干 | 精品美女在线视频 | 在线va网站 | 中文字幕在线观看播放 | 国产在线a | 在线看岛国av| 欧洲一区二区在线观看 | 免费精品 | 久久国内精品99久久6app | 亚洲国产精品一区二区久久hs | 天天插夜夜操 | 黄色av电影网 | a亚洲视频 | 五月婷婷,六月丁香 | 人人dvd| 欧美精品久久久 | 五月婷婷六月丁香在线观看 | 亚洲专区视频在线观看 | 久久综合加勒比 | 热久久精品在线 | 国产精品美女久久久久久久久久久 | 亚洲美女精品区人人人人 | 中文字幕在线观看播放 | 国产精品色婷婷 | 黄网av在线 | 香蕉视频国产在线观看 | 日韩毛片在线一区二区毛片 | 亚洲性xxxx | 天堂黄色片| 国产福利一区二区三区视频 | 麻豆视频免费播放 | 丝袜护士aⅴ在线白丝护士 天天综合精品 | 久久精品视频在线观看 | 天天操,夜夜操 | 婷婷激情综合网 | 亚洲狠狠婷婷 | 天天操天天操天天 | 五月天婷婷狠狠 | 成人av午夜 | 91中文字幕在线视频 | 开心色停停 | 欧美色操 | 欧美成人在线网站 | 国产精品99久久久久久人免费 | 精品一区二区日韩 | sm免费xx网站 | 国产精品区二区三区日本 | 国产精品成久久久久三级 | 欧美日本国产在线观看 | 日韩午夜网站 | av一级片 | 国产美女在线免费观看 | 国产一区免费观看 | 国产精品成人久久 | 中文字幕在线观看完整 | 亚洲综合网| 日韩a在线播放 | 中文一二区 | 国产人成免费视频 | 日韩久久午夜一级啪啪 | 国产视频一区在线播放 | 久久成人国产精品一区二区 | 久久人人爽av | 国产日本在线 | 免费看污在线观看 | 国产成年免费视频 | 国产精品永久免费 | 91精品久久久久久综合乱菊 | 久色婷婷 | 人人玩人人添人人 | 国产精品婷婷 | 超碰97中文 | 国产精品中文字幕av | 国产在线一线 | 久久亚洲热 | 国产99久久精品一区二区永久免费 | 久久精品小视频 | 久久久免费观看完整版 | 亚洲精品免费视频 | 久久99爱视频 | 亚洲理论片 | 免费在线观看av | 午夜精品电影一区二区在线 | 亚洲精品va | 国产一区二区在线影院 | 在线影院中文字幕 | 亚洲老妇xxxxxx | 69国产盗摄一区二区三区五区 | 亚洲欧美日韩精品久久奇米一区 | 免费久久久 | 国产成人在线播放 | 日韩欧美在线视频一区二区三区 | wwwwwww黄 | 精品字幕| 一级黄色视屏 | 欧美日韩xxx | 亚洲黄色三级 | 福利在线看片 | 国产精品你懂的在线观看 | 亚洲国产成人av网 | 黄色软件大全网站 | 丁五月婷婷 | 黄视频色网站 | 亚洲影院天堂 | 日韩乱色精品一区二区 | 久草网免费| 久久久久久久久久久国产精品 | 国产精品女 | 97热久久免费频精品99 | 欧美另类人妖 | 九九免费在线观看 | 国产亚洲成人网 | 国产日韩欧美视频在线观看 | 麻豆久久久久久久 | 午夜91视频| 四虎在线视频免费观看 | 久久影视网| 色婷婷免费 | 中文字幕一区二区三区精华液 | 在线观看免费观看在线91 | 日本电影久久 | 特级西西人体444是什么意思 | 日韩 精品 一区 国产 麻豆 | 日韩高清成人 | 碰超在线观看 | 国产特黄色片 | 99热在线免费观看 | www免费黄色 | 成人一区二区三区在线 | 久久a热6 | 欧美色插| 欧美精品一二 | 成人av影院在线观看 | 亚洲国产精品成人va在线观看 | 99精品视频在线观看免费 | 在线观看视频亚洲 | 午夜精品一区二区三区在线视频 | 色操插| 99精品视频在线免费观看 | 久久久久久免费网 | 日韩专区在线观看 | 日韩美在线观看 | 精品视频资源站 | 色www精品视频在线观看 | 天天干天天射天天爽 | 久久久久久黄色 | 992tv成人免费看片 | 免费精品国产va自在自线 | 一区二区三区四区五区在线视频 | 91av小视频 | 日日夜夜精品视频 | 免费网址你懂的 | 色噜噜在线观看 | 精品亚洲一区二区 | 在线看一区 | 伊人春色电影网 | 久久久久97国产 | 在线观看视频免费播放 | 又污又黄的网站 | 国产二区免费视频 | 国产欧美在线一区 | 中文字幕在线观看网址 | 91亚洲精品久久久蜜桃 | 日本一区二区不卡高清 | 丁香电影小说免费视频观看 | 91免费观看| 亚洲人毛片 | 欧美日韩一区二区视频在线观看 | 中文在线a在线 | 狠狠色丁香九九婷婷综合五月 | 欧美电影在线观看 | 91成人精品一区在线播放69 | 热久久视久久精品18亚洲精品 | 国产九色在线播放九色 | 日本少妇久久久 | 久久福利国产 | 夜夜操天天操 | 国产96av| 在线国产激情视频 | 欧美精品久久人人躁人人爽 | 在线中文字幕观看 | 欧美精品乱码久久久久久按摩 | 精品久久精品 | 久久久高清 | 香蕉视频在线免费看 | 国产成人久久精品一区二区三区 | 插综合网 | 日韩爱爱网站 | 成人h视频在线播放 | 免费亚洲视频 | 欧美在线aa | 欧美一级欧美一级 | 亚洲成人免费观看 | av网站在线观看免费 | 麻豆91小视频| 国产在线观看你懂得 | 婷婷六月中文字幕 | 亚洲精品视频免费观看 | av电影在线播放 | 99re视频在线观看 | 91手机在线看片 | 日韩久久精品一区二区三区 | 日韩免费视频 | 国产精品国产亚洲精品看不卡15 | 99久久影视| 久在线观看 | 午夜精品久久久久久久久久久 | 成年人免费在线观看网站 | 五月婷婷综合在线观看 | 99久久网站 | 色婷婷狠狠18 | 91视频免费国产 | 国产成人99久久亚洲综合精品 | 欧美精品在线一区二区 | 国产精品亚洲片夜色在线 | 国产精品成人免费 | www.夜夜 | 中文字幕 国产 一区 | 日韩a在线| 中文字幕亚洲高清 | 国产日产在线观看 | 一色av | 一级性视频 | 天天操天天色天天射 | 日韩精品中文字幕av | 黄色网www| 一区二区三区高清在线观看 | 国产黄在线免费观看 | 91麻豆精品国产91久久久无限制版 | 欧美日韩亚洲精品在线 | 欧美一级免费在线 | 免费精品在线视频 | 在线观看爱爱视频 | 国产四虎影院 | 久久久久久久亚洲精品 | 久久国产精品99久久人人澡 | www.av在线.com | 亚洲精品国偷自产在线91正片 | 999久久久精品视频 日韩高清www | 久久99久久精品国产 | 日韩性片 | 久久久免费看片 | 一区二区三区视频在线 | 九九视频这里只有精品 | 欧美成人tv| 日韩精品一区二区三区在线播放 | 国产录像在线观看 | 最近免费中文视频 | 在线观看v片 | 中国一级片在线观看 | 天堂素人在线 | 日韩美女久久 | 99精品久久久久 | 国产精品一区二区久久久 | 成人免费在线观看电影 | 久久精品男人的天堂 | 91看片网址 | 日韩一二区在线 | 在线免费观看视频一区二区三区 | 黄色免费观看 | 99精品热视频 | zzijzzij亚洲日本少妇熟睡 | 深爱激情丁香 | 天天色天天爱天天射综合 | 极品美女被弄高潮视频网站 | 国产在线中文字幕 | 亚洲成aⅴ人片久久青草影院 | 国产亚洲精品久久久久久 | 欧美日韩国产精品爽爽 | 亚a在线 | 高清不卡毛片 | 国产视频1区2区3区 久久夜视频 | 亚洲黄色小说网 | 久久精品中文 | 91九色综合 | 欧美激情精品久久 | 五月天堂色 | 99精品福利视频 | 国产在线欧美日韩 | 丝袜精品视频 | 蜜臀av麻豆 | 人人干网 | 亚洲黄色app | 欧美婷婷色 | 成片视频免费观看 | 国产大陆亚洲精品国产 | 亚洲免费av一区二区 | 国产高h视频 | av成人动漫 | 日韩精品一区二区三区外面 | av在线电影网站 | 91av九色 | 久久免费在线观看视频 | 成人禁用看黄a在线 | 久草免费电影 | 亚洲另类在线视频 | 丁香婷婷深情五月亚洲 | 色五月激情五月 | 日本黄色免费在线 | 婷婷综合五月 | 国产999精品视频 | 久久亚洲二区 | 日韩啪啪小视频 | 国产在线欧美在线 | 久草www | 免费久久视频 | 久久亚洲国产精品 | 就要色综合 | 欧美日韩精品在线一区二区 | 激情综合啪啪 | 人人爽人人爽人人爽学生一级 | 免费看v片 | 人人澡人人干 | 免费久草视频 | 黄网站污 | 国产黄色av影视 | 91在线产啪 | 99视频在线看 | 蜜臀av.com | 日韩高清精品免费观看 | 日日操网站 | 欧美日韩国产亚洲乱码字幕 | 色五月成人 | 韩国av一区二区三区在线观看 | 国产成人av一区二区三区在线观看 | 99久久99久久精品国产片果冰 | 色婷婷综合视频在线观看 | 91视频 - 88av | www.亚洲视频.com| 爱干视频 | 99精品视频在线免费观看 | 久久精品资源 | 天天干婷婷 | 婷婷色伊人 | 国产精品福利在线 | 91 在线视频播放 | 黄污视频网站 | www在线观看国产 | 国产亚洲精品久 | 一级黄色av | 免费观看一级视频 | 久久免费公开视频 | 黄网站免费看 | 91久久一区二区 | 国语久久| 欧美a性 | 成人全视频免费观看在线看 | 国产成人精品一区二区三区免费 | 美女露久久 | 51精品国自产在线 | 免费在线激情视频 | 久久久久美女 | 国产人成一区二区三区影院 | 久久久免费 | 精品免费在线视频 | 亚洲第一香蕉视频 | 99这里只有久久精品视频 | av大全在线 | 黄污在线看 | 久久激情久久 | 国产资源在线观看 | 97福利社 | 中文区中文字幕免费看 | 欧美日韩国语 | 免费色视频网站 | 欧美午夜理伦三级在线观看 | 久久免费观看视频 | 日韩欧美视频免费看 | av在线直接看 | 国产亚洲精品久久久久久 | 日韩在线三区 | 国产一区在线精品 | 国产3p视频 | 久久综合九色综合欧美就去吻 | 免费观看视频的网站 | 国产96在线观看 | 91系列在线 | 人人玩人人弄 | 色婷五月天 | 九月婷婷人人澡人人添人人爽 | 久草在线费播放视频 | 亚洲黄网址 | 久久精品国产第一区二区三区 | 国产在线观看中文字幕 | 亚洲一二视频 | 在线观看色视频 | 日日干美女| 久久视频 | 亚洲成人精品av | 亚洲精品白浆高清久久久久久 | 黄色亚洲在线 | 97精品久久人人爽人人爽 | 狠日日| 91视频3p| 欧美一级免费片 | 亚洲天堂精品视频在线观看 | 亚洲综合精品在线 | 亚洲色图美腿丝袜 | 欧美一区免费在线观看 | 欧美日韩高清不卡 | av在线影视| 国产高清久久久久 | 激情婷婷av | 精品久久电影 | 狠狠狠色丁香综合久久天下网 | 国产黄色片免费在线观看 | 中文字幕日韩精品有码视频 | 亚洲黄色影院 | 91精品国产91久久久久久三级 | 亚洲亚洲精品在线观看 | 在线观看不卡视频 | 免费视频一二三区 | 久久综合干 | 亚州欧美视频 | 在线免费中文字幕 | 久久午夜电影 | 在线а√天堂中文官网 | 亚洲电影一级黄 | 国产精品久久久久高潮 | 免费亚洲黄色 | 视频在线亚洲 | 亚洲精品女人久久久 | 色婷婷综合久久久久中文字幕1 | 99久久影院 | 99视频精品全国免费 | 在线免费观看欧美日韩 | 青青草国产免费 | 国产成人一区二区三区影院在线 | 色婷婷综合久久久 | 丁香狠狠 | 美女视频a美女大全免费下载蜜臀 | 亚洲91精品在线观看 | 国产一级视屏 | 日韩av资源在线观看 | 狠狠色噜噜狠狠狠合久 | 亚洲国产视频在线 | 成人av影视| 久久中文字幕导航 | 亚洲三级毛片 | 欧美人人| 久久精品xxx | 免费毛片aaaaaa| 91久久偷偷做嫩草影院 | 婷婷伊人综合亚洲综合网 | 亚洲视频99 | 人人爽人人干 | 国产精品久久久久一区 | 97超碰人人在线 | 成年人视频在线免费播放 | 国产无套视频 | 欧美色综合天天久久综合精品 | 黄色一级大片免费看 | 99热在 | 插婷婷 | 免费在线观看国产黄 | 国产精品久久久久久一二三四五 | 精品福利视频在线观看 | 狠狠的干狠狠的操 | 亚洲视频在线观看免费 | 精品美女久久久久久免费 | 国产亚洲人成网站在线观看 | 天天操夜夜逼 | 69精品视频| 在线岛国av | 中文字幕在线观看国产 | 毛片视频网址 | 中文在线最新版天堂 | 国产精品一区二区三区观看 | 欧美一二三视频 | 国产成人精品亚洲 | 在线观看中文av | 很黄很污的视频网站 | 久久久综合九色合综国产精品 | 国产亚洲婷婷免费 | 97天堂| 四虎最新域名 | 国产成人av| 欧美一二三专区 | 欧美性生活小视频 | 日韩无在线 | 毛片无卡免费无播放器 | 久久久国产一区二区三区 | 国产超碰在线 | 丁香婷婷激情 | 亚洲综合色视频在线观看 | 国产黄色精品在线观看 | 亚洲aⅴ乱码精品成人区 | 伊人首页 | 国产美女视频一区 | 国产99久久精品一区二区永久免费 | av片在线观看 | 国产在线探花 | 欧美在线一二 | 丝袜精品视频 | 亚洲 欧美 成人 | 在线观看蜜桃视频 | 97超碰免费在线 | 婷婷久久网 | 九九激情视频 | 在线不卡中文字幕播放 | 久久精品精品电影网 | 99精品一区二区三区 | 色网址99 | 成人一区在线观看 | 日日添夜夜添 | 91成人免费在线视频 | 国产黄色美女 | 午夜精品视频福利 | 在线看日韩 | www亚洲一区 | 欧美91视频| 日韩免费三区 | 久在线观看视频 | 免费人成在线观看网站 | 精品欧美日韩 | 日韩免费久久 | 日韩精品一区二区三区不卡 | 麻豆一区在线观看 | 色多视频在线观看 | 中文字幕中文字幕在线中文字幕三区 | 国产福利小视频在线 | 亚洲午夜久久久综合37日本 | 国产v欧美 | 久久久人人爽 | 欧美黑吊大战白妞欧美 | 天天操天天射天天 | 国产在线精品区 | 成人精品影视 | 99精品欧美一区二区蜜桃免费 | 亚洲精品乱码久久久久久久久久 | 免费看色网站 | 免费av网址大全 | 久久精品欧美一区 | 在线免费观看黄 | 天天干,天天干 | 人人看人人草 | 人人插人人爱 | 91爱爱网址 | 欧美va天堂在线电影 | 久久伊99综合婷婷久久伊 | 久久九九免费视频 | 成 人 黄 色 视频免费播放 | 一区二区三区四区不卡 | 国产韩国日本高清视频 | 国产精品99页 | 一区二区三区免费在线播放 | 免费麻豆 | 国产精品久久99综合免费观看尤物 | 超碰97在线资源 | 久久精品中文字幕一区二区三区 | 黄色的片子 | 久久全国免费视频 | 天天操天天综合网 | 久久激情日本aⅴ | 91自拍成人 | 国内精品久久久久久久久久久 | 国产精品激情偷乱一区二区∴ | 国内成人精品视频 | 成人av电影免费在线观看 | 国产精品成人自拍 | 国产成人亚洲在线电影 | 久久黄色成人 | 日韩av快播电影网 | 久久中文网 | 激情视频免费在线 | 四虎成人精品在永久免费 | 日韩欧美一区二区三区在线 | 韩国av永久免费 | 欧美在线视频精品 | 成人理论在线观看 | 最近中文字幕在线 | 又黄又爽又刺激视频 | 日本中文字幕影院 | 日韩成人免费在线电影 | 欧美va天堂va视频va在线 | 免费91在线观看 | 在线日本v二区不卡 | 成年人视频免费在线 | 69久久99精品久久久久婷婷 | 97品白浆高清久久久久久 | 深爱激情五月婷婷 | 天天干天天操天天 | 国产中文在线观看 | 国产福利在线免费 | 色婷婷www| 久久免费视频在线观看6 | 日韩中文在线播放 | 91成人黄色| 免费观看成人av | 久久99国产精品 | 97超碰人人澡 | 91精品一区二区三区蜜臀 | 亚洲天堂毛片 | 国产精品原创av片国产免费 | 午夜国产在线观看 | 亚州精品天堂中文字幕 | 日本一区二区三区免费观看 | 最新国产精品拍自在线播放 | 欧美性高跟鞋xxxxhd | 久久精品aaa | 色激情五月 | 日韩av免费一区二区 | 美女视频又黄又免费 | 中文字幕资源网在线观看 | 亚洲精品啊啊啊 | 国产视频日韩视频欧美视频 | 午夜视频免费在线观看 | 国产一二三四在线观看视频 | 色午夜| 一区二区中文字幕在线 | 成人免费中文字幕 | 日本久久久精品视频 | 开心激情网五月天 | 91成人区| 日韩一区二区三区免费视频 | 蜜桃av人人夜夜澡人人爽 | 欧美日本在线观看视频 | 国产一区二区三区黄 | 欧美一级在线 | 婷婷精品视频 | 欧美性色xo影院 | 2021av在线 | 久久人人爽人人爽人人片av软件 | 波多野结衣久久精品 | 亚洲二级片 | 97韩国电影| 青青河边草免费直播 | 亚洲国内精品视频 | 特级毛片在线免费观看 | 人人狠狠综合久久亚洲婷 | 91大神在线观看视频 | 亚洲最新av在线网址 | 丁香婷婷色综合亚洲电影 | av成人动漫 | 91麻豆精品| 亚洲一区二区视频在线 | 久久不卡电影 | 免费看三级网站 | 日韩免费在线观看视频 | 99视频免费播放 | 中文字幕av全部资源www中文字幕在线观看 | 在线99热| 午夜精品久久久久久久久久久 | 亚洲精品视频在线播放 | 日韩激情一二三区 | 欧美人人爱 | 中文字幕亚洲五码 | 亚洲午夜精品福利 | 人人超碰免费 | 久久久久人人 | 久久久久久久久久久综合 | 国产亚洲视频系列 | 亚洲 综合 精品 | 99免费在线播放99久久免费 | 国产精品久久在线观看 | 夜夜躁狠狠躁日日躁视频黑人 | 国产精品免费一区二区三区在线观看 | 日韩免费电影一区二区三区 | 999ZYZ玖玖资源站永久 | 天天爱天天操天天射 | 久久99热这里只有精品 | 国产精品18久久久久久vr | 久久久久久久影院 | 五月婷婷婷婷婷 | 精品久久久久久久久久 | 青青河边草观看完整版高清 | 最近日韩免费视频 | 日韩在线免费高清视频 | 免费高清无人区完整版 | 激情婷婷色| 国产粉嫩在线 | 日本精品视频一区 | 国产精品完整版 | 国产精品高清在线观看 | 日韩精品在线看 | 久久国产精品一区二区三区四区 | 国产久视频 | 免费69视频 | 一本一本久久a久久精品综合 | 操夜夜操| 在线视频日韩精品 | 97免费在线观看视频 | 美女免费电影 | 天天操天天综合网 | 国产精品成人久久久久 | 69国产在线观看 | 国内精品久久久久久 | 亚洲aⅴ一区二区三区 | 在线视频精品播放 | 丁香五婷 | 精品久久久网 | 丁香久久婷婷 | 久久免费视频这里只有精品 | 国产又黄又猛又粗 | 超碰97网站 | 国产乱对白刺激视频在线观看女王 | www.777奇米| 日韩亚洲在线视频 | 日韩高清一区 | 国产精品成人在线观看 | 午夜999 | 在线高清 | 成人黄大片视频在线观看 | 69精品在线 | 国产精品2019 | 国产a国产 | 夜夜操狠狠干 | av电影一区二区三区 | 国产一级二级在线 | 久久久久久久久久久高潮一区二区 | 91理论片午午伦夜理片久久 | 成人av电影免费观看 | www.在线看片.com | 欧美激情视频三区 | 亚洲国产精品一区二区久久,亚洲午夜 | 丰满少妇在线观看 | 国产精品美女999 | 欧美另类xxx| 日韩中文字幕免费 | 不卡在线一区 | 国产精品伦一区二区三区视频 | 在线中文字幕播放 | 国产日韩欧美在线播放 | 99中文字幕在线观看 | 99九九视频 | 狠狠五月天 | 国产精品一区二区三区四 | 99婷婷| 国产成人三级 | 五月婷婷六月综合 | 欧美日韩亚洲国产一区 | 99视频99| 视频在线日韩 | 一区二区三区在线电影 | 激情影院在线 | 欧美精品久久久久久久久久丰满 | 日本久久精 | 天天五月天色 | free,性欧美 九九交易行官网 | 亚洲精品视频大全 | 丁香六月国产 | 免费看v片 | 高清久久久 | 亚洲精品美女久久 | 日韩激情片在线观看 | 色之综合网 | 免费亚洲黄色 | 久久成人18免费网站 | 美女视频黄的免费的 | 国产精品久久久久久久久久了 | 天堂视频中文在线 | 亚洲欧美在线视频免费 | 色先锋av资源中文字幕 | 五月婷婷国产 | 天天干天天干天天干 | 成人h在线 | 久久精品国产亚洲精品 | 九月婷婷人人澡人人添人人爽 | 日韩三级视频 | 国产在线高清视频 | 国产精品久久久久久久久久久久午夜 | 日韩资源在线观看 | 美女免费网站 | 国产精品久久久久久久久久妇女 | 日韩a欧美 | 日本视频久久久 | 美女精品网站 | 亚洲影院天堂 | 久久久久久久久久电影 | 精品在线观看一区二区三区 | 99色免费视频 | 日本久久电影网 | 久久tv视频 | 啪嗒啪嗒免费观看完整版 | 天天操天天色天天射 | 狠狠狠狠狠狠狠狠 | 国产日女人 | 五月天六月婷婷 | 国产一区二区在线观看视频 | 久草视频免费观 | 亚州精品一二三区 | 国产一级片不卡 | 午夜视频播放 | 日韩欧美在线国产 | 日韩中文字幕在线不卡 | 色婷婷天天干 | 欧美精品一区二区在线观看 | 欧美夫妻性生活电影 | 四虎影视成人永久免费观看亚洲欧美 | 在线看的av网站 | 在线国产专区 | 中文字幕婷婷 | 亚洲精品视频在线观看免费 | 蜜臀久久99精品久久久酒店新书 | а天堂中文最新一区二区三区 | 波多在线视频 | 人人干人人上 | 又黄又爽免费视频 | 亚洲国产精品久久久久久 | 国产成人精品一区二区三区福利 | 亚洲va综合va国产va中文 | 国产精品18久久久久久久久久久久 | 欧美十八 | 亚洲资源在线网 | 97超碰人人澡人人爱学生 | 久久免费黄色网址 | 中文字幕在线观看第一区 | 一本一道久久a久久精品 | 亚洲精品婷婷 | 国产69精品久久久久久 | 中文永久字幕 | 啪啪凸凸 | 日韩欧美中文 | 成人久久18免费网站麻豆 | 国语自产偷拍精品视频偷 | 国产黄色av影视 | 97超碰资源网 | 亚洲三级视频 | 国产精品av久久久久久无 | 最近中文字幕第一页 | 视频在线观看91 | 日韩欧美视频在线观看免费 | 久草精品在线播放 | 91在线永久 | 国产一级片免费视频 | 久久精品综合视频 | 美女网站黄在线观看 | av在线最新 | av丝袜在线 | 99视频国产精品免费观看 | 日本精品久久久久久 | 在线观看视频色 | 日本久久成人 | 国产亚洲无 | av一级一片 | 日韩视| 人人看人人爱 | 黄色的视频 | 精品一区电影 | 免费国产在线视频 | 外国av网| 996久久国产精品线观看 | 亚洲欧美日韩不卡 | www黄色| 亚洲最大的av网站 | 久久免费av| 午夜精品福利一区二区三区蜜桃 | 超碰在线99 | 亚洲黄色免费在线看 | 国产精品video爽爽爽爽 | 久久er99热精品一区二区三区 | 久久免费视频这里只有精品 | 国产网红在线观看 | 美女国内精品自产拍在线播放 | 中文av资源站 | 国产成人久久av免费高清密臂 | 国产精品成久久久久 | 天天操比 | 中文字幕av有码 | 日韩av进入 | 黄色三级网站 | 视频国产一区二区三区 | 狠狠色噜噜狠狠狠狠2022 | 久久久91精品国产一区二区三区 | 亚洲综合网 | 97福利社| 日本精品久久久一区二区三区 | 黄色免费网战 | 欧美一级视频免费 | www.夜夜| 午夜精品中文字幕 | 俺要去色综合狠狠 | 国产成人精品av久久 | 欧美精品一区二区在线播放 | 日韩在线国产精品 | 亚洲欧美国产视频 | 伊人久久电影网 | 亚洲视频高清 | 免费观看xxxx9999片 | 日韩欧美网址 | 免费开视频 | 麻豆视频成人 | 日韩在线不卡 | 亚洲资源在线网 | 国产精品第一页在线观看 | 国产在线精品国自产拍影院 | 天堂黄色片 |