2012-11-13

Obfuskera Androidapp

Den Androidapp jag ska obfuskera är MantisDroid och den består av ett library (MantisDroidLibrary) och 2 appar: en gratisversion (MantisDroid Free) och en betalversion (MantisDroid).
Jag använder ProGuard för obfuskering och optimering. Det verktyget följer med Android SDK:n.

Först måste konfigurationsfilerna för ProGuard rättas till. I foldern <android-sdk>/tools/proguard/ ska filerna proguard-android.txt och proguard-android-optimize.txt editeras:
#-keep public class com.google.vending.licensing.ILicensingService
#-keep public class com.android.vending.licensing.ILicensingService
Dvs. kommentera bort de 2 raderna eftersom de annars ger fel i obfuskeringen.

Jag använder Ant för att bygga mina projekt så om du inte redan gjort det så kör följande kommando i din projektkatalog:
android update project -p .
Den skapar upp bland annat build.xml och lite andra filer som behövs.

Börja med projektet MantisDroidLibrary.
Den ska inte obfuskeras i sitt projekt utan gör det när apparna byggs och obfuskeras.
Se till att obfuskering inte är aktiverad genom att titta i project.properties och verifiera att direktivet proguard.config inte är aktiverad.

De två apparna har precis samma inställningar så gör samma sak i båda.
Öppna project.properties och kommentera fram följande för endast obfuskering:
proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
Om du vill ha både obfuskering och optimering så lägg till följande:
proguard.config=${sdk.dir}/tools/proguard/proguard-android-optimize.txt:proguard-project.txt

I filen proguard-project.txt i projekt så ska nu projektspecifika regler läggas till. Skapa filen om den inte redan finns.
I min skriver jag:
-dontwarn org.xmlpull.v1.**
-assumenosideeffects class android.util.Log {
    public static *** d(...);
    public static *** v(...);
}
-keep public class com.google.android.vending.licensing.ILicensingService

Den första regeln döljer alla varningar för klasser i paketet org.xmlpull.v1. Det gör jag eftersom det blir krockar mellan klasser i android.jar och ett library (ksoap2-android) som jag använder. I mitt fall är det ingen fara utan helt ok.
Den andra regeln är en optimeringsregel som ser till att optimera bort alla anrop till Log.d(...) och Log.v(...). Anledningen till det är att de loggningarna inte ska komma ut i mina apk:er eftersom de avslöjar vad olika delar av min kod gör. Samtidigt så ska inte debug- och verbose-loggning finnas ute i kundernas installationer.
Den tredje regeln är för att jag använder Google Play Licensing och inte vill att den ska optimeras bort.

För att signeringen ska fungera så behöver man fylla i key.store och key.alias i filen ant.properties:
key.store=mantisdroid_release_key.keystore
key.alias=mantisdroid

key.alias.password=[your_password]
key.store.password=[your_password]
Library-projektet behöver inte signeras så skriv inte någon key.store eller key.alias där.

Kompilera, obfuskera, optimera och signera sedan appen med Ant genom att köra (i projektets folder):
ant release

2012-11-07

MantisDroid v.1.1.1


MantisDroid har nu också uppdaterats till v.1.1.1.
Buggfix-release med samma ändringar som för MantisDroid Free:

-Development versions of MantisBT can now be used.
-QR codes now support other ports than port 80.

Anledningen till att den inte släpptes samtidigt som gratisversionen var för att projekthanteringen inte fungerade som den skulle. Det gick inte att skapa eller spara projekt. Orsaken till det var att ksoap2-android inte lyckades serialisera ArrayList. Vector går däremot bra. Förhoppningsvis går det att använda ArrayList i version 3.0 av ksoap2-android som dock endast har release candidates ute.

Ladda hem från Play Store: MantisDroid

2012-11-06

MantisDroid Free v.1.1.1

MantisDroid Free har uppdaterats till v.1.1.1.
Buggfix-release med följande ändringar:

-Development versions of MantisBT can now be used.
-QR codes now support other ports than port 80.

Ladda hem från Play Store: MantisDroid Free

MantisDroid (full version) will be updated to v.1.1.1 soon. Testing is not finished yet.

2012-11-02

Dekompilering av Android-appar

Först och främst skriver jag det här för att belysa den problematik som finns när det gäller apputveckling och hur lätt det är att kopiera appar och kringgå olika typer av skydd. Det är inte tänkt att vara en tutorial för hur man piratkopierar appar.
För att förhindra otillåten kopiering och användande av en app så går det att aktivera Google Play Licensing. Hur man implementerar det är upp till varje utvecklare, men lämpligt är att appen då och då kontrollerar mot Google Play om appen är installerad på korrekt sätt, dvs. genom Google Play och att eventuella avgifter är betalda. Om Google Play svarar att appen inte är licensierad så ber man användaren att köpa appen.

Problemet är att det ganska lätt går att dekompilera appen och ta bort licensieringskontrollen och sedan använda appen helt fritt.

Hur gör man det?
Skaffa först verktygen. Installera/packa upp på lämplig plats.
dex2jar: http://code.google.com/p/dex2jar/ - Läser dex-filer och skapar jar-filer.
JD-GUI: http://java.decompiler.free.fr/?q=jdgui - Grafiskt verktyg för att visa innehållet i .class-filer.

På Ubuntu kör jag följande kommando för att få ut en jar av en apk:
d2j-dex2jar.sh android-app.apk
Resultatet ut från den är filen android-app.jar

Starta JD-GUI och öppna android-app.jar.
Voila! All kod i klartext!

Härifrån är det lätt att ändra på det man behöver för att till exempel ta bort licensiering eller aktivera olika funktioner. Packa slutligen ihop appen och signera den. Sen är den klar att användas igen.

Hur gör man för att skydda sig från det här? Svaret heter obfuskering. Det gör koden väldigt mycket svårare att läsa eftersom de flesta namn översätts till enstaka bokstäver.
Här kan ni läsa om hur man obfuskerar med hjälp av ProGuard:
http://developer.android.com/tools/help/proguard.html

Obfuskering ger ett bra skydd, men ha ändå för vana att gå igenom den obfuskerade koden med JD-GUI och kontrollera känsliga punkter i koden och se till att det inte är för uppenbart vad som händer och hur man kan kringgå det. Alla klasser och metoder byter inte namn så det kan gå att luska ut hur det fungerar.
Det är viktigt att se till att loggning inte avslöjar vad som händer.
Ett enkelt och snabbt sätt är att låta ProGuard ta bort alla anrop till Log.d och Log.v med följande direktiv (observera att optimization måste vara påslagen):
-assumenosideeffects class android.util.Log {
    public static *** d(...);
    public static *** v(...);
}



Slutsats
Om du vill skydda din app så lägg in Google Play Licensing och obfuskera sedan all kod. Det viktigaste skyddet är ändå att du är medveten om problematiken och hur enkelt det är att titta i din kod, så kolla själv innan någon annan gör det.