text: from __future__ import print_function
  import requests as r
  import decoder
  import struct
  import sys
  import xml.etree.ElementTree as ET
  import xml.dom.minidom
  
  """
  Pull all the data from TrickBot
  20july2017 - Jason Reaves
  20jul2017 - Added dpost and mailconf - thanks @mesa_matt
  
  Eventually the botid will get blacklisted and you'll need to created one randomly :)
  """
  
  def generic_get_req(url, headers):
  	print("Requesting: "+url)
  	resp = 0
  	try:
  		resp = r.get(url, headers=headers, verify=False)
  	except:
  		print("Connection Error")
  	return resp
  
  
  def req_data(domain, campaign, req_num, mod=None):
  	resp = 0
  	headers = {"UserAgent": "Mozilla/5.0"}
  	url_fmt = "https://{}/{}/SYSOPFBSAYSHI_W629200.7F3181ECDB1F53C5DFBD6D5085426C67/{}/"
  	
  	if req_num == 0:
  		url_fmt_temp = url_fmt + "Windows%208%20x86/1008/23.23.86.44/649DBB78ADDAFEDC2DFFE8403D4A946B82A308FC7D06E8F1803044E1C94B81AC/amFzb25yZWF2ZXMK/"
  		url = url_fmt_temp.format(domain, campaign, req_num)
  		resp = generic_get_req(url, headers)
  	elif req_num == 5:
  		url_fmt_temp = url_fmt + "{}/"
  		url = url_fmt_temp.format(domain, campaign, req_num, mod)
  		resp = generic_get_req(url, headers)
  	else:
  		print("Unknown request")
  
  	return resp
  
  def parse_module_config(data):
  	psrvs = []
  	root = ET.fromstring(data)
  	for child in root:
  		if child.tag == 'plugins':
  			for psrv in child:
  				psrvs.append(psrv.text)
  	return psrvs
  
  if __name__ == "__main__":
  	fp = open('out.txt','w')
  	c2 = sys.argv[1]
  	campaign = sys.argv[2]
  	resp = req_data(c2, campaign, 0)
  	if  resp == 0 or resp.status_code != 200:
  		print("Error response")
  		fp.close()
  		sys.exit(-1)
  	data = resp.content
  	off = data.find('\r\n')
  	off += 2
  	data = data[off:]
  	decoded = decoder.dyre_decrypt(data)
  	l = struct.unpack_from("<I", decoded)[0]
  	mod_config = decoded[8:l+8]
  	plugin_srvs = parse_module_config(mod_config)
  	
  	print("Plugin servers:")
  	print(*plugin_srvs, sep='\n')
  	fp.write("Plugin servers:\n")
  	for p in plugin_srvs:
  		fp.write(p+'\n')
  	
  	#If you want to pull modules you could, not required now since
  	# config names are static but also exist in plugin strings if they randomize
  	#for srv in plugin_srvs:
  	#	resp = req_data(c2, campaign, 5, "injectDll32")
  
  
  	#Pull config data
  	resp = req_data(c2, campaign, 5, "sinj")
  	if  resp == 0 or resp.status_code != 200:
  		print("Error response")
  		fp.close()
  		sys.exit(-1)
  	decoded = decoder.dyre_decrypt(resp.content)
  	l = struct.unpack_from("<I", decoded)[0]
  	sinj_config = decoded[8:l+8]
  	try:
  		xmld = xml.dom.minidom.parseString(sinj_config.replace('\r\n', ''))
  		print(xmld.toprettyxml())
  		fp.write("Static Inject Config:\n")
  		fp.write(xmld.toprettyxml())
  	except:
  		print(sinj_config)
  		fp.write("Static Inject Config:\n")
  		fp.write(sinj_config)
  	
  	resp = req_data(c2, campaign, 5, "dinj")
  	if  resp == 0 or resp.status_code != 200:
  		print("Error response")
  		fp.close()
  		sys.exit(-1)
  	decoded = decoder.dyre_decrypt(resp.content)
  	l = struct.unpack_from("<I", decoded)[0]
  	dinj_config = decoded[8:l+8]
  	try:
  		xmld = xml.dom.minidom.parseString(dinj_config.replace('\r\n', ''))
  		print(xmld.toprettyxml())
  		fp.write("Dynamic Inject Config:\n")
  		fp.write(xmld.toprettyxml())
  	except:
  		print(dinj_config)
  		fp.write("Dynamic Inject Config:\n")
  		fp.write(dinj_config)
  		
  
  	
  	resp = req_data(c2, campaign, 5, "bcconf")
  	if  resp == 0 or resp.status_code != 200:
  		print("Error response")
  		fp.close()
  		sys.exit(-1)
  	decoded = decoder.dyre_decrypt(resp.content)
  	l = struct.unpack_from("<I", decoded)[0]
  	bcconf_config = decoded[8:l+8]
  	try:
  		xmld = xml.dom.minidom.parseString(bcconf_config.replace('\r\n', ''))
  		print(xmld.toprettyxml())
  		fp.write("BackConnect Config:\n")
  		fp.write(xmld.toprettyxml())
  	except:
  		print(bcconf_config)
  		fp.write("BackConnect Config:\n")
  		fp.write(bcconf_config)
  
  	resp = req_data(c2, campaign, 5, "dpost")
  	if  resp == 0 or resp.status_code != 200:
  		print("Error response")
  		fp.close()
  		sys.exit(-1)
  	decoded = decoder.dyre_decrypt(resp.content)
  	l = struct.unpack_from("<I", decoded)[0]
  	dpost_config = decoded[8:l+8]
  	try:
  		xmld = xml.dom.minidom.parseString(dpost_config.replace('\r\n', ''))
  		print(xmld.toprettyxml())
  		fp.write("Data Post Config:\n")
  		fp.write(xmld.toprettyxml())
  	except:
  		print(dpost_config)
  		fp.write("Data Post Config:\n")
  		fp.write(dpost_config)
  	
  	resp = req_data(c2, campaign, 5, "mailconf")
  	if  resp == 0 or resp.status_code != 200:
  		print("Error response")
  		fp.close()
  		sys.exit(-1)
  	decoded = decoder.dyre_decrypt(resp.content)
  	l = struct.unpack_from("<I", decoded)[0]
  	mail_config = decoded[8:l+8]
  	try:
  		xmld = xml.dom.minidom.parseString(mail_config.replace('\r\n', ''))
  		print(xmld.toprettyxml())
  		fp.write("Mail Config:\n")
  		fp.write(xmld.toprettyxml())
  	except:
  		print(mail_config)
  		fp.write("Mail Config:\n")
  		fp.write(mail_config)
  	
  	fp.close()
  
  