【テクニカル・上級編】【上級】ステンシル内のマスターシェイプを暗号化・保護して配布する方法 – Visio VBA解析バイブル

スポンサーリンク
スポンサーリンク

砦としてのステンシル:実行時再構築によるマスターシェイプの知的財産保護戦略

エンジニアリングの現場において、図形(シェイプ)は単なる視覚的記号ではない。それは、長年の設計ノウハウ、複雑な計算式(ShapeSheet)、そして企業秘密が凝縮された「動的なアルゴリズム」そのものである。

しかし、Visioの標準的なステンシル形式(.vssx)は、実態はXMLの集合体に過ぎない。XML構造を解析し、あるいは単純な解凍プロセスを経るだけで、我々が心血を注いで構築したマスターシェイプのロジックは、白日の下にさらされる。パスワード保護? そんなものは、プロフェッショナルなリバースエンジニアリングの前では、紙の壁に等しい。

本稿では、ステンシルを「配布可能なファイル」として渡すのではなく、「許可された環境でのみ、メモリ上で動的に再構築されるコード」へと昇華させる、極限の防御戦略を解説する。

1. 脆弱性の本質:なぜ標準的な配布では不十分なのか

通常のステンシル配布における最大のリスクは、「静的な資産(Static Asset)としての存在」にある。

1. XML構造の露出: .vssxファイルは実質的にZIPアーカイブであり、中の`master.xml`や`shape.xml`を解析すれば、ShapeSheetの数式や隠蔽したデータ属性(Prop)が容易に読み取れる。
2. オブジェクトの永続性: ファイルとして存在している限り、その中身をスキャンするツールは無限に存在する。
3. 環境の非制御: 誰が、どの端末で、そのロジックをコピーしたのかを追跡する術が、標準機能には存在しない。

我々が目指すべきは、「配布物にはロジックを含めず、認証された実行環境においてのみ、メモリ内にロジックを注入する」アーキテクチャである。

2. 防御アーキテクチャ:三層の防御レイヤー

この戦略を実現するために、以下の三層構造を構築する。

Layer 1: 環境認証(Hardware Fingerprinting)

Windows APIを呼び出し、実行環境のハードウェア識別子(UUIDやMACアドレス、ボリュームシリアル)を取得。許可されたホワイトリストと照合する。

Layer 2: データ難読化(Encrypted Payload)

マスターシェイプの構成要素(ジオメトリ情報、ShapeSheetの数式、カスタムプロパティ)を、暗号化されたバイナリ形式、あるいは難読化された文字列としてVBAプロジェクト内に埋め込む。

Layer 3: 実行時再構築(Runtime Reconstruction)

認証成功時のみ、VBAが暗号化データをデコードし、`Master.Shapes.Add`やプロパティ操作を通じて、メモリ上のステンシルへシェイプを「注入」する。

3. 実装へのアプローチ:プロフェッショナルのコード

以下に、Windows APIを用いた環境認証と、暗号化されたプロパティを注入するエンジンの骨格を示す。

3.1 環境認証エンジン(Windows APIの活用)

単なるマシン名ではなく、より強固な識別子としてボリュームシリアルを利用する。

Option Explicit

' Windows APIの宣言: ボリュームシリアルの取得
Private Declare PtrSafe Function GetVolumeInformation Lib "kernel32" Alias "GetVolumeInformationA" ( _
    ByVal lpRootPathName As String, _
    ByVal lpVolumeNameBuffer As String, _
    ByVal nVolumeNameSize As Long, _
    ByRef lpVolumeSerialNumber As Long, _
    ByVal lpMaximumComponentLength As Long, _
    ByRef lpFileSystemFlags As Long, _
    ByVal lpFileSystemNameBuffer As String, _
    ByVal nFileSystemNameSize As Long) As Long

''' <summary>
''' 実行環境のハードウェア識別子(シリアル)を検証する
''' </summary>
Public Function IsAuthorizedEnvironment() As Boolean
    Dim serialNumber As Long
    Dim result As Long
    
    ' Cドライブのボリュームシリアルを取得
    result = GetVolumeInformation("C:\", ByVal vbNullString, 0, serialNumber, 0, 0, ByVal vbNullString, 0)
    
    ' 本来はここでDBや暗号化されたリストと照合する
    ' 例: 許可されたシリアル番号 0x12345678
    If serialNumber = &H12345678 Then
        IsAuthorizedEnvironment = True
    Else
        IsAuthorizedEnvironment = False
    End If
End Function

3.2 マスターシェイプ注入エンジン(メモリ最適化と再構築)

ここでは、暗号化された「レシピ(構成情報)」を読み込み、マスターシェイプを動的に生成するロジックの概念を示す。

Option Explicit

' 簡易的なXORデコーダー(実運用ではAES等の強固なアルゴリズムを推奨)
Private Function DecryptPayload(ByVal encryptedData As String, ByVal key As String) As String
    Dim i As Long, j As Long
    Dim decrypted As String
    Dim kLen As Long: kLen = Len(key)
    
    decrypted = encryptedData
    For i = 1 To Len(encryptedData)
        decrypted = Left(decrypted, i - 1) & _
                     Chr(Asc(Mid(decrypted, i, 1)) Xor Asc(Mid(key, ((i - 1) Mod kLen) + 1, 1))) & _
                     Mid(decrypted, i + 1)
    Next i
    DecryptPayload = decrypted
End Function

''' <summary>
''' 暗号化されたデータからマスターシェイプを再構築する
''' </summary>
Public Sub InjectMasterShapes(ByRef targetStencil As Visio.Document)
    Dim master As Visio.Master
    Dim newShape As Visio.Shape
    Dim encryptedRecipe As String
    Dim decryptedRecipe As String
    Dim key As String: key = "Architect_Secret_Key_2024"
    
    ' 1. 暗号化されたレシピの取得(実際は外部バイナリや難読化文字列から)
    ' ここでは例として、ShapeSheetの数式を含むデータを模した暗号化文字列
    encryptedRecipe = "..." ' 実際には極めて複雑なバイナリ文字列
    
    ' 2. デコード
    decryptedRecipe = DecryptPayload(encryptedRecipe, key)
    
    On Error GoTo ErrorHandler
    
    ' 3. ステンシルへの注入プロセス
    ' 既存のマスターを削除、あるいは新規作成
    ' ここでは、テンプレートとなるマスターに対して、ロジックのみを注入する手法を採る
    Set master = targetStencil.Masters.Item("TemplateMaster")
    
    ' 形状のプロパティやShapeSheetの数式を動的に適用
    ' 例: セル(Width)に特定の計算式を注入
    With master.Shapes.Item(1)
        ' ShapeSheetへの直接アクセスは、実行時のパフォーマンスに影響するため、
        ' 可能な限り最小限の回数に抑えること
        .Cells("Width").Formula = decryptedRecipe ' デコードされた数式を注入
    End With

    ' 4. メモリの明示的解放(オブジェクトライフサイクルの管理)
    Set newShape = Nothing
    Set master = Nothing
    Exit Sub

ErrorHandler:
    MsgBox "Security Violation or Corruption detected.", vbCritical
    Set master = Nothing
End Sub

4. 極限の知見:パフォーマンスとメモリ管理の境界線

この高度な手法を実装する際、シニアエンジニアが直面する真の課題は、セキュリティではなく「リソースの管理」である。

オブジェクトのライフサイクルとメモリリーク

VBAで大量のマスターシェイプを動的に生成・操作する場合、`Visio.Shape` や `Visio.Master` オブジェクトの参照カウントが適切に処理されないと、Visioプロセスが急速にメモリを消費し、最終的にクラッシュする。

  • Rule 1: ループ内でのオブジェクト生成後は、必ず `Set obj = Nothing` を実行すること。
  • Rule 2: `Application.ScreenUpdating = False` は当然として、大規模な再構築時は `Application.Calculation = visCalculationManual` を検討せよ。

実行速度のトレードオフ

実行時に全てのロジックをデコードして注入する手法は、図面を開く際の「初動」を重くする。

  • 最適化戦略: 全てのシェイプを一度に注入するのではなく、ユーザーがステンシルからシェイプをドラッグ&ドロップした瞬間に、「遅延注入(Lazy Injection)」を行うイベント駆動型アーキテクチャを採用せよ。`Stencil.MasterAdded` や `Document.WindowSelectionChange` 等のイベントを監視し、必要なタイミングでロジックを流し込むのだ。

結論:アーキテクトの責務

ステンシルの保護は、単なる「隠蔽」ではない。それは、企業の知的資産を、正当な権利を持つ者だけが利用できる「道具」へと変える、設計思想の確立である。

標準機能に頼るな。Windows APIを操り、メモリの挙動を制御し、実行時のみに存在する「概念としてのステンシル」を構築せよ。それが、レガシーな環境を支配し、次世代の自動化システムを構築するチーフアーキテクトに求められる真の技術力である。

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