6 cara untuk menyembunyikan data di aplikasi Android

Hai, pembaca yang budiman, saya telah mempelajari beberapa aplikasi seluler cukup lama. Sebagian besar aplikasi tidak mencoba menyembunyikan fungsionalitas "rahasia" mereka dari saya. Dan saya senang saat ini, karena saya tidak harus mempelajari kode seseorang yang dikaburkan.


gambar


Dalam artikel ini, saya ingin berbagi visi kebingungan saya, serta berbicara tentang metode menarik menyembunyikan logika bisnis dalam aplikasi dengan NDK, yang saya temukan relatif baru-baru ini. Jadi jika Anda tertarik pada contoh langsung kode yang dikaburkan di Android - Saya minta kucing.


Di bawah kebingungan dalam kerangka artikel ini, kami memahami pengurangan kode yang dapat dieksekusi dari aplikasi Android ke bentuk yang sulit untuk dianalisis. Ada beberapa alasan untuk mempersulit analisis kode:


  1. Tidak ada bisnis yang ingin disodok dalam "bagian dalamnya".
  2. Bahkan jika Anda memiliki aplikasi tiruan, Anda selalu dapat menemukan hal-hal menarik di sana (contoh dengan instagram ).

Banyak pengembang memecahkan masalah hanya dengan mengonfigurasi konfigurasi ProGuard. Ini bukan cara terbaik untuk melindungi data (jika ini adalah pertama kalinya Anda mendengar tentang ini, lihat wiki ).


Saya ingin memberikan contoh, mengapa dugaan “perlindungan” dengan ProGuard tidak berhasil. Ambil contoh sederhana dari Sampel Google.


gambar


Setelah menghubungkan ProGuard dengan konfigurasi standar untuk itu, kami mendapatkan kode yang didekompilasi:


gambar


“Ohhh, tidak ada yang jelas,” ucap kami dan tenang. Tetapi setelah beberapa menit beralih antar file, kami menemukan potongan kode yang serupa:


gambar


Dalam contoh ini, kode aplikasi tampak agak lemah (pendataan data, membuat tangkapan video), sehingga beberapa metode yang digunakan dalam kode asli mudah dipahami bahkan setelah diproses dengan konfigurasi ProGuard.


Selanjutnya, lihat kelas data di Kotlin. Kelas data default menciptakan metode "toString", yang berisi nama-nama variabel instan dan nama kelas itu sendiri.


Sumber data kelas:


gambar


Itu bisa berubah menjadi berita gembira untuk mundur:


gambar
(Pembuatan-otomatis metode toString di Kotlin)


Ternyata ProGuard menyembunyikan jauh dari semua kode sumber proyek.


Jika saya masih belum meyakinkan Anda tentang tidak perlunya melindungi kode dengan cara ini, maka mari kita coba untuk meninggalkan atribut ".source" di proyek kami.


-keepattributes SourceFile 

Baris ini ada di banyak proyek opensource. Ini memungkinkan Anda untuk melihat StackTrace ketika aplikasi mogok. Namun, dengan menarik ".source" dari kode smali, kami mendapatkan seluruh hierarki proyek dengan nama kelas penuh.


Menurut definisi, kebingungan adalah "membawa kode sumber ke dalam bentuk yang tidak dapat dibaca untuk menangkal berbagai jenis penerimaan". Namun, ProGuard (bila digunakan dengan konfigurasi standar) tidak membuat kode tidak dapat dibaca - ia berfungsi sebagai minifier, mengompresi nama dan membuang kelas tambahan dari proyek.


Penggunaan ProGuard seperti itu mudah, tetapi tidak sepenuhnya cocok untuk solusi kebingungan yang baik. Pengembang yang baik perlu membuat reseller (atau penyerang) merasa takut pada "karakter Cina," yang sulit untuk diobobekan.


Jika Anda tertarik untuk mempelajari lebih lanjut tentang ProGuard, maka saya mengusulkan artikel informatif berikut ini .


Apa yang kita sembunyikan


Sekarang mari kita lihat apa yang biasanya tersembunyi di aplikasi.


  • Kunci Enkripsi:

gambar


  • Logika aplikasi khusus:

gambar


Sesuatu yang lebih tak terduga seringkali dapat disembunyikan dalam kode (pengamatan dari pengalaman pribadi), misalnya:


  • Nama Pengembang Proyek
  • Jalan penuh ke proyek
  • Client_secret untuk protokol Oauth2
  • Buku PDF "Bagaimana cara mengembangkan untuk Android" (mungkin selalu ada)

Sekarang kita tahu apa yang bisa disembunyikan di aplikasi Android dan bisa beralih ke hal utama, yaitu cara menyembunyikan data ini.


Cara untuk menyembunyikan data


Opsi 1: Jangan menyembunyikan apa pun, biarkan semuanya terlihat


Dalam hal ini, saya hanya menunjukkan gambar ini :)


“Bantu Dasha menemukan logika bisnis”


gambar


Solusi hemat biaya dan sepenuhnya gratis ini cocok untuk:


  • Aplikasi sederhana yang tidak berinteraksi dengan jaringan dan tidak menyimpan informasi pengguna yang sensitif;
  • Aplikasi yang hanya menggunakan API publik.

Opsi 2: Gunakan ProGuard dengan pengaturan yang benar


Keputusan ini masih memiliki hak untuk hidup, karena, pertama-tama, itu sederhana dan gratis. Terlepas dari kerugian yang disebutkan di atas, ia memiliki nilai tambah yang signifikan: jika aturan ProGuard dikonfigurasikan dengan benar, aplikasi dapat benar-benar dikaburkan.


Namun, Anda perlu memahami bahwa solusi seperti itu setelah setiap perakitan mengharuskan pengembang untuk mendekompilasi dan memeriksa apakah semuanya baik-baik saja. Setelah menghabiskan beberapa menit mempelajari file APK, pengembang (dan perusahaannya) dapat menjadi lebih percaya diri dalam keamanan produk mereka.


Cara mempelajari file APK

Memeriksa aplikasi untuk kebingungan cukup sederhana.


Untuk mendapatkan file APK dari proyek, ada beberapa cara:


  • ambil dari direktori proyek (di Android Studio, biasanya nama foldernya adalah "build");
  • instal aplikasi pada ponsel cerdas Anda dan dapatkan APK menggunakan aplikasi "Apk Extractor".

Setelah itu, menggunakan utilitas Apktool, kita mendapatkan kode Smali (instruksi untuk sampai di sini https://ibotpeaches.imtqy.com/Apktool/documentation ) dan mencoba menemukan sesuatu yang mencurigakan dibaca di baris proyek. Ngomong-ngomong, untuk mencari kode yang dapat dibaca, Anda dapat menyimpan dengan perintah bash yang sudah dibuat sebelumnya.


Solusi ini cocok untuk:


  • Aplikasi mainan, aplikasi toko online, dll;
  • Aplikasi yang benar-benar tipis, dan semua data datang secara eksklusif dari sisi server;
  • Aplikasi yang tidak menulis di semua spanduk mereka "Aplikasi Aman No. 1".

Opsi 3: Gunakan Obfuscator Sumber Terbuka


Sayangnya, saya tidak tahu obfuscator gratis yang sangat bagus untuk aplikasi seluler. Dan obfuscator yang dapat ditemukan di jaringan dapat membawa Anda banyak sakit kepala, karena akan terlalu sulit untuk merakit proyek semacam itu untuk versi baru API.


Secara historis, obfuscator keren yang ada dibuat di bawah kode mesin (untuk C / C ++). Contoh yang bagus:



Misalnya, Movfuscator mengganti semua opcode dengan movs, membuat kode linier, menghapus semua cabang. Namun, sangat dianjurkan untuk menggunakan metode kebingungan ini dalam proyek pertempuran, karena dengan demikian kode berisiko menjadi sangat lambat dan berat.


Solusi ini cocok untuk aplikasi yang bagian utamanya adalah NDK.


Opsi 4: Gunakan solusi berpemilik


Ini adalah pilihan paling kompeten untuk aplikasi serius, sebagai perangkat lunak berpemilik:
a) didukung;
b) akan selalu relevan.


Contoh kode yang dikaburkan ketika menggunakan solusi tersebut:


gambar


Dalam cuplikan kode ini Anda dapat melihat:


  1. Nama-nama variabel yang paling tidak bisa dipahami (dengan kehadiran huruf Rusia);
  2. Karakter Cina di baris yang tidak memperjelas apa yang sebenarnya terjadi dalam proyek;
  3. Ada banyak jebakan yang ditambahkan ke proyek ("switch", "goto"), yang sangat mengubah alur kode aplikasi.

Solusi ini cocok untuk:


  • Bank
  • Perusahaan asuransi;
  • Operator seluler, aplikasi penyimpanan kata sandi, dll.

Opsi 5: Gunakan React-Native


Saya memutuskan untuk menyoroti hal ini, karena menulis aplikasi lintas platform kini menjadi kegiatan yang sangat populer.


Selain komunitas yang sangat besar, JS memiliki sejumlah besar obfuscator terbuka. Misalnya, mereka dapat mengubah aplikasi Anda menjadi emotikon:


gambar


Saya benar-benar ingin menyarankan Anda tentang solusi ini, tetapi kemudian proyek Anda akan bekerja lebih cepat daripada kura-kura.


Tetapi dengan mengurangi persyaratan untuk kebingungan kode, kita dapat membuat proyek yang benar-benar terlindungi dengan baik. Jadi google "js obfuscator" dan mengaburkan file output bundle kami.


Solusi ini cocok untuk mereka yang siap menulis aplikasi lintas platform di React Native.


Xamarin

Akan sangat menarik untuk mengetahui tentang obfuscator di Xamarin, jika Anda memiliki pengalaman menggunakannya, silakan beri tahu kami tentang hal itu di komentar.


Opsi 6: Gunakan NDK


Saya sendiri sering harus menggunakan NDK dalam kode saya. Dan saya tahu bahwa beberapa pengembang percaya bahwa menggunakan NDK menyimpan aplikasi mereka dari pembalik. Ini tidak sepenuhnya benar. Pertama, Anda perlu memahami bagaimana persembunyian bekerja dengan NDK.


gambar


Ternyata sangat sederhana. Ada beberapa konvensi JNI dalam kode bahwa ketika Anda memanggil kode C / C ++ dalam suatu proyek, itu akan dikonversi sebagai berikut.


NativeSummator Native Class:


gambar


Penerapan metode penjumlahan asli:


gambar


Penerapan metode jumlah statis asli:


gambar


Menjadi jelas bahwa untuk memanggil metode asli, Anda menggunakan Java_<package name>_<Static?><class>_<method> fungsi pencarian di perpustakaan dinamis.


Jika Anda melihat kode Dalvik / ART, kami akan menemukan baris berikut:


gambar


( sumber )


Pertama, kita akan menghasilkan baris berikut Java_<package name>_<class>_<method> dari objek Java, dan kemudian mencoba menyelesaikan metode di perpustakaan dinamis menggunakan panggilan "dlsym", yang akan mencoba menemukan fungsi yang kita butuhkan di NDK.


Beginilah cara kerja JNI. Masalah utamanya adalah dengan mendekompilasi pustaka dinamis, kita akan melihat semua metode dalam tampilan penuh:


gambar


Jadi, kita perlu menemukan solusi seperti itu sehingga alamat fungsi dikaburkan.


Pada awalnya saya mencoba menulis data langsung ke tabel JNI kami, tetapi saya menyadari bahwa mekanisme ASLR dan versi Android yang berbeda tidak akan memungkinkan saya untuk membuat metode ini bekerja pada semua perangkat. Kemudian saya memutuskan untuk mencari tahu metode apa yang disediakan NDK untuk pengembang.


Dan, lihatlah , ada metode "RegisterNatives" yang melakukan persis apa yang kita butuhkan (memanggil fungsi internal dvmRegisterJNIMethod ).


Kami mendefinisikan array yang menggambarkan metode asli kami:


gambar


Dan kami mendaftarkan metode yang kami nyatakan dalam fungsi JNI_OnLoad (metode ini dipanggil setelah pustaka dinamis diinisialisasi, ribuan ):


gambar


Hore, kita sendiri menyembunyikan fungsi "hideFunc". Sekarang terapkan obfuscator llvm favorit kami dan nikmati keamanan kode dalam bentuk akhirnya.


Solusi ini cocok untuk aplikasi yang sudah menggunakan NDK (menghubungkan NDK membawa banyak kesulitan ke proyek, sehingga solusi ini tidak begitu relevan untuk aplikasi non-NDK).


Kesimpulan


Bahkan, aplikasi tidak boleh menyimpan data sensitif apa pun, atau hanya dapat diakses setelah otentikasi pengguna. Namun, itu terjadi bahwa logika bisnis memaksa pengembang untuk menyimpan token, kunci, dan elemen spesifik dari kode logika di dalam aplikasi. Saya harap artikel ini akan membantu Anda jika Anda tidak ingin berbagi data sensitif seperti itu dan menjadi "buku terbuka" untuk juru tulis.


Saya percaya bahwa kebingungan adalah bagian struktural penting dari setiap aplikasi modern.


Pikirkan baik-baik tentang masalah penyembunyian kode dan jangan mencari cara yang mudah! :)


Omong-omong, terima kasih kepada pengguna miproblema untuk bantuan dalam beberapa masalah. Berlangganan saluran telegramnya, itu menarik di sana.


Dan juga banyak terima kasih kepada para pengguna sverkunchik dan SCaptainCAP untuk bantuan mereka dalam mengedit artikel.

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


All Articles