When publishing Unity3D projects on iOS, a practical issue arises: resources and logic are relatively separated. Assembly-CSharp.dll, AssetBundles, configuration files, and even some script content can be individually replaced. If someone obtains the IPA, unpacks it, modifies resources, and re-signs it, they can generate a version that functions normally but has altered logic.

In a Unity project with in-app purchases and a numerical system, we encountered a resource replacement problem: changing just one configuration file bypassed the in-game currency logic. Subsequently, we separated anti-tampering for dedicated handling.

The following process is organized around the characteristics of Unity3D iOS applications, focusing on how to detect and prevent modifications to resources and binaries.


Unpacking IPA to Examine Unity Structure

First, look at the structure of a Unity iOS application after unpacking:

Payload/App.app/
 ├─ Data/
 │   ├─ Managed/
 │   │   └─ Assembly-CSharp.dll
 │   ├─ Raw/
 │   ├─ Resources/
 │   └─ globalgamemanagers
 ├─ Frameworks/
 └─ AppBinary

Key points:

  • Assembly-CSharp.dll: C# logic
  • Data directory: Resources and configurations
  • AppBinary: iOS native binary

Tampering behaviors typically focus on:

  • Modifying DLLs
  • Replacing resource files
  • Modifying configuration JSONs

Verifying Critical Resources

Unity itself does not verify resource integrity, so validation logic needs to be added in the code.

For example, calculate resource hashes during application startup:

MD5(file) == expected_hash

Implementation methods:

  • Generate an MD5 list of resources during build time
  • Write the list into code or store it encrypted
  • Verify each item during startup

If inconsistencies are found, you can:

  • Prevent startup
  • Or restrict certain functions

This step primarily prevents direct resource replacement.


Handling Assembly-CSharp.dll

Unity’s C# logic is compiled into DLLs but can still be decompiled.

Tools can be used:

  • IL2CPP (converts C# to C++)
  • Or code obfuscation tools

If the project has already generated an IPA, supplementary processing can be done directly at the IPA layer.

Ipa Guard supports obfuscation of Unity3D application binaries, including:

  • Function names
  • Class names
  • Method parameters

Although the DLL itself is not in the Mach-O, in Unity-exported iOS projects, some logic is compiled into the native layer or symbol tables, and these contents can still be processed.


Hiding Resource File Structure

Unity’s resource directories often have clear structures, for example:

Data/Resources/config.json
Data/Raw/level1.assetbundle

These names directly expose game logic.

At the IPA layer, Ipa Guard can be used to process resources:

  • Modify file names
  • Synchronously update reference paths

For example:

config.json → a82kd.json
level1.assetbundle → k39sd.bundle

After processing, unpacking the IPA again will make resource names incomprehensible.

Resource Obfuscation


Modifying Resource Fingerprints (Preventing Reuse)

If attackers directly extract resources and reuse them in other applications, file fingerprints can serve as identification criteria.

Ipa Guard supports modifying resource MD5s:

  • File content remains consistent
  • Fingerprint changes

Verification can be performed:

md5 level1.assetbundle

Results differ before and after processing.
MD5 Modification


Handling Images and UI Resources

UI images in Unity projects may also be extracted.

During resource processing, you can:

  • Modify image names
  • Add invisible watermarks

Watermarks do not affect display but can mark resource sources.


Cleaning Debug Information and Logs

Unity builds may include debug information.

Check:

strings AppBinary | grep Unity

If the output contains debug logs, they can be cleaned during IPA processing.

Ipa Guard supports removing some debug information to increase reverse engineering difficulty.


Binary Layer Anti-Tampering

In addition to resource verification, simple detection logic can be added at the native layer, for example:

  • Verify the hash of AppBinary
  • Detect if critical files have been modified

This logic can be written in native code.

Combined with Ipa Guard’s symbol obfuscation, the probability of bypassing these detection logics can be reduced.


Re-signing and Installation Testing

After all modifications are complete, re-signing is required.

You can use:

kxsign sign app.ipa \
-c cert.p12 \
-p password \
-m dev.mobileprovision \
-z test.ipa \
-i

Or directly complete signing in Ipa Guard.

After installation, focus on testing:

  • Resource loading
  • Scene switching
  • AssetBundle loading
  • In-app purchase processes
    Re-signing

The tampering risk for Unity3D applications mainly concentrates on the resource and configuration layers, rather than mere code decompilation. Through resource verification, file renaming, MD5 modification, debug information cleaning, and binary obfuscation, tampering costs can be significantly increased.

Reference link: https://ipaguard.com/blog/155