Wednesday, December 29, 2010

getting apk signature outside of android

one way to circumvent signature checking in an android app is to spoof with the correct signature (usually a hashcode but sometimes a tochar representation). but how do we get the apk signature? well, we could write a program in android to do it, which is pretty simple:
public void WriteSignature(String packageName)
 // all of this is fairly well documented
 // if it doesn't work, just search around.
 PackageManager pm = this.getPackageManager();
 PackageInfo pi = null;
 try {
  pi = pm.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
 } catch (NameNotFoundException e1) {
 Signature[] s = pi.signatures;
 // you can use toChars or get the hashcode, whatever
 String sig = new String(s[0].toChars());

 try {
  File root = Environment.getExternalStorageDirectory();
  if ( root.canWrite() )
   // toChars is long, so i write it to a file on the external storage
   File f = new File(root, "signature.txt");
   FileWriter fw = new FileWriter(f);
   BufferedWriter out = new BufferedWriter(fw);
   out.write(packageName + "\nSignature: " + sig);
 } catch (IOException e) {

but i wanted to be able to get the signature from my computer, and google wasn't helping. so i dug into the android code. then i found this:

the packageparser code was exactly what i needed. nothing about it was particularly magical and i could have probably figured it out on my own if i knew better, but here is what i came up with:
import java.lang.ref.WeakReference;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Main {

 private static final Object mSync = new Object();
 private static WeakReference<byte[]> mReadBuffer;

 public static void main(String[] args) {
  if (args.length < 1) {
   System.out.println("Usage: java -jar GetAndroidSig.jar <apk/jar>");


  String mArchiveSourcePath = args[0];

  WeakReference<byte[]> readBufferRef;
  byte[] readBuffer = null;
  synchronized (mSync) {
   readBufferRef = mReadBuffer;
   if (readBufferRef != null) {
    mReadBuffer = null;
    readBuffer = readBufferRef.get();
   if (readBuffer == null) {
    readBuffer = new byte[8192];
    readBufferRef = new WeakReference<byte[]>(readBuffer);

  try {
   JarFile jarFile = new JarFile(mArchiveSourcePath);[] certs = null;

   Enumeration entries = jarFile.entries();
   while (entries.hasMoreElements()) {
    JarEntry je = (JarEntry) entries.nextElement();
    if (je.isDirectory()) {
    if (je.getName().startsWith("META-INF/")) {
    }[] localCerts = loadCertificates(jarFile, je, readBuffer);
    if (false) {
     System.out.println("File " + mArchiveSourcePath + " entry " + je.getName()
         + ": certs=" + certs + " ("
         + (certs != null ? certs.length : 0) + ")");
    if (localCerts == null) {
     System.err.println("Package has no certificates at entry "
         + je.getName() + "; ignoring!");
    } else if (certs == null) {
     certs = localCerts;
    } else {
     // Ensure all certificates match.
     for (int i = 0; i < certs.length; i++) {
      boolean found = false;
      for (int j = 0; j < localCerts.length; j++) {
       if (certs[i] != null
           && certs[i].equals(localCerts[j])) {
        found = true;
      if (!found || certs.length != localCerts.length) {
       System.err.println("Package has mismatched certificates at entry "
           + je.getName() + "; ignoring!");
       return; // false


   synchronized (mSync) {
    mReadBuffer = readBufferRef;

   if (certs != null && certs.length > 0) {
    final int N = certs.length;
    for (int i = 0; i < N; i++) {
     String charSig = new String(toChars(certs[i].getEncoded()));
     System.out.println("Cert#: " + i + "  Type:" + certs[i].getType()
      + "\nPublic key: " + certs[i].getPublicKey()
      + "\nHash code: " + certs[i].hashCode()
       + " / 0x" + Integer.toHexString(certs[i].hashCode())
      + "\nTo char: " + charSig);
   } else {
    System.err.println("Package has no certificates; ignoring!");
  } catch (CertificateEncodingException ex) {
   Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
  } catch (IOException e) {
   System.err.println("Exception reading " + mArchiveSourcePath + "\n" + e);
  } catch (RuntimeException e) {
   System.err.println("Exception reading " + mArchiveSourcePath + "\n" + e);

 private static char[] toChars(byte[] mSignature) {
    byte[] sig = mSignature;
    final int N = sig.length;
    final int N2 = N*2;
    char[] text = new char[N2];

    for (int j=0; j<N; j++) {
      byte v = sig[j];
      int d = (v>>4)&0xf;
      text[j*2] = (char)(d >= 10 ? ('a' + d - 10) : ('0' + d));
      d = v&0xf;
      text[j*2+1] = (char)(d >= 10 ? ('a' + d - 10) : ('0' + d));

    return text;

 private static[] loadCertificates(JarFile jarFile, JarEntry je, byte[] readBuffer) {
  try {
   // We must read the stream for the JarEntry to retrieve
   // its certificates.
   InputStream is = jarFile.getInputStream(je);
   while (, 0, readBuffer.length) != -1) {
    // not using

   return ([]) (je != null ? je.getCertificates() : null);
  } catch (IOException e) {
   System.err.println("Exception reading " + je.getName() + " in "
       + jarFile.getName() + ": " + e);
  return null;

running it on crackme0 from way of the android cracker 0, produces this:

using it, in dalvik, would look something like this:
# get signatures array
iget-object v0, v0, Landroid/content/pm/PackageInfo;->signatures:[Landroid/content/pm/Signature;

# get element at index v10 in array v0 and store in v0
aget-object v0, v0, v10
# call Signature.hashCode() on v0, returns an integer
invoke-virtual {v0}, Landroid/content/pm/Signature;->hashCode()I
move-result v9

# spoof original signature hashcode. grin smugly.
const/16 v9, 0x58404

Tuesday, December 28, 2010

antilvl 0.9.1

antilvl 0.9.1 is posted and has a few small fixes. namely, when it complains about missing aapt and zipalign.

it seems more people are using it and making suggestions. right now i'm working on figuring out at least three different types of implementations that i have seen. one of them is quite complex and is taking me some time, but it's helping me improve my focus. once i figure them out, i may have to totally rewrite the cracking methods to be much more flexible, which should be fun. the end result is antilvl works with many more apps.

i've also been digging around the android source code, trying to figure out a way to get packageinfo as one does with an android app _outside_ of android. this way antilvl could possibly circumvent signature checking by substituting a string of the original signature whenever it is requested. this would make me very happy as signature checking is the principal anti-cracking mechanism currently, but more importantly, i think would just be clever to do.

Sunday, December 26, 2010

searching inside files

a very common operation while exploring code is searching inside all of the files in a folder for a specific bit. by default, windows xp (and perhaps windows 7) will not search files with unknown extensions (it also hides extensions, which is also annoying). i have read more than one tutorial on android cracking that suggests renaming all .smali files into .txt files for searching. this is not necessary. here's a link describing how to fix it titled (just it case it gets moved) "Using the ``A word of phrase in the file`` search may not work":

Wednesday, December 22, 2010

what are these empty methods in dalvik?

when i first started playing with dalvik, i would often get stuck at empty methods. something like this:
.method public abstract a()Z
.end method

.method public abstract b()V
.end method

i would trace a program's execution and get to one and not know what to do. maybe the decompiler could not handle the method? is there some trick preventing me from seeing the code? usually i would just backtrack and crack it elsewhere that works most of the time, but sooner or later you may need to know the implementation!

there are at least two reasons. either the method is abstract and is thus part of a super class that a child inherits from or the method is native and the method implementation is buried in a shared library (.so file). let's say you are looking at com/package/Super.smali and it has the two blank methods above, which are abstract. simply search the code for this line:
.implements Lcom/package/Super;

the file in which you find that line should also have a()Z and b()V and possibly some other methods. the code that calls Super;->a()Z or Super;->b()V is most likely initializing the child class before that and then storing it in a variable declared as Super. so all you need to do is correctly identify which child class is being used.

the other possibility is the code has been offloaded to some shared library. this is more common in technically complex apps or games that require fast, low-level code such as c. if you use apktool, look inside the dump directory for a folder called lib. in it there should be at least one .so file. you will need an arm decompiler such as ida pro. there are others but i do not have experience with them. if you do, post a comment. there are multiple variants of the arm instruction set if your decompiler asks which one it should try to use, try running:
aapt d --values badging your_apk_here.apk
aapt comes with apktool and the android-sdk. look near the bottom for the "native-code" portion. should look like this:
native-code: 'armeabi' 'armeabi-v7a'
the instruction set for this apk is armeabi v7 (quite common), so open the .so up in your decompiler and search for a function with a similar name to your empty abstract method. i believe the name will always be of the form Java_PackageName_ClassName_MethodName. if you find your method, hopefully you know arm enough to understand what it is doing. if you are lucky you will not need to modify the library because patching them is a little more difficult than simply editing a .smali file. i plan on including information on patching shared libraries in a later tutorial, but there are several out there.

Tuesday, December 21, 2010

AntiLVL 0.9

 had some more time to work on antilvl. main thing is linux compatibility. you have to change your path until i can find some work-around with apktool trying to run "aapt" instead of "./aapt". more info in the readme.
  • works with linux (Protector wins the prize for asking for it first!)
  • fixed compatibility with smali dumps
    • plan to add full smali/baksmali support in next version
  • changed behavior when CHECK_LICENSE permission cannot be found
    • instead of exiting immediately, just warn the user
  • changed dump path to reflect the package name
  • various smaller improvements
  • updated aapt and zipalign

pick it up here:

i have been busy with non-android things lately, so i was happy when a friend (SuRViVe) sent me a link to a tutorial for circumventing an android drm called slidelock. the tutorial was written by Nieylana, who has written some other very nice tutorials, including the first tutorial i could find on android

here's the one on slideme:

and there is some more info on slidelock at the, which is a great blog with lots of information on android:

it seems like 1.1 and maybe even 2.0 of slidelock are merely wrappers for the main class. it should be fairly easy to look at the androidmanifest.xml and poke around a few files and simply change the launcher activity so the drm isn't executed at all. i really don't like it because it sends far too much information about your phone to their servers. i will look into adding this as feature into antilvl.

Friday, December 17, 2010

antilvl 0.8.4

minor update to antilvl. someone pointed me to some apps that it did not correctly identify the implementation so the incorrect file was modified.

antilvl also now looks for the check_license permission which it uses as a definitive indicator that android lvl is being used. it check_license permission is not found, antilvl will tell you and exit.

Wednesday, December 15, 2010

antilvl 0.8.3

this new version has some support for non-lvl protection detection such as signature and last modified checks. if you have any suggestions for more let me know. in the future it may be possible to automatically disable some of these, but it is somewhat complicated.

also optimized how it scans through files so it should be a little faster. you can get it here:

Friday, November 19, 2010

ideas for antilvl and new lesson

my discretionary time is limited lately but i have begun work on lesson 2 which will cover anti-cracking techniques. it will give examples of all anti-cracking methods i have seen in the wild. i will attempt to come up with some novel techniques as well, because that seems fun.

also thought of a possible feature for antilvl. one anti-cracking technique is signature checking. the apk compares the hashcode of its signature with a stored hashcode to see if the apk has been resigned, which would indicate tampering since all apks must be resigned if modified. antilvl could search for these uses, which rarely have any other purpose but to prevent cracking, and optionally disable them. it would then be possible to extend this to other common, easy to interpret anti-cracking techniques. just some thoughts.

Saturday, November 13, 2010

sharing a good blog

found a nice blog about reversing and android cracking by Dan, who was kind enough to point out that the well-known site has some android crackmes (just search android).

his blog also introduced me to a tool called dex2jar that will sort of convert a classes.dex file into .java source. of course, it's not perfect and it's still new but it can be useful for getting a quick overview if the dalvik is too confusing.

here's Dan's article on android reversing:, check it out. it's got pictures!

Friday, November 12, 2010

AntiLVL 0.8.1

saw some new kinds of obfuscation right after i released 0.8 so i spent the past several hours rewriting everything and optimizing. i had been looking for a fun java project to get some practice, so this has been quite handy.

the detection was totally rethought and there is a much better chance of detecting new types of obfuscation and lvl files in very strange places. i'm only increasing the version to 0.8.1 from 0.8 until i get a lot more testing, but to do that i'll need to test many apks. best way to do that is just send me any that don't work. i will assume it is legal for you to do so.

tested with 7 different apps and 3 of them worked. one of them would not recompile, so it does not count. one of them required further modifications. one seems broken. your mileage will vary.

AntiLVL 0.8

last week, i released the proof-of-concept version of anti lvl. it really only cracked the standard, unobfuscated android license verification. this version cracks license checks of more implementations and works even if code is obfuscated. it is also designed to be flexible and extensible to keep up with changing trends or any new types of implementations.

the new version is here:

there is a new page for antilvl so you don't have to always watch the blog here:

Sunday, November 7, 2010

AntiLVL - android license verification subversion

new version released. read about it here:

i've written previously about android market license verification here and here. i decided to write a tool for developers who want to protect their apps more by automating the entire process. here's a copy of the readme:

AntiLVL - Android License Verification Library Subversion

[ What is it? ]
This takes an .apk or apktool dump directory, attempts to subvert the market license verification library and recompiles, signs and zipaligns the modified code. The result is an .apk with the LVL check effectively removed. To the App, it appears the check was successful and no part of the application code is modified.

[ Who is it for? ]
Developers who wish to have more than Android LVL protection could devise and implement other types of protection. Then this tool could be used to simulate a crack attempt without the developer having to learn to use apktool, Dalvik and LVL cracking methods.

[ Usage ]
Usage: java -jar AntiLVL.jar [options] <smali dump path | Apk file>  [output Apk name]
-v:     Verbose output
-s:     Skip assembly
-h:     Show help

[ Known Problems ]
Any sort of LVL obfuscation will prevent this tool from working. It will be added if people want it.
here is the download link:

Friday, November 5, 2010

more android license validation

in a previous post i mentioned a method of cracking the android market license validation library (lvl). there are apparently multiple ways of deploying the android license verification library. most of the time i see com/android/LicenseChecker.smali, com/android/LicenseValidator.smali, etc. recently i found an app that only used ILicensingService and ILicenseResultListener and my normal method of cracking could not be applied.

after about 30 minutes of illuminating reading over binders and parcels work on the android developer site, i came up with this solution: inside ILicenseResultListener$Stub.smali, in the method onTransact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z simply return true at the top, like this:
.method public onTransact(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z
    .locals 6
    .parameter "code"
    .parameter "data"
    .parameter "reply"
    .parameter "flags"
    .annotation system Ldalvik/annotation/Throws;
        value = {
    .end annotation

    const/4 v4, 0x1

    # lnote: never do binder.ontransact
    # just always return true :)
    return v4

if you want to try to improve on this solution, it help to look at the actual java source here:

string obfuscation

a common practice in pc apps is string encryption. when a program is compiled all literal strings are replaced with function calls with a parameter that retrieve that specific string. the result is when the program is decompiled it is not possible to simply search for strings. string searching makes finding interesting locations in code much easier so preventing this makes cracking more difficult for more people. recently, i came across some string obfuscation. this is the first time i have seen it "in the wild". proguard does not do it because it necessarily requires more work from the processor and may slow things down slightly.

how can we defeat it? it is difficult to analyze dalvik code and perform the encryption process in reverse without damaging other code (at least for me), but it is very simple to merely call the function for every possible string. here is an example: StringDumper.smali

StringDumper will output decrypted strings to the log file. the encrypted strings in my case were held inside StringHolder.smali and were retrieved using getString(I)Ljava/lang/String. there were only 0x15 strings, but if you run into this specific type of encryption there may be more or less.

it is not likely you will see this exact, specific encrypter implementation since i suspect it was developed in-house and is not open source. at least you will have a general idea of how to defeat such protection.

Thursday, November 4, 2010

crackme submissions

there are several websites that host crackmes but none of them have android sections. i'll continue to look but if anyone knows of a site that is open to them, let me know.

i want to see how people are doing the crackmes in the tutorials so if you send me a cracked version and a little explanation of how you did it i can add some points to your name.

Friday, October 29, 2010

way of the android cracker 1

lesson 1 is finished. it covers debugging methods such as log statements and smalidebugging with apktool and netbeans. it also features crackme1 which is still somewhat easy but more difficult and realistic. download here:

lesson 0 has been renovated to include screen shots, a few fixes and an updated crackme0.

hope you learn something. good luck.

Friday, October 22, 2010

progress on second lesson

i am about half-way finished with the second lesson. while doing it i had many ideas for improving the first lesson. i have gone back and updated, tweaked and fixed the first lesson and will upload it when i am finished with the second.

the next crackme is only slightly more complex but it will include signature verification, a common anti-cracking technique. it is still quite easy but illuminating. actually it is about as easy as many actual android apps. the next lesson will include an obfuscated crackme, an additional anti-cracking technique and perhaps killer robots that stalk you in your sleep, but i may only have time two of those three.

cracking android license code is such a straightforward process that i have started work on a program that will do all of the work for you (baksmali, patch, recompile, resign). i'm not sure if others will find it useful so it does not get much attention.

Tuesday, October 19, 2010

unexplainable problems after recompilation with apktool

something i have seen many times is when a program is recompiled it has strange errors. perhaps a progress bar is not showing up correctly, the layout is somehow distorted or there are strange force closes that happen. in my experience the reason for this is almost always apktool's handling of resources.

if you are having trouble, try simply dumping and building without changing anything with apktool. if there is a problem, then apktool is the culprit. i suggest making an issue on apktool's page here:

you don't have to go into detail about what you're using apktool for. there are lots of legitimate reasons such as adding localization. it should suffice to mention in the report that simply dumping/building results in a distorted .apk.

if you are merely modifying smali code and don't need to modify the resources, try using the --no-res option, or you could just use smali/baksmali. if you are trying to modify an .xml resource then you might have to do it manually.

working with smali means working with the classes.dex file in the apk, and not the apk itself. you will also have to handle resigning and zipaligning (optional) yourself

Friday, October 15, 2010

android market license validation

there are more and more apps using a new official license validation mechanism. it seems very well made and robust but unfortunately it is trivial to overcome in at least every instance where i have seen it.

for more information on how it works, there is lots of good information here:

update: all known (by me) license verification library cracking methods have been implemented in an automated tool here:

if you are interested in seeing how easy it is to defeat, read on.

open com/android/vending/licensing/LicenseValidator.smali and look at handleResponse() you'll see something like:

iget-object v0, p0, Lcom/android/vending/licensing/LicenseValidator;->mPolicy:Lcom/android/vending/licensing/Policy;

# this function returns true/false depending on if we should allow access 
invoke-interface {v0}, Lcom/android/vending/licensing/Policy;->allowAccess()Z

move-result v0

# comment out this jump and protection is gone.
# you can also make allowAccess() always return 0x1 (true)
#if-eqz v0, :cond_0

also there is an updated version of the smali syntax highlight file available here:

Sunday, September 26, 2010


this is a basic example of smali code with some comments. view it with ultraedit and syntax highlighting to get the full effect. this file is also included and updated in lesson 0 of the way of the android cracker.

for reference of dalvik opcodes, visit Dalvik opcodes.

update: if you like this, you may also want to see some example structures.

update #2:  threw in a little bit about primitives and arrays.

# class name, also determines file path when dumped
.class public Lcom/packageName/example;

# inherits from Object (could be activity, view, etc.)
# note class structure is L;
.super Ljava/lang/Object;

# original java file name
.source ""

# these are class instance variables
.field private someString:Ljava/lang/String;

# finals are not actually used directly, because references
# to them are replaced by the value itself
# primitive cheat sheet:
# V - void, B - byte, S - short, C - char, I - int
# J - long (uses two registers), F - float, D - double
.field public final someInt:I  # the :I means integer
.field public final someBool:Z # the :Z means boolean

# Do you see how to make arrays?
.field public final someCharArray:[C
.field private someStringArray:[Ljava/lang/String;

# this is the <init> of the constructor
# it calls the <init> of it's super, which in this case
# is Ljava/lang/Object; as you can see at the top
# the parameter list reads: ZLjava/lang/String;I
# Z - boolean
# Ljava/lang/String; - java String object
#   (semi-colon after non-primitive data types)
# I - integer
#   (no semi-colon)
# also notice this constructor returns V, which means void
.method public constructor <init>(ZLjava/lang/String;I)V
 # declare how many variable spaces we will need
 # we can have: v0, v1, v2, v3, v4 and v5 as variables.
 # smali/baksmali by default uses .registers
 # but you can change this by using --use-locals
 # apktool uses --use-locals and --sequential-labels
 .locals 6

 # these are not always present and are usuaully taken
 # out by optimization/obfuscation but they tell us
 # the names of Z, Ljava/lang/String; and I before
 # when it was in Java
 .parameter "someBool"
 .parameter "someInt"
 .parameter "exampleString"
 # the .prologue and .line directives can be mostly ignored
 # sometimes line numbers are useful for debugging errors
 .line 10
 # p0 means parameter 0
 # p0, in this case, is like "this" from a java class.
 # we are calling the constructor of our mother class.
 # what would p1 be?
 invoke-direct {p0}, Ljava/lang/Object;-><init>()V
 # store string in v0
 const-string v0, "i will not fear. fear is the mind-killer."
 # store 0xF hex value in v0 (or 15 in base 10)
 # this destroys previous value string in v0
 # variables do not have types they are just registers
 # for storing any type of value.
 # hexadecimal is base 15 is used in all machine languages
 # you normally use base 10
 # read up on it:
 const/4 v0, 0xF
 # create instance of StringBuilder in v1
 new-instance v1, Ljava/lang/StringBuilder;
 # initialize StringBuilder with v2
 # notice it returns V, or void
 const-string v2, "the spice must flow"
 invoke-direct {v1, v2}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V
 # append p1, which is our first paramater and is boolean
 # therefore we use append(Z)
 # notice how append returns a StringBuilder
 invoke-virtual {v1, p1}, Ljava/lang/StringBuilder;->append(Z)Ljava/lang/StringBuilder;
 # use move-result-object to store previous result in v1
 move-result-object v1
 # non-objects use move-result or move-result-wide

 # append v2 to our StringBuilder
 # notice how this append takes a string and not Z
 const-string v2, "some random string"
 invoke-virtual {v1, v2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
 move-result-object v1
 # call toString() on our StringBuilder
 # if you use Java you know that most objects have toString()
 invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
 move-result-object v1
 # send our new string to the log.
 # this can be used to debug and can be picked up with ddms, logcat
 # or log collector. as an exercise look up what the d() function does
 # in the android developer documentation.
 const-string v0, "Tag"
 invoke-static {v0, v1}, Landroid/util/Log;->d(Ljava/lang/String;Ljava/lang/String;)I
 move-result v0
 # get the current time in milliseconds
 # J denotes a float or wide return value
 invoke-static {}, Ljava/lang/System;->currentTimeMillis()J
 move-result-wide v2
 # note!! since it is a wide value, it takes up v2 AND v3

 # so we must use v4 next
 # try to reuse variables if possible.
 const-wide/16 v4, 0x300 # this takes up v4 and v5
 div-long/2addr v2, v4   # divide v2 by v4
 long-to-int v2, v2      # convert v2 to an integer
 # since i wrote this in my head, there was no Java
 # compiler to add the .line's in the right places
 # but normally they would relate to actual Java lines
 # these are often removed with proguard optimization
 .line 12
 # store p1 as an instance variable (someBool) for this class
 # in java this may look like this.someBool = p1;
 iput-boolean p1, p0, Lcom/packageName/example;->someBool:Z
 .line 14
 # do the same for p3 and someInt
 iput p3, p0, Lcom/packageName/example;->someInt:I
 # get the value from p0.someInt
 iget v0, p0, Lcom/packageName/example;->someInt:I
 # now we will invoke a static method.
 # {} means empty parameters then the full package name followed by ->
 # then the method and it's return value. everything must be there.
 invoke-static {}, Lcom/packageName/example;->someMethod()Ljava/lang/String;
 # for different types of invoke-*, try this:
 # invoke-virtual and direct take the class instance as a first parameter.
 .line 16
 return-void # meditate on the void.
.end method

# try and figure this one out
.method public static someMethod()Ljava/lang/String;
 # could i have used fewer variables?
 .locals 4
 new-instance v0, Ljava/lang/Long;
 invoke-static {}, Ljava/lang/System;->currentTimeMillis()J
 move-result-wide v1
 invoke-direct {v0, v1, v2}, Ljava/lang/Long;-><init>(J)V
 invoke-static {v0}, Ljava/lang/String;->valueOf(Ljava/lang/Object;)Ljava/lang/String;
 move-result-object v1
 # notice use of return-object and not just return
 return-object v1
.end method

smali syntax highlighting for ultraedit

syntax highlighting is handy dandy if you are staring at code for more than 10 seconds. you can install this into ultraedit by following the steps here:

get a copy here:

this file is included and kept up to date in lesson 0 of the way of the android cracker series.

cracking vs reversing

reversing is just a polite, politically correct term for cracking. the term cracking has developed a bad reputation in the past few years and those that don't want to look like they are breaking the law like to use the word reversing.

as if it's fooling anyone.

i wont post anything illegal, probably, and i have nothing against the word reversing. it's a nice word. it sounds mature, professional, clean. i still like the term cracking. one cracks nuts, safes, codes, bones, whips. it just sounds right and i'm not ashamed of it.

way of the android cracker 0

this is the first tutorial in a series. it lays the foundation. as you follow along you will set up your cracking environment, learn to use apktool and will have a general idea on how various cracking methods can be implemented.

also included is a crackme, an ultraedit syntax highlighting file and some heavily commented dalvik code.

if you learn anything new on your journey share it with others.

download it here: