The common theme here is that these are all naming tricks.

This helps to make your code hard to read for a human hacker, but
doesn't do anything to prevent an attacker with a good static analysis
framework.

A static analysis framework can usually deobfuscate (turn these
"nameless" classes into named things or common patterns) simply by
matching call/return sequences in a standard way using machine
learning.

So while you can prevent a human from saying "that's the licensing
check!  I'll look there!"  a computer can take in a bunch of known
good code using a licensing check and then training it, then taking in
the obfuscated app, looking at traces and saying "here's the licensing
check" and using program slicing to patch it out.

Hopefully this gives more insight into why the small lexical tricks
don't really help,

Kris

On Fri, Mar 1, 2013 at 12:40 PM, Nobu Games <dev.nobu.ga...@gmail.com> wrote:
> Unless your server provides something like downloadable content or
> functionality for your app I don't think you need to go through the trouble
> of implementing the license verification through your server. Doing it
> within your app is just fine, because either way a cracker can still look
> for these license check code portions and change them. Doing it just within
> your app is less work of course, so I'd go for that.
>
> Regarding the LVL there are a few very important things to know about.
> Google never intended it to be taken verbatim as a drop-in solution for
> protecting your app. A lot of developers did that. And their apps can be
> easily cracked. The problem is that a cracker also knows the original LVL
> code.
> You probably already know that the LVL needs to be customized for each app
> and definitely should not be used as an all-in-one solution library you just
> reference from your app project.
> So basically you should copy the files into your app project and change the
> heck out of it so it's not recognizable anymore. Also all logging lines must
> be removed. Why they are there in the first place is a bit beyond me.
>
> Anyway, the one big problem of the LVL is that its entry point interface
> ILicensingService apparently cannot be obfuscated. Proguard's documentation
> even says:
>
>> If you're using Google's optional License Verification Library, you can
>> obfuscate its code along with your own code. You do have to preserve its
>> ILicensingService interface for the library to work:
>>
>> -keep public interface com.android.vending.licensing.ILicensingService
>
>
> That advice is absolutely misleading and basically opens a big door into
> identifying and cracking your app's LVL self-check. If the interface name
> "ILicensingService" is literally to find in your obfuscated Java code you
> have basically the entry point for cracking the app right there. With Java
> decompiler it's just another click away to find the response code check.
>
> The Google session talk mentions that you should obfuscate the whole LVL,
> including ILicensingService. However, when I tried to do exactly that, it
> simply did not work. The name was always kept as if there is a hard-coded
> rule inside Proguard that makes the obfuscation of that identifier
> impossible. So I simply renamed ILicensingService. And it still works. I
> tested it extensively.
>
> About using the NDK for self-integrity checks: it's actually pretty similar
> to using reflection in Java. First of all you also have the same problem
> here with string literals that basically give away what you're trying to do
> (class and method names). You need to obfuscate them.
>
> One unobfuscated NDK example of getting the package name:
>
>> void Java_com_example_JniTestClass_checkPackageName(JNIEnv* env, jclass
>> clazz, jobject context) {
>>     jclass ctxClass = (*env)->GetObjectClass(env, context);
>>     jmethodID getPackageNameMethodID = (*env)->GetMethodID(env, ctxClass,
>> "getPackageName", "()Ljava/lang/String;");
>>     jstring packageName = (*env)->CallObjectMethod(env, context,
>> getPackageName);
>> }
>
> Each JNI method is basically the native counterpart of a Java method
> declaration. The Java original might look like as follows:
>
>> public class JniTestClass {
>>     public static native void checkPackageName(Context context);
>> }
>
>
> I'm going to dissect the NDK code a bit:
>
>     jclass ctxClass = (*env)->GetObjectClass(env, context);
>
> This gives you the class object of the context object. This is necessary for
> retrieving the class method "getPackageName" in the second line:
>
>     jmethodID getPackageNameMethodID = (*env)->GetMethodID(env, ctxClass,
> "getPackageName", "()Ljava/lang/String;");
>
> This gives you a class method handle. This is necessary for calling that
> method in the following line. The last argument looks a bit cryptic. It's
> Java convention for expressing the method signature in a string notation.
> You can find more information about these signature strings on this page.
>
> jstring packageName = (*env)->CallObjectMethod(env, context,
> getPackageName);
>
> This gives you the actual package name as a Java string object. It's not a
> C-string yet. With another JNI function call you can convert it into a
> C-string. You need to make yourself familiar with JNI. It looks awkward but
> it isn't that bad in the end.
>
> Reading the package info works pretty similar. You always need a "jclass"
> object then you can use that for retrieving a method or field member and
> then you can use JNI for calling that method or for reading the value of a
> field.
>
> A few more words of advice. You should also obfuscate these native method
> names. You cannot do that with Proguard because that would break the link
> between your Java code and the native library. After all there must be a way
> for JNI to find these native methods and Proguard's obfuscation is random.
> You should apply non-sensical method names as Proguard would do:
>
>> public native void x(Context c);
>
>
> Of course that makes it harder for you to maintain your code. However, you
> can make your native code a bit more readable by using #define:
>
>> #define jni_get_package_name Java_com_example_MyClass_x
>>
>> void jni_get_package_name(JNIEnv* env, jclass clazz, jobject context) {
>> ...
>> }
>
>
>
> On Friday, March 1, 2013 10:41:08 AM UTC-6, dashman wrote:
>>
>> Thank you for some excellent suggestions.
>>
>> I've watched that google i/o a few times.
>>
>> i problem is actually doing it. e.g. just looking at the NDK and wish they
>> had a sample to read the package info etc.
>>
>> offloading app logic to server is a great idea - but my app is designed to
>> work while off-line - so that will not help me.
>>
>> i think my thinking is:
>>     - doing some checks in native code
>>     - also including some critical app functions in navtive code (thanks
>> for that suggestion)
>>     - check license with my server (if online) - and make it a requirement
>> that it
>>       needs to pass the test within a set # of days (e.g. 30).
>>
>> the problem now is that - all the user has to do is uninstall the app and
>> re-install it
>> and then they can use the app for another fixed amount of days.
>>
>>
>>>
>
> --
> --
> You received this message because you are subscribed to the Google
> Groups "Android Developers" group.
> To post to this group, send email to android-developers@googlegroups.com
> To unsubscribe from this group, send email to
> android-developers+unsubscr...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/android-developers?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Android Developers" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to android-developers+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

-- 
-- 
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Android Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to android-developers+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to