Spotify.app をリバース エンジニアリングし、その機能をフックしてデータを取得する方法
プロジェクト
このプロジェクトの目標は、私のリスニング習慣を学習し、通常はスキップするいくつかの曲をスキップできる Spotify クライアントを構築することです。正直、この欲求は私の怠惰から来ていることを認めざるを得ません。何かをしたい気分のときにプレイリストを作成したり検索したりする必要はありません。私が望んでいるのは、ライブラリ内の曲を選択して、他の曲をシャッフルし、キューから「流れない」曲を削除できるようにすることです。
これを達成するには、このタスクを実行できる何らかのモデルを学習する必要があります (これについては、将来の投稿で詳しく説明する可能性があります)。ただし、モデルをトレーニングできるようにするには、まずモデルをトレーニングするためのデータが必要です。
データ
スキップした曲も含め、完全な視聴履歴が必要です。履歴の取得は簡単です。 Spotify API では最後に再生された 50 曲しか取得できませんが、エンドポイントを繰り返しポーリングする cron ジョブを設定できます。完全なコードはここに掲載されています: https://gist.github.com/SamL98/c1200a30cdb19103138308f72de8d198
最も難しい部分はスキップを追跡することです。 Spotify Web API は、このためのエンドポイントを提供しません。以前、Spotify AppleScript API を使用して再生を制御するサービスをいくつか作成しました (この記事の残りの部分では MacOS Spotify クライアントについて説明します)。これらのサービスを使用して、スキップされたコンテンツを追跡することもできますが、それは課題を回避しているように感じます。どうすれば完了できますか?
フック
私は最近、ターゲット バイナリから生成された関数呼び出しを「インターセプト」できるフックというテクニックについて学びました。これがスキップを追跡する最良の方法だと思います。
最も一般的なフック タイプはインターポーズ フックです。このタイプのフックは PLT 内の再配置をオーバーライドしますが、これは実際には何を意味するのでしょうか?
PLT またはプロシージャ リンケージ テーブルを使用すると、メモリ内の関数がどこにあるかを知らなくても、コードで外部関数 (libc を考えてください) を参照できます。PLT 内のエントリを参照するだけです。リンカーは、実行時に PLT 内の各関数またはシンボルに対して「再配置」を実行します。このアプローチの利点の 1 つは、外部関数が別のアドレスにロードされた場合、コード内の関数への各参照ではなく、PLT 内の再配置のみを変更する必要があることです。
したがって、printf の interpose フックを作成するとき、フックしているプロセスが printf を呼び出すたびに、libc の代わりに printf の実装を呼び出します (通常、カスタム ライブラリは標準実装も呼び出します)。
フックに関する基本的な背景知識を理解した後、Spotify にフックを挿入してみる準備が整いました。しかし、最初に何をフックしたいのかを理解する必要があります。
フックの場所
前述したように、外部関数の interpose フックのみ作成できるため、libc または Objective-C ランタイムで関数を探します。
どこにフックするかを調べたとき、Spotify ハンドルの「メディア コントロール キー」または MacBook の F7 ~ F9 からフックを開始するのが良いと考えました。 Spotify アプリで「次へ」ボタンが呼び出されたときに、これらのキーのハンドラーが関数を呼び出すとします。ついに SPMediaKeyTap ライブラリを https://github.com/nevyn/spmediakeytap で見つけました。 Spotify がこのライブラリからコードをコピーして貼り付けるかどうかを試してみようと思いました。 SPMediaKeyTap ライブラリには、startWatchingMediaKeys メソッドがあります。 Spotify バイナリに対して strings コマンドを実行して、このメソッドがあるかどうかを確認しました。そして、案の定、
Bingo!! となりました。 Spotify バイナリを IDA (もちろん無料バージョン) にロードしてこの文字列を検索すると、対応するメソッドが見つかります:
この関数に対応する Lookingソース コードでは、CGEventTapCreate 関数の興味深いパラメータ TapEventCallback が見つかります。
逆アセンブリを振り返ると、sub_10010C230 サブルーチンが次のように渡されていることがわかります。 TapEventCallback パラメータ。この関数のソース コードまたは逆アセンブリを見ると、ライブラリ関数 CGEventTapEnable が 1 つだけ呼び出されていることがわかります。
この関数をフックしてみましょう。
最初に行う必要があるのは、カスタム CGEventTapEnable を定義するライブラリを作成することです。コードは次のとおりです。
#include <corefoundation> #include <dlfcn.h> #include <stdlib.h> #include <stdio.h> void CGEventTapEnable(CFMachPortRef tap, bool enable) { typeof(CGEventTapEnable) *old_tap_enable; printf(“I'm hooked!\n”); old_tap_enable = dlsym(RTLD_NEXT, “CGEventTapEnable”); (*old_tap_enable)(tap, enable); }</stdio.h></stdlib.h></dlfcn.h></corefoundation>
dlsym 関数を呼び出して、実際のライブラリ CGEventTapEnable 関数のアドレスを取得します。次に、誤って何かを壊さないように古い実装を呼び出します。次のようにライブラリをコンパイルしましょう (https://ntvalk.blogspot.com/2013/11/hooking-explained-detouring-library.html):
gcc -fno-common -c <filename>.c gcc -dynamiclib -o <library> <filename>.o</filename></library></filename>
现在,让我们尝试在插入钩子时运行Spotify:DYLD_FORCE_FLAT_NAMESPACE=1 DYLD_INSERT_LIBRARIES=
Spotify打开正常,但Apple的系统完整性保护(SIP)没有让我们加载未签名库:(。
幸运的是,我是Apple的reasonably priced developer项目的成员,所以我可以对库进行代码签名。这个问题算是得到了解决。让我们用100美元证书签名我们的库,运行上一个命令,然后......
失败。这一点不奇怪,Apple不允许你插入使用任何旧标识签名的库,只允许使用签名原始二进制文件时使用的库。看起来我们必须要找到另一种方法来hook Spotify了。
作为补充说明,细心的读者可能会注意到我们hook的函数CGEventTapEnable,只有在media key event超时时才会被调用。因此,即使我们可以插入钩子,我们也可能不会看到任何的输出。本节的主要目的是详细说明我最初的失败(和疏忽),并作为一个学习经验。
HookCase
经过一番挖掘,我发现了一个非常棒的库HookCase:https://github.com/steven-michaud/HookCase。HookCase让我们实现一种比插入钩子( patch hook)更为强大的钩子类型。
通过修改你希望hook的函数触发中断插入Patch hooks。然后,内核可以处理此中断,然后将执行转移到我们的个人代码中。对于那些感兴趣的人,我强烈建议你阅读HookCase文档,因为它更为详细。
Patch hooks不仅允许我们对外部函数的hook调用,而且允许我们hook目标二进制文件内的任何函数(因为它不依赖于PLT)。HookCase为我们提供了一个框架来插入patch和/或interpose hooks,以及内核扩展来处理patch hooks生成的中断,并运行我们的自定义代码。
寻找 sub_100CC2E20
既然我们已经有办法hook Spotify二进制文件中的任何函数了,那么只剩下最后一个问题......就是位置在哪?
让我们重新访问SPMediaKeyTap源码,看看如何处理媒体控制键。在回调函数中,我们可以看到如果按下F7,F8或F9(NX_KEYTYPE_PREVIOUS,NX_KEYTYPE_PLAY等),我们将执行handleAndReleaseMediaKeyEvent选择器:
然后在所述选择器中通知delegate:
让我们看看repo中的这个delegate方法:
事实证明它只是为处理keys设置了一个模板。让我们在IDA中搜索receiveMediaKeyEvent函数,并查看相应函数的图形视图:
看起来非常相似,不是吗?我们可以看到,对每种类型的键都调用了一个公共函数sub_10006FE10,只设置了一个整数参数来区分它们。让我们hook它,看看我们是否可以记录按下的键。
我们可以从反汇编中看到,sub_10006FE10获得了两个参数:1)指向SPTClientAppDelegate单例的playerDelegate属性的指针,以及2)指定发生了什么类型事件的整数(0表示暂停/播放,3表示下一个,4表示上一个)。
看看sub_10006FE10(我不会在这里包含它,但我强烈建议你自己检查一下),我们可以看到它实际上是sub_10006DE40的包装器,其中包含了大部分内容:
哇!这看起来很复杂。让我们试着把它分解一下。
从这个图的结构来看,有一个指向顶部的节点有许多outgoing edges:
正如IDA所建议的那样,这是esi(前面描述的第二个整数参数)上的switch语句。看起来Spotify的处理的不仅仅是Previous,Pause/Play和Next。让我们把关注点集中到处理Next或3 block:
確かに、これを行うには時間がかかりましたが、一番下の 4 行目で r12 を呼び出していることに注意してください。他のケースをいくつか見てみると、レジスタを呼び出す非常によく似たパターンが見つかるでしょう。これは素晴らしい機能のように思えますが、それがどこにあるのかをどうやって知ることができるのでしょうか?
新しいツール、デバッガーを開いてみましょう。最初は Spotify をデバッグしようとして非常に苦労しました。私がデバッガにあまり詳しくないからかもしれませんが、かなり賢い解決策を思いついたと思います。
最初に sub_10006DE40 にフックを設定し、次にコード内でブレークポイントをトリガーします。これは、アセンブリ命令 int 3 を実行することで実行できます (GDB や LLDB などのデバッグなど)。
HookCase フレームワークにおけるフックは次のようになります:
これを HookCase テンプレート ライブラリに追加した後、user_hooks 配列にも追加する必要があります。 :
# 次に、Makefile HookCase が提供するテンプレートを使用してコンパイルします。次に、コマンド HC_INSERT_LIBRARY= /Applications/Spotify.app/Contents/MacOS/Spotify を使用して、ライブラリを Spotify に挿入できます。
次に、LLDB を実行し、次のように実行中の Spotify プロセスにアタッチします。
F9 キーを押してみてください (Spotify がアクティブなウィンドウでない場合は、 iTunes が開く場合があります)。フック内の行 int $3 はデバッガーをトリガーする必要があります。
これで、sub_10006DE40 エントリ ポイントに入ることができます。 PC は IDA に示されているアドレスに対応する場所にあることに注意してください (これはプロセスがメモリにロードされる場所によるものだと思います)。現在のプロセスでは、プッシュ r15 命令は 0x10718ee44 にあります。
IDA では、この命令のアドレスは 0x10006DE44 で、オフセットは 0x7121000 になります。 IDA では、r12 命令が呼び出されるアドレスは 0x10006E234 です。次に、そのアドレスにオフセットを追加し、それに応じてブレークポイントを設定します (b -a 0x10718f234)。続行します。
ターゲット命令にヒットすると、レジスタ r12 の内容を出力できます。
私たちがしなければならないことは、このアドレスからオフセットを減算することだけです。見てください、公称アドレスは 0x100CC2E20 です。
sub_100CC2E20
次に、この関数をフックしましょう:
これを user_hooks 配列に追加し、コンパイル、実行し、観察します。 Spotify アプリで F9 キーを押すか、「次へ」ボタンをクリックするたびに、メッセージが記録されます。
スキップ関数をフックしたので、
残りのコードを投稿しますが、残りのリバース エンジニアリングは完了しません。この記事のせいで この記事はすでに十分に長いです。
つまり、前の関数もフックしました (これに従うと良い練習になります)。次に、両方のサビで、まず現在の曲がすでに半分まで進んでいるかどうかを確認します。もしそうなら、私は何もしていないので、その曲が不適切だと思うのではなく、単にその曲に飽きているだけだと思います。次に、背面 (F7) で最後のスキップをポップします。
現在の曲が途中かどうかを確認する方法について少しお話したいと思います。私の当初のアプローチは、実際に Popen を呼び出して、対応する AppleScript コマンドを実行することでしたが、それは正しくないと感じました。
Spotify バイナリで class-dump を実行したところ、SPAppleScriptObjectModel と SPAppleScriptTrack という 2 つのクラスが見つかりました。これらのメソッドは、再生位置、継続時間、トラック ID に必要なプロパティを公開します。次に、これらのプロパティのゲッターをフックし、next フックと back フックを使用して呼び出しました (Swizzle の方が合理的だと思いますが、機能させることができません)。
ファイルを使用してスキップを追跡します。最初の行にはスキップの数が含まれます。スキップでは、このカウンターをインクリメントし、カウンターで指定された行のファイルに追跡 ID とタイムスタンプを書き込みます。 「戻る」ボタンでは、このカウンターをデクリメントするだけです。このようにして、戻るボタンを押したときに、バックトラックされたファイルに新しいスキップを書き込むようにファイルを設定するだけです。
以上がSpotify.app をリバース エンジニアリングし、その機能をフックしてデータを取得する方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









京東モールAPPで実名認証を取得するにはどうすればよいですか?京東モールは多くの友人がよく利用するオンライン ショッピング プラットフォームですが、充実したサービスを享受し、より良いショッピング体験を得るために、買い物をする前に全員が実名認証を行うことが最善です。以下はJD.comの実名認証方法です。ネチズンの参考になれば幸いです。 1. JD.com をインストールして開き、個人アカウントにログインします。 2. 次に、ページの下部にある [マイ] をクリックして、個人センター ページに入ります。 3. 次に、ページ内の小さな [設定] アイコンをクリックします。右上隅をクリックして設定機能インターフェイスに移動します; 4. [アカウントとセキュリティ] を選択してアカウント設定ページに移動します; 5. 最後に、[実名認証] オプションをクリックして実名情報を入力します; 6. . インストール システムでは、実際の個人情報を入力し、実名認証を完了する必要があります。

Dashen apk を例に挙げます。アプリ復号化 Lua スクリプトの以前の分析を通じて、Dashen apk の Lua スクリプトを復号化できます。次に、そのリソース (設定ファイルや画像など) を復号化しましょう。より重要な設定ファイルを例に挙げると、復号化前: ファイル ヘッダーには署名値「fuckyou!」も含まれています。これを見て、これもxxteaで暗号化されているのではないかと考え、上記の方法でxxteaで復号化してから解凍したところ、やはり文字化けしており、途中でエラーが発生しました。私たちが今言ったことを否定しなければなりません。推測です。設定ファイルの復号化を段階的に続けます。ちょっと考えてみてください。ファイルのヘッダーは次のとおりです。ファイルを復号化したい場合は、必然的に処理が必要になります

SpotifyAIDJ は、ユーザーにパーソナライズされた音楽推奨サービスを提供できる最新の機能です。 Android またはデスクトップで SpotifyAIDJ が見つからない場合は、この記事で問題を解決するためのガイドを参照してください。人工知能テクノロジーを通じて、SpotifyDJ は人間の DJ の音楽選択プロセスをシミュレートし、ユーザーに優れた音楽体験をもたらします。問題のトラブルシューティングを続行する前に、ネットワーク接続が安定していることを確認してください。 WiFi ルーターを再起動して、改善があるかどうかを確認してください。さらに、Spotify サーバーの稼働状況を確認することもできます。最新情報については @SpotifyStatus (Twitter アカウント) をフォローしてください。サーバーに問題がある場合はしばらくお待ちください

Appleの製品とサービスは、常に世界中のユーザーに愛され続けています。香港 Apple ID を登録すると、ユーザーはさらに便利になり、特典が得られます。香港 Apple ID の登録手順と注意点を見てみましょう。香港 Apple ID の登録方法 Apple デバイスを使用する場合、多くのアプリケーションや機能では、Apple ID を使用してログインする必要があります。香港からアプリケーションをダウンロードしたり、香港 AppStore の優待コンテンツを楽しみたい場合は、香港の Apple ID を登録することが非常に必要です。この記事では香港のApple IDの登録手順と注意点を詳しく解説します。手順: 言語と地域を選択します。Apple デバイスで「設定」オプションを見つけて、次のように入力します。

チャイナユニコムアプリはみんなのニーズを簡単に満たします。ニーズを解決するためのさまざまな機能があります。さまざまなサービスを処理したい場合は、ここで簡単に行うことができます。必要がない場合は、ここで時間内に購読を解除できます。携帯電話を利用していると、データ容量が足りないと感じて追加でデータパックを購入したものの、翌月には必要ないのですぐに退会したいという方も多いのではないでしょうか。必要な友達が来て利用できるように、退会方法を提供しています。 China Unicom アプリで、右下隅にある「My」オプションを見つけてクリックします。 「My」インターフェースで「My Services」列をスライドし、「注文しました」オプションをクリックします。

請求書は買い物券として、私たちの日常生活や仕事に欠かせないものです。では、普段買い物に Duodian アプリを使用する場合、Duodian アプリで簡単に請求書を発行するにはどうすればよいでしょうか?以下では、この Web サイトの編集者が、マルチポイント アプリで請求書を開くための詳細なステップバイステップ ガイドを提供します。さらに詳しく知りたいユーザーは、必ずお見逃しなく。テキストに従って詳細を確認してください。 [請求書センター]の[マルチポイントスーパー/フリーショッピング]をクリックし、注文完了ページで請求書が必要な注文を選択し、[次へ]をクリックして[請求書情報]、[受取人情報]を入力し、[クリック]をクリックします。正しいことを確認して送信し、数分後に受信メールボックスに入り、メールを開き、電子請求書のダウンロードアドレスをクリックし、最後に電子請求書をダウンロードして印刷します。

本日の「StreamOn」イベントで、SpotifyはiOSとAndroidアプリに展開する大幅な見直しを披露した。 2 つの最大のコンポーネントには、ホームページ フィード内の音楽、ポッドキャスト、オーディオブックのビデオとオーディオのプレビューと、検索での発見のための新しいビデオ フィードが含まれます。同社は、UIの大規模な刷新を「より深く掘り下げ、アーティストとファンの間のより有意義なつながりを発見するために設計された、新しいダイナミックなモバイルインターフェース」と呼び、これが「当社のこれまでで最大の進歩」であるとしている。 Spotifyは、「次世代のリスナーは、完全に没入する前にオーディオをサンプリングするより良い方法を求めている」ため、「まったく新しいインタラクティブなデザインによる、よりアクティブな体験」を目指していると述べている。

Blackmagic Design は、好評を博した Blackmagic Camera アプリをついに Android に導入しました。プロ仕様のビデオ カメラ アプリは無料でダウンロードでき、完全な手動制御が可能です。これらのコントロールは、プロレベルの cin を簡単に摂取できるようにすることを目的としています。
