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.
 Features of HoneyRJ were inspiration for this project.
 http://www.cse.wustl.edu/~jain/cse571-09/ftp/honey/manual.html
 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
 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
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or
 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=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.Hostage;
 import de.tudarmstadt.informatik.hostage.R;
 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.NBNS;
 import de.tudarmstadt.informatik.hostage.protocol.smbutils.NMB;
 import de.tudarmstadt.informatik.hostage.protocol.smbutils.NMB;
 import de.tudarmstadt.informatik.hostage.protocol.smbutils.SMBPacket;
 import de.tudarmstadt.informatik.hostage.protocol.smbutils.SMBPacket;
@@ -36,6 +37,7 @@ public class SMB implements Protocol {
 	 */
 	 */
 	private STATE state = STATE.NONE;
 	private STATE state = STATE.NONE;
 	private byte[] lastMessage;
 	private byte[] lastMessage;
+	private NMB nmb;
 
 
 	// version stuff
 	// version stuff
 	private String[][] possibleSmbVersions = {
 	private String[][] possibleSmbVersions = {
@@ -55,19 +57,24 @@ public class SMB implements Protocol {
 	}
 	}
 	
 	
 	public void setIP(String ip) {
 	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() {
 	private String[] initServerVersion() {
-		System.out.println("hi");
 		String sharedPreferencePath = Hostage.getContext().getString(
 		String sharedPreferencePath = Hostage.getContext().getString(
 				R.string.shared_preference_path);
 				R.string.shared_preference_path);
-		System.out.println(sharedPreferencePath);
 		String profile = Hostage
 		String profile = Hostage
 				.getContext()
 				.getContext()
 				.getSharedPreferences(sharedPreferencePath,
 				.getSharedPreferences(sharedPreferencePath,
 						Hostage.MODE_PRIVATE).getString("os", "");
 						Hostage.MODE_PRIVATE).getString("os", "");
-		System.out.println(profile);
+		if(profile.equals("Windows XP")) {
+			workgroup = "MSHOME";
+		} else {
+			workgroup = "WORKGROUP";
+		}
+		
 		if (profile.equals("Windows 7")) {
 		if (profile.equals("Windows 7")) {
 			return possibleSmbVersions[0];
 			return possibleSmbVersions[0];
 		} else if (profile.equals("Windows 8")) {
 		} 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!!
 	//required to be declared down here, do not change position over initServerVersion() and possibleServerVersions!!
 	private String[] serverVersion = initServerVersion();
 	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
 	@Override
 	public int getPort() {
 	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;
 import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
 
 
-
+/**
+ * NetBIOS Datagram Service.
+ * @author Wulf Pfeiffer
+ */
 public class NBDS {
 public class NBDS {
 	
 	
+	private String dst;
 	private byte[] type;
 	private byte[] type;
 	private byte[] flags;
 	private byte[] flags;
-	private byte[] id;
+	private byte[] transactID;
 	private byte[] srcIP;
 	private byte[] srcIP;
 	private byte[] srcPort;
 	private byte[] srcPort;
 	private byte[] length;
 	private byte[] length;
 	private byte[] offset;
 	private byte[] offset;
 	private byte[] srcName;
 	private byte[] srcName;
 	private byte[] dstName;
 	private byte[] dstName;
+	private int nbdstype;
 	private SMBPacket smb;
 	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};
 		flags = new byte[]{0x0a};
-		id = transactID;
 		srcIP = addr;
 		srcIP = addr;
 		srcPort = new byte[]{0x00, (byte) 0x8a};
 		srcPort = new byte[]{0x00, (byte) 0x8a};
 		offset = new byte[]{0x00, 0x00};
 		offset = new byte[]{0x00, 0x00};
 		length = new byte[2];
 		length = new byte[2];
 		srcName = NMBStringCoder.wrapNBNSName(NMBStringCoder.encodeNBNSName(src.getBytes()), NBNSService.WORKSTATION);
 		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);
 			dstName = NMBStringCoder.wrapNBNSName(NMBStringCoder.encodeNBNSName(dst.getBytes()), NBNSService.BROWSER_ELECTION);
 		} else if (nbdstype == NBDSType.DOMAIN_ANNOUNCEMENT) {
 		} else if (nbdstype == NBDSType.DOMAIN_ANNOUNCEMENT) {
 			dstName = HelperUtils.concat(new byte[]{0x20, 0x41, 0x42, 0x41, 0x43}, NMBStringCoder.encodeNBNSName("__MSBROWSE__".getBytes()),
 			dstName = HelperUtils.concat(new byte[]{0x20, 0x41, 0x42, 0x41, 0x43}, NMBStringCoder.encodeNBNSName("__MSBROWSE__".getBytes()),
@@ -35,17 +49,35 @@ public class NBDS {
 		} else {
 		} else {
 			dstName = NMBStringCoder.wrapNBNSName(NMBStringCoder.encodeNBNSName(dst.getBytes()), NBNSService.LOCAL_MASTER_BROWSER);
 			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[] buffer = HelperUtils.concat(srcName, dstName, smb.getTrans());
 		byte[] lengthBuffer = ByteBuffer.allocate(4).putInt(buffer.length).array();
 		byte[] lengthBuffer = ByteBuffer.allocate(4).putInt(buffer.length).array();
 		length[0] = lengthBuffer[2];
 		length[0] = lengthBuffer[2];
 		length[1] = lengthBuffer[3];
 		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());
 				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;
 package de.tudarmstadt.informatik.hostage.protocol.smbutils;
 
 
+/**
+ * NetBios Datagram Service types.
+ * @author Wulf Pfeiffer.
+ */
 public class NBDSType {
 public class NBDSType {
-	
+
 	public static final int HOST_ANNOUNCEMENT = 0;
 	public static final int HOST_ANNOUNCEMENT = 0;
 	public static final int HOST_ANNOUNCEMENT_WITH_SERVICES = 1;
 	public static final int HOST_ANNOUNCEMENT_WITH_SERVICES = 1;
 	public static final int BROWSER = 2;
 	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 LOCAL_MASTER_ANNOUNCEMENT_ALL = 4;
 	public static final int DOMAIN_ANNOUNCEMENT = 5;
 	public static final int DOMAIN_ANNOUNCEMENT = 5;
 	public static final int LOCAL_MASTER_ANNOUNCEMENT = 6;
 	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;
 import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
 
 
-
+/**
+ * NetBIOS Name Service.
+ * @author Wulf Pfeiffer
+ */
 public class NBNS {
 public class NBNS {
 	
 	
 	private byte[] transactID;
 	private byte[] transactID;
@@ -20,43 +23,15 @@ public class NBNS {
 	private int type;
 	private int type;
 	private int service;
 	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() {
 	private void preparePacket() {
+		transactID = NMB.getAndIncTransactID();
 		switch (type) {
 		switch (type) {
 		case NBNSType.REGISTRATION_UNIQUE:
 		case NBNSType.REGISTRATION_UNIQUE:
 			prepareRegistrationPacket();
 			prepareRegistrationPacket();
@@ -74,6 +49,9 @@ public class NBNS {
 		}
 		}
 	}
 	}
 	
 	
+	/**
+	 * Prepares the content for the next registration packet.
+	 */
 	private void prepareRegistrationPacket() {
 	private void prepareRegistrationPacket() {
 		flags = new byte[]{0x29, 0x10};
 		flags = new byte[]{0x29, 0x10};
 		questions = new byte[]{0x00, 0x01};
 		questions = new byte[]{0x00, 0x01};
@@ -84,6 +62,9 @@ public class NBNS {
 		additional = getAdditionalRecords();
 		additional = getAdditionalRecords();
 	}
 	}
 	
 	
+	/**
+	 * Prepares the content for the next name query packet.
+	 */
 	private void prepareNameQueryPacket() {
 	private void prepareNameQueryPacket() {
 		flags = new byte[] {0x01, 0x10};
 		flags = new byte[] {0x01, 0x10};
 		questions = new byte[]{0x00, 0x01};
 		questions = new byte[]{0x00, 0x01};
@@ -93,6 +74,9 @@ public class NBNS {
 		payload = getPayload();
 		payload = getPayload();
 	}
 	}
 	
 	
+	/**
+	 * Prepares the content for the next MSBROWSE registration packet.
+	 */
 	private void prepareRegistrationMsBrowse() {
 	private void prepareRegistrationMsBrowse() {
 		flags = new byte[]{0x29, 0x10};
 		flags = new byte[]{0x29, 0x10};
 		questions = new byte[]{0x00, 0x01};
 		questions = new byte[]{0x00, 0x01};
@@ -104,39 +88,55 @@ public class NBNS {
 		additional = getAdditionalRecords();
 		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() {
 	private byte[] getPayload() {
 		byte[] payload = NMBStringCoder.wrapNBNSName(this.name, service);
 		byte[] payload = NMBStringCoder.wrapNBNSName(this.name, service);
 		byte[] type = {0x00, 0x20};
 		byte[] type = {0x00, 0x20};
 		byte[] nbnsclass = {0x00, 0x01};
 		byte[] nbnsclass = {0x00, 0x01};
 		return HelperUtils.concat(payload, type, nbnsclass);
 		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() {
 	private byte[] getAdditionalRecords() {
 		byte[] name = {(byte) 0xc0, 0x0c};
 		byte[] name = {(byte) 0xc0, 0x0c};
 		byte[] type = {0x00, 0x20};
 		byte[] type = {0x00, 0x20};
@@ -148,43 +148,58 @@ public class NBNS {
 		return HelperUtils.concat(name, type, nbnsclass, timeToLive, length, nameFlags, addr);
 		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() {
 	public byte[] getNextPacket() {
 		preparePacket();
 		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();
 		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);
 		return HelperUtils.concat(transactID, flags, questions, answerRRs, authorityRRs, additionalRRs, payload, additional);
 	}
 	}
 
 
+	/**
+	 * Set the name for the payload.
+	 * @param name.
+	 */
 	public void setName(String name) {
 	public void setName(String name) {
 		this.name = name.getBytes();
 		this.name = name.getBytes();
 		this.name = NMBStringCoder.encodeNBNSName(this.name);
 		this.name = NMBStringCoder.encodeNBNSName(this.name);
 	}
 	}
 
 
+	/**
+	 * Set the NBNSType.
+	 * @param type NBNSType.
+	 */
 	public void setType(int type) {
 	public void setType(int type) {
 		this.type = type;
 		this.type = type;
 	}
 	}
 
 
+	/**
+	 * Set the NBNSService.
+	 * @param service NBNSService.
+	 */
 	public void setService(int service) {
 	public void setService(int service) {
 		this.service = 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;
 package de.tudarmstadt.informatik.hostage.protocol.smbutils;
 
 
+/**
+ * NetBios Name Service services.
+ * @author Wulf Pfeiffer.
+ */
 public class NBNSService {
 public class NBNSService {
+
 	public static final int SERVER = 0;
 	public static final int SERVER = 0;
 	public static final int MESSENGER = 1;
 	public static final int MESSENGER = 1;
 	public static final int WORKSTATION = 2;
 	public static final int WORKSTATION = 2;
 	public static final int BROWSER_ELECTION = 3;
 	public static final int BROWSER_ELECTION = 3;
 	public static final int LOCAL_MASTER_BROWSER = 4;
 	public static final int LOCAL_MASTER_BROWSER = 4;
 	public static final int BROWSER = 5;
 	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;
 package de.tudarmstadt.informatik.hostage.protocol.smbutils;
 
 
+/**
+ * NetBios Name Service types.
+ * @author Wulf Pfeiffer.
+ */
 public class NBNSType {
 public class NBNSType {
+
 	public static final int REGISTRATION_UNIQUE = 0;
 	public static final int REGISTRATION_UNIQUE = 0;
 	public static final int REGISTRATION_GROUP = 1;
 	public static final int REGISTRATION_GROUP = 1;
 	public static final int NAME_QUERY = 2;
 	public static final int NAME_QUERY = 2;
 	public static final int REGISTRATION_MSBROWSE = 3;
 	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.DatagramPacket;
 import java.net.DatagramSocket;
 import java.net.DatagramSocket;
 import java.net.InetAddress;
 import java.net.InetAddress;
+import java.net.SocketException;
 import java.net.SocketTimeoutException;
 import java.net.SocketTimeoutException;
 import java.net.UnknownHostException;
 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 {
 public class NMB extends Thread {
 	
 	
 	private DatagramSocket nbnsSocket;
 	private DatagramSocket nbnsSocket;
@@ -23,23 +29,46 @@ public class NMB extends Thread {
 	private String workgroup;
 	private String workgroup;
 	private NBNS nbns;
 	private NBNS nbns;
 	private NBDS nbds;
 	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) {
 	public NMB(String ip, String username, String workgroup) {
 		try {
 		try {
-			smbRunning = true;
+			isMaster = false;
 			this.username = username;
 			this.username = username;
 			this.workgroup = workgroup;
 			this.workgroup = workgroup;
 			this.ip = ip;
 			this.ip = ip;
 			ipParts = ip.split("\\.");
 			ipParts = ip.split("\\.");
 			String newHostAddr = ipParts[0] + "." + ipParts[1] + "." + ipParts[2] + ".255";
 			String newHostAddr = ipParts[0] + "." + ipParts[1] + "." + ipParts[2] + ".255";
 			dst = InetAddress.getByName(newHostAddr);
 			dst = InetAddress.getByName(newHostAddr);
+			addr = addressToBytes(ip);
+			nbns = new NBNS(addr);
+			nbds = new NBDS(addr, username, workgroup);
 		} catch (UnknownHostException e) {
 		} catch (UnknownHostException e) {
 			e.printStackTrace();
 			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) {
 	private void sendPacket(NBNS nbns) {
 		try {
 		try {
 			byte[] packetBytes = nbns.getNextPacket();
 			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) {
 	private void sendPacket(NBDS nbds) {
 		try {
 		try {
-			byte[] packetBytes = nbds.getBytes();
+			byte[] packetBytes = nbds.getNextPacket();
 			packet = new DatagramPacket(packetBytes, packetBytes.length, dst, nbdsPort);
 			packet = new DatagramPacket(packetBytes, packetBytes.length, dst, nbdsPort);
 			nbdsSocket.send(packet);
 			nbdsSocket.send(packet);
 		} catch (IOException e) {
 		} catch (IOException e) {
@@ -60,13 +93,21 @@ public class NMB extends Thread {
 		}
 		}
 	}
 	}
 	
 	
+	/**
+	 * Sends the required packets for user and workgroup registration.
+	 */
 	private void registrate() {
 	private void registrate() {
 		registrateUser();
 		registrateUser();
 		registrateGroup();
 		registrateGroup();
 	}
 	}
 	
 	
+	/**
+	 * Sends the required packets for user registration.
+	 */
 	private void registrateUser() {
 	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);
 		sendPacket(nbns);
 		
 		
 		nbns.setService(NBNSService.MESSENGER);
 		nbns.setService(NBNSService.MESSENGER);
@@ -76,6 +117,9 @@ public class NMB extends Thread {
 		sendPacket(nbns);
 		sendPacket(nbns);
 	}
 	}
 	
 	
+	/**
+	 * Sends the required packets for workgroup registration.
+	 */
 	private void registrateGroup() {
 	private void registrateGroup() {
 		nbns.setName(workgroup);
 		nbns.setName(workgroup);
 		nbns.setType(NBNSType.REGISTRATION_GROUP);
 		nbns.setType(NBNSType.REGISTRATION_GROUP);
@@ -85,11 +129,17 @@ public class NMB extends Thread {
 		sendPacket(nbns);
 		sendPacket(nbns);
 	}
 	}
 	
 	
+	/*
+	 * Sends the browser election request.
+	 */
 	private void browserElection() {
 	private void browserElection() {
-		nbds = new NBDS(nbns.getAndIncTransactID(), nbns.getAddr(), username, workgroup, NBDSType.BROWSER);
+		nbds.setNbdstype(NBDSType.BROWSER);
 		sendPacket(nbds);
 		sendPacket(nbds);
 	}
 	}
 	
 	
+	/**
+	 * Sends the required packets for MSBROWSE registration.
+	 */
 	private void registrateMsBrowse() {
 	private void registrateMsBrowse() {
 		nbns.setName("__MSBROWSE__");
 		nbns.setName("__MSBROWSE__");
 		nbns.setType(NBNSType.REGISTRATION_MSBROWSE);
 		nbns.setType(NBNSType.REGISTRATION_MSBROWSE);
@@ -97,6 +147,9 @@ public class NMB extends Thread {
 		sendPacket(nbns);
 		sendPacket(nbns);
 	}
 	}
 	
 	
+	/**
+	 * Sends the required packets for local master registration.
+	 */
 	private void registrateLocalMaster() {
 	private void registrateLocalMaster() {
 		nbns.setName(workgroup);
 		nbns.setName(workgroup);
 		nbns.setType(NBNSType.REGISTRATION_UNIQUE);
 		nbns.setType(NBNSType.REGISTRATION_UNIQUE);
@@ -104,122 +157,169 @@ public class NMB extends Thread {
 		sendPacket(nbns);
 		sendPacket(nbns);
 	}
 	}
 	
 	
+	/**
+	 * Sends the required packets for host announcement with services.
+	 */
 	private void announceHost() {
 	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);
 		sendPacket(nbds);
 	}
 	}
 	
 	
+	/**
+	 * Sends the required packets for a name query.
+	 */
 	private void queryName() {
 	private void queryName() {
 		nbns.setType(NBNSType.NAME_QUERY);
 		nbns.setType(NBNSType.NAME_QUERY);
 		nbns.setService(NBNSService.LOCAL_MASTER_BROWSER);
 		nbns.setService(NBNSService.LOCAL_MASTER_BROWSER);
 		sendPacket(nbns);
 		sendPacket(nbns);
 	}
 	}
 	
 	
+	/**
+	 * Sends the required packets for a request announcement
+	 */
 	private void requestAnnouncement() {
 	private void requestAnnouncement() {
-		nbds = new NBDS(nbns.getAndIncTransactID(), nbns.getAddr(), username, workgroup, NBDSType.REQUEST_ANNOUNCEMENT);
+		nbds.setNbdstype(NBDSType.REQUEST_ANNOUNCEMENT);
 		sendPacket(nbds);
 		sendPacket(nbds);
 	}
 	}
 	
 	
+	/**
+	 * Sends the required packets for a local master announcement to all.
+	 */
 	private void localMasterAnnouncementAll() {
 	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);
 		sendPacket(nbds);
 	}
 	}
 	
 	
+	/**
+	 * Sends the required packets for a domain announcement.
+	 */
 	private void domainAnnouncement() {
 	private void domainAnnouncement() {
-		nbds = new NBDS(nbns.getAndIncTransactID(), nbns.getAddr(), username, workgroup, NBDSType.DOMAIN_ANNOUNCEMENT);
+		nbds.setNbdstype(NBDSType.DOMAIN_ANNOUNCEMENT);
 		sendPacket(nbds);
 		sendPacket(nbds);
 	}
 	}
 	
 	
+	/**
+	 * Sends the required packets for a local master announcement.
+	 */
 	private void localMasterAnnouncement() {
 	private void localMasterAnnouncement() {
-		nbds = new NBDS(nbns.getAndIncTransactID(), nbns.getAddr(), username, workgroup, NBDSType.LOCAL_MASTER_ANNOUNCEMENT);
+		nbds.setNbdstype(NBDSType.LOCAL_MASTER_ANNOUNCEMENT);
 		sendPacket(nbds);
 		sendPacket(nbds);
 	}
 	}
 
 
 	@Override
 	@Override
-	public void run() {		
+	public void run() {
+		NBSS nbss = new NBSS();
+		nbss.start();
 		try {
 		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();
 			e.printStackTrace();
 		}
 		}
 		
 		
 		registrate();
 		registrate();
-		receiver = new Receiver();
-		receiver.start();
 		announceHost();
 		announceHost();
 		queryName();
 		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();	
 		announceHost();	
 		
 		
+//		talk();
+		
 		nbnsSocket.close();
 		nbnsSocket.close();
 		nbdsSocket.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 {
 			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) {
 			} catch (IOException e) {
 				e.printStackTrace();
 				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;
 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 {
 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) {
 	public static String decodeNBNSName(byte[] name) {
 		byte a_ascii = (byte) 'A';
 		byte a_ascii = (byte) 'A';
 		byte[] reducedA = new byte[name.length];
 		byte[] reducedA = new byte[name.length];
 		for (int i = 0; i < name.length; i++) {
 		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];
 		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);
 			converted[j] = (byte) (b1 | b2);
 		}
 		}
 		return new String(converted);
 		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) {
 	public static byte[] encodeNBNSName(byte[] name) {
 		byte a_ascii = (byte) 'A';
 		byte a_ascii = (byte) 'A';
 		byte[] bytes = name;
 		byte[] bytes = name;
 		byte[] converted = new byte[bytes.length * 2];
 		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];
 		byte[] addedA = new byte[converted.length];
 		for (int i = 0; i < converted.length; i++) {
 		for (int i = 0; i < converted.length; i++) {
@@ -34,25 +47,32 @@ public class NMBStringCoder {
 		}
 		}
 		return addedA;
 		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) {
 	public static byte[] wrapNBNSName(byte[] name, int service) {
-		byte[] nameStart = {0x20};
+		byte[] nameStart = { 0x20 };
 		byte[] namePadding = null;
 		byte[] namePadding = null;
 		if (name.length < 32) {
 		if (name.length < 32) {
 			int paddingLen = 32 - name.length;
 			int paddingLen = 32 - name.length;
 			namePadding = new byte[paddingLen];
 			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] = serviceBytes[0];
-					namePadding[i+1] = serviceBytes[1];
+					namePadding[i + 1] = serviceBytes[1];
 				} else {
 				} else {
 					namePadding[i] = 0x43;
 					namePadding[i] = 0x43;
-					namePadding[i+1] = 0x041;
+					namePadding[i + 1] = 0x041;
 				}
 				}
 			}
 			}
 		}
 		}
-		byte[] nameEnd = {0x00};
+		byte[] nameEnd = { 0x00 };
 		return HelperUtils.concat(nameStart, name, namePadding, nameEnd);
 		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.GregorianCalendar;
 import java.util.TimeZone;
 import java.util.TimeZone;
 
 
-import javax.net.ssl.HostnameVerifier;
-
 import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
 import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
 
 
 /**
 /**
@@ -17,8 +15,7 @@ import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
 public class SMBPacket {
 public class SMBPacket {
 	
 	
 	private String[] serverVersion;
 	private String[] serverVersion;
-	private static byte[] serverName = HelperUtils.fillWithZero(HelperUtils
-			.getRandomString(16, true).getBytes());
+	private static byte[] serverName;
 	private byte[] message = null;
 	private byte[] message = null;
 	private static final byte[] serverGUID = HelperUtils.randomBytes(16);
 	private static final byte[] serverGUID = HelperUtils.randomBytes(16);
 	private boolean authenticateNext = false;
 	private boolean authenticateNext = false;
@@ -38,14 +35,16 @@ public class SMBPacket {
 	private byte[] multiplexID = new byte[2];
 	private byte[] multiplexID = new byte[2];
 	
 	
 	//special nbds stuff
 	//special nbds stuff
-	private byte[] workgroup;
+	private static byte[] workgroup;
 	private int type;
 	private int type;
 	
 	
-	public SMBPacket(String[] serverVersion) {
+	public SMBPacket(String[] serverVersion, String serverName, String workgroup) {
 		this.serverVersion = serverVersion;
 		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 };
 		serverComp = new byte[] { (byte) 0xff, 0x53, 0x4d, 0x42 };
 		smbCommand = new byte[] { 0x25 };
 		smbCommand = new byte[] { 0x25 };
 		ntStat = new byte[] { 0x00, 0x00, 0x00, 0x00 };
 		ntStat = new byte[] { 0x00, 0x00, 0x00, 0x00 };
@@ -59,9 +58,7 @@ public class SMBPacket {
 		processID = new byte[] { 0x00, 0x00 };
 		processID = new byte[] { 0x00, 0x00 };
 		userID = new byte[] { 0x00, 0x00 };
 		userID = new byte[] { 0x00, 0x00 };
 		multiplexID = new byte[] { 0x00, 0x00 };
 		multiplexID = new byte[] { 0x00, 0x00 };
-		this.workgroup = workgroup.getBytes();
 		this.type = type;
 		this.type = type;
-		SMBPacket.serverName = serverName.getBytes();
 	}
 	}
 	
 	
 	public void prepareNextResponse(byte[] message) {
 	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
 		if (transSub[0] == (byte) 0xff) { // for NMB in host announcement, NOT smb protocol
 			byte[] wordCount = { 0x11 };
 			byte[] wordCount = { 0x11 };
 			byte[] totalParamCount = { 0x00, 0x00 };
 			byte[] totalParamCount = { 0x00, 0x00 };
-			byte[] totalDataCount = new byte[2]; //TODO
+			byte[] totalDataCount = new byte[2];
 			byte[] maxParamCount = { 0x00, 0x00 };
 			byte[] maxParamCount = { 0x00, 0x00 };
 			byte[] maxDataCount = { 0x00, 0x00 };
 			byte[] maxDataCount = { 0x00, 0x00 };
 			byte[] maxSetupCount = { 0x00 };
 			byte[] maxSetupCount = { 0x00 };
@@ -459,7 +456,7 @@ public class SMBPacket {
 			byte[] reserved2 = { 0x00, 0x00 };
 			byte[] reserved2 = { 0x00, 0x00 };
 			byte[] paramCount = { 0x00, 0x00 };
 			byte[] paramCount = { 0x00, 0x00 };
 			byte[] paramOffset = { 0x00, 0x00 };
 			byte[] paramOffset = { 0x00, 0x00 };
-			byte[] dataCount = new byte[2]; //TODO
+			byte[] dataCount = new byte[2];
 			byte[] dataOffset = { 0x56, 0x00 };
 			byte[] dataOffset = { 0x56, 0x00 };
 			byte[] setupCount = { 0x03 };
 			byte[] setupCount = { 0x03 };
 			byte[] reserved3 = { 0x00 };
 			byte[] reserved3 = { 0x00 };
@@ -468,20 +465,19 @@ public class SMBPacket {
 			byte[] opcode = new byte[]{0x01, 0x00};
 			byte[] opcode = new byte[]{0x01, 0x00};
 			byte[] priority = new byte[]{0x01, 0x00};
 			byte[] priority = new byte[]{0x01, 0x00};
 			byte[] smbclass = new byte[]{0x02, 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[] name = HelperUtils.concat("\\MAILSLOT\\BROWSE".getBytes(), new byte[]{0x00}); 
 			
 			
 			byte[] windowsBrowser = null;
 			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();
 				windowsBrowser = getBrowser();
 			} else if (type == NBDSType.REQUEST_ANNOUNCEMENT) {
 			} else if (type == NBDSType.REQUEST_ANNOUNCEMENT) {
 				byte[] command = {0x02};
 				byte[] command = {0x02};
 				byte[] unusedFlags = {0x01, 0x00};
 				byte[] unusedFlags = {0x01, 0x00};
 				byte[] responseCompName = serverName;
 				byte[] responseCompName = serverName;
 				windowsBrowser = HelperUtils.concat(command, unusedFlags, responseCompName);
 				windowsBrowser = HelperUtils.concat(command, unusedFlags, responseCompName);
+			} else {
+				windowsBrowser = getAnnouncement();
 			}
 			}
 
 
 			byte[] buffer = ByteBuffer.allocate(4).putInt(windowsBrowser.length).array();
 			byte[] buffer = ByteBuffer.allocate(4).putInt(windowsBrowser.length).array();
@@ -629,10 +625,14 @@ public class SMBPacket {
 		return transSub;
 		return transSub;
 	}
 	}
 	
 	
+	/**
+	 * For NBNS only.
+	 * @return announcement packet.
+	 */
 	private byte[] getAnnouncement() {
 	private byte[] getAnnouncement() {
 		//Microsoft Windows Browser
 		//Microsoft Windows Browser
 		byte[] command = null;
 		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};
 			command = new byte[]{0x0f};
 		} else if (type == NBDSType.DOMAIN_ANNOUNCEMENT) {
 		} else if (type == NBDSType.DOMAIN_ANNOUNCEMENT) {
 			command = new byte[]{0x0c};
 			command = new byte[]{0x0c};
@@ -647,6 +647,8 @@ public class SMBPacket {
 			updatePeriodicity = new byte[]{0x00, 0x00, 0x00, 0x00};
 			updatePeriodicity = new byte[]{0x00, 0x00, 0x00, 0x00};
 		} else if (type == NBDSType.LOCAL_MASTER_ANNOUNCEMENT_ALL || type == NBDSType.DOMAIN_ANNOUNCEMENT) {
 		} else if (type == NBDSType.LOCAL_MASTER_ANNOUNCEMENT_ALL || type == NBDSType.DOMAIN_ANNOUNCEMENT) {
 			updatePeriodicity = new byte[]{(byte) 0xc0, (byte) 0xd4, 0x01, 0x00};
 			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;
 		byte[] hostName = null;
 		if (type == NBDSType.DOMAIN_ANNOUNCEMENT) {
 		if (type == NBDSType.DOMAIN_ANNOUNCEMENT) {
@@ -662,7 +664,7 @@ public class SMBPacket {
 		byte[] serverType = null;
 		byte[] serverType = null;
 		if (type == NBDSType.HOST_ANNOUNCEMENT_WITH_SERVICES || type == NBDSType.LOCAL_MASTER_ANNOUNCEMENT_ALL) {
 		if (type == NBDSType.HOST_ANNOUNCEMENT_WITH_SERVICES || type == NBDSType.LOCAL_MASTER_ANNOUNCEMENT_ALL) {
 			serverType = new byte[]{0x03, (byte) 0x9a, (byte) 0x81, 0x00};
 			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};
 			serverType = new byte[]{0x00, 0x00, 0x00, 0x00};
 		} else if (type == NBDSType.DOMAIN_ANNOUNCEMENT) {
 		} else if (type == NBDSType.DOMAIN_ANNOUNCEMENT) {
 			serverType = new byte[]{0x00, 0x10, 0x00, (byte) 0x80};
 			serverType = new byte[]{0x00, 0x10, 0x00, (byte) 0x80};
@@ -682,6 +684,10 @@ public class SMBPacket {
 				signature, hostComment);
 				signature, hostComment);
 	}
 	}
 	
 	
+	/**
+	 * For NBNS only.
+	 * @return MicrosoftBrowser part in NetBIOS packets.
+	 */
 	private byte[] getBrowser() {
 	private byte[] getBrowser() {
 		byte[] command = {0x08};
 		byte[] command = {0x08};
 		byte[] electionVersion = {0x01};
 		byte[] electionVersion = {0x01};