__declspec(naked)详解
__declspec(naked)是用來告訴編譯器函數代碼的匯編語言為自己的所寫,不需要編譯器添加任何匯編代碼
注意點:
[cpp]?view plaincopy注意,__declspec(naked)是編譯器直接拿來用的匯編函數代碼,所以一定要記得在開始的時候保存上下文標志位(壓棧),在結束的時候要記得恢復上下文(出棧)。并且在結尾要加上ret命令
比較下面兩段代碼:(都是調用strcmp函數)
[cpp]?view plaincopy
對于jmp類型的hook, 如果自己的過程沒有使用_declspec(naked),那么系統會自動給添加一些額外的代碼,控制堆棧平衡,但是這些額外的代碼會破壞被hook函數的堆棧。對于call類型的hook,如果使用_declspec(naked)修飾的話,要注意自己恢復堆棧平衡。使用__declspec(naked)關鍵字定義函數:
1,使用 naked 關鍵字必須自己構建 EBP 指針 (如果用到了的話,如果最后是JMP到原函數,要自己在開始構建push ebp mov ebp, esp pushad pushfd在最后加popfd popad mov esp, ebp, pop ebp jmp xxxx);
2,必須自己使用 RET 或 RET n 指令返回?(除非你不返回,比如JMP到原函數); 對于一般的匯編內嵌代碼(沒有使用_declspec(naked)),不必保存上下文了,保存也不會有事,但是不能再加ret命令,因為編譯器也會為其加一個,ret命令不能同時執行兩次。會導致越界錯誤
?
?剛發現,在naked函數中不能出現如int i=0;這樣的賦值
在標明naked的函數中是不可以使用任何賦值都是不允許的。如果非要想用可以另寫一個函數進行處理,處理完成后將結果返回既可。如果使用VS會提示以下錯誤。
?initialized auto or register variable not allowed at function scope in 'naked' function
其實原因也很好解釋,因為naked和父函數共用一個ebp, 所以要子局部變量,就用esp,
naked函數就不要帶參數了,帶參數的沒必要寫成naked函數
總結
以上是生活随笔為你收集整理的__declspec(naked)详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 反汇编RETN 0x0c的理解
- 下一篇: Socket重叠IO