1. 程式人生 > >關於32位程式在64位系統下執行中需要注意的重定向問題(有圖有真相)(***)

關於32位程式在64位系統下執行中需要注意的重定向問題(有圖有真相)(***)

0x00 前言

最近學習了[email protected]的文章《Persistence Architecture Matters》,恰巧解決了我之前遇到過的一個問題,理清了檔案和登錄檔重定向中需要注意的細節

大家在學習的過程中難免也會碰到,所以在此分享一下。

0x01 消失的登錄檔鍵值

OS:Win8x64
開發環境:VS2008

1、編寫程式寫入登錄檔

程式碼如下:

#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

如圖


2、獲取寫入的鍵值

編寫批處理檔案來獲得寫入的結果

批處理內容如下:

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

在本地右鍵直接執行批處理檔案

可是,批處理執行後無法輸出寫入的鍵值

0x02 消失的檔案

1、編寫程式寫入檔案

程式碼如下:

#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

如圖


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

(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 <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;
}

再次執行批處理

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

成功獲得鍵值

如圖


注:
也可結合使用Wow64DisableWow64FsRedirectionWow64RevertWow64FsRedirection關閉和開啟重定向,以此來跳過重定向,寫入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)之前遇到過的一個問題:

使用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\

引用[email protected]文章中的兩幅圖,能夠幫助大家更清晰的認識其中的細節。



感謝[email protected]的分享。解決了我的問題,也讓我有了更清楚的認識。

更多學習資料:

本文由三好學生原創並首發於烏雲drops,轉載請註明

相關推薦

關於32程式64系統執行需要注意定向問題真相***

0x00 前言 最近學習了[email protected]的文章《Persistence Architecture Matters》,恰巧解決了我之前遇到過的一個問題,理清了檔案和登錄檔重定向中需要注意的細節 大家在學習的過程中難免也會碰到,所以在此分享一下。

64機器上VS2012編譯的32程式在XP系統執行提示Wow64EnableWow64FsRedirection無法定位於輸入點

Wow64EnableWow64FsRedirection()函式是64位計算機用於定義轉向的函式,在32位計算機中不存在轉向問題 因此,在32位計算機中的kernel32.dll庫中就不存在此函式,當程式執行在32位計算機中時,就會提示無法定位 解決方法: 採用函式指標的

Java程式在linux系統執行,為什麼會佔用很多虛擬記憶體?

Question: I have a problem with a Java application running under Linux. When I launch the application, using the default maximum heap size (64mb), I s

各種資料型別在163264系統所佔位元組差異簡介

編寫C、C++程式時需要考慮每種資料型別在記憶體中所佔的記憶體大小,即使同一種資料型別在不同平臺下所佔記憶體大小亦不相同,具體對比如下: 資料型別 16位系統(byte) 32位系統(by

Java在win10系統3264環境變數設定

今天解決的一個問題終於把困擾我多年的環境變數之類的東西搞懂了。 這一切罪惡的根源就是win10的64位系統可以相容32位軟體 當我多年前安裝java的時候,我選擇了安裝32位版本的java而並非64位版本。我按照百度經驗的教程https://jingyan.baidu.c

Linux 檢視系統32 還是64 的方法

1. 從系統檢視 1.1 uname -a 命令 [[email protected] ~]# uname -a Linux qs-dmm-rh2 2.6.18-194.el5 #1 S

判斷程式自身是執行32還是64

// 在做驅動和應用層通訊時,兩個程式必須都是32位或者64位的。(可能32位和64位的驅動可以通訊,未了解。)// 但是64位下可以執行32位的程式,導致與驅動的通訊失敗,於是乾脆就加了個判斷自身是否是32位還是64位。bool IsApp64() { int nNum

linux 3264系統資料型別長度的區別

近日在centos下用c寫東西,這個程式的服務端執行在64位的centos下,客戶端有可能是32機,也有可能是64位的。 為了保證資料傳輸的一致性制定了一套協議,用struct實現。為了保證輸出過程中,資料的完整性,特別針對系統的不同對struct裡變數的型別進行了優化。為了

Inno Setup 根據window系統3264安裝對應程式

最近在弄java Swing 打包成可執行檔案,這時候用到了Inno Setup工具,這個打包成安裝程式還是非常不錯的,下面用到的Inno Setup的指令碼,有註釋 ; -- 64BitTwoArch.iss -- ; Demonstrates how to instal

Linux系統查看系統32還是64方法總結 in 創新實訓

-a 如果 rep 分享 查看 blog cpu 整理 ble 這篇博客是總結、歸納查看Linux系統是32位還是64位的一些方法,很多內容來自網上網友的博客。本篇只是整理、梳理這方面的知識,方便自己忘記的時候隨時查看。 方法1:getconf LONG_BIT 查看 如下

3264系統,到底哪個好?

操作系統 32位系統 64位系統 今天這是個純理論分享了,32位和64位系統有什麽區別?我們到底用哪個好?這個問題在xp時代都不存在,vista系統不談,從win7開始,才出現在我們面前,讓我們抉擇。相信好多人不懂或有些誤區,更甚至有部分自稱為【專家】的人告訴你用32位的,用64位的系統好多軟件都

c#判斷操作系統32還是64

ping interop 64位 lin last 直接 run 遇到 roc 做一個c#項目時,遇到要獲取操作系統位數的問題,在網上找了幾個小時,都沒有找到比較完整的解決方案。話不多說,直接上可以運行的代碼(簡單、粗暴) using System.Runtime.Con

3264系統的區別

blank 內存 jce com 解釋 理論 light 一次 body 系統32位和64位官方解釋 32位和64位操作系統是指:CPU一次處理數據的能力是32位還是64位。現在市場上的CPU一般都是64位的,但是這些CPU並不是真正意義上的64 位CPU,裏面依然保留了大

Linux系統32還是64查看方法總結

x86_64 如果 9.png 支持 ges mod lag span long 【聲明】 本文版權歸原作者所有,歡迎轉載,轉載請註明出處。 原作者:瀟湘隱者 出處:http://www.cnblogs.com/kerrycode/ 原文鏈接:https://www.cn

32/64系統,jdk326432/64jdk編譯出來的class和eclipse 3264

首先關於32位/64位系統,jdk32位,64位,32/64位jdk編譯出來的class和eclipse 32位和64位的一些對應關係做些說明。 1.32位作業系統不可以裝64位jdk,64位作業系統一般都可以安裝32位jdk,64位jdk是完美髮揮效能的。 2.64位eclipse只能在6

3264程式的區別

轉自:https://blog.csdn.net/nma_123456/article/details/45077345 由於作業系統記憶體分配的不同,導致軟體開發過程中,需要編譯不同版本的軟體,此處以VS為例。 1、編譯程式根據需要選擇不同的編譯環境:

3264系統區別及int位元組數

一、64位系統和32位有什麼區別? 1、64bit CPU擁有更大的定址能力,最大支援到16GB記憶體,而32bit只支援4G記憶體 2、64位CPU一次可提取64位資料,比32位提高了一倍,理論上效能會提升1倍。但這是建立在64bit作業系統,64bit軟體的基礎上的。 什麼是64位處理器? 之所以叫

【問題】檢視當前系統32還是64

方法1 uname -i 方法2 getconf LONG_BIT 方法3 CentOS 6.X及低版本    file /sbin/init CentOS 7.X    file /lib/systemd/systemd

3264 CPU、編譯器、作業系統、應用程式、arm和X86關係

一:arm和X86的區別 arm:對應精簡指令集 X86:對應複雜指令集 arm上的和X86上編譯過的的東西是不能相互使用的,因為指令集不一樣嘛。指令集可以通俗的理解為,溝通語言。arm和X86之間東西不能直接用,類似於一個美國人和一箇中國人各自只說自己的語言,那麼這兩個人是沒法溝通的。

3264 區別 : CPU 作業系統 應用程式

https://www.cnblogs.com/mlgjb/p/8385658.html   原文連結 1.64位CPU與32位CPU 這兩者的指令集合、運算元位數、暫存器名稱和個數等等都不相同。 一、比如一條mov eax,1指令,可能在32bCPU上