Browse Source

-README updated for ssh lib from ganymed
-SMB: some more NetBIOS updates, including JavaDoc

Wulf Pfeiffer 10 years ago
parent
commit
660ae04e72

+ 4 - 0
README.md

@@ -6,6 +6,10 @@ Copyright (C) 2013  Mihai Plasoianu, Wulf Pfeiffer, Lars Pandikow
 Features of HoneyRJ were inspiration for this project.
 http://www.cse.wustl.edu/~jain/cse571-09/ftp/honey/manual.html
 
+Encryption for the SSH protocol were taken from Ganymed SSH-2
+and slightly modified.
+http://code.google.com/p/ganymed-ssh-2/
+
 This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or

+ 1 - 1
project.properties

@@ -15,4 +15,4 @@ target=android-19
 android.library=false
 
 
-android.library.reference.1=../google-play-services_lib
+android.library.reference.1=../../development/Android/HosTaGe/google-play-services_lib

+ 15 - 5
src/de/tudarmstadt/informatik/hostage/protocol/SMB.java

@@ -6,6 +6,7 @@ import java.util.List;
 
 import de.tudarmstadt.informatik.hostage.Hostage;
 import de.tudarmstadt.informatik.hostage.R;
+import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
 import de.tudarmstadt.informatik.hostage.protocol.smbutils.NBNS;
 import de.tudarmstadt.informatik.hostage.protocol.smbutils.NMB;
 import de.tudarmstadt.informatik.hostage.protocol.smbutils.SMBPacket;
@@ -36,6 +37,7 @@ public class SMB implements Protocol {
 	 */
 	private STATE state = STATE.NONE;
 	private byte[] lastMessage;
+	private NMB nmb;
 
 	// version stuff
 	private String[][] possibleSmbVersions = {
@@ -55,19 +57,24 @@ public class SMB implements Protocol {
 	}
 	
 	public void setIP(String ip) {
-		new NMB(ip, "ABCDEFG", "WORKGROUPA").start();
+//		TODO if porthack is working for UDP uncomment
+//		nmb = new NMB(ip, new String(serverName), workgroup);
+//		nmb.start();
 	}
 
 	private String[] initServerVersion() {
-		System.out.println("hi");
 		String sharedPreferencePath = Hostage.getContext().getString(
 				R.string.shared_preference_path);
-		System.out.println(sharedPreferencePath);
 		String profile = Hostage
 				.getContext()
 				.getSharedPreferences(sharedPreferencePath,
 						Hostage.MODE_PRIVATE).getString("os", "");
-		System.out.println(profile);
+		if(profile.equals("Windows XP")) {
+			workgroup = "MSHOME";
+		} else {
+			workgroup = "WORKGROUP";
+		}
+		
 		if (profile.equals("Windows 7")) {
 			return possibleSmbVersions[0];
 		} else if (profile.equals("Windows 8")) {
@@ -87,7 +94,10 @@ public class SMB implements Protocol {
 	
 	//required to be declared down here, do not change position over initServerVersion() and possibleServerVersions!!
 	private String[] serverVersion = initServerVersion();
-	private SMBPacket smbPacket = new SMBPacket(serverVersion);
+	private static byte[] serverName = HelperUtils.fillWithZero(HelperUtils
+			.getRandomString(16, true).getBytes());
+	private static String workgroup;
+	private SMBPacket smbPacket = new SMBPacket(serverVersion, new String(serverName), workgroup);
 
 	@Override
 	public int getPort() {

+ 42 - 10
src/de/tudarmstadt/informatik/hostage/protocol/smbutils/NBDS.java

@@ -4,30 +4,44 @@ import java.nio.ByteBuffer;
 
 import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
 
-
+/**
+ * NetBIOS Datagram Service.
+ * @author Wulf Pfeiffer
+ */
 public class NBDS {
 	
+	private String dst;
 	private byte[] type;
 	private byte[] flags;
-	private byte[] id;
+	private byte[] transactID;
 	private byte[] srcIP;
 	private byte[] srcPort;
 	private byte[] length;
 	private byte[] offset;
 	private byte[] srcName;
 	private byte[] dstName;
+	private int nbdstype;
 	private SMBPacket smb;
 	
-	public NBDS(byte[] transactID, byte[] addr, String src, String dst, int nbdstype) {
-		this.type = new byte[]{0x11};
+	public NBDS(byte[] addr, String src, String dst) {
+		this.dst = dst;
+		type = new byte[]{0x11};
 		flags = new byte[]{0x0a};
-		id = transactID;
 		srcIP = addr;
 		srcPort = new byte[]{0x00, (byte) 0x8a};
 		offset = new byte[]{0x00, 0x00};
 		length = new byte[2];
 		srcName = NMBStringCoder.wrapNBNSName(NMBStringCoder.encodeNBNSName(src.getBytes()), NBNSService.WORKSTATION);
-		if (nbdstype == NBDSType.REQUEST_ANNOUNCEMENT || nbdstype == NBDSType.LOCAL_MASTER_ANNOUNCEMENT_ALL) {
+		smb = new SMBPacket(null, src, dst);
+	}
+	
+	/**
+	 * Prepares the content for the next packet.
+	 */
+	private void preparePacket() {
+		transactID = NMB.getAndIncTransactID();
+		if (nbdstype == NBDSType.REQUEST_ANNOUNCEMENT || nbdstype == NBDSType.LOCAL_MASTER_ANNOUNCEMENT_ALL 
+				|| nbdstype == NBDSType.LOCAL_MASTER_ANNOUNCEMENT) {
 			dstName = NMBStringCoder.wrapNBNSName(NMBStringCoder.encodeNBNSName(dst.getBytes()), NBNSService.BROWSER_ELECTION);
 		} else if (nbdstype == NBDSType.DOMAIN_ANNOUNCEMENT) {
 			dstName = HelperUtils.concat(new byte[]{0x20, 0x41, 0x42, 0x41, 0x43}, NMBStringCoder.encodeNBNSName("__MSBROWSE__".getBytes()),
@@ -35,17 +49,35 @@ public class NBDS {
 		} else {
 			dstName = NMBStringCoder.wrapNBNSName(NMBStringCoder.encodeNBNSName(dst.getBytes()), NBNSService.LOCAL_MASTER_BROWSER);
 		}
-		smb = new SMBPacket(null);
-		smb.prepareNextResponse(nbdstype, src, dst);
+		smb.prepareNextResponse(nbdstype);
 		byte[] buffer = HelperUtils.concat(srcName, dstName, smb.getTrans());
 		byte[] lengthBuffer = ByteBuffer.allocate(4).putInt(buffer.length).array();
 		length[0] = lengthBuffer[2];
 		length[1] = lengthBuffer[3];
 	}
 	
-	public byte[] getBytes() {
-		return HelperUtils.concat(type, flags, id, srcIP, srcPort, length,
+	/**
+	 * @return next Packet.
+	 */
+	public byte[] getNextPacket() {
+		preparePacket();
+		return getBytes();
+	}
+	
+	/**
+	 * @return content of the packet.
+	 */
+	private byte[] getBytes() {
+		return HelperUtils.concat(type, flags, transactID, srcIP, srcPort, length,
 				offset, srcName, dstName, smb.getTrans());
 	}
 
+	/**
+	 * Set the NBDSType.
+	 * @param nbdstype.
+	 */
+	public void setNbdstype(int nbdstype) {
+		this.nbdstype = nbdstype;
+	}
+	
 }

+ 6 - 1
src/de/tudarmstadt/informatik/hostage/protocol/smbutils/NBDSType.java

@@ -1,7 +1,11 @@
 package de.tudarmstadt.informatik.hostage.protocol.smbutils;
 
+/**
+ * NetBios Datagram Service types.
+ * @author Wulf Pfeiffer.
+ */
 public class NBDSType {
-	
+
 	public static final int HOST_ANNOUNCEMENT = 0;
 	public static final int HOST_ANNOUNCEMENT_WITH_SERVICES = 1;
 	public static final int BROWSER = 2;
@@ -9,4 +13,5 @@ public class NBDSType {
 	public static final int LOCAL_MASTER_ANNOUNCEMENT_ALL = 4;
 	public static final int DOMAIN_ANNOUNCEMENT = 5;
 	public static final int LOCAL_MASTER_ANNOUNCEMENT = 6;
+
 }

+ 94 - 79
src/de/tudarmstadt/informatik/hostage/protocol/smbutils/NBNS.java

@@ -4,7 +4,10 @@ import java.nio.ByteBuffer;
 
 import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
 
-
+/**
+ * NetBIOS Name Service.
+ * @author Wulf Pfeiffer
+ */
 public class NBNS {
 	
 	private byte[] transactID;
@@ -20,43 +23,15 @@ public class NBNS {
 	private int type;
 	private int service;
 	
-	public NBNS(byte[] packet) {
-		transactID = new byte[]{packet[0], packet[1]};
-		flags = new byte[]{packet[2], packet[3]};
-		questions = new byte[]{packet[4], packet[5]};
-		answerRRs = new byte[]{packet[6], packet[7]};
-		authorityRRs = new byte[]{packet[8], packet[9]};
-		additionalRRs = new byte[]{packet[10], packet[11]};
-		int length = 0;
-		for (int i = 12; i < packet.length; i++, length++) {
-			if (packet[i] == 0x01) {
-				length++;
-				break;
-			}
-		}
-		payload = new byte[length];
-		for (int i = 0; i < payload.length; i++) {
-			payload[i] = packet[i+12];
-		}
-		additional = new byte[packet.length-12-length];
-		for (int i = 0; i < additional.length; i++) {
-			additional[i] = packet[i+12+length];
-		}
-	}
-	
-	public NBNS(byte[] transactID, String addr) {
-		this.transactID = transactID;
-		addressToBytes(addr);
-	}
-	
-	public NBNS(byte[] transactID, int type, int service, String name, String addr) {
-		this(transactID, addr);
-		this.type = type;
-		this.service = service;
-		setName(name);
+	public NBNS(byte[] addr) {
+		this.addr = addr;
 	}
 	
+	/**
+	 * Prepares the content for the next packet regarding of the set type.
+	 */
 	private void preparePacket() {
+		transactID = NMB.getAndIncTransactID();
 		switch (type) {
 		case NBNSType.REGISTRATION_UNIQUE:
 			prepareRegistrationPacket();
@@ -74,6 +49,9 @@ public class NBNS {
 		}
 	}
 	
+	/**
+	 * Prepares the content for the next registration packet.
+	 */
 	private void prepareRegistrationPacket() {
 		flags = new byte[]{0x29, 0x10};
 		questions = new byte[]{0x00, 0x01};
@@ -84,6 +62,9 @@ public class NBNS {
 		additional = getAdditionalRecords();
 	}
 	
+	/**
+	 * Prepares the content for the next name query packet.
+	 */
 	private void prepareNameQueryPacket() {
 		flags = new byte[] {0x01, 0x10};
 		questions = new byte[]{0x00, 0x01};
@@ -93,6 +74,9 @@ public class NBNS {
 		payload = getPayload();
 	}
 	
+	/**
+	 * Prepares the content for the next MSBROWSE registration packet.
+	 */
 	private void prepareRegistrationMsBrowse() {
 		flags = new byte[]{0x29, 0x10};
 		questions = new byte[]{0x00, 0x01};
@@ -104,39 +88,55 @@ public class NBNS {
 		additional = getAdditionalRecords();
 	}
 	
+	/**
+	 * Prepares the content for the next response packet.
+	 */
+	public void prepareResponsePacket(byte[] packet, byte[] myAddr) {
+		this.transactID = new byte[]{packet[0], packet[1]};
+		flags = new byte[]{(byte) 0x85, (byte) 0x80};
+		questions = new byte[]{0x00, 0x00};
+		answerRRs = new byte[]{0x00, 0x01};
+		authorityRRs = new byte[]{0x00, 0x00};
+		additionalRRs = new byte[]{0x00, 0x00};
+		byte[] nameBytes = new byte[32]; 
+		System.arraycopy(packet, 13, nameBytes, 0, 32);
+		String name = NMBStringCoder.decodeNBNSName(nameBytes);
+		byte[] query = new byte[50];
+		System.arraycopy(packet, 12, query, 0, 38);
+		// time to live
+		query[38] = 0x00;
+		query[39] = 0x00;
+		query[40] = 0x02;
+		query[41] = 0x58;
+		// data length
+		query[42] = 0x00;
+		query[43] = 0x06;
+		// name flags
+		query[44] = (byte) 0x80;
+		query[45] = 0x00;
+		// addr
+		query[46] = myAddr[0];
+		query[47] = myAddr[1];
+		query[48] = myAddr[2];
+		query[49] = myAddr[3];
+		payload = query;
+	}
+	
+	/**
+	 * Builds the payload for the packet.
+	 * @return payload.
+	 */
 	private byte[] getPayload() {
 		byte[] payload = NMBStringCoder.wrapNBNSName(this.name, service);
 		byte[] type = {0x00, 0x20};
 		byte[] nbnsclass = {0x00, 0x01};
 		return HelperUtils.concat(payload, type, nbnsclass);
 	}
-		
-	private void addressToBytes(String addrString) {
-		String[] addrParts = addrString.split("\\.");
-		addr = new byte[4];
-		addr[0] = (byte)Integer.parseInt(addrParts[0]);
-		addr[1] = (byte)Integer.parseInt(addrParts[1]);
-		addr[2] = (byte)Integer.parseInt(addrParts[2]);
-		addr[3] = (byte)Integer.parseInt(addrParts[3]);
-	}
-	
-	public static byte[] getServiceBytes(int service) {
-		switch (service) {
-		case NBNSService.SERVER:
-			return new byte[]{0x43, 0x41};
-		case NBNSService.MESSENGER:
-			return new byte[]{0x41, 0x44};
-		case NBNSService.WORKSTATION:
-			return new byte[]{0x41, 0x41};
-		case NBNSService.BROWSER_ELECTION:
-			return new byte[]{0x42, 0x4f};
-		case NBNSService.LOCAL_MASTER_BROWSER:
-			return new byte[]{0x42, 0x4e};
-		default:
-			return new byte[]{0x43, 0x41};
-		}
-	}
 
+	/**
+	 * Builds the additional records field.
+	 * @return additional records.
+	 */
 	private byte[] getAdditionalRecords() {
 		byte[] name = {(byte) 0xc0, 0x0c};
 		byte[] type = {0x00, 0x20};
@@ -148,43 +148,58 @@ public class NBNS {
 		return HelperUtils.concat(name, type, nbnsclass, timeToLive, length, nameFlags, addr);
 	}
 	
+	/**
+	 * Returns the next packet.
+	 * Use only after the name, type and service were set.
+	 * @return next packet.
+	 */
 	public byte[] getNextPacket() {
 		preparePacket();
-		transactID[1] += 0x01;
+		return getBytes();
+	}
+	
+	/**
+	 * Returns the next response packet.
+	 * @param packet request packet.
+	 * @param myAddr your current ip in bytes.
+	 * @return next response packet.
+	 */
+	public byte[] getNextResponse(byte[] packet, byte[] myAddr) {
+		prepareResponsePacket(packet, myAddr);
 		return getBytes();
 	}
 
-	public byte[] getBytes() {
+	/**
+	 * Returns the content of the packet in bytes.
+	 * @return packet content.
+	 */
+	private byte[] getBytes() {
 		return HelperUtils.concat(transactID, flags, questions, answerRRs, authorityRRs, additionalRRs, payload, additional);
 	}
 
+	/**
+	 * Set the name for the payload.
+	 * @param name.
+	 */
 	public void setName(String name) {
 		this.name = name.getBytes();
 		this.name = NMBStringCoder.encodeNBNSName(this.name);
 	}
 
+	/**
+	 * Set the NBNSType.
+	 * @param type NBNSType.
+	 */
 	public void setType(int type) {
 		this.type = type;
 	}
 
+	/**
+	 * Set the NBNSService.
+	 * @param service NBNSService.
+	 */
 	public void setService(int service) {
 		this.service = service;
 	}
 
-	public byte[] getAndIncTransactID() {
-		byte[] response = new byte[2];
-		response[0] = transactID[0];
-		response[1] = transactID[1];
-		transactID[1] += 0x01;
-		return response;
-	}
-
-	public byte[] getAddr() {
-		return addr;
-	}
-
-	public byte[] getName() {
-		return name;
-	}
-	
 }

+ 27 - 0
src/de/tudarmstadt/informatik/hostage/protocol/smbutils/NBNSService.java

@@ -1,10 +1,37 @@
 package de.tudarmstadt.informatik.hostage.protocol.smbutils;
 
+/**
+ * NetBios Name Service services.
+ * @author Wulf Pfeiffer.
+ */
 public class NBNSService {
+
 	public static final int SERVER = 0;
 	public static final int MESSENGER = 1;
 	public static final int WORKSTATION = 2;
 	public static final int BROWSER_ELECTION = 3;
 	public static final int LOCAL_MASTER_BROWSER = 4;
 	public static final int BROWSER = 5;
+
+	/**
+	 * Returns the proper bytes that are used in the wrapping of netbios names for the NBNSService.
+	 * @param service NBNSService.
+	 * @return bytes.
+	 */
+	public static byte[] getServiceBytes(int service) {
+		switch (service) {
+		case NBNSService.SERVER:
+			return new byte[]{0x43, 0x41};
+		case NBNSService.MESSENGER:
+			return new byte[]{0x41, 0x44};
+		case NBNSService.WORKSTATION:
+			return new byte[]{0x41, 0x41};
+		case NBNSService.BROWSER_ELECTION:
+			return new byte[]{0x42, 0x4f};
+		case NBNSService.LOCAL_MASTER_BROWSER:
+			return new byte[]{0x42, 0x4e};
+		default:
+			return new byte[]{0x43, 0x41};
+		}
+	}
 }

+ 6 - 0
src/de/tudarmstadt/informatik/hostage/protocol/smbutils/NBNSType.java

@@ -1,8 +1,14 @@
 package de.tudarmstadt.informatik.hostage.protocol.smbutils;
 
+/**
+ * NetBios Name Service types.
+ * @author Wulf Pfeiffer.
+ */
 public class NBNSType {
+
 	public static final int REGISTRATION_UNIQUE = 0;
 	public static final int REGISTRATION_GROUP = 1;
 	public static final int NAME_QUERY = 2;
 	public static final int REGISTRATION_MSBROWSE = 3;
+
 }

+ 69 - 0
src/de/tudarmstadt/informatik/hostage/protocol/smbutils/NBSS.java

@@ -0,0 +1,69 @@
+package de.tudarmstadt.informatik.hostage.protocol.smbutils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.List;
+
+import de.tudarmstadt.informatik.hostage.nio.Reader;
+import de.tudarmstadt.informatik.hostage.nio.Writer;
+import de.tudarmstadt.informatik.hostage.protocol.Protocol.TALK_FIRST;
+import de.tudarmstadt.informatik.hostage.protocol.SMB;
+import de.tudarmstadt.informatik.hostage.wrapper.Packet;
+
+/**
+ * NetBIOS Session Service.
+ * @author Wulf Pfeiffer
+ */
+public class NBSS extends Thread {
+	
+	private int nbssPort;
+	private ServerSocket nbssServer;
+	private Socket nbssSocket;
+	private Reader reader;
+	private Writer writer;
+	private SMB smb;
+	
+	@Override
+	public void run() {
+		try {
+			nbssPort = 139;
+			nbssServer = new ServerSocket(nbssPort);
+			nbssSocket = nbssServer.accept();
+			smb = new SMB();
+			talkToClient(nbssSocket.getInputStream(), nbssSocket.getOutputStream());
+			
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+	
+	/**
+	 * Used for communicating with a client.
+	 * @param in
+	 * @param out
+	 * @throws IOException
+	 */
+	private void talkToClient(InputStream in, OutputStream out) throws IOException {
+		reader = new Reader(in, smb.toString());
+		writer = new Writer(out);
+		Packet inputLine;
+		List<Packet> outputLine;
+		if (smb.whoTalksFirst() == TALK_FIRST.SERVER) {
+			outputLine = smb.processMessage(null);
+			writer.write(outputLine);
+		}
+		while (!isInterrupted() && (inputLine = reader.read()) != null) {
+			outputLine = smb.processMessage(inputLine);
+			if (outputLine != null) {
+				writer.write(outputLine);
+			}
+			if (smb.isClosed()) {
+				break;
+			}
+		}
+	}
+	
+}

+ 177 - 77
src/de/tudarmstadt/informatik/hostage/protocol/smbutils/NMB.java

@@ -4,11 +4,17 @@ import java.io.IOException;
 import java.net.DatagramPacket;
 import java.net.DatagramSocket;
 import java.net.InetAddress;
+import java.net.SocketException;
 import java.net.SocketTimeoutException;
 import java.net.UnknownHostException;
 
-import de.tudarmstadt.informatik.hostage.net.MyDatagramSocketFactory;
+import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
 
+/**
+ * NetBIOS.
+ * Used to registrate computers and workgroups in a windows network.
+ * @author Wulf Pfeiffer
+ */
 public class NMB extends Thread {
 	
 	private DatagramSocket nbnsSocket;
@@ -23,23 +29,46 @@ public class NMB extends Thread {
 	private String workgroup;
 	private NBNS nbns;
 	private NBDS nbds;
-	private volatile boolean smbRunning;
-	private Receiver receiver;
+	private boolean isMaster;
+	private byte[] addr = new byte[4]; 
+	private static byte[] transactID = HelperUtils.randomBytes(2);
 	
 	public NMB(String ip, String username, String workgroup) {
 		try {
-			smbRunning = true;
+			isMaster = false;
 			this.username = username;
 			this.workgroup = workgroup;
 			this.ip = ip;
 			ipParts = ip.split("\\.");
 			String newHostAddr = ipParts[0] + "." + ipParts[1] + "." + ipParts[2] + ".255";
 			dst = InetAddress.getByName(newHostAddr);
+			addr = addressToBytes(ip);
+			nbns = new NBNS(addr);
+			nbds = new NBDS(addr, username, workgroup);
 		} catch (UnknownHostException e) {
 			e.printStackTrace();
 		}
 	}
 	
+	/**
+	 * Converts an ip address string into a byte array of length 4.
+	 * @param addrString ip address.
+	 * @return 4 byte ip address.
+	 */
+	private byte[] addressToBytes(String addrString) {
+		String[] addrParts = addrString.split("\\.");
+		byte[] newAddr = new byte[4];
+		newAddr[0] = (byte)Integer.parseInt(addrParts[0]);
+		newAddr[1] = (byte)Integer.parseInt(addrParts[1]);
+		newAddr[2] = (byte)Integer.parseInt(addrParts[2]);
+		newAddr[3] = (byte)Integer.parseInt(addrParts[3]);
+		return newAddr;
+	}
+	
+	/**
+	 * Sends a NBNS packet.
+	 * @param nbns packet.
+	 */
 	private void sendPacket(NBNS nbns) {
 		try {
 			byte[] packetBytes = nbns.getNextPacket();
@@ -50,9 +79,13 @@ public class NMB extends Thread {
 		}
 	}
 	
+	/**
+	 * Sends a NBDS packet.
+	 * @param nbds packet.
+	 */
 	private void sendPacket(NBDS nbds) {
 		try {
-			byte[] packetBytes = nbds.getBytes();
+			byte[] packetBytes = nbds.getNextPacket();
 			packet = new DatagramPacket(packetBytes, packetBytes.length, dst, nbdsPort);
 			nbdsSocket.send(packet);
 		} catch (IOException e) {
@@ -60,13 +93,21 @@ public class NMB extends Thread {
 		}
 	}
 	
+	/**
+	 * Sends the required packets for user and workgroup registration.
+	 */
 	private void registrate() {
 		registrateUser();
 		registrateGroup();
 	}
 	
+	/**
+	 * Sends the required packets for user registration.
+	 */
 	private void registrateUser() {
-		nbns = new NBNS(new byte[]{0x50, 0x00}, NBNSType.REGISTRATION_UNIQUE, NBNSService.SERVER, username, ip);
+		nbns.setType(NBNSType.REGISTRATION_UNIQUE);
+		nbns.setService(NBNSService.SERVER);
+		nbns.setName(username);
 		sendPacket(nbns);
 		
 		nbns.setService(NBNSService.MESSENGER);
@@ -76,6 +117,9 @@ public class NMB extends Thread {
 		sendPacket(nbns);
 	}
 	
+	/**
+	 * Sends the required packets for workgroup registration.
+	 */
 	private void registrateGroup() {
 		nbns.setName(workgroup);
 		nbns.setType(NBNSType.REGISTRATION_GROUP);
@@ -85,11 +129,17 @@ public class NMB extends Thread {
 		sendPacket(nbns);
 	}
 	
+	/*
+	 * Sends the browser election request.
+	 */
 	private void browserElection() {
-		nbds = new NBDS(nbns.getAndIncTransactID(), nbns.getAddr(), username, workgroup, NBDSType.BROWSER);
+		nbds.setNbdstype(NBDSType.BROWSER);
 		sendPacket(nbds);
 	}
 	
+	/**
+	 * Sends the required packets for MSBROWSE registration.
+	 */
 	private void registrateMsBrowse() {
 		nbns.setName("__MSBROWSE__");
 		nbns.setType(NBNSType.REGISTRATION_MSBROWSE);
@@ -97,6 +147,9 @@ public class NMB extends Thread {
 		sendPacket(nbns);
 	}
 	
+	/**
+	 * Sends the required packets for local master registration.
+	 */
 	private void registrateLocalMaster() {
 		nbns.setName(workgroup);
 		nbns.setType(NBNSType.REGISTRATION_UNIQUE);
@@ -104,122 +157,169 @@ public class NMB extends Thread {
 		sendPacket(nbns);
 	}
 	
+	/**
+	 * Sends the required packets for host announcement with services.
+	 */
 	private void announceHost() {
-		nbds = new NBDS(nbns.getAndIncTransactID(), nbns.getAddr(), username, workgroup, NBDSType.HOST_ANNOUNCEMENT_WITH_SERVICES);
+		nbds.setNbdstype(NBDSType.HOST_ANNOUNCEMENT_WITH_SERVICES);
 		sendPacket(nbds);
 	}
 	
+	/**
+	 * Sends the required packets for a name query.
+	 */
 	private void queryName() {
 		nbns.setType(NBNSType.NAME_QUERY);
 		nbns.setService(NBNSService.LOCAL_MASTER_BROWSER);
 		sendPacket(nbns);
 	}
 	
+	/**
+	 * Sends the required packets for a request announcement
+	 */
 	private void requestAnnouncement() {
-		nbds = new NBDS(nbns.getAndIncTransactID(), nbns.getAddr(), username, workgroup, NBDSType.REQUEST_ANNOUNCEMENT);
+		nbds.setNbdstype(NBDSType.REQUEST_ANNOUNCEMENT);
 		sendPacket(nbds);
 	}
 	
+	/**
+	 * Sends the required packets for a local master announcement to all.
+	 */
 	private void localMasterAnnouncementAll() {
-		nbds = new NBDS(nbns.getAndIncTransactID(), nbns.getAddr(), username, workgroup, NBDSType.LOCAL_MASTER_ANNOUNCEMENT_ALL);
+		nbds.setNbdstype(NBDSType.LOCAL_MASTER_ANNOUNCEMENT_ALL);
 		sendPacket(nbds);
 	}
 	
+	/**
+	 * Sends the required packets for a domain announcement.
+	 */
 	private void domainAnnouncement() {
-		nbds = new NBDS(nbns.getAndIncTransactID(), nbns.getAddr(), username, workgroup, NBDSType.DOMAIN_ANNOUNCEMENT);
+		nbds.setNbdstype(NBDSType.DOMAIN_ANNOUNCEMENT);
 		sendPacket(nbds);
 	}
 	
+	/**
+	 * Sends the required packets for a local master announcement.
+	 */
 	private void localMasterAnnouncement() {
-		nbds = new NBDS(nbns.getAndIncTransactID(), nbns.getAddr(), username, workgroup, NBDSType.LOCAL_MASTER_ANNOUNCEMENT);
+		nbds.setNbdstype(NBDSType.LOCAL_MASTER_ANNOUNCEMENT);
 		sendPacket(nbds);
 	}
 
 	@Override
-	public void run() {		
+	public void run() {
+		NBSS nbss = new NBSS();
+		nbss.start();
 		try {
-			nbnsSocket = new MyDatagramSocketFactory().createDatagramSocket(nbnsPort);
-			nbnsSocket.connect(dst, nbnsPort);
-			nbdsSocket = new MyDatagramSocketFactory().createDatagramSocket(nbdsPort);
-			nbdsSocket.connect(dst, nbdsPort);
-		} catch (IOException e) {
+			nbnsSocket = new DatagramSocket(nbnsPort);
+			nbdsSocket = new DatagramSocket(nbdsPort);
+		} catch (SocketException e) {
 			e.printStackTrace();
 		}
 		
 		registrate();
-		receiver = new Receiver();
-		receiver.start();
 		announceHost();
 		queryName();
+		checkForAnswers();
 		
-		registrate();
-		queryName();
-		
-		registrate();
-		queryName();
-		
-		registrate();
-		queryName();	
-		
-		browserElection();
-		browserElection();
-		browserElection();
-		browserElection();
-		
-		registrateMsBrowse();
-		registrateMsBrowse();
-		registrateMsBrowse();
-		registrateMsBrowse();
-		
-		registrateLocalMaster();
-		registrateLocalMaster();
-		registrateLocalMaster();
-		registrateLocalMaster();
-		
-		requestAnnouncement();
-		localMasterAnnouncementAll();
-		domainAnnouncement();
-		
-//		// domain/workgroup announcement
-//		// local master announcmen
+		if (isMaster) {
+			registrate();
+			queryName();
+			
+			registrate();
+			queryName();
+			
+			registrate();
+			queryName();	
+			
+			browserElection();
+			browserElection();
+			browserElection();
+			browserElection();
+			
+			registrateMsBrowse();
+			registrateMsBrowse();
+			registrateMsBrowse();
+			registrateMsBrowse();
+			
+			registrateLocalMaster();
+			registrateLocalMaster();
+			registrateLocalMaster();
+			registrateLocalMaster();
+			
+			requestAnnouncement();
+			localMasterAnnouncementAll();
+			domainAnnouncement();
+			localMasterAnnouncement();
+		}
 		
 		announceHost();	
 		
+//		talk();
+		
 		nbnsSocket.close();
 		nbdsSocket.close();
 	}
+		
+	private byte[] buffer = new byte[2048];
+	private boolean masterAnswered = false;
+	private DatagramPacket receive = new DatagramPacket(buffer, buffer.length);
 
-	public synchronized void setSmbRunning(boolean smbRunning) {
-		this.smbRunning = smbRunning;
+	/**
+	 * Check if the specified workgroup is already existing.
+	 * If someone answers on your register messages there is already a master.
+	 */
+	private void checkForAnswers() {
+		try {
+			nbnsSocket.setSoTimeout(1000);
+			try {
+				while (!masterAnswered) {
+					nbnsSocket.receive(receive);					
+					if (!(receive.getAddress().toString().equals("/"+ip))) {
+						masterAnswered = true;
+						isMaster = false;
+					}
+					
+				}
+			} catch (SocketTimeoutException e) {
+				isMaster = true;
+				e.printStackTrace();
+			}
+		} catch (IOException e) {
+			isMaster = true;
+			e.printStackTrace();
+		}
+	}	
+
+	/**
+	 * Returns the current transactID and increases it by one.
+	 * @return transactID.
+	 */
+	public static byte[] getAndIncTransactID() {
+		transactID[1]++;
+		if (transactID[1] == 0x00) {
+			transactID[0]++;
+		}
+		return transactID;
 	}
 	
-	private class Receiver extends Thread {
-		
-		private DatagramPacket packet;
-		private byte[] buffer;
-		private boolean masterAnswered = false;
-		
-		public Receiver() {
-			buffer = new byte[2048];
-			packet = new DatagramPacket(buffer, buffer.length);
+	/**
+	 * Handling requests after initial registration
+	 */
+	private void talk() {
+		try {
+			nbnsSocket.setSoTimeout(0);
+		} catch (SocketException e) {
+			e.printStackTrace();
 		}
-		
-		@Override
-		public void run() {
+		DatagramPacket request = new DatagramPacket(buffer, buffer.length);
+		DatagramPacket response = new DatagramPacket(buffer, buffer.length);
+		while (true) {
 			try {
-				nbnsSocket.setSoTimeout(1000);
-				try {
-					while (!masterAnswered) {
-						nbnsSocket.receive(packet);
-						if (!(packet.getAddress().toString().equals("/"+ip))) {
-							masterAnswered = true;
-							setSmbRunning(false);
-						}
-					}
-				} catch (SocketTimeoutException e) {
-					setSmbRunning(false);
-					e.printStackTrace();
-				}	
+				nbnsSocket.receive(request);
+				byte[] resp = nbns.getNextResponse(request.getData(), addressToBytes(ip));
+				response = new DatagramPacket(resp, resp.length, request.getAddress(), nbnsPort);
+				nbnsSocket.send(response);
 			} catch (IOException e) {
 				e.printStackTrace();
 			}

+ 37 - 17
src/de/tudarmstadt/informatik/hostage/protocol/smbutils/NMBStringCoder.java

@@ -2,31 +2,44 @@ package de.tudarmstadt.informatik.hostage.protocol.smbutils;
 
 import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
 
-
+/**
+ * Used to encode and decode a String into a byte array so that they can be used in NetBIOS.
+ * @author Wulf Pfeiffer
+ */
 public class NMBStringCoder {
 
+	/**
+	 * Decodes a netbios name as byte array to its proper String value.
+	 * @param name bytes.
+	 * @return String.
+	 */
 	public static String decodeNBNSName(byte[] name) {
 		byte a_ascii = (byte) 'A';
 		byte[] reducedA = new byte[name.length];
 		for (int i = 0; i < name.length; i++) {
-			reducedA[i] = (byte)(name[i] - a_ascii);
+			reducedA[i] = (byte) (name[i] - a_ascii);
 		}
 		byte[] converted = new byte[reducedA.length / 2];
-		for (int i = 0, j = 0; i < name.length && j < converted.length; i+=2, j++) {
-			byte b1 = (byte) (reducedA[i]<<4);
-			byte b2 = reducedA[i+1];
+		for (int i = 0, j = 0; i < name.length && j < converted.length; i += 2, j++) {
+			byte b1 = (byte) (reducedA[i] << 4);
+			byte b2 = reducedA[i + 1];
 			converted[j] = (byte) (b1 | b2);
 		}
 		return new String(converted);
 	}
-	
+
+	/**
+	 * Encodes a String into its netbios name as byte array.
+	 * @param name.
+	 * @return netbios name.
+	 */
 	public static byte[] encodeNBNSName(byte[] name) {
 		byte a_ascii = (byte) 'A';
 		byte[] bytes = name;
 		byte[] converted = new byte[bytes.length * 2];
-		for (int i = 0, j = 0; i < bytes.length && j < converted.length; i++, j+=2) {
-			converted[j] = (byte)(bytes[i]>>4);
-			converted[j+1] = (byte)(bytes[i] & 0x0F);
+		for (int i = 0, j = 0; i < bytes.length && j < converted.length; i++, j += 2) {
+			converted[j] = (byte) (bytes[i] >> 4);
+			converted[j + 1] = (byte) (bytes[i] & 0x0F);
 		}
 		byte[] addedA = new byte[converted.length];
 		for (int i = 0; i < converted.length; i++) {
@@ -34,25 +47,32 @@ public class NMBStringCoder {
 		}
 		return addedA;
 	}
-	
+
+	/**
+	 * Wraps a NetBIOS name with the required start and end bytes and some more informations.
+	 * @param name netbios name.
+	 * @param service NBNDSService.
+	 * @return wrapped content.
+	 */
 	public static byte[] wrapNBNSName(byte[] name, int service) {
-		byte[] nameStart = {0x20};
+		byte[] nameStart = { 0x20 };
 		byte[] namePadding = null;
 		if (name.length < 32) {
 			int paddingLen = 32 - name.length;
 			namePadding = new byte[paddingLen];
-			for (int i = 0; i < namePadding.length; i+=2) {
-				if (i == namePadding.length-2) {
-					byte[] serviceBytes = NBNS.getServiceBytes(service);
+			for (int i = 0; i < namePadding.length; i += 2) {
+				if (i == namePadding.length - 2) {
+					byte[] serviceBytes = NBNSService.getServiceBytes(service);
 					namePadding[i] = serviceBytes[0];
-					namePadding[i+1] = serviceBytes[1];
+					namePadding[i + 1] = serviceBytes[1];
 				} else {
 					namePadding[i] = 0x43;
-					namePadding[i+1] = 0x041;
+					namePadding[i + 1] = 0x041;
 				}
 			}
 		}
-		byte[] nameEnd = {0x00};
+		byte[] nameEnd = { 0x00 };
 		return HelperUtils.concat(nameStart, name, namePadding, nameEnd);
 	}
+
 }

+ 24 - 18
src/de/tudarmstadt/informatik/hostage/protocol/smbutils/SMBPacket.java

@@ -5,8 +5,6 @@ import java.util.Calendar;
 import java.util.GregorianCalendar;
 import java.util.TimeZone;
 
-import javax.net.ssl.HostnameVerifier;
-
 import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
 
 /**
@@ -17,8 +15,7 @@ import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
 public class SMBPacket {
 	
 	private String[] serverVersion;
-	private static byte[] serverName = HelperUtils.fillWithZero(HelperUtils
-			.getRandomString(16, true).getBytes());
+	private static byte[] serverName;
 	private byte[] message = null;
 	private static final byte[] serverGUID = HelperUtils.randomBytes(16);
 	private boolean authenticateNext = false;
@@ -38,14 +35,16 @@ public class SMBPacket {
 	private byte[] multiplexID = new byte[2];
 	
 	//special nbds stuff
-	private byte[] workgroup;
+	private static byte[] workgroup;
 	private int type;
 	
-	public SMBPacket(String[] serverVersion) {
+	public SMBPacket(String[] serverVersion, String serverName, String workgroup) {
 		this.serverVersion = serverVersion;
+		SMBPacket.serverName = serverName.getBytes();
+		SMBPacket.workgroup = workgroup.getBytes();
 	}
 	
-	public void prepareNextResponse(int type, String serverName, String workgroup) {
+	public void prepareNextResponse(int type) {
 		serverComp = new byte[] { (byte) 0xff, 0x53, 0x4d, 0x42 };
 		smbCommand = new byte[] { 0x25 };
 		ntStat = new byte[] { 0x00, 0x00, 0x00, 0x00 };
@@ -59,9 +58,7 @@ public class SMBPacket {
 		processID = new byte[] { 0x00, 0x00 };
 		userID = new byte[] { 0x00, 0x00 };
 		multiplexID = new byte[] { 0x00, 0x00 };
-		this.workgroup = workgroup.getBytes();
 		this.type = type;
-		SMBPacket.serverName = serverName.getBytes();
 	}
 	
 	public void prepareNextResponse(byte[] message) {
@@ -449,7 +446,7 @@ public class SMBPacket {
 		if (transSub[0] == (byte) 0xff) { // for NMB in host announcement, NOT smb protocol
 			byte[] wordCount = { 0x11 };
 			byte[] totalParamCount = { 0x00, 0x00 };
-			byte[] totalDataCount = new byte[2]; //TODO
+			byte[] totalDataCount = new byte[2];
 			byte[] maxParamCount = { 0x00, 0x00 };
 			byte[] maxDataCount = { 0x00, 0x00 };
 			byte[] maxSetupCount = { 0x00 };
@@ -459,7 +456,7 @@ public class SMBPacket {
 			byte[] reserved2 = { 0x00, 0x00 };
 			byte[] paramCount = { 0x00, 0x00 };
 			byte[] paramOffset = { 0x00, 0x00 };
-			byte[] dataCount = new byte[2]; //TODO
+			byte[] dataCount = new byte[2];
 			byte[] dataOffset = { 0x56, 0x00 };
 			byte[] setupCount = { 0x03 };
 			byte[] reserved3 = { 0x00 };
@@ -468,20 +465,19 @@ public class SMBPacket {
 			byte[] opcode = new byte[]{0x01, 0x00};
 			byte[] priority = new byte[]{0x01, 0x00};
 			byte[] smbclass = new byte[]{0x02, 0x00};
-			byte[] size = new byte[2]; //TODO
+			byte[] size = new byte[2];
 			byte[] name = HelperUtils.concat("\\MAILSLOT\\BROWSE".getBytes(), new byte[]{0x00}); 
 			
 			byte[] windowsBrowser = null;
-			if (type == NBDSType.HOST_ANNOUNCEMENT_WITH_SERVICES || type == NBDSType.HOST_ANNOUNCEMENT
-					|| type == NBDSType.LOCAL_MASTER_ANNOUNCEMENT_ALL || type == NBDSType.DOMAIN_ANNOUNCEMENT) {
-				windowsBrowser = getAnnouncement();
-			} else if (type == NBDSType.BROWSER) {
+			if (type == NBDSType.BROWSER) {
 				windowsBrowser = getBrowser();
 			} else if (type == NBDSType.REQUEST_ANNOUNCEMENT) {
 				byte[] command = {0x02};
 				byte[] unusedFlags = {0x01, 0x00};
 				byte[] responseCompName = serverName;
 				windowsBrowser = HelperUtils.concat(command, unusedFlags, responseCompName);
+			} else {
+				windowsBrowser = getAnnouncement();
 			}
 
 			byte[] buffer = ByteBuffer.allocate(4).putInt(windowsBrowser.length).array();
@@ -629,10 +625,14 @@ public class SMBPacket {
 		return transSub;
 	}
 	
+	/**
+	 * For NBNS only.
+	 * @return announcement packet.
+	 */
 	private byte[] getAnnouncement() {
 		//Microsoft Windows Browser
 		byte[] command = null;
-		if(type == NBDSType.LOCAL_MASTER_ANNOUNCEMENT_ALL) {
+		if(type == NBDSType.LOCAL_MASTER_ANNOUNCEMENT_ALL || type == NBDSType.LOCAL_MASTER_ANNOUNCEMENT) {
 			command = new byte[]{0x0f};
 		} else if (type == NBDSType.DOMAIN_ANNOUNCEMENT) {
 			command = new byte[]{0x0c};
@@ -647,6 +647,8 @@ public class SMBPacket {
 			updatePeriodicity = new byte[]{0x00, 0x00, 0x00, 0x00};
 		} else if (type == NBDSType.LOCAL_MASTER_ANNOUNCEMENT_ALL || type == NBDSType.DOMAIN_ANNOUNCEMENT) {
 			updatePeriodicity = new byte[]{(byte) 0xc0, (byte) 0xd4, 0x01, 0x00};
+		} else if (type == NBDSType.LOCAL_MASTER_ANNOUNCEMENT) {
+			updatePeriodicity = new byte[]{0x00, 0x00, 0x00, 0x00};
 		}
 		byte[] hostName = null;
 		if (type == NBDSType.DOMAIN_ANNOUNCEMENT) {
@@ -662,7 +664,7 @@ public class SMBPacket {
 		byte[] serverType = null;
 		if (type == NBDSType.HOST_ANNOUNCEMENT_WITH_SERVICES || type == NBDSType.LOCAL_MASTER_ANNOUNCEMENT_ALL) {
 			serverType = new byte[]{0x03, (byte) 0x9a, (byte) 0x81, 0x00};
-		} else if (type == NBDSType.HOST_ANNOUNCEMENT) {
+		} else if (type == NBDSType.HOST_ANNOUNCEMENT || type == NBDSType.LOCAL_MASTER_ANNOUNCEMENT) {
 			serverType = new byte[]{0x00, 0x00, 0x00, 0x00};
 		} else if (type == NBDSType.DOMAIN_ANNOUNCEMENT) {
 			serverType = new byte[]{0x00, 0x10, 0x00, (byte) 0x80};
@@ -682,6 +684,10 @@ public class SMBPacket {
 				signature, hostComment);
 	}
 	
+	/**
+	 * For NBNS only.
+	 * @return MicrosoftBrowser part in NetBIOS packets.
+	 */
 	private byte[] getBrowser() {
 		byte[] command = {0x08};
 		byte[] electionVersion = {0x01};