
أنا واحد من هؤلاء الأشخاص الذين يحاولون ، مع بداية فصل الخريف ، قضاء وقت أقل في الشارع. في موسكو ، هذا ليس صعبًا: أنت مقيد بالطريق من المنزل إلى المكتب والعودة. ومع ذلك ، يمكن أن يتسبب الطقس الرطب في عدم الراحة في الغرفة ، خاصة إذا كان مكان عملك ، مثل لي ، في النافذة ، ويطلب كل زميل آخر ، يشكو من الازدحام ، تهوية المكتب. لكي لا تقع في الطحال ، قمت في هذا الخريف بتحديث خزانة الملابس.
التفكير في مصير الأشياء غير الضرورية ، تساءلت ماذا أفعل بها: رميها ، قطعها إلى الخرق ، وإعطائها لأخي الأصغر لحملها؟ ولكن لسبب واحد ، لم تكن أي من هذه الطرق مناسبة: كانت أحذية جلدية 44 بحجم لائق ، لكنهم أزعجوني بالترتيب. قررت بيعها على Avito. لقد قمت بتحميل الصور ، وأشرت إلى اسم زائف (أمن المعلومات هو نفسه) ، ووضعت حذائي ، وبعض الأشياء الأخرى ، ونمت. كيف أعرف أن هذا سيؤدي إلى تحليل طويل للتطبيق للتهديدات الخفية؟

مفاجأة سارة
في اليوم التالي بعد مكالمتين مشكوك فيهما ، تلقيت رسالة SMS مثيرة للاهتمام تحتوي على المحتويات التالية:

بعد يومين ، تلقيت رسالة أخرى مماثلة:

فوجئت بأن شخصًا ما كان قادرًا بطريقة ما على تحويل الأموال لي على الإنترنت (على ما يبدو ، أنا الوحيد القديم - ما زلت أستخدم كتب التوفير الورقية) ، نقرت على الرابط في الرسائل القصيرة.
بعد ذلك ، عرض علي تنزيل تطبيق Android (ملف apk). لحسن الحظ تنزيل الملف ، رأيت ما يلي:

إنها ذات مصداقية! أردت بتلهف تثبيت كل شيء بسرعة وإنهائه.
ولكن هنا ، كالعادة ، لم يسمح لي نظام التشغيل Android المزعج لسبب ما بتشغيل الملف. "أعطني المال بالفعل!" كنت ساخط. اضطررت للذهاب إلى الإعدادات وتشغيل بعض الخيار "مصادر غير معروفة" ، هل الهاتف غبي حقًا في 2018؟ بالمناسبة ، هاتفي هو Xiaomi Remdi مع Andoid 6.0.1 (ملاحظة للتكنولوجيا).


تبع ذلك سلسلة من الأحداث الغريبة. استمر الهاتف في الإبلاغ عن مصادر غير موثوقة. لكن أفيتو
مصدر موثوق ! اضطررت إلى البحث في Google ، ومعرفة كيفية الالتفاف حول هذا ، ثم إيقاف تشغيله في الإعدادات. سرعان ما ظهر مضاد فيروسات معين لم أقم بتثبيته.




أخيرًا ، رأيت نافذة التثبيت القياسية المرغوبة -
ليس من المنطقي أن ننظر إلى الأذونات في الوقت الحاضر ، والآن لن يبدأ تشغيل الكمبيوتر الدفتري حتى تمنحها حق الوصول الكامل إلى الهاتف. لحظة سعيدة لإكمال تثبيت التطبيق وبدء! كنت أتطلع إلى الأموال الموعودة. بالإضافة إلى ذلك ، طلب التطبيق امتيازات المسؤول ، والتي وافقت عليها بسرور. لسوء الحظ ، تصرف التطبيق بشكل غريب ولم يرغب في الدفع ، وسرعان ما اختفى تمامًا من قائمة التطبيقات على الشاشة المشتركة.





الإيثار
إذن ، ما الذي وصلنا إليه:
- استغرق التثبيت 20 دقيقة.
- لم أستلم المال.
اعتقدت أن المشكلة كانت خطأ في الكود ، كما هو الحال غالبًا مع المبرمجين. قررت تحديد الأخطاء التي تحدث عند تشغيل التطبيق على هاتفي ، وإرسال تقرير عنها إلى المطور.
المفسدالآن لم يبق سوى عدد قليل من الأشخاص المهتمين ، أحدهم هو أنا.
من الواضح أن هذا النوع من التطبيقات يجب أن يعمل عند اتصال الإنترنت ، لذلك حاولت في البداية تحليل حركة المرور بين الهاتف وخادم التطبيق.
الدليل الفني لتكوين الوكيليمكنك الاستماع إلى حركة مرور الإنترنت في أي وقت على طول المسار من الهاتف إلى الخادم ، سواء كان جهاز توجيه منزلي أو مزود إنترنت محلي أو العمود الفقري للإنترنت أو خادم التطبيق.
المشاكل:
- الوصول إلى هذا الجهاز مطلوب.
- مطلوب لفصل حركة مرور التطبيق المطلوب عن الباقي.
- في حالة التشفير (وفي عام 2018 تم تشفير كل شيء بالفعل) - من الضروري معرفة المفتاح.
قررت أن أذهب بطريقة أكثر كلاسيكية وتهيئة الوكلاء على الهاتف باستخدام خادم وكيل على جهاز الكمبيوتر المحمول الخاص بي. للتخفيف من مشكلة التشفير ، قررت استيراد شهادتي ، ولم أقم بتشغيل تطبيقات أخرى لفصل حركة مرور التطبيق.
اخترت
مجموعة التجشؤ كبرنامج الخادم الوكيل. لقد قمت بإعداد خادم وكيل وتصدير شهادة إلى هاتفي.




بعد إعداد برنامج متخصص ، تمكنت من رؤية الطلبات التي يرسلها التطبيق إلى الخادم:

كما ترى ، لم يتم إرسال البيانات (يشار إلى قيمة المضيف غير المعروفة في عمود IP) ، علاوة على ذلك ، لا يمكن تحليلها بسبب وجود تشفير إضافي على مستوى التطبيق. إذا حكمنا بالخطأ ، لم يتمكن الهاتف من تحديد عنوان IP الخاص بالخادم ونطاقاته الفرعية
https: //*.sky-sync.pw حسب اسم المجال الخاص به.
قد يعني هذا فقط الخيارات التالية:
- لقد توقف اسم المجال من الوجود
- تم حظره من قبل المالك نفسه.
- وقد منعه المسجل بسبب الشكوى.
- مشكلة في خادم DNS
- لا يعرف خادم DNS العنوان ، لأن المطور في الإنتاج طرح عنوان DNS المحلي.
- حظر خادم DNS هذا الطلب على وجه التحديد ، وهذا ليس مفاجئًا في عصر الرقابة على الإنترنت.
للتحقق من افتراض وجود مشكلة في خادم DNS ، حاولت تقديم طلبات من خوادم DNS كبيرة مختلفة: Google و Yandex و OpenDNS (عادة ما يتم حظر DNS المحلي):

يمكن ملاحظة أنه لا أحد منهم يعرف أي شيء عن هذا الاسم. بعد ذلك ، ألقيت نظرة على معلومات whois حول تسجيل النطاق:

فضولي: تم تسجيل النطاق ، أي أنه على الأرجح ليس محليًا ، ولكن نظرًا لعدم حل النطاق ، فربما تم حظره من قِبل المسجل بسبب إساءة الاستخدام. لكن لماذا؟ ما الخطأ الذي فعله؟
لمعرفة ما هو هذا التطبيق تمامًا وكيف يمكنني أخذ أموالي ، قررت استخدام
سحر الهندسة العكسية.
الهاوية
إذا كنت إنسانيًا وقرأت في هذا المكان ، فهذا أمر جيد - لتنمية اللاحقة أنت تستحق جائزة
بعد وفاتها .
مجموعة أدوات
لمعرفة ما "تحت غطاء" التطبيق ، نحتاج إلى تنزيل أدوات متخصصة. يمكنك تنزيلها بشكل فردي:
- فك حزمة APK
- كلاسيك - ApkTool .
- يمكنك فك ضغطه باستخدام أرشيفي تقليدي ، ولكن بعد ذلك ستكون جميع الموارد الثنائية ، بما في ذلك التطبيقات وملف البيان ، غير قابلة للقراءة.
- فك شفرة Smali
- المعيار هو Dex2Jar ، ولكن تعلم أن هذا البرنامج يعمل في كثير من الأحيان بشكل منحرف.
- تحتاج إلى التعامل مع الأمر بعناية شديدة ، لأن المترجم إلى المترجم مختلف ، سننظر في ذلك لاحقًا.
- برنامج لعرض التعليمات البرمجية المترجمة ، أوصي بـ jd-gui
أو يمكنك استخدام المنتج ، المدفوع عادة ، حيث يوجد كل شيء في وقت واحد. أنا أفضل
JebDecompiler : يمكنه فقط تقديم تطبيق apk
لمدخلاته ، وسوف يرتب كل شيء في علامات التبويب ، بالإضافة إلى أنه مناسب للتبديل بين كود Java smali و decompiled.
بشكل منفصل ، أود أن أشير إلى:
فقط كبار السن يخوضون المعركة
مراجعة
عند فتح الشفرة المترجمة ، يتضح على الفور أنها مشوشة.

كيف أفهم ذلك؟
- أسماء الفئات التي يمكن قراءتها بواسطة الإنسان
isqpwcmx.isfdztgb.adscjobz.nxscomkr.jypbdxnt.utagwpym.wprtdznb.swldgrhm.yrbjpktq.wukovicq;
- رمز لا يمكن الوصول إليه
if(0 != 0) {</li> String v1 = "flnwznvh";</li> if(v1.length() != 661 && v1.charAt(0) == 104) {</li> v1.length();</li> }
- تشفير السلسلة
vcgrnfjx.execSQL(nvhdzjfo.xipswfqb(new String[]{"f741f04a4991fc2f0a0029f610bbd1c250dfe115fb7770b892f75d8718b822d273251013991b4407e224fa3f9d4e92f6","378f40211b6e32a5406cd97e85bcf9ad","6378a459b1c20edf", "gexnfwok", "meazfhdp", "bsmotaxn"})
من غير المحتمل أن يكون المبرمج مجنونًا لدرجة أنه طور الشفرة في البداية. على الأرجح ، استخدم أحد الغامض المتاح للجمهور. هذه الخطوة شائعة جدًا لتعقيد تحليل الشفرة من أجل حماية الملكية الفكرية ، على سبيل المثال ، ولكن أي نوع من "الالتواء" بالنسبة للباحث.
دعونا ننتبه إلى وظيفة التشفير الرئيسية:

تقبل وظيفة التشفير نفسها 3 أسطر من المدخلات (إذا كان الأمر أكثر ، فإن الباقي لا معنى له):
- نص مشفر
- المفتاح
- ناقل التهيئة لـ CBC - AES
تتم الإشارة إلى هذه الوظيفة في البرنامج 213 مرة على الأقل:

ألاحظ أنه مفتاح مهم لتحليل الكود العادي. بعد ذلك ،
تحتاج إلى التفكير في أن لدينا الطرق التالية لتحليل البرنامج:
- قم باستعادة منطق الوظيفة ، وجمع كل المكالمات في التحليل الثابت ، وفك تشفير الخطوط. قد يكون الأمر صعبًا وطويلًا ، ولكنه سيعطي نتيجة 100 ٪.
- قم بإجراء تغييرات على رمز smali للتطبيق ، وقم بالترجمة مرة أخرى ، وقم بتشغيل التطبيق والتقاط الأسطر التي تم فك تشفيرها في السجلات. من السهل القيام بذلك ، ولكن الطريقة التي سيتصرف بها التطبيق في عملية تشغيل معينة غير معروفة ، وقد لا ترى الصورة كاملة (لا تحصل على مكالمات لجميع الوظائف). بالإضافة إلى ذلك ، قد تكون هناك مشاكل في الفحص الذاتي من خلال تطبيق الشهادة و (أو) التكامل.
- إذا كان من الصعب استعادة منطق الوظيفة ، فيمكنك حينئذٍ جمع كل استدعاءات الوظائف وسحب هذه الوظائف نفسها مع المعلمات الضرورية مباشرة في الديناميكيات (باستخدام ، على سبيل المثال ، برنامج Frida .
سنختار الطريقة رقم 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.

أحدث إصدار لها ، تم جمعه من المصادر ، أنتج كودًا مترجمًا لهذه الوظيفة ، لكنه لم يستطع فك العديد من اللغات الأخرى (هذه هي الحيلة).


خلاصة القول: فكر بعناية في اختيار جهاز فك الشفرة - سيوفر لك هذا الكثير من الوقت وسيكون أسهل من تحليل رمز 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 ""; }
الآن أصبح الأمر أكثر وضوحًا ، إليك فحص الإدخال المعتاد. في هذه الحالة ، نحتاج إلى:
- استبدل جميع "goto" ببنيات لغة أخرى ، مثل لطالما كان "Goto" عامل تشغيل غير صالح.
- استبدل مكالمات مكتبة Android بمكالمات مكتبة Java (إذا حاولنا تنفيذ التعليمات البرمجية في Java IDE).
- إدراج الفئات التابعة المشار إليها بواسطة التعليمات البرمجية الخاصة بنا.
- فكر في نفسك ما هو الخطأ.
نتيجة لذلك ، نحصل على:
package com.company;
{ "b1acd584a6eae4ca6321b1f7cdf9ba9617112b4fb39e76c8def876346e3032fbd32b2d188a09715f27124c1bf9facfdc"، "637904cd08aeb2d3f6a21b5c7e84f519"، "8f4c796d5a3120eb"، "zcmwgvdn"، "mkngbsyr"، "rwcdaieu"}))؛ package com.company;
يفي هذا الرمز بنجاح. بعد أن يصبح عمله واضحًا ، يمكن تبسيطه وتبسيطه ، مما يؤدي إلى النوع المقتضب المفترض الذي كتبه المبرمج (ما لم تكن يداه بالطبع ملتوية في البداية).
ملاحظةبالمناسبة ، في هذه الحالة ، يمكن إظهار فك تشفير السلاسل باستخدام مجموعة من الموارد عبر الإنترنت. مثال على استدعاء سلسلة مشفرة داخل برنامج:

هنا ، يجب تحويل متجه التهيئة أولاً إلى تنسيق Hex:

استبدل جميع القيم:

وفي النهاية ، فك الشفرة من base64:

ونتيجة لذلك ، نحصل على السلسلة المعتادة ، وتلقي المكالمة نظرة ذات معنى.
وبالتالي ، تحتاج إلى مراجعة الرمز بالكامل وجمع جميع السلاسل المشفرة ، والآن يمكننا فك تشفيرها بشكل مستقل. النقطة المهمة هنا هي أنه في مرحلة "التعديل والتعليق على الكود" يمكننا العمل على مستوى smali وعلى مستوى Java (smali decompiled).
| إيجابيات التعديل | سلبيات تعديل |
سمالي | يمكنك إجراء تغييرات وإعادة تجميع في dex وفك مع خطوط جديدة | ليس من السهل دائمًا العمل باستخدام رمز smali. إذا كان التغيير غير صحيح ، فلن يتم ترجمة التطبيق |
جافا | غالبًا ما يكون استخراج البيانات من عمليات المستوى الأعلى أسهل كثيرًا. | لا يستطيع معظم مشاهدي كود 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
مثال على رمز Smali 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
كما نرى ، تتغير المتغيرات الداخلية ، ويختلف تسلسل الأوامر ، كما يختلف عدد الحجج ، بالإضافة إلى ذلك ، في البرنامج ، لا يتم استدعاء وظيفة فك التشفير بشكل مباشر ، ولكن من خلال وظائف الطبقة. حاول كتابة قاعدة بنفسك للبحث عن هذه البنية ، وتجنب الأخطاء في التقاط السلاسل من الوظائف الأخرى ، وقم بكل ذلك بسرعة (
حظًا سعيدًا ).
خطة المصيدة:
- سنقوم باستخراج كل القيم من الكود المتحلل.
- فك تشفير.
- استبدل النص المشفر بالنص المفتوح في كود smali. نستبدل ، على سبيل المثال ، بدلاً من عامل التشغيل الأول. (سيكون من الأكثر احترافية قطع مكالمة الوظيفة بالكامل وترك السلسلة التي تم فك تشفيرها ، ولكن مرة أخرى هناك خطر كبير لكسر البرنامج).
- دعنا نجمع كود smali في ملف dex.
- سيكون من الملائم النظر إلى مزيد من المعلومات في محلل الشفرة ، حيث بدأنا.
إذا جمعت كل الشفرة المترجمة في ملف واحد ، فستحصل على حوالي 20000 سطر ، وهو ما يتطلب للتحليل اليدوي الكثير من الوقت ، والذي يكلف بوضوح أكثر من الأحذية التي عرضتها للبيع. أولاً ، اجمع كل الخطوط بتعبير عادي.

نرى 593 مباراة ، بالإضافة إلى اثني عشر من الذين لم يندرجوا تحت هذه القاعدة ،
لدى الأسرة خرافها السوداء . مثال:

ترتيب ، تصفية ، إجمالي 422 سطرًا فريدًا:

نمر من خلال وظيفة فك التشفير التي استعادناها في وقت سابق. النتيجة:

استبدل النص المشفر بالنص المفتوح برمز smali باستخدام Python:
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)
نجمع ملفات smali في dex:

الآن يمكن تحليل هذا بطريقة أو بأخرى (من خلال قراءة الحجة الأولى من البناء بأكمله):

تحليل
لذلك ، لدينا 20000 سطر من التعليمات البرمجية يمكن قراءتها أكثر أو أقل ، لا نحتاج إلى إجراء تحليل كامل. من الضروري فهم الوظيفة ككل. هنا ، في الواقع ، مطلوب فقط القدرة على قراءة شفرة مصدر جافا. تجول في الكود ، وانظر إلى المراجع التبادلية ، وأعد تسمية المتغيرات والوظائف.
ما هي أفضل طريقة لتحليل تطبيق 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. هناك ثلاثة ملفات html مثيرة للاهتمام في مجلد / asset (حاوية apk). هنا وجهة نظرهم في المتصفح:



يبدو الأمر مشكوكًا فيه بالنسبة لبرنامج Avito الرسمي لتحويل الدفع ، ألا يبدو لك ذلك؟ دعونا نتتبع ما يحدث عند الضغط على المفتاح لإرسال البيانات المصرفية على الصفحة مع شعار Sberbank. تستدعي JavaScript وظيفة
sendCardData()
:

ثم يتم تحويلها إلى كود Java من خلال المكالمة
ok.performClick()
:

في كود 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" }
إذا كانت لدي نافذة لإدخال البيانات المصرفية في الديناميكيات ، فستكون البيانات في حركة المرور. وهكذا ، يمكننا أن نستنتج أن هذا هو تطبيق "التصيد".أولئك الذين كانوا حذرين لاحظوا أن ملف Manifest لديه عدد غير قليل من الأذونات ، وأن التطبيق يحتوي على وظائف أكثر ثراء. سنقوم بإجراء تحليل عميق للوظيفة في مقال آخر. في هذه الأثناء ، النجاح!الاستنتاجات
أشعر بخيبة أمل لأنني لم أبيع الأحذية. وكانت الاستنتاجات كما يلي:لا تبيع الأحذية على Avito- لا تنقر على الروابط الغامضة (حتى لو كان من الأصدقاء وحتى إذا كنت "بحاجة إلى اقتراض 100 روبل بشكل عاجل - مسألة حياة أو موت")
- لا تقم بتنزيل تطبيقات بخلاف Google Play أو AppStore
- افصل التثبيت من "مصادر غير موثوقة" إذا كنت لا تفهم حقًا ما هو.
- لا تفصل "حماية التشغيل".
- تذكر أنه قد يكون هناك برامج ضارة على Google Play
- قم بتثبيت برنامج مكافحة الفيروسات على الهاتف (إنه يعمل حقًا).
- إذا كنت مطورًا ، لا تشوه الرمز ، دع الناس يتأكدون من حسن نواياك ( مجرد مزاح )
- إذا كنت باحثًا ، فلا تعمل من أجل الطعام ، وقم بتحليل التطبيقات في وقت فراغك ونشر التقارير. معًا سنجعل العالم مكانًا أفضل.
ملاحظة: حاولت كتابة المقالة قليلاً بتنسيق فكاهي وإرسالها بأبسط ما يمكن ، لأنني حتى لا أريد أن أقرأ على الأرجح يوم الجمعة رحلة طويلة خطيرة تسمى "الهندسة العكسية لتطبيق Android الخبيث المشوش".