تعطيل فحص حالة وقت التشغيل في تطبيق Android



في مقال سابق ، قمت بمراجعة على OWASP Mobile TOP 10 ثم لم يكن لدي حالة مناسبة لإثبات الحاجة إلى حماية شفرة المصدر. ظهرت حالة مثيرة للتظاهر مؤخرًا فقط ، ومن المهتمين بالنظر إلى تجربتنا في التحايل على الفحوصات البيئية ، فلنذهب تحت القطة.

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

  • تم تحطم الجهاز ؛
  • تم استخدام محاكي.
  • توفر الاتصال عبر USB ؛
  • باستخدام وضع المطور.

لم يعمد المطورون إلى تشفير شفرة المصدر ولم يكن هناك فحص داخلي لتعديل التعليمات البرمجية ، مما سمح لي بتحليل الطرق التي تم من خلالها إجراء عمليات الفحص وإجراء التلاعبات اللازمة معهم.

لذلك دعونا نبدأ. وفقًا لـ OWASP Mobile TOP 10 ، الذي نستخدمه كمنهجية للاختبار الأساسي في Hacken ، Reverse Engineering - تتضمن هذه الثغرة تحليل الملفات الثنائية لتحديد شفرة المصدر والمكتبات والخوارزميات ، إلخ. يمكن لبرامج مثل IDA Pro و Hopper و otool وأدوات الهندسة العكسية الأخرى إعطاء فكرة عن التشغيل الداخلي للتطبيق. يمكن استخدام هذا للبحث عن نقاط الضعف في التطبيق ، واستخراج المعلومات الهامة مثل خادم الواجهة الخلفية ، ومفاتيح التشفير أو الملكية الفكرية.

لإجراء التحليل الثابت الأساسي ، استخدمت أداة مثيرة للاهتمام مثل MobSF ، والتي قامت بفك التحليل والتحليل الثابت الأساسي. بعد فك التجميع ، كنت مهتمًا برموز جافا و smali للبرنامج. كود Java مطلوب للتحليل ، وسنجري تغييرات على كود smali. يمكن العثور على مزيد من التفاصيل حول كيفية ارتباط smali و Java هنا .

بعد الاطلاع على قائمة الفئات ، وجدت ملفًا مسؤولاً عن التحقق من روتين الهاتف (انظر الشكل 1) - rootingcheck / RootBeerNative.java.


التين. 1. قائمة فئات التطبيق

بعد تحليل الصف ، أصبح من الواضح أننا بحاجة إلى مزيد من البحث عن المكالمات للوظائف checkForRoot () و setLogDebugMessage () (انظر الشكل 2).


التين. 2. كود المصدر للفئة للتحقق من rutovanost

باستخدام الأمر grep ، نحصل على النتائج التالية ، التي توضح لنا الملفات التي تحتوي على استدعاء طرق checkForRoot () و setLogDebugMessage ().

نتائج البحث:
root @ kali: ~ / Desktop # grep -nr 'RootBeerNative' ******** _ v_0.9.2 /

********_v_0.9.2/smali/rootingcheck/RootBeerNative.smali:1:.class public Lrootingcheck/RootBeerNative; ********_v_0.9.2/smali/rootingcheck/RootBeerNative.smali:17: sput-boolean v0, Lrootingcheck/RootBeerNative;->?:Z ********_v_0.9.2/smali/rootingcheck/RootBeerNative.smali:28: sput-boolean v0, Lrootingcheck/RootBeerNative;->?:Z ********_v_0.9.2/smali/rootingcheck/RootBeerNative.smali:57: sget-boolean v0, Lrootingcheck/RootBeerNative;->?:Z ********_v_0.9.2/smali/o/CM.smali:591: new-instance v1, Lrootingcheck/RootBeerNative; ********_v_0.9.2/smali/o/CM.smali:593: invoke-direct {v1}, Lrootingcheck/RootBeerNative;-><init>()V ********_v_0.9.2/smali/o/CM.smali:685: new-instance v0, Lrootingcheck/RootBeerNative; ********_v_0.9.2/smali/o/CM.smali:687: invoke-direct {v0}, Lrootingcheck/RootBeerNative;-><init>()V ********_v_0.9.2/smali/o/CM.smali:689: invoke-static {}, Lrootingcheck/RootBeerNative;->?()Z ********_v_0.9.2/smali/o/CM.smali:753: new-instance v4, Lrootingcheck/RootBeerNative; ********_v_0.9.2/smali/o/CM.smali:755: invoke-direct {v4}, Lrootingcheck/RootBeerNative;-><init>()V ********_v_0.9.2/smali/o/CM.smali:764: invoke-virtual {v4, v3}, Lrootingcheck/RootBeerNative;->checkForRoot([Ljava/lang/Object;)I ********_v_0.9.2/smali/o/xZ$5.smali:257: new-instance v1, Lrootingcheck/RootBeerNative; ********_v_0.9.2/smali/o/xZ$5.smali:259: invoke-direct {v1}, Lrootingcheck/RootBeerNative;-><init>()V ********_v_0.9.2/smali/o/xZ$5.smali:261: invoke-static {}, Lrootingcheck/RootBeerNative;->?()Z 

root @ kali: ~ / Desktop # grep -nr 'setLogDebugMessages' ******** _ v_0.9.2 /
 ********_v_0.9.2/smali/o/CM.smali:599: invoke-virtual {v1, v0}, Lrootingcheck/RootBeerNative;->setLogDebugMessages(Z)I ********_v_0.9.2/smali/o/CM.smali:761: invoke-virtual {v4, v0}, Lrootingcheck/RootBeerNative;->setLogDebugMessages(Z)I 

لكن هذه لم تكن كلها شيكات. بعد تحليل فئة MainActivity.java ، وجدنا مكالمات وظيفية حيث يتم تمرير السلاسل "su" و "مفاتيح الاختبار" و "التي" ، والتي يتم إجراء الفحص منها (انظر الشكل 3).


الشكل 3. الشيكات الروتينية

ومرة أخرى ، باستخدام الأمر grep ، ننظر في ملفات smali للتحقق من الروتين:

نتائج البحث:
root @ kali: ~ / Desktop # grep -nr 'su' ******** _ v_0.9.2 /

 ********_v_0.9.2/smali/o/CM.smali:443: const-string v2, "su" ********_v_0.9.2/smali/o/CM.smali:706: const-string v2, "su" ********_v_0.9.2/smali/o/xZ$5.smali:172: const-string v1, "su" ********_v_0.9.2/smali/o/xZ$5.smali:347: const-string v0, "su" 

root @ kali: ~ / Desktop # grep -nr "test-keys" ******** _ v_0.9.2 /

 ********_v_0.9.2/smali/o/xZ$5.smali:141: const-string v1, "test-keys" ********_v_0.9.2/smali/o/xZ$5.smali:374: const-string v0, "test-keys" 


root @ kali: ~ / Desktop # grep -nr 'الذي' ******** _ v_0.9.2 /

 ********_v_0.9.2/smali/o/CM.smali:437: const-string v2, "which" 

في المقالة سأعرض واحدًا فقط من التعديلات التي تم العثور عليها لعمليات الفحص الروتينية. بعد القليل من التلاعب ، أي تغيير 1 إلى 0 ، تمت إزالة الفحوصات الروتينية.


التين. 4. قيمة المتغير تساوي واحد إذا كان الهاتف متجذرًا


التين. 5. الآن قيمة المتغير هي صفر إذا كان الهاتف متجذرًا

بعد ذلك - يمكن تجميع البرنامج وتوقيعه بمفتاح التحرير وتشغيله على هاتف محمول. ولكن إن لم يكن لمدة سنتين ولكن! وهي:

  1. فحص اتصال USB ؛
  2. التحقق من تضمين وضع المطور - يسمح اتصال USB ووضع المطور المضمن بالتحليل الديناميكي.

يتم إيقاف تشغيل فحص وضع المطور بنفس طريقة الفحص الروتيني - عن طريق تغيير الوحدة إلى صفر في الاختبارات

في فئة MainActivity.java ، نجد الخط المسؤول عن التحقق من وضع المطور (انظر الشكل 6). بعد ذلك ، ابحث عن الملفات التي توجد فيها السلسلة "development_settings_enabled" وقم بتعديل الاختيار - قم بتغيير 1 إلى 0 (انظر الشكل 7 و 8).


التين. 6. تحقق من تمكين وضع المطور على الهاتف

نتائج البحث:
grep -nr "development_settings_enabled" ******** _ v_0.9.2 \

 Binary file ********_v_0.9.2\/build/apk/classes.dex matches ********_v_0.9.2\/smali/o/xZ$1.smali:49: const-string v1, "development_settings_enabled" 


التين. 7. المكان الذي تحتاج فيه لإجراء التعديل


التين. 8. التعديل

بعد كل التلاعبات ، يمكنك تشغيل البرنامج في وضع المطور.

بعد ذلك ، قم بإيقاف تشغيل فحص اتصال USB. هذا الفحص موجود في فئة MainActivity.java (انظر الشكل 9). بدون grep ، نجد السطر في MainActivity.smali ، نجد السطر الذي يحتوي على السطر مع فحص USB - android.hardware.usb.action.USB_STATE. بعد ذلك ، في كود smali ، نقوم بتعديل الخط إلى أي أذونات أخرى تُرجع "false" (انظر الشكل 10).


التين. 9. تحقق من وجود اتصال USB في كود MainActivity.java


التين. 10. سطر الكود المراد حذفه من MainActivity.smali

الآن يبقى إنشاء مفتاح الإصدار الخاص بك وتوقيع التطبيق معه. يتم ذلك على النحو التالي:

  1. تحتاج إلى تثبيت تطبيقين: Keytool و Jarsinger.
  2. قم بتشغيل الأمر لتجميع التطبيق:
  3. apktool ب C: \ Users \ User \ Desktop \ ********
  4. التالي: cd ******** \ dist \
  5. التالي: Keytool.exe -genkey -alias key.keystore -keyalg RSA -validity 20000 -keystore key.keystore
  6. التالي: Jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore key.keystore ********. Apk key.keystore
  7. التالي: jarsigner -verify -verbose -certs ********. APK

هنا ، من حيث المبدأ ، تم الانتهاء من جميع التلاعبات. الآن نقوم بتثبيت التطبيق على الهاتف باستخدام تثبيت ADB أو من دليل الهاتف الذكي ويمكنك إجراء اختبار الثغرة الديناميكية.

بعد تثبيت التطبيق ، قم بتشغيله (انظر الشكل 11 والشكل 12).

التين. 11. قم بتشغيل وضع المطور وتوصيل USBالتين. 12. إطلاق التطبيق

الاستنتاجات

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

ما يمكن أن يؤدي سلوك إهمال تجاه حماية التعليمات البرمجية إلى:

  • هذه هي التحايلات على بعض الشيكات المضمنة في البرنامج
  • تنفيذ كود الطرف الثالث ، وبعد ذلك يمكن نشر البرنامج واستخدامه كبرنامج ضار

كيف يمكنني حماية نفسي؟ في ByteCode ، قررنا عدم إعادة اختراع العجلة واقترح أن يقوم العميل بإخفاء شفرة المصدر واستخدام الوظائف التي تتحقق من تعديل شفرة المصدر.

ملاحظة

يمكنك استخدام طريقة تحليل أكثر تقدمًا - هذا هو تصحيح الأخطاء. يمكنك قراءة المزيد عن هذا في الدليل .

كمرجع قليل ، قمت بصياغة قائمة من الخطوط التي تستخدم للتحقق من الروتين:

  • "مفاتيح الاختبار" ؛
  • "/system/app/Superuser.apk" ؛
  • "/ sbin / su" ؛
  • "/ system / bin / su" ؛
  • "/ system / xbin / su" ؛
  • "/ data / local / xbin / su" ؛
  • "/ data / local / bin / su" ؛
  • "/ system / sd / xbin / su" ؛
  • "/ system / bin / failsafe / su" ؛
  • "/ data / local / su" ؛
  • "/ su / bin / su" ؛
  • "/ system / xbin / which" ؛
  • "Su" ؛
  • "أي".

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


All Articles