Windows 註冊表是系統配置的核心數據庫。本文系統總結註冊表操作的四大主流方式:原生 reg.exe、Java JReg 框架、主流語言 API,並分析惡意代碼通過註冊表實現持久化、提權的常見手法。
無需編程,批處理/腳本直接調用,功能完整、穩定可靠。
| 操作 | 命令示例 |
|---|---|
| 查詢鍵/值 | reg query HKLM\Software\MyApp /v Version |
| 添加/修改值 | reg add HKLM\Software\MyApp /v Path /t REG_EXPAND_SZ /d "%%SystemRoot%%" /f |
| 刪除值 | reg delete HKLM\Software\MyApp /v Temp /f |
| 導出備份 | reg export HKLM\Software\MyApp backup.reg |
| 導入恢復 | reg import backup.reg |
for /f "tokens=3" %%i in ('reg query "HKLM\Software\MyApp" /v Version ^| find "Version"') do set MY_VER=%%i
echo 版本: %MY_VER%
JReg 通過 JNI 調用 Windows API (RegOpenKeyEx, RegQueryValueEx 等),功能強大但部署麻煩(需隨應用分發 jreg.dll,32/64 位區分)。
import com.registry.RegistryKey;
import com.registry.RegistryValue;
public class RegUtil {
static final RegistryKey LOCAL_MACHINE = RegistryKey.getRootKeyForIndex(RegistryKey.HKEY_LOCAL_MACHINE_INDEX);
// 讀取遠程桌面端口
public static int getRdpPort() {
RegistryKey key = new RegistryKey(LOCAL_MACHINE,
"SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations\\RDP-Tcp");
if (key.hasValues()) {
RegistryValue val = key.getValue("PortNumber");
// val.toString() -> "Name: PortNumber Type: REG_DWORD Value: 3389"
String s = val.toString();
return Integer.parseInt(s.substring(s.lastIndexOf(": ") + 2));
}
return -1;
}
// 遍歷服務列表(示例)
public List<Map> listServices() {
RegistryKey svcKey = new RegistryKey(LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\services");
List<RegistryKey> subKeys = svcKey.getSubKeys();
// 遍歷 subKeys,提取 DisplayName, ImagePath, Start, Description 等值
// 注意:值編碼多為 UnicodeLittleUnmarked,需 byte[] 轉 String
}
}
避坑:getSubKeys() 在某些 JDK/JReg 版本下需先定位到父鍵再調用,否則返回空。
| 語言 | 核心 API / 庫 | 備註 |
|---|---|---|
| C# | Microsoft.Win32.Registry, RegistryKey | 原生托管封裝,極其簡潔 |
| C/C++ | Win32 API: RegOpenKeyEx, RegSetValueEx | 底層控制最精細 |
| Python | winreg (標準庫), pywin32 | winreg.OpenKey, SetValueEx |
| PowerShell | Provider: Get-Item HKLM:\Software\..., Set-ItemProperty | 物件化管道操作,極強 |
| Go | golang.org/x/sys/windows/registry | 輕量封裝 |
| Node.js | winreg (npm), ffi-napi 調用 DLL | 異步回調風格 |
| PHP | COM("WScript.Shell") -> RegRead/RegWrite | 依賴 COM 組件,僅限 Windows |
| Java | JReg, Preferences API (僅用戶節點), Runtime.exec("reg ...") | 首選 reg.exe 進程調用,避免 JNI 坑 |
| 技術 | 註冊表位置 | 原理 | 檢測建議 |
|---|---|---|---|
| 開機自啟 | HKLM\Software\Microsoft\Windows\CurrentVersion\RunHKCU\Software\Microsoft\Windows\CurrentVersion\Run | 用戶登錄/系統啟動時自動執行指定程序 | 監控 Run/RunOnce 鍵值變更,白名單校驗 |
| 服務註冊 | HKLM\SYSTEM\CurrentControlSet\Services\ | 創建服務鍵,設置 ImagePath 指向惡意程序,Start=2 (自動) | 審計新增服務,驗證簽名與路徑合法性 |
| 映像劫持 (IFEO) | HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\值: Debugger = malware.exe | 目標程序啟動時,系統改為啟動 Debugger 指定的程序 | 監控 IFEO 鍵創建,合法調試器極少 |
| DLL 劫持/KnownDLLs | HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs | 修改系統已知 DLL 映射,加載惡意 DLL | 嚴格保護 KnownDLLs 權限,啟用簽名強制 |
| WMI 事件訂閱 | HKLM\SOFTWARE\Microsoft\WBEM\Scripting\... (實際存儲於 WMI 庫) | 註冊永久事件消費者,觸發條件執行惡意腳本 | WMI 審計工具掃描可疑消費者 |
HKCU\Software\,避免寫入 HKLM 需管理員權限。HKCU\Software\Classes\VirtualStore。reg.exe,無依賴、可遠程(\\HOST\HKLM\...)。Runtime.exec("reg ...") 或 JNA 調用 Win32 API,避開 JReg 的 DLL 地獄。