關於32位程式在64位系統下執行中需要注意的重定向問題

wyzsk發表於2020-08-19
作者: 三好學生 · 2016/04/18 10:18

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的時候就存在這個問題:
/tips/?id=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,轉載請註明

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章