Files
RePairip/README.md
T
2026-06-12 02:10:13 +06:00

13 KiB

RePairip logo

RePairip

A Java reverse-engineering utility for analyzing and rebuilding Android APK/APKS packages that use Google Play PairIP protection.

Current version: 1.4.14  |  Language: Java 17  |  Build: Gradle + Shadow Jar


Overview

RePairip is a command-line tool that works with PairIP-protected Android packages. It can merge split .apks packages, patch PairIP-related dex code, clean split metadata from the manifest, rebuild the APK, and optionally apply a static translation JSON to restore dumped PairIP values.

The project focuses on two workflows:

  • Dynamic dump/logging workflow: merge an .apks, inject logging support, patch PairIP launcher/signature logic, rebuild the APK, and preserve selected dex CRC values.
  • Static translation workflow: take a merged APK plus a pairip.json translation file, rewrite PairIP classes, restore strings/method references, remove unused PairIP runtime pieces, and rebuild a translated APK.

The dex rewriting logic is built on top of the open-source smali/dexlib2 ecosystem.


Screenshots

App UI Dump Style
App UI Dump Style

Features

  • Loads normal .apk files and split .apks bundles.
  • Merges split APK modules into a single APK with ARSCLib.
  • Patches AndroidManifest.xml split metadata and PairIP license components.
  • Injects helper dex code from embedded resources:
    • log.dex
    • restoreMethod.dex
  • Patches PairIP startup and license classes.
  • Adds a PairipLog helper with an app-specific dictionary path.
  • Detects simple PairIP junk holder classes.
  • Inserts a StartupLauncher.pairip() call after VMRunner.invoke().
  • Rewrites signature/integrity checks to return safe values.
  • Applies translation data from a JSON file.
  • Extracts embedded dex payloads from top-level PairIP assets when needed.
  • Removes libpairipcore.so during translation patching.
  • Rebuilds final APK output beside the input file.

Requirements

  • JDK 17 or newer
  • Gradle wrapper included in this repository
  • A PairIP-protected .apks or already merged .apk

Build

Windows

gradlew.bat assemble

Linux / macOS

./gradlew assemble

The final jar is generated here:

antik/build/libs/RePairip.jar

The jar entry point is:

com.antik.Main

Usage

1. Merge and patch an APKS bundle

java -jar antik/build/libs/RePairip.jar -i input.apks

This flow:

  • extracts the .apks bundle into a temporary directory
  • merges split APK modules
  • patches manifest split/license metadata
  • patches dex files for PairIP logging and launcher behavior
  • writes a merged output APK
  • writes a PairIP-patched output APK

Expected output names:

input_merged.apk
input_merged_pairip.apk

2. Apply a translation JSON to an APK

java -jar antik/build/libs/RePairip.jar -i input.apk -t pairip.json

This flow:

  • loads the APK
  • reads pairip.json
  • rewrites selected PairIP classes
  • restores static string/method values
  • adds required embedded dex payloads when needed
  • removes native PairIP runtime library entries
  • writes a translated APK

Expected output name:

input_translated.apk

Translation JSON Format

The translation file is a JSON object keyed by class name. Each class entry contains a value type and a fields object.

Example:

{
  "com.example.SomePairipHolder": {
    "type": "java.lang.String",
    "fields": {
      "a": "restored value",
      "b": "another restored value"
    }
  },
  "Lcom/example/MethodHolder;": {
    "type": "java.lang.reflect.Method",
    "fields": {
      "m0": "com.example.Target->methodName(java.lang.String):void"
    }
  }
}

Supported type forms include:

java.lang.String
Ljava/lang/String;
java.lang.reflect.Method
Ljava/lang/reflect/Method;

Class names can be written as Java-style names or dex descriptors:

com.example.ClassName
Lcom/example/ClassName;

How It Works

Full Pipeline

// RePairip high-level flow
//
//                 input
//                   |
//        +----------+----------+
//        |                     |
//       .apk                  .apks
//        |                     |
//        |              +------v------+
//        |              |  Extract    |
//        |              |  Splits     |
//        |              +------+------+
//        |                     |
//        |              +------v------+
//        +------------->|  Merge APK  |
//                       +------+------+
//                              |
//                    +---------v----------+
//                    | Patch Manifest     |
//                    | - split metadata   |
//                    | - license entries  |
//                    +---------+----------+
//                              |
//                  +-----------v------------+
//                  | Translation provided?  |
//                  +-----------+------------+
//                       yes    |     no
//                              |
//        +---------------------+--------------------+
//        |                                          |
// +------v------+                           +-------v-------+
// | Rewrite     |                           | Logging Patch |
// | PairIP dex  |                           | + Dex Patch   |
// +------+------+                           +-------+-------+
//        |                                          |
// +------v------+                           +-------v-------+
// | Add restore |                           | Patch CRC32   |
// | dex/assets  |                           | if available  |
// +------+------+                           +-------+-------+
//        |                                          |
//        +---------------------+--------------------+
//                              |
//                       +------v------+
//                       | Build APK   |
//                       +------+------+
//                              |
//                           output

Dynamic Dump / Logging Patch

// Before
//
//             app start
//                |
//        +-------v--------+
//        | StartupLauncher |
//        | launch()        |
//        +-------+--------+
//                |
//        +-------v--------+
//        | VMRunner.invoke |
//        +-------+--------+
//                |
//              return
//
//
// After
//
//             app start
//                |
//        +-------v--------+
//        | StartupLauncher |
//        | launch()        |
//        +-------+--------+
//                |
//        +-------v--------+
//        | VMRunner.invoke |
//        +-------+--------+
//                |
//        +-------v--------+
//        | pairip()        |
//        | dump/log values |
//        +-------+--------+
//                |
//              return

Static Translation Patch

// Before
//
//          PairIP classes
//               |
//     +---------v----------+
//     | Obfuscated fields  |
//     | VM/runtime restore |
//     +---------+----------+
//               |
//        runtime lookup
//               |
//             return
//
//
// After
//
//          pairip.json
//               |
//     +---------v----------+
//     | TranslationData    |
//     | class -> fields    |
//     +---------+----------+
//               |
//     +---------v----------+
//     | TranslationRewriter|
//     | restore statically |
//     +---------+----------+
//               |
//     +---------v----------+
//     | Clean PairIP flow  |
//     | remove runtime lib |
//     +---------+----------+
//               |
//          translated APK

Manifest Patch

// AndroidManifest.xml cleanup
//
//     manifest/application
//              |
//   +----------v-----------+
//   | Remove split flags   |
//   | requiredSplitTypes   |
//   | splitTypes           |
//   | isSplitRequired      |
//   | isFeatureSplit       |
//   +----------+-----------+
//              |
//   +----------v-----------+
//   | Remove Play metadata |
//   | vending splits       |
//   | stamp source/type    |
//   +----------+-----------+
//              |
//   +----------v-----------+
//   | Remove PairIP license|
//   | activity/provider    |
//   | CHECK_LICENSE perm   |
//   +----------+-----------+
//              |
//       patched manifest

Signature / Integrity Patch

// Target methods
//
//   verifySignatureMatches()
//   verifyIntegrity()
//
//
// Before:
//
//       entry
//         |
//   +-----v------+
//   | original   |
//   | validation |
//   +-----+------+
//         |
//      result
//
//
// After:
//
//       entry
//         |
//   +-----v------+
//   | fixed safe |
//   | return     |
//   +-----+------+
//         |
//   true / void / null

Class Rewrite Map

// Translation mode class handling
//
//   Lcom/pairip/Application;          -> clean constructor + clinit
//   Lcom/pairip/StartupLauncher;      -> launch + restoreString + restoreMethod
//   Lcom/pairip/VMRunner;             -> private constructor + invoke returns null
//   Lcom/pairip/licensecheck3/...;    -> clean constructor + no-op activity hook
//   Other com/pairip/* classes        -> removed unless explicitly kept

Project Structure

RePairip/
├── antik/
│   ├── build.gradle.kts
│   └── src/main/
│       ├── java/com/antik/
│       │   ├── Main.java
│       │   ├── AntikUtils.java
│       │   ├── DexPatcher/
│       │   │   ├── DexPatcher.java
│       │   │   ├── MethodT/
│       │   │   ├── PairipMethodMake/
│       │   │   └── Translation/
│       │   ├── crc32/
│       │   ├── manifest/
│       │   ├── ui/
│       │   └── utils/
│       └── resources/
│           ├── log.dex
│           ├── restoreMethod.dex
│           └── info.txt
├── gradle/
├── preview/
├── build.gradle.kts
├── settings.gradle.kts
└── README.md

Important Source Files

File Purpose
Main.java CLI argument parsing and main APK/APKS workflow
manifestP.java Manifest split/license metadata cleanup
DexPatcher.java Dynamic logging dex patch flow
patchLauncher.java Rebuilds StartupLauncher and creates pairip()
patchLaunchMethod.java Inserts StartupLauncher.pairip() after VMRunner.invoke()
patchM.java Rewrites signature/integrity methods
TranslationPatcher.java Static translation patch workflow
TranslationData.java Parses and normalizes pairip.json
TranslationRewriter.java Rewrites known PairIP classes
crc32.java Copies dex CRC values from merged source APK to patched APK

Dependencies

Dependency Use
org.smali:dexlib2 Read and write dex classes/methods/instructions
com.github.REAndroid:ARSCLib Load, merge, patch, and write APK/APKS modules
com.google.guava:guava Utility dependency
com.gradleup.shadow Build the runnable fat jar

Notes

  • RePairip writes generated APK files beside the input file.
  • Temporary APKS extraction folders are deleted after processing.
  • APK signing is not handled by this tool. Sign the rebuilt APK with your preferred Android signing workflow.
  • Results can vary by PairIP version and app build layout.
  • If you find a bug, open an issue with the input type, command, stack trace, and expected behavior.

Contributing

Contributions are welcome. Good areas for improvement include:

  • better PairIP version detection
  • stronger translation JSON validation
  • more detailed error messages
  • test APK fixtures
  • signing workflow documentation
  • additional dex rewrite strategies

Please keep patches focused and include enough detail to reproduce any bug you fix.


License

This project is distributed under the Apache License 2.0.

Apache License
Version 2.0, January 2004
https://www.apache.org/licenses/

Copyright (C) 2026 HighCapable