5

关于32位程序在64位系统下运行中需要注意的重定向问题 | WooYun知识库

 6 years ago
source link:
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

关于32位程序在64位系统下运行中需要注意的重定向问题

0x00 前言


[email protected] Architecture Matters》,恰巧解决了我之前遇到过的一个问题,理清了文件和注册表重定向中需要注意的细节

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

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

0x01 消失的注册表键值


OS:Win8x64
开发环境:VS2008

1、编写程序写入注册表

代码如下:

#!cpp
#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!\n");
    else
        printf("[+] RegSetValueEx Success!\n");
    ::RegCloseKey(hKey);
    return 0;
}

编译平台设置为Win32

以管理员权限运行后会向HKLM\Software\Microsoft\Windows\CurrentVersion\Run写入键值test

如图

Alt text

2、获取写入的键值

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

批处理内容如下:

#!bash
REG query "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" /v "test" >>result.txt

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

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

0x02 消失的文件


1、编写程序写入文件

代码如下:

#!cpp
#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!\n");
    fclose(fp);
}

编译平台设置为Win32

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

如图

Alt text

2、获取写入的文件

批处理内容如下:

#!bash
dir c:\windows\system32\test.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位程序的注册表信息

如果在HKLM\Software\Wow6432Node\Microsoft\CurrentVersion\Run添加启动项来运行dll,系统默认会执行32位的rundll32.exe(路径为:c:\windows\SysWOW64\rundll32.exe)来加载dll,加载的dll必须是32位(如果是64位会出错)

当然,如果在HKLM\Software\Microsoft\Windows\CurrentVersion\Run添加启动项来运行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位程序写注册表的操作会被重定向到HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Run

而在本地执行批处理默认会调用64位的程序,不会被重定向,查询的位置为HKLM\Software\Microsoft\Windows\CurrentVersion\Run

解决方法:

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

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

KEY_ALL_ACCES改为KEY_ALL_ACCESS | KEY_WOW64_64KEY

这样就会跳过重定向,最终写入的位置为HKLM\Software\Microsoft\Windows\CurrentVersion\Run

修改后的代码如下:

#!cpp
#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!\n");
        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!\n");
    else
        printf("[+] RegSetValueEx Success!\n");
    ::RegCloseKey(hKey);
    return 0;
}

再次执行批处理

#!bash
REG query "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" /v "test" >>result.txt

成功获得键值

如图

Alt text

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

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

不修改原程序,默认让其写入HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Run

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

#!bash
REG query "HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Run" /v "test"

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

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

0x05 找回文件


解决思路:

同样,32位程序写入c:\windows\system32\ 的操作会被重定向到c:\windows\SysWOW64\

32位程序如果需要访问真正的c:\windows\system32\,可访问c:\windows\Sysnative\

1、修改批处理

32位程序生成的文件实际位置为C:\Windows\SysWOW64\test.txt

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

#!bash
dir C:\Windows\SysWOW64\test.txt >>result.txt

2、补充

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

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

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

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

解决方法:

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

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

32位cmd:

#!bash
C:\Windows\SysWOW64\cmd.exe

64位cmd:

#!bash
c:\windows\system32\cmd.exe

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

写注册表:

#!bash
reg add "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" /v "test"

查询注册表:

#!bash
REG query "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" /v "test"
REG query "HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Run" /v "test"

写文件:

#!bash
copy test.txt c:\windows\system32\test.txt

查找文件:

#!bash
dir c:\windows\system32\test.txt
dir C:\Windows\SysWOW64\test.txt
dir C:\Windows\Sysnative\test.txt

0x06 小结


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

对注册表操作:

访问HKLM\Software\的实际路径为HKLM\Software\Wow6432Node\

对文件操作:

访问c:\windows\Sysnative\ 的实际路径为 c:\windows\system32\
访问c:\windows\system32\ 的实际路径为 c:\windows\SysWOW64\

[email protected],能够帮助大家更清晰的认识其中的细节。

Alt text

Alt text

[email protected],也让我有了更清楚的认识。

更多学习资料:

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK