2016年2月21日日曜日

白猫のパケット

ソースの見方

必要な物:
java
jad → jd-gui
ILspy
adb
tcpdump → fiddler4

ロリポップ!レンタルサーバ

手順:

adbとtcpdunmでパケットのログを取って
パラメータに何が必要かなどを調べて、javaとC#の中を探す
 javaは、jarコマンドでapkを展開、jadで、javaを復元して見る。
 C#は、jarコマンドで展開されたフォルダ内の、assetsフォルダ内のdllをILspyで見る。
(ソースをいきなりみても追うのが大変だから先にパケットを見るという順番)

---------

初回起動時(リクエストのみ)
/ajax/regist/create
(この応答まではSO中のカギで読めると思う。この後は差し替えてから読む)


起動時のパケット概要(リクエストのみ)

registチェック
デフォルト装備
バージョン
世界のリスト
エリアリスト
loginbonus
再びバージョン
クエストリスト


クエスト開始~討伐完了までのパケット概要(リクエストのみ)

バージョン
クエストジェネレータ
再びバージョン
クエストコンプリート

ロリポップ!レンタルサーバ


パラメータに連結されていく文字列がわかればクエストはパケ投げクリアできるのかな。
ソースの見当は、 NetworkManagerでキーの名前持ってるのでこの辺りを読めばよさそうです。違うかな。
パケ投げでクリアするときは即クリじゃなくて、手動と同じ速度にしたほうが無難かもしれません。
あと、念のため白猫が更新されるたびにパケット解析したほうがいいです。


あ。でも、パケ投げする方法は反対です。


マクロ中からパケットを見て何かの判定として使うならいいけど
パケット投げるのってあるいみ攻撃なので本当やめたほうがいいです。


追記:
バージョンをキックしてるのはクッキーのチェックぽいのかな。

クッキーは、ゲームのキャシュ消しても変わらなかったから
おそらく固有の値ぽく、これは変更不可能なのかもしれない。
でも、ライフサイクルどうなってるんだろ。


あと、クエスト開始~コンプリートまで
初回のクエストジェネレータキックからコンプリートキックまでの間
ローカルやりたい放題に見えた。
箱開け、敵全滅やりたいほうだいやって、コンプリートキックとか。

ここで輝くハイジャック(・ω・)

ロリポップ!レンタルサーバ


追記:3月31日

ILSPYでNetworkManagerを見ると、IEnumeratorのメソッドがたくさんあり
見たことがなかったので少ししらべてみたところIteratorパターンでいうところの反復子にあたる部分だということがわかりました。
集合体にあたるのがEnumerableです。

ILSPYでの表示をilに切り替えると、NetworkManagerにあるIteratorが何かわかります。
Request_ImplとRequestCoroutineのMoveNextで、DecryptとEncryptしてます。
(うーん、Enumerableはイテレータってだけじゃなさそう。startで呼ばれてるから・・タスクとかスレッド?かな?httpのやりとりを貯めてって、必要がある時にmovenextで順に使ってく感じかもしれない。)
さらにたどっていくと、 RijndaelManagedが使われていることがわかりました。

余談ですが、ilのcallとcallvirtの違いは、インタフェースを実装したメソッドを呼ぶときcallvirtになるみたい
callのほうが最適化が積極的にされてるらしく、できるだけilがcallになるようなコーディングが好ましいっぽくどっかにかいてあった。とはいえC#の話であってUnityの事じゃないです。

あと、httpリクエストは一般的にはキックすると生で提供してはこず、こちらからのリクエストヘッダーを見て、対応できる形式で圧縮した状態でレスを返してきます。
なので、いちおうソース中でさがしてみましたZlibが使われてるようでした。

何を使ってるかわかったので、APIをみて使い方を調べて見ます。
サーバー立てるまでもなく、経由させればOKかも。

ここまでのまとめ。

パケットを見て、ヒントを得る。今回のヒントはトークンキーの名前。
ソース中をグレップして位置を特定。今回はNetworkManager。
何をしてるか見て、何を使うか決める。今回はRijndaelManaged、Zlib。
APIを見て使い方を調べて、必要な値をソース中から探す。

ロリポップ!レンタルサーバ



追記:4月4日

RijndaelManagedのAPIを見るとIVKEYが必要であることがわかりました。
ソース中を探すと、その2つがSOの中にあることがわかったので
IDA」のフリー版を落としてきて開いてみると、こんな感じで呼び出していたラベルがあるので


それ以降に記述してあるアセンブラを読むと戻り値がわかると思います。
アセンブラと聞くと腰が引けるかもしれませんがニーモニックは超簡単です。
慣れれば簡単な処理ならマシン語のままでも読めちゃいます。


現状、インストールしてあるものは
7-zip、IDA、VS、ILSpy、java、adb
あと、なんちゃってプロクシ(fidder4は使ってなくって、C#のなんちゃってプロクシを使ってます)

見たものはパケット(httpヘッダー、ボディ)→トークンキーの名前を発見
C#とILをトークンキーでグレップ→通信するためのクラスを発見
C#とILを読む→何を用いてるか発見
用いる物のAPIをチェック→KEYとIVが必要な事を発見
ILを読む→SOをキックしてることを発見
SOをIDAで開いてニーモニックを確認 ^-^ 
読まなくても、SOのラベルわかってるからキックすればいいのかもしれない。

気になるのは変数に入ってなければSOの値を使うぽくなってる。なんだろう。
(追記:インストールしたてで起動したときのパケットでカギがさし変わる仕組みらしい)
プロクシモドキのソースに手を加えて試してみます。
C#で作ってあるので、復元したソースのメソッドコピペで流用できちゃうのがいい感じ。dllも使える。

一般人にとってVSは本当に心強い味方(・ω・)
ま、きっと何やってるかわかればエクセルでもできちゃうんでしょう。

自分で自分のセッションハイジャックまであと少しかも・・?
(あ、パケ投げは攻撃だから駄目ですよ!あくまでも見るだけですよ!)

ロリポップ!レンタルサーバ

追記:4月7日
SO中の16進をUTF8にした文字列でググルと
「新規」か「機種変更」のときのパケットで初回の鍵がユーザ固有の鍵にさしかわるって書いてありました。



代表的なアーキやパターンを知ってればC#のソースを見て内部的に呼ばれる関数なども読み取れるのかもしれませんね。
あまり大きいソースを見たことが無かったのでいろいろ勉強になりました。



パケット復元の仕方のまとめ

C#で作る場合、apk中のzlibとjsonのdllを参照したプロジェクトを作成して
プロクシモドキを作って経由させてあげればOKぽいです。
レスポンスはdll中の関数をキックするメソッドで解凍できました。コピペメソッドです。
・・・ゲームソース中のメソッドを丸ごとコピペして使います
(必要そうなのは複合・暗号・圧縮・解凍あたり)
コピペコピペコピペ(・ω・)
ポストを見たい場合はunscapeしないとデコードできないので気を付けてね。
json中の\uで始まる16進むはUTF-16で復元できます。

SO中のカギで読めるレスポンスの中のjsonに差し替えのカギが入ってるので
まず、レスポンス中でcharset=UTF-8のパケットをデコードしてテキストに出力して読みます。
で、json中から新しいカギを見つけて、差し替えてから後々のパケットが読めるようになります。
(uhってuser hashの略かな?だとするとユーザ単位ってのはありえますね)

ロリポップ!レンタルサーバ


次は
復元した受信のパケットを、いじってクライアントに読み込ませてみます。

試したい事は
敵とか木箱とか宝を増やしたり減らしたりできるかどうか。
敵のレベルとか下げれるとクリア簡単になるかな?
まずはパラメータの調査からですねl。

0 件のコメント:

コメントを投稿