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

スポンサーリンク

【VBScriptを掌握する極限の知見】FSOと排他制御が織りなす、機密テキストの簡易難読化・インメモリ復元アーキテクチャ

レガシーシステムの自動化やバッチ処理において、VBScript(Visual Basic Scripting Edition)はいまだにWindows環境のインフラストラクチャの深部で静かに、しかし強烈な負荷を背負って稼働し続けている。
特に `Scripting.FileSystemObject`(以下、FSO)を用いたファイル入出力は、業務自動化の生命線だ。

だが、ここでシニアエンジニアとして直面する永遠の課題がある。「設定ファイルやスクリプト内に混入する平文の認証情報・機密テキストを、どうやって簡易的に、かつ堅牢に保護するか」という問題だ。

本稿では、本格的な暗号化ライブラリ(CryptoAPI等)が使えない厳格な閉域環境や、レガシーなWindows Server上において、FSOと独自の文字コード変換アルゴリズムを組み合わせ、機密データを「読ませず、漏らさない」ための極限の実装手法を解説する。

—

1. レガシー環境におけるセキュリティの現実解

現代のモダンな開発言語であれば、AESによる暗号化や環境変数の動的注入が標準である。しかし、VBScriptが稼働する素のWindows環境(WSH)では、依存関係を増やせない、サードパーティ製DLLの持ち込みが禁止されている、といった制約がつきまとう。

ここで求められるのは、「OS標準機能だけで完結し、かつ人間が目視しても即座に意味が分からない状態(簡易難読化)をFSOのI/Oパイプラインに組み込むこと」である。

今回は、単なるBase64エンコードのような「誰でも一瞬でデコードできる手法」ではなく、シフト演算とマルチバイト文字のコードポイント操作を融合させた、VBScriptならではの軽量かつ実用的な難読化アルゴリズムを構築する。

—

2. アーキテクチャ設計:メモリ最適化とオブジェクトのライフサイクル管理

VBScriptのメモリ管理は、COMコンポーネントの参照カウンタ(Reference Counting)に依存している。特にFSOやADODB.Streamを多用するスクリプトでは、「オブジェクトの解放漏れによるメモリリーク」が長時間稼働するバッチプロセスの致命傷となる。

以下の原則を徹底する:
1. インスタンスのスコープを最小化する
2. 処理完了後は即座に `Nothing` を代入し、COMの実体参照を断つ
3. エラーハンドリング(`On Error Resume Next`)の局所化

—

3. 実装コード:難読化I/Oエンジン(完全版)

以下のコードは、機密テキストを独自のオフセット・シフトアルゴリズムで難読化してFSO経由で書き出し、読み込み時にオンザフライで復元(デコード)してメモリ上に展開するプロダクション品質のVBScriptである。

‘ ==============================================================================
‘ Script Name: SecureFSOEngine.vbs
‘ Description: FSOを用いた機密テキストの簡易難読化・インメモリ復元モジュール
‘ Author: Chief Architect (Legacy Systems Division)
‘ ==============================================================================

Option Explicit

‘ メイン処理実行
Call Main()

Sub Main()
Dim targetPath
targetPath = CreateObject(“WScript.Shell”).CurrentDirectory & “\secure_config.dat”

Dim rawSecret
rawSecret = “DB_Password=SuperSecretP@ssw0rd!202X”

WScript.Echo “[INFO] 平文データ: ” & rawSecret

‘ 1. 難読化してFSOで書き込み
Call WriteObfuscatedFile(targetPath, rawSecret)
WScript.Echo “[INFO] 難読化ファイルを書き出しました: ” & targetPath

‘ 2. FSOから読み込み、メモリ上で復元
Dim restoredText
restoredText = ReadAndDeobfuscateFile(targetPath)
WScript.Echo “[INFO] 復元データ: ” & restoredText

‘ 3. 検証
If rawSecret = restoredText Then
WScript.Echo “[SUCCESS] データの整合性検証に成功しました。”
Else
WScript.Echo “[ERROR] データの整合性検証に失敗しました。”
End If
End Sub

‘ ==============================================================================
‘ 難読化書き込み関数
‘ ==============================================================================
Sub WriteObfuscatedFile(filePath, plainText)
Dim fso, ts
Set fso = CreateObject(“Scripting.FileSystemObject”)

‘ 独自の難読化処理を適用
Dim obfuscatedText
obfuscatedText = TransformText(plainText, 7) ‘ シフトキー = 7

‘ ForWriting (2), Create (True), Unicode (-1 または False ※ここではASCII/UTF-8制御のため標準テキストストリーム使用)
‘ 厳密な文字コード制御が必要な場合は ADODB.Stream を推奨するが、今回はFSOのTextStreamを使用
Set ts = fso.CreateTextFile(filePath, True, False)
ts.Write obfuscatedText

‘ クリーンアップ(リソースの即時解放)
ts.Close
Set ts = Nothing
Set fso = Nothing
End Sub

‘ ==============================================================================
‘ 難読化読み込み・復元関数
‘ ==============================================================================
Function ReadAndDeobfuscateFile(filePath)
Dim fso, ts, obfuscatedText
Set fso = CreateObject(“Scripting.FileSystemObject”)

If Not fso.FileExists(filePath) Then
Err.Raise 53, “ReadAndDeobfuscateFile”, “指定されたファイルが存在しません: ” & filePath
End If

‘ ForReading (1)
Set ts = fso.OpenTextFile(filePath, 1, False)
If Not ts.AtEndOfStream Then
obfuscatedText = ts.ReadAll
End If

ts.Close
Set ts = Nothing
Set fso = Nothing

‘ 復元処理(逆シフト)
ReadAndDeobfuscateFile = TransformText(obfuscatedText, -7)
End Function

‘ ==============================================================================
文字コード変換・難読化コアアルゴリズム (XOR代替の文字コードシフト)
‘ ==============================================================================
Function TransformText(ByVal targetStr, ByVal shiftKey)
Dim i, charCode, transformedChar
Dim resultBuffer

‘ VBScriptでの文字列連結のパフォーマンス劣化を防ぐため配列バッファを使用することも視野に入れるが、
‘ 設定ファイルサイズ(数KB程度)であればString連結の許容範囲内。
‘ 極限のパフォーマンスを求める場合は StringBuilder パターン(ADODB.Stream等)を使用する。
resultBuffer = “”

For i = 1 To Len(targetStr)
charCode = AscW(Mid(targetStr, i, 1))

‘ 文字コードポイントをシフト(簡易難読化)
‘ ※制御文字や予期せぬ文字化けを防ぐため、可視文字の範囲(例: 32~126)に絞る実装も有効
charCode = charCode + shiftKey

‘ 2バイト文字(日本語等)のオーバーフローを防ぐための丸め処理
If charCode > 65535 Then
charCode = charCode – 65535
ElseIf charCode < 0 Then charCode = charCode + 65535 End If resultBuffer = resultBuffer & ChrW(charCode) Next TransformText = resultBuffer End Function ---

4. チーフアーキテクトが指摘する「実装上の罠」と最適化の極意

このコードを実運用に投入する際、シニアエンジニアとして考慮すべき極限のポイントを共有する。

① 文字コード(BOMとエンコーディング)の罠

FSOの `CreateTextFile` はデフォルトでANSI(Shift_JIS等)またはUnicode(UTF-16LE)でファイルを生成する。
日本語の機密情報や特殊記号を扱う場合、`AscW` / `ChrW` 関数を用いたUnicodeベースの処理を行わないと、文字化けによって復元時にデータが破損する。
より厳密なエンコーディング制御(UTF-8での入出力など)が必要な場合は、FSO単体ではなく `ADODB.Stream` オブジェクトを組み合わせるべきである。

② パフォーマンスとメモリプレッシャー

`TransformText` 関数内の `resultBuffer = resultBuffer & …` は、VBScriptの内部実装(BSTRの再割り当て)において、大規模なテキストを扱うと極端なパフォーマンス低下(O(N^2)の挙動)を引き起こす。
設定ファイル程度のサイズ(数行〜数百バイト)であれば問題ないが、数十MBを超えるファイルを処理する場合は、事前に配列を確保する、あるいは `ADODB.Stream` のストリームバッファリングを活用する設計へ昇華させること。

③ セキュリティの限界値の理解

今回紹介した手法は、あくまで「ソースコードやファイルのエクスプローラー上での目視による平文暴露を防ぐ(セキュリティ・バイ・オキュスクレーション)」ためのものである。
本気で解析しようとする攻撃者に対しては無力であることを理解し、真の機密保護にはWindowsのアクセス制御リスト(ACL)によるファイル権限の厳格な絞り込み(実行ユーザー以外のアクセス遮断)を必ず併用すること。

—

5. 総括

VBScriptはレガシーな技術と片付けられがちだが、その制約の多い環境下でいかに堅牢なアーキテクチャを組み上げるかに、エンジニアの真価が問われる。
FSOの本質を理解し、オブジェクトライフサイクルを支配し、メモリ上のデータフローをコントロールすることで、枯れた技術であっても実用に耐えうる堅牢なシステムを構築することが可能だ。

現場のコードに魂を込めよ。自動化の神は細部に宿る。

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