萬盛學電腦網

您现在的位置: 萬盛學電腦網 >> 網路安全 >  >> 網路應用技術

WinSCP 密碼獲取與解密全解析:註冊表、INI 文件與多語言實現

WinSCP 預設將用戶密碼加密存儲,本文彙總其存儲位置、加密邏輯及多語言(Go、Java、C#)解密實現代碼,供安全研究與授權審計參考。

一、 密碼存儲位置

註冊表(舊版/默認)

HKEY_USERS\\Software\Martin Prikryl\WinSCP 2\Sessions\

INI 文件(Win7/8/10/11 常見)

  • C:\Users\\AppData\Local\VirtualStore\Program Files (x86)\WinSCP\WinSCP.ini (64 位系統)
  • C:\Program Files (x86)\WinSCP\WinSCP.ini (64 位系統)
  • C:\Users\\AppData\Local\VirtualStore\Program Files\WinSCP\WinSCP.ini (32 位系統)
  • C:\Program Files\WinSCP\WinSCP.ini (32 位系統)

二、 開源解密項目

三、 加密算法核心邏輯(以 Go 版為例)

const (
    PW_MAGIC = 0xA3
    PW_FLAG  = 0xFF
)

func decrypt(host, username, password string) string {
    key := username + host                    // 密鑰 = 用戶名 + 主機名
    passbytes := hexDecode(password)          // 16 進制字符串轉字節切片

    flag, passbytes := decNext(passbytes)
    var length byte
    if flag == PW_FLAG {
        _, passbytes = decNext(passbytes)     // 跳過 dummy
        length, passbytes = decNext(passbytes)
    } else {
        length = flag
    }

    toBeDeleted, passbytes := decNext(passbytes)
    passbytes = passbytes[toBeDeleted*2:]     // 跳過填充

    clearpass := ""
    for i := byte(0); i < length; i++ {
        val, passbytes := decNext(passbytes)
        clearpass += string(val)
    }

    if flag == PW_FLAG {
        clearpass = clearpass[len(key):]      // 去除前綴 key
    }
    return clearpass
}

func decNext(passbytes []byte) (byte, []byte) {
    if len(passbytes) < 2 { return 0, passbytes }
    a, b := passbytes[0], passbytes[1]
    passbytes = passbytes[2:]
    return ^(((a >> 4) + b) ^ PW_MAGIC) & 0xff, passbytes
}

Java 版邏輯完全一致,僅語法差異。核心點:

  1. 密鑰 = Username + Hostname(Unicode)。
  2. 2. 密文為十六進制字符串,每兩字符解一字節。 3. 解密函數 decNext 利用魔數 0xA3 與位運算還原明文字節。 4. Flag=0xFF 表示新版格式,含長度字節與填充;否則舊版格式。 5. 解出明文後,若為新版需去除前綴 Key。

四、 安全提示

  • WinSCP 加密屬可逆混淆,非真正加密,任何拿到配置文件/註冊表權限者均可解密。
  • 生產環境建議:勿勾選「保存密碼」,改用 SSH Key 認證或集中憑證管理工具。
  • 本文代碼僅供授權審計、滲透測試、遺忘密碼找回等合法場景使用。
copyright © 萬盛學電腦網 all rights reserved