Skip to main content
  1. Ctfs/

1337UP

·4 mins
Table of Contents

🏆  318/1061 -- 700 Points

ChallangeTypePointsFinished
Secure BankRev100November 16th, 11:55:09 PM
BabyFlowWarmup50November 16th, 8:29:59 PM
Rigged Slot Machine 1Warmup50November 16th, 8:21:55 PM
Trackdown 2OSINT100November 15th, 8:09:06 PM
TrackdownOSINT100November 15th, 7:49:05 PM
Cold StorageMobile100November 15th, 5:05:44 PM
BioCorpWeb100November 15th, 3:16:32 PM
Pizza ParadiseWeb100November 15th, 2:46:25 PM

Writeups
#

Cold Storage 🐈
#


The Initial Roadblock: APK Installation Blues

Like any eager hacker starting a mobile challenge, I dove straight in trying to install the APK. However, Android had other plans for my evening:
adb install .\\cryptovault.apk

Performing Streamed Install
adb: failed to install .\\cryptovault.apk: Failure [INSTALL_PARSE_FAILED_NO_CERTIFICATES: Failed to collect certificates from /data/app/vmdl318868043.tmp/base.apk: Attempt to get length of null array]

Ah yes, the classic “where’s your signature, buddy?” error. Android, being the responsible platform it is, refuses to run applications without proper signing. It’s like trying to enter a fancy restaurant without a tie – you’ve got to dress the part!

Making Our APK Presentable

First things first, we need the Android SDK build tools. Adding them to PATH:
C:\\Users\\<USER>\\AppData\\Local\\Android\\Sdk\\build-tools\\34.0.0

The Great Decompilation Adventure

While we could jump straight to signing the APK, experience has taught us that we’ll need to decompile it anyway for our investigation. So why not kill two birds with one stone?

Time to crack open this APK like a digital coconut using apktool. For those unfamiliar with apktool, it’s like having X-ray vision for Android apps - it lets us peek inside and see what makes them tick!

apktool d .\\cryptovault.apk
cd cryptovaul
  • smali files (Android’s equivalent of assembly code - as fun to read as ancient hieroglyphics!)
  • Resource files in res/
  • The holy grail of Android app analysis: AndroidManifest.xml

Creating Our Own VIP Pass

Since we can't get in without proper credentials, let's make some! We'll create a signing key that would make any app proud:
keytool -genkey -v -keystore research.keystore -alias research_key -keyalg RSA -keysize 2048 -validity 10000

Making Everything Pretty (And Aligned)

Modern Android is picky about its APKs being aligned properly. Think of it as straightening your tie before entering:
zipalign -p -f -v 4 cryptovault.apk aligned.apk

The Final Touch: Signing Our Masterpiece

apksigner sign --ks ./research.keystore ./aligned.apk

And voilà! We now have an APK that Android will welcome with open arms.

Down the Rabbit Hole: Application Analysis 🕵️‍♂️

You can also drag-and-drop the APK directly into the emulator if you're feeling fancy.
adb install aligned.apk
Description of the image

AndroidManifest.xml

https://github.com/skylot/jadx

Diving into the manifest, we find something interesting - or rather, the lack of something interesting. Just one lonely permission:

<uses-permission android:name="android.permission.INTERNET"/>

At least our cat friend can browse cat memes while guarding the vault!

The manifest revealed a surprisingly minimalist activity structure:

<activity android:name="com.example.cryptoVault.MainActivity"> [..] </activity>

Web Assets: Where the Magic Happens

The real treasure was hidden in Resources/assets/dexopt/www. Inside, we discovered the unlockVault() function, which revealed our feline friend's secret: PIN `7331`.

It spells ‘1337’, but backwards.. wow!

After entering the correct PIN, we were rewarded with… another puzzle. An encrypted key. Because one layer of security is never enough!

Description of the image

The Final Boss: Key Decryption 🔐

The encryption scheme was hidden in an obfuscated keygen.js file. After some quality time with a deobfuscator, we uncovered the encryption algorithm:

function affineEncrypt(value, multiplier, offset) {
    return (multiplier * value + offset) % 256;
}

function xor(a, b) {
    return a ^ b;
}

...

Rather than trying to understand the entire obfuscated mess (life’s too short!), Myself ChatGPT wrote a Python script to reverse the operations and retrieve the flag:

def affine_decrypt(value, multiplier, offset):
    for x in range(256):
        if (multiplier * x) % 256 == 1:
            break
    return (x * (value - offset)) % 256

# The encrypted treasure map
encrypted_key_hex = "abf6c8abb5daabc8ab69d7846def17b19c6dae843a6dd7e1b1173ae16db184e0b86dd7c5843ae8dee15f"
encrypted_key_bytes = hex_to_bytes(encrypted_key_hex)

# Magic numbers (because every good crypto needs magic numbers)
multiplier = 9
offset = 7
xor_key = 51

# Let the decryption begin!
decrypted_bytes = [
    affine_decrypt(xor(byte, xor_key), multiplier, offset)
    for byte in encrypted_key_bytes
]

Related

Glacier
·2 mins