APK → libgame.so → game

From an old APK to a game you can play again

No original source code was available. We took facts from the APK, rewrote them in TypeScript, and verified the result in Cocos Creator.

Part 1

What do we get from the APK?

Extract it once to separate the resources, decompiled Java from the app package, and the native library.

Method

  1. Verify the hash so the APK cannot change unnoticed.
  2. Run scripts/inventory-apk.sh extract; it uses JADX for classes.dex and extracts libgame.so.
  3. Keep the output unchanged as the reference for later work.
One slice of the extracted data
jadx/resources/…
java/app-owned/PencilBlade.java
java/app-owned/R.java
native/libgame.so

Result: 862 resources, 3 decompiled Java files from the app package, and one libgame.so.

Part 2

Read libgame.so and connect it to resources

Find functions, constants, and path strings; then match those paths to the resources extracted in Part 1.

Method

  1. Use readelf and nm -C to identify the architecture, symbols, and addresses.
  2. Run scripts/analyze-native-static.sh to map functions, calls, constants, and string xrefs.
  3. Match each path xref to the same resource path, then write the behavior as a tested contract.
Excerpt from the function map
0x00145538  Bomb::onEnter()
string_xref → "Bomb/bomb_X.png"
string_xref → "Sounds/boomsound.wav"

Result: the Bomb::onEnter() handler connects to the bomb_X.png sprite and boomsound.wav sound. The same method handles the remaining evidence.

Open the detailed forensics

Part 3

Try the game

The contracts were rewritten in TypeScript, connected to the recovered resources, and run in Cocos Creator 3.8.8. This is a reconstruction, not the original runtime; it never loads or links libgame.so.

Method

  1. Open the Web H5 build.
  2. Press Play to load the game.
  3. Choose a mode and try slicing fruit.
Main Menu of the reconstructed Pencil Blade Web H5 build.
Capture from the current H5 build.Try the game

Result: the reconstruction runs in the browser with all 6 game modes.