
2026/02/02 6:30
「40年にわたるコピー保護ドングルを打ち破る」
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
著者は、2026年のWindows 98会計事務所で使用されていたSoftware West社の1990年代製RPG IIコンパイラが、並列ポート用ハードウェアコピー保護ドングルを必要としていることを発見しました。
とそのエディタRPGC.EXEは両方ともドングルの有無を確認します。ドングルがない場合、SEUは数秒後に「No dongle, no edit.」というメッセージで終了します。SEU.EXE
アセンブルコードを見ると、セグメント0800内に0x90バイトのルーチンがあり、並列ポートへのIN/OUTを行い、定数値(、ここではBX)を返しています。このルーチンをBH=76h(バイト列MOV BX, 7606h)に書き換えるとドングルチェックが回避され、SEUは即座に終了します。BB 06 76 CB
全てのコンパイラ実行ファイルには同一のコピー保護ロジックが含まれているため、この4バイトのパッチを適用すると、ハードウェアなしでコンパイラがパッチ済み出力バイナリを生成できるようになります。保護は単に定数番号を検証するだけであり、容易に破棄可能です。個人データを削除すれば、このコンパイラは無料の歴史的アーティファクトとして公開されます。
本文
正解です――この小さな装置が、私と最近ソフトウェア考古学の探査で発掘したさらに古いプログラムを動かすために必要だったものです。
少し背景をお話すると、私は最近友人の会計事務所が四十年もの間使ってきた極めてレガシーなソフトウェアパッケージから離れさせる手助けをしていました。そのソフトはRPG(「Report Program Generator」)で作られており、COBOLよりも古く、IBMのミッドレンジコンピュータ――System/3、System/32、そしてAS/400 まで使用されていました。後にMS‑DOSへ移植され、同じツールがパーソナルコンピュータ上で動作できるようになったため、ここまで来ました。
会計事務所は実際には Windows 98 コンピュータ(2026年にも関わらず)を使い、DOS のコンソールウィンドウ内で RPG ソフトウェアを走らせていました。このソフトを動かすためには、コンピュータの並列ポートに特殊なハードウェアコピー保護ドングルを接続する必要がありました――当時は「エンタープライズ」ベンダーが無許可使用から自社製品を守る一般的手法でした。
ドングルのラベルに書かれた文字の大部分は摩耗してしまっているものの、いくつか手掛かりが残っています:
- 「Stamford, CT」の文字
- 会社名「Software Security Inc.」と思しきロゴ(この企業の唯一の証拠は1990年代初頭にSIGGRAPHで展示した記録とソフトウェア保護に関する複数の特許)
- 「RUNTIME」と読める文字
まず最初に取った行動は、Windows 98 PC のディスクイメージを作成し、それをエミュレータ上で実行して実際にソフトが何をしているか確認することでした。ハードウェアドングルはすべての会計ツールで必須で、接続されていないと動きません。
さらにディスクイメージを調査した結果、以下のような手掛かりを発見しました:
- RPG II コンパイラ(素晴らしい!)が Software West Inc. によって作成
- 1990年代に Software West がリリースした RPG II コンパイラの2つのバージョン
- 会計ソフトウェア全体のソースコード(RPG で書かれた複数モジュール)と、DOS バッチファイルがそれらをメニューシステムにまとめている。作者は IBM メインフレームプログラマであり、そのスキルを DOS に持ち込もうとしていたようです。
コンパイラを試してみると、これもハードウェアドングルを必要としていました。何かコードをコンパイルすると、同じコピー保護ロジックが生成された実行ファイルに注入されており――これがドングル上の「RUNTIME」という文字の由来です。
コンパイラは複数の実行可能ファイルから構成され、特に RPGC.EXE(コンパイラ)と SEU.EXE(ソースエディタ)が含まれます。SEU をドングル無しで起動すると、並列ポートへの通信を試みて一時停止し、その後エラーで終了します。このことからプログラムが並列ポートの I/O を試みていることが分かります。
これら古典的な実行ファイルを逆アセンブルするには Reko が非常に便利です。16‑ビットリアルモードコードを理解し、読みやすい C コードへデコンパイルできます。ただし、このケースでは一小さなセグメントのデコンパイルに失敗しました。
逆アセンブリを調べると、0800h と 0809h の2つのセグメントがありました。0809h セグメントには大部分のコードが含まれていましたが、0800h セグメントは IN/OUT 命令で並列ポート経由でコピー保護チェックを行う短いルーチン(約 0x90 バイト)でした。
このルーチンは自己完結型で FAR CALL により呼び出され、RETF で戻ります。機能は次の通りです:
- BIOS データ領域から並列ポートのアドレスを検知し、複数ある場合は LPT1 を使用
- データレジスタに書き込み、ステータスレジスタを読み取り、応答を BH と BL に蓄積
- BX(BH + BL)で結果を返す。入力レジスタやスタック値は読まず、出力は定数です。
この情報をもとにルーチンの先頭4バイトをパッチしました:
BB 34 12 MOV BX,1234h CB RETF
プログラムはまだ「No dongle, no edit」と失敗しますが、これで数秒後ではなく直ちに失敗するようになり、ルーチンが回避されたことを示しています。
さらに調べると BH は常に 0x76 に終わるため、BX は 0x76xx の形になります。DosBox で実行可能ファイルをスクリプト化し BL を 0–255 までブルートフォースして出力を確認した結果、正しい値は 6(=0x06)でした。つまり魔法の数値は 0x7606 です:
BB 06 76 MOV BX,7606h CB RETF
コンパイラスイート内の他の実行ファイルも同じルーチンを持っています。RPGC.EXE がコードをコンパイルするとき、このルーチンが生成されたプログラムにコピーされます。したがって、コンパイラのルーチンをパッチすれば自動的に全ての生成バイナリが修正されるわけです。
このコピー保護メカニズムは驚くほど単純で――ハードウェアドングルが定数値を返し、4 バイトのパッチで回避可能です。Software West Inc. が本当に頑丈に設計したつもりだったのか、それとも単なる見落としだったのかは不明です。
RPG II コンパイラは並列ポートドングル不要になりました。ディレクトリから PII を削除し、他にはオンラインで入手できないこのコンパイラを計算機史のアーカイブとして公開する予定です。Software West Inc. に関わった方がいればぜひご連絡ください――質問がたくさんあります!