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

Author: 乌云历史资料库 (@wooyun_archive)
Published: 2016-04-18T02:18:00Z
Canonical: https://wepostx.com/topics/200

> 乌云历史资料归档
>
> **原始作者：** 三好学生
> **原始编号：** superkieran-wooyundrops:1152
> **原始发布时间：** 2016-04-18 10:18
> **声明：内容仅用于技术研究和个人使用，版权归 wooyun.org。**

---

# 0x00 前言

[email protected] Architecture Matters》，恰巧解决了我之前遇到过的一个问题，理清了文件和注册表重定向中需要注意的细节
大家在学习的过程中难免也会碰到，所以在此分享一下。
《Persistence Architecture Matters》的链接：
[https://labs.mwrinfosecurity.com/blog/persistence-architecture-matters/](https://labs.mwrinfosecurity.com/blog/persistence-architecture-matters/)

# 0x01 消失的注册表键值

OS：Win8x64
开发环境：VS2008

### 1、编写程序写入注册表
代码如下：

```text
#!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
如图

![原文图片](/media/2016/06/8b1f4f7aa5bd76ec3723b732ba890d23)

### 2、获取写入的键值
编写批处理文件来获得写入的结果
批处理内容如下：

```text
#!bash REG query "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" /v "test" >>result.txt
```
在本地右键直接执行批处理文件
可是，批处理执行后无法输出写入的键值

# 0x02 消失的文件

### 1、编写程序写入文件
代码如下：

```text
#!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
如图

![原文图片](/media/2016/06/9489f4fb0e1647b292ba4ff39621bfc2)

### 2、获取写入的文件
批处理内容如下：

```text
#!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](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
修改后的代码如下：

```text
#!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; }
```
再次执行批处理

```text
#!bash REG query "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" /v "test" >>result.txt
```
成功获得键值
如图

![原文图片](/media/2016/06/6b46a4dd748a86c9885aa1e4c0034d76)

注：
也可结合使用Wow64DisableWow64FsRedirection和Wow64RevertWow64FsRedirection关闭和开启重定向，以此来跳过重定向，写入64位的注册表

### 2、修改批处理，查询重定向后的注册表键值（验证结论用）
不修改原程序，默认让其写入HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Run
修改批处理文件查询重定向后的注册表键值，代码为：

```text
#!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
所以批处理对应的内容如下：

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

### 2、补充
（1）之前遇到过的一个问题：
在测试Security Support Provider的时候就存在这个问题:
[http://drops.wooyun.org/tips/12518](http://drops.wooyun.org/tips/12518)
使用32位的程序将mimikatz.dll上传至域控(Server2008x64)的c:\windows\system32\下
由于重定向的缘故mimikatz.dll实际的上传位置为C:\Windows\SysWOW64，因此导致测试失败
解决方法：

- 文件的复制路径改为c:\windows\Sysnative

- 换用批处理实现复制功能，不会存在重定向问题
（2）可供测试32位和64位程序区别的小方法：
32位cmd：

```text
#!bash C:\Windows\SysWOW64\cmd.exe
```
64位cmd：

```text
#!bash c:\windows\system32\cmd.exe
```
分别执行写注册表和写文件的操作，重定向的细节显而易见
写注册表：

```text
#!bash reg add "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" /v "test"
```
查询注册表：

```text
#!bash REG query "HKLM\Software\Microsoft\Windows\CurrentVersion\Run" /v "test" REG query "HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Run" /v "test"
```
写文件：

```text
#!bash copy test.txt c:\windows\system32\test.txt
```
查找文件：

```text
#!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]，能够帮助大家更清晰的认识其中的细节。

![原文图片](/media/2016/06/ff0917d002edddbeaea942eb957c7a4e)

![原文图片](/media/2016/06/ab18bf8375222f05581608541537ae88)

[email protected]，也让我有了更清楚的认识。
更多学习资料：

- [https://msdn.microsoft.com/en-us/library/windows/desktop/aa384232(v=vs.85).aspx](https://msdn.microsoft.com/en-us/library/windows/desktop/aa384232(v=vs.85).aspx)

- [https://msdn.microsoft.com/en-us/library/windows/desktop/aa384187(v=vs.85).aspx](https://msdn.microsoft.com/en-us/library/windows/desktop/aa384187(v=vs.85).aspx)
本文由三好学生原创并首发于乌云drops，转载请注明

## Replies
