Showing posts with label antilvl. Show all posts
Showing posts with label antilvl. Show all posts

Thursday, October 27, 2011

antilvl 1.4.0

it's been a while, but antilvl 1.4.0 is finally released. i did not plan to make another release, but there were some show-stopping bugs in the linux version and some other things that were just embarrassing. :D

major changes include:
  • option to use your own signatures
  • more control over which fingerprints are used
  • support for verizon drm
  • a few new anti-tampering checks are known
  • some fixes in how fingerprints were applied

you can read more / download here: http://androidcracking.blogspot.com/p/antilvl_01.html

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

Thursday, March 24, 2011

original smalihook java source

i've noticed some interest about a file that antilvl sometimes uses when cracking a program. it's called smalihook and it's purpose is to provide "hook" (actually replacement) methods for things like getting device id or signature. it's not really anything special, unless you actually modify the places in the app that make use of certain function calls. there is also a smalihook.java floating around that is actually a badly decompiled, broken version. i'd rather people have the real thing.

the variable strings that start with "%!" (ex: %!AppPackage%) are for antilvl to replace with the actual information when it copies it over.

if you want to use any of the functions here you can simply use antilvl.

if you just want to spoof your android_id or getdeviceid, try this: http://strazzere.com/blog/?p=217




package lohan;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Random;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.Signature;
import android.content.pm.PackageManager.NameNotFoundException;
import android.telephony.TelephonyManager;
import android.util.Log;

/*
 * TODO:
 * I wonder if it's possible to check getClasses or getMethods to detect this
 * hook
 * Hooks:
 * PackageManager
 * getInstallerPackageName
 * getPackageInfo
 * getApplicationEnabledSetting
 * checkSignatures
 * getDeviceID - requires context
 * File
 * length
 * lastModified
 */

public class SmaliHook {

 // replace with random var per antilvl run
 private static String PrefsFile = "HookSettings";
 private static Context myAppContext = null;
 
 // random - always random, permute - unreversible permutation
 // session means until app is reinstalled
 private static enum DEVICE_ID_SPOOF {
  RANDOM, SESSION_RANDOM, SESSION_PERMUTE
 };
 private static DEVICE_ID_SPOOF myIDSpoof = DEVICE_ID_SPOOF.SESSION_RANDOM;
 private static String LOG_TAG = "lohan";
 private static boolean DEBUG = true;
 private static boolean DUMP_STACK = false;

 public static Object invokeHook(Method method, Object receiver,
   Object[] args) throws IllegalArgumentException,
   IllegalAccessException, InvocationTargetException,
   NameNotFoundException {

  boolean HookEnabled = true;

  String methodClassName = "unknown-static";
  String methodName = method.getName();
  if ( receiver != null )
   methodClassName = receiver.getClass().getName();
  else methodClassName = method.getDeclaringClass().getName();

  if ( DEBUG ) {
   String logStr = "Invoke Hook: " + methodClassName + "."
     + methodName + "(";
   if ( args != null ) {
    String argStr = "";
    for ( Object arg : args )
     argStr += arg.getClass().getName() + ":" + arg + ", ";
    if ( argStr.length() > 2 )
     argStr = argStr.substring(0, argStr.length() - 2);
    logStr += argStr;
   }

   Log(logStr + ")");
  }

  DumpStackIfWeShould();

  if ( !HookEnabled ) return method.invoke(receiver, args);

  if ( methodClassName
    .equals("android.app.ContextImpl$ApplicationPackageManager")
    || methodClassName
      .equals("android.app.ApplicationContext$ApplicationPackageManager")
    || methodClassName.equals("android.content.pm.PackageManager")
    || methodClassName.contains("ApplicationPackageManager") ) {
   if ( methodName.equals("getInstallerPackageName") ) {
    // Hook get installer package name
    return getInstallerPackageName((String) args[0]);
   }
   else if ( methodName.equals("getPackageInfo") ) {
    // Hook get package info for signatures
    int flags = (Integer) args[1];

    if ( methodClassName
      .equals("android.content.pm.PackageManager") )
     return SmaliHook.getPackageInfo(
       ((PackageManager) receiver), (String) args[0],
       flags);

    // Cannot simply recast receiver to
    // ContextImpl.ApplicationPackageManager or we get error
    Object result = null;
    try {
     result = method.invoke(receiver, args);
    }
    catch (Exception e) {
     result = method.invoke(receiver, "%!AppPackage%");
    }

    if ( (flags & PackageManager.GET_SIGNATURES) == PackageManager.GET_SIGNATURES ) {
     Signature[] spoofSigs = SmaliHook.spoofSignatures();
     // should only need to spoof the first one
     ((PackageInfo) result).signatures[0] = spoofSigs[0];
    }

    return result;
   }
   else if ( methodName.equals("getApplicationEnabledSetting") ) {
    int result = getApplicationEnabledSetting(
      (PackageManager) receiver, (String) args[0]);
    return (Object) Integer.valueOf(result);
   }
   else if ( methodName.equals("checkSignatures") ) {
    // This could be detected by comparing a known installed package
    // that will not match signatures. Will deal with that if it
    // ever happens. :D
    return checkSignatures((String) args[0], (String) args[1]);
   }

  }
  else if ( methodClassName.equals("java.io.File") ) {
   if ( shouldSpoofFileInfo((File) receiver) ) {
    if ( methodName.equals("length") ) { return length((File) receiver); }

    if ( methodName.equals("lastModified") ) { return lastModified((File) receiver); }
   }
  }

  // No hooks, work as normal
  return method.invoke(receiver, args);
 }

 public static int checkSignatures(String p1, String p2) {
  Log("checkSignatures returning SIGNATURE_MATCH");
  DumpStackIfWeShould();

  return PackageManager.SIGNATURE_MATCH;
 }

 public static int checkSignatures() {
  Log("checkSignatures returning SIGNATURE_MATCH");
  DumpStackIfWeShould();

  return PackageManager.SIGNATURE_MATCH;
 }

 public static String getInstallerPackageName(String packageName) {
  // LIE and say installed from market :D
  String result = "com.google.android.feedback";
  Log("getInstallerPackageName returning " + result);
  DumpStackIfWeShould();
  return result;
 }

 public static int getApplicationEnabledSetting(PackageManager pm,
   String packageName) {

  int result;
  try {
   result = pm.getApplicationEnabledSetting(packageName);
  }
  catch (IllegalArgumentException ex) {
   result = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
  }

  // Fake value if it's disabled
  if ( result == PackageManager.COMPONENT_ENABLED_STATE_DISABLED )
   result = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;

  Log("enabledSetting returning " + result);
  DumpStackIfWeShould();
  return result;
 }

 public static PackageInfo getPackageInfo(PackageManager pm,
   String packageName, int flags) throws NameNotFoundException {

  // Get regular package info
  PackageInfo pi = null;
  try {
   pi = pm.getPackageInfo(packageName, flags);
  }
  catch (NameNotFoundException e) {
   // Sometimes the app wants to know of other, helper apps are
   // installed or if trial / nonfull versions are installed
   // Fail normally if it's NOT checking for pro/full version stuff
   if ( !(packageName.toLowerCase().contains("pro")
     || packageName.toLowerCase().contains("full")
     || packageName.toLowerCase().contains("donate") || packageName
     .toLowerCase().endsWith("key")) )
    throw new NameNotFoundException();

   // Spoof with this package's info
   pi = pm.getPackageInfo("%!AppPackage%", flags);
  }

  // Populate with fake signatures if flags ask for it
  if ( (flags & PackageManager.GET_SIGNATURES) == PackageManager.GET_SIGNATURES ) {
   Signature[] spoofSigs = SmaliHook.spoofSignatures();
   for ( int i = 0; i < pi.signatures.length; i++ )
    pi.signatures[i] = spoofSigs[i];
   Log("spoofing signatures for " + packageName);
   DumpStackIfWeShould();
  }

  return pi;
 }

 public static Signature[] spoofSignatures() {
  final int certCount = Integer.parseInt("%!CertCount%");
  Signature[] result = new Signature[certCount];

  // Usually check signature of package and not individual files
  // This will only fool checks of entire package
  // Individual files would require a lot of smali generation
  String replace = "%!SignatureChars%";

  for ( int i = 0; i < certCount; i++ )
   result[i] = new Signature(replace);

  return result;
 }

 public static long length(File f) {
  long retVal = Long.parseLong("%!OrigFileSize%");

  if ( !shouldSpoofFileInfo(f) ) {
   retVal = f.length();
   Log("spoofing file length of " + f.getName() + " with " + retVal);
   DumpStackIfWeShould();
  }

  return retVal;
 }

 public static long lastModified(File f) {
  // long retVal = 1287850800968L;
  long retVal = Long.parseLong("%!OrigLastModified%");

  if ( DUMP_STACK ) Thread.dumpStack();

  if ( !shouldSpoofFileInfo(f) ) {
   retVal = f.lastModified();
   Log("spoofing file modified of " + f.getName() + " with " + retVal);
   DumpStackIfWeShould();
  }

  return retVal;
 }

 public static String getDeviceID() {
  if ( myAppContext == null ) {
   Log("getDeviceID has no context, can't spoof device id");
   return "";
  }

  // final TelephonyManager tm = (TelephonyManager)
  // myAppContext.getSystemService(Context.TELEPHONY_SERVICE);
  // Log("this is my device id: " + tm.getDeviceId());

  // fallback id
  String spoofID = "359881030314356";
  
  if ( myIDSpoof == DEVICE_ID_SPOOF.RANDOM )
   spoofID = generateRandomDeviceID();
  else {
   SharedPreferences settings = myAppContext.getSharedPreferences(
     PrefsFile, Context.MODE_PRIVATE);
   spoofID = settings.getString("android_id", "");

   if ( spoofID.length() == 0 ) {
    if ( myIDSpoof == DEVICE_ID_SPOOF.SESSION_RANDOM )
     spoofID = generateRandomDeviceID();
    else if ( myIDSpoof == DEVICE_ID_SPOOF.SESSION_PERMUTE )
     spoofID = getPermutedDeviceID();
   
    SharedPreferences.Editor editor = settings.edit();
    editor.putString("android_id", spoofID);
    editor.commit();
   }
  }
  
  Log("spoofing device id: " + spoofID);

  return spoofID;
 }

 private static boolean shouldSpoofFileInfo(File f) {
  boolean result = false;

  if ( f.exists() ) result = false;

  if ( f.getName().contains("%!AppPackage%")
    && f.getName().endsWith(".apk") ) result = true;

  return result;
 }

 public static void SetAppContext(Context c) {
  if ( myAppContext == null ) myAppContext = c;
 }

 private static String getPermutedDeviceID() {
  // permute device id
  final TelephonyManager tm = (TelephonyManager) myAppContext
    .getSystemService(Context.TELEPHONY_SERVICE);
  // lazy lazy lazy http://www.random.org/sequences/
  // this is a permutation with a loss of information
  // prevent anyone from knowing the id even if they knew the mapping
  final int[] p = { 12, 2, 10, 2, 13, 8, 0, 3, 14, 3, 6, 9, 5, 1, 12 };

  String deviceId = tm.getDeviceId();
  String result = "";
  if ( deviceId != null ) {
   for ( int i : p )
    result += deviceId.charAt(i);
  }

  return result;
 }

 private static String generateRandomDeviceID() {
  // device id is 15 digit number with seemingly no pattern
  // only changed by factory reset or with root
  // ex: 359881030314356 (emulators is all 0s)
  return generateString("0123456789", 15);
 }

 private static String generateString(String charSet, int length) {
  Random rng = new Random();
  char[] text = new char[length];
  for ( int i = 0; i < length; i++ )
   text[i] = charSet.charAt(rng.nextInt(charSet.length()));

  return new String(text);
 }

 public static void Log(Object o) {
  if ( !DEBUG ) return;

  Log.d(LOG_TAG, String.valueOf(o));
 }

 public static void DumpStackIfWeShould() {
  if ( !DUMP_STACK ) return;

  DumpStack();
 }

 public static void DumpStack() {
  StackTraceElement[] ste = Thread.currentThread().getStackTrace();

  // skip the first 4, it's just local stuff
  String trace = "Stack trace:\n";
  for ( int i = 4; i < ste.length; i++ )
   trace += "  " + ste[i].toString() + "\n";

  Log.d(LOG_TAG, trace);
 }

 public static void Toast(Object o) {
  // todo: implement
 }
}

Sunday, February 13, 2011

antilvl 1.1.3

just put up antilvl 1.1.3. a few small but annoying bugs fixed and some improvements with the hooks. pick it up from the usual spot: http://androidcracking.blogspot.com/p/antilvl_01.html

also had to do some major refactoring so people could make use of the source once it's released, and i think i got most of the kinks out.

while working on this, i noticed a few more apps that were using string encryption. maybe it will start to get popular? i wrote a proof of concept decryptor just to see how feasible it would be to convert dex to java .class files and run the apk's own methods to decrypt the strings. it worked but i want to make something more general. here's my idea:

  • start with an apk and disassemble
  • chose to decode literal strings (ex: const-string "some-encoded-string") or assume strings are the result of a function call (ex: invoke-static LStringHolder;->getString(v0)).
  • show all lines that match the above selection and allow for regex filtering. this way, if you pick literal strings and not all strings are encoded, you can filter for just the ones that are
  • decode strings by one of several methods: run the function, in the case of function-call encryption, built-in stuff like base 64, etc. or by using reflection on the classes of the apk. this way if every literal string in the apk is decoded through some function, i could use dex2jar to get the java class, dynamically load that and run each string through it.
the goal is to make the tool generic enough so that it's useful in the most situations. shouldn't be too hard. half of the work will be making my patching and apk libraries more generic and useful, so it wont be a total waste of time.

Monday, February 7, 2011

antilvl's source

several have asked for antilvl's source to use it in ways i could not have imagined. it seems it's true purpose is more of a general semi-automated apk patcher, which is fine. i'm thinking i should rename it and make it more general purpose, while still including the lvl-patching and anticracking-patching information.

i'm also getting a lot of fun out of this little shell extension for windows to get explorer to replace an apk's icon with the actual icon for the app inside: http://code.google.com/p/apkshellext/

Sunday, February 6, 2011

antilvl 1.1.2

antilvl 1.1.2 is finished. thanks for the bug reports from anonymous, sage and others. changes and download links are here: http://androidcracking.blogspot.com/p/antilvl_01.html

Sunday, January 30, 2011

quick antilvl fix

got overeager with antilvl's new found powers and released without doing some extra bug testing. just uploaded a less broken version just now. download links haven't changed.

antilvl 1.1

finished antilvl 1.1. it's kind of scary how well it's working. now that the anti-cracking methods are added in, it should be able to crack the android license verification library and any type of protection i have ever seen, including a few i haven't.

the number of modifications done to an app has increased a bit, so there may be some mix up. let me know how it works for you.

here's the main gist of the changes:
  • introduced many anti-cracking bypassing methods. it's better than me!
  • improved --sign-only behavior, though it still errors every other time
  • fixed issue with modification's sometimes being done improperly
  • several under the hood improvements for future features
 you can download it here: http://androidcracking.blogspot.com/p/antilvl_01.html

next up i intend to tackle slidelock protection and api key requirements.

Sunday, January 23, 2011

anti-cracking example

there are only a handful of anti-cracking techniques for android, at least that i know of. this seems to be because of how android apps must behave. they must operate inside their own virtual machine and are not allowed to store permenent data. when they are uninstalled, they must remove all traces of themselves. this makes things like timed trials difficult to implement because a simple reinstall will reset timers.

if an app wants to prevent cracking, it only has a few options. it can check file properties of the apk such as file size, last modified date and signature. it could also check the installer package name to test if it was installed via market. a cracker or pirate would install via adb, not market. antilvl can already hook and subvert signature checks. file size, last modified and installer package hooking are in the works. :D

this is what a installer package check may look like in java:
private boolean InstalledFromMarketEasy() {
  String pname = this.getPackageName();
  PackageManager pm = this.getPackageManager();
  String installPM = pm.getInstallerPackageName(pname);
 
  if ( installPM == null ) {
    // Definitely not installed from Android Market
    return false;
  }
  else if ( installPM.equals("com.google.android.feedback") ) {
    // Installed from the Android Market
    return true;
  }

  return false;
}


but there's another way to perform any check in a more clever way that makes detection more difficult... by using java reflection. instead of calling the method directly, the app could use reflection to store the method in a variable and call it later indirectly. this makes searching for the direct method call difficult. it also allows the method name to be obfuscated since it is just a strong. let me show you in code what it may look like:
const-class v1, Landroid/content/pm/PackageManager;

# do not assume this will not always be a plain text
# it could be put together in a much more complicated way such as building character by character using ascii codes
# you'll have to hook reflection methods to test the name or figure it out manually
const-string v2, "getInstallerPackageName"

# make array of size 1
const/4 v3, 0x1
new-array v3, v3, [Ljava/lang/Class;

const/4 v4, 0x0
const-class v5, Ljava/lang/String;

# store String class in array v3, at index v4 (0)
aput-object v5, v3, v4

# get method of name v2 ("getInstallerPackageName") and move to v0
# http://download.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html#getMethod(java.lang.String, java.lang.Class...)
invoke-virtual {v1, v2, v3}, Ljava/lang/Class;->getMethod(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;
move-result-object v0

# do something with v0, like store in class variable
# ....
# and then sometime later, somewhere else in code

# get the package manager and store in v1
invoke-virtual {p0}, Lcom/clever/app/Main;->getPackageManager()Landroid/content/pm/PackageManager;
move-result-object v1

const/4 v2, 0x1
new-array v2, v2, [Ljava/lang/Object;

const/4 v3, 0x0
invoke-virtual {p0}, Lcom/clever/app/Main;->getPackageName()Ljava/lang/String;
move-result-object v4

# put package name in array v2 at index v3 (0)
aput-object v4, v2, v3

# actually call "getInstallerPackageName" with the array we built as parameters
# which contains this package name
# http://download.oracle.com/javase/1.5.0/docs/api/java/lang/reflect/Method.html#invoke%28java.lang.Object,(java.lang.Object...)
invoke-virtual {v0, v1, v2}, Ljava/lang/reflect/Method;->invoke(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;
move-result-object v0
check-cast v0, Ljava/lang/String;

# clever to not use any type of full string, just "goog"
# remember the full string is expected to be "com.google.android.feedback"
const-string v1, "goog"
invoke-virtual {v0, v1}, Ljava/lang/String;->indexOf(Ljava/lang/String;)I
move-result v0

# check to see if v0 has the correct value. if not... error :D

the next lesson in way of the android cracker will cover all anti-cracking techniques i know in detail, and antilvl will support these types of checks soon, but this is enough for anyone to figure it out. :D

for some more information on reflection:
Using Java Reflection
Java programming dynamics, Part 2: Introducing reflection

Saturday, January 22, 2011

antilvl 1.0

antilvl 1.0 is finished and ready for action. here are some changes:
  • complete rewrite of previous versions
  • acts more like an engine, with modification information stored in fingerprints.xml
  • many, many more apk files can be decompiled and recompiled
  • handles several new types of protection methods
  • signature checking, a common anti-tampering technique, is subverted
  • file size / last modification checks are more accurately detected
  • pro / full unlock app protection is correctly handled sometimes
  • much more compact / optimized java bytecode

you can pick it up here: http://androidcracking.blogspot.com/p/antilvl_01.html

doing a total rewrite has opened up many more possibilities for new ideas. the next major thing i plan to implement is complete file size / last modified hooking.

Monday, January 10, 2011

upcoming antilvl 1.0

it's been a while since my last update, so i figure i should say something about progress on antilvl 1.0.

i wanted to learn all kinds of best practices in java, so i spent a lot of time designing classes while trying to avoid coupling and other oop pitfalls. even threw in some unit testing. i also want antilvl to be able to be able to learn how to subvert any implementation of the lvl, and do it without having pages and pages of complicated regex code.

to accomplish this, antilvl's code will be more like an engine, with all file identification patterns and code modification information written in xml with a specification of my own design. it will be mature enough to have in-place dynamic variables and definable search patterns. the result will be almost any apk modification could be cleverly constructed inside the xml without touching the code in about 10-20 lines.

i must stress i'm not doing this for piracy. i'm doing it because it's a challenge. no one else has done it. it's really fun for me. if i was trying to be a pirate, i would not explain how the cracks work. if you're a developer and you insist on protection, you will have to roll your own and heavily modify the official lvl so known methods will not work. use antilvl to help you figure out if it's well protected.

most people don't mind paying a few euros for a program on what amounts to their main computing device. the benefit from spending many hours on increased protection may not be worth it unless your App is very expensive. or perhaps your and android master and just really get off to having wonderfully insane levels of protection.

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.

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: http://androidcracking.blogspot.com/p/antilvl.html


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: http://www.accessroot.com/arteam/site/download.php?view.327

and there is some more info on slidelock at the starzzere.com, which is a great blog with lots of information on android: http://strazzere.com/blog/?p=177

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.

http://androidcracking.blogspot.com/p/antilvl.html

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:

http://androidcracking.blogspot.com/p/antilvl.html

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.

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:
https://sites.google.com/site/lohanplus/files/AntiLVL-0.8.zip?attredirects=0&d=1

there is a new page for antilvl so you don't have to always watch the blog here:
http://androidcracking.blogspot.com/p/antilvl.html

Sunday, November 7, 2010

AntiLVL - android license verification subversion

update:
new version released. read about it here: http://androidcracking.blogspot.com/2010/11/anti-lvl-08.html


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]
Options:
-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:
https://sites.google.com/site/lohanplus/files/AntiLVL-0.5.zip?attredirects=0&d=1