Skip to main content

SoftCloak

The goal of this repository is to try and make reverse engineering more difficult. Currently only focused on APK files but will eventually move on to IPA files, binaries, firmware, and other software.

SoftCloak replaces text inside an APK, then signs the rebuilt package. Substring matches are swapped for one generated token of the same length. Exact matches are swapped for text you choose. The APK is signed with a new jar signature.

Same-length replacements keep the DEX, manifest, and resource table aligned, so the file can still be installed.

Install

A JDK is required. keytool and jarsigner must be on PATH.

Android SDK build-tools are optional. When ANDROID_HOME or ANDROID_SDK_ROOT points at an SDK, SoftCloak signs with apksigner and writes v1, v2, and v3 signatures. If apksigner cannot read minSdkVersion from the manifest, the APK is signed with --min-sdk-version 1. Without build-tools, SoftCloak signs with jarsigner and prints a warning: the result is a JAR v1 signature, and an app with targetSdk 30 or higher will not install on Android 11 or later.

pip install softcloak

If softcloak is not found after that, the scripts directory is not on PATH. Use python -m softcloak in the examples below.

Command line

Generate a token for every occurrence of a substring:

python -m softcloak app.apk -o rebuilt.apk --contains com.example --contains CompanyName

Replace one exact string with your own text. The new text has to be the same length:

python -m softcloak app.apk -o rebuilt.apk --exact "Old full sentence" "New full sentence"

Both can be combined. Exact replacements run first, then substring tokens. The command prints each mapping and checks the signature before it finishes.

python -m softcloak app.apk -o rebuilt.apk --dry-run --contains CompanyName
python -m softcloak app.apk -o rebuilt.apk --exact "abcdef" "xy" --fit pad
python -m softcloak app.apk -o rebuilt.apk --contains CompanyName --keystore my.keystore --storepass secret --alias mykey

--fit pad fills a shorter exact replacement. --fit clip cuts a longer one and pads a shorter one. The default is to stop when the lengths differ.

--contains replaces that text wherever it sits inside a longer string, in every file, in both UTF-8 and UTF-16. A dotted name also rewrites the DEX form with slashes, so com.example changes Lcom/example/... as well. An exact replacement does the same, and keeps the separator you would expect: com.example to org.example also rewrites com/example to org/example. Matching is case-sensitive. Pass AppName and appname separately. Patterns shorter than 4 characters are allowed, but they can hit unrelated bytes, and SoftCloak prints a warning.

Image, audio, font, and native-library bytes are left unchanged. A stored native library is repacked so its bytes start on a 16384-byte boundary, which covers 4 KB and 16 KB memory pages. Signature files are removed and replaced by the new signature. Other META-INF files are kept and edited. The generated certificate subject is CN=SoftCloak and the default alias is repack. Pass --keystore and --alias to use your own. The zip writer uses the classic zip format, so an archive over 4 GB or with more than 65535 entries is out of scope.

Python

Skip the command line and call the same operation from a script:

from softcloak import rewrite_apk

result = rewrite_apk(
    "app.apk",
    "rebuilt.apk",
    contains=["com.example", "CompanyName"],
    exact=[("Old full sentence", "New full sentence")],
)
for rule in result.rules:
    utf8_count, utf16_count = result.counts[rule.old]
    print(f"{rule.old} -> {rule.new}  utf8={utf8_count} utf16={utf16_count}")
print(result.output)

Preview the mapping without writing a file:

result = rewrite_apk(
    "app.apk",
    "rebuilt.apk",
    contains=["CompanyName"],
    dry_run=True,
)

result.counts maps each original string to (utf8_matches, utf16_matches). result.warnings lists matches that were left unchanged. result.output is the signed APK, or None when dry_run is true.

Other arguments match the command line: seed, fit ("error", "pad", or "clip"), pad_char, allow_missing, keystore, storepass, keypass, and alias.

Development

From a checkout of this repository:

pip install -e ".[dev]"

The dev extra installs Ruff. The test suite runs ruff check and ruff format --check.

What can break the app

SoftCloak changes only the text you pass in. A same-length rename of your own package or class name can still install and run, because the manifest and classes.dex are updated together.

The app can crash or fail a lookup when a replacement has to match something that was not changed:

  • Framework names such as android or java appear inside system class names. Replacing them makes those calls invalid. A short warning exists for patterns under 4 characters, and it does not stop the run. android is long enough to pass through with no warning.
  • Resource paths, such as res/layout/..., must match the file names in the APK. SoftCloak does not rename those files.
  • Native libraries are left unchanged. If code now looks up a new name and the library still has the old one, that call fails.
  • Intent actions, content-provider authorities, and server URLs fail when only one side of the match is replaced.
  • A JAR v1 signature alone fails install for an app whose targetSdk is 30 or higher. Point ANDROID_HOME at Android SDK build-tools so the rebuilt APK gets a v2 signature.

Metadata

Release files for softcloak 1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for softcloak 1.1
File Size Uploaded
softcloak-1.1.tar.gz 17.3 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for softcloak 1.1
File Interpreter ABI Platform
softcloak-1.1.0-py3-none-any.whl Python 3 none any Details
softcloak-1.1-py3-none-any.whl Python 3 none any Details

Total release size: 44.4 kB

Release files / softcloak-1.1.tar.gz

Download URL softcloak-1.1.tar.gz
Size 17.3 kB
Tags Source
SHA-256 checksum
How to use checksums
3d2ce3ff325e68a35a4cf73226be315984b7884c0395c8931154a3ff8639b5bb
BLAKE2b-256 checksum
How to use checksums
c88301cc67f504b7a6efc30de8f327f00b30c52c7a1c30aa4cda313a826167c2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release files / softcloak-1.1.0-py3-none-any.whl

Download URL softcloak-1.1.0-py3-none-any.whl
Size 13.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bab4f19ed75d797e0de457462c58e08561499e1dda78f70ba49de65e49760515
BLAKE2b-256 checksum
How to use checksums
076a944c06732e56a2903fd92ee4676b12ed781df5587089e8cb6810457714b3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release files / softcloak-1.1-py3-none-any.whl

Download URL softcloak-1.1-py3-none-any.whl
Size 13.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
f5ad72bf36b2498465af4e2e9ef4430541b887c4979f19444ff8eae1bcb8e8e1
BLAKE2b-256 checksum
How to use checksums
426164244945d53cfa828e87280a398fe6f94ad3aac3ea8741706f7cc97397b9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 12, 2026.

Transparency log

Release history Release notifications | RSS feed

2.0.1

2 release files

2.0.0

2 release files

1.1.1

2 release files

This release

1.1 This release

3 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page