32位和64位的区别

1.支持32位应用程序是64位OS的核心功能

Q:在64位OS中支持现有的32位应用程序运行的机制是什么?

A:WOW64(即windows on windows 64)

Q:具体是如何实现的?

A:

64位windows提供了32位windows的系统环境,借助WOW64将其变化为64位环境

此处需要注意的是:

1.WOW仅在用户模式下运行

2.运行在内核模式中的驱动程序(Driver)文件必须编译成64位。

3.内核模式中发生内存引用错误时,就会引发BSOD(BlueScreen Of Death)蓝屏死机

2.两者文件夹结构的区别

代码验证

#include <iostream>
#include <Windows.h>

int main() {
    char systemDirectory[MAX_PATH];
        GetSystemDirectoryA(systemDirectory, MAX_PATH);
        std::cout << systemDirectory << std::endl;
    return 0;
}

首先是在32位环境先输出

然后再在64位环境下输出

可以看到返回结果都是system32

这是因为WOW64在中间截获了API调用并进行操作后返回的结果

同理,32位的应用程序使用SHGetSpecialFolderPath()API获取Progarm File文件夹路径时,WOW64会在中间对其进行截获,并返回Program Files(X86)路径

3.在注册表项的区别

在software项下存在一个WOW6432Node子项

当32位的进程访问HKLM\SOFTWARE下的键时,WOW64会将其重定向到32位的HKLM\SOFTWARE\WOW6432Node下。

4.X64中新增的项目

最显著的变化:内存地址是64位,指针大小是64位,寄存器和栈的基本单位也是64位

机器

32

64

进程的虚拟内存

4GB

16TB

通用寄存器

EAX……

新增R8-R15,

不使用段寄存器

CALL/JMP指令

FF15 XXXXXXXX

其中XXXXXXXX绝对地址指向IAT区域的某一个位置

在FF15之后仍然跟着4个字节大小,不过是相对地址

Q:相对地址是怎么转化成绝对地址的呢?

A:CALL指令所在地址+相对地址+6(CALL指令的长度)=变换后的绝对地址

函数调用约定

存在3种函数调用约定,分别是cdcall,stdcall,fastcall,

在64位系统中的是统一的变形后的fastcall

最多可以将4个参数传递到寄存器中,如上是使用寄存器的顺序

当参数的个数超过4个的时候,第五个参数会在栈中进行传递,后期栈的清理由函数调用者完成,

注意:函数的前四个参数虽然是使用寄存器进行传递的,但是在栈中依然保留了4个参数也就是32个字节的空间

栈\栈帧

使用push指令传递参数

通过mov指令操作寄存器和预定的栈来传递

优点是调用子函数时不需要改变栈指针,函数返回时也不需要清理堆栈

5.代码验证

#include <windows.h>
#include <stdio.h>

int main() {
    HANDLE hFile;

    // 使用 CreateFile 函数创建文件
    hFile = CreateFile(
        L"example.txt",     // 文件名
        GENERIC_WRITE,      // 访问权限:写入
        0,                  // 共享模式:无
        NULL,               // 安全属性:默认
        CREATE_ALWAYS,      // 打开方式:如果文件存在则覆盖,否则创建
        FILE_ATTRIBUTE_NORMAL, // 文件属性:普通文件
        NULL                // 模板句柄:无
    );

    if (hFile != INVALID_HANDLE_VALUE) {
        // 关闭文件句柄
        CloseHandle(hFile);
    }

    return 0; // 返回零值表示程序正常结束
}

32

调用子函数时用栈传递参数

在32位环境下采用stdcall,属于内平栈,由被调用者清理栈

进入CreateFile()API 中查看

768DA520 | 8BFF | mov edi, edi                                    |
768DA522 | 55   | push ebp                                        |
768DA523 | 8BEC | mov ebp, esp                                    |
768DA525 | 51   | push ecx                                        |
768DA526 | 51   | push ecx                                        |
768DA527 | 8B55 | mov edx, dword ptr ss:[ebp+0x8]                 |
768DA52A | 8D4D | lea ecx, dword ptr ss:[ebp-0x8]                 |
768DA52D | E8 6 | call <kernelbase._Basep8BitStringToDynamicUnico |
768DA532 | 85C0 | test eax, eax                                   | eax:___argc
768DA534 | 74 2 | je kernelbase.768DA564                          |
768DA536 | 56   | push esi                                        | esi:&"C:\\Users\\win2021ltsc\\AppData\\Local\\Temp\\vmware-win2021ltsc\\VMwareDnD\\7158df7b\\RVATOFOA.exe"
768DA537 | FF75 | push dword ptr ss:[ebp+0x20]                    |
768DA53A | FF75 | push dword ptr ss:[ebp+0x1C]                    |
768DA53D | FF75 | push dword ptr ss:[ebp+0x18]                    |
768DA540 | FF75 | push dword ptr ss:[ebp+0x14]                    | [ebp+14]:__RtlUserThreadStart+2F
768DA543 | FF75 | push dword ptr ss:[ebp+0x10]                    |
768DA546 | FF75 | push dword ptr ss:[ebp+0xC]                     | [ebp+C]:@BaseThreadInitThunk@12
768DA549 | FF75 | push dword ptr ss:[ebp-0x4]                     |
768DA54C | E8 E | call <kernelbase._CreateFileW@28>               |
768DA551 | 8BF0 | mov esi, eax                                    | esi:&"C:\\Users\\win2021ltsc\\AppData\\Local\\Temp\\vmware-win2021ltsc\\VMwareDnD\\7158df7b\\RVATOFOA.exe", eax:___argc
768DA553 | 8D45 | lea eax, dword ptr ss:[ebp-0x8]                 | eax:___argc
768DA556 | 50   | push eax                                        | eax:___argc
768DA557 | FF15 | call dword ptr ds:[<&_RtlFreeUTF8String@4>]     |
768DA55D | 8BC6 | mov eax, esi                                    | eax:___argc, esi:&"C:\\Users\\win2021ltsc\\AppData\\Local\\Temp\\vmware-win2021ltsc\\VMwareDnD\\7158df7b\\RVATOFOA.exe"
768DA55F | 5E   | pop esi                                         | esi:&"C:\\Users\\win2021ltsc\\AppData\\Local\\Temp\\vmware-win2021ltsc\\VMwareDnD\\7158df7b\\RVATOFOA.exe"
768DA560 | C9   | leave                                           |
768DA561 | C2 1 | ret 0x1C                                        |
768DA564 | 83C8 | or eax, 0xFFFFFFFF                              | eax:___argc
768DA567 | EB F | jmp kernelbase.768DA560                         |

在调用CreateFile()API之前就使用过Push指令将接收的参数压入栈,此时栈中有两份相同的参数()

Q:为什么参数要传递两次呢

A:这是因为函数支持多种字符编码或者字符串格式

64

00007FF84EE62630 | 48:83EC 78               | sub rsp,0x78                            |
00007FF84EE62634 | 4C:8BC9                  | mov r9,rcx                              |
00007FF84EE62637 | 48:8B05 B2791100         | mov rax,qword ptr ds:[<&BaseThreadInitT |
00007FF84EE6263E | 48:85C0                  | test rax,rax                            |
00007FF84EE62641 | 74 10                    | je ntdll.7FF84EE62653                   |
00007FF84EE62643 | 4C:8BC2                  | mov r8,rdx                              |
00007FF84EE62646 | 48:8BD1                  | mov rdx,rcx                             |
00007FF84EE62649 | 33C9                     | xor ecx,ecx                             |
00007FF84EE6264B | FF15 AF091300            | call qword ptr ds:[0x7FF84EF93000]      |
00007FF84EE62651 | EB 20                    | jmp ntdll.7FF84EE62673                  |
00007FF84EE62653 | 48:8BCA                  | mov rcx,rdx                             |
00007FF84EE62656 | 49:8BC1                  | mov rax,r9                              |
00007FF84EE62659 | FF15 A1091300            | call qword ptr ds:[0x7FF84EF93000]      |
00007FF84EE6265F | 8BC8                     | mov ecx,eax                             |
00007FF84EE62661 | E8 8A1F0000              | call <ntdll.RtlExitUserThread>          |
00007FF84EE62666 | 90                       | nop                                     |
00007FF84EE62667 | 8BD0                     | mov edx,eax                             |
00007FF84EE62669 | 48:83C9 FF               | or rcx,0xFFFFFFFFFFFFFFFF               |
00007FF84EE6266D | E8 6EAC0400              | call <ntdll.NtTerminateProcess>         |
00007FF84EE62672 | 90                       | nop                                     |
00007FF84EE62673 | 48:83C4 78               | add rsp,0x78                            |
00007FF84EE62677 | C3                       | ret                                     |

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tntlbb

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值