专栏首页csicoWindows内核开发-9-32位和64位的区别

Windows内核开发-9-32位和64位的区别

32位的应用程序可以完美再64位的电脑上运行,而32位的内核驱动无法再64位的电脑上运行,或者64位的驱动无法在32位的应用程序上运行。这是为什么呢。

原因是在x64的Windows操作系统上,模拟了x86操作系统的操作,并且引入了一个WOW64子系统,将x86和x64完美进行兼容。

WOW64子系统

x86能在x64上运行全靠这个东西。全名叫做Windows On Windows,英文名感觉是在套娃,其实它的意思就是在Windows64上运行Windows32。

这个系统由Wow64.dll,Wow64Win.dll,Wow64Cpu.dll三个dll实现,具体怎么实现的不用考虑。

Wow64子系统可以完美实现x86和x64之间的转换。

转换流程: 当一个32位Application发起系统调用时,WOW64会拦截下来,将其转换为64位的类型(包括指针范围,数据类型范围等等),然后再把系统调用请求提交给内核。这整个拦截-转换的流程被称为"thunking"。

WOW64有两个重要的模块,一个是系统文件重定向(File System Redirector),一个是注册表重定向(Registry Redirector)。

系统文件重定向(File System Redirector)

Windows64位OS包含了两个System32文件,一个是System32另一个是SysWow64。默认情况下的安装路径%Windows%\System32和%Windows%\SysWow64。

System32这个文件里面保存了系统需要的一些二进制文件,System32里面存放的是x64的系统二进制文件,SysWow64里面存放的是x86里的文件。不要被这个什么system32迷惑成了它就是32位的系统文件了。

一般情况下32位的只能加载32位的系统dll,64只能加载64的。因为是64位的操作系统,所以肯定默认是加载64的dll,但是32位怎么办,为了解决这个问题WOW64就构成了文件系统重定向模块,把32的系统dll放到了SysWow64里面,然后把System32这个文件夹给他重定向指到了SysWow64文件夹里了。

这里我们写一个代码来验证一下:

void TestFileRedirector()
{
    HANDLE hFile = CreateFileA("C:\\Windows\\System32\\test.txt", GENERIC_READ | GENERIC_WRITE, 0x00000000, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE)
    {
        cout << "创建文件失败" << endl;
    }
    else
    {
        cout << "创建文件成功,文件名为test.txt" << endl;
    }
    CloseHandle(hFile);
}

假如说这个test文件是在SysWow64文件夹下面创建的,那么说明我们前面的讲述没问题,确实是重定向到了SysWow64里面。这里我们要用管理员启动Visual Studio才行,因为这个文件夹是系统文件夹,需要管理员权限。

下面是我的验证结果:

在x86和x64运行后分别是在System32和SysWow64新建了文件,足以说明结论了。

关闭系统文件重定向

文件重定向固然不错,但是肯定有时候我们会不得不关闭它。

这里就会用到两个API:

BOOL Wow64DisableWow64FsRedirection(
  [out] PVOID *OldValue
);//关闭重定向,将原来的值保存到输入参数oldvalue里面
BOOL Wow64RevertWow64FsRedirection(
  PVOID OlValue
);//通过参数olvalue来恢复重定向

这里我们在修改一下我们的代码,让他x86的程序不要重定向到x64文件里面:

void TestFileRedirector()
{
    PVOID OldValue;
    auto ret = Wow64DisableWow64FsRedirection(&OldValue);
    if (ret == 0)
    {
        cout << "调用关闭重定向的函数失败,请检查" << endl;
        return;
    }
    else
    {
        cout << "调用重定向的函数成功,已经取消文件系统重定向" << endl;
    }
​
    HANDLE hFile = CreateFileA("C:\\Windows\\System32\\test.txt", GENERIC_READ | GENERIC_WRITE, 0x00000000, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hFile == INVALID_HANDLE_VALUE)
    {
        cout << "创建文件失败" << endl;
        return;
    }
    else
    {
        cout << "创建文件成功,文件名为test.txt" << endl;
    }
    CloseHandle(hFile);
    Wow64RevertWow64FsRedirection(OldValue);
}

这样再创建就是到System32系统文件夹里面了。

有一部分文件是不会被重定向的:

%Windows%System32\catrrot
%Windows%System32\catrrot2
%Windows%System32\drivers\etc
%Windows%System32\logfiles
%Windows%System32\spool

注册表重定向(Registry Redirector)

和系统文件重定向(File System Redirecotr)比较类似,但是功能更为复杂。除了重定向还有注册表反射功能(Registry Reflection 该功能暂时用不到)。

和File System Redirector比较类似的是,win32访问HKEY_LOCAL_MACHINE\SOFTWARE会被重定向到HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node下面。同样写一下代码测试一下:

void TestRegRedirector()
{
    HKEY hKey = NULL;
    RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Test"),
        0, NULL, 0, KEY_READ, NULL, &hKey,NULL);
    if (hKey != NULL)
    {
        cout << "创建注册表成功" <<endl;
        RegCloseKey(hKey);
    }
    else
    {
        cout << "创建注册表失败" << endl;
        return;
    }
}

用32位来运行,看他添加到哪里:

当然也肯定有关闭的办法。

DIY注册表重定向

在创建注册表的API上加一个宏定义就可完美解决这个问题了:

    RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Test"),0, NULL, 0, KEY_READ | KEY_WOW64_32KEY, NULL, &hKey,NULL);
这里的KEY_WOW64_32KEY就是32位,KEY_WOW64_64KEY就可以锁定为64位了。
void TestRegRedirector()
{
    HKEY hKey = NULL;
    RegCreateKeyEx(HKEY_LOCAL_MACHINE, TEXT("Software\\Test"),
        0, NULL, 0, KEY_READ | KEY_WOW64_32KEY, NULL, &hKey,NULL);
    if (hKey != NULL)
    {
        cout << "创建注册表成功" <<endl;
        RegCloseKey(hKey);
    }
    else
    {
        cout << "创建注册表失败" << endl;
        return;
    }
}

64位系统的升级技术

64对比32提供了很多新技术,比如之前的32位被很多程序很多公司,进行挂钩啊各种功能导致很不安全很麻烦。

PatchGuard

所以升级了一个PatchGuard技术,这个机制就是系统会定期检查内部的关键位置是否被篡改,一旦被篡改就会蓝屏。

比如一些论坛常见的SSDT(系统描述表),GDT(全局描述表),IDT(中断描述表)等等。但是其实也是可以绕过的。正所谓道高一尺魔高一丈就是这个意思,没有绝对的安全。

x64的编译、安装、运行

编译很简单,vs换成x64就行了。

安装的话著需要考虑32位exe安装驱动的时候不会把他放到64位驱动system32这个文件夹下就行了,这个用关闭File System redirecotr就行。

运行:x64的驱动必须得有签名才行,变相提高了安全吧,不过我们自己测试就把测试机变成测试模式就好了。

编程差异

x86和x64编程还是有少许区别的。

加入汇编

32位和64比较麻烦的就是不能直接内联汇编了,就比如说下面这段代码:

#include<ntddk.h>
​
​
extern "C"
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)
{
    UNREFERENCED_PARAMETER(DriverObject);
    UNREFERENCED_PARAMETER(RegistryPath);
    __asm
    {
        int 3
    }
​
    return STATUS_SUCCESS;
}

一个很简单的内核驱动代码,用x64编译就不行,而x86没问题:

也就是说不运行直接内联汇编了,只能用汇编asm写好了,然后作为函数的形式放进去了。

条件编译

WDK设置了宏来帮助条件编译,比如针对操作系统平台有: _M_AMD64, _M_IX64等等,对于位数也有 _WIN64和 _WIN32 ,比如说:

#ifdef _WIN32   //32位情况
​
#else //不是32位情况
​
#endif

调整数据结构

当一个32位的exe通过DeviceIoControl的方式和64位驱动进行交互的时候,如果结构体里有指针是不会进行thunking技术调整的,所以这里就会涉及到一些问题了,比如指针位数的不兼容,以及比如int这种位数也是不兼容的,还有对齐的一些很多问题。所以最好是采用限制好了的数据结构体。

比如说结构体定义成这样

struct DRIVER_DATA
{
    void* POINTER_32    test;
    UNICODE_STRING32    testUnicode_string;
};

原文链接:https://www.cnblogs.com/Sna1lGo/p/15426507.html

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 64位内核第一讲,和32位内核的区别

              64位内核第一讲,和32位内核的区别 双击调试配置请查看 连接: https://www.cnblogs.com/aliflycoris/p...

    IBinary
  • 32位和64位系统的区别

    64位系统和32位系统首先涉及到提取数据的能力,64位系统肯定比32位系统提取数据的能力强一倍 但是这只是建立在64位操作系统的64位软件上。 进程的64位...

    狼啸风云
  • python 32位和64位的区别在哪

    py3study
  • 常说的32位和64位有什么区别?

    https://baike.baidu.com/item/%E4%BD%8D%E3%80%81%E5%AD%97%E8%8A%82%E3%80%81%E5%AD...

    简单并不简单
  • 64位Java开发平台的选择,如何区分JDK,Tomcat,eclipse的32位与64版本

    当你想下载Linux、JDK、Tomcat、eclipse时,你是下载32位版本还是64位版本?64位版本有两种,应该选哪一个?

    我是李超人
  • 64位内核开发第十讲,IRQL中断级别了解

    中断就是产生的一个电信号.比如键盘.当按下就会产生电信号发送给CPU 而CPU就会停止当前处理.去执行电信号.他是根据IRQL中断级别来进行处理的. 如下图...

    IBinary
  • Linux 中的 32 位与 64 位

    在通用PC领域,不论是windows还是linux界,我们都会经常听到"32位"与"64位"的说法,类似的还有"x86"与"x86_64","i386"与"am...

    杰哥的IT之旅
  • Microsoft 安全公告摘要(2015 年 10 月)

    Microsoft 安全公告摘要(2015 年 10 月) 10(共 16)对本文的评价是有帮助 - 评价此主题 发布日期:2015 年 10 月 13 日 |...

    逸鹏
  • Win7 64位和32位有什么区别?

    64位操作系统的设计初衷是:满足机械设计和分析、三维动画、视频编辑和创作,以及科学计算和高性能计算应用程序等领域中需要大量内存和浮点性能的客户需求。换句...

    点云PCL博主
  • 又是一年PC操作系统三国鼎立的时刻~

    Win8 在今早零时,发布开发者预览版,Lion已经发布多时,Ubuntu11.10的正式版也已经逼近

    libo1106
  • 最全Windows代系介绍,迎接Windows 2020,回顾Windows XP经典

    Windows 在历史上曾出现过的产品可以划分为三个阶段,分别为:以 DOS 为基础的 Windows,以 Windows 9x 为代表的 Windows,以 ...

    shawyang
  • 64位内核开发第十三讲,内核中常用的链表等数据结构

    不管是Ring0还是Ring3数据结构都是必须要知道的.数据结构是一种思想. 以及怎么存储数据. 跟语言无关.平台无关.

    IBinary
  • [Python之道] 几种判断操作系统

    在实际项目中有时候不知道操作系统的类型,比如是Windows、OS X、*Unix?而Python代码虽说是跨平台(CrossPlatform)的,但是毕竟他们...

    py3study
  • 服务器系统选择 32 位还是 64 位?

    今天继续给大家说说服务器的选购,很多站长们选购服务器的时候纠结于是选 32 位还是 64 位,今天就给大家讲讲 32 位和 64 位的区别和优缺点。

    明月云服务
  • windows 小技巧搜集(不定期更新)

    1、更改cmd的默认路径 你可以在注册表的“HKEY_CURRENT_USER\Software\Microsoft\CommandProcessor” 下面新...

    用户1177713
  • 用Qt写软件系列三:一个简单的系统工具(上)

    导言       继上篇《用Qt写软件系列二:QIECookieViewer》之后,有一段时间没有更新博客了。这次要写的是一个简单的系统工具,需求来自一个内部项...

    24K纯开源
  • 创建简单、免费的恶意软件分析环境

    原文地址:Creating a Simple Free Malware Analysis Environment

    Seebug漏洞平台
  • Linux分页机制之概述--Linux内存管理(六)

    在虚拟内存中,页表是个映射表的概念, 即从进程能理解的线性地址(linear address)映射到存储器上的物理地址(phisical address).

    233333
  • 将Windows日志转换为Syslog

    无论是Unix、Linux、FreeBSD、Ubuntu,还是路由器、交换机,都会产生大量的日志,而这些,一般会以syslog的形式存在。在RFC 3164中定...

    张善友

扫码关注云+社区

领取腾讯云代金券