ufo.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443
  1. /*
  2. UFONet - Denial of Service Toolkit - 2013/2018 - by psy (epsylon@riseup.net)
  3. You should have received a copy of the GNU General Public License along
  4. with UFONet; if not, write to the Free Software Foundation, Inc., 51
  5. Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  6. */
  7. // this variable defines the delay between each ajax update (statistics and geoip information)
  8. var AJAX_DELAY = 1234
  9. // interface control definitions, managed by leaflet
  10. var UfoControlClass = L.Control.extend({
  11. options: {
  12. position: 'bottomright'
  13. },
  14. onAdd: function (map) {
  15. var container = L.DomUtil.create('div', 'ufo_msg_div leaflet-control-layers leaflet-control-layers-expanded')
  16. L.DomEvent.on(container,'mousedown',L.DomEvent.stopPropagation)
  17. .on(container,'doubleclick',L.DomEvent.stopPropagation)
  18. .on(container,'click',L.DomEvent.stopPropagation)
  19. return container;
  20. }
  21. });
  22. var UfoTitleClass = L.Control.extend({
  23. options: {
  24. position: 'topleft'
  25. },
  26. onAdd: function (map) {
  27. var container = L.DomUtil.create('div', 'ufo_title_div leaflet-control-layers leaflet-control-layers-expanded')
  28. return container;
  29. }
  30. });
  31. var UfoErrorClass = L.Control.extend({
  32. options: {
  33. position: 'bottomleft'
  34. },
  35. onAdd: function (map) {
  36. var container = L.DomUtil.create('div', 'ufo_error_div leaflet-control-layers leaflet-control-layers-expanded')
  37. return container;
  38. }
  39. });
  40. var UfoStatClass = L.Control.extend({
  41. options: {
  42. position: 'bottomleft'
  43. },
  44. onAdd: function (map) {
  45. var container = L.DomUtil.create('div', 'ufo_stat_div leaflet-control-layers leaflet-control-layers-expanded')
  46. L.DomEvent.on(container,'mousedown',L.DomEvent.stopPropagation)
  47. .on(container,'doubleclick',L.DomEvent.stopPropagation)
  48. .on(container,'click',L.DomEvent.stopPropagation)
  49. return container;
  50. }
  51. });
  52. // leaflet cluster, regrouping zombies by country
  53. function Cluster(){
  54. this._clusters=new Array()
  55. this.add=function(zombie,marker){
  56. cc=zombie.country_code
  57. cg=false
  58. if(cc){
  59. cg=this.find(cc)
  60. if(cg==false){
  61. cg=new L.MarkerClusterGroup()
  62. this._clusters.push({"cc":cc,"z":zombie,"cg":cg})
  63. }
  64. cg.addLayer(marker)
  65. map.addLayer(cg)
  66. }
  67. }
  68. this.find=function(cc){
  69. for(c in this._clusters){
  70. if(this._clusters[c].cc==cc){
  71. return this._clusters[c].cg
  72. }
  73. }
  74. return false
  75. }
  76. }
  77. // Target object
  78. function Doll(name){
  79. this.name = name
  80. this.data=false
  81. this.latlong = false
  82. this.city = false
  83. this.country = false
  84. this.country_code = false
  85. this.asn = false
  86. this.ip = false
  87. this.hostname = false
  88. this.drawnLayers = new Array()
  89. this.show=function(){
  90. target_icon=L.icon({iconUrl:"/js/leaflet/images/marker-icon.png",
  91. iconSize: [25, 41],
  92. iconAnchor: [13, 42],
  93. popupAnchor: [-3, -76],
  94. shadowUrl: '/js/leaflet/images/marker-shadow.png',
  95. shadowSize: [68, 95],
  96. shadowAnchor: [22, 94]
  97. })
  98. var marker = L.marker(this.latlong,{icon: target_icon})
  99. var popup = L.Popup({
  100. maxHeight: 50})
  101. var popupcontent = "<b>"+this.name+"</b>"
  102. +"<br />-------------<br />"
  103. +"Localisation: "+this.city+"/"+this.country
  104. +"<br/>"
  105. +"IP: "+this.ip+"<br/>"
  106. +"Hostname: "+this.hostname+"<br/>"
  107. +"ASN: "+this.asn+"<br/>"
  108. marker.bindPopup(popupcontent)
  109. this.drawnLayers.push(marker)
  110. map.addLayer(marker)
  111. }
  112. this.setData = function(data){
  113. this.data=data
  114. this.latlong = data[0]
  115. this.city = data[1]
  116. this.country = data[2]
  117. this.country_code = data[3]
  118. this.asn = data[4]
  119. this.ip = data[5]
  120. this.hostname = data[6]
  121. }
  122. }
  123. // object for each zombie
  124. function zombieEntry(name,data){
  125. this.data=data
  126. this.name = name
  127. this.latlong = data[0]
  128. this.city = data[1]
  129. this.country = data[2]
  130. this.country_code = data[3]
  131. this.asn = data[4]
  132. this.ip = data[5]
  133. this.hostname = data[6]
  134. this.drawnLayers = new Array()
  135. this.index=0
  136. this.state='awakening'
  137. this.speed= 1000 // animation speed in ms
  138. this.cluster = false
  139. this.show=function(){
  140. if(this.state==='awakening'){
  141. this.state='awake'
  142. this.stop_anim=false
  143. this.drawMarker()
  144. }
  145. }
  146. this.drawMarker=function(){
  147. if(!zombie_icon)
  148. zombie_icon=L.icon({iconUrl:"/js/leaflet/images/ufonet-zombie.png",
  149. iconSize: [16, 15],
  150. iconAnchor: [8, 8],
  151. popupAnchor: [-3, -76]
  152. })
  153. var marker = L.marker(this.latlong,{icon:zombie_icon}) //,{icon: this.makeCustomMarker()})
  154. var popup = L.Popup({
  155. maxHeight: 50})
  156. var popupcontent = "<b>"+this.name+"</b>"
  157. +"<br />-------------<br />"
  158. +"Localisation: "+this.city+"/"+this.country+"<br/>"
  159. +"IP: "+this.ip+"<br/>"
  160. +"Hostname: "+this.hostname+"<br/>"
  161. +"ASN: "+this.asn+"<br/>"
  162. marker.bindPopup(popupcontent)
  163. cluster.add(this,marker)
  164. this.drawnLayers.push(marker)
  165. this.fire()
  166. }
  167. this.fire = function(){
  168. if(doll){
  169. var src = this.latlong
  170. var dest = doll.latlong
  171. var b = new R.BezierAnim([src, dest])
  172. map.addLayer(b)
  173. this.drawnLayers.push(b)
  174. }
  175. }
  176. this.makeCustomMarker= function(){
  177. if (this.index < this.counter_max){
  178. var customIcon = new L.icon({
  179. iconUrl: 'images/markers/marker-icon-'+this.index+'.png',
  180. iconSize: [30, 30], // size of the icon
  181. iconAnchor: [15, 15], // point of the icon which will correspond to marker's location
  182. popupAnchor: [-150, 50] // point from which the popup should open relative to the iconAnchor
  183. });
  184. }
  185. if (this.index == this.counter_max){
  186. var customIcon = new L.icon({
  187. iconUrl: 'images/markers/marker-icon-last.png',
  188. iconSize: [30, 30], // size of the icon
  189. iconAnchor: [15, 15], // point of the icon which will correspond to marker's location
  190. popupAnchor: [-150, 0] // point from which the popup should open relative to the iconAnchor
  191. });
  192. }
  193. return customIcon
  194. }
  195. this.makeClusterGroups=function(country_code_list){
  196. for (var i = 0; i < this.unique_country_code_list.length; i++){
  197. if (this.unique_country_code_list[i] == this.country_code_list[this.index]){
  198. if (this.clusterGroups[this.unique_country_code_list[i]]){
  199. //checks if a cluster for the country already exists
  200. return
  201. }
  202. else
  203. //if not make it.
  204. this.clusterGroups[this.unique_country_code_list[i]] = new L.MarkerClusterGroup();
  205. }
  206. }
  207. }
  208. this.AddMarkerCluster= function(marker){
  209. this.clusterGroups[this.country_code_list[this.index]].addLayer(marker)
  210. map.addLayer(this.clusterGroups[this.country_code_list[this.index]])
  211. this.drawnLayers.push(this.clusterGroups[this.country_code_list[this.index]])
  212. }
  213. this.AddMarker=function(src){
  214. var marker = L.marker([src[0], src[1]],{icon: this.makeCustomMarker()})
  215. this.drawnLayers.push(marker)
  216. }
  217. this.hide=function() {
  218. $('.header').hide()
  219. this.index =0
  220. this.state='awakening'
  221. this.stop_anim=true
  222. for (i in this.drawnLayers){
  223. if(map.hasLayer(this.drawnLayers[i]))
  224. map.removeLayer(this.drawnLayers[i])
  225. }
  226. this.drawnLayers=new Array()
  227. }
  228. }
  229. // List of zombies
  230. function Herd(){
  231. this.zombieEntries = new Array
  232. this.find=function (name){
  233. for (z in this.zombieEntries){
  234. if (this.zombieEntries[z].name === name){
  235. return this.zombieEntries[z]
  236. }
  237. }
  238. return false;
  239. }
  240. this.load=function(name){
  241. e=this.find(name)
  242. if(e){
  243. e.show()
  244. return
  245. }
  246. return false
  247. }
  248. this.hideAll = function(){
  249. for (ufoe in this.zombieEntries)
  250. this.zombieEntries[ufoe].hide()
  251. this.render()
  252. }
  253. this.hide = function(name){
  254. var ufoe=this.find(name)
  255. if(!ufoe) return
  256. ufoe.hide()
  257. this.render()
  258. }
  259. this.remove = function(name){
  260. for (z in this.zombieEntries){
  261. if(this.zombieEntries[z].name === name){
  262. this.zombieEntries[z].hide()
  263. this.zombieEntries.splice(z,1)
  264. this.render()
  265. return
  266. }
  267. }
  268. }
  269. this.add = function(name,data){
  270. var ufoe=this.find(name)
  271. if(!ufoe){
  272. ufoe=new zombieEntry(name,data)
  273. this.zombieEntries.push(ufoe)
  274. }
  275. ufoe.show()
  276. return ufoe
  277. }
  278. this.stop=function() {
  279. for(i=0;i<this.zombieEntries.length;i++) {
  280. this.zombieEntries[i].stop();
  281. }
  282. this.render()
  283. }
  284. this.count=function(){
  285. return this.zombieEntries.length
  286. }
  287. }
  288. // jquery shortcuts
  289. function ufomsg(msg){
  290. if ($('#ufomsg').html().indexOf(msg) == -1){
  291. $('#ufomsg').append(msg+"<br/>\n")
  292. $('#ufomsg_last').html(msg)
  293. }
  294. }
  295. function show_error(){
  296. $(".ufo_error_div").toggle()
  297. }
  298. function zombie_detail(data=''){
  299. t=''
  300. if (data!=''){
  301. t+="<h2>Zombie: <i>"+data.name+"</i> <a href='#' onclick='zombie_detail()'>X</a></h2>"
  302. t+=data.hits+" hits / "+data.retries+" retries / "+data.fails+" fails <br/>"
  303. t+=data.min_time+" min time / "+data.avg_time+" average time / "+data.max_time+" max time <br/>"
  304. t+=data.min_size+" min size / "+data.avg_size+" average size / "+data.max_size+" max size <br/>"
  305. }
  306. $('#zombie_detail').html(t)
  307. }
  308. // watchdog function
  309. function ufowatch(){
  310. // if attack mode we have a doll, and do a check if herd is done and bail if so
  311. // if herd is not done, get stats
  312. if(doll && !hdone){
  313. d = new Date()
  314. $("#ufostat").load("/js/ajax.js?stats="+d.getTime()).show()
  315. }
  316. // load doll geoip data
  317. if(doll && !doll.data)
  318. $(".ufo_error_div").load("/js/ajax.js?fetchdoll="+doll.name)
  319. // bail if all zombies are done in view mode
  320. if (zdone)
  321. return
  322. // we are not finished loading zombie geoip data, let's start...
  323. d=new Date
  324. var lw=d.getTime()
  325. error=''
  326. // basic check to prevent overload - relies on AJAX_DELAY variable
  327. if(last_watch < lw - AJAX_DELAY){
  328. last_watch=lw
  329. // loading next zombie
  330. $(".ufo_error_div").load('/js/ajax.js?zombie='+btoa(unescape(encodeURIComponent(last_zombie))))
  331. label=Zombies.count()+"/"+total_zombies
  332. if (Zombies.count()== total_zombies)
  333. label = total_zombies
  334. else
  335. if (Zombies.count() +dead_zombies.length== total_zombies){
  336. label=total_zombies
  337. if(dead_zombies.length>0){
  338. label=total_zombies -dead_zombies.length
  339. $('.ufo_error_div').html('<div id="ufo_error_div">To be discarded : <br/><ul>'
  340. +dead_zombies.join("<li> -")+'</ul></div>')
  341. error = "<a href='#' onclick='show_error()'> + "+dead_zombies.length+" not listed...</a>"
  342. }
  343. }
  344. $(".ufo_title_div").html('<div id="status"><center><h2><font color="red">Zombies:</font></h2><h3><font color="green" size="9px"><b>'+label+'</b></font></h3>'+error+'</center></div>');
  345. }
  346. }
  347. // (leaflet) map initialization
  348. function initMap (targetdoll=false) {
  349. if(map){
  350. return
  351. }
  352. if(targetdoll){
  353. doll=targetdoll
  354. }
  355. index = 0
  356. osm_sat = L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png')
  357. map = L.map('map',{
  358. minZoom: 2,
  359. maxZoom: 7,
  360. zoomControl:false,
  361. layers: [osm_sat]
  362. });
  363. if (typeof latlong !== 'undefined') {
  364. map.setView(latlong[index], 1)
  365. }
  366. else{
  367. map.setView(new L.LatLng(0,0), 1)
  368. }
  369. osm_sat.addTo(map)
  370. var baseMaps = {
  371. "Sats": osm_sat,
  372. }
  373. // initializing controls:
  374. new L.control.layers(baseMaps, null, {collapsed:false}).addTo(map)
  375. new L.Control.Zoom({position: 'topright'}).addTo(map)
  376. map.scrollWheelZoom.disable()
  377. map.addControl(new UfoControlClass())
  378. $('.ufo_msg_div').html("<h2 style='text-align:right'>Map Console <a href=\"#\" id='showMsg'>[+]</a> <a href=\"#\" id='hideMsg'>[-]</a></h2><div id='ufomsg'>[Info] [AI] [Control] Locating zombies... -> [Waiting!]<br/><br/></div><div id='ufomsg_last'>[Info] [AI] [Control] Locating zombies.... -> [Waiting!]<br/></div>")
  379. map.addControl(new UfoTitleClass())
  380. $(".ufo_title_div").html('<div id="status"><h2><font color="red">Zombies:</font></h2><center><h3><font color="green" size="9px"><b>'+total_zombies+'</b></font></h3></center></div>');
  381. map.addControl(new UfoErrorClass())
  382. $('.ufo_error_div').hide()
  383. map.addControl(new UfoStatClass())
  384. $('.ufo_stat_div').html("<h2 style='text-align:right'>Last Statistics <a href=\"#\" id='showStat'>[+]</a> <a href=\"#\" id='hideStat'>[-]</a></h2><div id='zombie_detail'></div><div id=\"ufostat\"></div>").hide()
  385. $('a#showStat').hide()
  386. $('a#showStat').click(function(){
  387. $('a#showStat').hide()
  388. $('a#hideStat').show()
  389. $('#ufostat').show()
  390. })
  391. $('a#hideStat').click(function(){
  392. $('a#hideStat').hide()
  393. $('a#showStat').show()
  394. $('#ufostat').hide()
  395. })
  396. $('a#hideMsg').hide()
  397. $('#ufomsg').hide()
  398. $('a#showMsg').click(function(){
  399. $('a#showMsg').hide()
  400. $('a#hideMsg').show()
  401. $('#ufomsg').show()
  402. $('#ufomsg_last').hide()
  403. })
  404. $('a#hideMsg').click(function(){
  405. $('a#hideMsg').hide()
  406. $('a#showMsg').show()
  407. $('#ufomsg').hide()
  408. $('#ufomsg_last').show()
  409. })
  410. // starting watchdog ajax request
  411. window.setInterval("ufowatch()",AJAX_DELAY)
  412. }
  413. // global variables
  414. var Zombies = new Herd()
  415. var cluster = new Cluster()
  416. var map = false
  417. var last_zombie = 'None'
  418. var zombie_icon = false
  419. d=new Date
  420. var last_watch = d.getTime()
  421. var target_icon = false
  422. var doll = false
  423. var dead_zombies = new Array()
  424. var errdiv = false
  425. var hdone = false
  426. var zdone = false
  427. var total_zombies=false