您的位置:首页 > 编程语言 > C语言/C++

YJX_Driver_024_驱动代码中C和C++代码区别

2016-04-06 16:58 746 查看
1、

驱动代码中C和C++代码区别
  A、函数调用约定
  B、C和C++编译方式
  C、用C++方式编译驱动
  D、C代码升级至C++
  E、优化21课的代码

本课主要是做着两个工作:"D、C代码升级至C++"、"E、优化21课的代码"

【180】把 第21课 的代码复制过来

【275】一般是通过改后缀名

  【315】mini_ddk.c 改名为 mini_ddk.cpp,使得 默认以c++的编译方式来编译。理论上是这样的。

【360】入口函数(DriverEntry)这里,理论上要以 C 的标准方式来编译

  现在 使用 继承开发环境来编译 可能感觉不出来,它同样是可以编译的。【440】但是,使用 DDK来编译的话 就会发现 它有错误

    【490】修改 source文件:mini_ddk.c 改为 mini_ddk.cpp

    【525】此时编译报错

    【640】



*.c
当文件后缀名为*.c时 编译器将会用C编译器方式编译
*.cpp
当文件后缀名为*.cpp时 编译器将会用C++编译器方式编译
区别:

解决办法
在需要用到C方式编译的函数前加extern "C"

需要用C方式编译的头文件做如下修改
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif
#include <NTDDK.h> //这里包含需要用C方式编译的头文件
#ifdef __cplusplus
}
#endif



    【810】再次编译,还是有报错,但是 错误少了。头文件的错误提示 没有了



1>errors in directory g:\驱动教程\024_驱动代码中c和c++代码区别\mini_ddk
1>mini_ddk.obj : error LNK2001: unresolved external symbol "struct _ServiceDescriptorTable * KeServiceDescriptorTable" (?KeServiceDescriptorTable@@3PAU_ServiceDescriptorTable@@A)
1>bufferoverflowk.lib(gs_support.obj) : error LNK2019: unresolved external symbol _DriverEntry@8 referenced in function _GsDriverEntry@8
1>sys\i386\ddk_helloworld.sys : error LNK1120: 2 unresolved externals



    【1160】



_DriverEntry@8 //要求格式
?DriverEntry@@YGJPAU_DRIVER_OBJECT@@PAU_UNICODE_STRING@@@Z ?
实例 修改21课的代码 升级到C++编译模式
A、为入口函数 添加Extern "C"
B、修改Source文件
C、修改21课的BUG



    【1220】

    (1)、“extern PServiceDescriptorTable KeServiceDescriptorTable;”

      改为“extern "C" extern PServiceDescriptorTable KeServiceDescriptorTable;”

    (2)、【1250】“NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING B)”

      改为“extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING B)”

    【1300】这是 链接错误(非 编译错误),【1325】在生成目标文件时 并没有出错

      【1390】看 编译生成的目标文件(ZC: 貌似这里是 未加“extern "C"”时的 .obj文件)

        【1425】DriverEntry 被替代成了 “?DriverEntry@@YGJPAU_DRIVER_OBJECT@@PAU_UNICODE_STRING@@@Z...”

        【1490】而 错误提示里面 要求的是 symbol是这个“_DriverEntry@8”

    【1585】再次编译

      【1605】重新打开 mini_ddk.obj

        【1660】查找 "DriverEntry"

          【1675】这个时候我们看到,加“extern "C"”之后,生成的替代函数就是 “_DriverEntry@8”

          【1750】此时的提示 也看到 编译成功了

    【1765】集成环境里面编译,报错了

      【1805】它把“extern "C"”识别成了错误。这时一个经典错误:vs2003-->项目 --> mini_ddk属性 --> 配置属性 --> C/C++ --> 高级 --> “编译为”,现在的值为 “编译为C代码(/TC)”,这里要 修改 选成 “默认” 或者 “编译为C++代码(/TP)”。【1920】“默认” 的话,它就是通过 文件的后缀名 来判断它所要编译的方式。

      【1975】改过之后,vs2003再来编译,就OK了

【2050】第21课 写的代码里面有一个bug

  【2100】卸载例程 DDK_Unload里面,【2140】需要加一个判断,它是否进行了HOOK,加上一个标识

  【2375】不加这个判断的话,如果没有 hook的话,在卸载驱动时,会蓝屏

  【2420】用 之前没有加 ishook的那个驱动(DDK_HelloWorld.sys),到虚拟机中 测试一下

    【2490】驱动载入的时候正常,【2495】卸载的时候 就蓝屏了

  【2520】vs2003保存一下,重新用DDK编译

    【2723】放到 虚拟机中 测试一下

      【2790】加载 和 卸载 都OK



bool ishook = false;

NTSTATUS DriverEntry(PDRIVER_OBJECT _pDrvierObject, PUNICODE_STRING B)
{
  ULONG cur, old, ulOffset;
  JMPCODE JmpCode;

  cur = GetNt_CurAddr() ;
  old = GetNt_OldAddr();
  if (cur != old)
  {
    // hook
    ishook = true;
    // 【2040】保存 前5个字节
    pcur = (PJMPCODE)(cur);  // 【2500】初始化指针
    oldCode.E9 = pcur->E9; // 【2205】1字节
    oldCode.JMPADDR = pcur->JMPADDR; // 【2210】4字节

    ulOffset = old - (cur + 5);
    JmpCode.E9 = 0xE9;
    JmpCode.JMPADDR = ulOffset;
    
    KdPrint(("要写入的地址 : 0x%08X", JmpCode.JMPADDR));
    __asm // 去掉页面保护
    {
      cli
      mov eax,cr0
      and eax,not 10000h //and eax,0FFFEFFFFh
      mov cr0,eax
    }

    pcur->E9 = 0xE9;
    pcur->JMPADDR = JmpCode.JMPADDR; // 【1790】要跳转到的地址

    __asm // 恢复页保护
    {
      mov eax,cr0
      or eax,10000h //or eax,not 0FFFEFFFFh
      mov cr0,eax
      sti  // 【1145】恢复中断
    }
    KdPrint(("NtOpenProcess被Hook了"));
  }
  else
    KdPrint(("NtOpenProcess没有被Hook"));

  _pDrvierObject->DriverUnload = DDK_Unload;
  return 1;
}

VOID DDK_Unload(IN PDRIVER_OBJECT _pDrvierObject)
{
  PDEVICE_OBJECT pDev; // 用来取得要删除的设备对象
  UNICODE_STRING symLinkName;

// unhook
if (ishook)
{
  __asm // 去掉页面保护
  {
    cli
    mov eax,cr0
    and eax,not 10000h //and eax,0FFFEFFFFh
    mov cr0,eax
  }

  pcur->E9 = oldCode.E9;
  pcur->JMPADDR = oldCode.JMPADDR;

  __asm // 恢复页保护
  {
    mov eax,cr0
    or eax,10000h //or eax,not 0FFFEFFFFh
    mov cr0,eax
    sti  // 【1145】恢复中断
  }
} // end unhook
  pDev = _pDrvierObject->DeviceObject;
  IoDeleteDevice(pDev); // 删除设备

  // 取得符号链接的名字
  RtlInitUnicodeString(&symLinkName, L"\\??\\yjx888");
  IoDeleteSymbolicLink(&symLinkName);

  KdPrint(("驱动成功被卸载...OK----------"));
}



2、

extern "C" __declspec(naked) __stdcall test(int a, int b)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: