13 KiB
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.jsontranslation 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 |
|---|---|
![]() |
![]() |
Features
- Loads normal
.apkfiles and split.apksbundles. - Merges split APK modules into a single APK with
ARSCLib. - Patches
AndroidManifest.xmlsplit metadata and PairIP license components. - Injects helper dex code from embedded resources:
log.dexrestoreMethod.dex
- Patches PairIP startup and license classes.
- Adds a
PairipLoghelper with an app-specific dictionary path. - Detects simple PairIP junk holder classes.
- Inserts a
StartupLauncher.pairip()call afterVMRunner.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.soduring translation patching. - Rebuilds final APK output beside the input file.
Requirements
- JDK 17 or newer
- Gradle wrapper included in this repository
- A PairIP-protected
.apksor 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
.apksbundle 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


