APC 篇——初識 APC


寫在前面

  此系列是本人一個字一個字碼出來的,包括示例和實驗截圖。由於系統內核的復雜性,故可能有錯誤或者不全面的地方,如有錯誤,歡迎批評指正,本教程將會長期更新。 如有好的建議,歡迎反饋。碼字不易,如果本篇文章有幫助你的,如有閑錢,可以打賞支持我的創作。如想轉載,請把我的轉載信息附在文章后面,並聲明我的個人信息和本人博客地址即可,但必須事先通知我

你如果是從中間插過來看的,請仔細閱讀 羽夏看Win系統內核——簡述 ,方便學習本教程。

  看此教程之前,問幾個問題,基礎知識儲備好了嗎?保護模式篇學會了嗎?練習做完了嗎?沒有的話就不要繼續了。


🔒 華麗的分割線 🔒


APC 結構

  上一篇我們簡單介紹了APC的概念。有些人可能對為什么線程不能被“殺掉”、“掛起”和“恢復”還是有些疑問,我們舉個極端的例子:如果不調用API,屏蔽中斷,並保證代碼不出現異常,線程將永久占用CPU,何談控制呢?所以說線程如果想“死”,一定是自己執行代碼把自己殺死,不存在“他殺”這種情況。我們可以畫個簡單的示意圖:

  下面我們來看看存儲APC的結構體:

kd> dt _KAPC
ntdll!_KAPC
   +0x000 Type             : Int2B
   +0x002 Size             : Int2B
   +0x004 Spare0           : Uint4B
   +0x008 Thread           : Ptr32 _KTHREAD
   +0x00c ApcListEntry     : _LIST_ENTRY
   +0x014 KernelRoutine    : Ptr32     void 
   +0x018 RundownRoutine   : Ptr32     void 
   +0x01c NormalRoutine    : Ptr32     void 
   +0x020 NormalContext    : Ptr32 Void
   +0x024 SystemArgument1  : Ptr32 Void
   +0x028 SystemArgument2  : Ptr32 Void
   +0x02c ApcStateIndex    : Char
   +0x02d ApcMode          : Char
   +0x02e Inserted         : UChar

  存在於KTHREAD結構體的0x34偏移的位置有一個ApcState,如下所示:

kd> dt _KTHREAD
nt!_KTHREAD
    ...
       +0x034 ApcState         : _KAPC_STATE
    ...

  我們看到這個存着一個結構體,如下所示:

kd> dt _KAPC_STATE
ntdll!_KAPC_STATE
   +0x000 ApcListHead      : [2] _LIST_ENTRY
   +0x010 Process          : Ptr32 _KPROCESS
   +0x014 KernelApcInProgress : UChar
   +0x015 KernelApcPending : UChar
   +0x016 UserApcPending   : UChar

ApcListHead

  第一個成員ApcListHead是個雙向鏈表的數組,一共有兩個成員,所謂的APC就是插入到里面的,給個示意圖如下:

  ApcListHead一個成員存儲着用戶APC,用戶APC的函數地址位於用戶空間,在用戶空間執行;另一個成員存儲着內核APC,內核APC函數地址位於內核空間,在內核空間執行。

Process

  線程線程所屬或者所掛靠的進程,這個在逆向線程切換的時候我們就用過。具體細節都在進程線程篇的總結與提升講過,就不再贅述了。

KernelApcInProgress

  指示內核APC是否正在執行。

KernelApcPending

  指示是否有正在等待執行的內核APC

UserApcPending

  指示是否有正在等待執行的用戶APC

小結

  上面的介紹僅僅是對APC的初步講解,里面所有的詳細細節將在后面的教程講解。后面會詳細介紹KAPC這個結構體,並研究APC是誰插入的、插入到哪里、誰執行APC和什么時候執行APC。本篇是對后面學習的鋪墊。

本節練習

本節的答案將會在下一節進行講解,務必把本節練習做完后看下一個講解內容。不要偷懶,實驗是學習本教程的捷徑。

  俗話說得好,光說不練假把式,如下是本節相關的練習。如果練習沒做好,就不要看下一節教程了,越到后面,不做練習的話容易夾生了,開始還明白,后來就真的一點都不明白了。本節練習不多,請保質保量的完成。

1️⃣ 使用現成提供的API,自己編寫代碼向某個線程插入一個用戶APC
2️⃣ 分析TerminateThreadSuspendThread是如何實現的(從3環開始分析)。(要求:只需逆向分析到別的進程是如何控制目標進程行為,其他細節暫時不需分析,本題參考將會在正文給出。)

下一篇

  APC 篇——備用 APC 隊列


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM