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

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

0x00 前言
=======

* * *

最近学习了Stuart@ukstufus的文章《Persistence 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、编写程序写入注册表

代码如下:

“`
#include

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](http://drops.javaweb.org/uploads/images/ad6d8f9cfe210c7561fd03a48211a05161b79cb2.jpg)

### 2、获取写入的键值

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

批处理内容如下:

“`
REG query “HKLM\Software\Microsoft\Windows\CurrentVersion\Run” /v “test” >>result.txt

“`

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

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

0x02 消失的文件
==========

* * *

### 1、编写程序写入文件

代码如下:

“`
#include
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](http://drops.javaweb.org/uploads/images/8faf794a32437ffb098f3978d16991b8d3436e55.jpg)

### 2、获取写入的文件

批处理内容如下:

“`
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`

修改后的代码如下:

“`
#include “stdafx.h”
#include
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;
}

“`

再次执行批处理

“`
REG query “HKLM\Software\Microsoft\Windows\CurrentVersion\Run” /v “test” >>result.txt

“`

成功获得键值

如图

![Alt text](http://drops.javaweb.org/uploads/images/ce5b3e951e932a5629412152d5e16fde04753c8b.jpg)

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

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

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

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

“`
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

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

“`
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,因此导致测试失败

解决方法:

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

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

32位cmd:

“`
C:\Windows\SysWOW64\cmd.exe

“`

64位cmd:

“`
c:\windows\system32\cmd.exe

“`

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

写注册表:

“`
reg add “HKLM\Software\Microsoft\Windows\CurrentVersion\Run” /v “test”

“`

查询注册表:

“`
REG query “HKLM\Software\Microsoft\Windows\CurrentVersion\Run” /v “test”
REG query “HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Run” /v “test”

“`

写文件:

“`
copy test.txt c:\windows\system32\test.txt

“`

查找文件:

“`
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\`

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

![Alt text](http://drops.javaweb.org/uploads/images/6049f113bd5f99a3010671ad08b131459a365e82.jpg)

![Alt text](http://drops.javaweb.org/uploads/images/0a82053153cd21961ac08ab4c4dacc9eb2ab659f.jpg)

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

更多学习资料:

* [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,转载请注明**

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发

请登录后发表评论

    请登录后查看评论内容