叀いコヌドを再掻性化するか、悪いアプリケヌションに察しお良いこずをする方法

ハブラヌで曞くよりも頻繁にゲヌムをプレむするこずを認めなければなりたせんが、「リズミカルな」ゞャンルには垞に䞀定の匱点がありたした。 か぀お、私はAudiosurfが本圓に奜きでしたが、埌にそれの異なるクロヌン、Beat Hazard、osuに出䌚いたした。 その埌、App StoreでDeemoずDuetに出䌚い、そこからたくさんの楜しい時間を過ごしたした。



終わりのない眠れぬ倜、さたざたな堎所で眠りに぀いた半ば、私は自分の興味の茪の䞀郚である小さなこずに気づきたした。 無料ダりンロヌド、おなじみの䌚瀟、ええ、それはたくさんの有料コンテンツがあるこずを意味したす。 䞀方、圌らはおそらく無料で䜕かをするでしょう。 明らかな結論を出しお、私はゲヌムをダりンロヌドしたした...そしお、凊女の癜い画面を芋たした。



これ以䞊の議論は、コヌドを倱ったり、曎新を蚘録したパブリッシャヌの過倱を匕き起こした感情を揺さぶるものではなく、わずかな絶望の状況で望んでいたものを手に入れるこずに぀いおです。



説明を読んで、時にはそれでもやりがいのあるこずは、2぀のニュヌスをもたらしたした



ゎヌゞャス。 おそらく、プラットフォヌムがx86ではなく、ゲヌムがヒットしないなどの理由で、倚くの人はこの埌撀回するでしょうただし、埌でメカニックが本圓に奜きでしたが。 しかし、私は個人的なin蟱を受け、翌朝、患者を蚺察するこずにしたした。



掻性化



最初のステップは芋るこずですが、モンスタヌは䜕かを蚘録しおいたせんか sshで行っお、 syslogモニタリングを開き、アプリケヌションを実行したす。 すぐに画面が次の圢匏のメッセヌゞでいっぱいになりたす。

  bird [1792] <゚ラヌ>蚭定゚ラヌ<NSError0x15df7ba0BRCloudDocsErrorDomain5-{
     NSDescription = "URLにドキュメントがありたせん";
     NSFilePath = "/ private / var / mobile / Library / Mobile Documents / JZKSZCX743〜com〜square-enix〜tact / oks_savedata.bin";
     NSUnderlyingError = "<NSError0x15df7b60NSPOSIXErrorDomain2-{\ n NSDescription = \"そのようなファむルたたはディレクトリはありたせん\ "; \ n}>";
 }> 


おっず、ブルズアむ。 iOS 9はiCloudのおもちゃを壊し、䜕らかの理由で保存ず蚭定のあるファむルは䜜成されず、起動は無限ルヌプに入りたした。 䜜成しおみたしょう。

  touch "/ private / var / mobile / Library / Mobile Documents / JZKSZCX743〜com〜square-enix〜tact / oks_savedata.bin" 


そしお、これが0_oむンタヌフェヌスです。 萜ち着いた私はストヌリヌに登り、同時にヘッドフォンを぀けたした。 そこに私は芋たただ䜕もない







ファむルが䜕らかの構造を持っおいる必芁があるこずは理解できたす。 ファむル名でさらに怜玢するず、次の2぀の堎所に移動したす。

  find / private / var -name oks_savedata.bin
 /private/var/mobile/Containers/Data/Application/long-uuid/Documents/oks_savedata.bin
 / private / var / mobile / Library / Mobile Documents / JZKSZCX743〜com〜square-enix〜tact / oks_savedata.bin 


しかし、悲しいかな、最初のファむル自䜓は2番目のファむルなしでは䜜成されたせん。 もっず深くする必芁がありたす。



アプリケヌションをダンプし、ipaを解凍したすこれは通垞のzipです。アプリケヌションバンドルの内容を確認したす。



Info.plistのCFBundleExecutableによるず、実行可胜ファむルはoks、2぀のアヌキテクチャを備えたFAT binarです。

  jtool -h OK
ファットバむナリ、ビッグ゚ンディアン、2アヌキテクチャarmv7、armv7s
 -archスむッチでこれらのアヌキテクチャのいずれかを指定するか、ARCH環境倉数を゚クスポヌトしたす 


ほら、アヌムなし64。 たあ、私にずっおこれはある意味でプラスです。iOSずそのチュヌトンの制限、さらにはアヌムの詳现さえ-玹介にもかかわらず、私のトピックではないからです。 私はここでめったに走りたせんが、良い人生からではありたせん。 iCloudの暙準セットのように、資栌を確認したす。

Jtoolの出力
  jtool --ent -arch armv7s oks
譊告コンパニオンファむル./oks.ARM䞍明.69981636-7F33-3C43-BD58-7F5BBE2A6CCAが芋぀かりたせん
 <DOCTYPE plist PUBLIC "-// Apple // DTD PLIST 1.0 // EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version = "1.0">
	 <dict>
		 <key> keychain-access-groups </ key>
		 <配列>
			 <string> JZKSZCX743.com.square-enix.tact </ string>
		 </ array>

		 <key> com.apple.developer.ubiquity-container-identifiers </ key>
		 <配列>
			 <string> JZKSZCX743.com.square-enix.tact </ string>
		 </ array>

		 <key>アプリケヌション識別子</ key>
		 <string> JZKSZCX743.com.square-enix.tacthd </ string>

	 </ dict>
 </ plist> 




すぐに考えが蚪れたしたが、それが必芁かどうか。 ゞェむルブレむク再眲名せずにアプリケヌションを埌でデバむスに配眮するず、iCloudは動䜜しなくなり、動䜜しない堎合はすぐに切断される可胜性がありたす。 同時に、突然動䜜し始めたすか 蚀われた-完了 資栌を指定せずに自己眲名蚌明曞で再眲名  codesign -f -s mycert oks  するず同時に、iTunes経由でバックアップバックアップのためにInfo.plistにUIFileSharingEnabledプロパティを远加しそしお突然䟿利になる、アプリケヌションをipaにパックし、デバむスにむンストヌルしたす。



ご想像のずおり、その埌数分間満足しおプレむしたした。 ラズベリヌがアプリ内賌入によっお残酷にカットされた最初の4぀のレベルを通過する盎前。 [ストア]セクションに移動するず、䟡栌が高いだけでなく、䟡栌も非垞に高いこずがわかりたす。 ロヌンチを修埩したずきにストアを壊したのは、本圓にしたい堎合でも機胜しないからです。 その時たでに、私はすでに元のIPAを削陀しおいたので、ダりンロヌドしたくありたせんでした。 私は思うが、たあたあ、私はすぐにinappsにパッチを適甚し、終わりに察凊したす。



ゞャンブ番号1を修正



Objective-Cクラスのリストを調べ、問題に関連するものを探したす。

クラスリスト
 jtool -dにObjC OKS oksAppDelegate oksExtendView EAGLView oksViewController SeqLogo SeqTitleシヌケンスのSeqmanスプラむトSprMan SndOne SndMan SeqIngame DataoneのDataManのTouchEff TouchOne KEYMAN ChartObj ResultIconOne ResultIcon楜団ChobjEndEffOne ChobjEndEff FadeMan NumberSpr SeqResult MenuStatusポップアップSeqMainMenu SeqStory SptMan SptCharaOne SptChara SptMsgLog SptMsg SptBg SptStill SptCol SptShake SptSnd SeqSelConcert MenuCmnBtn OnpuEffOne OnpuEff SelStoryChap SelStoryLine SeqSelStory StaffData SeqStaffRoll MusicStill SeqMusicメニュヌオプションSeqDownload MyStoreObserverチュヌトリアルFontMan VerificationController Reachability 




名前から刀断するず、 SeqStory 、 SelStoryChap、たたはSeqSelStoryの いずれかになりたす。 そしお、すでに2幎生で、幞運は私たちに埮笑みたす。

ダンプ方法
  jtool -d SelStoryChap -arch armv7s oks
譊告コンパニオンファむル./oks.ARM䞍明.69981636-7F33-3C43-BD58-7F5BBE2A6CCAが芋぀かりたせん
 //ダンプクラス45SelStoryChap
 @interface SelStoryChapCoreFoundation :: _ OBJC_METACLASS _ $ _ NSObject
 //プロパティはありたせん..
 // 11個のむンスタンス倉数
  / * 0 * / unsigned intフラグ。  //私
  / * 1 * / int storyId;  //私
  / * 2 * / int prio;  //私
  / * 3 * / float oriPosx;  // f
  / * 4 * / float oriPosy;  // f
  / * 5 * / float posx;  // f
  / * 6 * / float posy;  // f
  / * 7 * / float plate_w_2;  // f
  / * 8 * / float plate_h_2;  // f
  / * 9 * / sprAry;  // ^ @
  / * 10 * / int sprNum;  //私
 // 25のむンスタンスメ゜ッド
  / * 0 * / 0x38f01-isUnlock;  //プロトコルc8 @ 04
  / * 1 * / 0x38f15-isHave;  //プロトコルc8 @ 04
  / * 2 * / 0x38f29-canPlay;  //プロトコルc8 @ 04
  / * 3 * / 0x38f3d-canSelect;  //プロトコルc8 @ 04
  / * 4 * / 0x38f81-isTouch;  //プロトコルc8 @ 04
  / * 5 * / 0x38fd5-plateTye;  //プロトコルi8 @ 04
  / * 6 * / 0x3900d-isKeyDisp;  //プロトコルc8 @ 04
  / * 7 * / 0x39031-isPlayingDisp;  //プロトコルc8 @ 04
  / * 8 * / 0x39045-isChapTitleDisp;  //プロトコルc8 @ 04
  / * 9 * / 0x39085-アルファ;  //プロトコルf8 @ 04
  / * 10 * / 0x390d9-isDisp;  //プロトコルc8 @ 04
  / * 11 * / 0x39135-クリア;  //プロトコルv8 @ 04
  / * 12 * / 0x391d5-リセット;  //プロトコルv8 @ 04
  / * 13 * / 0x392a5-ロヌド;  //プロトコルv8 @ 04
  / * 14 * / 0x396d1-initWithPrio;  //プロトコル@ 12 @ 04i8
  / * 15 * / 0x39725-dealloc;  //プロトコルv8 @ 04
  / * 16 * / 0x397a1-setStoryId;  //プロトコルv12 @ 04i8
  / * 17 * / 0x39859-updatePos;  //プロトコルv8 @ 04
  / * 18 * / 0x3991d-setOriPosy;  //プロトコルv16 @ 04f8f12
  / * 19 * / 0x3994d-setOfstPosy;  //プロトコルv16 @ 04f8f12
  / * 20 * / 0x3996d-setDisp;  //プロトコルv12 @ 04c8
  / * 21 * / 0x39aa1-startSelEff;  //プロトコルv8 @ 04
  / * 22 * / 0x39c7d-storyId;  //プロトコルi8 @ 04
  / * 23 * / 0x39c8d-posx;  //プロトコルf8 @ 04
  / * 24 * / 0x39c9d-花束;  //プロトコルf8 @ 04
 @end




メンバヌシップメ゜ッドisUnlock / isHaveを優しくヒントそこを芋る必芁がありたす。 私の代わりに有胜な人がFlexパッチを曞くか、 Mobile Cydia Substrateの短いラむブラリを䜜成したす。 しかし、セオの最も䞀般的な䞍十分さずしお、私は入れたせんでした、そしお、私はフレックスを䜿いたせん。 メ゜ッドスりィズル甚の暙準​​APIを䜿甚しお通垞のダむナミックラむブラリを䜜成するこずはできたしたが、それは私には起こりたせんでした。そしお、圹に立たないこずが明らかになりたした。 ファむルをIDAにロヌドし、メ゜ッドに移動しお、内容を構造䜓mov r0、1bx lrに眮き換えたす。

このように


→





デバむスの実行可胜ファむルの倖芳を曎新した埌、isUnlockは「゚ピ゜ヌドがゲヌムで利甚可胜かどうか」であり、「isHave」は賌入ステヌタスであるこずがわかりたした。 以前閉じた゚ピ゜ヌドを開くず、レヌキに乗っおいるこずがわかりたす。





䞭身を確認する必芁がありたす。 armは私にずっお最も銎染みのあるアヌキテクチャではないので、特に機胜が短く、あたり時間をかけたくないので、必芁なくアセンブラコヌドを䜿甚したせん。 コヌドisHave / isUnlockを芋おください 



char __cdecl -[SelStoryChap isHave](struct SelStoryChap *self, SEL a2) { return (self->flag >> 1) & 1; } char __cdecl -[SelStoryChap isUnlock](struct SelStoryChap *self, SEL a2) { return (self->flag >> 2) & 1; }
      
      





ええ、これらのメ゜ッドは既に蚭定されおいる倀のみを読み取りたす。おそらくどこか別の堎所で実際にチェックしたす。 XREF フラグを䜿甚しお、 フラグに曞き蟌むメ゜ッドを芋぀けたす以降、読みやすくするために名前を郚分的に手動で远加したす。

 // SelStoryChap - (void)setStoryId:(int) void __cdecl -[SelStoryChap setStoryId:](struct SelStoryChap *self, SEL a2, int story_id) { self->storyId = story_id; self->flag &= 0xFFFFFF80; if ( checkStoryFlag1(self->storyId) ) self->flag |= 1u; if ( checkStoryFlag2(self->storyId) ) //  isHave self->flag |= 2u; if ( checkStoryFlag4(self->storyId) ) //  isUnlock self->flag |= 4u; ... }
      
      





2番目のビットをチェックする必芁があるこずを知っお、 checkStoryFlag2の内容を芋お、必芁に応じお調敎したす。

もう少し詳现
 int __fastcall checkStoryFlag2(int a1) { return checkStoryStatus(a1, dword_7D84C); } signed int __fastcall inRange(int value, int start, int end) { signed int result; // r0@1 result = 0; if ( start <= value && value <= end ) result = 1; return result; } signed int __cdecl checkStoryStatus(int story_id, int *table) { signed int ret; // r4@1 ret = 0; if ( table ) { ret = 0; if ( inRange(story_id, 0, 63) ) { ret = 0; if ( sub_xxxx(global_entry1, story_id, table, 's') ) { if ( !memcmp(global_entry1, &table[8 * story_id + 6], 0x20u) ) ret = 1; } } } return ret; }
      
      







䜕らかの皮類の倀テヌブルがdword_7D84C 埌でSHA-256ハッシュがあるこずがわかりたしたに栌玍されおおり、珟圚のIDに察しお新しく蚈算されたものがチェックされるようです。 その堎合、章が開きたす。 これはテストを削陀する堎所であり、考えない堎所だず思いたす。 ナニットの無条件埩垰はその仕事を果たし、私はすべおの16章を通過したした:)。



ゞャブ番号2を修正



このストヌリヌは、1぀ではないにしおも完了できたすが、





残りの24トラックはどこにありたすか そうです、圌らは別々に賌入されたす。 ここで私はおもちゃが少し嫌いになり始めたしたが、䜕も、前の手順は簡単すぎたした、䜕か他のものがあるに違いありたせん。 しかし、私は再び幞運でした。 すぐに、setupSelMusicずいう䟿利な名前のメ゜ッドの1぀で、トラックを反埩凊理し、いく぀かの関数を呌び出すコヌドが芋぀かりたしたD

  v3 = 0; memset(self->ctrl_music_idx, 0, 0x200u); v1 = 0; self->music_max = 0; do { if ( sub_36C24(v1) ) self->ctrl_music_idx[v3++] = v1; ++v1; } while ( v1 != 128 ); self->music_max = v3;
      
      





぀たり
  i = 0; memset(self->ctrl_music_idx, 0, 0x200u); track_id = 0; self->music_max = 0; do { if ( trackCheckingFunction(track_id) ) self->ctrl_music_idx[i++] = track_id; ++track_id; } while ( track_id != 128 ); self->music_max = i;
      
      







チェックのコンテキストに基づいお、機胜を4぀の確認のセットずしお解釈したしたトラックは蚱容範囲0〜127にあり、トラックはゲヌムのベヌスに存圚し、トラックは賌入され、少なくずも1぀のレベルがゲヌムで利甚可胜です。

擬䌌コヌド
 signed int __fastcall trackCheckingFunction(int track) { signed int ret; // r5@1 int lvl; // r6@4 char open; // r0@6 ret = 0; if ( inRange(track, 0, 127) ) //   { ret = 0; if ( trackExists2(track) ) //   { ret = 0; if ( checkTrackStatus(track, dword_7D84C) ) //   { lvl = 1; do { ret = 0; if ( lvl > 4 ) break; open = checkTrackPassedLevel(track, lvl++); //   ret = 1; } while ( !open ); } } } return ret; }
      
      





checkTrackStatusに条件なしでナニットを返すように匷制する...困ったこずになりたした。 賌入可胜なトラックはストアに衚瀺されなくなりたしたが、ゲヌムメニュヌにも衚瀺されたせんでした。 ここで、しばらくの間、頭を骚折したした。最初はレベルが䜎すぎお、すべおが解錠しようずしおいるず考えおいたした。 しかし、私の䞭の合理䞻矩者は、少し埌で、各トラックには最倧4぀の難易床モヌドがあり、それぞれが前のトラックに察しお十分に高いマヌクが埗られたずきに開くこずを思い出したした。 ぀たり、この関数のlvl倉数はプレむダヌのポむントずは関係なく、少なくずも1぀の難易床モヌドの「開攟性」を単玔に決定したす。 コヌドのさらなる研究により、これが確認されたした。

もう少し
 BOOL __fastcall isEntryAvailble(int *table, signed int index) { return (table[index >> 5] & (1 << (index & 0x1F))) != 0; } // -    ... signed int __fastcall checkTrackStatus(int track, int *table) { signed int ret; // r4@1 ret = 0; if ( table ) { ret = 0; if ( inRange(track, 0, 127) ) { ret = 0; if ( loadEntryHash(hash, track, table, 'm') ) { if ( !memcmp(hash, &table[8 * track + 522], 0x20u) ) ret = 1; } } } return ret; } BOOL __fastcall checkTrackPassedLevel(int track, int level) { BOOL ret; // r6@1 ret = 0; if ( inRange(track, 0, 127) ) { ret = 0; if ( inRange(level, 1, 4) ) { ret = 0; if ( checkTrackStatus(track, dword_7D84C) ) ret = isEntryAvailble(&track_status_list, level + 4 * track - 1); } } return ret; }
      
      





えヌず、蚺断は䞋されたすが、私たちはどうしたすか checkTrackPassedLevelにパッチを圓おるこずができたすが、パッセヌゞに関係なく、すべおのトラックず難易床モヌドが利甚可胜になりたす。 このオプションは個人的にはあたりにも倱瀌なように思えたので、私の宗教家は初期化子を探すようになりたした。 track_status_listに適切なXREFがなかったので 、私はすでにそのような愛されおいないデバッガヌを䜿いたいず思っおいたした。 最埌の瞬間、私はアむデアを思い぀きたした。特定のテヌブルで生成されたハッシュに至る堎合、そこに䜕かを眮くべきであり、ハッシュがどこにあるかはステヌタスです。 開発者が2぀の異なる関数を䜿甚しおこの投皿の2、3の蚈算からでもコピヌず貌り付けに関するすべおが明らかである、蚈算するこずはほずんどありたせん。XREFloadEntryHashを調べたした。 文字通り数分怜玢した埌、このコンテンツで機胜が芋぀かったず思いたす。



 int *__fastcall sub_xxxx(int track) { int *result; // r0@1 result = inRange(track, 0, 127); if ( result ) { performLoadHashForTrack(track); sub_36EC0(track, 1); result = dword_7D84C; unk_7D860[0] |= 1u; } return result; }
      
      





私の意芋では、名前を倉曎せずに、これがトラックの賌入/通過埌に呌び出される䞀皮のオヌプナヌであるこずは明らかです。 いずれにせよ、これらの小さなものは単にそれに぀いお叫びたした-XREFに関する䞊蚘の[MyStoreObserver complete_sub]は私に同意したした:)技術的な問題おそらく䟿利な堎所にこの関数の呌び出しを挿入するこずは、おそらく初めおアセンブラヌが私にずっお本圓に圹に立ちたした。 checkTrackStatusでトラックのIDを盎接チェックする最も簡単な方法でトリックが行われ、すべおが非垞に良くなりたした。

すなわち


→





結論の代わりに



明らかに、そのような小さな倉曎は、䜕かのふりをするこずはほずんどありたせん。 私は、はるかに厳しい、費甚のかかる状況があるこずを知っおいたす。 はい、たずえばここでも、ロシア語テキストデヌタはUTF-16 LE゚ンコヌドの芋かけ䞊単玔な圢匏で保存され、䞀般にグラフィックデヌタはPNGで保存されたすたたはiTunesラむブラリからの動的な読み蟌みで独自のトラックを远加するこずができたした。 さらに、埌者の堎合、ゲヌムリ゜ヌスにはバむナリ構造だけでなく、それらを受信するための゜ヌスファむルもありたした。

そのようなファむルの䟋
 /****************************************************************************** * wav-file : jupiter.mp3 * midi-file : jupiter.mid * create at 2012/8/17 20:54 ******************************************************************************/ //////////////// ヘッダ情報 //////////////// ST_CHDATA_HEAD s_chdata_head = { "OKCH", // 固定倀"OKCH" 7 , // メゞャヌバヌゞョン倀(匕き継ぎ䞍可曎新) 1 0 , //マむナヌバヌゞョン倀(匕き継ぎ可曎新) 0 294.40034f, // 曲尺 [秒] 625, // オブゞェクト総数154.00015f, // 初期スクロヌルスピヌド[dot / sec] 154.00015f, // 初期BPM [beat / minutes] E_HAKU_2_4, // 初期拍子0, // パディング甚ダミヌ 0, // パディング甚ダミヌ 0, // パディング甚ダミヌ 0, // パディング甚ダミヌ 0, // パディング甚ダミヌ 0, // パディング甚ダミヌ 0, // パディング甚ダミヌ 0, // パディング甚ダミヌ 0, // パディング甚ダミヌ }; //////////////// 本䜓デヌタ //////////////// ST_CHOBJ_HAKU s_chdata_main_0000[] = { {E_CHOBJ_HAKU , 16 , 0.00000f , 0.00000f , E_HAKU_2_4}, }; ST_CHOBJ_BPM s_chdata_main_0001[] = { {E_CHOBJ_BPM , 20 , 0.00000f , 0.00000f , 120.00000f , 500000}, }; 

      
      





それは可胜ですが、それぞれの趣味には時間ず想像力の䞡方に限界があり、私にずっおは数時間を費やしたした。 この蚘事の目的は、モバむルプラットフォヌムを恐れないようにするこずです。モバむルプラットフォヌムには倚くの制限がありたすが、TEXTにバむトを動的に曞き蟌むこずはなく、ビッグブラザヌず違いはありたせん。 他の人のコヌドを掘り䞋げるこずをheしないでください。それほど難しくはなく、時には非垞に刺激的です私のテキストのNFSに関する最近の䞀連の蚘事ずは異なり、これはほずんど感じられたせん。



PS最埌になっおくれおありがずう。

PPS販売終了前にディストリビュヌションを配垃するこずは、法埋䞊の理由から䟡倀がないず思いたす。そしお、なぜ、誰かにずっおこれは実践する絶奜の機䌚です。



免責事項この蚘事では、ラむセンス契玄の違反、ハッキング、たたは゜フトりェアの䞍正䜿甚を䞀切求めおいたせん。 そのテキストは、玔粋に教育および情報提䟛のために提瀺されおいたす。



All Articles