I am very new to DexGuard and Proguard. I was going through their documentation and sample examples. They have dexguard_util which helps you detect if the application is tampered with and also helps in detecting if it is running in the environment it is supposed to run. The document suggests that this tamper and environment detection be encrypted using the following code is dexgaurd-project.txt.
-encryptclasses A$D
-encryptstrings A$D
follwing is the activity
public class A extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
new D().c();
}
private class D
{
public void c()
{
//some code to which detects the tampering and environment and takes action accordingly
}
}
}
What if a hacker inject this line of code.
public class A extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//code commented by hacker
//new D().c();
}
private class D
{
public void c()
{
//some code to which detects the tampering and environment and takes action accordingly
}
}
}
Then my application will run without running those tests which I think is a big problem. Is my understanding of how reverse engineering works wrong or there are better ways of doing this. Please share better methods of doing this if they exist. Thanks in advance. Note that public class A cannot be encrypted as it is an entry point and is kept using this command in progaurd-project.txt
-keep class somepackage.A
When it comes to anti-tampering, it is important to keep in mind that their goal is not to stop any and all potential tampering efforts, but, rather, it's just a matter of raising the security bar of the target high enough to dissuade most attackers.
With that said, the
A bit of a tangent:
The document suggests that this tamper and environment detection be encrypted using the following code is dexgaurd-project.txt.
Class encryption does prevent basic static analysis of the application package, e.g. simply unzipping the package and loading it in jd-gui. However, as this answer shows, it's trivial to circumvent: one only has to hook into the static method that decrypts the apk on load, and dump it. But this allows the security bar to be raised.
Now back to your original question:
What if a hacker inject this line of code.
As an attacker, that would be the next step. However, that would require repackaging the app, and signing it with the hacker's signing key. Therefore, it is necessary to combine Dexguard's anti-tampering measures like checking the apk signature.
Is DexGuard tamper and Environment detection helpful?
In summary, yes, it is helpful in as far as it raises the bar above the vast majority of apps out there. But it's no silver bullet.
Related
Is there anyone knows SDK well enough to tell why after making my app device-owner and executing DevicePolicyManager.setApplicationHidden for a list of apps I can't then find them unless I'd put PackageManager.getInstalledApplications(PackageManager.GET_META_DATA or PackageManager.MATCH_UNINSTALLED_PACKAGES) in the query flags? (meaning just GET_META_DATA won't work and hidden applications would not be unhidden)
I try to find them to unhide them — but no success unless I am looking for uninstalled also.
My theory is that Android doesn't really hide them, but actually marking them uninstalled yet keeping all the data — but I didn't find any information regards it in the documentation. Wonder if someone can clarify this behavior (with source).
Thanks!
The naming is ambiguous but indeed setApplicationHidden effectively uninstalls the app but keeps the APK and data in storage. If you're looking for a way to prevent use of the app without uninstalling it you can try setPackagesSuspended.
You can find the source for setApplicationHidden in PackageManagerService.setApplicationHiddenSettingAsUser() (relevant abstract below). Its logic is simple:
setApplicationHiddenSettingAsUser calls packageSetting.setHidden() to mark the package as hidden for the user,
other methods of PackageManagerService call packageSetting.getHidden() to decide whether the package should be returned.
Code abstract for setApplicationHiddenSettingAsUser:
#Override
public boolean setApplicationHiddenSettingAsUser(String packageName, boolean hidden,
int userId) {
PackageSetting pkgSetting;
...
try {
...
synchronized (mPackages) {
pkgSetting = mSettings.mPackages.get(packageName);
...
if (pkgSetting.getHidden(userId) != hidden) {
pkgSetting.setHidden(hidden, userId);
mSettings.writePackageRestrictionsLPr(userId);
...
}
}
...
}
}
Recently I had opened some real apps by using this
So I'm getting the source code from that. In those source code, I found that most of the code is designed like this
public class LockActivity extends Activity {
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
if (GlobalDataHolder.m9617e()) {
bm.m8771b(getApplicationContext(), getPackageManager());
finish();
}
}
protected void onResume() {
super.onResume();
if (GlobalDataHolder.m9617e()||this.f4719a.m9124j()) {
bm.m8771b(getApplicationContext(), getPackageManager());
finish();
return;
}
startActivity(new Intent(getApplicationContext(), LaunchActivity.class));
}
public void onPause() {
super.onPause();
}
public void onDestroy() {
super.onDestroy();
}
}
And also the java file named by Garbled text such as
aa.java
bh.java
cj.java
My question is
1) Why those developer create the function named 'm8771b','m9617e'
2) Why most of apps is designed like that?
3) Is this more secure for avoid other to copy their code?
4) Should we also design the application like that?
5) How they can remember where they put the function?
People don't write code like that... unless they are either a savant or inexperienced. Using seemingly random strings of methods/class names is something called Obfuscation, which means to hide the real meaning of something in order to make it difficult to read.
Obfuscation Wiki as it pertains to software development
There are programs out there, like ProGuard which do this for us. Its purpose is to both compact and obscure code. That way it is difficult for someone to decompile and reconstruct the project without pouring over what it does (depending on complexity) endlessly.
Since Java always compiles into bytecode, it is predictable in the way in which it can be decompiled and much more standard that a write-once compile-anywhere language. ProGuard helps protect intellectual property or proprietary software and keep people from just stealing code.
I have an app which uses Google Maps (v1) and from the crash reports, I am seeing this exception from time to time:
java.lang.NoClassDefFoundError: android.security.MessageDigest
at com.google.android.maps.KeyHelper.getSignatureFingerprint(KeyHelper.java:60)
at com.google.android.maps.MapActivity.createMap(MapActivity.java:513)
at com.google.android.maps.MapActivity.onCreate(MapActivity.java:409)
I have defined
<uses-library
android:name="com.google.android.maps"
android:required="true" />
inside the application tag and I am extending MapActivity as well. The application works fine on most devices but there are some uncommon ones that report this exception, usually on Android 4.0.4 like Woxter Tablet PC 90BL, TAB9008GBBK and other generic names.
From what I read in Stackoverflow, it is a problem in the ROM and it can be solved by the user doing some advanced tricks but what I want is to prevent this crash, as I don't think it can be solved, I just want to inform the user (and thell him to buy a better device :) and disable maps functionality instead of crashing. But I can't find a way to handle this error or test it with the devices I have.
Also my main activity is based on MapActivity so I don't know how can I handle this exception before opening it.
Disclaimer: I've not come across this error on any of my apps / devices but I solved a similar problem. May be that same technique can help you.
Given that the class is either unavailable or an exception occurrs while loading the class, why not try to force load it when your application starts ? Class.forName("android.security.MessageDigest") should load the class and you can catch the Error thrown from that call. I know its dirty, but it should work. You can declare a custom Application class on the manifest to make this check.
Class loading test
try
{
Class.forName("android.security.MessageDigest");
}
catch (Throwable e1)
{
e1.printStackTrace();
//Bad device
}
You can also perform a litmus test and check the functionality of the class should the class loading succeed by digesting a simple String.
Functional test
try
{
MessageDigest digester = MessageDigest.getInstance("MD5");
digester.update("test".getBytes("UTF-8"));
byte[] digest = digester.digest();
}
catch (Throwable e1)
{
e1.printStackTrace();
// Class available but not functional
}
If the class loading / litmus test fails, update a shared preference flag and let the user know that his device sucks :)
Try to change the import android.security.MessageDigest to java.security.MessageDigest
by the look at this link:
What is 'android.security.MessageDigest''?
It looks that the android.security.MessageDigest was remove from Honeycomb so change it to the java one. and check this link as well:
http://productforums.google.com/forum/#!category-topic/maps/google-maps-for-mobile/KinrGn9DcIE
As been suggested there by #XGouchet:
Try downloading the latest version of the Google Maps API and rebuild your application with targetSDK set to the highest available (as of today it should be 17 / Jelly Bean).
The class android.security.MessageDigest is an abstract class (see MessageDigest API) what means that it can't be instantiated right away. So what happens is, that any time a device/app can't find an implementation of this class you will get the exception above, namely
java.lang.NoClassDefFoundError: android.security.MessageDigest
It's a good question why this happens. May be some phone vendors didn't ship their phone with the required library that actually implements this abstract class. I faced a similar issue with the TUN.ko module in the past.
Approach 1
What should help is, if you provide your own (empty) implementation of this class that "implements" the abstract classes and methods like this:
public class MessageDigestSpi extends Object {
byte[] engineDigest() { return new byte[0]; }
void engineReset() { }
void engineUpdate(byte[] input, int offset, int len) { }
}
public class MessageDigest extends MessageDigestSpi {
}
... and put those classes into the folder <src>/java/security/. So this way you provide your own implementation that is always found and might contain some code in order to inform the user or provide an alternative implementation.
So the remaining questions are: what does the app do, if the implementation is provided by the system, too and how to control that the system implementation is the first choice?
The answer: which implementation is chosen depends on the import order. Looking at Eclipse you can define the order in the project properties, Java build path, tab order and export. Be sure that you have any system libraries on top that might include the system implementation (most likely the Android libraries). This way the system searches in those libraries first. If nothing is found your classes get loaded and executed.
Approach 2
As an alternative to the implementation in an own abstract class you could of course simply instantiate the MessageDigest class, catch the NoClassDefFoundError exception and store the result for later evaluation:
import android.security.MessageDigest;
public class MessageDigestTester {
private static Boolean messageDigestAvailable = null;
public static Boolean isLibraryAvailable() {
if (messageDigestAvailable == null) {
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
messageDigestAvailable = true;
} catch (NoClassDefFoundError e) {
messageDigestAvailable = false;
}
}
return messageDigestAvailable;
}
}
Then use if (MessageDigestTester.isLibraryAvailable()) { } else { } in your code in order to encapsulate the usage of this library and to provide an alternative.
Approach two is easier to implement whereas approach one is the more sophisticated solution.
Hope this was helpful ... Cheers!
In my Java code, I use the Debug flag to control debug model, if is debug ,there are some extra functions,such as:sway the phone show a activity to change app version. Now I want to erase these code when publishing the code to market.
Like the code below, is there a way to make VersionSwitchService.class code is null and other code is running normal?
I mean that even if, someone decompiles the apk, VersionSwitchService.class code is seen as blank.
if (isDEBUG) {
VersionSwitchService.libStart(this, new LibVersionSwitch() {
#Override
public void versionSwitchToOnline() {
//...
}
#Override
public void versionSwitch(String version) {
//...
}
});
}
If you make isDebug final static:
final static boolean isDebug = false;
the Java compiler will complete remove the parts of code that are unreached. Sp in your example, the 'then'-part is completely omitted and thus not available in your apk.
Furthermore, when creating a (release) apk build, the Android tools will strip all methods and classes that are unused. So, if your VersionSwitchService class is only used for debugging, it will not present (due to the combination of the static final debug constant)
Has anybody had success integrating the Licensing Verification Library (LVL) with a Live Wallpaper? If it were just running an Activity, it'd be crystal clear to just extend my Activity from the Licensing Activity, which in turn extends Activity. But Live Wallpapers are a Service, and I'm not sure how the two are intended to interact.
I'm using code derived from this: http://www.droidforums.net/forum/android-app-developers/69899-market-license-easy-implementation-protect-your-apps.html which seems to be the code that nearly everything I can find on the web refers to.
I notice that wallpaper settings are an activity, and I have those working properly, but for some reason I can't grok the Licensing stuff...
It's actually really quite simple, you don't need to use any Activity class to implement licensing into a WallpaperService.
Make sure you've followed the directions carefully at http://developer.android.com/guide/publishing/licensing.html
Here's how I did it:
Your extended Engine class should include something similar to the following... (code not essential to your question has been removed)
class startYourEngines extends Engine {
public startYourEngines() {
super();
licenseStatus(); //custom license check method (for modularity)
//the rest of your engine would go here
}
public void onDestroy() {
super.onDestroy();
licenseChecker.onDestroy(); //we call this to close IPC connections
}
//prep work
private static final String BASE64_PUBLIC_KEY = //OMITTED//;
private LicenseCheckerCallback licenseCallback;
private LicenseChecker licenseChecker;
private byte[] salt = "rAnd0mStr!ng".getBytes();
private AESObfuscator aes;
private String deviceId;
//our custom license check method
private void licenseStatus() {
deviceId = Secure.getString(getContentResolver(), Secure.ANDROID_ID);
aes = new AESObfuscator(salt, getPackageName(), deviceId);
licenseCallback = new licenseVerification();
licenseChecker = new LicenseChecker(context, new ServerManagedPolicy(context, aes), BASE64_PUBLIC_KEY);
licenseChecker.checkAccess(licenseCallback);
}
//our callback method
private class licenseVerification implements LicenseCheckerCallback {
#Override
public void allow() {
//allow full app use
}
#Override
public void dontAllow() {
//prevent or limit app use
}
#Override
public void applicationError(ApplicationErrorCode errorCode) {
//error handling here
}
}
}
Licensing on the Android platform was created with versatility in mind. Just be sure to read through the documentation, and you shouldn't have any issues.
I have only written applications that start activities, but looking at my source code, it seems that the only reason that you would have to have an Activity do the license check is to show dialogs.
In all of the examples available on line, the LicenseCheckerCallback implementation always shows a dialog in the allow() and dontAllow() methods. Why not just show a toast in dontAllow() and exit your wallpaper service (call stopSelf(YourService.this))?
Let me know if you want more information, because I dont think you are limited to only using an activity for license checking. As an aside, make sure that you dont keep whole strings, etc in your app or in the preferences. Anyone with root access can access your preferences and if your app is decompiled, your strings are visible...
I think I've actually got it working now. I'm extending LicenseCheckActivity to my own Activity class that I'm calling in the manifest file with the usual MAIN action and LAUNCH category. I instantiate my class, do the license check, and then either allow the wallpaper to function or not based on that result (though the best way to do that is still something I need to sort out).
It almost seems too easy that I think I must be missing something. I'd appreciate anybody with experience with selling a licensed live wallpaper on the Android Market to share whatever wisdom they care to.