zoukankan      html  css  js  c++  java
  • 关于32位程序在64位系统下运行中需要注意的重定向问题(有图,很清楚)

    0x00 前言


    最近学习了Stuart@ukstufus的文章《Persistence Architecture Matters》,恰巧解决了我之前遇到过的一个问题,理清了文件和注册表重定向中需要注意的细节

    大家在学习的过程中难免也会碰到,所以在此分享一下。

    《Persistence Architecture Matters》的链接:
    https://labs.mwrinfosecurity.com/blog/persistence-architecture-matters/

    0x01 消失的注册表键值


    OS:Win8x64
    开发环境:VS2008

    1、编写程序写入注册表

    代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #include <atlbase.h>
     
    int main(int argc, char *argv[])
    {
     
        LPCTSTR lpSubKey = "Software\Microsoft\Windows\CurrentVersion\Run";
        HKEY hKey;
        DWORD dwDisposition = REG_OPENED_EXISTING_KEY;
        LONG lRet = ::RegCreateKeyEx(HKEY_LOCAL_MACHINE, lpSubKey, NULL, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dwDisposition);
        if (ERROR_SUCCESS != lRet)
        {
            return 0;
        }
        char szModuleName[MAX_PATH] = { 0 };
        ::GetModuleFileNameA(NULL, szModuleName, MAX_PATH);
     
        lRet = ::RegSetValueEx(hKey, "test", NULL, REG_SZ, (BYTE*)szModuleName, strlen(szModuleName) + 1);
        if (ERROR_SUCCESS != lRet)
            printf("RegSetValueEx error! ");
        else
            printf("[+] RegSetValueEx Success! ");
        ::RegCloseKey(hKey);
        return 0;
    }

    编译平台设置为Win32

    以管理员权限运行后会向HKLMSoftwareMicrosoftWindowsCurrentVersionRun写入键值test

    如图

    Alt text

    2、获取写入的键值

    编写批处理文件来获得写入的结果

    批处理内容如下:

    1
    REG query "HKLMSoftwareMicrosoftWindowsCurrentVersionRun" /v "test" >>result.txt

    在本地右键直接执行批处理文件

    可是,批处理执行后无法输出写入的键值

    0x02 消失的文件


    1、编写程序写入文件

    代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <stdio.h>
    void main()
    {
        char *temp="test";
        FILE* fp;
        fp=fopen("c:\windows\system32\test.txt","a+");       
        if(fp==0)
        return;
        fwrite(temp,strlen(temp),1,fp);
        printf("[+] Write Success! ");
        fclose(fp);
    }

    编译平台设置为Win32

    以管理员权限运行后会向c:windowssystem32写入文件test.txt

    如图

    Alt text

    2、获取写入的文件

    批处理内容如下:

    1
    dir c:windowssystem32test.txt >>result.txt

    在本地右键直接执行批处理文件

    同样,批处理无法输出写入的文件内容

    0x03 原因分析


    1、重定向

    自xp系统开始,64位的系统引入了新技术:文件重定向和注册表重定向
    这个技术是为了在64位系统下将32位程序和64程序分离开
    在64位平台上运行32位程序的模拟器被称为WOW64
    WOW64全称为"Windows 32 on Windows 64"

    2、注册表重定向

    在X64系统里面,一些特殊的注册表键会被分为2个独立的部分

    (1)32位程序对注册表某些位置的操作存在重定向

    比如对HKLM/Software访问,会被WOW64重定向至HKLM/Software/Wow6432Node

    具体存在重定向的注册表位置可参考如下链接:
    https://msdn.microsoft.com/en-us/library/windows/desktop/aa384253(v=vs.85).aspx

    (2)64位程序对注册表的操作不存在重定向

    (3)补充

    HKLM/Software/Wow6432Node下保存的均为32位程序的注册表信息

    如果在HKLMSoftwareWow6432NodeMicrosoftCurrentVersionRun添加启动项来运行dll,系统默认会执行32位的rundll32.exe(路径为:c:windowsSysWOW64 undll32.exe)来加载dll,加载的dll必须是32位(如果是64位会出错)

    当然,如果在HKLMSoftwareMicrosoftWindowsCurrentVersionRun添加启动项来运行dll,则默认为64位rundll32.exe,加载64位dll文件

    3、文件重定向

    同样,文件系统也存在2个独立的部分

    (1)32位程序对%systemroot%/system32 的操作存在重定向

    32位文件会被重定向到%systemroot%/SysWOW64

    (2)64位程序对文件操作不存在重定向

    (3)补充

    %systemroot%/SysWOW64下的都为32位程序,在里面可以找到32位的cmd、calc等

    基于以上的分析,整理出了如下操作注册表键值和文件系统的方法

    0x04 找回注册表键值


    解决思路:

    32位程序写注册表的操作会被重定向到HKLMSoftwareWow6432NodeMicrosoftWindowsCurrentVersionRun

    而在本地执行批处理默认会调用64位的程序,不会被重定向,查询的位置为HKLMSoftwareMicrosoftWindowsCurrentVersionRun

    解决方法:

    1、修改调用的api参数,跳过重定向,使32位程序去访问64位的注册表

    在调用函数RegCreateKeyEx创建注册表项时,对其第六个参数REGSAM samDesired设置中添加参数KEY_WOW64_64KEY

    KEY_ALL_ACCES改为KEY_ALL_ACCESS | KEY_WOW64_64KEY

    这样就会跳过重定向,最终写入的位置为HKLMSoftwareMicrosoftWindowsCurrentVersionRun

    修改后的代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    #include "stdafx.h"
    #include <atlbase.h>
    int main(int argc, char *argv[])
    {
     
        LPCTSTR lpSubKey = "Software\Microsoft\Windows\CurrentVersion\Run";
        HKEY hKey;
        DWORD dwDisposition = REG_OPENED_EXISTING_KEY;
        LONG lRet = ::RegCreateKeyEx(HKEY_LOCAL_MACHINE, lpSubKey, NULL, NULL, REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS | KEY_WOW64_64KEY, NULL, &hKey, &dwDisposition);
        if (ERROR_SUCCESS != lRet)
        {
            printf("RegCreateKeyEx error! ");
            return 0;
        }
        char szModuleName[MAX_PATH] = { 0 };
        ::GetModuleFileNameA(NULL, szModuleName, MAX_PATH);
     
        lRet = ::RegSetValueEx(hKey, "test", NULL, REG_SZ, (BYTE*)szModuleName, strlen(szModuleName) + 1);
        if (ERROR_SUCCESS != lRet)
            printf("RegSetValueEx error! ");
        else
            printf("[+] RegSetValueEx Success! ");
        ::RegCloseKey(hKey);
        return 0;
    }

    再次执行批处理

    1
    REG query "HKLMSoftwareMicrosoftWindowsCurrentVersionRun" /v "test" >>result.txt

    成功获得键值

    如图

    Alt text

    注:
    也可结合使用Wow64DisableWow64FsRedirectionWow64RevertWow64FsRedirection关闭和开启重定向,以此来跳过重定向,写入64位的注册表

    2、修改批处理,查询重定向后的注册表键值(验证结论用)

    不修改原程序,默认让其写入HKLMSoftwareWow6432NodeMicrosoftWindowsCurrentVersionRun

    修改批处理文件查询重定向后的注册表键值,代码为:

    1
    REG query "HKLMSoftwareWow6432NodeMicrosoftWindowsCurrentVersionRun" /v "test"

    在本地右键执行后可成功获得键值

    注:
    实际测试的过程中很少能够在本地右键执行批处理,所以该方法仅作验证思路
    通常情况下,32位的程序执行批处理文件也会存在重定向的问题。

    0x05 找回文件


    解决思路:

    同样,32位程序写入c:windowssystem32 的操作会被重定向到c:windowsSysWOW64

    32位程序如果需要访问真正的c:windowssystem32,可访问c:windowsSysnative

    1、修改批处理

    32位程序生成的文件实际位置为C:WindowsSysWOW64 est.txt

    所以批处理对应的内容如下:

    1
    dir C:WindowsSysWOW64test.txt >>result.txt

    2、补充

    (1)之前遇到过的一个问题:

    在测试Security Support Provider的时候就存在这个问题:
    http://drops.wooyun.org/tips/12518

    使用32位的程序将mimikatz.dll上传至域控(Server2008x64)的c:windowssystem32下

    由于重定向的缘故mimikatz.dll实际的上传位置为C:WindowsSysWOW64,因此导致测试失败

    解决方法:

    1. 文件的复制路径改为c:windowsSysnative
    2. 换用批处理实现复制功能,不会存在重定向问题

    (2)可供测试32位和64位程序区别的小方法:

    32位cmd:

    1
    C:WindowsSysWOW64cmd.exe

    64位cmd:

    1
    c:windowssystem32cmd.exe

    分别执行写注册表和写文件的操作,重定向的细节显而易见

    写注册表:

    1
    reg add "HKLMSoftwareMicrosoftWindowsCurrentVersionRun" /v "test"

    查询注册表:

    1
    2
    REG query "HKLMSoftwareMicrosoftWindowsCurrentVersionRun" /v "test"
    REG query "HKLMSoftwareWow6432NodeMicrosoftWindowsCurrentVersionRun" /v "test"

    写文件:

    1
    copy test.txt c:windowssystem32test.txt

    查找文件:

    1
    2
    3
    dir c:windowssystem32test.txt
    dir C:WindowsSysWOW64test.txt
    dir C:WindowsSysnativetest.txt

    0x06 小结


    32位程序在64系统下执行的时候,如果有对注册表和文件的操作,重定向的细节必须考虑。

    对注册表操作:

    访问HKLMSoftware的实际路径为HKLMSoftwareWow6432Node

    对文件操作:

    访问c:windowsSysnative 的实际路径为 c:windowssystem32
    访问c:windowssystem32 的实际路径为 c:windowsSysWOW64

    引用Stuart@ukstufus文章中的两幅图,能够帮助大家更清晰的认识其中的细节。

    感谢Stuart@ukstufus的分享。解决了我的问题,也让我有了更清楚的认识。

    更多学习资料:

    本文由三好学生原创并首发于乌云drops,转载请注明

    http://drops.wooyun.org/tips/14831

  • 相关阅读:
    49. Group Anagrams
    43. Multiply Strings
    22. Generate Parentheses
    17. Letter Combinations of a Phone Number
    8. String to Integer (atoi)
    【转】C#中base关键字的几种用法:base()
    【转】C#中virtual和abstract的区别
    [转]C#中的abstract 类和方法
    【转】C#虚方法virtual详解
    【转】C#中protected用法详解
  • 原文地址:https://www.cnblogs.com/findumars/p/5532591.html
Copyright © 2011-2022 走看看