Browse Source

SSH: add proper Signature, en-/decryption working, missing: terminal
functionality
Added a library for ssh
Added Custom Port Echo
Minor changes

Wulf Pfeiffer 10 years ago
parent
commit
d739db5d46

+ 1 - 0
.classpath

@@ -5,5 +5,6 @@
 	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
 	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
 	<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
+	<classpathentry kind="lib" path="libs/sshlib-v0.1.jar"/>
 	<classpathentry kind="output" path="bin/classes"/>
 </classpath>

BIN
libs/sshlib-v0.1.jar


+ 47 - 0
src/de/tudarmstadt/informatik/hostage/protocol/Custom.java

@@ -0,0 +1,47 @@
+package de.tudarmstadt.informatik.hostage.protocol;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.tudarmstadt.informatik.hostage.wrapper.Packet;
+
+public class Custom implements Protocol {
+
+	@Override
+	public int getPort() {
+		return ProtocolSettings.getCustomPort();
+	}
+
+	@Override
+	public TALK_FIRST whoTalksFirst() {
+		return TALK_FIRST.CLIENT;
+	}
+	
+	@Override
+	public List<Packet> processMessage(Packet packet) {
+		List<Packet> response = new ArrayList<Packet>();
+		response.add(packet);
+		return response;
+	}
+
+	@Override
+	public boolean isClosed() {
+		return true;
+	}
+
+	@Override
+	public boolean isSecure() {
+		return false;
+	}
+
+	@Override
+	public Class<byte[]> getType() {
+		return byte[].class;
+	}
+	
+	@Override
+	public String toString() {
+		return "Custom";
+	}
+
+}

+ 7 - 7
src/de/tudarmstadt/informatik/hostage/protocol/ECHO.java

@@ -11,39 +11,39 @@ import de.tudarmstadt.informatik.hostage.wrapper.Packet;
  */
 public class ECHO implements Protocol{
 
-	
+	@Override
 	public int getPort() {
 		return 7;
 	}
 
-	
+	@Override
 	public TALK_FIRST whoTalksFirst() {
 		return TALK_FIRST.CLIENT;
 	}
 	
-	
+	@Override
 	public List<Packet> processMessage(Packet packet) {
 		List<Packet> response = new ArrayList<Packet>();
 		response.add(packet);
 		return response;
 	}
 
-	
+	@Override
 	public boolean isClosed() {
 		return true;
 	}
 
-	
+	@Override
 	public boolean isSecure() {
 		return false;
 	}
 
-	
+	@Override
 	public Class<byte[]> getType() {
 		return byte[].class;
 	}
 	
-	
+	@Override
 	public String toString() {
 		return "ECHO";
 	}

+ 8 - 6
src/de/tudarmstadt/informatik/hostage/protocol/FTP.java

@@ -10,6 +10,7 @@ import de.tudarmstadt.informatik.hostage.wrapper.Packet;
  * @author Wulf Pfeiffer
  */
 public class FTP implements Protocol {
+	
 	/**
 	 * Represents the states of the protocol
 	 */
@@ -22,17 +23,17 @@ public class FTP implements Protocol {
 	 */
 	private STATE state = STATE.NONE;
 	
-	
+	@Override
 	public int getPort() {
 		return 21;
 	}
 
-	
+	@Override
 	public TALK_FIRST whoTalksFirst() {
 		return TALK_FIRST.SERVER;
 	}
 
-	
+	@Override
 	public List<Packet> processMessage(Packet packet) {
 		String request = null;
 		if (packet != null) {
@@ -99,21 +100,22 @@ public class FTP implements Protocol {
 	private String c500 = "500 Syntax error, command unrecognized.";
 	private String c501 = "501 Syntax error in parameters or arguments";
 	
+	@Override
 	public boolean isClosed() {
 		return state == STATE.CLOSED;
 	}
 
-	
+	@Override
 	public boolean isSecure() {
 		return false;
 	}
 
-	
+	@Override
 	public Class<String> getType() {
 		return String.class;
 	}
 
-	
+	@Override
 	public String toString() {
 		return "FTP";
 	}

+ 7 - 7
src/de/tudarmstadt/informatik/hostage/protocol/HTTP.java

@@ -16,17 +16,17 @@ import de.tudarmstadt.informatik.hostage.wrapper.Packet;
  */
 public class HTTP implements Protocol {
 	
-	
+	@Override
 	public int getPort() {
 		return 80;
 	}
 
-	
+	@Override
 	public TALK_FIRST whoTalksFirst() {
 		return TALK_FIRST.CLIENT;
 	}
 	
-	
+	@Override
 	public List<Packet> processMessage(Packet packet) {
 		String request = null;
 		if (packet != null) {
@@ -59,22 +59,22 @@ public class HTTP implements Protocol {
 		return response;
 	}
 
-	
+	@Override
 	public boolean isClosed() {
 		return true;
 	}
 
-	
+	@Override
 	public boolean isSecure() {
 		return false;
 	}
 
-	
+	@Override
 	public Class<String> getType() {
 		return String.class;
 	}
 
-	
+	@Override
 	public String toString() {
 		return "HTTP";
 	}

+ 1 - 0
src/de/tudarmstadt/informatik/hostage/protocol/HTTPS.java

@@ -28,6 +28,7 @@ public class HTTPS extends HTTP implements SSLProtocol {
 		return "HTTPS";
 	}
 	
+	@Override
 	public SSLContext getSSLContext() {
 		String ksName = "https_cert.bks";
 		char ksPass[] = "password".toCharArray();

+ 42 - 0
src/de/tudarmstadt/informatik/hostage/protocol/Mirror.java

@@ -0,0 +1,42 @@
+package de.tudarmstadt.informatik.hostage.protocol;
+
+import java.util.List;
+
+import de.tudarmstadt.informatik.hostage.wrapper.Packet;
+
+public class Mirror implements Protocol {
+
+	@Override
+	public int getPort() {
+		// TODO Auto-generated method stub
+		return 0;
+	}
+
+	@Override
+	public TALK_FIRST whoTalksFirst() {
+		return TALK_FIRST.CLIENT;
+	}
+
+	@Override
+	public List<Packet> processMessage(Packet packet) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public boolean isClosed() {
+		// TODO Auto-generated method stub
+		return false;
+	}
+
+	@Override
+	public boolean isSecure() {
+		return false;
+	}
+
+	@Override
+	public Class<? extends Object> getType() {
+		return byte[].class;
+	}
+
+}

+ 7 - 5
src/de/tudarmstadt/informatik/hostage/protocol/MySQL.java

@@ -27,7 +27,7 @@ public class MySQL implements Protocol {
 	/** last request from client */ 
 	private byte[] lastMessage;
 	
-	
+	@Override
 	public List<Packet> processMessage(Packet packet) {
 		byte[] request = null;
 		if (packet != null) {
@@ -61,30 +61,32 @@ public class MySQL implements Protocol {
 		return response;
 	}
 	
-	
+	@Override
 	public TALK_FIRST whoTalksFirst() {
 		return TALK_FIRST.SERVER;
 	}
 
-	
+	@Override
 	public String toString(){
 		return "MySQL";		
 	}
 	
-	
+	@Override
 	public int getPort() {
 		return 3306;
 	}
 	
-	
+	@Override
 	public boolean isClosed() {
 		return state == STATE.CLOSED;
 	}
 	
+	@Override
 	public boolean isSecure() {
 		return false;
 	}
 
+	@Override
 	public Class<byte[]> getType() {
 		return byte[].class;
 	}

+ 1 - 2
src/de/tudarmstadt/informatik/hostage/protocol/Protocol.java

@@ -6,7 +6,6 @@ import de.tudarmstadt.informatik.hostage.wrapper.Packet;
 
 /**
  * Interface for protocols that are used by the application.
- * @param <T> Denotes if the protocol is using Strings or ByteArrays.
  * @author Mihai Plasoianu
  * @author Wulf Pfeiffer
  */
@@ -33,7 +32,7 @@ public interface Protocol {
 
 	/**
 	 * Determines the next message that is sent by the server.
-	 * @param message last message that was sent by the client.
+	 * @param packet last message that was sent by the client.
 	 * @return next message that will be sent.
 	 */
 	List<Packet> processMessage(Packet packet);

+ 14 - 0
src/de/tudarmstadt/informatik/hostage/protocol/ProtocolSettings.java

@@ -35,6 +35,8 @@ public class ProtocolSettings {
 		{{"5."},{"0","1","2","3","4","5","6","7","8","9"}},
 		{{"6."},{"0","1","2","3","4"}}
 	};
+	//Custom Echo
+	private static int customPort		= initCustomPort();
 	//HTTP
 	private static String httpQotd		; //is initialized by honeyservice
 	private static String httpVersion	= initHttpVersion();
@@ -60,6 +62,10 @@ public class ProtocolSettings {
 		smbVersion = possibleSmbVersions[4];
 	}
 	
+	private static int initCustomPort() {
+		return 1433; //MsSQL Port
+	}
+	
 	private static String initHttpVersion() {
 		int majorVersion = rndm.nextInt(possibleHttpVersions.length);
 		return possibleHttpVersions[majorVersion][0][0] + possibleHttpVersions[majorVersion][1][rndm.nextInt(possibleHttpVersions[majorVersion][1].length)];
@@ -93,6 +99,14 @@ public class ProtocolSettings {
 
 	//~~~ Getters and Setters ~~//
 	
+	public static int getCustomPort() {
+		return customPort;
+	}
+
+	public static void setCustomPort(int customPort) {
+ 		ProtocolSettings.customPort = customPort;
+	}
+	
 	public static String getHttpQotd() {
 		return httpQotd;
 	}

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

@@ -6,28 +6,34 @@ import de.tudarmstadt.informatik.hostage.wrapper.Packet;
 
 public class SIP implements Protocol {
 
+	@Override
 	public int getPort() {
 		return 5060;
 	}
 
+	@Override
 	public TALK_FIRST whoTalksFirst() {
 		return TALK_FIRST.CLIENT;
 	}
 
+	@Override
 	public List<Packet> processMessage(Packet packet) {
 		// TODO Auto-generated method stub
 		return null;
 	}
 
+	@Override
 	public boolean isClosed() {
 		// TODO Auto-generated method stub
 		return true;
 	}
 
+	@Override
 	public boolean isSecure() {
 		return false;
 	}
 
+	@Override
 	public Class<byte[]> getType() {
 		return byte[].class;
 	}

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

@@ -29,19 +29,19 @@ public class SMB implements Protocol {
 
 	private byte[] lastMessage;
 	
-	
+	@Override
 	public int getPort() {
 		return 445;
 	}
 
-	
+	@Override
 	public TALK_FIRST whoTalksFirst() {
 		return TALK_FIRST.CLIENT;
 	}
 	
 	private SMBPacket smbPacket = new SMBPacket();
 
-	
+	@Override
 	public List<Packet> processMessage(Packet packet) {
 		if(packet != null)
 			lastMessage = packet.getMessage();
@@ -115,22 +115,22 @@ public class SMB implements Protocol {
 		return response;
 	}
 
-	
+	@Override
 	public boolean isClosed() {
 		return (state == STATE.CLOSED);
 	}
 
-	
+	@Override
 	public boolean isSecure() {
 		return false;
 	}
 
-	
+	@Override
 	public Class<byte[]> getType() {
 		return byte[].class;
 	}
 
-	
+	@Override
 	public String toString() {
 		return "SMB";
 	}

+ 227 - 223
src/de/tudarmstadt/informatik/hostage/protocol/SSH.java

@@ -2,23 +2,21 @@ package de.tudarmstadt.informatik.hostage.protocol;
 
 import java.math.BigInteger;
 import java.nio.ByteBuffer;
-import java.security.KeyFactory;
-import java.security.KeyPair;
-import java.security.KeyPairGenerator;
-import java.security.MessageDigest;
-import java.security.PublicKey;
 import java.security.SecureRandom;
-import java.security.Signature;
-import java.security.interfaces.DSAPublicKey;
 import java.util.ArrayList;
 import java.util.List;
 
-import javax.crypto.KeyAgreement;
-import javax.crypto.interfaces.DHPublicKey;
-import javax.crypto.spec.DHParameterSpec;
-import javax.crypto.spec.DHPublicKeySpec;
-
 import de.tudarmstadt.informatik.hostage.commons.HelperUtils;
+import de.tudarmstadt.informatik.hostage.ssh.crypto.KeyMaterial;
+import de.tudarmstadt.informatik.hostage.ssh.crypto.PEMDecoder;
+import de.tudarmstadt.informatik.hostage.ssh.crypto.cipher.CBCMode;
+import de.tudarmstadt.informatik.hostage.ssh.crypto.cipher.DESede;
+import de.tudarmstadt.informatik.hostage.ssh.crypto.dh.DhExchange;
+import de.tudarmstadt.informatik.hostage.ssh.crypto.digest.MAC;
+import de.tudarmstadt.informatik.hostage.ssh.signature.DSAPrivateKey;
+import de.tudarmstadt.informatik.hostage.ssh.signature.DSASHA1Verify;
+import de.tudarmstadt.informatik.hostage.ssh.signature.DSASignature;
+import de.tudarmstadt.informatik.hostage.ssh.util.TypesWriter;
 import de.tudarmstadt.informatik.hostage.wrapper.Packet;
 
 /**
@@ -34,82 +32,100 @@ public class SSH implements Protocol {
 		SERVER_VERSION,
 		CLIENT_VERSION,
 		KEX_INIT,
+		USERAUTH,
+		CONNECTION,
+		CHANNEL,
+		LOOP, // TODO for debugging
 		CLOSED
 	}
 	
 	/**
 	 * Denotes in which state the protocol is right now.
 	 */
-	private STATE connectionState = STATE.NONE;
-	
-	/** Denotes in which state the protocol is right now */
 	private STATE state = STATE.NONE;
-	
-	
+		
+	@Override
 	public int getPort() {
 		return 22;
 	}
 
-	
+	@Override
 	public TALK_FIRST whoTalksFirst() {
 		return TALK_FIRST.SERVER;
 	}
 
-	
+	@Override
 	public List<Packet> processMessage(Packet packet) {
 		List<Packet> response = new ArrayList<Packet>();
 		byte[] request = null;
 		if(packet != null) {
 			request = packet.getMessage();
 		}
-		
-		switch(connectionState) {
+		switch(state) {
 		case NONE:			
 			response.add(new Packet(serverVersion + serverType + "\r\n"));
-			connectionState = STATE.SERVER_VERSION;
+			state = STATE.SERVER_VERSION;
 			break;
 		case SERVER_VERSION:
 			extractType(request);
-			extractCookie(request);
+			extractPayload(request);
 			response.add(kexInit());
-			connectionState = STATE.CLIENT_VERSION;
+			state = STATE.CLIENT_VERSION;
 			break;
 		case CLIENT_VERSION:
 			extractPubKey(request);
 			response.add(dhKexReply());
-			//FIXME signature in dhKexReply seems to be wrong
 			response.add(newKeys());
-			connectionState = STATE.KEX_INIT;
+			state = STATE.KEX_INIT;
 			break;
 		case KEX_INIT:
-			connectionState = STATE.CLOSED;
+			response.add(serviceReply(request));
+			state = STATE.USERAUTH;
+			break;
+		case USERAUTH:
+			response.add(userauthReply(request));
+			state = STATE.CONNECTION;
+			break;
+		case CONNECTION:
+			response.add(channelOpenReply(request));
+			state = STATE.CHANNEL;
+			break;
+		case CHANNEL:
+			response.add(channelSuccessReply(request));
+			response.add(data(request));
+			state = STATE.LOOP;
+			break;
+		case LOOP:
+			decryptPacket(request);
+			response.add(data(request));
+			state = STATE.LOOP;
 			break;
 		case CLOSED:
 			break;
 		default:
-			connectionState = STATE.CLOSED;
+			state = STATE.CLOSED;
 			break;
 		}
 		
 		return response;
 	}
 
-	
+	@Override
 	public boolean isClosed() {
 		return (state == STATE.CLOSED);
 	}
 
-	
+	@Override
 	public boolean isSecure() {
 		return false;
 	}
 
-	
+	@Override
 	public Class<byte[]> getType() {
 		return byte[].class;
 	}
 
-	
+	@Override
 	public String toString() {
 		return "SSH";
 	}
@@ -119,7 +135,7 @@ public class SSH implements Protocol {
 	 * @param packet content that is wrapped.
 	 * @return wrapped packet.
 	 */
-	private Packet wrapPacket(byte[] packet) {
+	private Packet wrapPacket(byte[] packet, boolean encrypt) {
 		int packetLength = 5 + packet.length; 	//4 byte packet length, 1 byte padding length, payload length
 		int paddingLengthCBS = cipherBlockSize - (packetLength % cipherBlockSize);
 		int paddingLength8 = 8 - (packetLength % 8);
@@ -134,7 +150,37 @@ public class SSH implements Protocol {
 			SecureRandom rndm = new SecureRandom();
 			paddingString[i] = (byte) rndm.nextInt(255);
 		}
-		return new Packet(HelperUtils.concat(packetLen, paddingLen, packet, paddingString));
+		byte[] response = HelperUtils.concat(packetLen, paddingLen, packet, paddingString);
+		if(encrypt) {
+			byte[] mac = new byte[20];
+			macEnc.initMac(send_packet_number);
+			macEnc.update(response, 0, response.length);
+			macEnc.getMac(mac, 0);		
+			
+			byte[] responseEnc = new byte[response.length];
+			for(int i = 0; i < response.length; i+=8) { 
+				cbcEnc.transformBlock(response, i, responseEnc, i);
+			}
+			response = HelperUtils.concat(responseEnc,mac);
+		}
+		send_packet_number++;
+		
+		return new Packet(response);
+	}
+	
+	private byte[] decryptPacket(byte[] request) {
+		byte[] message = new byte[request.length - ((request.length % 8 == 0) ? 0 : 20)];
+		for(int i = 0; i < message.length; i += 8) { // -12 wegen MAC
+			cbcDec.transformBlock(request, i, message, i);
+		}
+		System.out.println("Encrypted packet:");
+		System.out.println(HelperUtils.bytesToHexString(request));
+		System.out.println("\nDecrypted packet:");
+		System.out.println(HelperUtils.bytesToHexString(message));
+		System.out.println("\nDecrypted string packet:");
+		System.out.println(HelperUtils.byteToStr(message));
+		System.out.println();
+		return message;
 	}
 	
 	/**
@@ -143,7 +189,7 @@ public class SSH implements Protocol {
 	 */
 	private Packet kexInit() {
 		byte[] msgCode = {0x14};
-		I_S = randomBytes(16);
+		byte[] cookie = HelperUtils.randomBytes(16);
 		byte[] kexLength = ByteBuffer.allocate(4).putInt(kex_alg.getBytes().length).array();
 		byte[] serverLength = ByteBuffer.allocate(4).putInt(server_alg.getBytes().length).array();
 		byte[] encrypt_c_Length = ByteBuffer.allocate(4).putInt(encrypt_alg_c.getBytes().length).array();
@@ -157,11 +203,12 @@ public class SSH implements Protocol {
 		byte[] kexFirsPckt = {0x00};
 		byte[] reserved = {0x00, 0x00, 0x00, 0x00};	
 		
-		byte[] response = HelperUtils.concat(msgCode, I_S, kexLength, kex_alg.getBytes(), serverLength, server_alg.getBytes(),
+		byte[] response = HelperUtils.concat(msgCode, cookie, kexLength, kex_alg.getBytes(), serverLength, server_alg.getBytes(),
 							encrypt_c_Length, encrypt_alg_c.getBytes(), encrypt_s_Length, encrypt_alg_s.getBytes(), mac_c_Length, mac_alg_c.getBytes(),
 							mac_s_Length, mac_alg_s.getBytes(), comp_c_Length, comp_alg_c.getBytes(), comp_s_Length, comp_alg_s.getBytes(),
 							language_c_s, language_s_c, kexFirsPckt, reserved);
-		return wrapPacket(response);
+		I_S = response;
+		return wrapPacket(response, false);
 	}
 	
 	/**
@@ -169,126 +216,123 @@ public class SSH implements Protocol {
 	 * @return Diffie-Hellman Kex Reply packet.
 	 */
 	private Packet dhKexReply() {
-		generateDHKeys();
-		generateHostKey();
-		generateSha1Hash();
-		generateSignature();
-		byte[] msgCode = {0x1f};
-		byte[] hostKeyLength = ByteBuffer.allocate(4).putInt(K_S.length).array();
-				byte[] fDHLength = ByteBuffer.allocate(4).putInt(f.length).array();
-		byte[] signatureLength = ByteBuffer.allocate(4).putInt(sig.length).array();
-		byte[] server_algLength = ByteBuffer.allocate(4).putInt(server_alg.getBytes().length).array();
-		byte[] payloadLength = ByteBuffer.allocate(4).putInt(server_algLength.length + signatureLength.length + sig.length + server_alg.getBytes().length).array();
-		byte[] response = HelperUtils.concat(msgCode, hostKeyLength,  K_S,
-									fDHLength, f, payloadLength, server_algLength, server_alg.getBytes(), signatureLength, sig);
-		return wrapPacket(response);
+		//TODO make it small		
+		try {
+			SecureRandom rnd = new SecureRandom();
+			DhExchange dhx = new DhExchange();
+			dhx.serverInit(1, rnd);
+			dhx.setE(new BigInteger(e));
+			f = dhx.getF();
+			DSAPrivateKey dsa = (DSAPrivateKey) PEMDecoder.decode(dsa_pem, null);
+			K_S = DSASHA1Verify.encodeSSHDSAPublicKey(dsa.getPublicKey());
+			h = dhx.calculateH(V_C, V_S, I_C, I_S, K_S);
+			k = dhx.getK();
+			DSASignature ds = DSASHA1Verify.generateSignature(h, dsa, rnd);
+			sig = DSASHA1Verify.encodeSSHDSASignature(ds);
+			TypesWriter tw = new TypesWriter();
+			tw.writeByte(31);
+			tw.writeString(K_S, 0, K_S.length);
+			tw.writeMPInt(f);
+			tw.writeString(sig, 0, sig.length);
+			byte[] response = tw.getBytes();
+			
+			//init for decryption and encryption
+			KeyMaterial km = KeyMaterial.create("SHA1", h, k, h, 24, 8, 20, 24, 8, 20); // alg, h, k, keylength, blocklength, maclength, keylength, blocklength, maclength
+			enc = new DESede();
+			dec = new DESede();
+			enc.init(true, km.enc_key_server_to_client);
+			dec.init(false, km.enc_key_client_to_server);
+			cbcEnc = new CBCMode(enc, km.initial_iv_server_to_client, true);
+			cbcDec = new CBCMode(dec, km.initial_iv_client_to_server, false);
+			macEnc = new MAC("hmac-sha1", km.integrity_key_server_to_client);
+			macDec = new MAC("hmac-sha1", km.integrity_key_client_to_server);
+			
+			return wrapPacket(response, false);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return wrapPacket(null, false);
 	}
-	
+
 	/**
 	 * New Keys response.
 	 * @return New Keys response.
 	 */
 	private Packet newKeys() {
 		byte[] msgCode = {0x15};
-		return wrapPacket(msgCode);
+		return wrapPacket(msgCode, false);
 	}
 	
-	/**
-	 * Generates the required Diffie-Hellman keys with p and g from Oakley Group 1.
-	 */
-	private void generateDHKeys() {	
-		try {
-			KeyPairGenerator myKpairGen = KeyPairGenerator.getInstance("DH");
-			KeyAgreement myKeyAgree = KeyAgreement.getInstance("DH");
-			BigInteger p = new BigInteger(this.p);
-			BigInteger g = new BigInteger(this.g);
-			BigInteger e = new BigInteger(this.e);
-			
-            DHParameterSpec dhParamSpec = new DHParameterSpec(p, g);
-            myKpairGen.initialize(dhParamSpec);
-            KeyPair myKpair = myKpairGen.generateKeyPair();
-            myKeyAgree.init(myKpair.getPrivate());
-            BigInteger f = ((DHPublicKey) (myKpair.getPublic())).getY();
-            this.f = f.toByteArray();
-            
-            KeyFactory myKeyFac = KeyFactory.getInstance("DH");
-            DHPublicKeySpec keySpec = new DHPublicKeySpec(e, p, g);
-            PublicKey yourPubKey = myKeyFac.generatePublic(keySpec);
-            myKeyAgree.doPhase(yourPubKey, true);
-            byte[] mySharedSecret = myKeyAgree.generateSecret();
-            k = mySharedSecret;
-		} catch (Exception e) {
-			e.printStackTrace();
+	// TODO
+	private Packet serviceReply(byte[] request) {
+		byte[] messageBuf;
+		if(request[5] == 0x15) {	//if newkeys request is included in the same packet
+			messageBuf = new byte[request.length - 16];
+			System.arraycopy(request, 16, messageBuf, 0, request.length-16);
+		} else {
+			messageBuf = request;
 		}
+		byte[] message = decryptPacket(messageBuf);
+		
+		if (message[5] != 0x05 && message[9] != 0x0c) {
+			// TODO disconnect because its not servicerequest ssh-userauth
+		}
+		byte[] msgcode = {0x06};
+		byte[] serviceLength;
+		byte[] service = "ssh-userauth".getBytes();
+		serviceLength = ByteBuffer.allocate(4).putInt(service.length).array();
+		
+		byte[] response = HelperUtils.concat(msgcode, serviceLength, service);
+		return wrapPacket(response, true);		
 	}
 	
-	/**
-	 * Generates the Host Key based on the DSA algorithm
-	 */
-	private void generateHostKey() {
-        try {
-            KeyPairGenerator generator = KeyPairGenerator.getInstance("DSA");
-            dsa = generator.generateKeyPair();
-            
-            byte[] string = "ssh-dss".getBytes();
-            byte[] stringLength = ByteBuffer.allocate(4).putInt(string.length).array();
-            
-            byte[] p = ((DSAPublicKey) dsa.getPublic()).getParams().getP().toByteArray();
-            if(p[0] != 0x00) p = HelperUtils.concat(new byte[]{0x00}, p);
-            byte[] pLength = ByteBuffer.allocate(4).putInt(p.length).array();
-            
-            byte[] q = ((DSAPublicKey) dsa.getPublic()).getParams().getQ().toByteArray();
-            if(q[0] != 0x00) q = HelperUtils.concat(new byte[]{0x00}, q);
-            byte[] qLength = ByteBuffer.allocate(4).putInt(q.length).array();
-            
-            byte[] g = ((DSAPublicKey) dsa.getPublic()).getParams().getG().toByteArray();
-            if(g[0] != 0x00) g = HelperUtils.concat(new byte[]{0x00}, g);
-            byte[] gLength = ByteBuffer.allocate(4).putInt(g.length).array();
-            
-            byte[] y = ((DSAPublicKey) dsa.getPublic()).getY().toByteArray();
-            if(y[0] != 0x00) y = HelperUtils.concat(new byte[]{0x00}, y);
-            byte[] yLength = ByteBuffer.allocate(4).putInt(y.length).array();
-            
-            K_S = HelperUtils.concat(stringLength, string, pLength, p, qLength, q, gLength, g, yLength, y);       		
-        } catch (Exception e) {
-        	e.printStackTrace();
-        }
+	// TODO
+	private Packet userauthReply(byte[] request) {
+		byte[] message = decryptPacket(request);
+		if (message[5] != 0x32) {
+			// TODO disconnect because its not servicerequest ssh-connect
+		}
+		byte[] msgcode = {0x34};
+		byte[] response = msgcode;
+		
+		return wrapPacket(response, true);		
 	}
 	
-	/**
-	 * Generates the SHA-1 Hash from several values
-	 */
-	private void generateSha1Hash() {
-		try {
-			MessageDigest sha = MessageDigest.getInstance("SHA-1");
-			sha.update(V_C);
-			sha.update(V_S);
-			sha.update(I_C);
-			sha.update(I_S);
-			sha.update(K_S);
-			sha.update(e);
-			sha.update(f);
-			sha.update(k);
-			h = sha.digest();
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
+	// TODO
+	private Packet channelOpenReply(byte[] request) {
+		byte[] message = decryptPacket(request);
+		// TODO if contains "session" ok else disc
+		byte[] msgcode = {0x5b};
+		recipientChannel = new byte[4];
+		byte[] senderChannel = new byte[4];
+		byte[] initialWindowSize = new byte[4];
+		byte[] maximumPacketSize = new byte[4];
+		System.arraycopy(message, 17, recipientChannel, 0, 4); //TODO dynamic position
+		System.arraycopy(message, 17, senderChannel, 0, 4);
+		System.arraycopy(message, 21, initialWindowSize, 0, 4);
+		System.arraycopy(message, 25, maximumPacketSize, 0, 4);
+		byte[] response = HelperUtils.concat(msgcode, recipientChannel, senderChannel, initialWindowSize, maximumPacketSize);
+		System.out.println("CHANNEL REPLY:");
+		System.out.println(HelperUtils.bytesToHexString(response));
+		return wrapPacket(response, true);
 	}
 	
-	/**
-	 * Generates the signature of the hash using DSA algorithm with SHA-1
-	 */
-	private void generateSignature() {	
-		//FIXME something is wrong with this signature.. maybe one of the used components is generated wrong?! 
-		try {
-			Signature sig = Signature.getInstance("SHA1withDSA");
-            sig.initVerify(dsa.getPublic());
-            sig.initSign(dsa.getPrivate());
-            sig.update(h);
-            this.sig = extractSignature(sig.sign());
-		} catch (Exception e) {
-			e.printStackTrace();
-		}
+	byte[] recipientChannel; //TODO
+	private Packet channelSuccessReply(byte[] request) {
+		decryptPacket(request);
+		byte[] msgcode = {0x63}; //TODO check msg type
+		byte[] response = HelperUtils.concat(msgcode, recipientChannel);
+		System.out.println(HelperUtils.bytesToHexString(response));
+		return wrapPacket(response, true);
+	}
+	
+	private Packet data(byte[] request) {
+		byte[] msgcode = {0x5E};
+		byte[] msglength = new byte[4];
+		byte[] msg = "lolol".getBytes();
+		msglength = ByteBuffer.allocate(4).putInt(msg.length).array();
+		byte[] response = HelperUtils.concat(msgcode, recipientChannel, msglength, msg);
+		return wrapPacket(response, true);
 	}
 	
 	/**
@@ -297,27 +341,32 @@ public class SSH implements Protocol {
 	 */
 	private void extractType(byte[] request) {
 		int length = 0;
-		for(int i = 8; i < request.length; i++, length++) { 	//start at 8 because "SSH-2.0-" is not part of type
+		for(int i = 0; i < request.length; i++, length++) { 	
 			if(request[i] == 0x0d) break;			//find the end of the type: '\r'
 		}
 		V_C = new byte[length];
-		System.arraycopy(request, 8, V_C, 0, length);
+		System.arraycopy(request, 0, V_C, 0, length);
 	}
 	
 	/**
-	 * Extracts the cookie from the Kex Init client request 
-	 * @param request containing the clients cookie
+	 * Extracts the payload of a packet and writes it in I_C.
+	 * @param request packet of which the payload is extracted.
 	 */
-	private void extractCookie(byte[] request) {
+	private void extractPayload(byte[] request) {
 		int pos = 0;
-		if(request[5] != 0x14) {	//if type packet is in front of kex init
-			pos = 1;				//start behind the end of type message
+		if(request[5] != 0x14) {
+			pos = 1;
 			for(int i = 0; i < request.length; i++, pos++) {
-				if(request[i] == 0x0a) break;		//find end of type message: '\n'
+				if(request[i] == 0xa) break;
 			}
 		}
-		I_C = new byte[16];
-		System.arraycopy(request, 6+pos, I_C, 0, 16); //srcLen: headersize+position after type packet
+		int packetLength = byteToInt(new byte[]{request[pos], request[1+pos], request[2+pos], request[3+pos]});
+		int paddingLength = byteToInt(new byte[]{request[4+pos]});
+		byte[] payload = new byte[packetLength - paddingLength - 1];
+		for(int i = 5; i < packetLength - paddingLength - 1; i++) {
+			payload[i-5] = request[i+pos];
+		}
+		I_C = payload;
 	}
 	
 	/**
@@ -345,98 +394,53 @@ public class SSH implements Protocol {
 		  return ret;
 	}
 	
-	/**
-	 * Generates a random byte[] of a specified size
-	 * @param size of the byte[]
-	 * @return random byte[]
-	 */
-	private byte[] randomBytes(int size) {
-		byte[] bytes = new byte[size];
-		SecureRandom rdm = new SecureRandom();
-		rdm.nextBytes(bytes);
-		return bytes;		
-	}
-
-	/**
-	 * Extracts r and s from a DSA-signature
-	 * @param signature 
-	 * @return r and s as byte[]
-	 */
-	private byte[] extractSignature(byte[] signature) {
-        int length = 0;
-        int index = 3;
-        length = signature[index++] & 0xff;
-        byte[] r = new byte[length];
-        System.arraycopy(signature, index, r, 0, r.length);
-        index = index + length + 1;
-        length = signature[index++] & 0xff;
-        byte[] s = new byte[length];
-        System.arraycopy(signature, index, s, 0, s.length);
-        byte[] result = new byte[40];
-        // result must be 40 bytes, but r and s may be longer than 20
-        System.arraycopy(r,
-                         (r.length > 20) ? 1 : 0,
-                         result,
-                         (r.length > 20) ? 0 : 20 - r.length,
-                         (r.length > 20) ? 20 : r.length);
-        System.arraycopy(s,
-                         (s.length > 20) ? 1 : 0,
-                         result,
-                         (s.length > 20) ? 20 : 40 - s.length,
-                         (s.length > 20) ? 20 : s.length);
-        return result;
-    }
-	
 	private String serverVersion = ProtocolSettings.getSshVersion();
 	private String serverType = ProtocolSettings.getSshType();
-		
-	//Diffie-Hellman-Group-1 p and g
-	private final byte[] p = {
-            (byte)0x00,
-            (byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,
-            (byte)0xC9,(byte)0x0F,(byte)0xDA,(byte)0xA2,(byte)0x21,(byte)0x68,(byte)0xC2,(byte)0x34,
-            (byte)0xC4,(byte)0xC6,(byte)0x62,(byte)0x8B,(byte)0x80,(byte)0xDC,(byte)0x1C,(byte)0xD1,
-            (byte)0x29,(byte)0x02,(byte)0x4E,(byte)0x08,(byte)0x8A,(byte)0x67,(byte)0xCC,(byte)0x74,
-            (byte)0x02,(byte)0x0B,(byte)0xBE,(byte)0xA6,(byte)0x3B,(byte)0x13,(byte)0x9B,(byte)0x22,
-            (byte)0x51,(byte)0x4A,(byte)0x08,(byte)0x79,(byte)0x8E,(byte)0x34,(byte)0x04,(byte)0xDD,
-            (byte)0xEF,(byte)0x95,(byte)0x19,(byte)0xB3,(byte)0xCD,(byte)0x3A,(byte)0x43,(byte)0x1B,
-            (byte)0x30,(byte)0x2B,(byte)0x0A,(byte)0x6D,(byte)0xF2,(byte)0x5F,(byte)0x14,(byte)0x37,
-            (byte)0x4F,(byte)0xE1,(byte)0x35,(byte)0x6D,(byte)0x6D,(byte)0x51,(byte)0xC2,(byte)0x45,
-            (byte)0xE4,(byte)0x85,(byte)0xB5,(byte)0x76,(byte)0x62,(byte)0x5E,(byte)0x7E,(byte)0xC6,
-            (byte)0xF4,(byte)0x4C,(byte)0x42,(byte)0xE9,(byte)0xA6,(byte)0x37,(byte)0xED,(byte)0x6B,
-            (byte)0x0B,(byte)0xFF,(byte)0x5C,(byte)0xB6,(byte)0xF4,(byte)0x06,(byte)0xB7,(byte)0xED,
-            (byte)0xEE,(byte)0x38,(byte)0x6B,(byte)0xFB,(byte)0x5A,(byte)0x89,(byte)0x9F,(byte)0xA5,
-            (byte)0xAE,(byte)0x9F,(byte)0x24,(byte)0x11,(byte)0x7C,(byte)0x4B,(byte)0x1F,(byte)0xE6,
-            (byte)0x49,(byte)0x28,(byte)0x66,(byte)0x51,(byte)0xEC,(byte)0xE6,(byte)0x53,(byte)0x81,
-            (byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF
-      };
-	private final byte[] g = {0x02};
+	private int send_packet_number = 0;
 	
 	//SSH Parameters for Kex etc.
-    private byte[] V_S = serverType.getBytes();
+    private byte[] V_S = (serverVersion + serverType).getBytes();
     private byte[] V_C;
     private byte[] I_S;
     private byte[] I_C;
     private byte[] e;
-    private byte[] f;
-    private byte[] k;
+    private BigInteger f;
     private byte[] h;
+    private BigInteger k;
     private byte[] K_S;
     private byte[] sig;
-
-    //Keys for signature
-    private KeyPair dsa;
 			
     //allowed algorithms for kexinit
 	private String kex_alg = "diffie-hellman-group1-sha1";
 	private String server_alg = "ssh-dss";
-	private String encrypt_alg_c = "aes128-ctr";
-	private String encrypt_alg_s = "aes128-ctr";
+	private String encrypt_alg_c = "3des-cbc";
+	private String encrypt_alg_s = "3des-cbc";
 	private String mac_alg_c = "hmac-sha1";
 	private String mac_alg_s = "hmac-sha1";
 	private String comp_alg_c = "none";
 	private String comp_alg_s = "none";
 	
 	private int cipherBlockSize = 16;
+	
+	DESede enc;
+	DESede dec;
+	CBCMode cbcEnc;
+	CBCMode cbcDec;
+	MAC macEnc;
+	MAC macDec;
+	
+	//dsa private key
+	private final char[] dsa_pem = ("-----BEGIN DSA PRIVATE KEY-----\n" +
+			"MIIBugIBAAKBgQCDZ9R2vfCPwjv5vKF1igIv9drrZ7G0dhMkGT9AZTjgI34Qm4w0\n" +
+			"0iWeCqO7SmqiaMIjbRIm91MeDed4ObAq4sAkqRE/2P4mTbzFx5KhEczRRiDoqQBX\n" +
+			"xYa0yWKJpeZ94SGM6DEPuBTxKo0T4uMjbq2FzHL2FXT1/WoNCmRU6gFSiwIVAMK4\n" +
+			"Epz3JiwDUbkSpLOjIqtEhJmVAoGAL6zlXRI4Q8iwvSDh0vDf1j9a5Aaaq+93LTjK\n" +
+			"SwL4nvUWBl2Aa0vqu05ZS5rOD1I+/naLMg0fNgFJRhA03sl+12MI3a2HXJWXRSdj\n" +
+			"m1Vq9cUXqiYrX6+iGfEaA/y9UO4ZPF6if6eLypXB8VuqjtjDCiMMsM6+qQki7L71\n" +
+			"yN4M75ICgYAcFXUhN2zRug3JvwmGxW8gMgHquSiBnbx1582KGh2B/ukE/kOrbKYD\n" +
+			"HUkBzolcm4x1Odq5apowlriFxY6zMQP615plIK4x9NaU6dvc/HoTkjzT5EYSMN39\n" +
+			"eAGufJ0jrtIpKL4lP8o8yrAHfmbR7bjecWc0viTH0+OWlyVsex/bZAIUEKn310Li\n" +
+			"v62Zs4hlDvhwvx8MQ+A=\n" +
+			"-----END DSA PRIVATE KEY-----").toCharArray();
 
 }

+ 0 - 1
src/de/tudarmstadt/informatik/hostage/protocol/SSLProtocol.java

@@ -4,7 +4,6 @@ import javax.net.ssl.SSLContext;
 /**
  * Interface for ssl protocols that are used by hostage
  * @author Wulf Pfeiffer
- * @param <T> Denotes if the protocol is using Strings or ByteArrays
  */
 public interface SSLProtocol extends Protocol {
 

+ 7 - 5
src/de/tudarmstadt/informatik/hostage/protocol/TELNET.java

@@ -23,16 +23,17 @@ public class TELNET implements Protocol {
 	 */
 	private STATE state = STATE.NONE;
 	
+	@Override
 	public int getPort() {
 		return 23;
 	}
 
-	
+	@Override
 	public TALK_FIRST whoTalksFirst() {
 		return TALK_FIRST.SERVER;
 	}
 
-	
+	@Override
 	public List<Packet> processMessage(Packet packet) {
 		byte[] request = null;
 		if(packet != null) {
@@ -134,21 +135,22 @@ public class TELNET implements Protocol {
 		return response;
 	}
 
-	
+	@Override
 	public boolean isClosed() {
 		return (state == STATE.CLOSED);
 	}
 
-	
+	@Override
 	public boolean isSecure() {
 		return false;
 	}
 	
+	@Override
 	public String toString() {
 		return "TELNET";
 	}
 	
-	
+	@Override
 	public Class<byte[]> getType() {
 		return byte[].class;
 	}