【转】_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函数体重!

    __asm
    {
        jmp [retAddress]
    }
}

int main()
{
    NormalFunc();
    printf(" before exit\r\n");

    return 0;
}

posted @ 2012-11-29 20:06  瓜蛋  阅读(1854)  评论(0编辑  收藏  举报