以CreateFile為例,因為它常見,且對應於nt中的函數NtCreateFile。
對於程序中隊CreateFile的調用,編譯器會編譯成如下匯編碼:
先會將參數壓棧,然後調用函數:
01031017 call dword ptr[__imp__CreateFileW@28 (1032000h)]
上面的1032000處的值為0x7664cc56,也就是跳到這個值處。這是應用其它模塊函數的標準方式。(通過導入表跳轉)
看下面的代碼,在kernel32模塊裏面,
_CreateFileWImplementation@28:
7664CC56 mov edi,edi
。。。
7664CC98 push dword ptr [ebp+8]
7664CC9B call _CreateFileW@28(7664CCA9h)
。。。
又調用函數了,看調用方式應該還在kernel32裏面
_CreateFileW@28:
7664CCA9 jmp dword ptr[__imp__CreateFileW@28 (766019E0h)]
貌似和exe中的處理方式壹樣,跳轉到其他模塊的函數時會使用導入表中的對應函數地址。
果然,到KernelBase.dll中了,(發現VS2010每次加載dll都會從定位,這是為了安全著想,不過調試的時候很討厭)
_CreateFileW@28:
75B9A850 mov edi,edi
。。。
準備參數,入棧(44個字節的參數啊),
75B9AA1B lea eax,[ebp-8]
75B9AA1E push eax
75B9AA1F call esi
75B9AA21 mov ebx,eax
75B9AA23 mov edi,0C0000022h
。。。
call了就到了ntdll裏面的_NtCreateFile@44了(這個函數在msdn上有介紹,參數中有處理過的文件名)。這個函數應該是軟件生成的,因為很多這樣的函數,只是調用號和彈出字節數不壹樣,她有個名字叫stub function。
_NtCreateFile@44:
778455C8 mov eax,42h
778455CD mov edx,7FFE0300h
778455D2 call dword ptr [edx]
778455D4 ret 2Ch
上面的42h是win7中nt!NtCreateFile的系統調用編號(和win2003的不壹樣了,微軟真惡心)。7FFE0300h是壹個固定的位置,該位置根據cpu是否支持sysenter設置成不同的函數。
下面就到了KiFastSystemCall了:
_KiFastSystemCall@0:
778470B0 mov edx,esp
778470B2 sysenter
調用上面這個又進無回的函數之前,eax是系統調用的調用號,那edx是什麽了?看下面的棧結構:
KiFastSystemCall@0的返回後的eip地址
_NtCreateFile@44返回後的eip地址
參數1
參數2
參數3這個參數裏面含有路徑信息。驗證方法看下面.
。。。
參數11
所以,edx-8為第壹個參數的地址。參數3驗證為:
找到參數3的內容(4字節),該地址指向POBJECT_ATTRIBUTES結構,該結構在msdn中有定義,第3個成員就是文件名。
好了,用戶態就這麽多了,剩下了就要進入內核了。