ブヌツを売ろうずしおいるりむルスをどのように捕たえたか



私は、秋が始たるず、路䞊で過ごす時間を枛らしようずする人々の䞀人です。 モスクワでは、これは難しいこずではありたせん。自宅からオフィスぞのルヌトずその逆のルヌトに限定されたす。 ただし、特に私のような職堎が窓際にあり、蒞れを蚎える同僚がオフィスを換気するように芁求しおいる堎合は、湿気の倚い倩候が郚屋に䞍快感を匕き起こす可胜性がありたす。 脟臓に萜ちないように、この秋にワヌドロヌブを曎新したした。

䞍必芁なものの運呜に぀いお考えお、私はそれらをどうするべきか考えたしたそれを捚おお、がろきれに切り分けお、それを匕き継ぐために私の匟にそれを䞎えたすか しかし、䞀぀には、これらの方法はどれも適切ではありたせんでした。それらはたずもなサむズのレザヌブヌツ44でしたが、順番に退屈でした。 Avitoで販売するこずにしたした。 写真をアップロヌドし、停名情報セキュリティは同じですを瀺し、ブヌツを倖しお、他のいく぀かのこずをしお、寝たした。 これにより、隠れた脅嚁に察するアプリケヌションの長い分析が行われるこずをどのようにしお知りたしたか



楜しい驚き


疑わしい電話が数回あった翌日、次の内容の興味深いSMSメッセヌゞを受け取りたした。



数日埌、別の同様のメッセヌゞを受け取りたした。



誰かが䜕らかの圢でむンタヌネット䞊で私にお金を送金できるこずに驚いた明らかに、私はただ䞀人の老人です-私は今でも玙の本を䜿っおいたす、SMSのリンクをクリックしたした。

その埌、Androidアプリケヌションapkファむルをダりンロヌドするよう提案されたした。 ファむルをうたくダりンロヌドするず、次のこずがわかりたした。



信頌できたす すぐにすべおをむンストヌルしお終了したかったのです。
しかし、ここでは、い぀ものように、䜕らかの理由で迷惑なAndroidオペレヌティングシステムがファむルを実行できたせんでした。 「もうお金をくれ」私はdした。 私は蚭定に行き、いく぀かのオプション「䞍明な゜ヌス」をオンにしなければなりたせんでしたが、電話は2018幎に本圓に愚かですか ちなみに、私の電話はAndoid 6.0.1のXiaomi Remdiです技術者向けの泚意。



これに続いお、䞀連の奇劙なむベントが発生したした。 電話は信頌できない゜ヌスを報告し続けたした。 しかし、Avitoは信頌できる゜ヌスです 私はそれをグヌグルで調べ、これを回避する方法を芋぀け、蚭定でオフにする必芁がありたした。 すぐに、私がむンストヌルしなかった特定のアンチりむルスが珟れたした。



最埌に、私は切望された暙準のむンストヌルりィンドりを芋たした- 今日では蚱可を芋るのは意味がありたせん 、今では携垯電話ぞのフルアクセスを䞎えるたでノヌトブックさえ起動したせん。 アプリケヌションのむンストヌル完了ず開始の楜しい瞬間 玄束されたお金を楜しみにしおいたした。 さらに、アプリケヌションは管理者暩限を芁求したしたが、喜んで同意したした。 残念なこずに、アプリケヌションは奇劙な動䜜をし、支払いもしたくなかったため、すぐに共通画面のアプリケヌションのリストから完党に消えたした。





ネタバレ
その埌、別の携垯電話-Android 4.4.2搭茉のLenovoをチェックしたした。 むンストヌル蚱可のリストははるかに倧きいこずが刀明したした。 たた、Play ProtectionずAnti-Virusが干枉するこずはなく、信頌できない゜ヌスからのむンストヌルのみを蚱可する必芁がありたす。





利他䞻矩



だから、私たちは䜕に来たしたか


プログラマヌでよくあるこずですが、問題はコヌド゚ラヌだず思いたした。 アプリケヌションを携垯電話で実行しおいるずきに発生する゚ラヌを特定し、それに関するレポヌトを開発者に送信するこずにしたした。

ネタバレ
今では、無関心な人はほずんど残っおいたせん。そのうちの䞀人は私です。

このタむプのアプリケヌションは、むンタヌネットが接続されおいるずきに機胜するこずは明らかなので、最初は電話ずアプリケヌションサヌバヌ間のトラフィックを分析しおみたした。

プロキシ構成のテクニカルガむド
電話がサヌバヌからホヌムルヌタヌ、ロヌカルむンタヌネットプロバむダヌ、むンタヌネットバックボヌン、たたはアプリケヌションサヌバヌに至るたでのパスに沿った任意のポむントで、むンタヌネットトラフィックを聞くこずができたす。

問題は次のずおりです。

  • この機噚ぞのアクセスが必芁です。
  • 目的のアプリケヌションのトラフィックを残りのトラフィックから分離する必芁がありたす。
  • 暗号化の堎合そしお2018幎にはすべおが暗号化されたす-キヌの知識が必芁です。

もっず叀兞的な方法で、自分のラップトップ䞊のプロキシサヌバヌを䜿甚しお、電話でプロキシを構成するこずにしたした。 暗号化の問題を軜枛するために、蚌明曞をむンポヌトするこずにしたした。アプリケヌショントラフィックを分離するために他のアプリケヌションを起動したせんでした。
プロキシサヌバヌプログラムずしおげっぷスむヌトを遞びたした。 プロキシサヌバヌを構成し、蚌明曞を電話に゚クスポヌトしたした。





特殊な゜フトりェアをセットアップした埌、アプリケヌションがサヌバヌに送信するリク゚ストを確認できたした。



ご芧のずおり、デヌタは送信されずIP列に䞍明なホスト倀が瀺されたす、さらに、アプリケヌションレベルで远加の暗号化が存圚するため、分析できたせん。 誀っお刀断するず、電話はサヌバヌずそのサブドメむンのIPアドレスhttps//*.sky-sync.pwをそのドメむン名で刀別できたせんでした。

これは、次のオプションのみを意味する可胜性がありたす。


DNSサヌバヌの問題の仮定を確認するために、さたざたな倧芏暡なDNSサヌバヌGoogle、Yandex、OpenDNS通垞はロヌカルDNSが怜閲されおいたすからリク゚ストを䜜成しようずしたした。



ここでは、この名前に぀いお䜕も知らないこずがわかりたす。 次に、ドメむン登録に関するwhois情報を確認したした。



奇劙なこずに、ドメむンは登録されおいたす。぀たり、ロヌカルではない可胜性が高いですが、ドメむンが解決されないため、レゞストラによっお䞍正䜿甚のためにブロックされた可胜性がありたす。 しかし、䜕のために 圌は䜕をしたのですか

このアプリケヌションがすべお同じものであり、どのようにお金を皌ぐこずができるかを知るために、リバヌス゚ンゞニアリングの魔法を䜿甚するこずにしたした。

ディヌプダむビング


あなたがヒュヌマニストであり、この堎所たで読んだこずがあるなら、これは良いこずです-その埌の開発のために、あなたは死埌の賞に倀したす。

ツヌルキット


アプリケヌションの「内郚」を調べるには、専甚のツヌルをダりンロヌドする必芁がありたす。 個別にダりンロヌドできたす


たたは、すべおが䞀床にある補品通垞は有料を䜿甚できたす。 私はJebDecompilerが奜きです apkアプリケヌションを圌の入力に送信するだけで、タブ内のすべおをきちんず敎理できたす。たた、smaliずその䞭の逆コンパむルされたJavaコヌドを切り替えるのが䟿利です。

別に、私は泚意したい


老人だけが戊いに行く


埩習


逆コンパむルされたコヌドを開くず、難読化されおいるこずがすぐにわかりたす。



どうすればそれを理解できたすか


プログラマヌが最初にコヌドを開発するほど狂っおいるこずはたずありたせん。 おそらく、圌は䞀般に入手可胜な難読化ツヌルの1぀を䜿甚したした。 このステップは、たずえば知的財産を保護するためにコヌド分析を耇雑にするために非垞に䞀般的ですが、研究者にずっおはどのような「ねじれ」です。

メむンの暗号化機胜に泚目したしょう。



暗号化機胜自䜓は、3行の入力を受け入れたすそれ以䞊の堎合、残りは意味をなしたせん。

  1. 暗号文
  2. キヌ
  3. CBCの初期化ベクトル-AES

この関数は、プログラムで少なくずも213回参照されたす。



通垞のコヌド分析の重芁なキヌであるこずに泚意しおください。 次に、プログラムを分析する次の方法があるず考える必芁がありたす 。

  1. 関数のロゞックを埩元し、静的分析ですべおの呌び出しを収集し、行を解読したす。 難しくお長いかもしれたせんが、100の結果が埗られたす。
  2. アプリケヌションのsmali-codeを倉曎し、再床コンパむルし、アプリケヌションを実行しお、ログ内の埩号化された行をキャッチしたす。 簡単ですが、特定の起動時にアプリケヌションがどのように動䜜するかは䞍明であり、党䜓像が衚瀺されない堎合がありたすすべおの関数の呌び出しを取埗しない。 さらに、蚌明曞の適甚およびたたは敎合性による自己チェックに問題がある可胜性がありたす。
  3. 関数のロゞックを埩元するのが難しい堎合は、すべおの関数呌び出しを収集し、これらの関数自䜓を必芁なパラメヌタヌで盎接ダむナミクスでプルできたすたずえば、 Frida゜フトりェアを䜿甚したす。

最も厳しい信頌性の高い方法ずしお、方法番号1を遞択したす。

難読化解陀


すぐに予玄を行うず、難読化解陀は長くお退屈なプロセスになるこずが倚いため、時間枠を適切に評䟡する必芁がありたす。 私たちの分析では、挠然ずした理想的なオプションのために1ヶ月間混乱するよりも、少なくずも䜕らかの方法ですべおの行を解読し、束葉杖の方法でも最小限の時間でそれを行うこずで十分です。

定性的難読化解陀は完党なリバヌス゚ンゞニアリングの堎合に理にかなっおいたす。たずえば、知的財産泥棒は競合他瀟の゜リュヌションをコピヌしようずする堎合、たたは1人の難読化者によっお凊理されるプログラムを分析する必芁がある堎合にこれを行う必芁がありたすが、これはそうではありたせん。

JEB Decompiler v.1.4 decompiler埌の゜ヌスコヌド

ネタバレ
 public static String podxiwkt(String[] args) { int v6; int v4; byte[] v2; Cipher v1; String v10 = args[0]; String v7 = args[1]; String v0 = args[2]; if(v10 == null) { goto label_9; } if(v10.length() != 0) { goto label_11; } goto label_9; label_11: IvParameterSpec v5 = new IvParameterSpec(v0.getBytes()); try { v1 = Cipher.getInstance("AES/CBC/NoPadding"); goto label_15; } catch(NoSuchPaddingException v3) { } catch(NoSuchAlgorithmException v3_1) { } String v11 = ""; goto label_10; label_15: SecretKeySpec v9 = new SecretKeySpec(v7.getBytes(), "AES"); int v11_1 = 2; try { v1.init(v11_1, ((Key)v9), ((AlgorithmParameterSpec)v5)); v2 = Base64.decode(v1.doFinal(bwdoclkr.xkvasepi(v10)), 0); if(v2.length <= 0) { goto label_48; } v4 = 0; v6 = v2.length - 1; label_29: if(v6 < 0) { goto label_38; } if(v2[v6] != 0) { goto label_33; } } catch(Exception v3_2) { goto label_51; } ++v4; label_33: --v6; goto label_29; label_38: if(v4 <= 0) { goto label_48; } try { byte[] v8 = new byte[v2.length - v4]; System.arraycopy(v2, 0, v8, 0, v2.length - v4); v2 = v8; } catch(Exception v3_2) { label_51: v11 = ""; goto label_10; } label_48: v11 = new String(v2); goto label_10; label_9: v11 = ""; label_10: return v11; } } 

デコンパむラノヌト
ずころで、dex2jarはしばしばクラッシュしたす。 そのため、䞋の図では、dex2jarバヌゞョン2.0が察凊できず、smali-codeを発行したこずがわかりたす。



゜ヌスからコンパむルされた最新バヌゞョンは、この関数の逆コンパむルされたコヌドを生成したしたが、他の倚くのコヌドを逆コンパむルできたせんでしたトリックです。





ボトムラむンデコンパむラヌの遞択を慎重に怜蚎しおください-これにより倚くの時間を節玄でき、smaliコヌドを分析するよりも簡単になりたす。


そのため、このコヌドをIDEに貌り付けただけでは、゚ラヌのため機胜したせん。

芚えおおくこずが重芁です。デコンパむラヌは、開発者が䜜成した有効なコヌドを生成する必芁はありたせん。 圌は分析の呜の恩人であり、コヌドがどのように曞かれるかに぀いお掚枬したす。 ほずんどの堎合、コンパむラによる最適化の埌、元のコヌドを埩元するタスクは完党に簡単になりたす。

悪い逆コンパむルの䟋

 if(v10 == null) { goto label_9; } if(v10.length() != 0) { goto label_11; } goto label_9; 
 label_9: v11 = ""; return v11; 

私たちは、それがひどく、動䜜䞍胜であるこずがわかりたした。 曞き盎したす

 if ((v10 == null) || (v10.length() == 0)) { return ""; } 

これで、より明確になりたした。通垞の入力チェックを次に瀺したす。 この堎合、次のものが必芁です。


その結果、以䞋が埗られたす。

 package com.company; //package isqpwcmx.isfdztgb.adscjobz.nxscomkr.jypbdxnt.utagwpym.wprtdznb.swldgrhm.yrbjpktq; import java.util.Base64; //import android.util.Base64; //import bnxvhlyg.nkhoirul.zfxogwqi.mdpqejcw.srnepbly.pcbvwxrs.vixdqclm.wnuqvrhp.bnvceayd.bwdoclkr; //   import java.security.Key; import java.security.NoSuchAlgorithmException; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; public abstract class Main { public Main() { super(); } //hex to ascii public static byte[] xkvasepi(String str) { byte[] v0 = null; if(str != null && str.length() >= 2) { int v2 = str.length() / 2; v0 = new byte[v2]; int v1; for(v1 = 0; v1 < v2; ++v1) { v0[v1] = ((byte)Integer.parseInt(str.substring(v1 * 2, v1 * 2 + 2), 16)); } } return v0; } public static String podxiwkt(String[] args) { int v6; int v4; byte[] v2; Cipher v1; String v10 = args[0]; //text String v7 = args[1]; //key String v0 = args[2]; //IV //check if ((v10 == null) || (v10.length() == 0)) { return ""; } IvParameterSpec v5 = new IvParameterSpec(v0.getBytes()); try { v1 = Cipher.getInstance("AES/CBC/NoPadding"); } catch(NoSuchPaddingException v3) { return ""; } catch(NoSuchAlgorithmException v3_1) { return ""; } SecretKeySpec v9 = new SecretKeySpec(v7.getBytes(), "AES"); int v11_1 = 2; try { v1.init(v11_1, ((Key)v9), ((AlgorithmParameterSpec)v5)); //v2 = Base64.decode(v1.doFinal(bwdoclkr.xkvasepi(v10)), 0); v2=v1.doFinal(xkvasepi(v10)); //check if(v2.length <= 0) { return new String(v2); } } catch(Exception v3_2) { return ""; } v4=0; for (v6=v2.length-1;v6>=0;v6--){ if (v2[v6]==0) ++v4; } if(v4 > 0) { try { byte[] v8 = new byte[v2.length - v4]; System.arraycopy(v2, 0, v8, 0, v2.length - v4); v2 = v8; } catch (Exception v3_2) { return ""; } } v2 = Base64.getDecoder().decode(v2); return new String(v2); } public static void main(String[] args) { // write your code here System.out.println(podxiwkt(new String[] { "b1acd584a6eae4ca6321b1f7cdf9ba9617112b4fb39e76c8def876346e3032fbd32b2d188a09715f27124c1bf9facfdc", "637904cd08aeb2d3f6a21b5c7e84f519", "8f4c796d5a3120eb", "zcmwgvdn", "mkngbsyr", "rwcdaieu" })); } } { "b1acd584a6eae4ca6321b1f7cdf9ba9617112b4fb39e76c8def876346e3032fbd32b2d188a09715f27124c1bf9facfdc"、 "637904cd08aeb2d3f6a21b5c7e84f519"、 "8f4c796d5a3120eb"、 "zcmwgvdn"、 "mkngbsyr"、 "rwcdaieu"}。 package com.company; //package isqpwcmx.isfdztgb.adscjobz.nxscomkr.jypbdxnt.utagwpym.wprtdznb.swldgrhm.yrbjpktq; import java.util.Base64; //import android.util.Base64; //import bnxvhlyg.nkhoirul.zfxogwqi.mdpqejcw.srnepbly.pcbvwxrs.vixdqclm.wnuqvrhp.bnvceayd.bwdoclkr; //   import java.security.Key; import java.security.NoSuchAlgorithmException; import java.security.spec.AlgorithmParameterSpec; import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; public abstract class Main { public Main() { super(); } //hex to ascii public static byte[] xkvasepi(String str) { byte[] v0 = null; if(str != null && str.length() >= 2) { int v2 = str.length() / 2; v0 = new byte[v2]; int v1; for(v1 = 0; v1 < v2; ++v1) { v0[v1] = ((byte)Integer.parseInt(str.substring(v1 * 2, v1 * 2 + 2), 16)); } } return v0; } public static String podxiwkt(String[] args) { int v6; int v4; byte[] v2; Cipher v1; String v10 = args[0]; //text String v7 = args[1]; //key String v0 = args[2]; //IV //check if ((v10 == null) || (v10.length() == 0)) { return ""; } IvParameterSpec v5 = new IvParameterSpec(v0.getBytes()); try { v1 = Cipher.getInstance("AES/CBC/NoPadding"); } catch(NoSuchPaddingException v3) { return ""; } catch(NoSuchAlgorithmException v3_1) { return ""; } SecretKeySpec v9 = new SecretKeySpec(v7.getBytes(), "AES"); int v11_1 = 2; try { v1.init(v11_1, ((Key)v9), ((AlgorithmParameterSpec)v5)); //v2 = Base64.decode(v1.doFinal(bwdoclkr.xkvasepi(v10)), 0); v2=v1.doFinal(xkvasepi(v10)); //check if(v2.length <= 0) { return new String(v2); } } catch(Exception v3_2) { return ""; } v4=0; for (v6=v2.length-1;v6>=0;v6--){ if (v2[v6]==0) ++v4; } if(v4 > 0) { try { byte[] v8 = new byte[v2.length - v4]; System.arraycopy(v2, 0, v8, 0, v2.length - v4); v2 = v8; } catch (Exception v3_2) { return ""; } } v2 = Base64.getDecoder().decode(v2); return new String(v2); } public static void main(String[] args) { // write your code here System.out.println(podxiwkt(new String[] { "b1acd584a6eae4ca6321b1f7cdf9ba9617112b4fb39e76c8def876346e3032fbd32b2d188a09715f27124c1bf9facfdc", "637904cd08aeb2d3f6a21b5c7e84f519", "8f4c796d5a3120eb", "zcmwgvdn", "mkngbsyr", "rwcdaieu" })); } } 

このコヌドは正垞に実行されたす。 圌の仕事が明確になった埌、それは単玔化および単玔化され、プログラマヌによっお曞かれたおそらく簡朔な皮類になりたすもちろん、圌の手が最初に曲がっおいなかった堎合を陀きたす。

ご泚意
ずころで、この堎合、文字列の埩号化は、オンラむンリ゜ヌスの束を䜿甚しお実蚌できたす。 プログラム内で暗号化された文字列を呌び出す䟋



ここでは、たず初期化ベクトルを16進圢匏に倉換する必芁がありたす。



すべおの倀を眮き換えたす



最埌に、base64からデコヌドしたす。



その結果、通垞の文字列が取埗され、呌び出しが意味のあるものになりたす。

したがっお、コヌド党䜓を調べおすべおの暗号化された文字列を収集する必芁がありたすが、今ではそれらを個別に埩号化できたす。 ここで重芁な点は、「コヌドの倉曎ずコメント」の段階で、smaliレベルずJavaレベルsmaliの逆コンパむルの䞡方で䜜業できるこずです。

修正のプラス短所Mods
スマリ倉曎を加え、dexで再コンパむルし、新しい行で逆コンパむルできたす。smaliコヌドを扱うのは必ずしも簡単ではありたせん。 倉曎が正しくない堎合、アプリケヌションはビルドされたせん
Java倚くの堎合、高レベルの操䜜からデヌタを抜出する方がはるかに簡単です。ほずんどのJavaコヌドビュヌアヌは線集できたせん。

別の行の䟋

 vcgrnfjx.execSQL(nvhdzjfo.xipswfqb(new String[]{"f741f04a4991fc2f0a0029f610bbd1c250dfe115fb7770b892f75d8718b822d273251013991b4407e224fa3f9d4e92f6","378f40211b6e32a5406cd97e85bcf9ad","6378a459b1c20edf", "gexnfwok", "meazfhdp", "bsmotaxn"}) 

ここから、次のコヌドに正芏衚珟を曞くよりも、正芏衚珟を䜿甚しおパラメヌタヌを遞択するのが非垞に簡単です。

スマリコヌド䟋1

 00000280 new-instance v13, Ljava/lang/StringBuilder; 00000284 invoke-direct {v13}, Ljava/lang/StringBuilder;-><init>()V 0000028A const/4 v14, 0x6 0000028C new-array v14, v14, [Ljava/lang/String; 00000290 const/4 v15, 0x0 00000292 const-string v16, "f741f04a4991fc2f0a0029f610bbd1c250dfe115fb7770b892f75d8718b822d273251013991b4407e224fa3f9d4e92f6" 00000296 aput-object v16, v14, v15 0000029A const/4 v15, 0x1 0000029C const-string v16, "378f40211b6e32a5406cd97e85bcf9ad" 000002A0 aput-object v16, v14, v15 000002A4 const/4 v15, 0x2 000002A6 const-string v16, "6378a459b1c20edf" 000002AA aput-object v16, v14, v15 000002AE const/4 v15, 0x3 000002B0 const-string v16, "gexnfwok" 000002B4 aput-object v16, v14, v15 000002B8 const/4 v15, 0x4 000002BA const-string v16, "meazfhdp" 000002BE aput-object v16, v14, v15 000002C2 const/4 v15, 0x5 000002C4 const-string v16, "bsmotaxn" 000002C8 aput-object v16, v14, v15 


スマリコヌド䟋2

 0000008E new-array v0, v0, [Ljava/lang/String; 00000092 move-object/from16 v89, v0 00000096 const/16 v90, 0x0 0000009A const-string v91, "4500b5e2e2ad26b7545eb54d70ab360ae28c9d031e2afcc3f6a2b2ac488ea440" 0000009E aput-object v91, v89, v90 000000A2 const/16 v90, 0x1 000000A6 const-string v91, "da96f678922d4b07350b3a184ecc1f5e" 000000AA aput-object v91, v89, v90 000000AE const/16 v90, 0x2 000000B2 const-string v91, "0cf69e3d2745a1b8" 000000B6 aput-object v91, v89, v90 000000BA const/16 v90, 0x3 000000BE const-string v91, "jhiqsaoe" 000000C2 aput-object v91, v89, v90 000000C6 const/16 v90, 0x4 000000CA const-string v91, "khbqxurn" 000000CE aput-object v91, v89, v90 


スマリコヌド䟋3

 00000D3E new-array v0, v0, [Ljava/lang/String; 00000D42 move-object/16 v298, v0 00000D48 const/4 v0, 0x0 00000D4A move/16 v299, v0 00000D50 const-string v0, "b286945744e085f4d5c19916fd261481" 00000D54 move-object/16 v300, v0 00000D5A move-object/from16 v0, v300 00000D5E move-object/from16 v1, v298 00000D62 move/from16 v2, v299 00000D66 aput-object v0, v1, v2 00000D6A const/4 v0, 0x1 00000D6C move/16 v299, v0 00000D72 const-string v0, "df6883742b2911ac5ac7b4dee065390f" 00000D76 move-object/16 v300, v0 00000D7C move-object/from16 v0, v300 00000D80 move-object/from16 v1, v298 00000D84 move/from16 v2, v299 00000D88 aput-object v0, v1, v2 00000D8C const/4 v0, 0x2 00000D8E move/16 v299, v0 00000D94 const-string v0, "90a463ce2df17b58" 00000D98 move-object/16 v300, v0 00000D9E move-object/from16 v0, v300 00000DA2 move-object/from16 v1, v298 00000DA6 move/from16 v2, v299 00000DAA aput-object v0, v1, v2 00000DAE const/4 v0, 0x3 00000DB0 move/16 v299, v0 00000DB6 const-string v0, "cupyzsgq" 00000DBA move-object/16 v300, v0 00000DC0 move-object/from16 v0, v300 00000DC4 move-object/from16 v1, v298 00000DC8 move/from16 v2, v299 00000DCC aput-object v0, v1, v2 


ご芧のずおり、内郚倉数が倉化し、コマンドのシヌケンスが倉化し、匕数の数も倉化したす。さらに、プログラムでは、埩号化関数は盎接ではなく、レむダヌの関数を通じお呌び出されたす。 このコンストラクトを怜玢するルヌルを自分で蚘述し、他の関数から文字列をキャプチャする際の間違いを避け、すべおを迅速に実行しおください 幞運 。

トラップ蚈画

  1. 逆コンパむルされたコヌドからすべおの倀を抜出したす。
  2. 解読する。
  3. smaliコヌドで暗号文を開いおいるものに眮き換えたす。 たずえば、最初の挔算子の代わりに眮き換えたす。 関数呌び出し党䜓を切り取り、埩号化された文字列を返されたたたにしおおく方が専門的ですが、それでもプログラムを壊す倧きなリスクがありたす。
  4. smaliコヌドをdexファむルに集めたしょう。
  5. 開始したコヌドアナラむザヌをさらに調べるず䟿利です。

すべおの逆コンパむルされたコヌドを1぀のファむルに収集するず、玄20,000行を取埗したす。これは、手動分析に倚くの時間を必芁ずし、販売するブヌツより明らかにコストがかかりたす。 たず、すべおの行を正芏衚珟で収集したす。



私たちは593詊合に加えお、この芏則に該圓しなかったダヌスを芋るず、家族には黒い矊がいたす。 䟋



合蚈422の䞀意の行の䞊べ替え、フィルタヌ凊理



前に埩元した埩号化関数を通過したす。 結果



Pythonを䜿甚しお、暗号文をsmali-codeで開いおいるものに眮き換えたす。

 import os words_replace=dict() words_replace["0018aacad3d146266317d8d8c51785fd"]="imei" words_replace["016d15e4d0a72667c61428e736a6f3b8"]="WakeLock" words_replace["032c534efb6c9990cd845a08c5a08b95"]="inbox" #
  .. # smali- #      def change(path): print("file="+path) file_handle = open(path, 'r') context_full = file_handle.read() file_handle.close() for i in words_replace: context_full=context_full.replace(i, words_replace[i]) #print (i+""+words_replace[i]) file_handle = open(path, 'w') context_full = file_handle.write(context_full) file_handle.close() #      smali- for top, dirs, files in os.walk('C:\\work\\test'): for nm in files: path=os.path.join(top, nm) print (path) change(path) 

dexでsmaliファむルを収集したす。



これは䜕らかの圢で分析できたす構造党䜓から最初の匕数を読み取るこずにより。



分析


そのため、コヌドの読み取り可胜な行数は20,000行前埌になりたすが、完党な分析を実行するタスクには䟡倀がありたせん。 機胜党䜓を理解する必芁がありたす。 ここでは、実際には、Java゜ヌスコヌドを読み取る機胜のみが必芁です。 コヌドを歩き回り、盞互参照を調べ、倉数ず関数の名前を倉曎したす。

Androidアプリケヌション、特に倧芏暡なアプリケヌションを分析する最良の方法は䜕ですか

オプション1マニフェストファむルから移動できたす

たずえば、LAUNCHERから順番に呌び出しのチェヌン党䜓を解こうずしたす。 ずころで、プログラムの線圢実行を倉曎できる「受信者」ず「サヌビス」がただあるこずを忘れないでください。



完党なマニフェストファむル
 <?xml version="1.0" encoding="utf-8" standalone="no"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="xfmpuwon.mtnbupnc.ihqdgjal.ndgmqawx.bjunzerq.cznfpnoq.fzevcuym.jmpdiqft"> <uses-permission android:name="xfmpuwon.mtnbupnc.ihqdgjal.ndgmqawx.bjunzerq.cznfpnoq.fzevcuym.jmpdiqft.permission.C2D_MESSAGE"/> <uses-permission android:name="com.google.android.c2dm.permission.RECEIVE"/> <uses-permission android:name="android.permission.SEND_SMS"/> <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.READ_PHONE_STATE"/> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> <uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/> <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/> <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/> <uses-permission android:name="android.permission.RECEIVE_SMS"/> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <uses-permission android:name="android.permission.QUICKBOOT_POWERON"/> <uses-permission android:name="android.permission.READ_SMS"/> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> <permission android:name="xfmpuwon.mtnbupnc.ihqdgjal.ndgmqawx.bjunzerq.cznfpnoq.fzevcuym.jmpdiqft.permission.C2D_MESSAGE" android:protectionLevel="signature"/> <application android:allowBackup="true" android:icon="@drawable/icon" android:label="@string/tgiwmpqy" android:noHistory="true"> <activity android:configChanges="orientation" android:excludeFromRecents="true" android:label="@string/tgiwmpqy" android:launchMode="singleTop" android:name="zemquyog.csrtmnak.xrkfygen.wkahrnjd.acnfunjh.rgipxbuf.lruiwxeg.blqndche.dcjihbou" android:screenOrientation="portrait"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> <activity android:configChanges="orientation" android:launchMode="singleTop" android:name="xbfrscou.hxrvwnoi.djvpcqri.enlnrfio.aoegxbiu.heywzmnb.znfnxcht.nazcxobq" android:screenOrientation="portrait"/> <activity android:configChanges="orientation" android:launchMode="singleTop" android:name="hcfkagds.timkagsd.oetvghzr.fcioynvl.psynofdj.slcghdjz.tapnwsdk.gzvwnban.htenafdb.qwebhzgy" android:noHistory="true" android:screenOrientation="portrait"/> <activity android:configChanges="orientation" android:excludeFromRecents="true" android:launchMode="singleTop" android:name="njfbwmre.voefarqx.ftuxvngl.wrmshxqj.zdenywgn.eiwyunlg.jysgkbam.yrijthab.vstqxpuo.iplamgxf" android:priority="2147483647" android:screenOrientation="portrait"/> <receiver android:name="gfbaznoc.asyoqtnm.kbetoqca.mqysobzu.gqwfibrv.dorxijuk.wgzkmiep.ywnnurzv.csfpqhrn" android:permission="android.permission.BIND_DEVICE_ADMIN"> <meta-data android:name="@string/pkzrlscm" android:resource="@xml/ynqukvnb"/> <intent-filter android:priority="2147483646"> <action android:name="android.app.action.DEVICE_ADMIN_ENABLED"/> </intent-filter> </receiver> <receiver android:name="ykwbodxc.gymjhibn.kgmdfqor.hbasvmfz.yegkmaif.ortzknvm.quplincn.cuxytvhs.fqonzuts.cyuoxgqi.znumwyct" android:permission="com.google.android.c2dm.permission.SEND"> <intent-filter> <action android:name="com.google.android.c2dm.intent.RECEIVE"/> <action android:name="com.google.android.c2dm.intent.REGISTRATION"/> <action android:name="com.google.android.c2dm.intent.UNREGISTRATION"/> <category android:name="xfmpuwon.mtnbupnc.ihqdgjal.ndgmqawx.bjunzerq.cznfpnoq.fzevcuym.jmpdiqft"/> </intent-filter> </receiver> <receiver android:enabled="true" android:exported="true" android:name="kqwihjot.nvkqjloc.grjnyknm.owydvckh.mugknwdx.enhcyvja.mhvbpcue.ztbwjhfo"> <intent-filter android:priority="2147483646"> <action android:name="android.intent.action.LOCKED_BOOT_COMPLETED"/> <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/> <action android:name="android.intent.action.QUICKBOOT_POWERON"/> <action android:name="android.intent.action.BOOT_COMPLETED"/> <action android:name="android.intent.action.USER_PRESENT"/> <action android:name="android.intent.action.BATTERY_OKAY"/> <action android:name="android.intent.action.BATTERY_LOW"/> <action android:name="android.intent.action.ACTION_POWER_CONNECTED"/> <action android:name="android.intent.action.ACTION_POWER_DISCONNECTED"/> <action android:name="android.intent.action.APP_ERROR"/> <action android:name="android.intent.action.HEADSET_PLUG"/> <action android:name="android.intent.action.PHONE_STATE"/> <action android:name="android.intent.action.NEW_OUTGOING_CALL"/> <action android:name="android.provider.Telephony.SMS_RECEIVED"/> <action android:name="android.intent.action.TIME_TICK"/> <action android:name="android.intent.action.SCREEN_ON"/> <action android:name="android.intent.action.SCREEN_OFF"/> <action android:name="android.net.conn.CONNECTIVITY_CHANGE"/> <action android:name="android.net.wifi.WIFI_STATE_CHANGED"/> <action android:name="android.intent.action.DREAMING_STOPPED"/> <category android:name="android.intent.category.HOME"/> </intent-filter> </receiver> <receiver android:name="btnsxnuz.wmjizbky.lynvjxqz.zinomjuv.yizlgcnf.qwoikgnc.wnrskjea.wfqgmeny.lcgvqrms.ocwkgblp"> <intent-filter android:priority="2147483646"> <action android:name="android.provider.Telephony.SMS_RECEIVED"/> </intent-filter> </receiver> <service android:name="ltvsrezg.ehxndrat.twnnyxrf.nqynefws.dhbalcnr.ynjkuxod.nhoxmsbq.nackoyhn.voycgfek.znhwkqba.taxvnfyn"/> <service android:name="rbnakfzo.qsreiubk.pwvlnngs.twoxnhfv.mftarcnd.pfioxcub.xjlaftqr.nxrqvlwh"/> <service android:enabled="true" android:name="xfmpuwon.mtnbupnc.ihqdgjal.ndgmqawx.bjunzerq.cznfpnoq.fzevcuym.jmpdiqft.ugshpjvo"/> </application> </manifest> 


オプション2興味深い行から移動できたす



解読された文字列の䞀郚
 system_update.apk () () , error = , unregistered = ,  .permission.C2D_MESSAGE //sky-sync.pw/ //sms/inbox /system_update.apk ALLCONTACTS ALLMSG AUTHENTICATION_FAILED Acquiring wakelock Application BLOCKER_BANKING_START BLOCKER_EXTORTIONIST_START BLOCKER_STOP BLOCKER_UPDATE_START Banking CHANGE_GCM_ID CONTACTS CONTACTS_PRO CREATE TABLE IF NOT EXISTS END Error|No process list|No access Extortionist Foreground GCM returned invalid number of GCMBaseIntentService GCMBroadcastReceiver GCMIntentService- GCMRegistrar GCM_LIB GET MESSAGE Mobile Network NEWMSG Not retrying failed operation ONLINE PAGE POST Process finished with exit code 0 RESTART Received deleted messages Registering receiver Releasing wakelock SERVICE_NOT_AVAILABLE SSL START STOP Saving regId on app version Scheduling registration retry, backoff = Setting registeredOnServer status as Stop System UNBLOCK UPDATE UPDATE_PATTERNS URL UTF-8 Update WakeLock Wakelock reference is null Wi-Fi WiMax _success add_msg_ok address android.intent.action.QUICKBOOT_POWERON answer_text answer_to api_url app appVersion application application/vnd.android.package-archive apps_list ask backoff_ms blocker blocker_banking blocker_banking_autolock blocker_banking_forced_access blocker_banking_success blocker_extortionist blocker_extortionist_autolock blocker_extortionist_forced_access blocker_extortionist_success blocker_update blocker_update_forced_access blocker_update_success body build callback cardSuccess check com.android.settings com.google.android.c2dm.intent.RECEIVE com.google.android.c2dm.intent.REGISTER com.google.android.c2dm.intent.REGISTRATION com.google.android.c2dm.intent.UNREGISTER com.google.android.gcm com.google.android.gcm.intent.RETRY com.google.android.gsf com.htc.intent.action.QUICKBOOT_POWERON command command_receive contactslist country data date delete deleted_messages device_block disableDataConnectivity enableDataConnectivity error failure file deleted. first_start force-locked gafzpjxb.cix gcm gcm_id gcm_register gcm_register_ok getITelephony get_message_list id integer primary key autoincrement, id=? imei immunity inbox init_bootable init_imei is_admin is_awake_display is_imunnity is_locked is_network_type is_top_activity job job_date job_id komgejif.hqr locked message message_delivered message_type method model msg msg_id msglist name not nypjtinq.nvp ok onServer onServerExpirationTime onServerLifeSpan operator org.android.sys.admin.disabled org.android.sys.admin.enabled org.android.sys.admin.request org.android.sys.command.receive org.android.sys.launch.first org.android.sys.sms.pro.sent org.android.sys.sms.push org.android.sys.sms.sent outbox page params pattern patterns personal phone phone_list privet process_list protocol qwertyuiopasdfghjklzxcvbnm receive regId regex register register_ok registrationId = registration_id repeat resetting backoff for ru save_contacts_list save_message_history sender sent sent_status sid ss status stop_blocker text text, text/html time token total_deleted type unknown unregistered until url useragent utf-8 value version xpls yes   !     ...                   !  ?                ! 

オプション3興味深いリ゜ヌスアセット、ラむブラリから移動できたす

この堎合、オプション3が掚奚されたした。 / assetフォルダヌapkコンテナヌには3぀の興味深いhtmlファむルがありたす。 ブラりザでのビュヌは次のずおりです。





公匏のAvito支払い振替プログラムには疑わしいず思われたすが、そうではないでしょうか キヌを抌しおSberbankロゎ付きの銀行口座デヌタをペヌゞに送信するずどうなるかを远跡したしょう。 JavaScriptはsendCardData()関数を呌び出したす。



そしお、 ok.performClick()呌び出しを介しおJavaコヌドに枡されたす。



Javaコヌドでは、凊理が実行されたす。



さらに、これらはすべおmcryptクラスで暗号化されたす。



関数内では、デヌタは以前に怜蚎されたのず同じ方法で暗号化されたす



しかし、残りの郚分では、キヌはハヌドワむダヌドです



オンラむンリ゜ヌスを介しお埩号化を詊みたす。



そしお、base64から倉換したす。 成功 すべおのアプリケヌションデヌタを埩号化できたす。以前にキャプチャされたトラフィックでチェックされたす。

アプリケヌションは、すべおのむベントに぀いおサヌバヌに報告したす
 { "sid":15, "imei":"861117030537111", "phone":"System", "message":"     22.10.2018 23:30:47", "time":"1540240247", "msg_id":1, "status":"unknown", "type":"inbox", "method":"message" } 

たた、実行䞭のすべおのアプリケヌションを定期的に転送したす
 { "sid": 15, "imei": "861117030537111", "country": "ru", "operator": "MTS RUS", "phone": "", "model": "Xiaomi Redmi 3X", "version": "6.0.1", "application": "", "build": "30.0.2", "process_list": [ "Background|com.android.bluetooth|com.android.bluetooth.hid.HidService", "Background|com.android.settings:remote|com.android.settings.wifi.MiuiWifiService", "Background|com.android.phone|org.codeaurora.ims.ImsService", "Background|system|com.qualcomm.location.LocationService", ..., "Background|xfmpuwon.mtnbupnc.ihqdgjal.ndgmqawx.bjunzerq.cznfpnoq.fzevcuym.jmpdiqft|ltvsrezg.ehxndrat.twnnyxrf.nqynefws.dhbalcnr.ynjkuxod.nhoxmsbq.nackoyhn.voycgfek.znhwkqba.taxvnfyn" ], "apps_list": [ "com.introspy.config", "com.google.android.youtube", "com.google.android.googlequicksearchbox", "org.telegram.messenger", ..., "com.google.android.inputmethod.latin", "jakhar.aseem.diva" ], "method": "register" } 

ダむナミクスに銀行デヌタ入力のりィンドりがある堎合、デヌタはトラフィックにありたす。したがっお、これは「フィッシング」アプリケヌションであるず結論付けるこずができたす。

マニフェストファむルには非垞に倚くのアクセス蚱可があり、アプリケヌションには豊富な機胜があるこずに気づいた人たちです。別の蚘事で機胜の詳现な分析を行いたす。それたでの間、成功

結論


私はブヌツを売らなかったこずに倱望しおいたす。そしお、結論は次のずおりです。


PSこの蚘事をナヌモラスな圢匏で少し曞き、できるだけ簡単に送信しようずしたした。金曜日に「リバヌス゚ンゞニアリングの難読化された悪意のあるAndroidアプリケヌション」ずいうタむトルの深刻なロングラむドを読みたくはないからです。

Source: https://habr.com/ru/post/J430074/


All Articles