From a Regular Infostealer to its Obfuscated Version
There are many malicious scripts available on the Internet. Github has plenty of info stealers and RATs made available “for testing or research purposes”. Here is one that I found recently: Trap-Stealer[1]. Often those scripts are pretty well obfuscated to pass through security controls and make Security Analysts’ life harder. Let’s review a practical example.
Today, I won't review the info stealer capabilities because they are common but let's check the obfuscation techniques. The file was dropped as a fake JPEG image: C:\Users\user\AppData\Local\apxpvddh.jpeg. It has a low score on VT: 3/63[2].
First, the code is “flooded” with classes that do nothing:
class TtV4adTuzK: def __init__(self): self.data = True def get_data(self): return self.data class nxTJRP4oBo: def __init__(self): self.data = True def get_data(self): return self.data class cLaiqjSQel: def __init__(self): self.data = True def get_data(self): return self.data
Or useless variables:
J4BL2VTnoS = 95994844 Q5eKoFfYgd = 79322716 ME2ZgJpLA0 = 84016443 m4tvU1GFfJ = 31572061 EacvCg0xlz = 58092955 TRwCJhKsQb = 88130587
Dependencies with some Python modules are resolved:
requirements = [ ["requests", "requests"], ["Cryptodome.Cipher", "pycryptodomex" if not 'PythonSoftwareFoundation' in executable else 'pycryptodome'] ] for modl in requirements: try: import_module(module[0]) except: subprocess.Popen(executable + " -m pip install " +modl[1], shell=True) time.sleep(3)
The interesting code starts here:
f2KQN4bukRZMWSZicAmmYUWycFs6d0m5AqoEhG(base64.b64decode(S3ZpuwXgombrIYkwUNwRUJmSFtqLNOGKAHETR1))
A huge chunk of Base64 data is decoded and passed to f2KQN4bukRZMWSZicAmmYUWycFs6d0m5AqoEhG, an alias for exe()!
Once decoded, a second script obfuscated with the same techniques is disclosed. It contains another Base64 chunk of data. This time, the decoded data is encrypted.
Here a funny technique is used to decrypt the next payload. An array of encryption keys is provided and all of them are tested until the decryption succeeds:
s = [b'Co-7hDMhMh7UtUQ29kT0J7krqsTXPUAFXA7RtpcU6xY=', b'cbkSAtHBbB-1QGa6bhIz_faB_iLXMnoQ2DnoXOGCxLo=', b'0d5ykqArsb7Gkb3ZJtjr5-nzIF-2bOYgKtwAyny8B8k=', b'ztG6jHYX0PPlTa_yMzrrxLelrKf79hovRQADx5sioXo=', b'JT0JyIIHm3LfeAuit0xf-vej3m37Qhxvnwc3flWQ3ew=', b'0lSaIjRa6nePT6QiGIoPpVrw8EMHDCT_I7T6JwCk0Cc=', b'KhJzINwra-Dv78aZpTZeqClzc484KhtXEO8fvmV38nY=', b'cRReHk0vv3NlLplRTBxly-B5LamTR4s-7UwaGl-iuak=', b'NWXrr-8oMnHPP9q46JheOjH46abeH9_kHUcUjhxRbsE=', b'4Vu6YVdZGOSclihs4ukSRppyV1M62QFqwp7ZU6y3RBs=', b'M1qQk8eFmk_tigtJgYhOFQVb6pxA4YAfzXAbzx-0BhA=', b'0KjwnWf-Bqri4ae4UVy3pBUCCcAWiFbgWjkWmd7zsdI=', b'WBkyoZfIwgzunYz9je8_-lBeotQ2ntjx59kVuscHboQ=', b'usQcLUBWrVM7dENg0A6ge15mHK9RtB4RV6MB4hbD70o='] for key in s: try: decrypted_code = wqSJRHIzn7T3FiBgqfmquhhSEyCwLpRRMcdtF3(key.decode("utf-8")).decrypt(encrypted_code) break except Exception as e: pass
Finally, the decrypted code is decompressed and executed:
decompressed_code = zlib.decompress(decrypted_code).decode('utf-8') f2KQN4bukRZMWSZicAmmYUWycFs6d0m5AqoEhG(decompressed_code)
You may wonder how these obfuscation techniques are implemented by the attacker. They have tools for this! In the context of Trap-Stealer, the obfuscation tool is even part of the repository[3]. Here is how it works:
remnux@remnux:/MalwareZoo/20241125/Trap-Stealer$ mkdir build remnux@remnux:/MalwareZoo/20241125/Trap-Stealer$ cat <<__END__ >build/temp.py print("This is a super malicious Python script! }:->") __END__ remnux@remnux:/MalwareZoo/20241125/Trap-Stealer$ python3 ./obfucator.py my_super_cool_infostealer INFO:root:The code has been encrypted, Filename: ./build/my_super_cool_infostealer.py remnux@remnux:/MalwareZoo/20241125/Trap-Stealer$ head build/my_super_cool_infostealer.py from sys import executable, stderr ueupD5ALo7 = 33628666 VKkflw4g74 = 98340683 XRPK2HJT5b = 80807402 fhaj93exmX = 5089192 class fMVSRbmSTG: def __init__(self): self.data = True remnux@remnux:/MalwareZoo/20241125/Trap-Stealer$ python3 build/my_super_cool_infostealer.py [...pip stuff removed ...] This is a super malicious Python script! }:->
Note that the obfuscated file is pretty big compared to the "clear text" version: 37 bytes for "temp.py" and 20087 bytes for "my_super_cool_infostealer.py". Obfuscation has a cost! :-)
[1] https://github.com/TheCuteOwl/Trap-Stealer/tree/main
[2] https://www.virustotal.com/gui/file/85a0342027420025c477f3f6ab68376aa1608a447d1fb24920ac36b7cf7fd59d/detection
[3] https://github.com/TheCuteOwl/Trap-Stealer/blob/main/obfuscator.py
Xavier Mertens (@xme)
Xameco
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key
Reverse-Engineering Malware: Malware Analysis Tools and Techniques | Frankfurt | Dec 9th - Dec 14th 2024 |
Comments