|
@@ -1,250 +1,201 @@
|
|
|
package de.tudarmstadt.informatik.hostage.protocol;
|
|
|
|
|
|
-import java.security.SecureRandom;
|
|
|
-import java.util.ArrayList;
|
|
|
-import java.util.List;
|
|
|
|
|
|
+import android.content.Context;
|
|
|
import android.content.SharedPreferences;
|
|
|
+import android.net.DhcpInfo;
|
|
|
+import android.net.wifi.WifiManager;
|
|
|
import android.preference.PreferenceManager;
|
|
|
|
|
|
+import org.alfresco.jlan.app.XMLServerConfiguration;
|
|
|
+import org.alfresco.jlan.netbios.server.NetBIOSNameServer;
|
|
|
+import org.alfresco.jlan.server.SessionListener;
|
|
|
+import org.alfresco.jlan.server.SrvSession;
|
|
|
+import org.alfresco.jlan.server.config.InvalidConfigurationException;
|
|
|
+import org.alfresco.jlan.server.filesys.FileListener;
|
|
|
+import org.alfresco.jlan.server.filesys.NetworkFile;
|
|
|
+import org.alfresco.jlan.smb.server.CIFSConfigSection;
|
|
|
+import org.alfresco.jlan.smb.server.SMBServer;
|
|
|
+
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.InputStreamReader;
|
|
|
+import java.net.InetAddress;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+import de.tudarmstadt.informatik.hostage.Handler;
|
|
|
import de.tudarmstadt.informatik.hostage.Hostage;
|
|
|
+import de.tudarmstadt.informatik.hostage.Listener;
|
|
|
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.location.MyLocationManager;
|
|
|
+import de.tudarmstadt.informatik.hostage.logging.AttackRecord;
|
|
|
+import de.tudarmstadt.informatik.hostage.logging.Logger;
|
|
|
+import de.tudarmstadt.informatik.hostage.logging.MessageRecord;
|
|
|
+import de.tudarmstadt.informatik.hostage.logging.NetworkRecord;
|
|
|
+import de.tudarmstadt.informatik.hostage.logging.SyncDevice;
|
|
|
+import de.tudarmstadt.informatik.hostage.protocol.cifs.CifsServer;
|
|
|
+import de.tudarmstadt.informatik.hostage.ui.activity.MainActivity;
|
|
|
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
|
|
|
+ * HostageV3
|
|
|
+ * ================
|
|
|
+ * @author Alexander Brakowski
|
|
|
+ * @author Daniel Lazar
|
|
|
*/
|
|
|
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];
|
|
|
+ private Listener mListener;
|
|
|
+ private Handler mHandler;
|
|
|
+ private SMBServer mSmbServer;
|
|
|
+ private NetBIOSNameServer mNbNameServer;
|
|
|
+ private CifsServer mCifsServer;
|
|
|
+
|
|
|
+ SharedPreferences pref;
|
|
|
+
|
|
|
+ private int attack_id;
|
|
|
+ private String externalIP;
|
|
|
+ private String BSSID;
|
|
|
+ private String SSID;
|
|
|
+
|
|
|
+ private int subnetMask;
|
|
|
+ private int internalIPAddress;
|
|
|
+
|
|
|
+ private boolean logged;
|
|
|
+
|
|
|
+ public Listener getListener(){
|
|
|
+ return mListener;
|
|
|
+ }
|
|
|
+
|
|
|
+ public void initialize(Listener mListener) {
|
|
|
+ this.mListener = mListener;
|
|
|
+
|
|
|
+ Hostage service = mListener.getService();
|
|
|
+ pref = PreferenceManager.getDefaultSharedPreferences(service);
|
|
|
+ getAndIncrementAttackID(pref);
|
|
|
+ SharedPreferences connInfo = service.getSharedPreferences(service.getString(R.string.connection_info), Context.MODE_PRIVATE);
|
|
|
+ BSSID = connInfo.getString(service.getString(R.string.connection_info_bssid), null);
|
|
|
+ SSID = connInfo.getString(service.getString(R.string.connection_info_ssid), null);
|
|
|
+ externalIP = connInfo.getString(service.getString(R.string.connection_info_external_ip), null);
|
|
|
+
|
|
|
+ // we need this info to find out whether the attack was internal
|
|
|
+ subnetMask = connInfo.getInt(service.getString(R.string.connection_info_subnet_mask), 0);
|
|
|
+ internalIPAddress = connInfo.getInt(service.getString(R.string.connection_info_internal_ip), 0);
|
|
|
+ logged = false;
|
|
|
+
|
|
|
+ XMLServerConfiguration smbConfig = new XMLServerConfiguration();
|
|
|
+
|
|
|
+ try {
|
|
|
+ smbConfig.loadConfiguration(new InputStreamReader(MainActivity.context.getResources().openRawResource(R.raw.jlan_config)));
|
|
|
+ mCifsServer = new CifsServer(smbConfig, this);
|
|
|
+ mCifsServer.run();
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ } catch (InvalidConfigurationException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public void stop(){
|
|
|
+ mCifsServer.stop();
|
|
|
+ }
|
|
|
+
|
|
|
+ public int getLocalIp(){
|
|
|
+ WifiManager wifi = (WifiManager) MainActivity.context.getSystemService(Context.WIFI_SERVICE);
|
|
|
+ DhcpInfo dhcp = wifi.getDhcpInfo();
|
|
|
+
|
|
|
+ return dhcp.ipAddress;
|
|
|
+ }
|
|
|
+
|
|
|
+ private synchronized void getAndIncrementAttackID(SharedPreferences pref) {
|
|
|
+ SharedPreferences.Editor editor = pref.edit();
|
|
|
+ attack_id = pref.getInt("ATTACK_ID_COUNTER", 0);
|
|
|
+ editor.putInt("ATTACK_ID_COUNTER", attack_id + 1);
|
|
|
+ editor.commit();
|
|
|
+ }
|
|
|
+
|
|
|
+ public MessageRecord createMessageRecord(MessageRecord.TYPE type, String packet) {
|
|
|
+ MessageRecord record = new MessageRecord(true);
|
|
|
+ //record.setId(message_id++); // autoincrement
|
|
|
+ record.setAttack_id(attack_id);
|
|
|
+ record.setType(type);
|
|
|
+ record.setTimestamp(System.currentTimeMillis());
|
|
|
+ record.setPacket(packet);
|
|
|
+ return record;
|
|
|
+ }
|
|
|
+
|
|
|
+ public AttackRecord createAttackRecord(int localPort, InetAddress remoteIP, int remotePort) {
|
|
|
+ AttackRecord record = new AttackRecord();
|
|
|
+ record.setAttack_id(attack_id);
|
|
|
+ record.setSync_id(attack_id);
|
|
|
+ record.setDevice(SyncDevice.currentDevice().getDeviceID());
|
|
|
+
|
|
|
+ record.setProtocol(this.toString());
|
|
|
+ record.setExternalIP(externalIP);
|
|
|
+ record.setLocalIP(CifsServer.intToInetAddress(getLocalIp()).getHostAddress());
|
|
|
+ record.setLocalPort(localPort);
|
|
|
+ record.setWasInternalAttack((HelperUtils.packInetAddress(remoteIP.getAddress()) & subnetMask) == (internalIPAddress & subnetMask));
|
|
|
+ record.setRemoteIP(remoteIP.getHostAddress());
|
|
|
+ record.setRemotePort(remotePort);
|
|
|
+ record.setBssid(BSSID);
|
|
|
+ return record;
|
|
|
+ }
|
|
|
+
|
|
|
+ public NetworkRecord createNetworkRecord() {
|
|
|
+ NetworkRecord record = new NetworkRecord();
|
|
|
+ record.setBssid(BSSID);
|
|
|
+ record.setSsid(SSID);
|
|
|
+ if (MyLocationManager.getNewestLocation() != null) {
|
|
|
+ record.setLatitude(MyLocationManager.getNewestLocation().getLatitude());
|
|
|
+ record.setLongitude(MyLocationManager.getNewestLocation().getLongitude());
|
|
|
+ record.setAccuracy(MyLocationManager.getNewestLocation().getAccuracy());
|
|
|
+ record.setTimestampLocation(MyLocationManager.getNewestLocation().getTime());
|
|
|
+ } else {
|
|
|
+ record.setLatitude(0.0);
|
|
|
+ record.setLongitude(0.0);
|
|
|
+ record.setAccuracy(Float.MAX_VALUE);
|
|
|
+ record.setTimestampLocation(0);
|
|
|
}
|
|
|
- return new String(hexChars);
|
|
|
+ return record;
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
- public List<Packet> processMessage(Packet requestPacket) {
|
|
|
- if (requestPacket != null && requestPacket.getBytes().length != 0){
|
|
|
- lastMessage = requestPacket.getBytes();
|
|
|
- System.out.println("request packet " + bytesToHex(lastMessage));
|
|
|
- smbPacket.prepareNextResponse(lastMessage);
|
|
|
+ public void log(MessageRecord.TYPE type, String packet, int localPort, InetAddress remoteIP, int remotePort){
|
|
|
+ if(!logged){
|
|
|
+ Logger.log(Hostage.getContext(), createNetworkRecord());
|
|
|
+ Logger.log(Hostage.getContext(), createAttackRecord(localPort, remoteIP, remotePort));
|
|
|
+ logged = true;
|
|
|
}
|
|
|
- else{
|
|
|
- //something needs to be done, if there is no message
|
|
|
- smbPacket.prepareNextResponse(0);
|
|
|
+ if (packet != null && packet.length() > 0) { // prevent logging empty packets
|
|
|
+ Logger.log(Hostage.getContext(), createMessageRecord(type, packet));
|
|
|
}
|
|
|
- byte smbCommand = smbPacket.getSmbCommand();
|
|
|
- byte[] response;
|
|
|
- List<Packet> responsePackets = new ArrayList<Packet>();
|
|
|
-
|
|
|
- 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;
|
|
|
- }
|
|
|
-}
|
|
|
+ }
|
|
|
+ @Override
|
|
|
+ public int getPort() {
|
|
|
+ return 1025;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean isClosed() {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean isSecure() {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public List<Packet> processMessage(Packet message) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public TALK_FIRST whoTalksFirst() {
|
|
|
+ return TALK_FIRST.CLIENT;
|
|
|
+ }
|
|
|
+
|
|
|
+ public String toString(){
|
|
|
+ return "SMB";
|
|
|
+ }
|
|
|
+}
|