__declspec(naked)是用来告诉编译器函数代码的汇编语言为自己的所写,不需要编译器添加任何汇编代码

注意点:

[cpp] view plaincopy
  1. void __declspec(naked) funname()
  2. {
  3. _asm
  4. {
  5. ...
[cpp] view plaincopy
  1. ret
  2. }
  3. }

注意,__declspec(naked)是编译器直接拿来用的汇编函数代码,所以一定要记得在开始的时候保存上下文标志位(压栈),在结束的时候要记得恢复上下文(出栈)。并且在结尾要加上ret命令

比较下面两段代码:(都是调用strcmp函数)

[cpp] view plaincopy
  1. VOID __declspec(naked) MyNakedFunction()
  2. {
  3. strcmp(...);
  4. // __cdecl 函数是调用者清除参数堆栈,对于非内联汇编调用这类函数,编译器将自动平衡堆栈,加入 ADD ESP, 8
  5. }
  6. VOID __declspec(naked) MyNakedFunction()
  7. {
  8. //...
  9. __asm CALL strcmp;
  10. __asm ADD ESP, 8; // 内联汇编需要自己平衡堆栈
  11. }

对于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)详解相关推荐

  1. 【转】__declspec用法详解

    __declspec用法详解 __declspec用于指定所给定类型的实例的与Microsoft相关的存储方式.其它的有关存储方式的修饰符如static与extern等是C和 C++语言的ANSI规范 ...

  2. __declspec(dllexport)、__declspec(dllimport)详解

    在Visual studio中新建DLL项目时编译器会自动生成下面这样的宏定义: #ifdef DLL_EXPORTS #define DLL_API __declspec(dllexport) #e ...

  3. pragma comment的使用 pragma预处理指令详解

    pragma comment的使用 pragma预处理指令详解 #pragma comment( comment-type [,"commentstring"] ) 该宏放置一个注 ...

  4. #pragma comment和#pragma 预处理指令详解

    该宏放置一个注释到对象文件或者可执行文件. 例如,#pragma   comment(lib,"Ws2_32.lib")表示链接Ws2_32.lib这个库. 和在工程设置里写上链入 ...

  5. #pragma 详解

    #pragma 求助编辑 pragma - 必应词典 美[p'ræɡmə]英[p'ræɡmə] n.[计]杂注 网络编译指示:显示编译指示:特殊指令 百科名片 在所有的预处理指令中,#Pragma 指 ...

  6. vs cpp生成h文件_lib 和 dll 的区别、生成以及使用详解

    (给CPP开发者加星标,提升C/C++技能) 来源:tenoshttps://www.cnblogs.com/TenosDoIt/p/3203137.html [导读]:在日常开发中,我们只需要知道l ...

  7. JNI详解---从不懂到理解

     Chap1:JNI完全手册... 3 Chap2:JNI-百度百科... 11 Chap 3:javah命令帮助信息... 16 Chap 4:用javah产生一个.h文件... 17 Chap ...

  8. OpenGL,GLUT,FreeGLUT,GLFW,GLEW,GLAD,GL3W,GLAD,GLM,GLSL的区别详解

    OpenGL,GLUT,FreeGLUT,GLFW,GLEW,GLAD,GL3W,GLAD,GLM,GLSL的区别详解 很多同学在初学计算机图形学时,都要去配置OpenGL环境,其中涉及多个库的选择和 ...

  9. C++11、C++14、C++17、C++20新特性总结(5万字详解)

    文章目录 C++ 11是什么,C++ 11标准的由来 C++ auto类型推导完全攻略 auto 类型推导的语法和规则 auto 的高级用法 auto 的限制 auto 的应用 使用 auto 定义迭 ...

最新文章

  1. koa2 mysql sequelize_Vue2+Koa2+Typescript前后端框架教程--05Sequelize(ORM)的使用实现基础的班级增删...
  2. Log4j配置文件以及配置方法
  3. mysql 设置中文 重启_如何启动/停止/重启MySQL + 进入MYSQL-Go语言中文社区
  4. C++打印0到N的Catalan数卡特兰数(附完整源码)
  5. OpenStack部署之小结
  6. 程序的灵魂-----算法
  7. sql2005 无法解决 equal to 操作Chinese_PRC_CI_AS 和 Chinese_PRC_CS_AS 之间的排序
  8. OJ1159: 最大的两个数(指针专题)(C语言)
  9. 二分法08:寻找旋转排序数组中的最小值
  10. asp.net core web api token验证和RestSharp访问
  11. 电脑广告太多,请避免安装这些软件
  12. 面试——嵌入式面试内容和注意事项
  13. Maven读书笔记之七(生命周期和插件)
  14. [Python从零到壹] 五十八.图像增强及运算篇之图像锐化Sobel、Laplacian算子实现边缘检测
  15. 关于英语学习和字幕的那点事儿
  16. Netty4.x 的逆袭之路 —— 再识 Netty
  17. [转载] 如果你在公司遇见这4种情况,说明你该辞职了,千万别犹豫
  18. java如何设置jlabel位置_Java Swing – JLabel位置
  19. windows系统目录programdata和program file(x86)
  20. Python中如何保留n位有效数字

热门文章

  1. 重载练习3_实现重载的println方法
  2. spring配置详解-初始化销毁方法
  3. SpringCloud 定义Eureka服务端、Eureka服务信息、Eureka发现管理、Eureka安全配置、Eureka-HA机制、 Eureka服务打包部署
  4. 把数据存入excel文件_Python从原Excel表中抽出数据存入同一文件的新的Sheet(实例53)...
  5. JVM-Java内存区域
  6. .net core webapi 列表返回指定的字段_ADO.NET 使用初探之SQL操作 | C# 数据操作系列...
  7. 【SpringBoot零基础案例05】【IEDA 2021.1】若SpringBoot项目两种配置文件同时存在,哪种文件配置起作用?
  8. Node.js模块之Buffer
  9. 基于HTML5的WebGL呈现A星算法的3D可视化
  10. 用Matlab与c++程序生成的数据文件绘制sin函数