SSブログ

ちょっとしたプログラムプロテクトの話 #2 [プログラム]

ちょっとしたプログラムプロテクトの話 #1」のつづきです。




コード内のメッセージを見たい VS メッセージを覗かれたくない

この戦いに決着をつけるためのアプローチとしては、大きく分けて2つの方法が採られました。

ひとつは、リストを見られないように BASIC プログラム自体に細工をすること。
もうひとつは、コード内にあるメッセージを「暗号化」することでした。




ひとつめのアプローチは BASIC プログラム自体に細工をすることです。

あるゲームではリストの各所に REM 文が挿入してあり、コメントの先頭文字が「CLR(画面消去)」になっていました。 リストを取ると頻繁に画面消去が繰り返され、内容を確認する事がとても困難になります。

また、あるゲームでは 'P' オプション付きでセーブされているのですが、ワークエリアを操作して 'P' オプションを解除しても、リストを取ると特定の場所の表示時に「暴走」するような仕掛けがしてありました。
リスト中に「…:PC=98」という記述があり、この部分に細工がしてありました【PC-9801版 大○○2】

どちらの場合も、「MON」命令が無効化されていたのですが、無効化を解除した後でモニタから直接 BASIC のテキストを操作する事で破られてしまいました。




様々な方法で BASIC のテキストを「不可視化」する試みが行われましたが、ことごとく破られてしまうためか、この後テキスト自体を不可視化することはあまり行われなくなります。

これは BASIC の不可視化よりもディスク自体のプロテクトにウェイトが置かれるようになったのと、C コンパイラでの開発が主流になってきたのが原因と思われますが、真相は定かではありません。




ふたつめのアプローチは、コード内にあるメッセージを暗号化することでした。

これは現在でも使用されている方法です。 もちろん当時よりは高度な暗号化技術が使われているので「暗号強度」は比べるまでもありませんが…。


最初に用いられた暗号化は、「シーザー暗号」と呼ばれる、単純に
'IBM' → 'HAL'
'シンブンシ' → 'スアベアス'
という具合にキャラクタコードをずらしただけのものでした。 しかしこれだと、表示されたメッセージと比較する事で簡単に見破られてしまいます。

また、メッセージ全体を暗号化すると、
'ココ ニハ ナニ モ ナイ' → 'スス#ノヘ#ネノ#ヨ#ネオ'
と、単語の区切りに使用する「スペース」が、特定の文字(この場合は '#' )に変換されることから、元のメッセージとの対応が容易に推測されてしまいます。
(この場合は ' '(0x20) '#'(0x23) が ASCII コードでは +3 の違いなので、
<暗号化された文字> - 3 = <元の文字>
という推測が簡単に導けます。)




雑誌投稿や同人系のゲームでは、単純な「シーザー暗号」でも問題はないでしょうが、パッケージで発売されるゲームとなると、もう少し複雑な仕組みでないと「技術力が低い」と馬鹿にされてしまいます。
そこで「シーザー暗号」よりも、もう少し高度な「ビット反転」が使われます。
ビット反転だけだと見破られてしまう可能性があるのですが、暗号化/復号化の両方で同じルーチンが使える利点があります。


Encrypt_sample
メッセージ暗号化ルーチン サンプル(MSX)

これは、友人に頼まれて作った「簡易暗号化ルーチン」の復刻版(!)です。
このままだとリストが見難いので、テキストに直したものを掲載しておきます。
list
10 DEFINT A-Z
20 A$="ここには Shield が おいてあります"
30 FOR I=1 TO LEN(A$)
40  C=ASC(MID$(A$,I,1))
50  IF C>&H85 THEN E=C XOR &H5C ELSE IF C>&H40 THEN E=C XOR &H1F 
    ELSE E=C
60  PRINT CHR$(E);
70 NEXT
Ok
run
ニニコカ Lwvzs{ ハ♣ ノホソヘ、ウチ
Ok


この暗号化の利点は、単純なので CPU パワーを食わないことと、アルファベット/記号部分(0x21 - 0x7f)とひらがな/カタカナ部分(0x86 - 0xfd)の反転させるビットを違うパターンにする事で、解読され難くなっている事です。

欠点としては、
'`' 0x60 → 0x7f 「削除」
'「' 0xa2 → 0xfe 「未定義文字」
'」' 0xa3 → 0xff 「カーソル表示」
' ' 0x90 → 0xcc 'フ'
' ' 0xa0 → 0xfc 'わ'
と変換されるため、BASIC でプログラミングする場合、ルーチンをこのまま使用すると
「バッククォート(0x60)
「山括弧(0xa2 - 0xa3)
'フ'
'わ'
をメッセージ中に使用できなります。
そのため BASIC で上記の文字を表示させるには例外処理を追加する必要があります。

また、例外処理を追加する事で暗号化されたメッセージに「迷彩」が施され、単純なビット反転だけではなくなるので、逆に破られにくくなる利点もあります。




BASIC でゲームを作る時代は瞬く間に過ぎ去り、C やマシン語での開発も汎用ツール(ゲームエンジン/スクリプトエンジン)を使う方式へと代わりました。
今では「暗号化」はエンジンの一機能として存在していますが、ほとんど誰も気に留めることはありません。

コード内のメッセージを見たい VS メッセージを覗かれたくない

たぶん永遠に続くであろう戦いの「始まりの時代」のお話でした。


(参考)
Wikipedia: 単一換字式暗号
Wikipedia: シーザー暗号
Wikipedia: ゲームエンジン
Wikipedia: スクリプトエンジン (ゲーム)

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。