__declspec(naked)详解
2015-12-30 13:20
751 查看
__declspec(naked)是用来告诉编译器函数代码的汇编语言为自己的所写,不需要编译器添加任何汇编代码
注意点:
[cpp] view
plaincopy
void __declspec(naked) funname()
{
_asm
{
...
[cpp] view
plaincopy
ret
}
}
注意,__declspec(naked)是编译器直接拿来用的汇编函数代码,所以一定要记得在开始的时候保存上下文标志位(压栈),在结束的时候要记得恢复上下文(出栈)。并且在结尾要加上ret命令
比较下面两段代码:(都是调用strcmp函数)
[cpp] view
plaincopy
VOID __declspec(naked) MyNakedFunction()
{
strcmp(...);
// __cdecl 函数是调用者清除参数堆栈,对于非内联汇编调用这类函数,编译器将自动平衡堆栈,加入 ADD ESP, 8
}
VOID __declspec(naked) MyNakedFunction()
{
//...
__asm CALL strcmp;
__asm ADD ESP, 8; // 内联汇编需要自己平衡堆栈
}
对于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函数
注意点:
[cpp] view
plaincopy
void __declspec(naked) funname()
{
_asm
{
...
[cpp] view
plaincopy
ret
}
}
注意,__declspec(naked)是编译器直接拿来用的汇编函数代码,所以一定要记得在开始的时候保存上下文标志位(压栈),在结束的时候要记得恢复上下文(出栈)。并且在结尾要加上ret命令
比较下面两段代码:(都是调用strcmp函数)
[cpp] view
plaincopy
VOID __declspec(naked) MyNakedFunction()
{
strcmp(...);
// __cdecl 函数是调用者清除参数堆栈,对于非内联汇编调用这类函数,编译器将自动平衡堆栈,加入 ADD ESP, 8
}
VOID __declspec(naked) MyNakedFunction()
{
//...
__asm CALL strcmp;
__asm ADD ESP, 8; // 内联汇编需要自己平衡堆栈
}
对于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函数
相关文章推荐
- HDU 1115 Lifting the Stone(计算几何)
- STM32端 UCOII+LWIP问题汇总
- Putty完全使用方法
- [LeetCode]题解(python):078-Subsets
- 万能网卡驱动
- Android:ContentProvider、URI、UriMatcher、ContentUris、ContentResolver、ContentObserver
- Foreground Detection: A Fast Self-tuning Background Subtraction Algorithm
- XML-DTD
- iOS开发学习路线
- [ios]纯代码实现UITableViewCell的自定义扩展
- spring4.2+mybatis3.3+freemark+log4j2+fastjson整合
- Java第二课:整数、浮点数
- Linux下SVN服务器同时支持Apache的http和https及svnserve独立服务器三种模式且使用相同的访问权限账号
- Android中的线程池简介
- Fragment+ViewPager(一)
- 将博客搬至CSDN
- Android 媒体 I-媒体播放
- 今天我微博做的回复,关于中国知识灌输教育和国外知识引导教育
- Notepad++ 开启「切分窗口」同时检视、比对两份文件
- 关于Entity Framework中的Attached报错相关解决方案的总结