Personal Information Security

From a Regular Infostealer to its Obfuscated Version, (Sat, Nov 30th)

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.