前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >64位内核开发第十三讲,内核下C++编程

64位内核开发第十三讲,内核下C++编程

作者头像
IBinary
发布2022-05-10 13:11:19
5470
发布2022-05-10 13:11:19
举报
文章被收录于专栏:逆向技术

目录

  • Windows内核驱动 使用 C++ 代码编程
    • 一 丶 C++在Windows内核中的使用
      • 1.1 简介
      • 1.2 头文件的引用
    • 二丶使用C++ 类
      • 2.1 介绍内核中的内存申请函数
      • 2.2 重载类中的 new delete函数
      • 2.3 使用继承以及虚函数重写父类函数
      • 2.4 使用虚析构
    • 三丶全局new delete 重构
      • 3.1 代码
    • 四丶建议

Windows内核驱动 使用 C++ 代码编程

一 丶 C++在Windows内核中的使用

1.1 简介

在驱动内核中是可以使用C++来进行编程的.只不过需要你重载一下new delete等函数

你可以看使用类 使用继承等. 但是如果是内核API的时候注意需要对其进行 C函数导出.

否则就会报解析不到名字 最好使用状态就是 c with class 使用基本的类来管理自己的函数.

比直接使用C强

1.2 头文件的引用

代码语言:javascript
复制
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif

#include <ntifs.h>
#include <ntddk.h>
#include <Ntstrsafe.h>
#include <ntimage.h>

#ifdef __cplusplus
}
#endif

在引入头文件的时候使用条件宏包含以下 其中 __cplusplus 的意思是 是否使用 C++的编译方式编译.如果是后缀名为.cpp则此宏就会启作用. 那么就会加入一个 extern "C" 修饰,这样声明的时候就是使用C的方式编译了.也不会遇到解析名称错误了.

对于DriverEntry入口我们也需要进行C修饰

如一个.cpp文件中的内容如下:

代码语言:javascript
复制
extern "C" NTSTATUS DriverEntry(
    PDRIVER_OBJECT pDriverObj,
    PUNICODE_STRING pReg)
{
    UNREFERENCED_PARAMETER(pDriverObj);
    UNREFERENCED_PARAMETER(pReg);
}

二丶使用C++ 类

2.1 介绍内核中的内存申请函数

如果想在类中使用new和delete 那么我们需要重载一下new和delete 变成内核方式的内存申请. 当然如果你想写一个 string函数 那么你也可以重载 + [] ....等运算符

在内核中申请内存可以使用以下函数

代码语言:javascript
复制
ExAllocatePool                 ----过时
ExAllocatePoolWithTag          ----在windows2004上过时
ExAllocatePool2
ExAllocatePool3                -----2 3 都是在2004

对应释放函数分别就是
ExFreePoolxxxxxx

申请的时候需要指定类型 类型如下:

类型

说明以及使用

是否常用

NonPagedPool

非分页内存,申请的内存是读写执行 可以执行ShellCode

常用

PagedPool

分页内存,分页内存可能会被换出,访问的时候要注意检查

一般

NonPagedPoolMustSucceed

指定分贝非分页内存,必须成功.

不使用

DontUseThisType

未指定

不使用

NonPagePoolCacheAligned

分配非分页内存,而且必须内存对齐

不使用

PagedPoolCacheAligned

分页内存,必须内存对齐

不使用

NonPagedPoolCacheAlignedMustS

非分页内存必须对齐必须成功

不使用

new的重载就是用ExAllocatePool xxx

2.2 重载类中的 new delete函数

看一下简单的代码吧.

代码语言:javascript
复制
#pragma once
#ifdef __cplusplus
extern "C"
{
#endif

#include <ntifs.h>
#include <ntddk.h>
#include <Ntstrsafe.h>
#include <ntimage.h>

#ifdef __cplusplus
}
#endif

class father
{
public:
    father();
    ~father();

public:
    void *operator new(size_t size, POOL_TYPE poolType = NonPagedPool);
    void operator delete(void *pointer);

public:
    virtual void testprint();

private:
    char szBuffer[1024];
};

cpp实现

代码语言:javascript
复制
#include "test.h"

father::father()
{
    DbgPrint("startfather\n");
}
father::~father()
{
    DbgPrint("endfather\n");
}
void father::testprint()
{
    DbgPrint("father\n");
}

void *father::operator new(size_t size, POOL_TYPE poolType)
{
    return ExAllocatePoolWithTag(poolType, size, 'abcd');
}
void father::operator delete(void *pointer)
{
    ExFreePoolWithTag(pointer, 'abcd');
}

使用

代码语言:javascript
复制
extern "C" NTSTATUS DriverEntry(
    PDRIVER_OBJECT pDriverObj,
    PUNICODE_STRING pReg)
{
    UNREFERENCED_PARAMETER(pReg);
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    pDriverObj->DriverUnload = DriverUnLoad;
    father *pf = new father;
    pf->testprint();
    delete pf;
    
    return STATUS_SUCCESS;
}

使用结果:

可以看到先进行构造 然后调用testprintf输出. 最后析构.

2.3 使用继承以及虚函数重写父类函数

如果定义一个类继承自父类调用testprint会怎么样? 代码如下:

代码语言:javascript
复制
class child : public father
{
public:
    child();
    ~child();

public:
    void *operator new(size_t size, POOL_TYPE poolType = NonPagedPool);
    void operator delete(void *pointer);

public:
    void testprint();

private:
    char szBuffer[1024];
};

使用:

代码语言:javascript
复制
extern "C" NTSTATUS DriverEntry(
    PDRIVER_OBJECT pDriverObj,
    PUNICODE_STRING pReg)
{
    UNREFERENCED_PARAMETER(pReg);
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    pDriverObj->DriverUnload = DriverUnLoad;
    father *pf = new child;
    pf->testprint();
    delete pf;

    return STATUS_SUCCESS;
}

结果

少了一次析构 child没有进行析构 testprintf我们使用的是虚函数,重写了父类. 所以说虚函数是可以进行使用的.

2.4 使用虚析构

不重复粘贴代码了.做一下说明

1.父类的析构函数前边加了关键字 virtual

2.子类的析构前边也加了关键字 virtual 调用方式同上

结果:

使用虚析构结果就是正确的了 会发现子类会被析构了.而不会直接析构父类了.

三丶全局new delete 重构

3.1 代码

father中的重载代码进行删除 使用全局的new delete一样可以.

代码语言:javascript
复制
void *__cdecl operator new(size_t Size, POOL_TYPE PoolType)
{
    PAGED_CODE();
    Size = (Size != 0) ? Size : 1;
    void *pObject = ExAllocatePoolWithTag(PoolType, Size, POOLTAG);
#if DBG
    if (pObject != NULL)
    {
        RtlFillMemory(pObject, Size, 0xCC);
    }
#endif // DBG
    return pObject;
}
void *__cdecl operator new[](size_t Size, POOL_TYPE PoolType)
{
    PAGED_CODE();
    Size = (Size != 0) ? Size : 1;
    void *pObject = ExAllocatePoolWithTag(PoolType, Size, POOLTAG);
#if DBG
    if (pObject != NULL)
    {
        RtlFillMemory(pObject, Size, 0xCC);
    }
#endif // DBG
    return pObject;
}
void __cdecl operator delete(void *pObject)
{
    PAGED_CODE();
    if (pObject != NULL)
    {
        ExFreePoolWithTag(pObject, POOLTAG);
    }
}
void __cdecl operator delete[](void *pObject)
{
    PAGED_CODE();
    if (pObject != NULL)
    {
        ExFreePoolWithTag(pObject, POOLTAG);
    }
}

extern "C" NTSTATUS DriverEntry(
    PDRIVER_OBJECT pDriverObj,
    PUNICODE_STRING pReg)
{
    UNREFERENCED_PARAMETER(pReg);
    NTSTATUS status = STATUS_UNSUCCESSFUL;
    pDriverObj->DriverUnload = DriverUnLoad;

    PCHAR pszBuffer = NULL;
    PWCHAR pwzBuffer = NULL;
    father *pFather = NULL;
    pszBuffer = new (NonPagedPool) CHAR[100];
    pwzBuffer = new (NonPagedPool) WCHAR[100];
    pFather = new (NonPagedPool) father;
    // check ...
    delete pFather;
    delete[] pszBuffer;
    delete[] pwzBuffer;
    return STATUS_SUCCESS;
}

四丶建议

  • 可使用 DBG宏判断是否是DBG版本下编译,如果是可以初始化内存为0XCC
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-01-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Windows内核驱动 使用 C++ 代码编程
    • 一 丶 C++在Windows内核中的使用
      • 1.1 简介
      • 1.2 头文件的引用
    • 二丶使用C++ 类
      • 2.1 介绍内核中的内存申请函数
      • 2.2 重载类中的 new delete函数
      • 2.3 使用继承以及虚函数重写父类函数
      • 2.4 使用虚析构
    • 三丶全局new delete 重构
      • 3.1 代码
    • 四丶建议
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档