ajaxmap.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-"
  3. """
  4. UFONet - DDoS Botnet via Web Abuse - 2013/2014/2015/2016 - by psy (epsylon@riseup.net)
  5. You should have received a copy of the GNU General Public License along
  6. with UFONet; if not, write to the Free Software Foundation, Inc., 51
  7. Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  8. """
  9. import socket, threading, re, base64, os, time, base64, traceback
  10. import webbrowser, subprocess, urllib2, json, sys, shlex
  11. from urlparse import urlparse
  12. from main import UFONet
  13. try:
  14. import pygeoip
  15. except:
  16. print "\n[Error] [AI] Cannot import lib: pygeoip. \n\n To install it try:\n\n $ 'sudo apt-get install python-geoip' or 'pip install geoip'\n"
  17. sys.exit(2)
  18. class AjaxMap(object):
  19. def __init__(self):
  20. self.geo_db_mirror1 = 'http://176.28.23.46/bordercheck/maps.tar.gz' # Turina Server
  21. self.geo_db_mirror2 = 'http://83.163.232.95/bordercheck/maps.tar.gz' # Mirror
  22. self._geoip=None
  23. self._geoasn=None
  24. self._geoipstatus='nomap'
  25. self._err=''
  26. ufonet = UFONet()
  27. ufonet.create_options()
  28. try:
  29. self.zombies = ufonet.extract_zombies()
  30. aliens_army = ufonet.extract_aliens()
  31. droids_army = ufonet.extract_droids()
  32. ucavs_army = ufonet.extract_ucavs()
  33. rpcs_army = ufonet.extract_rpcs()
  34. self.zombies.extend(aliens_army)
  35. self.zombies.extend(droids_army)
  36. self.zombies.extend(ucavs_army)
  37. self.zombies.extend(rpcs_army)
  38. except:
  39. return
  40. def get_err(self):
  41. return self._err
  42. # check for geoip data status
  43. # basic lock file mechanism to avoid multiple downloads
  44. def get_status(self):
  45. if os.path.exists('maps.downloading'):
  46. if not os.path.exists('maps.downloadmsg'):
  47. f=open("maps.downloadmsg","wb")
  48. f.write("")
  49. f.close()
  50. print "[Info] [AI] [Control] GeoIP data download started! -> [OK!]\n"
  51. self._geoipstatus='downloading'
  52. elif os.path.isdir('maps'):
  53. if self._geoip == None :
  54. self._geoip = pygeoip.GeoIP('maps/GeoLiteCity.dat')
  55. if self._geoasn == None :
  56. self._geoasn = pygeoip.GeoIP('maps/GeoIPASNum.dat')
  57. if os.path.exists("maps.downloadmsg") :
  58. os.remove("maps.downloadmsg")
  59. self._geoipstatus='ok'
  60. return self._geoipstatus
  61. def retrieve(self,url,name):
  62. try:
  63. handle = urllib2.urlopen(url)
  64. CHUNK = 16384
  65. with open(name,'wb') as fp:
  66. while True:
  67. chunk = handle.read(CHUNK)
  68. if not chunk:
  69. break
  70. fp.write(chunk)
  71. except:
  72. traceback.print_exc()
  73. def download_maps(self):
  74. # generate geolocation values on a map
  75. if self.get_status() != 'nomap':
  76. return self._geoipstatus == 'ok'
  77. if os.path.exists("maps.downloadmsg"):
  78. os.remove("maps.downloadmsg")
  79. f=open("maps.downloading",'w')
  80. f.write("download started<script>$'('#ufomsg').load('/js/ajax.js?fetchmap=')")
  81. f.close()
  82. self._geoipstatus="downloading"
  83. try: # mirror 1
  84. print "\n[Info] [AI] Fetching maps from 'Mirror 1':", self.geo_db_mirror1 + "\n"
  85. response = self.retrieve(self.geo_db_mirror1, 'maps.tar.gz')
  86. except:
  87. try: # mirror 2
  88. print "[Error] [AI] Mirror 1':", self.geo_db_mirror1 + " Failed! -> [Discarding!]\n"
  89. print "[Info] [AI] Fetching maps from 'Mirror 2':", self.geo_db_mirror2 + "\n"
  90. response = self.retrieve(self.geo_db_mirror2, 'maps.tar.gz')
  91. except:
  92. print("[Error] [AI] Something wrong fetching maps from mirrors! -> [Aborting!]"), "\n"
  93. traceback.print_exc()
  94. return False #sys.exit(2)
  95. subprocess.call(shlex.split('tar zxfv maps.tar.gz'))
  96. print "\n[Info] [AI] [Control] GeoIP maps and databases -> [OK!]\n"
  97. # set pygeoip data sources
  98. self._geoip = pygeoip.GeoIP('maps/GeoLiteCity.dat')
  99. self._geoasn = pygeoip.GeoIP('maps/GeoIPASNum.dat')
  100. self._geoipstatus='ok'
  101. os.remove('maps.tar.gz')
  102. os.remove('maps.downloading')
  103. return True
  104. # fetches geoip data for specified zombie
  105. def geo_ip(self, zombie):
  106. # check for status, downloading is done by ajax() method
  107. if self.get_status() != 'ok':
  108. if self._geoipstatus =='downloading':
  109. print "\n[Info] [AI] [Control] GeoIP maps and databases -> [Downloading!]\n"
  110. self._err= "ufomsg('[Info] [AI] Downloading maps... -> [Waiting!]')"
  111. elif not os.path.exists('maps/GeoIPASNum.dat') or not os.path.exists('maps/GeoLiteCity.dat'):
  112. print "\n[Info] [AI] GeoIP maps and databases -> [Starting!]\n"
  113. self._err= "ufomsg('[Info] [AI] Map download starting')\n$('#ufomsg').load('/js/ajax.js?fetchgeoip=')"
  114. else:
  115. print "\n[Error] [AI] GeoIP maps and databases: FAILED! -> [Discarding!]\n"
  116. self._err= "ufomsg('<font color='red'>[Info] [AI]</font> Maps: unknown error -> [Discarding!]')"
  117. return None
  118. if re.match(r'^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$', zombie) or re.match(r'^10\.\d{1,3}\.\d{1,3}\.\d{1,3}$', zombie) or re.match(r'^192.168\.\d{1,3}\.\d{1,3}$', zombie) or re.match(r'^172.(1[6-9]|2[0-9]|3[0-1]).[0-9]{1,3}.[0-9]{1,3}$', zombie) or re.match('localhost', zombie):
  119. self._err= "ufomsg('<font color='red'>[Info] [AI] [Control]</font> Maps: invalid ip data -> [Discarding!]')"
  120. return None
  121. # create geoip data skeleton
  122. geo_zombie={}
  123. geo_zombie['qq']=zombie
  124. url = urlparse(zombie)
  125. geo_zombie['city'] = '-'
  126. geo_zombie['country'] = '-'
  127. geo_zombie['country_code'] = '-'
  128. geo_zombie['longitude'] = '-'
  129. geo_zombie['latitude'] = '-'
  130. geo_zombie['ip'] = '-'
  131. geo_zombie['host_name'] = '-'
  132. geo_zombie['asn'] = '-'
  133. geo_zombie['latitude'] = '-'
  134. # retrieve and allocate geoip data
  135. try:
  136. ip = socket.gethostbyname(url.netloc)
  137. except:
  138. try:
  139. import dns.resolver
  140. r = dns.resolver.Resolver()
  141. r.nameservers = ['8.8.8.8', '8.8.4.4'] # google DNS resolvers
  142. a = r.query(url.netloc, "A") # A record
  143. for rd in a:
  144. ip = str(rd)
  145. except:
  146. self._err= "ufomsg('<font color='yellow'>[Error] [AI]</font> GeoIP: hostbyname failed for "+str(url.netloc)+"...')"
  147. return None
  148. if ip:
  149. if re.match(r"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$",ip):
  150. geo_zombie['ip'] = ip
  151. try:
  152. record = self._geoip.record_by_addr(ip)
  153. except:
  154. self._err= "ufomsg('<font color='yellow'>[Error] [AI] </font> GeoIP: lookup failed for "+ip+", page reload required...')"
  155. return None
  156. try:
  157. asn = self._geoasn.org_by_addr(ip)
  158. if asn is not None:
  159. geo_zombie['asn'] = asn.encode('utf-8')
  160. except:
  161. geo_zombie['asn'] = 'No ASN provided'
  162. try:
  163. geo_zombie['host_name'] = socket.gethostbyaddr(ip)[0].encode('utf-8')
  164. except:
  165. geo_zombie['host_name'] = 'No hostname'
  166. try:
  167. longitude = str(float(record['longitude']))
  168. geo_zombie['longitude'] = longitude
  169. latitude = str(float(record['latitude']))
  170. geo_zombie['latitude'] = latitude
  171. except:
  172. pass
  173. try:
  174. geo_zombie['country'] = record["country_name"].encode('utf-8')
  175. geo_zombie['country_code'] = record["country_code"].lower().encode('utf-8')
  176. if record['city'] is not None:
  177. geo_zombie['city'] = record["city"].encode('utf-8')
  178. except:
  179. pass
  180. else:
  181. geo_zombie = None
  182. return geo_zombie
  183. # generates javascript for adding a new zombie with geoip data
  184. def get_js(self,z):
  185. ret = ""
  186. gz = self.geo_ip(z)
  187. if gz is not None and gz['latitude']!= '-':
  188. ret = "Zombies.add('"+z+"',Array(new L.LatLng("+str(gz['latitude'])+","+str(gz['longitude'])+"),'"+gz['city']+"','"+gz['country']+"','"+gz['country_code']+"','"+gz['asn']+"','"+gz['ip']+"','"+gz['host_name']+"'))\n"
  189. else:
  190. url = urlparse(z)
  191. print '[Error] [AI] [Control] [GUI]',url.netloc, "isn't geolocated on [Map] -> [Discarding!]"
  192. ret += "dead_zombies.push('"+z+"')\n"
  193. ret += "last_zombie = '"+z+"'\n"
  194. return ret
  195. # fetches next zombie from list (using all types of zombies)
  196. def get_next_zombie(self,name):
  197. if name in self.zombies:
  198. for z in self.zombies:
  199. if name == None:
  200. return z
  201. if z == name:
  202. name = None
  203. return None
  204. else:
  205. return self.zombies[0]
  206. # ajax controller
  207. def ajax(self,pGet={}):
  208. if 'fetchgeoip' in pGet.keys():
  209. if self.get_status() == "nomap":
  210. self.download_maps()
  211. return "[Info] [AI] [Control] Geoip data download! -> [OK!]<br/>"
  212. if 'stats' in pGet.keys():
  213. stat='<script>$(".ufo_stat_div").show()</script>'
  214. if os.path.exists('/tmp/ufonet.html'):
  215. for x in open(r'/tmp/ufonet.html').readlines():
  216. stat = stat + x
  217. else:
  218. stat="<i>[Info] [AI] [Control] Generating statistics... -> [Waiting!]</i>"
  219. return stat+"</div>"
  220. if self.get_status() != "ok":
  221. dljs=""
  222. if self.get_status() == "nomap":
  223. dljs+="$('#ufomsg').load('/js/ajax.js?fetchgeoip=')\n"
  224. if 'doll' in pGet.keys():
  225. dljs+="$('#ufomsg').load('/js/ajax.js?fetchdoll="+pGet['doll']+"')\n"
  226. dljs+="doll=new Doll('"+pGet["doll"]+"')\n"
  227. return "[Info] [AI] GeoIP data download in progress...<br><i>See console for errors</i>+<script>"+dljs+"</script>"
  228. if 'zombie' in pGet.keys():
  229. zn=base64.b64decode(pGet['zombie'])
  230. nzn=self.get_next_zombie(zn)
  231. if nzn is not None:
  232. zombie=self.get_js(nzn)
  233. return """ <script>
  234. """+zombie+"""
  235. ufomsg('[Info] [AI] [Control] Adding zombie: """+nzn+"""...')
  236. </script>"""
  237. else:
  238. return "<script>zdone=true\nufomsg('[Info] [AI] [Control] All zombies deployed! -> [OK!]')\n </script>\n"
  239. if 'fetchdoll' in pGet.keys():
  240. tn=pGet['fetchdoll']
  241. target = self.geo_ip(tn)
  242. if target is None:
  243. return "doll waiting for geoip data !"
  244. return """ doll up !<script>
  245. doll.setData(Array(new L.LatLng("""+str(target['latitude'])+","+str(target['longitude'])+"),'"+target['city']+"','"+target['country']+"','"+target['country_code']+"','"+target['asn']+"','"+target['ip']+"','"+target['host_name']+"'))\nufomsg('[Info] Adding target: """+tn+"""...')\ndoll.show() </script>"""
  246. if 'doll' in pGet.keys():
  247. tn=pGet['doll']
  248. return """<script>
  249. doll=new Doll('"""+tn+"""')\n</script>"""
  250. return "\n"