• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            S.l.e!ep.¢%

            像打了激速一樣,以四倍的速度運轉,開心的工作
            簡單、開放、平等的公司文化;尊重個性、自由與個人價值;
            posts - 1098, comments - 335, trackbacks - 0, articles - 1
              C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理

            在內核調試會話中設置用戶態斷點

            Posted on 2009-11-02 17:18 S.l.e!ep.¢% 閱讀(638) 評論(0)  編輯 收藏 引用 所屬分類: WinDbg

            在內核調試會話中設置用戶態斷點

            使用內核調試會話也可以執行一些用戶態調試任務,比如向位于用戶態的模塊設置斷點。但這樣做與使用用戶態調試器有什么不同呢?我們就以向NTDLL.dll模塊的ZwTerminateProcess函數(Stub)為例談談二者的區別。

            區別一、在內核調試會話中設置這個斷點的“難度”略大些。這是因為NTDLL不屬于內核態的模塊,所以內核會話通常不會加載這個模塊(的符號),因此當執行bp命令時很可能被自動蛻化為bu命令。

            0:?kd>?bp?ntdll!ZwTerminateProcess
            Bp?expression?'ntdll!ZwTerminateProcess'?could?not?be?resolved,?adding?deferred?bp

            恢復執行后,一般的操作也不會觸發調試器來加載NTDLL模塊和解決這個未決的斷點。因此再中斷下來,重新加載符號也可能沒有用:

            2:?kd>?.reload
            Connected?to?Windows?Vista?6000?x86?compatible?target,?ptr64?FALSE
            Loading?Kernel?Symbols
            .............................................................................................................................
            Loading?User?Symbols

            Loading?unloaded?module?list
            ........
            2:?kd>?bl
            ?0?eu?????????????0001?(0001)?(ntdll!ZwTerminateProcess)

            使用.reload命令強制加載這個模塊也不那么容易:

            0:?kd>?.reload?/s?/f?ntdll.dll

            "ntdll.dll"?was?not?found?in?the?image?list.
            Debugger?will?attempt?to?load?"ntdll.dll"?at?given?base?00000000.

            Please?provide?the?full?image?name,?including?the?extension?(i.e.?kernel32.dll)
            for?more?reliable?results.Base?address?and?size?overrides?can?be?given?as
            .reload?<image.ext>=<base>,<size>.
            Unable?to?add?module?at?00000000

            那么該如何設置呢?方法一需要以下幾步:

            1.A?使用!process命令顯示當前進程:

            kd>?!process
            PROCESS?80af22a0??SessionId:?none??Cid:?0000????Peb:?00000000??ParentCid:?0000
            ????DirBase:?00039000??ObjectTable:?e1001e38??HandleCount:?240.
            ????Image:?Idle

            如果像上面這樣是IDLE進程或者是System這些沒有用戶態的進程,那么就需要執行下面一步,否則跳到1.C。

            1.B?使用!process?0?0命令列出所有進程,然后選一個普通的Windows進程,并切換到這個進程:

            kd>?!process?0?0?
            ****?NT?ACTIVE?PROCESS?DUMP?****

            ...
            PROCESS?82748330??SessionId:?0??Cid:?0110????Peb:?7ffde000??ParentCid:?059c
            ????DirBase:?13076000??ObjectTable:?e1a55640??HandleCount:??72.
            ????Image:?notepad.exe

            kd>?.PROCESS?82748330
            Implicit?process?is?now?82748330
            WARNING:?.cache?forcedecodeuser?is?not?enabled

            1.C?執行.reload或.reload?/user重新加載符號:

            kd>?.reload
            Connected?to?Windows?XP?2600?x86?compatible?target,?ptr64?FALSE
            Loading?Kernel?Symbols
            ................................................................................................
            Loading?User?Symbols
            ...............................
            Loading?unloaded?module?list
            ..............................
            kd>?lm?m?ntdll
            start????end????????module?name
            7c800000?7c8c3000???ntdll??????(pdb?symbols)??????????d:\symbols\ntdll.pdb\9A2A73EBE8194059A14361915257B0B01\ntdll.pdb

            第二種看起來可能更費事的方法就是在系統服務的內核函數設置斷點,斷點命中后,執行棧回溯這樣的命令,再執行.reload(加/user會省些時間,不是必須)。例如:

            0:?kd>?bp?nt!NtTerminateProcess
            0:?kd>?g

            Breakpoint?2?hit
            nt!NtTerminateProcess:
            81a1b043?8bff????????????mov?????edi,edi
            0:?kd>?kv
            ChildEBP?RetAddr??Args?to?Child??????????????
            9f272d54?8188c96a?00000000?00000000?0021f998?nt!NtTerminateProcess
            9f272d54?77c20f34?00000000?00000000?0021f998?nt!KiFastCallEntry+0x12a?(FPO:?[0,3]?TrapFrame?@?9f272d64)
            WARNING:?Frame?IP?not?in?any?known?module.?Following?frames?may?be?wrong.
            0021f998?7682d873?00000000?77e8f3b0?ffffffff?0x77c20f34
            ...

            0:?kd>?.reload
            Connected?to?Windows?Vista?6000?x86?compatible?target,?ptr64?FALSE
            Loading?Kernel?Symbols
            ..............................................................................................................................
            Loading?User?Symbols
            ..................

            再執行kv:
            0:?kd>?kv
            ChildEBP?RetAddr??Args?to?Child??????????????
            9f272d54?8188c96a?00000000?00000000?0021f998?nt!NtTerminateProcess
            9f272d54?77c20f34?00000000?00000000?0021f998?nt!KiFastCallEntry+0x12a?(FPO:?[0,3]?TrapFrame?@?9f272d64)
            0021f978?77c20580?77bfa35f?00000000?00000000?ntdll!KiFastSystemCallRet?(FPO:?[0,0,0])
            0021f97c?77bfa35f?00000000?00000000?00af0e70?ntdll!NtTerminateProcess+0xc?(FPO:?[2,0,0])
            0021f998?7682d872?00000000?77e8f3b0?ffffffff?ntdll!RtlExitUserProcess+0x39?(FPO:?[Non-Fpo])

            此時可以確信內核調試會話已經加載NTDLL的符號了,再顯示斷點:

            0:?kd>?bl
            ?0?e?77c20574?????0001?(0001)?ntdll!NtTerminateProcess
            ?2?e?81a1b043?????0001?(0001)?nt!NtTerminateProcess

            這個顯示表明內核調試會話已經落實了這個用戶態的斷點。

            如果是在加載NTDLL模塊后再執行bp命令,恢復執行后,KD會有一個提示告訴我們它成功的向斷點位置寫入了INT?3。

            0:?kd>?bp?ntdll!ZwTerminateProcess
            0:?kd>?bl
            ?0?e?77c20574??0001?(0001)?ntdll!NtTerminateProcess

            0:?kd>?g
            KD:?write?to?77c20574??ok

            相對而言,如果是在用戶態調試會話中,因為NTDLL會被映射到所有用戶態進程中,而且ZwTerminateProcess是導出的函數,所以bp?ntdll!ZwTerminateProcess會非常順利的執行。

            區別二、斷點的作用范圍不同,在內核調試會話中設置的ntdll!NtTerminateProcess斷點會影響所有進程(可能有特例),而在用戶態調試中對這個位置設置的斷點只對當前進程有效。舉例來說,剛才在內核調試會話中設置bp斷點時的當前進程是notepad,但是當我們關閉計算器進程時這個斷點也會命中。甚至當我們新啟動一個WinMine程序,然后關閉它時,斷點也會命中。

            相對而言,如果是在調試notepad進程的用戶態調試會話中對ntdll!NtTerminateProcess設置一個斷點,那么這絕不會影響其它進程。

            那么為什么有這個差異呢?

            首先解釋一下,為什么在內核調試會話中設置的斷點會影響所有進程。還是通過試驗來說明,我們先想辦法觀察到我們設置的斷點所對應的INT?3指令。當KD落實我們的斷點后,將目標再中斷到調試器,這時無論是直接觀察線性地址還是物理地址,都看不到INT?3:

            1:?kd>?dd?77c20574
            77c20574??000152cc?0300ba00?12ff7ffe?900008c2
            77c20584??000153b8?0300ba00?12ff7ffe?900008c2
            77c20594??000154b8?0300ba00?12ff7ffe?00498dc3
            77c205a4??000155b8?0300ba00?12ff7ffe?00498dc3
            77c205b4??000156b8?0300ba00?12ff7ffe?00498dc3
            77c205c4??000157b8?0300ba00?12ff7ffe?900010c2
            77c205d4??000158b8?0300ba00?12ff7ffe?900018c2
            77c205e4??000159b8?0300ba00?12ff7ffe?900010c2

            0:?kd>?!pte?77c20574?????
            ???????????????VA?77c20574
            PDE?at?00000000C0601DF0????PTE?at?00000000C03BE100
            contains?000000001C9AC867??contains?000000001DDDD025
            pfn?1c9ac?---DA--UWEV????pfn?1dddd?----A--UREV

            0:?kd>?!dd?1dddd574?
            #1dddd574?000152b8?0300ba00?12ff7ffe?900008c2
            #1dddd584?000153b8?0300ba00?12ff7ffe?900008c2
            #1dddd594?000154b8?0300ba00?12ff7ffe?00498dc3
            #1dddd5a4?000155b8?0300ba00?12ff7ffe?00498dc3
            #1dddd5b4?000156b8?0300ba00?12ff7ffe?00498dc3
            #1dddd5c4?000157b8?0300ba00?12ff7ffe?900010c2
            #1dddd5d4?000158b8?0300ba00?12ff7ffe?900018c2
            #1dddd5e4?000159b8?0300ba00?12ff7ffe?900010c2

            這是因為調試器在將目標中斷到調試器之前會恢復已經設置的斷點,按Ctrl+Alt+D啟用WinDBG與KD的通信過程后就可以看到這樣的信息:

            DbgKdRestoreBreakPoint(1)?returns?00000000

            當恢復執行時,WinDBG會重新把斷點寫入:

            DbgKdWriteBreakPoint(77c20574)?returns?00000000,?1


            那么如何觀察到寫入的INT?3呢?一種很愜意的方法就是使用ITP這樣的硬件調試器,用了ITP,對付這樣的任務真是手到擒來(圖1)。

            http://advdbg.com/img/inset/bp_at_ntdll.bmp

            圖1?使用硬件調試器觀察斷點指令(0xCC)

            因為NTDLL是映射到所有進程中的,所以每個進程執行NtTerminateProcess函數時都會撞見這個0xCC,于是乎這個斷點對所有進程都起作用也就在情理之中了。

            下面再說說另一種情況,也就是在用戶態調試器中對ntdll!NtTerminateProcess設置斷點,難道這時就沒有把0xCC寫在大家都會“撞見”的地方么?的確如此。

            我們在內核調試會話中使用bc?*命令清除所有斷點,并恢復執行一次,而且通過ITP觀察確保剛才的0xcc已經不在。然后在目標系統中啟動系統中自帶的 NTSD來調試計算器程序,并使用bp?ntdll!NtTerminateProcess設置一個斷點。恢復執行一次,以便讓調試器寫入這個斷點。然后退出計算器程序,這時計算器程序會中斷到NTSD,NTSD中不做分析,直接用g命令恢復執行,這下,我們前面設置的nt! NtTerminateProcess斷點會命中,也就是中斷到內核調試器中。

            在內核調試器中,觀察nt!NtTerminateProcess所對應的線性地址:

            1:?kd>?dd?77c20574
            77c20574??000152cc?0300ba00?12ff7ffe?900008c2
            77c20584??000153b8?0300ba00?12ff7ffe?900008c2
            77c20594??000154b8?0300ba00?12ff7ffe?00498dc3
            77c205a4??000155b8?0300ba00?12ff7ffe?00498dc3
            77c205b4??000156b8?0300ba00?12ff7ffe?00498dc3
            77c205c4??000157b8?0300ba00?12ff7ffe?900010c2
            77c205d4??000158b8?0300ba00?12ff7ffe?900018c2
            77c205e4??000159b8?0300ba00?12ff7ffe?900010c2

            睜大眼睛看那個0xCC,對的,這里的確有0xCC。因為內核斷點已經取消了,這一定是用戶態調試器寫入的。

            接下來的問題是,既然這里有0xCC,那么為什么不影響其它進程呢?注意這個線性地址與前面的一模一樣。

            其中的奧妙在于這個線性地址已經不再是前面那個物理地址了:

            1:?kd>?!pte?77c20574?
            ???????????????VA?77c20574
            PDE?at?00000000C0601DF0????PTE?at?00000000C03BE100
            contains?00000000012E0867??contains?00000000049BD025
            pfn?12e0?---DA--UWEV????pfn?49bd?----A--UREV

            雖然還同是一個線性地址,但是它現在對應的物理地址變成了49bd574。觀察這個物理地址,其內容與剛才使用線性地址的得到的結果是一樣的:

            1:?kd>?!dd?49bd574?
            #?49bd574?000152cc?0300ba00?12ff7ffe?900008c2
            #?49bd584?000153b8?0300ba00?12ff7ffe?900008c2
            #?49bd594?000154b8?0300ba00?12ff7ffe?00498dc3
            #?49bd5a4?000155b8?0300ba00?12ff7ffe?00498dc3
            #?49bd5b4?000156b8?0300ba00?12ff7ffe?00498dc3
            #?49bd5c4?000157b8?0300ba00?12ff7ffe?900010c2
            #?49bd5d4?000158b8?0300ba00?12ff7ffe?900018c2
            #?49bd5e4?000159b8?0300ba00?12ff7ffe?900010c2

            而此時,物理地址1dddd574那里根本沒有0xCC。

            說到這里,謎團基本揭開了。事實上,?對于一個普通的進程,系統會把NTDLL的代碼映射給它,如果這個進程始終很普通,那么它便會永遠使用這份映射過來的代碼。但是當它要修改代碼時,系統會執行所謂的Copy?on?Write動作,為其復制一份,讓它來寫。結合我們的情況,當在用戶態調試會話中向 NTDLL中設置斷點時,系統為其復制了一份代碼,讓它去寫,因此它寫入的斷點只有它自己“撞的到”,不會影響其它進程。但是當在內核會話中寫入斷點時,因為是內核調試引擎執行的寫動作,所以沒有觸發Copy?on?Write,因此KD寫入的斷點寫在了公共的代碼上,會影響到使用這個公共代碼的所有進程。


            原文出處:http://advdbg.com/blogs/advdbg_syste...cles/1492.aspx

            《軟件調試》下載:http://bv.csdn.net/resource/rjts.pdf

            久久国产精品二国产精品| 久久久亚洲欧洲日产国码二区| 777午夜精品久久av蜜臀 | 欧美丰满熟妇BBB久久久| 亚洲欧美日韩精品久久亚洲区| 久久精品二区| 手机看片久久高清国产日韩| 久久夜色精品国产www| 色综合久久中文字幕综合网| 婷婷久久综合| 亚洲精品美女久久久久99| 久久久精品国产sm调教网站| 99久久免费国产特黄| 99久久精品久久久久久清纯| 久久精品无码一区二区三区免费| 狠狠人妻久久久久久综合蜜桃| 无码人妻久久一区二区三区蜜桃| 四虎国产精品免费久久| 亚洲国产另类久久久精品小说 | 99久久精品费精品国产 | 亚洲一区精品伊人久久伊人 | 国内精品久久久久| 国产一区二区精品久久凹凸| 一本综合久久国产二区| 奇米影视7777久久精品| 国产成人久久精品二区三区| 中文字幕无码av激情不卡久久| 久久Av无码精品人妻系列| 国产—久久香蕉国产线看观看| 欧美日韩精品久久免费| 久久精品嫩草影院| 伊人久久大香线蕉综合5g| 精品九九久久国内精品| 欧美黑人激情性久久| 91久久精品国产91性色也| 伊人久久大香线蕉亚洲| 精品无码久久久久久久久久| 亚洲狠狠婷婷综合久久蜜芽| 色播久久人人爽人人爽人人片aV | 国产亚州精品女人久久久久久 | 精品永久久福利一区二区|