افزایش امنیت برنامه های اندروید با ProGuard و R8

افزایش امنیت برنامه های اندروید با Proguard و R8
اندروید

افزایش امنیت برنامه های اندروید با ProGuard و R8

امنیت کدها و تامین امنیت برنامه همواره یکی از اصلی‌ترین دغده‌های هر برنامه‌نویسی هستش.

قبل از اینکه سراغ تامین امنیت برنامه‌های خودتون برید، باید یک نکته خیلی مهمی رو بدونید.

امنیت هیچ چیزی رو نمیشه 100درصد تامین کرد.
طبیعتا اپلیکیشن هم از این قاعده مستثنا نیستش.

پس ما فقط می‌خوایم کاری کنیم که عملیات هک و کرک اپلیکیشن خودمون رو برای هکرها سخت‌تر کنیم.

طوری نباشه که خیلی راحت بتونن هکش کنن و به کدهای ما دسترسی داشته باشن.

با این مواردی که توی این پست توضیح میدم، عملیات هک شدن اپلیکیشن خودتون رو به شدت سخت‌تر می‌کنید.

تقریبا میشه گفتش که تا 90% میشه جلو هک رو گرفت.

اون 10% هم برای هکرهای واقعا حرفه‌ای هستش که هیچ چیزی جلودارشون نیست و نمیشه کنترلشون کرد.😉

در حوزه صعنت یک اصطلاحی هستش که بهش مهندسی معکوس یا Reverse Engineering میگن.

درواقع عملیات مربوط به مهندسی معکوس طوری هستش که میان کدهای ما رو باز میکنن و شروع میکنن به خوندن.

می‌بینن که ما چه کارهایی انجام دادیم، توسط همین کدها میتونن خیلی راحت به سیستم نفوذ کنن و به اطلاح باعث هک یا کرک شدن سیستم میشن.

برای اینکه کار رو برای مهندسین معکوس سخت‌تر و پیچیده‌تر کنیم باید کدهای خودمون رو طوری کنیم که موقع انتشار بهم ریخته بشن.

یعنی کسی نفهمه که ما چی نوشتیم.

مثلا بجای اینکه باید دقیقا کد ما رو نشون بده که ما چه کدی نوشتیم، بیاد کد نهایی ما رو تبدیل کنه به همچین چیزی👇👇

کد معمولیکد بهم ریخته شده
val name : String
p082x.p001h.p009a.C0320g

حتما روی تب کد بهم ریخته شده بزن تا نتیجه مورد نظر رو ببینی.

خب حالا که فرق جفتشون رو دیدی، میخوام خودت بهم بگی.

خوندون کدومش راحت‌تره؟

اصلا کی متوجه میشه که عبارت p082x.p001h.p009a.C0320g یعنی چی ؟!!

خب حالا که متوجه شدی هدفمون چیه، بهتره کم کم بریم سراغ اصل کاریا.

اندروید برای اینکار یه ابزار بسیار قدرتمندی داره، که بهش ProGuard میگن.

برای تامین امنیت کدها برنامه نویس ها همیشه ProGuard رو فعال میکردن، ولی 2 سالی هستش که گوگل یه امکان بهتر و مطمئن‌تری رو به نام R8 معرفی کرده.

درواقع میشه گفتش که R8 نسخه بهینه و بروزرسانی شده ProGuard برای امنیت هستش.

به این نوع عملیات و کارهایی که میخوایم انجام بدیم اطلاحا Obfuscation یا مبهم سازی کدها میگن.

البته ProGuard محدود به مبهم سازی کدها نمیشه و باعث کاهش حجم اپلیکیشن هم میشه.

طوری که حجم 15مگابایت رو حتی به 11 مگابایت هم میتونه کاهش بده.🤩

ProGuard چیه؟

پروگارد باعث مبهم شدن کد و کاهش حجم اپلیکیشن میشه.

پروگارد به صورت پیشفرض توی Gradle اپلیکیشن وجود داره و نیازی به نصب کردن هیچ چیزی نیستش.

وظایف ProGuard چیه؟
  • مبهم سازی کدها : این قابلیت برای ناخوانایی کدها بسیار اهمیت داره. درواقع میاد کدهایی که نوشتیم رو به کاراکترهایی تبدیل می‌کنه که قابل فهم نیستش. درست مثل مثال بالا.
  • کاهش حجم برنامه : ممکنه توی پروژه خودتون کلی متد، کلاس، کتابخونه و … داشته باشید که ازش استفاده‌ای نکردید و فراموش کردید که پاکشون کنید. پروگارد این کار رو هم میکنه و چیزایی که ازشون استفاده نکردید رو پاک میکنه.
  • بهینه سازی کد : توی این بخش پروگارد میاد کدهای شما رو یکبار بازنگری میکنه، اگه از کدهایی استفاده کردید که بهینه نیستش، کلی فضای خالی برای کدتون ایجاد کردید و … همه اینارو میاد مرتب میکنه.
چطور از ProGuard استفاده کنم؟

برای فعال کردن پروگارد و تامین امنیت باید وارد فایل app/build.gradle بشی.

بعد که وارد این فایل شدی، بلاک buildTypes رو پیدا کن.

کدی شبیه به کد زیر رو میتونی ببینی

buildTypes {
    release {
        minifyEnabled false
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
}

اگه به کد بالا توجه کنی یه عبارتی رو میبینی که جلوش false نوشته.

منظورم minifyEnabled هستش.

برای فعال کردن پروگارد فقط باید مقدار minifyEnabled رو به true تغییر بدی.

مثل کد زیر :

buildTypes {
    release {
        minifyEnabled true
        proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    }
}

خب حالا نوبت این رسیده که پروژه رو sync کنی.

تبریک میگم، پروژه شما امن شد😊

ولی خب عجله نکن تامین امنیت اینقدرها هم راحت نیست و فعلا کلی کار داریم😀

توی پروژه ممکنه که از کتابخونه‌های متفاوتی استفاده کرده باشی.

کتابخونه‌هایی مثل : RetrofitDaggerGlideRoom  و …

اگه به توضیحات بالا خوب توجه کرده باشی، گفتم که پروگارد میاد کدها رو بهم میریزه که باعث ناخوانی کدها میشه و اینطوری امنیت خوندن شدن کدهای شما رو بالاتر میبره.

ممکنه این کتابخونه‌هایی که استفاده کردی بخشی از کلاس یا کدشون نباید بهم بریزه.

چون اگه بهم بریزه اصلا درست کار نمیکنه و برنامه شما کلا با مشکل روبرو میشه!

خب اینجور مواقع باید چیکار کرد؟!

باید بیایم و برای پروگارد، قوانین مخصوصی رو بنویسیم.

برای اینکه بتونی واسه پروگارد قوانین مخصوصی رو بنویسی باید وارد فایل proguard-rules.pro بشی.

توی این فایل یکسری کدها به صورت راهنما وجود دارن که توضیح میدن چطور میشه از این بخش استفاده کرد.

کدها تقریبا شبیه به زیر هستن :

# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

این کدها همگی کامنت شدن و موقع کامپایل گرفتن هیچ تاثیری روی پروژه نمیزارن. پس میتونی پاکشون کنی.

و اما چطور میشه این قوانین رو برای کتابخونه موردنظر پیدا کرد؟

برای اینکار باید وارد صفحه داکیومنت اون کتابخونه بشی و دنبال عبارتی مثل Proguard rules یا هرچیزی شبیه به این بگردی و پیداش کنی.

مثلا من میخوام قوانین پروگارد مربوط به Retrofit رو پیدا کنم.

اول رفتم توی صفحه مربوط به کتابخونه Retrofit توی گیتهات و سپس قوانین مروبط به پروگارد رو پیدا کردم.

بعد اینکه قوانین پروگارد اون کتابخونه رو پیدا کردی، اون رو باید توی فایل proguard-rules.pro قرار بدی.

مثل کد زیر :

# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and
# EnclosingMethod is required to use InnerClasses.
-keepattributes Signature, InnerClasses, EnclosingMethod

# Retrofit does reflection on method and parameter annotations.
-keepattributes RuntimeVisibleAnnotations, RuntimeVisibleParameterAnnotations

# Retain service method parameters when optimizing.
-keepclassmembers,allowshrinking,allowobfuscation interface * {
    @retrofit2.http.* <methods>;
}

# Ignore annotation used for build tooling.
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement

# Ignore JSR 305 annotations for embedding nullability information.
-dontwarn javax.annotation.**

# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
-dontwarn kotlin.Unit

# Top-level functions that can only be used by Kotlin.
-dontwarn retrofit2.KotlinExtensions
-dontwarn retrofit2.KotlinExtensions$*

# With R8 full mode, it sees no subtypes of Retrofit interfaces since they are created with a Proxy
# and replaces all potential values with null. Explicitly keeping the interfaces prevents this.
-if interface * { @retrofit2.http.* <methods>; }
-keep,allowobfuscation interface <1>

همینطور باید ادامه بدی و قوانین پروگارد همه کتابخونه‌ها رو توی فایل بالایی قرار بدی.

اگه به بلاک buildTypes توجه کنی میبینی که داخل این بلاک، یه بلاک دیگه‌ای هم با عنوان release هستش. این یعنی قوانین مربوط به پروگارد فقط موقع خروجی گرفتن به صورت release کار میکنه.
اگه میخوای موقع develop کردن هم قوانین پروگارد اعمال بشه میتونی بلاک debug رو هم به بلاک buildTypes اضافه کنی.

خب، امیدوارم که با پروگارد کامل آشنا شده باشید.

حالا که پروگارد رو توضیح دادم، بهتره که بریم سمت R8.

R8 چیه ؟

R8 از نسخه 3.4 اندرویداستدیو اضافه شد و یه جورایی جایگرین ProGuard شد.

R8 به نسبت ProGuard سرعت بیشتری داره و کدها رو بهتر بهینه میکنه و باعث کاهش چشمگیر حجم برنامه هم میشه.

حجم اپکیلیشن به طور معمول حجم اپلیکیشن بعد از پروگارد حجم اپلیکیشن بعد از R8
15 مگابایت 11 مگابایت 8 مگابایت
مقایسه ProGuard با R8 :

بهتره که تفاوت‌های این دو رو به لحاظ فنی و دقیق برای شما توضیح بدم، تا درک بهتری از تصمیم گوگل برای جایگزینی R8 داشته باشید.

البته شاید عنوان مقایسه خیلی برای این قسمت درست نباشه ولی می‌خوام تاریخچه اینکه چرا به مرور توسعه دهنده‌های گوگل R8 رو جایگزین ProGuard کردن توضیح بدم.

در گذشته روش کار به اینصورت بود که کامپایلر جاوا، سورس کدهای جاوای پروژه اندروید رو به بایت کد (Bytecode) های جاوا تبدیل می‌کرد.

سپس این بایت کدها توسط ProGuard بهینه شده و بایت کدهای بهینه‌ای ایجاد می‌شد که سریعتر و کم حجم تر بودند.

در نهایت، کامپایلر DX این بایت کدها رو به بایت کدهای ویژه ماشین مجازی دالویک (Dalvik) تبدیل می‌کرد.

افزایش امنیت برنامه های اندروید با ProGuard و R8
کامپایلر Dex

این بایت کدها که با فرمت .dex توی پکیج فایل نصبی APK نگهداری میشن، بسته به نسخه سیستم عامل اندروید دستگاه کاربر، توسط ماشین مجازی (Dalvik یا ART) و یا ترکیبی از جفتش (مثل Android P) به زبان قابل فهم واسه ماشین ترجمه میشه.

فایل dex چیه
قبلا راجب فایل dex توضیح دادم. اگه میخوای بیشتر بدونی به این لینک مراجعه کن

این فرآیند نسبتا زمانبر بود و توی سال ۲۰۱۵ تیم توسعه اندروید تصمیم گرفت که کامپایلر جدیدی رو جایگزین قبلی بکنه تا مراحل کامپایل کاهش پیدا کنه.

بنابراین کامپایلری با نام Jack & Jill معرفی شد.

افزایش امنیت برنامه های اندروید با ProGuard و R8
کامپایلر Jack & Jill

در واقع این کامپایلر ترکیبی از کامپایلر جاوا، پروگارد و کامپایلر Dalvik بود و دستورات و توابع هرسه توی یک مرحله انجام می‌شد که نتیجه اون افزایش سرعت کامپایل پروژه اندرویدی بود.

اما Jack & Jill هم خالی از ایراد نبود و در تعامل با بعضی بایت کدهای Java مشکلاتی داشت.

به همین دلیل تیم توسعه اندروید این کامپایلر رو در سال ۲۰۱۷ کنار گذاشت.

سپس کامپایلر دیگه‌ای با اسم D8 جایگزین شد که از حیث تعداد مراحل تفاوتی با حالت اول نداشت و صرفا در مرحله آخر، D8 جایگزین DX شده بود.

افزایش امنیت برنامه های اندروید با ProGuard و R8
کامپایلر D8

کامپایلر D8 سازگاری بیشتر بخصوص با کاتلین داشت.

علاوه بر اون بایت کدهای کمتر و بهینه تری رو هم تولید میکرد.

در نهایت R8 معرفی شد که از ادغام ProGuard و D8 بوجود آمده است.

افزایش امنیت برنامه های اندروید با ProGuard و R8
کامپایلر R8

الان بایت کدهای جاوا مستقیما توسط کامپایلر R8 به بایت کدهای بهینه دالویک تبدیل میشن.

مزایای کامپایلر R8

این مواردی که این پایین میخوام بگم، جز مهمترین دلایلی هستش که باعث شد، گوگل R8 رو جایگزین ProGuard کنه.

  • بهینه سازی بیشتر: R8 در مقایسه با ProGuard بهینه سازی بیشتر و عمیق‌تری انجام میده که نتیجه اون، فشرده شدن بیشتر نسخه خروجی یعنی فایل APK هستش.بر اساس تست‌هایی که انجام شده R8 حتی میتونه تا ۷۰ درصد از حجم برنامه رو نسبت به حالت عادی فشرده‌تر کنه که یک خروجی فوق العاده به حساب می‌آید.
  • سازگاری بیشتر با Kotlin: با پشتیبانی رسمی اندروید استودیو از زبان کاتلین در نسخه‌های جدید، کامپایلر باید از کاتلین به طور کامل پشتیبانی میکرد. R8 این ویژگی رو داره و توی بهینه کردن کدهایی که به زبان کاتلین نوشته شده‌اند بازدهی بالاتری نسبت به پروگارد دارد.
  • خروجی بهتر: R8 خروجی بهتری نسبت به پروگارد به ما تحویل میده. علاوه بر اون، سرعت بیلد شدن پروژه نیز به نسبت قبل مقداری کاهش پیدا کرده.
فعال سازی R8 :

فعالسازی این بخش هیچ فرقی با پروگارد نمیکنه. شما اگه minifyEnabled رو true کنی R8 هم فعال میشه.

اگه نسخه اندرویداستدیو که داری زیر 4 هستش برای فعال کردن R8 باید توی فایل gradle.properties کد زیر رو هم اضافه کنی.
کد : android.enableR8=true
اگه نسخه اندرویداستدیو بالای 4 هستش که نمیخواد کاری بکنی خودش فعال میشه
حداکثر فشرده سازی با R8

اگه فکر کردی که R8 تا همینقدر بسنده کرده که باید بگم سخت در اشتباهی😀

R8 یه قابلتی داره که به طرز شگفت‌انگیزی باعث کاهش حجم میشه.

اگه میخوای از این قابلیت استفاده کنی باید کد زیر رو توی فایل gradle.properties اضافه کنی

android.enableR8.fullMode=true

با اضافه کردن این تکه کد، از حداکثر توان R8 میشه استفاده کرد.

نوشتن قوانین دلخواه برای ProGuard  و R8

بعضی مواقع پیش میاد که برای تامین امنیت نیاز داریم خودمون یکسری قوانینی رو برای ProGuard  و R8 بنویسیم.

مخصوصا زمانی که پروژه بزرگی داریم و خودمون یکسری از Custom viewها ایجاد کردیم.

با کمک کدهای زیر میتونی برای پروژه خودت یکسری قوانین مخصوصی رو بنویسی و ازشون استفاده کنی.

کدهای زیر همه کدهای مربوط به قوانین نویسی نیستن و کلی کد دیگه‌ای هم وجود دارن. کدهای زیر درواقع مهمترین این کدها هستن.

-keepattributes : مواردی که توسط این قانون تعریف شوند بدون تغییر باقی میمونن.

-keep : توسط این دستور میتونیم یک کلاس، متدها و فیلدهای داخلی رو به عنوان استثناء تعریف کنیم تا عملکردهای R8 روی اون پیاده نشه.

-keepclassmembers : متدها و فیلدهای موردنظر داخل یک کلاس رو میشه به عنوان استثناء تعریف کرد.

-keepnames : از تغییر نام کلاس یا متدها و فیلدهای مدنظر جلوگیری میکنه.

-dontwarn : تعیین میکنه که هیچگونه هشداری در مورد ارجاعاتی (References) که در کلاس مدنظر ذکر شده و ProGuard/R8 نتونسته که اونارو پیدا، ازشون عبور کنه و خطایی نشون نده.

-dontshrink : این قانون، قابلیت Shrink یعنی حذف آیتم‌های بلا استفاده رو غیر فعال می‌کنه و صرفا دو عمل دیگه یعنی بهینه سازی (Optimization) و مبهم سازی (Obfuscation) رو برای اون انجام می‌شود.

-dontoptimize : مانند مورد قبل با این تفاوت که فقط عمل بهینه سازی انجام نمیشه.

صفحه اصلی قوانین پروگارد
اگه راجب قوانین ProGuard و R8 میخوای بیشتر بدونی به این لینک میتونی مراجعه کنی.

دیدگاه خود را اینجا قرار دهید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

فیلدهای نمایش داده شده را انتخاب کنید. دیگران مخفی خواهند شد. برای تنظیم مجدد سفارش ، بکشید و رها کنید.
  • عکس
  • شناسه محصول
  • امتیاز
  • قیمت
  • در انبار
  • موجودی
  • افزودن به سبد خرید
  • توضیحات
  • محتوا
  • عرض
  • اندازه
  • تنظیمات بیشتر
  • ویژگی ها
  • Custom attributes
  • زمینه های دلخواه
مقایسه
لیست علاقه مندی ها 0