Windows系統調用中的系統服務表

 Windows內核分析索引目錄:https://www.cnblogs.com/onetrainee/p/11675224.htmlhtml

Windows系統調用中的系統服務表函數

  若是這部分不理解,能夠查看 Windows內核分析索引目錄依次閱讀。spa

  咱們在以前講過系統調用過程當中,給予eax一個編號,操做系統經過這個編號來執行某個內核函數。操作系統

  這個函數是經過操做系統的系統服務表來查找的。線程

  如今,咱們來探究一下nt!KiFastCallEntry的反彙編代碼,看看其如何查看系統服務表找到要執行的函數的。3d

 

1、系統服務表結構指針

  Windows一共有兩張表,每張表大小10h,每一個成員佔4h。code

  如圖,其中函數地址表每成員四字節,函數參數表每成員一字節。htm

  參數的數值是以字節爲單位。blog

  

2、系統服務表在哪裏

  在Win7 32位中存於 [KTHREAD+0xbc]

  kd> dt _KTHREAD
    ntdll!_KTHREAD

    +0x000 Header           : _DISPATCHER_HEADER

    ·······

    +0x0bc ServiceTable     : Ptr32 Void

    ····

  該結構地址爲第一個表

  

3、要判斷使用哪一個表

  傳入函數序號的第12位,存儲的就是關於使用那個表的標誌,若是爲0,則調用第一張表,若是爲2,則調用第二張表。

  大於12位的值其實所有是忽略的。

  

4、找到要執行的函數

  如圖,經過第0-11位做爲序號,找到函數地址表和函數參數表。

  以參數表中的數值做爲開闢新的棧的大小,以後開闢新的棧,將參數傳入進來,以後根據函數地址表來調用內核函數。

  

 

 5、nt!KiFastCallEntry反彙編代碼分析

  結合上面內容以及windgb實操來理解下面的反彙編代碼。

  1 nt!KiFastCallEntry:
  2 83e8d0c0 b923000000      mov     ecx,23h
  3 83e8d0c5 6a30            push    30h
  4 83e8d0c7 0fa1            pop     fs
  5 83e8d0c9 8ed9            mov     ds,cx
  6 83e8d0cb 8ec1            mov     es,cx
  7 83e8d0cd 648b0d40000000  mov     ecx,dword ptr fs:[40h]
  8 83e8d0d4 8b6104          mov     esp,dword ptr [ecx+4]
  9 83e8d0d7 6a23            push    23h
 10 83e8d0d9 52              push    edx
 11 83e8d0da 9c              pushfd
 12 83e8d0db 6a02            push    2
 13 83e8d0dd 83c208          add     edx,8
 14 83e8d0e0 9d              popfd
 15 83e8d0e1 804c240102      or      byte ptr [esp+1],2
 16 83e8d0e6 6a1b            push    1Bh
 17 83e8d0e8 ff350403dfff    push    dword ptr ds:[0FFDF0304h]
 18 83e8d0ee 6a00            push    0
 19 83e8d0f0 55              push    ebp
 20 83e8d0f1 53              push    ebx
 21 83e8d0f2 56              push    esi
 22 83e8d0f3 57              push    edi
 23 83e8d0f4 648b1d1c000000  mov     ebx,dword ptr fs:[1Ch]  // fs:[1ch] 爲SelfProc,故 ebx 指向本身
 24 83e8d0fb 6a3b            push    3Bh
 25 83e8d0fd 8bb324010000    mov     esi,dword ptr [ebx+124h] // esi指向當前線程 KTHREAD(也是ETHREAD,ETHREA包含KTHREAD且在頭部)
 26 83e8d103 ff33            push    dword ptr [ebx]
 27 83e8d105 c703ffffffff    mov     dword ptr [ebx],0FFFFFFFFh
 28 83e8d10b 8b6e28          mov     ebp,dword ptr [esi+28h]
 29 83e8d10e 6a01            push    1
 30 83e8d110 83ec48          sub     esp,48h
 31 83e8d113 81ed9c020000    sub     ebp,29Ch
 32 83e8d119 c6863a01000001  mov     byte ptr [esi+13Ah],1
 33 83e8d120 3bec            cmp     ebp,esp
 34 83e8d122 7597            jne     nt!KiFastCallEntry2+0x49 (83e8d0bb)
 35 83e8d124 83652c00        and     dword ptr [ebp+2Ch],0
 36 83e8d128 f64603df        test    byte ptr [esi+3],0DFh
 37 83e8d12c 89ae28010000    mov     dword ptr [esi+128h],ebp
 38 83e8d132 0f8538feffff    jne     nt!Dr_FastCallDrSave (83e8cf70)
 39 83e8d138 8b5d60          mov     ebx,dword ptr [ebp+60h]
 40 83e8d13b 8b7d68          mov     edi,dword ptr [ebp+68h]
 41 83e8d13e 89550c          mov     dword ptr [ebp+0Ch],edx
 42 83e8d141 c74508000ddbba  mov     dword ptr [ebp+8],0BADB0D00h
 43 83e8d148 895d00          mov     dword ptr [ebp],ebx
 44 83e8d14b 897d04          mov     dword ptr [ebp+4],edi
 45 83e8d14e fb              sti
 46 83e8d14f 8bf8            mov     edi,eax
 47 
 48 // 判斷12位是0仍是1,而後決定使用那張表
 49 // 計算結果 ecx與edi  爲 0h 或者 10h
 50 83e8d151 c1ef08          shr     edi,8        
 51 83e8d154 83e710          and     edi,10h
 52 83e8d157 8bcf            mov     ecx,edi // ECX中存儲的值爲0x00或者0x10(調用號大於0x1000的話)
 53 
 54 
 55 // 注意,ServiceTable表開始部分位於 [esi+0BCh] 指針處
 56 // 該地址Notoskrl.exe的表。
 57 // 下一個表結構是Win32k.sys的表
 58 // 由於咱們根據表結構,一張表10h(4個成員,每一個成員4字節)
 59 // 因此若爲win32K.sys, add 10h,天然跳轉到關於win32k.sys的這張表 
 60 83e8d159 03bebc000000    add     edi,dword ptr [esi+0BCh] // 存儲 ServiceTable  這張表
 61 
 62 // 系統服務號存到ebx備份一份
 63 83e8d15f 8bd8            mov     ebx,eax // 系統服務號存到ebx備份一份
 64 83e8d161 25ff0f0000      and     eax,0FFFh // 系統調用號,只須要12後12爲
 65 
 66 // 比較該函數索引號與表函數個數判讀,若是索引號>=函數表個數,則說明函數不在這張表中,觸發異常
 67 83e8d166 3b4708          cmp     eax,dword ptr [edi+8]
 68 83e8d169 0f8333fdffff    jae     nt!KiBBTUnexpectedRange (83e8cea2)
 69 
 70 // 若沒有越界,則判斷是哪一個系統表win32k.sys
 71 // 若是是調用win32k.sys,則執行下面這部分函數,win32k.sys跟圖形界面相關,關於動態加載的問題(nt!KeGdiFlushUserBatch。
 72 // 若是是調用Notoskrl.exe,則直接跳轉到 83e8d18e
 73 83e8d16f 83f910          cmp     ecx,10h
 74 83e8d172 751a            jne     nt!KiFastCallEntry+0xce (83e8d18e)
 75 83e8d174 8b8e88000000    mov     ecx,dword ptr [esi+88h]
 76 83e8d17a 33f6            xor     esi,esi
 77 83e8d17c 0bb1700f0000    or      esi,dword ptr [ecx+0F70h]
 78 83e8d182 740a            je      nt!KiFastCallEntry+0xce (83e8d18e)
 79 83e8d184 52              push    edx
 80 83e8d185 50              push    eax
 81 83e8d186 ff154c99fb83    call    dword ptr [nt!KeGdiFlushUserBatch (83fb994c)] // win
 82 83e8d18c 58              pop     eax
 83 83e8d18d 5a              pop     edx
 84 
 85 // 若爲 notoskrl.exe中,從83e8d172直接跳轉過來;若是爲win32.sys,則須要執行上邊過程
 86 83e8d18e 64ff05b0060000  inc     dword ptr fs:[6B0h] // KPCR->+0x6B0 KeSystemCalls 系統調用個數+1
 87 83e8d195 8bf2            mov     esi,edx // edx存儲着三環傳入函數的指針
 88 83e8d197 33c9            xor     ecx,ecx // 將ecx清零
 89 83e8d199 8b570c          mov     edx,dword ptr [edi+0Ch] //_SYSTEM_SERVICE_TABLE+0ch,獲得SSDT參數表地址
 90 83e8d19c 8b3f            mov     edi,dword ptr [edi]    // _SYSTEM_SERVICE_TABLE+0h,函數表的地址
 91 83e8d19e 8a0c10          mov     cl,byte ptr [eax+edx] // eax系統調用號 參數表*系調用號獲得的參數個數cl。
 92 83e8d1a1 8b1487          mov     edx,dword ptr [edi+eax*4] // 真正的函數地址edx = eax函數索引*4+edi指向參數地址表
 93 83e8d1a4 2be1            sub     esp,ecx   // 提高堆棧,有多少參數提高多少個            
 94 83e8d1a6 c1e902          shr     ecx,2    // 參數總長度/4 == 參數複製的次數(由於在83e8d1b7處使用rep指令一次複製四個字節)     
 95 83e8d1a9 8bfc            mov     edi,esp // 設置要複製的地址
 96 
 97 //esi存儲調用內核函數的指針,跟用戶地址函數能訪問的最大範圍進行判斷,若是超出了則跳轉到錯誤處理模塊
 98 83e8d1ab 3b351c97fb83    cmp     esi,dword ptr [nt!MmUserProbeAddress (83fb971c)]
 99 83e8d1b1 0f832e020000    jae     nt!KiSystemCallExit2+0xa5 (83e8d3e5)
100 
101 // 複製函數參數 
102 83e8d1b7 f3a5            rep movs dword ptr es:[edi],dword ptr [esi]
103 
104 
105 // 下面來進行某些必要的檢測  
106 83e8d1b9 f6456c01        test    byte ptr [ebp+6Ch],1
107 83e8d1bd 7416            je      nt!KiFastCallEntry+0x115 (83e8d1d5)
108 83e8d1bf 648b0d24010000  mov     ecx,dword ptr fs:[124h]
109 83e8d1c6 8b3c24          mov     edi,dword ptr [esp]
110 83e8d1c9 89993c010000    mov     dword ptr [ecx+13Ch],ebx
111 83e8d1cf 89b92c010000    mov     dword ptr [ecx+12Ch],edi
112 83e8d1d5 8bda            mov     ebx,edx
113 83e8d1d7 f6050869f88340  test    byte ptr [nt!PerfGlobalGroupMask+0x8 (83f86908)],40h
114 83e8d1de 0f954512        setne   byte ptr [ebp+12h]
115 83e8d1e2 0f858c030000    jne     nt!KiServiceExit2+0x17b (83e8d574)
116 
117 // 若是上面檢測沒問題,則開始執行函數
118 83e8d1e8 ffd3            call    ebx
119 
120 // 判斷執行結果並返回給用戶層
121 83e8d1ea f6456c01        test    byte ptr [ebp+6Ch],1
122 83e8d1ee 7434            je      nt!KiFastCallEntry+0x164 (83e8d224)
123 83e8d1f0 8bf0            mov     esi,eax
124 83e8d1f2 ff156801e583    call    dword ptr [nt!_imp__KeGetCurrentIrql (83e50168)]
125 83e8d1f8 0ac0            or      al,al
126 83e8d1fa 0f853b030000    jne     nt!KiServiceExit2+0x142 (83e8d53b)
127 83e8d200 8bc6            mov     eax,esi
128 83e8d202 648b0d24010000  mov     ecx,dword ptr fs:[124h]
129 83e8d209 f68134010000ff  test    byte ptr [ecx+134h],0FFh
130 83e8d210 0f8543030000    jne     nt!KiServiceExit2+0x160 (83e8d559)
131 83e8d216 8b9184000000    mov     edx,dword ptr [ecx+84h]
132 83e8d21c 0bd2            or      edx,edx
133 83e8d21e 0f8535030000    jne     nt!KiServiceExit2+0x160 (83e8d559)
134 83e8d224 8be5            mov     esp,ebp
135 83e8d226 807d1200        cmp     byte ptr [ebp+12h],0
136 83e8d22a 0f8550030000    jne     nt!KiServiceExit2+0x187 (83e8d580)
137 83e8d230 648b0d24010000  mov     ecx,dword ptr fs:[124h]
138 83e8d237 8b553c          mov     edx,dword ptr [ebp+3Ch]
139 83e8d23a 899128010000    mov     dword ptr [ecx+128h],edx
相關文章
相關標籤/搜索