本プラットフォームが提供するゲームセキュリティ保護ソリューションにおいて、CLI版ハードニングツールの利用者は、apkまたはaabファイルがSO単独モードハードニング機能を使用した後、必ずハードニング後のゲームが正常に動作することを検証してください。
元ドキュメント: Single File Guide
使用前の注意事項
- SO単独ハードニングモードは特定のSOファイルのみ暗号化をサポートしており、ホットアップデート等のシナリオに適しています。
- SO単独ハードニングモードの実行時、apk/aabパッケージ単位で行われます。入力・出力ともに完全なapk/aabパッケージですが、ハードニングプロセスでは選択されたSOファイルのみ保護し、他のファイルは変更しません。ゲーム側はハードニング後のapk/aabパッケージからハードニングされた対象ファイルを抽出し、対象ファイルに対してホットアップデートやその他の後続処理を行う必要があります。
ツール説明
CLI版ハードニングツールを使用すると、ハードニングと署名プロセスをCIフローに統合できます。わずか1行のコードでハードニングと署名の自動化を実現できます。
特記事項:
本ツールが対応しているゲームバージョン:Androidゲーム
本ツールが対応しているOS:Windows、macOS、Linux(WindowsおよびLinuxシステムについて、それぞれx86版とx64版のツールを提供していますので、お使いのPCのOS構成を確認してから対応するツールバージョンを選択してください)
本ツール実行時、まずゲームの認証を行います。本プラットフォームは各ゲームにcert形式の証明書を発行します。ダウンロードしたツールパッケージに対応ゲームの証明書がない場合は、カスタマーサービスにお問い合わせください
本ツールは2種類のハードニングを提供します:APKハードニング、App Bundleハードニング
MacおよびLinuxシステムでツールを呼び出す前に、まずツールに権限を付与してください:ツール所在ディレクトリで以下を実行します
xmlcd where_your_mtpclientconsole_dir chmod -R 777 ./*
APKハードニング
呼び出し方法:
cd where_your_mtpclientconsole_dir
MTPClientConsole.exe -d <gameId> <apkpath> <outDir> <certPath> -c <configPath>パラメータ説明:
| パラメータ | 説明 |
|---|---|
| -d | 標準版(デフォルトオプション、変更不可) |
| gameId | ゲームID(コンソール登録) |
| apkPath | ハードニング対象apkファイルの完全パス(パスに非ASCII文字を含めないでください) |
| outDir | ハードニング後apkファイルの出力先完全パス(パスに非ASCII文字を含めないでください) |
| certPath | ゲームIDに対応する証明書パス(証明書名はGame_ID.cert、パスに非ASCII文字を含めないでください) |
| -c | 設定ファイル呼び出し(デフォルトオプション、変更不可) |
| configPath | tpshell-config.xml設定ファイルのパス(パスに非ASCII文字を含めないでください)。設定ファイル内のタグペアは同一行に配置し、ファイル名は.xmlで終わる必要があります |
App Bundleハードニング
App Bundleハードニングモード。Android App BundleはGoogleが最新リリースしたAPKダイナミックパッケージング・ダイナミックコンポーネント化技術で、最終的に.aabで終わるbundleファイルが生成されます。
呼び出し方法:
cd where_your_mtpclientconsole_dir
MTPClientConsole.exe -a <gameId> <aabPath> <outDir> <certPath> -c <configPath>パラメータ説明:
| パラメータ | 説明 |
|---|---|
| -a | AppBundle版(デフォルトオプション、変更不可) |
| gameId | ゲームID(コンソール登録) |
| aabPath | ハードニング対象aabファイルの完全パス(パスに非ASCII文字を含めないでください) |
| outDir | ハードニング後apkファイルの出力先完全パス(パスに非ASCII文字を含めないでください) |
| certPath | ゲームIDに対応する証明書パス(証明書名はGame_ID.cert、パスに非ASCII文字を含めないでください) |
| -c | 設定ファイル呼び出し(デフォルトオプション、変更不可) |
| configPath | tpshell-config.xml設定ファイルのパス(パスに非ASCII文字を含めないでください)。設定ファイル内のタグペアは同一行に配置し、ファイル名は.xmlで終わる必要があります |
tpshell-config.xml設定ファイルの記述例:
<?xml version="1.0" encoding="utf-8"?>
<!-- This configuration only configures basic properties -->
<Config>
<!--Server Tools Version, please use default value and modify it after contacting with customer service-->
<TPVersion>default</TPVersion>
<!--ToolPath: tools location,default ClientConsole/tools or cut this atrribute-->
<ToolPath>your_tool_absolute_path</ToolPath>
<!--TPSvrHost: provite server host if you deploy a private svr. Use official host when not set. -->
<!--TPSvrHost>your_private_svr_host</TPSvrHost-->
<!-- Sign: information of keystore when using local sign-->
<Sign>
<sign-argument name = "keystorePath" value="your_keystore_absolute_path"/>
<sign-argument name = "keypass" value="123456"/>
<sign-argument name = "storepass" value="123456"/>
<sign-argument name = "alianame" value="test"/>
<!-- This config is obsolete -->
<!-- <sign-argument name = "v1SigningEnabled" value="true"/>
<sign-argument name = "v2SigningEnabled" value="false"/>
<sign-argument name = "v3SigningEnabled" value="false"/> -->
</Sign>
<!-- EncSo: so fileName that you want to encrypt, less than 5 files for performance-->
<EncSo>libmono.so</EncSo>
<!-- Encrypt global-metadata requires configuring libil2cpp.so and enable_globalmetadata_enc to true-->
<EncSo>libil2cpp.so</EncSo>
<EncSo>libGameCore.so</EncSo>
<!-- if you want so independent enc,just add: "enc_independent": true to extparams -->
<extparams>{
"enable_globalmetadata_enc" : false,
"enc_independent": true
}
</extparams>
</Config>tpshell-config設定ファイル説明:
| 設定項目 | 説明 |
|---|---|
| TPVersion | 必須項目、ハードニングバージョン番号を指定 |
| ToolPath | CLI版ハードニングツールの実行にはツールパッケージ内のtoolsディレクトリ情報に依存しますので、そのtoolsディレクトリの完全な絶対パスを記入してください(引用符不要) |
| Sign | 任意項目、署名証明書情報。ゲーム開発者が提供します |
| keystorePath | キーストアファイルのパス、文字列型(絶対パスを記入してください) |
| keyPass | キーパスワード、文字列型 |
| storePass | ストアパスワード、文字列型 |
| aliaName | エイリアス、文字列型 |
| EncSo | 暗号化対象.soファイル名リスト。メインのゲームロジック.soのみ選択することをお勧めします。暗号化.so数が多すぎるとゲームパフォーマンスに影響します(引用符不要) |
| enable_globalmetadata_enc | global-metadata.dat暗号化機能の有無。il2cpp.soファイル暗号化と同時でのみ有効。"true"または"false"のみ |
| enc_independent | SO単独ハードニング機能の有無。"true"または"false"のみ |
特記事項:
*TPVersionについて: コマンドラインツール付属のデフォルトバージョンの使用をお勧めします。バージョンの変更が必要な場合は当社までご連絡ください。
*署名について: ローカル署名を使用する場合、証明書および証明書情報のアップロードは不要で、keystorePath、storePass、keyPass、aliaNameの署名情報を記入するだけでOKです。 APKハードニング、App Bundleハードニングともに、署名方式はハードニング前後で同一バージョンを維持し、v1、v2、v3の設定は不要です。署名情報未記入・誤記入、またはハードニング対象パッケージが未署名の場合、デフォルトで署名せず、ハードニング後のゲームは手動署名が必要になります。一般的にaabパッケージはv1署名のみ使用します。
*暗号化ファイルリストについて: EncSoが空リストまたは未記入の場合、デフォルトでlibmono.soファイル、libil2cpp.soファイルなどを暗号化します。
*SO単独ハードニングモードについて: enc_independentフィールドはファイルSO単独ハードニングモードを有効にするための設定で、ハードニングバージョン3.0以上でのみサポートされています。
*global-metadata.dat暗号化について: enable_globalmetadata_encフィールドはglobal-metadata.dat暗号化を有効にするための設定で、同時にil2cpp.soファイルを暗号化する必要があります。デフォルトは無効です。ハードニングバージョン2.6でのみカスタム設定をサポートしています。
*高速アップロードについて: 本バージョンのCLI版ハードニングツールには高速アップロード機能が統合されており、ネットワーク転送内容を精簡し転送速度を向上させています。また、完全パッケージのアップロードは不要です。
一般的な返却結果
| パラメータ | 説明 |
|---|---|
| The shelling task was finished | ハードニングタスク完了 |
| Shell failed for time out | ハードニングタイムアウト失敗 |
| Configuration error | 設定解析エラー |
| Command line parameter error | コマンドラインパラメータエラー |
| Shelling error | シェルエラー |
| Local client error | ローカルクライアントエラー |
| Server error | サーバーエラー |
バッチ処理疑似コード
注意
シェリング処理には多くのIO操作が含まれます。マシンのCPUやネットワーク帯域を考慮し、同時実行プロセス数は10個以下(マシンパフォーマンスに応じて調整)にすることをお勧めします。スレッドプールを使用して大量のインストールパッケージをバッチ処理します。
ディレクトリ構造:

#/usr/local/bin/python3
import os
import sys
import time
import shutil
from contextlib import contextmanager
from multiprocessing import Pool
import subprocess
g_temp_out = os.path.realpath("./multi_out")
g_is_aab_shell = False
@contextmanager
def _cwd(path):
#change workspace into multichannel
saved_dir = os.getcwd()
if path is not None:
os.chdir(path)
try:
yield
finally:
os.chdir(saved_dir)
def get_timestamp():
now = int(round(time.time()*1000))
now = time.strftime('%Y%m%d%H%M%S',time.localtime(now/1000))
return now
def shell_sub_main(apk_absolute_path):
channal_name = get_timestamp() + "_" + os.path.basename(apk_absolute_path).replace(".apk", "")
workspace = os.path.join(g_temp_out, channal_name)
if os.path.isdir(workspace):
shutil.rmtree(workspace)
os.makedirs(workspace)
result = {apk_absolute_path:"None"}
with _cwd(workspace):
'''
here run console command
note:
use Absolute Path in config!!!
'''
#customize your config begin
mtpclient_absolute_path = "MTPClientConsole" # Absolute MTPClientConsole path
shell_type = "-a" if g_is_aab_shell else "-d"
gameid = "12345" #your gameid
output_dir = "./"
cert = "12345.cert" #your cert
config_xml = "tpshell-config.xml" #your tpshell config
#customize your config end
cmd = "%s %s %s %s %s %s -c %s" %(mtpclient_absolute_path,shell_type,gameid,apk_absolute_path,output_dir,cert,config_xml)
pipe = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
print("workace:",workspace)
while True:
line = pipe.stdout.readline()
if not line:
break
line = line.decode("utf-8", "ignore").replace("\r","").replace("\n","")
print(line)
if "The shelling task was finished" in line:
if "apkPath" in line:
output = line.split("apkPath:")[1][:-1]
else:
output = line.split("aabPath:")[1][:-1]
result[apk_absolute_path] = output
return result
def process_result(results):
# You can customize the processing result
for result in results:
print(result)
for k,v in result.items():
if v == "None":
print("input:%s shell FAILED!!!"%(k))
else:
print("input:%s shell ok,output:%s"%(k,v))
return
def shell_main():
inDir = os.path.realpath("./in")
files = os.listdir(inDir)
tasks = []
for fi in files:
path = "%s/%s"%(inDir, fi)
if fi.endswith(".apk"):
tasks.append(path)
pool = Pool(maxtasksperchild=1)
ret = pool.map_async(shell_sub_main, tasks, callback=process_result)
pool.close()
pool.join()
if ret.successful():
print("all over,result:",ret.get())
else:
print("something wrong,please check")
if __name__ == '__main__':
shell_main()