Wednesday, June 8, 2011

anti-tampering with crc check

one way an app will try to detect if it has been tampered with is to look at classes.dex inside the apk. just so you know, java code is compiled to java .class files, which is then transformed by dx into classes.dex. this one file contains all the compiled code of an app. once the code is finished and the app is ready to be published, properties of the file such as the size or crc (cyclic redundancy check) can be determined and then stored inside the resources of the app.

when the app runs, it can compare the stored values with the actual values of the classes.dex file. if they do not match, then the code was likely tampered with.

note that we're using zipentry here, but we could also use jarentry and jarfile. you can't simply look for getCrc() and feel safe either, because the method could be called with reflection.

here's what a crc check may look like in java:
private void crcTest() throws IOException {
boolean modified = false;

// required dex crc value stored as a text string.
// it could be any invisible layout element
long dexCrc = Long.parseLong(Main.MyContext.getString(R.string.dex_crc));

ZipFile zf = new ZipFile(Main.MyContext.getPackageCodePath());
ZipEntry ze = zf.getEntry("classes.dex");

if ( ze.getCrc() != dexCrc ) {
// dex has been modified
modified = true;
}
else {
// dex not tampered with
modified = false;
}
}

and here's the above code translated into smali:
.method private crcTest()V
.locals 7
.annotation system Ldalvik/annotation/Throws;
value = {
Ljava/io/IOException;
}
.end annotation

.prologue
.line 599
const/4 v2, 0x0

.line 602
# modified will be set to true if classes.dex crc is not what it should be
.local v2, modified:Z
sget-object v5, Lcom/lohan/testtarget/Main;->MyContext:Landroid/content/Context;

# get the crc value from string resources
const v6, 0x7f040002
invoke-virtual {v5, v6}, Landroid/content/Context;->getString(I)Ljava/lang/String;
move-result-object v5

# convert it to a long since ZipEntry.getCrc gives us long
invoke-static {v5}, Ljava/lang/Long;->parseLong(Ljava/lang/String;)J
move-result-wide v0

.line 604
.local v0, dexCrc:J
new-instance v4, Ljava/util/zip/ZipFile;

sget-object v5, Lcom/lohan/testtarget/Main;->MyContext:Landroid/content/Context;

# get the path to the apk on the system
invoke-virtual {v5}, Landroid/content/Context;->getPackageCodePath()Ljava/lang/String;
move-result-object v5

invoke-direct {v4, v5}, Ljava/util/zip/ZipFile;->(Ljava/lang/String;)V

.line 605
.local v4, zf:Ljava/util/zip/ZipFile;
# get classes.dex entry from our apk
const-string v5, "classes.dex"
invoke-virtual {v4, v5}, Ljava/util/zip/ZipFile;->getEntry(Ljava/lang/String;)Ljava/util/zip/ZipEntry;
move-result-object v3

.line 607
.local v3, ze:Ljava/util/zip/ZipEntry;
# you could crack here by providing v5 with the correct
# long value. this may be easier if later logic is convoluted
# or if the result is stored in a class variable and acted
# on later. you can write your own java program to get the
    # correct value. 
    invoke-virtual {v3}, Ljava/util/zip/ZipEntry;->getCrc()J
move-result-wide v5

# compare v5 (actual crc) with v0 (stored crc)
cmp-long v5, v5, v0

# if v5 is 0, meaning cmp-long reports values are NOT the same
# goto :cond_0. this is where this could be cracked.
# could simply remove this line, in this case.
if-eqz v5, :cond_0

.line 609
# otherwise store true in v2.
# normally there will be code to act on the value of v2.
const/4 v2, 0x1

.line 615
:goto_0
return-void

.line 613
:cond_0
# store false in v2.
const/4 v2, 0x0

goto :goto_0
.end method

Monday, June 6, 2011

protection by checking for debuggers

one way to figure out what an app is doing is to use a debugger so you can step through line by line. apktool makes it possible to debug apps to which you do not have the source, and you also have to setup a few other things covered in lesson 1 of the way of the android crack tutorials.

some apps try to protect against this and there are two techniques of doing so. the first is to check the android manifest to see if the app is set to debuggable. the java code would look something like this:

boolean isDebuggable = (0 != (getApplcationInfo().flags &= ApplicationInfo.FLAG_DEBUGGABLE));
if ( isDebuggable )
invalidLicense(); // you get the idea

in smali, specifically from the testtarget app distributed with antilvl, it looks like:
# get app info object
invoke-virtual {p0}, Lcom/lohan/testtarget/Main;->getApplicationInfo()Landroid/content/pm/ApplicationInfo;
move-result-object v1

# get flags mask
iget v2, v1, Landroid/content/pm/ApplicationInfo;->flags:I

# 0x2 is ApplicationInfo.FLAG_DEBUGGABLE
and-int/lit8 v2, v2, 0x2

iput v2, v1, Landroid/content/pm/ApplicationInfo;->flags:I

# if v2 is 0x0 (the debuggable flag is not set), goto :cond_0
if-eqz v2, :cond_0


the second method is to check if a debugger is currently connected. the java looks like:
boolean debugConn = Debug.isDebuggerConnected();

Wednesday, April 27, 2011

smali syntax resource

jesusfreke, the guy who wrote smali/baksmali, has some nice documentation on the smali syntax on the wiki for his project: http://code.google.com/p/smali/w/list i learned some stuff! thanks jesusfreke.

Wednesday, April 20, 2011

Simple List




Simple List Free is a small, intuitive and easy-to-use application. Designed to be able to create an unlimited amount of lists...you'll be organised before you know it!
Within each list you can add many entries, rank them them and check them off as completed.
Can be used for grocery lists, check lists, packing list, basically whereever there is a need for a list you can use Simple List. If all you want to do is manage lists without the bells and whistles then this is the
application for you.

1. Creating a List

The first time you launch Simple List you will see the following screen:


 
To create your first list, enter the name of the list in the text box at the bottom of the screen. You should then select the add button or press the return key:



The Edit List Screen will then be opened:



You can add as many items to the list as you like by entering them into the text box at the bottom of the screen. As with adding lists you select the add button or press the return key to add an item to the list. 

2. Quick Actions

You can select any List or List-Item by using a Long Press and a quick action bar will appear:




The options available are:
  • Edit (List Only)
  • Check/Uncheck (List-Item only)
  • Remind (List-Item only)
  • Send (List Only)
  • Delete
  • Rename
  • Move Up
  • Move Down

3. Gestures

A Single tap will open up a list.

A Long press will open the quick action bar

If you swipe across a List-Item it will check or uncheck this swiped List-Item.











If you like this application then please give us a good rating.

Monday, April 18, 2011

antilvl 1.1.5

thanks to Notion and SuRViVe pointing out some instances of the lvl not being properly identified. i removed some requirements to match some key files that weren't likely necessary and were not being found recently. two new anti-cracking methods have been added and testtarget was updated appropriately.

grab it here:
http://androidcracking.blogspot.com/p/antilvl_01.html

Friday, April 8, 2011

antilvl 1.1.4

antilvl 1.1.4 has been released. main new feature is support for cracking amazon appstore drm. it also includes the apk i use to test new releases called testtarget.apk.

let me know if the new release breaks something :D

grab it here: http://androidcracking.blogspot.com/p/antilvl_01.html

Saturday, April 2, 2011

cracking amazon drm

update: antilvl 1.1.4 can handle amazon drm protection.

amazon has an app store now and they rolled their own drm. Anonymous was kind enough to post a link describing how to crack the protection: http://pastebin.com/cFddguZX

there may be a cleaner solution, and if you find one you are encouraged to share it. here's the code from the above link but syntax highlighted:
# virtual methods
.method public final a()V
.registers 6

const-string v4, "LICENSE_FAILURE_CONTENT"

iget-object v0, p0, Lcom/amazon/android/aa/d;->b:Lcom/amazon/android/o/d;

const-string v1, "APPLICATION_LICENSE"

invoke-virtual {v0, v1}, Lcom/amazon/android/o/d;->b(Ljava/lang/String;)Z

move-result v0

# Comment out first jump
#if-eqz v0, :cond_14

sget-object v0, Lcom/amazon/android/aa/d;->a:Lcom/amazon/android/u/a;

const-string v1, "license verification succeeded"

invoke-virtual {v0, v1}, Lcom/amazon/android/u/a;->a(Ljava/lang/String;)V

:goto_13
return-void

:cond_14
invoke-virtual {p0}, Lcom/amazon/android/aa/d;->f()Z

move-result v0

# Comment out second jump
#if-eqz v0, :cond_1d

invoke-virtual {p0}, Lcom/amazon/android/aa/d;->g()V

:cond_1d
new-instance v1, Lcom/amazon/android/l/m;

iget-object v0, p0, Lcom/amazon/android/aa/d;->b:Lcom/amazon/android/o/d;

const-string v2, "LICENSE_FAILURE_CONTENT"

invoke-virtual {v0, v4}, Lcom/amazon/android/o/d;->a(Ljava/lang/String;)Ljava/lang/Object;

move-result-object v0

check-cast v0, Lcom/amazon/android/l/d;

# Comment out third jump
#if-eqz v0, :cond_3d

iget-object v2, p0, Lcom/amazon/android/aa/d;->b:Lcom/amazon/android/o/d;

const-string v3, "LICENSE_FAILURE_CONTENT"

iget-object v2, v2, Lcom/amazon/android/o/d;->a:Lcom/amazon/android/o/b;

invoke-virtual {v2, v4}, Lcom/amazon/android/o/b;->c(Ljava/lang/String;)V

:goto_34
invoke-direct {v1, v0}, Lcom/amazon/android/l/m;->(Lcom/amazon/android/l/d;)V

iget-object v0, p0, Lcom/amazon/android/aa/d;->c:Lcom/amazon/android/l/f;

invoke-interface {v0, v1}, Lcom/amazon/android/l/f;->a(Lcom/amazon/android/l/a;)V

goto :goto_13

:cond_3d
sget-object v0, Lcom/amazon/android/aa/f;->e:Lcom/amazon/android/l/d;

goto :goto_34
.end method

the file name will likely always be different with obfuscation. just search for strings like "LICENSE_FAILURE_CONTENT" or "APPLICATION_LICENSE" and perform the three modifications mentioned above.

i'll be adding this functionality to the next release of antilvl. it will also contain a few more bypasses for anti-cracking techniques i've seen, and some improvements in lvl fingerprinting.