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:UsersuserAppDataLocalapxpvddh.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
(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.