Jump to content
Tuts 4 You

Titanium (Python Obfuscator)


Go to solution Solved by Extreme Coders,

Recommended Posts

Posted

Titanium (Python Obfuscator)


This is my first crackme, so I may have screwed up some things, but overall it should be a fun challenge. The file is protected with my own packer/obfuscator, Titanium, and compiled with pyinstaller. Read the readme before reversing.


 

  • 2 months later...
  • Solution
Extreme Coders
Posted

Correct Key:

  Reveal hidden contents

WriteUp:

Running crackme.exe prompts for a key and prints "Bad key!" if its incorrect.

  Reveal hidden contents

As per the challenge description, this crackme is a PyInstaller generated executable. The "protection" is implemented in the C extension (native library) titanium.pyd which we can obtain after extracting with Pyinstxtractor.

Decompiling crackme.pyc with uncompyle6, we get this code.

# uncompyle6 version 3.8.0
# Python bytecode 3.7.0 (3394)
# Decompiled from: Python 3.8.12 (default, Oct 17 2021, 23:37:02) [MSC v.1929 64 bit (AMD64)]
# Embedded file name: crackme.py
import lzma, base64
from titanium import __titanium_runtime__
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import os, zlib
__titanium_runtime__('linear', b'x\x9c%\xd79\xb2$!......[snip].....x9e\xf8', 10, False)
# okay decompiling crackme.pyc

The protection tries to mimic pyarmor in the sense that pyarmor also has a pyarmor_runtime function which is called with similar set of arguments. __titanium_runtime__ is defined in the C extension titanium.pyd. Python extensions are commonly written in C but can also be written in Python itself using Cython. The crackme follows the later approach. Cython "compiles" the python bytecode to native code which is generally difficult to RE than plain Python code.

At this point it may look as if we've to analyze titanium.pyd to understand what its going on, but there easier ways. :)

The fastest way

Note the string "Bad key!". We can search for this string in memory of the crackme process. Since this is a pyinstaller generated executable there will be two crackme processes. We need to scan the child process, (with PID 5600 in the image below)

  Reveal hidden contents

Searching for "Bad key!" we get to

  Reveal hidden contents

A little above is the base64 encoded correct key

anRyfFlAWjJvSzpNZnxQOGVNUVRbLF4jfTdYMGx+

which after decoding reveals the correct key.

  Reveal hidden contents

The logical way

Instead of searching for "Bad key!" in memory its also possible to have the crackme print its real code bypassing titanium entirely.
Note the lzma, zlib imports at the top of crackme.py. Obfuscators commonly compress and then encrypt the code. Doing the other way doesn't make sense as encrypted code won't be compressible. This implies while executing its decryption followed by decompression.

Python is a dynamic language which makes it possible to replace the implementation of any function at runtime. Using this we can "hook" lzma.decompress and check out the decompressed result.

  Reveal hidden contents

Before running the above code in Python 3.7, ensure that PyCryptoDome is installed and titanium.pyd is in the same directory as the crackme.

  Reveal hidden contents

Base64 decoding the exec-d string "X0I9YidVbXhHY1Z........WNsYXJlX18oKQ==", we get this minified Python  code.

  Reveal hidden contents

which after formatting comes to

  Reveal hidden contents

The correct key is in the last exec-d string as we also found earlier.

  • Like 5
  • Thanks 3
  • 1 month later...
Posted

good reversing skill of yours. good for you.

thank you for your explanation.

regards.

sean.

  • Like 1
  • 2 months later...
Posted
  On 11/13/2021 at 5:56 AM, Extreme Coders said:

Correct Key:

  Reveal hidden contents

WriteUp:

Running crackme.exe prompts for a key and prints "Bad key!" if its incorrect.

  Reveal hidden contents

As per the challenge description, this crackme is a PyInstaller generated executable. The "protection" is implemented in the C extension (native library) titanium.pyd which we can obtain after extracting with Pyinstxtractor.

Decompiling crackme.pyc with uncompyle6, we get this code.

# uncompyle6 version 3.8.0
# Python bytecode 3.7.0 (3394)
# Decompiled from: Python 3.8.12 (default, Oct 17 2021, 23:37:02) [MSC v.1929 64 bit (AMD64)]
# Embedded file name: crackme.py
import lzma, base64
from titanium import __titanium_runtime__
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import os, zlib
__titanium_runtime__('linear', b'x\x9c%\xd79\xb2$!......[snip].....x9e\xf8', 10, False)
# okay decompiling crackme.pyc

The protection tries to mimic pyarmor in the sense that pyarmor also has a pyarmor_runtime function which is called with similar set of arguments. __titanium_runtime__ is defined in the C extension titanium.pyd. Python extensions are commonly written in C but can also be written in Python itself using Cython. The crackme follows the later approach. Cython "compiles" the python bytecode to native code which is generally difficult to RE than plain Python code.

At this point it may look as if we've to analyze titanium.pyd to understand what its going on, but there easier ways. :)

The fastest way

Note the string "Bad key!". We can search for this string in memory of the crackme process. Since this is a pyinstaller generated executable there will be two crackme processes. We need to scan the child process, (with PID 5600 in the image below)

  Reveal hidden contents

Searching for "Bad key!" we get to

  Reveal hidden contents

A little above is the base64 encoded correct key

anRyfFlAWjJvSzpNZnxQOGVNUVRbLF4jfTdYMGx+

which after decoding reveals the correct key.

  Reveal hidden contents

The logical way

Instead of searching for "Bad key!" in memory its also possible to have the crackme print its real code bypassing titanium entirely.
Note the lzma, zlib imports at the top of crackme.py. Obfuscators commonly compress and then encrypt the code. Doing the other way doesn't make sense as encrypted code won't be compressible. This implies while executing its decryption followed by decompression.

Python is a dynamic language which makes it possible to replace the implementation of any function at runtime. Using this we can "hook" lzma.decompress and check out the decompressed result.

  Reveal hidden contents

Before running the above code in Python 3.7, ensure that PyCryptoDome is installed and titanium.pyd is in the same directory as the crackme.

  Reveal hidden contents

Base64 decoding the exec-d string "X0I9YidVbXhHY1Z........WNsYXJlX18oKQ==", we get this minified Python  code.

  Reveal hidden contents

which after formatting comes to

  Reveal hidden contents

The correct key is in the last exec-d string as we also found earlier.

Expand  

what program do you use to edit hex?

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...