Commits

Vincenzo Ampolo committed 25d55a2

Initial import of BLuebatClient.d

  • Participants

Comments (0)

Files changed (1)

D/bluebatClient.d

+import bluez;
+import tango.sys.Process;
+import tango.sys.Environment;
+import tango.io.stream.Lines;
+import tango.io.Stdout;
+import tango.io.Console;
+import tango.io.Path;
+import tango.util.log.Log;
+import tango.util.log.AppendFile;
+import tango.util.log.AppendConsole;
+import tango.core.ThreadPool;
+import tango.core.Thread;
+import tango.text.xml.Document;
+import tango.text.xml.DocPrinter;
+import tango.io.device.File;
+import Integer = tango.text.convert.Integer;
+import tango.net.device.Socket;
+import tango.net.InternetAddress;
+import tango.io.FileScan;
+import tango.io.encode.Base64;
+
+/**
+ * DataFile handles the data.xml file which is used to store collected data 
+ * from the honeypot.
+ * 
+ */
+class DataFile{
+	private:
+		File output;
+	public:
+		/**
+		 * Create an instance of DataFile in the working directory
+		 * Append other data if there is still data to send to BluebatServer
+		 * from the previous execution
+		 */
+		this(){
+			output = new File("data.xml", File.WriteAppending);
+		}
+		/**
+		 * When object is destroyed, close the data.xml file
+		 *
+		 */
+		~this(){
+			output.close();
+		}
+		/**
+		 * Add data to the data.xml file
+		 * Params:
+		 *     msg = a char[] with xml data to put in data.xml 
+		 */
+		synchronized void UpdateFile(char[] msg){
+			output.write(msg~"\n");				
+		}
+		/**
+		 * Create a new data.xml file since the content have been sent
+		 * to BluebatServer
+		 *
+		 */
+		synchronized void CleanData(){
+			output.close();
+			output = new File("data.xml", File.WriteCreate);
+		}
+}
+
+DataFile datafile;
+
+///this statement is executed before main and represent global variables
+static this(){
+	datafile = new DataFile();
+}
+
+/**
+ * Uploads data to BluebatServer running at pluto.vincenzo-ampolo.net
+ * Every 10 mins this function tries to upload data.xml file to the BluebatServer
+ * It needs to be executed by a thread
+ */
+void upload_data(){
+	///set up logging system
+	auto logger = Log.lookup("bluebat.client.file_uploader");
+	logger.level = logger.Info;
+	logger.add(new AppendFile("log.txt"));
+	logger.add(new AppendConsole());
+	
+	char[] server = "bluebat.elet.polimi.it";
+	int port = 5168;
+	char[] buf;
+	auto output = new File("data.xml");
+	Socket s;
+	File file;
+	logger.info("Starting file uploader");
+	
+	///enter the main loop
+	while(1){
+		
+		//sleep for 10 mins = 600
+		Thread.sleep(600);
+		
+		file = new File("data.xml");
+		
+		if(file.length == 0)
+			continue;
+		
+		logger.info("data.xml is not empty, trying to send to server {}", server);
+				
+		//check if there is connection
+		try{
+			///try to connect to BluebatServer via tcp/ip
+		s = new Socket();
+		s.connect(new InternetAddress (server, port));
+		}
+		catch (tango.core.Exception.SocketException){
+			continue;
+		}
+		
+		logger.info("Connection Created. Sending data.xml");
+		
+		///allocate a buffer dynamic array at the same size of the file
+		buf = new char [file.length];
+		
+		///read the whole file
+		file.read(buf);
+		file.close();
+		
+		///remove old data.xml file
+		datafile.CleanData();
+		
+		///send the whole file
+		s.write(buf);
+		
+		///close socket with BluebatServer
+		s.shutdown();
+	}
+}
+
+/**
+ * This function takes care of all the data gathered with OBEX-PUSH
+ * and stores inside the data.xml file
+ * The main loop is executed every 5 seconds
+ * It needs to be executed by a thread
+ */
+void merge_data_sobexsrv(){
+	auto logger = Log.lookup("bluebat.client.sobexsrv");
+	logger.level = logger.Info;
+	logger.add(new AppendFile("log.txt"));
+	logger.add(new AppendConsole());
+	
+	auto scan = new FileScan();
+	File file;
+	FilePath file_path;
+	ubyte[] buf;
+	char[] encoded;
+	
+	///entering the main loop
+	while(1){
+		//sleep for 5 sec
+		Thread.sleep(5);
+		
+		scan("/tmp/sobexfiles");
+		
+		///recursive scanning of files and directories like python os.walk
+		foreach (filename; scan.files){
+		         logger.info("received {}", filename);
+		         file = new File(filename.toString());
+		         buf = new ubyte [file.length];
+		         file.read(buf);
+		         file.close();
+		         
+		         ///Encode to Base64 to be sure that binary data is preserved in xml
+		         encoded = null;
+		         encoded = encode(buf);
+		         
+		         auto doc = new Document!(char);
+		         auto docprint = new DocPrinter!(char);
+		     	
+		         ///create a xml entry to be written in data.xml
+		         doc.tree.element(null, "communication", "file")
+		         .attribute(null, "address", "unknow")
+		         .attribute(null, "protocol", "OBEX-PUSH")
+		         .element(null, "file", encoded)
+		         .attribute(null, "name", filename.toString()[16 .. filename.toString().length])
+		         .attribute(null, "encoded", "base64");
+		     	
+		        ///write xml entry
+		     	datafile.UpdateFile(docprint(doc));
+		     	file_path = new FilePath(filename.toString());
+		     	file_path.remove();
+		     	
+		     	logger.info("File included in data.xml");
+		         
+		}
+	}
+}
+
+/**
+ * Handles a single client
+ */
+int process_client(Communication client, char[] protocol, int port){
+	auto doc = new Document!(char);
+	auto docprint = new DocPrinter!(char);
+	
+	auto logger = Log.lookup("bluebat.client.communication");
+	logger.level = logger.Info;
+	logger.add(new AppendFile("log.txt"));
+	logger.add(new AppendConsole());
+	ubyte[] data;
+	
+	///get data from the Bluetooth interface
+	data = client.Receive();
+	
+	///	Encode to Base64 to be sure that binary data is preserved in xml
+    char[] encoded = encode(data);
+    
+    ///create xml entry
+	doc.tree.element(null, "communication", "stream")
+    .attribute(null, "address", client.GetAddr)
+    .attribute(null, "protocol", protocol)
+    .attribute(null, "port", Integer.toString(port))
+    .element(null, "stream", encoded)
+    .attribute(null, "encoded", "base64");
+	
+	logger.warn("Communication on protocol {} port {}, client address {}", protocol, port, client.GetAddr);
+	
+	///write data into data.xml file
+	datafile.UpdateFile(docprint(doc));
+	
+	return 0;
+}
+
+/**
+ * Create a RfcommServer instace at given channel
+ */
+void Rf_thread(int i){
+ 	auto logger = Log.lookup("bluebat.Rfthread");
+	logger.level = logger.Info;
+	logger.add(new AppendFile("log.txt"));
+	logger.add(new AppendConsole());
+	
+	auto server = new RfcommServer(i,1);
+	logger.info("Rfcomm server active in channel {}", i);
+	
+	while(1){
+		auto client = server.Accept();
+		process_client(client, "rfcomm", i);
+	}
+	
+}
+
+/**
+ * Create a L2CapServer instance at give channel
+ */
+void L2_thread(int i){
+	auto logger = Log.lookup("bluebat.L2thread");
+	logger.level = logger.Info;
+	logger.add(new AppendFile("log.txt"));
+	logger.add(new AppendConsole());
+	
+	auto server = new L2capServer(i,1);
+	logger.info("L2cap server active in channel {}", i);
+	
+	while(1){
+		auto client = server.Accept();
+		process_client(client, "l2cap", i);
+	}
+	
+}
+
+int main(){
+	///set up the logging system
+	auto logger = Log.lookup("bluebat.main");
+	int[] rfcomm;	//store all the socket that should be opened
+	int[] l2cap;	//this too
+	
+	logger.level = logger.Info;
+	logger.add(new AppendFile("log.txt"));
+	logger.add(new AppendConsole());
+	
+	logger.info("Starting");
+	
+	///calculate the RFCOMM and L2CAP channel and psm to listen to
+	rfcomm.length = 30;
+	for(int i = 1; i < 30; i++)
+		rfcomm[i-1]= i;
+	logger.info("Rfcomm sockets to monitor are {}", rfcomm.length);
+	logger.info("Rfcomm {}", rfcomm);
+	
+	l2cap.length = 0x10FF - 0x1001;
+	logger.info("L2cap sockets to monitor are {}", l2cap.length);
+	for(int i = 0x1001; i < 0x10FF; i++)
+		l2cap[i - 0x1001] = i;
+	
+	logger.info("Creating Threads");
+	
+	logger.info("Total Threads are {}", rfcomm.length + l2cap.length);
+	
+	///Create one thread for each listening server
+	auto RfPool = new ThreadPool!(int)(rfcomm.length);
+	void delegate(int) f = (int x) { Rf_thread(x); };
+	auto L2Pool = new ThreadPool!(int)(l2cap.length);
+	void delegate(int) g = (int x) { L2_thread(x); };
+	
+	///Run threads
+	foreach(int i; rfcomm)
+			 RfPool.append(f, i);
+	foreach(int i; l2cap)
+			L2Pool.append(g,i);
+	
+	///create two threads for merge_data_sobexsrv() and upload data
+	auto SysPool = new ThreadPool!()(2);
+	void delegate() h = () {
+		merge_data_sobexsrv();
+	};
+	
+	void delegate() l = (){
+		upload_data();
+	};
+	
+	SysPool.append(h);
+	SysPool.append(l);
+	
+	Thread.sleep(2);
+	
+	///create /tmp/sobexfiles to store OBEX files
+	auto path = new FilePath("/tmp/sobexfiles");
+	try{
+		path.createFolder();
+	}
+	catch (tango.core.Exception.IOException){
+		;
+	}
+	
+	///run Collin Mulliner's sobexsrv
+	auto sobexsrv = new Process(Environment.cwd~"sobexsrv-1.0.1/src/"~"./sobexsrv -d -I -r /tmp/sobexfiles/", null); 
+	
+	sobexsrv.execute();
+	
+	///set device to discoverable mode
+	auto dbus = new Process("bash -c 'dbus-send --system --type=method_call --print-reply --dest=org.bluez /org/bluez/`pidof bluetoothd`/hci0 org.bluez.Adapter.SetProperty string:Discoverable variant:boolean:true'", null);
+	
+	dbus.execute();
+	
+	Thread.sleep(5);
+	logger.warn("Press any key to close the honeypot");
+	Cin.get();
+	
+	logger.warn("Exiting...");
+	
+	///close all the interfaces
+	RfPool.finish();
+	L2Pool.finish();
+	SysPool.finish();
+	sobexsrv.kill();
+	
+	return 0;
+	
+}