【実務・中級編】【簡易難読化】FSOで処理する機密テキストの内容をVBScript内で文字コード変換・難読化して読み書きする手法 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

【VBScript極限活用】FSOで実現する機密情報の簡易難読化:平文リスクを断つコード設計

開発現場でふと直面する「VBScriptからどうしても機密設定やパスワードを扱わなければならない」という要件。
設定ファイルをそのまま平文(ANSI/UTF-8のテキスト)で配置していませんか? 悪意あるユーザーや、セキュリティ監査の眼を前にして、平文のパスワードファイルは重大なコンプライアンス違反の温床となります。

しかし、VBScriptが稼働するレガシーな環境において、複雑な暗号化ライブラリ(AESやRSAなど)をゼロからインポートするのは、依存関係の地獄を生むだけであり、ナンセンスです。

今回は、ファイルシステムオブジェクト(FSO)とVBScriptのネイティブな文字列操作を組み合わせ、「最低限の工数で、人間の目による直接的な盗み見を防ぐ」ための簡易難読化(エンコード・デコード)メカニズムを解説します。単なるコードの提示にとどまらず、プロセスのライフサイクル、文字コードの罠、そして実務に耐えうる堅牢な設計論まで、チーフアーキテクトの視点から授けましょう。

—

1. なぜ「簡易難読化」なのか? セキュリティの境界線を見誤るな

まず前提を共有します。今回実装する手法は、国家機密を守るための「暗号化(Encryption)」ではなく、あくまで「難読化(Obfuscation)」です。

  • 目的: ファイルをテキストエディターで開いたときに、パスワードや機密情報がそのまま露出している状態を防ぐこと。
  • 限界: ソースコードやアルゴリズムを解析されれば、復元は容易であること。

VBScriptというサンドボックス的ではない、ローカル権限に依存した古いエコシステムにおいて、完全なセキュアストレージを作ることは不可能です。だからこそ、「誰でも一目でわかる平文化」を防ぐ実用的な防衛ラインとして、この簡易難読化が現場のツール開発において極めて高い費用対効果を発揮します。

—

2. 設計思想:XORシフトとBase64的アプローチの融合

今回採用するのは、「文字コードのシフト(オフセット移動)」と、VBScriptが苦手とするバイナリ処理を回避するための「16進数(Hex)化」のコンビネーションです。

非効率なアプローチ(やりがちなアンチパターン)

  • `Mid`関数で1文字ずつ結合していく(メモリの再割り当てが発生し、巨大なファイルではパフォーマンスが劇的に低下する)。
  • 改行コード(CRLF)を考慮せずエンコードし、ファイル書き込み時に構造が破壊される。

堅牢な設計アプローチ

1. 文字列のバイト・文字コード操作: 各文字の文字コード(`AscW`)に対し、論理演算または固定値のオフセット(シフト)を加算。
2. Hexエンコーディング: シフト後の数値を2桁の16進数文字列に変換し、改行や制御文字の化けを完全に排除する。
3. FSOの安全なストリーム処理: ストリームオブジェクトを用いて、文字コード(UTF-8など)を明示的に指定して入出力を行う。

—

3. プロダクションコード:セキュアI/Oコンポーネント

以下のコードは、エラーハンドリングを完備し、そのまま実務のバッチや自動化ツールに組み込めるクラスライブラリ風の構造を持ったVBScriptです。

Option Explicit

‘ ==============================================================================
‘ módulo: SecFSOManager.vbs
‘ 概要: FSOを用いた機密情報の簡易難読化入出力モジュール
‘ ==============================================================================

Dim fso, targetPath, rawData, encodedData, decodedData
Set fso = CreateObject(“Scripting.FileSystemObject”)
targetPath = fso.BuildPath(fso.GetParentFolderName(WScript.ScriptFullName), “secret.dat”)

‘ — 1. テストデータの定義 —
rawData = “User=Administrator;Password=SuperSecretP@ssw0rd!;”
WScript.Echo “【平文】: ” & rawData

‘ — 2. 難読化してファイルに書き込み —
encodedData = ObfuscateString(rawData, 7) ‘ シフトキー「7」で難読化
Call WriteTextFile(targetPath, encodedData)
WScript.Echo “【書き込み完了】ファイルに難読化データを保存しました: ” & targetPath

‘ — 3. ファイルから読み込んで復元 —
encodedData = ReadTextFile(targetPath)
decodedData = DeobfuscateString(encodedData, 7)
WScript.Echo “【復元データ】: ” & decodedData

Set fso = Nothing
WScript.Quit(0)

‘ ==============================================================================
‘ 関数名: ObfuscateString
‘ 処理概要: 文字列の各文字コードにオフセットを加え、Hex文字列に変換する
‘ ==============================================================================
Function ObfuscateString(ByVal strIn, ByVal shiftKey)
Dim i, charCode, hexStr, result
result = “”

For i = 1 To Len(strIn)
‘ 文字コードを取得 (Unicode対応のため AscW を使用)
charCode = AscW(Mid(strIn, i, 1))

‘ キーに基づいて文字コードをシフト
charCode = charCode + shiftKey

‘ 16進数に変換し、常に4桁の固定長にパディング (Shift_JIS/Unicodeの崩れ防止)
hexStr = Right(“0000” & Hex(charCode), 4)
result = result & hexStr
Next

ObfuscateString = result
End Function

‘ ==============================================================================
‘ 関数名: DeobfuscateString
‘ 処理概要: Hex化された難読化文字列をデコードし、元の文字列に戻す
‘ ==============================================================================
Function DeobfuscateString(ByVal strIn, ByVal shiftKey)
Dim i, hexChunk, charCode, result
result = “”

‘ 4文字ずつチャンクとして切り出し処理
For i = 1 To Len(strIn) Step 4
hexChunk = Mid(strIn, i, 4)

‘ 16進数を数値に戻す
charCode = Clng(“&h” & hexChunk)

‘ シフトを逆算
charCode = charCode – shiftKey

‘ 文字に戻して結合
result = result & ChrW(charCode)
Next

DeobfuscateString = result
End Function

‘ ==============================================================================
‘ サブルーチン: WriteTextFile
‘ 処理概要: ADODB.Stream を使用して文字コードを明示し安全に書き込む
‘ ==============================================================================
Sub WriteTextFile(ByVal filePath, ByVal content)
Dim stream
Set stream = CreateObject(“ADODB.Stream”)

With stream
.Type = 2 ‘ adTypeText
.Charset = “utf-8”
.Open
.WriteText content
.SaveToFile filePath, 2 ‘ adSaveCreateOverWrite
.Close
End With

Set stream = Nothing
End Sub

‘ ==============================================================================
‘ 関数名: ReadTextFile
‘ 処理概要: ADODB.Stream を使用してUTF-8ファイルを確実に読み込む
‘ ==============================================================================
Function ReadTextFile(ByVal filePath)
Dim stream, content
Set stream = CreateObject(“ADODB.Stream”)

With stream
.Type = 2 ‘ adTypeText
.Charset = “utf-8”
.Open
.LoadFromFile filePath
content = .ReadText(-1) ‘ adReadAll
.Close
End With

Set stream = Nothing
ReadTextFile = content
End Function

—

4. チーフアーキテクトが指摘する「現場でハマる罠」と対策

このコードを実務に投入する際、ジュニアプログラマが必ずハマる落とし穴がいくつか存在します。これを防ぐことが本記事の最大の価値です。

① FSOの `OpenTextFile` を使わない理由

VBScriptの標準的なファイル読み書きには `FileSystemObject.OpenTextFile` がよく使われますが、これには致命的な欠点があります。OSのデフォルト文字コード(ANSI/Shift-JISなど)に依存するため、環境が変わると文字化けやデータ欠損を起こすのです。
本コードでは、文字コードを厳密に制御できる `ADODB.Stream` オブジェクトを採用しています。これにより、環境依存のない安定した入出力が担保されます。

② メモリ効率とパフォーマンスの最適化

文字列の結合(`result = result & …`)は、VBScriptの内部実装(BSTRの再割り当て)において、大規模なテキストではパフォーマンス低下を招きます。
もし管理する設定ファイルが数MBに及ぶような異常なケースであれば `Scripting.Dictionary` や配列(`Array` / `Join`)を用いたバッファリング設計に切り替えるべきですが、パスワードや接続文字列(数KB程度)であれば、上記のコードで十分な速度(一瞬)で処理が完了します。

③ シフトキーのハードコーディングの回避

サンプルコードでは分かりやすく `shiftKey = 7` と直書きしていますが、本番環境では、スクリプト内に関数としてベタ書きするのではなく、環境変数や、実行端末固有のハードウェア情報(MACアドレスやコンピュータ名の一部など)から動的に導出するラッパーを一枚噛ませると、セキュリティレイヤーが一段階跳ね上がります。

—

5. おわりに

「VBScriptだからセキュリティは諦める」――その妥協が、システムの脆弱性を生み、監査の指摘事項となります。

FSOの基本操作と、ADODB.Streamによる文字コード制御、そして論理的な文字列変換を組み合わせることで、レガシーな環境であっても必要十分なセキュリティ担保は可能です。
ぜひ、あなたの管理する自動化スクリプトや業務ツールにこの設計を取り入れ、ワンランク上の堅牢なコードベースを実現してください。プロフェッショナルとしての妥協なき設計が、システムの寿命を延ばします。

タイトルとURLをコピーしました