|
@@ -1,10 +1,10 @@
|
|
package de.tudarmstadt.informatik.hostage.protocol;
|
|
package de.tudarmstadt.informatik.hostage.protocol;
|
|
|
|
|
|
import java.nio.ByteBuffer;
|
|
import java.nio.ByteBuffer;
|
|
|
|
+import java.security.SecureRandom;
|
|
import java.util.ArrayList;
|
|
import java.util.ArrayList;
|
|
import java.util.Calendar;
|
|
import java.util.Calendar;
|
|
import java.util.List;
|
|
import java.util.List;
|
|
-import java.util.Random;
|
|
|
|
import java.util.TimeZone;
|
|
import java.util.TimeZone;
|
|
|
|
|
|
import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
|
|
import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
|
|
@@ -14,7 +14,7 @@ import de.tudarmstadt.informatik.hostage.wrapper.ByteArray;
|
|
* SMB protocol
|
|
* SMB protocol
|
|
* @author Wulf Pfeiffer
|
|
* @author Wulf Pfeiffer
|
|
*/
|
|
*/
|
|
-public final class SMB implements Protocol<ByteArray> {
|
|
|
|
|
|
+public class SMB implements Protocol<ByteArray> {
|
|
/**
|
|
/**
|
|
* Represents the states of the protocol
|
|
* Represents the states of the protocol
|
|
*/
|
|
*/
|
|
@@ -164,7 +164,7 @@ public final class SMB implements Protocol<ByteArray> {
|
|
*/
|
|
*/
|
|
private byte[] randomBytes(int size) {
|
|
private byte[] randomBytes(int size) {
|
|
byte[] bytes = new byte[size];
|
|
byte[] bytes = new byte[size];
|
|
- Random rdm = new Random();
|
|
|
|
|
|
+ SecureRandom rdm = new SecureRandom();
|
|
rdm.nextBytes(bytes);
|
|
rdm.nextBytes(bytes);
|
|
return bytes;
|
|
return bytes;
|
|
}
|
|
}
|
|
@@ -173,9 +173,18 @@ public final class SMB implements Protocol<ByteArray> {
|
|
* Denotes a SMB packet
|
|
* Denotes a SMB packet
|
|
*/
|
|
*/
|
|
private class SMBPacket {
|
|
private class SMBPacket {
|
|
- private byte[] message = null;
|
|
|
|
- private final byte[] serverGUID = randomBytes(16);
|
|
|
|
- private boolean authenticateNext = false;
|
|
|
|
|
|
+ private SecureRandom rndm = new SecureRandom();
|
|
|
|
+ private String[][] possibleVersions = { {"Windows Server 2008 R2 Enterprise 7600","Windows Server 2008 R2 Enterprise 6.1"},
|
|
|
|
+ {"Windows 7 Professional 7600","Windows 7 Professional 6.1"},
|
|
|
|
+ {"Windows 8 Enterprise 9200", "Windows 8 Enterprise 9200"},
|
|
|
|
+ {"Windows Server 2012 Standard 6.2", "Windows Server 2012 Standard 6.2"},
|
|
|
|
+// {"Unix", "Samba"}
|
|
|
|
+ };
|
|
|
|
+ private byte[] serverName = fillWithZero("lalalalalala".getBytes());
|
|
|
|
+ private final String[] serverVersion = possibleVersions[rndm.nextInt(possibleVersions.length)];
|
|
|
|
+ private byte[] message = null;
|
|
|
|
+ private final byte[] serverGUID = randomBytes(16);
|
|
|
|
+ private boolean authenticateNext = false;
|
|
//components of a SMB packet
|
|
//components of a SMB packet
|
|
private byte[] serverComp = new byte[4];
|
|
private byte[] serverComp = new byte[4];
|
|
private byte[] smbCommand = new byte[1];
|
|
private byte[] smbCommand = new byte[1];
|
|
@@ -307,47 +316,68 @@ public final class SMB implements Protocol<ByteArray> {
|
|
* @return session setup challange packet
|
|
* @return session setup challange packet
|
|
*/
|
|
*/
|
|
private byte[] getSetupChal() {
|
|
private byte[] getSetupChal() {
|
|
- byte[] wordCount = {0x04};
|
|
|
|
- byte[] andXCommand = {(byte) 0xff};
|
|
|
|
- byte[] reserved = {0x00};
|
|
|
|
- byte[] andXOffset = {0x60, 0x01};
|
|
|
|
- byte[] action = {0x00, 0x00};
|
|
|
|
- byte[] secBlobLength = {(byte) 0xc7, 0x00};
|
|
|
|
- byte[] byteCount = {0x35, 0x01};
|
|
|
|
- byte[] secBlob = {(byte) 0xa1, (byte) 0x81, (byte) 0xc4};
|
|
|
|
- byte[] negToken = {0x30, (byte) 0x81, (byte) 0xc1, (byte) 0xa0, 0x03, 0x0a, 0x01};
|
|
|
|
- byte[] negResult = {0x01};
|
|
|
|
- byte[] negToken2 = {(byte) 0xa1, 0x0c, 0x06, 0x0a};
|
|
|
|
- byte[] supportedMech = {0x2b, 0x06, 0x01, 0x04, 0x01, (byte) 0x82, 0x37, 0x02, 0x02, 0x0a};
|
|
|
|
- byte[] negToken3 = {(byte) 0xa2, (byte) 0x81, (byte) 0xab, 0x04, (byte) 0x81, (byte) 0xa8};
|
|
|
|
- byte[] respToken = {0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00,
|
|
|
|
- 0x38, 0x00, 0x00, 0x00, 0x15, (byte) 0x82, (byte) 0x8a, 0x62};
|
|
|
|
- byte[] challenge = randomBytes(8);
|
|
|
|
- byte[] respToken2 = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x48, 0x00, 0x00, 0x00,
|
|
|
|
- 0x06, 0x01, (byte) 0xb0, 0x1d, 0x00, 0x00, 0x00, 0x0f, 0x42, 0x00, 0x55, 0x00, 0x53, 0x00, 0x49, 0x00,
|
|
|
|
- 0x4e, 0x00, 0x45, 0x00, 0x53, 0x00, 0x53, 0x00, 0x02, 0x00, 0x10, 0x00, 0x42, 0x00, 0x55, 0x00,
|
|
|
|
- 0x53, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x45, 0x00, 0x53, 0x00, 0x53, 0x00, 0x01, 0x00, 0x10, 0x00,
|
|
|
|
- 0x42, 0x00, 0x55, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x45, 0x00, 0x53, 0x00, 0x53, 0x00,
|
|
|
|
- 0x04, 0x00, 0x10, 0x00, 0x42, 0x00, 0x55, 0x00, 0x53, 0x00, 0x49, 0x00, 0x4e, 0x00, 0x45, 0x00,
|
|
|
|
- 0x53, 0x00, 0x53, 0x00, 0x03, 0x00, 0x10, 0x00, 0x42, 0x00, 0x55, 0x00, 0x53, 0x00, 0x49, 0x00,
|
|
|
|
- 0x4e, 0x00, 0x45, 0x00, 0x53, 0x00, 0x53, 0x00, 0x07, 0x00, 0x08, 0x00};
|
|
|
|
- byte[] timeStamp = getTimeInBytes();
|
|
|
|
- byte[] respToken3 = {0x00, 0x00, 0x00, 0x00};
|
|
|
|
- byte[] nativOS = {0x57, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x64, 0x00,
|
|
|
|
- 0x6f, 0x00, 0x77, 0x00, 0x73, 0x00, 0x20, 0x00, 0x37, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00,
|
|
|
|
- 0x6f, 0x00, 0x66, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00,
|
|
|
|
- 0x61, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x37, 0x00, 0x36, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00}; //Windows 7 Professional 7600
|
|
|
|
- byte[] nativLanMngr = {0x57, 0x00, 0x69, 0x00, 0x6e, 0x00,
|
|
|
|
- 0x64, 0x00, 0x6f, 0x00, 0x77, 0x00, 0x73, 0x00, 0x20, 0x00, 0x37, 0x00, 0x20, 0x00, 0x50, 0x00,
|
|
|
|
- 0x72, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00,
|
|
|
|
- 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x36, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x00, 0x00}; //Windows 7 Professional 6.1
|
|
|
|
|
|
+ byte[] wordCount = {0x04};
|
|
|
|
+ byte[] andXCommand = {(byte) 0xff};
|
|
|
|
+ byte[] reserved = {0x00};
|
|
|
|
+ byte[] andXOffset = {0x60, 0x01};
|
|
|
|
+ byte[] action = {0x00, 0x00};
|
|
|
|
+ byte[] secBlobLength;
|
|
|
|
+ byte[] byteCount;
|
|
|
|
+ byte[] secBlob = {(byte) 0xa1, (byte) 0x81, (byte) 0xc4};
|
|
|
|
+ byte[] negToken = {0x30, (byte) 0x81, (byte) 0xc1, (byte) 0xa0, 0x03, 0x0a, 0x01};
|
|
|
|
+ byte[] negResult = {0x01};
|
|
|
|
+ byte[] negToken2 = {(byte) 0xa1, 0x0c, 0x06, 0x0a};
|
|
|
|
+ byte[] supportedMech = {0x2b, 0x06, 0x01, 0x04, 0x01, (byte) 0x82, 0x37, 0x02, 0x02, 0x0a};
|
|
|
|
+ byte[] negToken3 = {(byte) 0xa2, (byte) 0x81, (byte) 0xab, 0x04, (byte) 0x81, (byte) 0xa8};
|
|
|
|
+ byte[] ntlmsspId = {0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00};
|
|
|
|
+ byte[] nlmMsgType = {0x02, 0x00, 0x00, 0x00};
|
|
|
|
+ byte[] buffer = ByteBuffer.allocate(4).putInt(serverName.length).array();
|
|
|
|
+ byte[] targetNameLength = new byte[]{buffer[3], buffer[2]};
|
|
|
|
+ byte[] targetNameMaxLength = new byte[]{buffer[3], buffer[2]};
|
|
|
|
+ byte[] targetNameOffset = {0x38, 0x00, 0x00, 0x00};
|
|
|
|
+ byte[] flags = {0x15, (byte) 0x82, (byte) 0x8a, 0x62};
|
|
|
|
+ byte[] challenge = randomBytes(8);
|
|
|
|
+ byte[] reserved2 = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
+ byte[] targetInfoLength = {0x60, 0x00};
|
|
|
|
+ byte[] targetInfoMaxLength = {0x60, 0x00};
|
|
|
|
+ byte[] targetInfoOffset = {0x48, 0x00, 0x00, 0x00};
|
|
|
|
+ byte[] version = null;
|
|
|
|
+ if(serverVersion[0].contains("Windows 7") || serverVersion[0].contains("Windows Server 2008")) {
|
|
|
|
+ version = new byte[]{0x06, 0x01, (byte) 0xb0, 0x1d, 0x00, 0x00, 0x00, 0x0f};
|
|
|
|
+ } else if(serverVersion[0].contains("Windows 8") || serverVersion[0].contains("Windows Server 2012")) {
|
|
|
|
+ version = new byte[]{0x06, 0x02, (byte) 0xf0, 0x23, 0x00, 0x00, 0x00, 0x0f};
|
|
|
|
+ }
|
|
|
|
+ // serverName
|
|
|
|
+ byte[] attributeNBDomain = {0x02, 0x00, 0x10, 0x00};
|
|
|
|
+ // serverName
|
|
|
|
+ byte[] attributeNBcomputer = {0x01, 0x00, 0x10, 0x00};
|
|
|
|
+ // serverName
|
|
|
|
+ byte[] attributeDNSDomain = {0x04, 0x00, 0x10, 0x00};
|
|
|
|
+ // serverName
|
|
|
|
+ byte[] attributeDNScomputer = {0x03, 0x00, 0x10, 0x00};
|
|
|
|
+ // serverName
|
|
|
|
+ byte[] attributeTimeStamp = {0x07, 0x00, 0x08, 0x00};
|
|
|
|
+ byte[] timeStamp = getTimeInBytes();;
|
|
|
|
+ byte[] attributeEnd = {0x00, 0x00, 0x00, 0x00};
|
|
|
|
+ secBlob = HelperUtils.concat(secBlob, negToken, negResult, negToken2, supportedMech, negToken3,
|
|
|
|
+ ntlmsspId, nlmMsgType, targetNameLength, targetNameMaxLength, targetNameOffset,
|
|
|
|
+ flags, challenge, reserved2, targetInfoLength, targetInfoMaxLength, targetInfoOffset,
|
|
|
|
+ version, serverName, attributeNBDomain, serverName, attributeNBcomputer, serverName,
|
|
|
|
+ attributeDNSDomain, serverName, attributeDNScomputer, serverName, attributeTimeStamp,
|
|
|
|
+ timeStamp, attributeEnd);
|
|
|
|
+ byte[] nativOS = fillWithZeroExtended(serverVersion[0].getBytes());
|
|
|
|
+ byte[] nativLanMngr = fillWithZeroExtended(serverVersion[1].getBytes());
|
|
|
|
+
|
|
|
|
+ buffer = ByteBuffer.allocate(4).putInt(secBlob.length).array();
|
|
|
|
+ secBlobLength = new byte[]{buffer[3], buffer[2]};
|
|
|
|
+ buffer = ByteBuffer.allocate(4).putInt(secBlob.length + nativOS.length + nativLanMngr.length).array();
|
|
|
|
+ byteCount = new byte[]{buffer[3], buffer[2]};
|
|
|
|
|
|
ntStat = new byte[]{0x16, 0x00, 0x00, (byte) 0xc0};
|
|
ntStat = new byte[]{0x16, 0x00, 0x00, (byte) 0xc0};
|
|
userID = new byte[]{0x00, 0x08};
|
|
userID = new byte[]{0x00, 0x08};
|
|
|
|
|
|
byte[] response = HelperUtils.concat(wordCount, andXCommand, reserved, andXOffset, action, secBlobLength,
|
|
byte[] response = HelperUtils.concat(wordCount, andXCommand, reserved, andXOffset, action, secBlobLength,
|
|
- byteCount, secBlob, negToken, negResult, negToken2, supportedMech, negToken3,
|
|
|
|
- respToken, challenge, respToken2, timeStamp, respToken3, nativOS, nativLanMngr);
|
|
|
|
|
|
+ byteCount, secBlob, nativOS, nativLanMngr);
|
|
return wrapNetbios(wrapHeader(response));
|
|
return wrapNetbios(wrapHeader(response));
|
|
}
|
|
}
|
|
|
|
|
|
@@ -361,18 +391,16 @@ public final class SMB implements Protocol<ByteArray> {
|
|
byte[] reserved = {0x00};
|
|
byte[] reserved = {0x00};
|
|
byte[] andXOffset = {(byte) 0xa2, 0x00};
|
|
byte[] andXOffset = {(byte) 0xa2, 0x00};
|
|
byte[] action = {0x01, 0x00};
|
|
byte[] action = {0x01, 0x00};
|
|
- byte[] secBlobLength = {0x09, 0x00};
|
|
|
|
- byte[] byteCount = {(byte) 0x77, 0x00};
|
|
|
|
|
|
+ byte[] secBlobLength;
|
|
|
|
+ byte[] byteCount;
|
|
byte[] secBlob = {(byte) 0xa1, 0x07, 0x30, 0x05, (byte) 0xa0, 0x03, 0x0a, 0x01, 0x00};
|
|
byte[] secBlob = {(byte) 0xa1, 0x07, 0x30, 0x05, (byte) 0xa0, 0x03, 0x0a, 0x01, 0x00};
|
|
- byte[] nativOS = {0x57, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x64, 0x00,
|
|
|
|
- 0x6f, 0x00, 0x77, 0x00, 0x73, 0x00, 0x20, 0x00, 0x37, 0x00, 0x20, 0x00, 0x50, 0x00, 0x72, 0x00,
|
|
|
|
- 0x6f, 0x00, 0x66, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00, 0x6e, 0x00,
|
|
|
|
- 0x61, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x37, 0x00, 0x36, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00}; //Windows 7 Professional 7600
|
|
|
|
- byte[] nativLanMngr = {0x57, 0x00, 0x69, 0x00, 0x6e, 0x00,
|
|
|
|
- 0x64, 0x00, 0x6f, 0x00, 0x77, 0x00, 0x73, 0x00, 0x20, 0x00, 0x37, 0x00, 0x20, 0x00, 0x50, 0x00,
|
|
|
|
- 0x72, 0x00, 0x6f, 0x00, 0x66, 0x00, 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6f, 0x00,
|
|
|
|
- 0x6e, 0x00, 0x61, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x36, 0x00, 0x2e, 0x00, 0x31, 0x00, 0x00, 0x00}; //Windows 7 Professional 6.1
|
|
|
|
-
|
|
|
|
|
|
+ byte[] nativOS = fillWithZeroExtended(serverVersion[0].getBytes());
|
|
|
|
+ byte[] nativLanMngr = fillWithZeroExtended(serverVersion[1].getBytes());
|
|
|
|
+
|
|
|
|
+ byte[] buffer = ByteBuffer.allocate(4).putInt(secBlob.length).array();
|
|
|
|
+ secBlobLength = new byte[]{buffer[3], buffer[2]};
|
|
|
|
+ buffer = ByteBuffer.allocate(4).putInt(secBlob.length + nativOS.length + nativLanMngr.length).array();
|
|
|
|
+ byteCount = new byte[]{buffer[3], buffer[2]};
|
|
|
|
|
|
byte[] response = HelperUtils.concat(wordCount, andXCommand, reserved, andXOffset, action, secBlobLength,
|
|
byte[] response = HelperUtils.concat(wordCount, andXCommand, reserved, andXOffset, action, secBlobLength,
|
|
byteCount, secBlob, nativOS, nativLanMngr);
|
|
byteCount, secBlob, nativOS, nativLanMngr);
|
|
@@ -602,7 +630,6 @@ public final class SMB implements Protocol<ByteArray> {
|
|
return transSub;
|
|
return transSub;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
public String toString() {
|
|
public String toString() {
|
|
return HelperUtils.byteToStr(message);
|
|
return HelperUtils.byteToStr(message);
|
|
}
|
|
}
|
|
@@ -614,5 +641,31 @@ public final class SMB implements Protocol<ByteArray> {
|
|
public byte getSmbCommand() {
|
|
public byte getSmbCommand() {
|
|
return smbCommand[0];
|
|
return smbCommand[0];
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Puts a 0x00 byte between each byte and another 2 0x00 bytes at the end of a byte array.
|
|
|
|
+ * @param bytes that need to be filled with 0x00.
|
|
|
|
+ * @return filled byte array.
|
|
|
|
+ */
|
|
|
|
+ private byte[] fillWithZeroExtended(byte[] bytes) {
|
|
|
|
+ byte[] zeroBytes = fillWithZero(bytes);
|
|
|
|
+ byte[] newBytes = new byte[zeroBytes.length+2];
|
|
|
|
+ newBytes = HelperUtils.concat(zeroBytes, new byte[]{0x00, 0x00});
|
|
|
|
+ return newBytes;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * Puts a 0x00 byte between each byte in a byte array.
|
|
|
|
+ * @param bytes that need to be filled with 0x00.
|
|
|
|
+ * @return filled byte array.
|
|
|
|
+ */
|
|
|
|
+ private byte[] fillWithZero(byte[] bytes) {
|
|
|
|
+ byte[] newBytes = new byte[(bytes.length * 2)];
|
|
|
|
+ for(int i = 0, j = 0; i < bytes.length && j < newBytes.length; i++, j=j+2) {
|
|
|
|
+ newBytes[j] = bytes[i];
|
|
|
|
+ newBytes[j+1] = 0x00;
|
|
|
|
+ }
|
|
|
|
+ return newBytes;
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|