package de.tudarmstadt.informatik.hostage.protocol; import java.security.SecureRandom; import java.util.ArrayList; import java.util.List; import android.content.SharedPreferences; import android.preference.PreferenceManager; import de.tudarmstadt.informatik.hostage.Hostage; import de.tudarmstadt.informatik.hostage.R; import de.tudarmstadt.informatik.hostage.commons.HelperUtils; import de.tudarmstadt.informatik.hostage.protocol.smbutils.NBDSType; import de.tudarmstadt.informatik.hostage.protocol.smbutils.NBNS; import de.tudarmstadt.informatik.hostage.protocol.smbutils.NBNSType; import de.tudarmstadt.informatik.hostage.protocol.smbutils.NMB; import de.tudarmstadt.informatik.hostage.protocol.smbutils.SMBPacket; import de.tudarmstadt.informatik.hostage.wrapper.Packet; /** * SMB protocol. It can handle the following requests: Negotiate Protocol * Request, Session Setup AndX Request, Tree Connect AndX Request, NT Create * AndX Request, Bind, NetShareEnumAll, Close Request, Tree Disconnect Request, * Echo Request, Trans2 Request. * * @author Wulf Pfeiffer */ public class SMB implements Protocol { // message constants private static final byte SMB_COM_CLOSE = 0x04; private static final byte SMB_COM_TRANSACTION = 0x25; private static final byte SMB_COM_ECHO = 0x2B; private static final byte SMB_COM_TRANSACTION2 = 0x32; private static final byte SMB_COM_TREE_DISCONNECT = 0x71; private static final byte SMB_COM_NEGOTIATE = 0x72; private static final byte SMB_COM_SESSION_SETUP_ANDX = 0x73; private static final byte SMB_COM_TREE_CONNECT_ANDX = 0x75; private static final byte SMB_COM_NT_CREATE_ANDX = (byte) 0xA2; /** * Denotes in which state the protocol is right now */ private STATE state = STATE.NONE; private byte[] lastMessage; private NMB nmb; // version stuff private String[][] possibleSmbVersions = { { "Windows 7 Professional 7600", "Windows 7 Professional 6.1" }, { "Windows 8 Enterprise 9200", "Windows 8 Enterprise 9200" }, { "Windows Server 2008 R2 Enterprise 7600", "Windows Server 2008 R2 Enterprise 6.1" }, { "Windows Server 2012 Standard 6.2", "Windows Server 2012 Standard 6.2" }, { "Unix", "Samba" }, { "Windows 2002 Service Pack 2", "Windows 2002 5.1" } }; /** * Represents the states of the protocol */ private static enum STATE { NONE, CONNECTED, AUTHENTICATED, LISTING, DISCONNECTED, CLOSED } public void setIP(String ip) { // TODO if porthack is working for UDP uncomment nmb = new NMB(ip, "BLIBLABLUB", "Workgroup"); nmb.start(); // nmb = new NMB(ip, new String(serverName), workgroup); // nmb.start(); } private String[] initServerVersion() { String sharedPreferencePath = Hostage.getContext().getString( R.string.shared_preference_path); String profile = Hostage .getContext() .getSharedPreferences(sharedPreferencePath, Hostage.MODE_PRIVATE).getString("os", ""); if(profile.equals("Windows XP")) { workgroup = "MSHOME"; } else { workgroup = "WORKGROUP"; } if (profile.equals("Windows 7")) { return possibleSmbVersions[0]; } else if (profile.equals("Windows 8")) { return possibleSmbVersions[1]; } else if (profile.equals("Windows Server 2008")) { return possibleSmbVersions[2]; } else if (profile.equals("Windows Server 2012")) { return possibleSmbVersions[3]; } else if (profile.equals("Linux")) { return possibleSmbVersions[4]; } else if (profile.equals("Windows XP")) { return possibleSmbVersions[5]; } else { return possibleSmbVersions[new SecureRandom().nextInt(possibleSmbVersions.length)]; } } //required to be declared down here, do not change position over initServerVersion() and possibleServerVersions!! private String[] serverVersion = initServerVersion(); 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); private int maxEchoPackets = initMaxPackets(); private int receivedEchoPackets = 0; private int initMaxPackets() { int maxPackets; SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(Hostage.getContext()); maxPackets = Integer.parseInt(prefs.getString("pref_timeout", "30")) / 5; return maxPackets; } @Override public int getPort() { return 445; } @Override public boolean isClosed() { return (state == STATE.CLOSED); } @Override public boolean isSecure() { return false; } //just for debugging purpose final protected static char[] hexArray = "0123456789ABCDEF".toCharArray(); public static String bytesToHex(byte[] bytes) { char[] hexChars = new char[bytes.length * 2]; for ( int j = 0; j < bytes.length; j++ ) { int v = bytes[j] & 0xFF; hexChars[j * 2] = hexArray[v >>> 4]; hexChars[j * 2 + 1] = hexArray[v & 0x0F]; } return new String(hexChars); } @Override public List processMessage(Packet requestPacket) { if (requestPacket != null && requestPacket.getBytes().length != 0){ lastMessage = requestPacket.getBytes(); System.out.println("request packet " + bytesToHex(lastMessage)); smbPacket.prepareNextResponse(lastMessage); } else{ //something needs to be done, if there is no message smbPacket.prepareNextResponse(0); } byte smbCommand = smbPacket.getSmbCommand(); byte[] response; List responsePackets = new ArrayList(); if (smbCommand == SMB_COM_ECHO) { receivedEchoPackets++; } else { receivedEchoPackets = 0; } if (receivedEchoPackets == maxEchoPackets) { state = STATE.CLOSED; response = smbPacket.getTreeDisc(); responsePackets.add(new Packet(response, toString())); return responsePackets; } switch (state) { case NONE: if (smbCommand == SMB_COM_NEGOTIATE) { state = STATE.CONNECTED; response = smbPacket.getNego(); } else { state = STATE.DISCONNECTED; response = smbPacket.getTreeDisc(); } break; case CONNECTED: if (smbCommand == SMB_COM_SESSION_SETUP_ANDX) { response = smbPacket.getSessSetup(); } else if (smbCommand == SMB_COM_TREE_CONNECT_ANDX) { state = STATE.AUTHENTICATED; response = smbPacket.getTreeCon(); } else { state = STATE.DISCONNECTED; response = smbPacket.getTreeDisc(); } break; case AUTHENTICATED: if (smbCommand == SMB_COM_NT_CREATE_ANDX) { state = STATE.LISTING; response = smbPacket.getNTCreate(); } else if (smbCommand == SMB_COM_ECHO) { response = smbPacket.getEcho(); } else if (smbCommand == SMB_COM_TRANSACTION2) { response = smbPacket.getTrans2(); } else if (smbCommand == SMB_COM_CLOSE) { response = smbPacket.getClose(); } else if (smbCommand == SMB_COM_TREE_DISCONNECT) { state = STATE.CLOSED; response = smbPacket.getTreeDisc(); } else { state = STATE.DISCONNECTED; response = smbPacket.getTreeDisc(); } break; case LISTING: if (smbCommand == SMB_COM_TRANSACTION) { response = smbPacket.getTrans(); } else if (smbCommand == SMB_COM_CLOSE) { response = smbPacket.getClose(); } else if (smbCommand == SMB_COM_TREE_DISCONNECT) { state = STATE.CLOSED; response = smbPacket.getTreeDisc(); } else if (smbCommand == SMB_COM_NEGOTIATE) { state = STATE.CONNECTED; response = smbPacket.getNego(); } else { state = STATE.DISCONNECTED; response = smbPacket.getTreeDisc(); } break; case DISCONNECTED: state = STATE.CLOSED; response = smbPacket.getTreeDisc(); break; default: state = STATE.CLOSED; response = smbPacket.getTreeDisc(); } responsePackets.add(new Packet(response, toString())); return responsePackets; } @Override public String toString() { return "SMB"; } @Override public TALK_FIRST whoTalksFirst() { return TALK_FIRST.CLIENT; } }