Обфускација кода (Code Obfuscation) је процес претварања извршног кода у форму сложену за анализу и реверсе енгинееринг, уз очување потпуне функционалности апликације. Методе обфускације укључују преименовање класа и метода у бесмислене идентификаторе, замршавање тока контроле и шифровање стринг константи. Према Android Developers (2025), обфускација је стандардна фаза изградње продакшн верзија. Code Obfuscation отежава крађу интелектуалне својине и проналажење рањивости у апликацији.
Главне тачке
Обфускација кода (од лат. obfuscare — замрачити, замрсити) је намерно претварање изворног или међукода апликације у форму која максимално отежава његову анализу од стране човека или аутоматских алата за декомпилацију. Кључни захтев обфускације: након трансформације програм мора да задржи потпуну функционалну еквивалентност са оригиналном верзијом.
Потреба за обфускацијом настала је са порастом популарности језика са међурепрезентацијом (JVM бајт код, .NET IL, JavaScript). Такви језици се компилирају не у машински код, већ у међубајт код који се лако декомпилира назад у читљив изворни код. На пример, Java бајт код се декомпилира алатима JD-GUI или CFR практично без губитка информација, што чини интелектуалну својину рањивом.
У мобилном развоју, обфускација је постала обавезна фаза изградње продакшн верзија. Android користи ProGuard и R8 за Java/Kotlin код, iOS — компилатор LLVM са оптимизацијама и додатне алате попут SwiftShield. Чак и Flutter апликације могу бити обфусковане путем заставице --obfuscate при компилацији, која преименује Dart идентификаторе у насумичне знакове.
Постоје бројне методе обфускације које се деле у неколико категорија. Лексичка обфускација — преименовање класа, метода и поља у кратке бесмислене називе (a, b, c). Структурна обфускација — промена тока контроле, уметање мртвог кода, надувавање хијерархије наслеђивања. Заштита података — шифровање стринг константи, обфускација нумеричких литерала, разбијање низова.
Најраспрострањенија метода обфускације — замена значајних имена класа, метода и поља кратким идентификаторима. Као резултат, класа UserAuthenticationService постаје класа a, метод validateLoginCredentials — метод a(Bundle). Ово не мења понашање програма, али чини декомпилирани код практично нечитљивим. Пројекат са 1000 класа може бити компримован у неколико стотина знакова заједничких идентификатора.
Важно ограничење: преименовање не сме да утиче на јавне API — методе позиване путем reflection, Binding (DataBinding, ViewBinding), серијализацију (Gson, Kotlinx Serialization) и JNI функције. За ове случајеве у ProGuard-у се користе правила -keep која експлицитно забрањују преименовање одређених класа и метода.
Control Flow Obfuscation (CFO) — метода која мења структуру програма без промене резултата. Компилатор убацује фиктивне условне скокове који се увек извршавају исто, дуплира блокове кода са истом семантиком, претвара линеарне секвенце позива у рекурзивне или цикличне конструкције. Ово јако отежава статичку анализу кода.
Неки алати, попут Obfuscator-LLVM, имплементирају напредну CFO на нивоу међурепрезентације LLVM IR. Они разбијају основне блокове на мале фрагменте, мешају их и повезују путем безусловних скокова (goto). Као резултат, граф тока контроле постаје лавиринт који се не може обновити без извршења кода.
Стринг константе су најинформативнији елемент декомпилираног кода. URL-ови API-ја, API кључеви, SQL упити, поруке о грешкама — све је то у отвореном облику присутно у бајт коду. Шифровање стрингова замењује све стринг константе шифрованим секвенцама које се дешифрују у runtime при првом приступу.
// Изворни код пре обфускације
String apiUrl = "https://api.example.com/v2/users";
String apiKey = "sk_live_abc123def456";
// Након обфускације стрингова (декомпилирани приказ)
String apiUrl = decrypt("x9K2pQ7mR4");
String apiKey = decrypt("z3F8nL1tV6");
// Метод децрипт дешифрује стринг у рунтиме-у
String decrypt(String encoded) {
return new String(xorDecode(base64Decode(encoded)), StandardCharsets.UTF_8);
}
ProGuard је класични алат за компресију, оптимизацију и обфускацију Java/Kotlin бајт кода, интегрисан у Android SDK. Од 2018. године Google препоручује коришћење R8 — продуктивније замене за ProGuard која обавља исте функције брже и са бољом оптимизацијом. R8 је подразумевано укључен у Android Gradle Plugin од верзије 3.4.0.
Конфигурација обфускације се дефинише кроз ProGuard Rules — текстуалну датотеку са скупом правила. Правила одређују које класе и методе треба сачувати (-keep), које се могу преименовати (-obfuscate) и које треба уклонити (-dontwarn). proguard-rules.pro — стандардна локација датотеке правила у Android пројекту.
// proguard-rules.pro — основна правила за Android
// Сачувати класе које се користе путем рефлецтион
-keep class com.example.models.** { *; }
// Сачувати класе које се серијализују путем Gson
-keepattributes Signature
-keepattributes *Annotation*
-keep class com.google.gson.** { *; }
// Не обфусковати JNI методе
-keepclasseswithmembernames class * {
native <methods>;
}
// Сачувати Activity (улазне тачке)
-keep class * extends android.app.Activity
Важно је разумети разлику између minifyEnabled и обфускације. Заставица minifyEnabled true у build.gradle укључује компресију (уклањање некоришћеног кода). Заставица proguardFiles указује на датотеку правила. За укључивање обфускације додатно се наводи useProguard true или се користи R8 где је обфускација подразумевано укључена уз minifyEnabled.
Приликом обфускације R8/ProGuard генерише mapping.txt — датотеку подударања између обфускованих и оригиналних имена. Ова датотека је критична за анализу crash логова: без ње стек траце садржи само имена попут a.b.c() што је немогуће читати. Mapping датотека мора бити сачувана за свако релеасе издање и отпремљена у Google Play Console или Sentry.
// build.gradle — подешавање обфускације за Android
android {
buildTypes {
release {
minifyEnabled true
shrinkResources true
proguardFiles getDefaultProguardFile(
'proguard-android-optimize.txt'
), 'proguard-rules.pro'
}
}
}
У iOS екосистему, обфускација је мање распрострањена него у Android-у, јер компилатор LLVM за Swift и Objective-C обавља низ оптимизација које делимично отежавају реверсе енгинееринг. Међутим, потпуна обфускација iOS апликација је такође могућа. SwiftShield је популарни алат који преименује Swift и Objective-C симболе у насумичне стрингове у фази компилације.
SwiftShield ради као пост-компилациони алат: анализира бинарну Mach-O датотеку и замењује све симболе апликације (класе, протоколе, методе) обфускованим именима. Важно је да SwiftShield не дира симболе системских библиотека и јавног API-ја, чувајући компатибилност са App Store. За Objective-C могуће је коришћење компилатора LLVM са додатним заставицама обфускације.
Obfuscator-LLVM — форк компилатора LLVM са додатним пролазима обфускације: замршавање тока контроле, шифровање стрингова и уметање мртвог кода. Подржава C, C++, Objective-C и Swift, али захтева изградњу сопствене верзије компилатора. Овај приступ је најефикаснији, али сложен у подешавању и интеграцији са CI/CD пајплајном.
Flutter SDK пружа уграђену подршку за обфускацију путем заставице --obfuscate при компилацији релеасе верзије. Ова заставица преименује идентификаторе Dart кода користећи насумичне знакове, слично ProGuard-у. За додатну заштиту, може се комбиновати Flutter обфускација са обфускацијом нативног кода кроз R8 (Android) или SwiftShield (iOS).
React Native апликације се обфускују на нивоу JavaScript бандла. Алат javascript-obfuscator (или JScrambler) трансформише JS код: мења имена променљивих, шифрује стрингове, убацује фиктивни код. Након обфускације, величина бандла се повећава за 50–100%, али анализа кода се знатно компликује. На нивоу нативних омотача такође се примењују стандардни алати Android и iOS.
Обфускација обезбеђује заштиту интелектуалне својине — копирање алгоритама и пословне логике постаје економски неисплативо због времена утрошеног на деобфускацију. Ово смањује ризик појаве клонова апликације у незваничним продавницама и штити јединствене алгоритме, на пример, у апликацијама за обраду слика, системима препорука или криптовалутним новчаницима.
Важна предност — заштита од аутоматске анализе. Многи алати статичке анализе које користе нападачи за проналажење рањивости (стрингови повезивања са базом података, API кључеви, тајни ендпоинти) губе ефикасност након обфускације. Алати морају да извршавају код (динамичка анализа), што је за ред величине теже од статичке анализе.
Прво ограничење — обфускација није шифровање. Код остаје читљив за процесор и може бити анализиран у runtime путем дебагера (LLDB, Frida) и трасера. Обфускација само отежава реверсе енгинееринг, али га не чини немогућим уз довољно времена и ресурса нападача.
Друго ограничење — утицај на перформансе. Неке методе обфускације (замршавање тока контроле, шифровање стрингова) додају додатне трошкове у runtime. Агресивна обфускација може повећати време покретања за 10–30% и величину бинарне датотеке за 50–200%. Стога избор метода мора бити уравнотежен: заштита не сме да учини апликацију неприхватљиво спором.
Треће ограничење — компатибилност са алатима. Обфускација може пореметити рад система за пријављивање грешака (Firebase Crashlytics, Sentry) ако се не подесе mapping датотеке. Библиотеке засноване на reflection-у (Dagger/Hilt, Retrofit, Gson) захтевају експлицитна правила чувања. R8 и ProGuard се редовно ажурирају, али грешке у конфигурацији могу довести до уклањања коришћеног кода.
Често постављана питања
Обфускација — претварање читљивог кода у замршени код који ради исто, али га је тешко анализирати. Имена класа и метода се замењују бесмисленим скуповима знакова.
У build.gradle подесите minifyEnabled true и наведите proguardFiles за релеасе компилацију. R8 је подразумевано укључен и аутоматски врши компресију, оптимизацију и обфускацију.
R8 — модернија и бржа замена за ProGuard од Google-а. R8 обавља исте функције (компресија, оптимизација, обфускација), али је дубље интегрисан у Android Gradle Plugin и ради ефикасније.
Mapping.txt — датотека подударања између обфускованих и оригиналних имена класа и метода. Неопходна за деобфускацију crash логова и анализу релеасе издања.
Користите ProGuard/R8 са заставицом -obfuscate-strings (Android) или алате за шифровање стрингова у фази компилације. За iOS примените SwiftShield или Obfuscator-LLVM са пролазом за шифровање константи.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође