Home - Galaxy1036/GalaxyLifeReborn GitHub Wiki

We'll start reverse engineering the game using the android version (sha1: F05CA57582ECE97856B66589B4C07B0AEB733A40, version: 1.7.0). First it look like our game is using a native library as we can see it in /lib/armeabi-v7a/libGalaxyLifePocketAdventures.so. This lib contains all the important stuff, but before looking at it we'll have to see how it is loaded.

Like every android app the entry point of the app is situed in the java code (that is packed as Dalvik bytecode in classes.dex), the entry point is basically the onCreate function of the main class. The main class is defined in AndroidManifest.xml (that can be decompressed using apktool), by looking at it it seems that our main class is com.digitalchocolate.igalaxy.iStarNativeActivity. Now let's take a look at the onCreate function.

protected void onCreate(Bundle bundle) {
    UbiDebug.v(TAG, "onCreate");
    super.onCreate(bundle);
    createBundle = bundle;
    setVolumeControlStream(3);
    if (isFirstTimeSplashScreen) {
        startActivity(new Intent(this, splashScreenActivity.class));
        isFirstTimeSplashScreen = false;
    }
    flurryHelper = new FlurryHelper(this);
}

It look like the work is delegated to the parent class as we can see here super.onCreate(bundle), parent class is defined here

iStarNativeActivity extends UbiAppStartUpNativeActivity

Let's take a look at UbiAppStartUpNativeActivity onCreate function

protected void onCreate(Bundle bundle) {
    UbiDebug.v(TAG, "onCreate");
    if (!UbiNativeActivity.s_gameAlreadyStarted) {
        UbiDebug.v(TAG, "lifecycle Dynamically link required native libraries before continuing with startup");
        try {
            UbiAppStartUpRuntime.onCreate(this, bundle);
            onNativeCreate(UbiAppStartUpNativeActivity.class, bundle);
        } catch (Throwable e) {
            UbiDebug.e(TAG, "Native implementation of UbiAppStartUpNativeActivity.onNativeCreate not found.", e);
        }
        this.m_deltaRotationDegrees = 0.0f;
        this.m_scaleDetector = new ScaleGestureDetector(this, new ScaleListener());
        this.m_rotateDetector = new RotateGestureDetector(this, new RotateListener());
        this.m_rotateGestureProgress = GestureProgress.GESTURE_NOTSTARTED;
        UbiNativeActivity.s_gameAlreadyStarted = true;
    }
    super.onCreate(bundle);
}

It seems that this function call UbiAppStartUpRuntime.onCreate and setup some other things like rotation detector (super.onCreate doesn't interest us here), again let's look at UbiAppStartUpRuntime.onCreate.

public static void onCreate(Activity activity, Bundle bundle) {
    UbiDebug.v(TAG, "onCreate");
    try {
        String string = activity.getPackageManager().getActivityInfo(activity.getIntent().getComponent(), 128).metaData.getString("android.app.lib_name");
        try {
            System.loadLibrary(string);
        } catch (Throwable e) {
            UbiDebug.e(TAG, "Exception encountered loading native library: " + string, e);
        }
    } catch (Throwable e2) {
        UbiDebug.e(TAG, "Couldn't find activity info for: 128", e2);
    }
}

Finally !!! We got it, our lib get loaded here. As you can see System.loadLibrary get called with the lib name as params, the lib name is stored in the variable string. It is the direct result of activity.getPackageManager().getActivityInfo(activity.getIntent().getComponent(), 128).metaData.getString("android.app.lib_name") which basically look into the AndroidManifest.xml and search for the android.app.lib_name key value. This value can be found at this line <meta-data android:name="android.app.lib_name" android:value="GalaxyLifePocketAdventures"/>. As we can see it the key value is "GalaxyLifePocketAdventures", the System.loadLibrary is simply gonna prefix it with 'lib' and suffix it with '.so' and open this it. libGalaxyLifePocketAdventures.so get loaded and all the fun start here :)

Native lib reverse engineering

Let's open the library in IDA Pro (v7.0), it look like strings are there and even debug symbols, that's gonna help us a lot :) . After digging a bit in the lib it look like the "entry point" sub is the one called ANativeActivity_onCreate. This sub will initialize the game, we'll follow the following way: ANativeActivity_onCreate -> sub_4DAC58 (called as a routine by pthread_create) -> android_main -> UbiAppStartUpNativeActivity::onCreate -> UbiAppStartUpRuntime::onCreate -> ApplicationSetConfiguration. This last sub will simply setup some event that will get triggered during the app lifecycle. The event that interest us is the one called istar::iStarNativeActivity::onAppDidLaunch, as it's name let suppose it this event will be triggered when the app start. Let's look at this sub deeper: image This sub call a lot of other sub, bcn::GameApp::CreateEntryPoint will be the one that interest us: image

After looking at it, it seems to create an instance of istar::GameApplication. This instance is responsible of the whole game data loading (scene graphic, online data etc...). Let's RE that :)

Reverse glossary: