天天看点

_declspec(naked) 使用

// 将本文完整拷贝, 然后在VC6 下建立控制台程序, 可直接运行~  看到结果后再来阅读此文

// 文章出处甚多, 已不能列出所有连接

#include "stdafx.h"

#include <stdio.h>

/*

    >>>>>>   _declspec(naked) 使用  <<<<<<<<

最近学习驱动开发,在写绕过inline hook的代码时,有个问题困扰了我一天,

最后发现原来是在内嵌汇编时,没有使用_declspec(naked)导致的,

看来是偶的基础知识掌握的不牢固啊(得补一下了,磨刀不误砍柴功),在此给记录一下,给自己一个警示。

对于jmp类型的hook, 如果自己的过程没有使用_declspec(naked),那么系统会自动给添加一些额外的代码,控制堆栈平衡,

但是这些额外的代码会破坏被hook函数的堆栈。

对于call类型的hook,如果使用_declspec(naked)修饰的话,要注意自己恢复堆栈平衡..

下面是网上对_declspec(naked) 的介绍:

_declspec(naked)

就是告诉编译器,在编译的时候,不要优化代码,通俗的说就是

没代码,完全要自己写

比如

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

#define NAKED   __declspec(naked)

void NAKED code(void)

{

    __asm

    {

        ret

    }

}

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

使用__declspec(naked)关键字定义函数:

1,使用 naked 关键字必须自己构建 EBP 指针 (如果用到了的话);

2,必须自己使用 RET 或 RET n 指令返回 (除非你不返回);

// >> __declspec(naked) 是且仅是不产生 prolog 和 epilog 代码 

// >> {保存并恢复使用过的寄存器和分配局部变量、平衡堆栈、返回值}。

_delcspec(naked)用在驱动编写,C语言内嵌汇编完成一些特定功能。

*/

#pragma warning (disable: 4700)

unsigned int retAddress;

void Test2();

void NormalFunc();

void NormalFunc()

    // data[1] : ebp的值, data[2] : 函数返回地址

    unsigned int data[1] = { 0 };

    // 保存 返回地址

    retAddress = data[2];

    data[2] = (unsigned int)Test2;

    return ;

// naped 函数 (手工指定 prolog 和 epilog)

// >> 一下四种形式皆可

// __declspec(naked) void Test2()

// void __declspec(naked) Test2()

// void _declspec(naked) Test2()

_declspec(naked) void Test2()

    printf("Naked : hello world!\r\n");

    // 跳回main函数体重!

        jmp [retAddress]

int main()

    NormalFunc();

    printf(" before exit\r\n");

    return 0;

继续阅读