ツクールMVのチート(セーブデータの改造)について調べてみる

はいどーもこんばんは、明日の生活すら危ういニートです。
本日はツクールMVのチート(セーブデータの改造)について調べてみようと思いますよ。
対象はローカル環境に保存されているデータです(要はPC版のアプリを対象)。

とりあえずセーブデータを開いてみる

自分のゲームで適当にデータを保存したあと、saveフォルダを覗いてみてください。
その中にあるfile1やらfile2を見ると、おそらくよくわからない英数記号(例えば「N4IgzgnmAuCmC2IBcoD6YCGA3WBRAdhgEYA2sAJstAE4CusANCKvLPrQcWZUjfU6jYBjAPa18cap1IUqdRswBmI6vAzQAliPzTuc/syLroZAMJiJyAAwCA7hvznx0awNhghGAA6wnlpDbMmDh+LkgAjAI41GBa」みたいなの)が延々と続いていると思います。
一見すると「暗号化されているのか?」と思うかも知れませんが、これ実は全く暗号化されていませんw
ではこの謎な文字列は一体何かと言うと、lz-stringというライブラリを使ってただ単に文字列を圧縮しているだけです。
LZString.decompressFromBase64メソッドを使えば元のJSONデータを簡単に得ることができます。
また、当然ですが、復元したデータを再び圧縮することも可能です(興味のある人は自分で調べてください)。

つまりセーブデータが完全に丸見えなので、大事な情報のフラグを保存していたり、エロゲーなんかの体験版フラグをここで管理していたら厄介なことになりますね。また、値からデータの内容を推測して改変されることも十分に考えられます。
具体的に言えば、ゴールド改造やらレベル改変やらはデフォシステムを使っているならすぐできちゃいます。
いやあ困りました。

実際に改変してみて

特に対策をしていない場合、ツクールMV製のゲームは上述の単純な方法でデータの改造ができるようでした。
では対策は何かないのかと言えば、セーブデータを暗号化するか、データの改変を実行時にチェックすると、一般的なチート行為を防ぐくらいには十分じゃないかなーと思いました(それでも突破してくる人はしょうがない)。

「そんなの一体どうやればいいんだよお」ということですが、そこで前回の記事で紹介したTsumioErrorChecker.jsを使ってみましょう。
このプラグインはデータの改変を実行時に(つまりセーブデータのロード時に)チェックします。
https://raw.githubusercontent.com/Tsumio/rmmv-plugins/master/plugins/TsumioErrorChecker.js
実際、このプラグインを導入してから、例えばJSONデータをいじって「ゴールドを999999に増やした」というやり方のデータの改変をした場合、ゲーム実行時(セーブデータロード時)が改竄されていることを検出し、dupファイルの方を読み込みました。
これはすなわち、今までごく単純な方法でできていた不正行為が不可になっていることを意味します。

注*TsumioErrorChecker.jsが内部で何をやっているのかと言えば、JSONファイルにハッシュ値を埋め込んでいるだけです。このハッシュ値と、実際にゲームでロードしたセーブデータから生成できるハッシュ値をかなり簡単にですが比較して、データが改竄されていないことを確認しています。

とは言えこれも、やり方さえ知っていればサクサクと「データの改竄はなかった」こととしてデータを読み込むことができてしまいます。
まあTsumioErrorChecker.jsを利用しているということを知らなければ、その改竄が割とめんどくさいのでやる人は少なそうですが。

その他の対策

その他の対策としてぱっと思いついたのは以下のような方法でしょうか。

1.lz-string以外で圧縮・解凍する
2.セーブデータを暗号化する
3.データの改変をロード時にチェックする(TsumioErrorChecker.jsはこれ)

とりあえず3だけでチートに対してはある程度は効果があるかなと思いますが、データの中身が見放題という事実はいかんともしがたいです。
というわけでまず1ですが、これは「ツクールMVはlz-strinを使っているはずだから、lz-strinを使って解凍すればいいや」という層を弾くことが可能になります。
実際、この方法を使えば、よく見かける改造サイトは使えなくなるような気がしますね(試してませんが)。
まあ実装が面倒そうな上に根本的な対策ではないので、これはしなくてもいいんじゃないでしょーか。

お次は2ですが、有名なのはEnigma Virtualboxを使った暗号化でしょうか。
ただ僕はEnigma Virtualboxを使ったことがないので、生成されたセーブデータも一緒に暗号化してくれるのかどうかまでは知りませんw

そして2の別解ですが、セーブデータ生成時に暗号化をほどこす方法です。
これはプラグインを導入するという性質上、暗号化を解除する方法も一緒に書かないといけないわけでして、「このプラグインを使っているなら、この方法で復号化できる」という知識がある人に対しては無効です。
逆にどのように暗号化しているかということに気が付かれなければ、それなりに有効なんじゃないでしょーか。
というわけでTsumioErrorChecker.jsにこの暗号化の機能を入れました。

暗号化について

TsumioErrorChecker.jsのプラグインパラメーターの暗号化フラグにチェックを入れると、セーブデータ保存時にデータを暗号化するようになります。
また、プラグインパラメーターで復号化時(正確には暗号化時にもですが)に使うキーを設定できます。
キーは基本的にはなんでもいいのですが、デフォルトのものからは変えた方がいいかなと思います(バージョンアップのときに復号化キーを変えると、以前のデータを読み込めなくなります)。

さて暗号化すると一体どうなるのでしょうか?
暗号化していない状態では簡単にJSONファイルを復元できましたが(ツクールMVのデフォルトのシステムを利用しているなら、どれでも同じやり方でJSONファイルを復元できたことを思い出してください)、暗号化していると少なくとも同じやり方ではダメで、復元のためのキーを探さし(現状の仕様だとすぐ見つかるんですけどねこれw もう少しうまいやり方を探したい)、データを保存するたびに(つまり暗号化されるたびに)自分でデータを復元しなければなりません。
また、復号化をすり抜け、JSONファイルに戻したとしても、ハッシュ値で改竄チェックが入ります(当たり前ですが、ハッシュ値はセーブデータを保存するたびに変わる)。

というわけで、不正のためのチェックが何度も入るので、データをいじって何かしら不正行為をやってやるぞー! という人にとってはかなり面倒なシステムと言えるんじゃないかなーと思います。

終わりに

いかがでしたでしょーか。
セキュリティのことをちまちま勉強している最中なので、こうやって少しずつアウトプットしていきたいと思いますよ。

なお今回の不正対策はあくまでも「セーブデータの改変」に対するもので、ゲーム実行時に直接メモリをいじられた場合は全くお話になりません。
全然やり方がわかりませんが、その辺の対策もそのうち少しは考えてみたいですねえ。

追記:メモリ改竄チートを予防するプラグインも作りました。

ほなそんな感じでまた。

フォローする