Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BadZip + fails to unpack #4

Closed
cryptax opened this issue Dec 14, 2023 · 6 comments
Closed

BadZip + fails to unpack #4

cryptax opened this issue Dec 14, 2023 · 6 comments

Comments

@cryptax
Copy link

cryptax commented Dec 14, 2023

This sample: 0070bc10699a982a26f6da48452b8f5e648e1e356a7c1667f393c5c3a1150865 fails to be be processed by Kavanoz currently.

The first issue is a bad CRC32 for AndroidManifest.xml in the ZIP.

# kavanoz 0070bc10699a982a26f6da48452b8f5e648e1e356a7c1667f393c5c3a1150865.apk 
✸ Extracting apk/dvm informationTraceback (most recent call last):
  File "/root/.local/bin/kavanoz", line 8, in <module>
    sys.exit(cli())
  File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 1157, in __call__
    return self.main(*args, **kwargs)
  File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 1078, in main
    rv = self.invoke(ctx)
  File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 1434, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/local/lib/python3.10/dist-packages/click/core.py", line 783, in invoke
    return __callback(*args, **kwargs)
  File "/opt/kavanoz/src/kavanoz/core.py", line 59, in cli
    k = Kavanoz(filename, output_dir=output_dir)
  File "/opt/kavanoz/src/kavanoz/core.py", line 22, in __init__
    self.apk_object = APK(apk_path)
  File "/usr/local/lib/python3.10/dist-packages/androguard/core/bytecodes/apk.py", line 291, in __init__
    self._apk_analysis()
  File "/usr/local/lib/python3.10/dist-packages/androguard/core/bytecodes/apk.py", line 311, in _apk_analysis
    manifest_data = self.zip.read(i)
  File "/usr/lib/python3.10/zipfile.py", line 1478, in read
    return fp.read()
  File "/usr/lib/python3.10/zipfile.py", line 913, in read
    buf += self._read1(self.MAX_N)
  File "/usr/lib/python3.10/zipfile.py", line 1017, in _read1
    self._update_crc(data)
  File "/usr/lib/python3.10/zipfile.py", line 945, in _update_crc
    raise BadZipFile("Bad CRC-32 for file %r" % self.name)
zipfile.BadZipFile: Bad CRC-32 for file 'AndroidManifest.xml'

Kavanoz is indeed right: the CRC32 for that file is wrong.
If we fix it with the correct value, Kavanoz still fails to unpack and says the sample is not packed.

# kavanoz patched.apk 
⚠ Sample is not packed
❌ Cannot unpack

This is incorrect. The encrypted payload is present in ./assets/moqls/oxcsbcc.joi.
The file is decrypted, dumped, dynamically loaded and deleted.
See my blog post for more info if you wish: https://cryptax.medium.com/bad-zip-and-new-packer-for-android-bianlian-5bdad4b90aeb

I attempted to write a very quick static decryptor, but it's not working yet. The code is basically copy pasted from the malware.

@eybisi
Copy link
Owner

eybisi commented Dec 14, 2023

Thanks for heads up. I manually patched androguard to bypass crc checks. This case should be decrypted in this function here. To debug such cases as this, try to add -vvv as parameter

I've added third plan for finding key in multidex. Now key is found as "捨뺑戚\ue684聳踖曡㒕躚\udafdﶃ킎" but fails to decrypt payload. I will try debug the decryption function.

@eybisi
Copy link
Owner

eybisi commented Dec 15, 2023

Found the issue, key is incorrect.

 INFO     | multidex:brute_assets:416 - Starting brute-force inflate 捨뺑戚\ue684聳踖曡㒕躚\\udafdﶃ킎 for file : assets/moqls/oxcsbcc.joi
 INFO     | multidex:solve_encryption2:441 - Start of encrypted data b'U\x9e\x01d\xd4'
sput-object v0, Ltsn/sooukgb/ifosbvtru/btqv/dgokr;->pqaarcapibyjtdxwstukh Ljava/lang/String;
const-string v0, '捨뺑戚\ue684聳踖曡㒕躚\\udafdﶃ킎'
sput-object v0, Ltsn/sooukgb/ifosbvtru/btqv/dgokr;->xofephmnksi Ljava/lang/String;

There are two reasons we fail here:
1 - Kavanoz was not handling unicode escapes.
2 - Androguard 3.3.5 was giving wrong key .

Androguard (v3.3.5) prints second unicode with additional "\" . Now deep diving into androguard source code, changing this line to just return s makes it return correct. Upgrading androguard to version v3.4.0a should fix this, now they are not callling patch_string. But that version breaks some apis. I will look into that.

I've committed unicode handling to multidex loader, can you test it again by changing androguard source code? My output for this sample :

λ kavanoz /tmp/0070BC10699A982A26F6DA48452B8F5E648E1E356A7C1667F393C5C3A1150865.apk
⚠ Sample is not packed
✨ Unpacked succesfully!
Plugin tag : loader.multidex
Plugin description : Unpacker for multidex variants
Output file : ./external-44d56932.dex

@eybisi
Copy link
Owner

eybisi commented Dec 15, 2023

Upgrading to androguard v3.4.0a1 fixed the extra "\" issue.

@cryptax
Copy link
Author

cryptax commented Dec 15, 2023

Yep, it works on the patched file now cool :)
Is there a way you can ignore the ZIP issue? zipfile.BadZipFile: Bad CRC-32 for file 'AndroidManifest.xml'

@eybisi
Copy link
Owner

eybisi commented Dec 15, 2023

AFAIK only way is to edit zipfile library

@cryptax cryptax closed this as completed Dec 15, 2023
@erev0s
Copy link
Contributor

erev0s commented Dec 17, 2023

@cryptax @eybisi androguard 4.0.0 has https://github.com/erev0s/apkInspector integrated which means that it is now capable of parsing badly formatted apk files.

This means that it is very likely you will not have an issue with this Bad CRC-2 error.
I have also updated Androguard to tackle certain cases for tampering on the AndroidManifest itself.

I can see kavanoz uses the version 3.4.0 of Androguard and in order to integrate the latest version(4.0.0) some adjustments are required as Androguard has changed a lot in the past years.

If i have enough time in the upcoming weeks i will create a PR to try out the new version of Androguard in combination with kavanoz.

Also @cryptax please share any apk that could be used as a POC to try out edge cases. Also please keep in mind that apkInspector can also fetch the AndroidManifest from packed APKs, but it will be more on the "raw" side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants