From 31e05a4f7bb2d94f662753910782131493b5e35f Mon Sep 17 00:00:00 2001 From: MatrixTM26 Date: Sun, 4 Oct 2026 21:40:21 +0700 Subject: [PATCH] fixed: missing operator re-auth after connection lost --- .../src/main/java/com/raven/Start.java | 7 +- .../core/command/AgentCommandDispatcher.java | 4 +- .../raven/core/command/CommandDispatcher.java | 15 +- .../raven/core/command/CommandRegistry.java | 4 +- .../com/raven/core/command/ExportCommand.java | 25 ++- .../core/cryptography/CertificateManager.java | 21 +- .../java/com/raven/core/output/EventLog.java | 22 +- .../java/com/raven/core/output/Logger.java | 93 ++++---- .../com/raven/core/output/PromptManager.java | 30 ++- .../com/raven/core/server/BaseServer.java | 30 +-- .../com/raven/core/server/RavenServer.java | 2 +- .../java/com/raven/core/session/Session.java | 4 +- .../raven/core/session/SessionManager.java | 10 +- .../java/com/raven/interfaces/CLI/CLI.java | 112 +++++----- .../CLI/core/operator/OperatorCommands.java | 22 +- .../CLI/core/server/ServerManager.java | 6 +- .../CLI/core/session/SessionCommands.java | 44 ++-- .../CLI/core/task/TaskCommands.java | 8 +- .../CLI/module/chat/ChatManager.java | 12 +- .../interfaces/CLI/module/log/LogManager.java | 6 +- .../java/com/raven/interfaces/TeamClient.java | 209 ++++++++++++------ .../java/com/raven/interfaces/TeamServer.java | 54 ++--- .../src/main/java/com/raven/utils/Helper.java | 3 +- .../java/com/raven/utils/ServerConfig.java | 2 + .../config/raven-defaults.properties | 2 + 25 files changed, 439 insertions(+), 308 deletions(-) diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/Start.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/Start.java index fa6f668..a69d24c 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/Start.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/Start.java @@ -99,10 +99,7 @@ private static void StartInterface(String Host, int Port, ListenerMode Mode, Str case "gui" -> GUI.Launch(Config); case "teamserver" -> { int ApiPort = ParseInt(Arg(Args, "-tp", "-tport", String.valueOf(Config.GetTeamServerPort())), Config.GetTeamServerPort()); - int WebPort = ParseInt(Arg(Args, "-wp", "-web-port", "-1"), -1); - TeamServer BackendServer = new TeamServer(Config, Mode); - BackendServer.RunAsBackend(Config.GetWebHost(), ApiPort); - if (WebPort > 0) BackendServer.StartWebPanel(Config.GetWebHost(), WebPort); + new TeamServer(Config, Mode).RunAsBackend(Config.GetWebHost(), ApiPort); Thread.currentThread().join(); } case "teamserver-cli" -> { @@ -216,7 +213,7 @@ private static void RevokeAgent(String AgentId) { private static void DeployAgent(String AgentId, String CertPath, String Host, int Port, boolean UseMtls, boolean Persist, boolean Hide, String Lang) throws IOException { - String OutputDir = "IMPLANT/" + AgentId.toUpperCase(); + String OutputDir = Config.GetAgentOutputDir() + "/" + AgentId.toUpperCase(); Files.createDirectories(Paths.get(OutputDir)); Files.copy(Paths.get(CertPath), Paths.get(OutputDir + "/agent.p12"), StandardCopyOption.REPLACE_EXISTING); Files.copy(Paths.get(Config.GetCaPath()), Paths.get(OutputDir + "/ca.p12"), StandardCopyOption.REPLACE_EXISTING); diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/command/AgentCommandDispatcher.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/command/AgentCommandDispatcher.java index cc6ede9..be7dea1 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/command/AgentCommandDispatcher.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/command/AgentCommandDispatcher.java @@ -67,7 +67,9 @@ public Map BroadcastDispatch(List SessionIds, S public Map BroadcastAllDispatch(String UserCommand) { Map Results = new LinkedHashMap<>(); - for (Session S : Server.GetSessions().GetAll()) Results.put(S.GetId(), Dispatch(S.GetId(), UserCommand)); + if (Server == null || !Server.IsRunning()) return Results; + for (Session AgentSession : Server.GetSessions().GetAll()) + Results.put(AgentSession.GetId(), Dispatch(AgentSession.GetId(), UserCommand)); return Results; } diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/command/CommandDispatcher.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/command/CommandDispatcher.java index fc0f73d..d6314de 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/command/CommandDispatcher.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/command/CommandDispatcher.java @@ -313,8 +313,19 @@ public DispatchResult Dispatch(String Command, String[] Parts) { } } case "webstart" -> { - String WebHost = Parts.length > 1 ? Parts[1] : Config.GetWebHost(); - int WebPort = Parts.length > 2 ? TaskCommands.ParseIntSafe(Parts[2], Config.GetWebPort()) : Config.GetWebPort(); + String WebHost = Config.GetWebHost(); + int WebPort = Config.GetWebPort(); + for (int FlagIndex = 1; FlagIndex < Parts.length - 1; FlagIndex++) { + switch (Parts[FlagIndex].toLowerCase()) { + case "-lhost", "-host", "-h" -> { WebHost = Parts[FlagIndex + 1]; FlagIndex++; } + case "-lport", "-port", "-p" -> { WebPort = TaskCommands.ParseIntSafe(Parts[FlagIndex + 1], WebPort); FlagIndex++; } + } + } + if (Parts.length == 2 && !Parts[1].startsWith("-")) WebHost = Parts[1]; + if (Parts.length == 3 && !Parts[1].startsWith("-")) { + WebHost = Parts[1]; + WebPort = TaskCommands.ParseIntSafe(Parts[2], WebPort); + } WebPanelManager.Start(WebHost, WebPort, ServerManager.GetServer(), ServerManager.GetServerStartTime()); } case "webstop" -> WebPanelManager.Stop(); diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/command/CommandRegistry.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/command/CommandRegistry.java index fda0357..5d2a16a 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/command/CommandRegistry.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/command/CommandRegistry.java @@ -35,7 +35,7 @@ public record CommandDef(String Name, String Usage, String Description, Category Register("status", "status", "Show server mode, uptime, and database status", Category.SERVER, false); Register("logs", "logs", "Show recent server event logs", Category.SERVER, false); - Register("start", "start -lhost -lport -M ", "Start agent listener (modes: multi, raw, http, https, tls, mtls, fmtls)", Category.SERVER, false); + Register("start", "start [-lhost ] [-lport ] [-M ]", "Start agent listener modes: multi|raw|http|https|tls|mtls|fmtls flags: -h/-host/-lhost -p/-port/-lport -m/-M/-mode", Category.SERVER, false); Register("stop", "stop", "Stop the running agent listener", Category.SERVER, false); Register("sessions", "sessions", "List all active agent sessions", Category.SESSION, false); @@ -134,7 +134,7 @@ public record CommandDef(String Name, String Usage, String Description, Category Register("cloneprofile", "cloneprofile ", "Clone an existing profile under a new name", Category.PROFILE, false); Register("editprofile", "editprofile ", "Set a single key in a saved profile", Category.PROFILE, false); - Register("webstart", "webstart [host] [port]", "Start the web panel server", Category.WEB, false); + Register("webstart", "webstart [-lhost ] [-lport ]", "Start web panel flags: -h/-host/-lhost -p/-port/-lport (or positional: webstart )", Category.WEB, false); Register("webstop", "webstop", "Stop the web panel server", Category.WEB, false); Register("webstatus", "webstatus", "Show web panel current status", Category.WEB, false); } diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/command/ExportCommand.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/command/ExportCommand.java index 2b2e84b..4c6c548 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/command/ExportCommand.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/command/ExportCommand.java @@ -91,26 +91,27 @@ public void Run(String TargetStr, String FormatStr) { } } + @SuppressWarnings("unchecked") private void ExportAll(Format ExportFormat) { Map Bundle = new LinkedHashMap<>(); Bundle.put("exported_at", LocalDateTime.now().format(LogFmt)); - Bundle.put("logs", CollectLogs()); - Bundle.put("chat", CollectChat()); - Bundle.put("history", CollectHistory()); - Bundle.put("sessions", CollectSessions()); - Bundle.put("operators", CollectOperators()); - Bundle.put("notes", CollectNotes()); + Bundle.put("logs", CollectLogs()); + Bundle.put("chat", CollectChat()); + Bundle.put("history", CollectHistory()); + Bundle.put("sessions", CollectSessions()); + Bundle.put("operators", CollectOperators()); + Bundle.put("notes", CollectNotes()); if (ExportFormat == Format.JSON) { WriteRaw("export_all", "json", Gson.toJson(Bundle)); } else { StringBuilder Builder = new StringBuilder(); Builder.append("RAVEN FULL EXPORT — ").append(LocalDateTime.now().format(LogFmt)).append("\n\n"); - AppendSection(Builder, "SERVER LOGS", CollectLogs()); - AppendSection(Builder, "CHAT HISTORY", CollectChat()); - AppendSection(Builder, "COMMAND HISTORY", CollectHistory()); - AppendSection(Builder, "SESSION HISTORY", CollectSessions()); - AppendSection(Builder, "OPERATORS", CollectOperators()); - AppendSection(Builder, "AGENT NOTES", CollectNotes()); + AppendSection(Builder, "SERVER LOGS", (List>) Bundle.get("logs")); + AppendSection(Builder, "CHAT HISTORY", (List>) Bundle.get("chat")); + AppendSection(Builder, "COMMAND HISTORY", (List>) Bundle.get("history")); + AppendSection(Builder, "SESSION HISTORY", (List>) Bundle.get("sessions")); + AppendSection(Builder, "OPERATORS", (List>) Bundle.get("operators")); + AppendSection(Builder, "AGENT NOTES", (List>) Bundle.get("notes")); WriteRaw("export_all", "txt", Builder.toString()); } } diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/cryptography/CertificateManager.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/cryptography/CertificateManager.java index 1072459..14f2a65 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/cryptography/CertificateManager.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/cryptography/CertificateManager.java @@ -36,11 +36,20 @@ public CertificateManager(ServerConfig Config) { } private void EnsureDirs() { - for (String Dir : new String[] { Config.GetAgentCertDir(), Paths.get(Config.GetKeystorePath()).getParent().toString(), Paths.get(Config.GetCaPath()).getParent().toString(), Paths.get(Config.GetTruststorePath()).getParent().toString() }) { + java.util.List Dirs = new java.util.ArrayList<>(); + Dirs.add(Config.GetAgentCertDir()); + for (String PathStr : new String[] { + Config.GetKeystorePath(), + Config.GetCaPath(), + Config.GetTruststorePath() }) { + java.nio.file.Path Parent = Paths.get(PathStr).getParent(); + if (Parent != null) Dirs.add(Parent.toString()); + } + for (String Dir : Dirs) { try { Files.createDirectories(Paths.get(Dir)); - } catch (IOException E) { - Logger.Warn("Cannot create dir [" + Dir + "]: " + E.getMessage()); + } catch (IOException DirException) { + Logger.Warn("Cannot create dir [" + Dir + "]: " + DirException.getMessage()); } } } @@ -244,7 +253,8 @@ private void RemoveFromTruststore(String Alias) throws Exception { } private void SaveP12(String Path, String Password, String Alias, PrivateKey Key, X509Certificate[] Chain) throws Exception { - Files.createDirectories(Paths.get(Path).getParent()); + java.nio.file.Path Parent = Paths.get(Path).getParent(); + if (Parent != null) Files.createDirectories(Parent); KeyStore Ks = EmptyPkcs12(); Ks.setKeyEntry(Alias, Key, Password.toCharArray(), Chain); SaveKeystore(Ks, Path, Password); @@ -270,7 +280,8 @@ private void ExportPem(String Path, X509Certificate Cert, PrivateKey Key) { } private static void SaveKeystore(KeyStore Ks, String Path, String Password) throws Exception { - Files.createDirectories(Paths.get(Path).getParent()); + java.nio.file.Path Parent = Paths.get(Path).getParent(); + if (Parent != null) Files.createDirectories(Parent); try (OutputStream Out = new FileOutputStream(Path)) { Ks.store(Out, Password == null ? new char[0] : Password.toCharArray()); } diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/output/EventLog.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/output/EventLog.java index b664e78..cffd617 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/output/EventLog.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/output/EventLog.java @@ -16,15 +16,29 @@ public EventLog(int MaxEntries) { this.Entries = new CopyOnWriteArrayList<>(); } - public void Add(String Message, boolean PrintNow) { - String Entry = "[" + LocalDateTime.now().format(RavenConstants.TimestampFmt) + "] " + Message; + public void Add(String Level, String Message, boolean PrintNow) { + String Entry = "[" + LocalDateTime.now().format(RavenConstants.TimestampFmt) + "] [" + Level + "] " + Message; Entries.add(Entry); if (Entries.size() > MaxEntries) Entries.remove(0); - if (PrintNow) Logger.Info(Entry); + if (PrintNow) { + switch (Level) { + case "WARN" -> Logger.Warn(Entry); + case "ERROR" -> Logger.Error(Entry); + default -> Logger.Info(Entry); + } + } + } + + public void Add(String Level, String Message) { + Add(Level, Message, false); + } + + public void Add(String Message, boolean PrintNow) { + Add("INFO", Message, PrintNow); } public void Add(String Message) { - Add(Message, false); + Add("INFO", Message, false); } public int Count() { diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/output/Logger.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/output/Logger.java index f7e23bb..2147420 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/output/Logger.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/output/Logger.java @@ -1,13 +1,12 @@ package com.raven.core.output; -import com.raven.core.output.PromptManager; import com.raven.utils.AnsiColor; +import com.raven.utils.RavenConstants; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; -import com.raven.utils.RavenConstants; import java.time.LocalDateTime; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; @@ -15,57 +14,58 @@ public final class Logger { public enum Level { - VERBOSE, - DEBUG, - INFO, - WARN, - ERROR + VERBOSE, DEBUG, INFO, WARN, ERROR } - private static volatile Level CurrentLevel = Level.INFO; private static volatile boolean Verbose = false; - private static volatile boolean FileEnabled = false; - private static volatile String LogFilePath = "logs/raven.log"; - private static volatile int MaxEntries = 1000; + private static volatile Level CurrentLevel = Level.INFO; + private static volatile boolean Verbose = false; + private static volatile boolean FileEnabled = false; + private static volatile String LogFilePath = "logs/raven.log"; + private static volatile int MaxEntries = 1000; + private static final BlockingQueue FileQueue = new ArrayBlockingQueue<>(4096); private static Thread WriterThread; private Logger() {} - public static void Configure(String Level, boolean IsVerbose, boolean EnableFile, String FilePath, int MaxEnt) { - CurrentLevel = ParseLevel(Level); - Verbose = IsVerbose; - FileEnabled = EnableFile; - LogFilePath = FilePath; - MaxEntries = MaxEnt; + public static void Configure(String LevelName, boolean IsVerbose, boolean EnableFile, String FilePath, int MaxEnt) { + CurrentLevel = ParseLevel(LevelName); + Verbose = IsVerbose; + FileEnabled = EnableFile; + LogFilePath = FilePath; + MaxEntries = MaxEnt; if (EnableFile) StartFileWriter(FilePath); } - private static Level ParseLevel(String LogLevel) { + private static Level ParseLevel(String LevelName) { try { - return Level.valueOf(LogLevel.toUpperCase()); - } catch (Exception E) { + return Level.valueOf(LevelName.toUpperCase()); + } catch (Exception Ignored) { return Level.INFO; } } private static void StartFileWriter(String Path) { - try { - Files.createDirectories(Paths.get(Path).getParent()); - } catch (Exception Ignored) {} + java.nio.file.Path Parent = Paths.get(Path).getParent(); + if (Parent != null) { + try { Files.createDirectories(Parent); } catch (Exception Ignored) {} + } WriterThread = new Thread(() -> { - try (BufferedWriter StrObject = new BufferedWriter(new FileWriter(Path, true))) { + try (BufferedWriter Writer = new BufferedWriter(new FileWriter(Path, true))) { while (!Thread.currentThread().isInterrupted()) { try { - StrObject.write(FileQueue.take()); - StrObject.newLine(); - StrObject.flush(); - } catch (InterruptedException E) { + Writer.write(FileQueue.take()); + Writer.newLine(); + Writer.flush(); + } catch (InterruptedException InterruptedException) { Thread.currentThread().interrupt(); break; } } } catch (IOException WriteException) { - PromptManager.PrintLine("[ERROR] Log file writer failed: " + WriteException.getMessage()); + PromptManager.PrintLine( + AnsiColor.White + "[" + AnsiColor.Red + "ERROR" + AnsiColor.White + "] " + + "Log file writer failed: " + WriteException.getMessage() + AnsiColor.Reset); } }, "LogFileWriter"); WriterThread.setDaemon(true); @@ -76,34 +76,34 @@ private static String Timestamp() { return LocalDateTime.now().format(RavenConstants.TimestampFmt); } - private static String Format(String Message, Object[] Args) { - if (Args == null || Args.length == 0) return Message; + private static String Format(String Message, Object... Args) { + if (Args == null || Args.length == 0) return Message.replace("%n", System.lineSeparator()); try { return String.format(Message, Args); - } catch (java.util.IllegalFormatException E) { - return Message + " [FORMAT_ERROR: " + E.getMessage() + "]"; + } catch (java.util.IllegalFormatException FormatException) { + return Message + " [FORMAT_ERROR: " + FormatException.getMessage() + "]"; } } - private static void Emit(Level MessageLevel, String PlainTag, String ColorCode, String Message, Object[] Args) { + private static void Emit(Level MessageLevel, String PlainTag, String LevelColor, String Message, Object[] Args) { if (MessageLevel.ordinal() < CurrentLevel.ordinal()) return; - String Formatted = Format(Message, Args); - String ColorLine = ColorCode + "[" + PlainTag + "]" + AnsiColor.Reset + " " + Formatted; + String Formatted = Format(Message, Args); + String ColorLine = AnsiColor.White + "[" + LevelColor + PlainTag + AnsiColor.White + "] " + Formatted + AnsiColor.Reset; String PlainLine = "[" + Timestamp() + "] [" + PlainTag + "] " + Formatted; PromptManager.PrintLine(ColorLine); if (FileEnabled) FileQueue.offer(PlainLine); } public static void Info(String Message, Object... Args) { - Emit(Level.INFO, "INFO", AnsiColor.Cyan, Message, Args); + Emit(Level.INFO, "INFO", AnsiColor.Blue, Message, Args); } public static void Warn(String Message, Object... Args) { - Emit(Level.WARN, "WARN", AnsiColor.Orange, Message, Args); + Emit(Level.WARN, "WARN", AnsiColor.Yellow, Message, Args); } public static void Error(String Message, Object... Args) { - Emit(Level.ERROR, "ERROR", AnsiColor.BrightRed, Message, Args); + Emit(Level.ERROR, "ERROR", AnsiColor.Red, Message, Args); } public static void Debug(String Message, Object... Args) { @@ -114,13 +114,18 @@ public static void Success(String Message, Object... Args) { Emit(Level.INFO, "OK", AnsiColor.Green, Message, Args); } + public static void Ok(String Message, Object... Args) { + Emit(Level.INFO, "OK", AnsiColor.Green, Message, Args); + } + public static void Verbose(String Message, Object... Args) { if (!Verbose) return; Emit(Level.VERBOSE, "TRACE", AnsiColor.Dim, Message, Args); } public static void Custom(String Text) { - System.out.println(Text); + System.out.print(Format(Text)); + System.out.flush(); } public static void Custom(String Text, Object... Args) { @@ -129,11 +134,11 @@ public static void Custom(String Text, Object... Args) { } public static void Custom(String Text, long DelayMs) { - System.out.println(Text); + System.out.print(Format(Text)); + System.out.flush(); if (DelayMs > 0) { - try { - Thread.sleep(DelayMs); - } catch (InterruptedException Ignored) {} + try { Thread.sleep(DelayMs); } + catch (InterruptedException InterruptedException) { Thread.currentThread().interrupt(); } } } diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/output/PromptManager.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/output/PromptManager.java index 9b7713c..cdab280 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/output/PromptManager.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/output/PromptManager.java @@ -4,22 +4,31 @@ public final class PromptManager { - private static volatile String ActivePrompt = ""; - private static final AtomicBoolean PromptVisible = new AtomicBoolean(false); + private static volatile String ActivePrompt = ""; + private static volatile int PromptLineCount = 1; + private static final AtomicBoolean PromptVisible = new AtomicBoolean(false); private PromptManager() {} public static void SetPrompt(String FullPrompt) { - ActivePrompt = FullPrompt; + ActivePrompt = FullPrompt; + PromptLineCount = (int) FullPrompt.chars().filter(Character -> Character == '\n').count() + 1; } public static void MarkVisible(boolean Visible) { PromptVisible.set(Visible); } + public static boolean IsActive() { + return PromptVisible.get(); + } + public static synchronized void PrintLine(String Line) { if (PromptVisible.get()) { - System.out.print("\r\033[2K"); + for (int LineIndex = 1; LineIndex < PromptLineCount; LineIndex++) { + System.out.print("\033[1A"); + } + System.out.print("\r\033[J"); System.out.println(Line); System.out.print(ActivePrompt); System.out.flush(); @@ -27,4 +36,17 @@ public static synchronized void PrintLine(String Line) { System.out.println(Line); } } + + public static synchronized void Redraw() { + System.out.print(ActivePrompt); + System.out.flush(); + } + + public static synchronized void Erase() { + for (int LineIndex = 1; LineIndex < PromptLineCount; LineIndex++) { + System.out.print("\033[1A"); + } + System.out.print("\r\033[J"); + System.out.flush(); + } } diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/server/BaseServer.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/server/BaseServer.java index f6bf73e..d427a54 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/server/BaseServer.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/server/BaseServer.java @@ -474,22 +474,15 @@ protected byte[] ReadFramedResponse(Socket Sock, int TimeoutMs, SymmetricCryptog public Map BroadcastCommand(List SessionIds, String Command) { Map Results = new ConcurrentHashMap<>(); - java.util.concurrent.ExecutorService BroadcastPool = java.util.concurrent.Executors.newCachedThreadPool(Task -> { - Thread Worker = new Thread(Task, "BroadcastWorker"); - Worker.setDaemon(true); - return Worker; - }); List> Futures = new ArrayList<>(); for (int Id : SessionIds) { - CompletableFuture Future = CompletableFuture.runAsync(() -> Results.put(Id, ExecuteCommand(Id, Command)), BroadcastPool); - Futures.add(Future); + Futures.add(CompletableFuture.runAsync(() -> Results.put(Id, ExecuteCommand(Id, Command)))); } try { - CompletableFuture.allOf(Futures.toArray(new CompletableFuture[0])).get(Config.GetCommandTimeout() + 5000, TimeUnit.MILLISECONDS); - } catch (Exception E) { - Logger.Warn("Broadcast partial timeout: " + E.getMessage()); - } finally { - BroadcastPool.shutdownNow(); + CompletableFuture.allOf(Futures.toArray(new CompletableFuture[0])) + .get(Config.GetCommandTimeout() + 5000L, TimeUnit.MILLISECONDS); + } catch (Exception Exception) { + Logger.Warn("Broadcast partial timeout: " + Exception.getMessage()); } return Results; } @@ -561,7 +554,7 @@ private String[] HandleUpload(Session S, String Command) { synchronized (SLck) { Out.write(CmdFrame); Out.flush(); - Thread.sleep(300); + try { Thread.sleep(300); } catch (InterruptedException IntEx) { Thread.currentThread().interrupt(); throw new java.io.IOException("Upload interrupted"); } byte[] Data = Files.readAllBytes(Paths.get(Local)); Map Meta = new LinkedHashMap<>(); Meta.put("type", "file"); @@ -571,7 +564,7 @@ private String[] HandleUpload(Session S, String Command) { Out.write(MetaEnc); Out.write(MetaMarker); Out.flush(); - Thread.sleep(100); + try { Thread.sleep(100); } catch (InterruptedException IntEx) { Thread.currentThread().interrupt(); throw new java.io.IOException("Upload interrupted"); } Out.write(Data); Out.write(EndMarker); Out.flush(); @@ -601,9 +594,10 @@ private String[] SendThenDownload(Session S, String Command) { private String[] HandleDownload(Session S, SymmetricCryptography Crypto) { try { + int DownloadTimeout = Config.GetCommandTimeout(); ByteArrayOutputStream Buf = new ByteArrayOutputStream(); byte[] Tmp = new byte[Config.GetBufferSize()]; - S.GetSocket().setSoTimeout(30_000); + S.GetSocket().setSoTimeout(DownloadTimeout); while (true) { int N; try { @@ -627,7 +621,7 @@ private String[] HandleDownload(Session S, SymmetricCryptography Crypto) { String Filename = (String) Meta.getOrDefault("filename", "received_file"); ByteArrayOutputStream FileBuf = new ByteArrayOutputStream(); FileBuf.write(Rest); - S.GetSocket().setSoTimeout(30_000); + S.GetSocket().setSoTimeout(DownloadTimeout); while (!EndsWith(FileBuf.toByteArray(), EndMarker)) { int N; try { @@ -653,7 +647,7 @@ private String[] HandleDownload(Session S, SymmetricCryptography Crypto) { protected String SaveFile(String Filename, byte[] Data, int SessionId) { try { - Path Dir = Paths.get("Downloads/Session_" + SessionId); + Path Dir = Paths.get(Config.GetDownloadDir()).resolve("Session_" + SessionId); Files.createDirectories(Dir); String Base = Filename, Ext = ""; @@ -707,7 +701,7 @@ private static String CleanRawOutput(String Raw, String SentCommand) { } public void RemoveSession(int SessionId) { - Sessions.Remove(SessionId); + if (!Sessions.Remove(SessionId)) return; CommandLocks.remove(SessionId); SocketLocks.remove(SessionId); SessionCryptos.remove(SessionId); diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/server/RavenServer.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/server/RavenServer.java index f46d985..35afb2d 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/server/RavenServer.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/server/RavenServer.java @@ -215,7 +215,7 @@ private void HandleTcp(Socket Client) { CloseQuietly(Client); return; } - HandleBeacon(Client, false); + HandleBeacon(Client, Client instanceof SSLSocket); } default -> { Logger.Warn("unknown protocol from " + RemoteAddr + " — dropping"); diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/session/Session.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/session/Session.java index 0bc4c5f..cbc8018 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/session/Session.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/session/Session.java @@ -54,8 +54,8 @@ public Session() { CertCn = "N/A"; AgentId = GenerateAgentId(); SessionKey = GenerateSessionKey(); - SleepIntervalMs = 5000; - JitterMs = 1000; + SleepIntervalMs = 0; + JitterMs = 0; } private static String GenerateAgentId() { diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/session/SessionManager.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/session/SessionManager.java index 64c25b2..4d259ee 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/session/SessionManager.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/core/session/SessionManager.java @@ -20,13 +20,11 @@ public Optional Get(int Id) { return Optional.ofNullable(Sessions.get(Id)); } - public void Remove(int Id) { + public boolean Remove(int Id) { Session S = Sessions.remove(Id); - if (S != null) { - try { - S.GetSocket().close(); - } catch (Exception Ignored) {} - } + if (S == null) return false; + try { S.GetSocket().close(); } catch (Exception Ignored) {} + return true; } public List GetAll() { diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/CLI.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/CLI.java index 97c6c2b..3330d19 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/CLI.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/CLI.java @@ -84,8 +84,8 @@ public void Run(String Host, int Port, ListenerMode Mode) { } private boolean Login(BufferedReader Reader) { - System.out.println(TerminalHelper.Box("TEAMSERVER LOGIN")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("TEAMSERVER LOGIN")); + Logger.Custom("%n"); Logger.Custom(" %sDefault: admin / admin (change after first login)%s%n%n", AnsiColor.White, AnsiColor.Reset); for (int Try = 1; Try <= 3; Try++) { try { @@ -194,7 +194,7 @@ private void RunLoop() { Logger.Info(Current - LastCount + " new event(s) - type 'logs' to view"); LastCount = Current; } - System.out.println(); + Logger.Custom("%n"); System.out.println(PromptTop); System.out.print(PromptBottom); System.out.flush(); @@ -227,8 +227,8 @@ private int Dispatch(String Cmd, String[] P) { } case "status" -> { long Uptime = ServerStartTime != null ? java.time.Duration.between(ServerStartTime, java.time.Instant.now()).getSeconds() : 0; - System.out.println(TerminalHelper.Box("SERVER STATUS")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("SERVER STATUS")); + Logger.Custom("%n"); if (Server != null && Server.IsRunning()) { Logger.Custom(" %sStatus %sONLINE%n", AnsiColor.Red, AnsiColor.Green); Logger.Custom(" %sMode %s%s%n", AnsiColor.Red, AnsiColor.White, ActiveMode.name()); @@ -242,12 +242,12 @@ private int Dispatch(String Cmd, String[] P) { if (IsTeamMode) Logger.Custom(" %sOperator %s%s [%s]%n%n", AnsiColor.Red, AnsiColor.White, OperatorName, CurrentRole); } case "logs" -> { - System.out.println(TerminalHelper.Box("RECENT LOGS")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("RECENT LOGS")); + Logger.Custom("%n"); List Entries = Log.GetLast(30); if (Entries.isEmpty()) Logger.Info(" no logs"); else Entries.forEach(Entry -> Logger.Custom(" %s%s%s%n", AnsiColor.White, Entry, AnsiColor.Reset)); - System.out.println(); + Logger.Custom("%n"); return 1; } case "webstart" -> { @@ -413,15 +413,15 @@ private int Dispatch(String Cmd, String[] P) { case "sessions-history", "sesshistory" -> { int Limit = P.length > 1 ? Helper.ParseInt(P[1], 50) : 50; List> Sessions = Db.GetSessionHistory(Limit); - System.out.println(TerminalHelper.Box("SESSION HISTORY (last " + Limit + ")")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("SESSION HISTORY (last " + Limit + ")")); + Logger.Custom("%n"); if (Sessions.isEmpty()) { Logger.Info(" no session history"); - System.out.println(); + Logger.Custom("%n"); break; } Sessions.forEach(Session -> Logger.Custom(" %s%s%s%n", AnsiColor.White, Session, AnsiColor.Reset)); - System.out.println(); + Logger.Custom("%n"); } case "note" -> { if (P.length < 3) { @@ -580,11 +580,11 @@ private int Dispatch(String Cmd, String[] P) { } case "profiles" -> { List ProfileList = ProfileManager.ListProfiles(); - System.out.println(TerminalHelper.Box("SAVED PROFILES (" + ProfileList.size() + ")")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("SAVED PROFILES (" + ProfileList.size() + ")")); + Logger.Custom("%n"); if (ProfileList.isEmpty()) { Logger.Info(" no profiles found"); - System.out.println(); + Logger.Custom("%n"); break; } for (String ProfileName : ProfileList) { @@ -593,7 +593,7 @@ private int Dispatch(String Cmd, String[] P) { String Mark = ProfileName.equals(ActiveProfileName) ? AnsiColor.Green + " ◀ active" + AnsiColor.Reset : ""; Logger.Custom(" %s%-20s%s %s%s%n", AnsiColor.White, ProfileName, AnsiColor.Reset, Desc, Mark); } - System.out.println(); + Logger.Custom("%n"); } case "profile" -> { String ViewName = P.length > 1 ? P[1] : ActiveProfileName; @@ -603,8 +603,8 @@ private int Dispatch(String Cmd, String[] P) { break; } var ActiveProfile = ProfileOpt.get(); - System.out.println(TerminalHelper.Box("PROFILE — " + ViewName)); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("PROFILE — " + ViewName)); + Logger.Custom("%n"); Logger.Custom(" %sName %s%s%n", AnsiColor.Red, AnsiColor.White, ActiveProfile.Name()); Logger.Custom(" %sDescription%s %s%n", AnsiColor.Red, AnsiColor.White, ActiveProfile.Description()); Logger.Custom(" %sCreated %s%s%n%n", AnsiColor.Red, AnsiColor.White, ActiveProfile.CreatedAt()); @@ -612,7 +612,7 @@ private int Dispatch(String Cmd, String[] P) { String KeyStr = Key.toString(); if (!KeyStr.startsWith("profile.")) Logger.Custom(" %s%-36s%s %s%n", AnsiColor.Red, KeyStr, AnsiColor.White, Value); }); - System.out.println(); + Logger.Custom("%n"); } case "loadprofile" -> { if (P.length < 2) { @@ -721,8 +721,8 @@ private int Dispatch(String Cmd, String[] P) { } private void ShowHelp() { - System.out.println(TerminalHelper.Box("COMMAND REFERENCE")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("COMMAND REFERENCE")); + Logger.Custom("%n"); if (IsTeamMode && OperatorName != null) { Logger.Custom(" %s[TEAMSERVER]%s Operator: %s%s%s Role: %s%s%s%n", AnsiColor.Red, AnsiColor.Reset, AnsiColor.White, OperatorName, AnsiColor.Reset, AnsiColor.White, CurrentRole != null ? CurrentRole.name() : "?", AnsiColor.Reset); if (CurrentRole != null) Logger.Custom(" %sPermissions:%s %s%n%n", AnsiColor.Red, AnsiColor.White, CurrentRole.PermissionString()); @@ -735,7 +735,7 @@ private void ShowHelp() { if (Def.RequireTeamMode() && !IsTeamMode) continue; Logger.Custom(" %s%-42s%s %s%n", AnsiColor.White, Def.Usage(), AnsiColor.Reset, Def.Description()); } - System.out.println(); + Logger.Custom("%n"); } } @@ -745,19 +745,19 @@ private void ShowSessions() { return; } List All = Server.GetSessions().GetAll(); - System.out.println(TerminalHelper.Box("ACTIVE SESSIONS (" + All.size() + ")")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("ACTIVE SESSIONS (" + All.size() + ")")); + Logger.Custom("%n"); if (All.isEmpty()) { Logger.Info(" no active sessions"); - System.out.println(); + Logger.Custom("%n"); return; } Logger.Custom(" %s%-5s %-14s %-16s %-14s %-10s %-10s %s%s%n", AnsiColor.Red, "ID", "NAME", "IP", "TYPE", "OS", "USER", "KEY", AnsiColor.Reset); - System.out.println(TerminalHelper.Divider()); + Logger.Custom("%s%n", TerminalHelper.Divider()); for (Session S : All) { Logger.Custom(" %s#%-4d %-14s %-16s %-14s %-10s %-10s %s%s%n", AnsiColor.White, S.GetId(), TerminalHelper.Truncate(S.GetAgentName(), 14), TerminalHelper.Truncate(S.GetAgentIp(), 16), S.GetSessionType().name(), TerminalHelper.Truncate(S.GetOs(), 10), TerminalHelper.Truncate(S.GetUser(), 10), S.GetSessionKey(), AnsiColor.Reset); } - System.out.println(); + Logger.Custom("%n"); } private void ShowStats() { @@ -766,17 +766,17 @@ private void ShowStats() { return; } int Count = Server.GetSessions().Count(); - System.out.println(TerminalHelper.Box("SESSION STATS")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("SESSION STATS")); + Logger.Custom("%n"); Logger.Custom(" %sTotal Active%s %d%n", AnsiColor.Red, AnsiColor.White, Count); - System.out.println(); + Logger.Custom("%n"); } private void ShowTasks() { - System.out.println(TerminalHelper.Box("TASK QUEUE")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("TASK QUEUE")); + Logger.Custom("%n"); Logger.Info(" (task queue display not implemented — extend here)"); - System.out.println(); + Logger.Custom("%n"); } private void ShowSessionInfo(int Id) { @@ -789,8 +789,8 @@ private void ShowSessionInfo(int Id) { Logger.Warn("session not found: " + Id); return; } - System.out.println(TerminalHelper.Box("SESSION INFO — #" + Id)); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("SESSION INFO — #" + Id)); + Logger.Custom("%n"); Logger.Custom(" %sID %s%d%n", AnsiColor.Red, AnsiColor.White, S.GetId()); Logger.Custom(" %sName %s%s%n", AnsiColor.Red, AnsiColor.White, S.GetAgentName()); Logger.Custom(" %sHostname %s%s%n", AnsiColor.Red, AnsiColor.White, S.GetHostname()); @@ -803,7 +803,7 @@ private void ShowSessionInfo(int Id) { Logger.Custom(" %smTLS %s%b%n", AnsiColor.Red, AnsiColor.White, S.IsMtlsEnabled()); Logger.Custom(" %sJoined %s%s%n", AnsiColor.Red, AnsiColor.White, S.GetJoinedAt()); Logger.Custom(" %sNote %s%s%n", AnsiColor.Red, AnsiColor.White, Db.GetAgentNote(Id)); - System.out.println(); + Logger.Custom("%n"); } private void Interactive(int Id) { @@ -841,9 +841,9 @@ private void Execute(int SessionId, String UserCommand) { } AddLog("[>] [" + OperatorName + "] session-" + SessionId + " » " + UserCommand, false); CommandResult Result = new AgentCommandDispatcher(Server, Db, OperatorName).Dispatch(SessionId, UserCommand); - if (Result.Success()) System.out.println(TerminalHelper.OutputBox(Result.Output())); + if (Result.Success()) Logger.Custom("%s%n", TerminalHelper.OutputBox(Result.Output())); else Logger.Error(Result.Output()); - System.out.println(); + Logger.Custom("%n"); } private void Broadcast(List Ids, String UserCommand) { @@ -868,48 +868,48 @@ private void BroadcastAll(String UserCommand) { private void ShowCommandHistory(int AgentId, int Limit) { List> Hist = Db.GetCommandHistory(AgentId, Limit); - System.out.println(TerminalHelper.Box("COMMAND HISTORY (last " + Limit + (AgentId > 0 ? " — session-" + AgentId : "") + ")")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("COMMAND HISTORY (last " + Limit + (AgentId > 0 ? " — session-" + AgentId : "") + ")")); + Logger.Custom("%n"); if (Hist.isEmpty()) { Logger.Info(" no history"); - System.out.println(); + Logger.Custom("%n"); return; } Logger.Custom(" %s%-5s %-12s %-10s %-36s %s%s%n", AnsiColor.Red, "SID", "OPERATOR", "STATUS", "COMMAND", "TIMESTAMP", AnsiColor.Reset); - System.out.println(TerminalHelper.Divider()); + Logger.Custom("%s%n", TerminalHelper.Divider()); for (Map H : Hist) { boolean Ok = Boolean.parseBoolean(H.getOrDefault("Success", "false").toString()); String Cmd = TerminalHelper.Truncate(H.getOrDefault("Command", "").toString(), 36); Logger.Custom(" %s%-5s %-12s %s%-10s%s %-36s %s%s%n", AnsiColor.White, H.getOrDefault("AgentId", "?"), TerminalHelper.Truncate(H.getOrDefault("Operator", "?").toString(), 12), Ok ? AnsiColor.Green : AnsiColor.Red, Ok ? "✔ ok" : "✘ fail", AnsiColor.White, Cmd, H.getOrDefault("Timestamp", ""), AnsiColor.Reset); } - System.out.println(); + Logger.Custom("%n"); } private void ShowOperators() { List> Ops = Db.GetOperators(); - System.out.println(TerminalHelper.Box("OPERATORS (" + Ops.size() + ")")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("OPERATORS (" + Ops.size() + ")")); + Logger.Custom("%n"); Logger.Custom(" %s%-18s %-14s %-30s %-20s%s%n", AnsiColor.Green, "USERNAME", "ROLE", "PERMISSIONS", "LAST SEEN", AnsiColor.Reset); - System.out.println(TerminalHelper.Divider()); + Logger.Custom("%s%n", TerminalHelper.Divider()); for (Map Op : Ops) { OperatorRole R = OperatorRole.FromString(Op.get("Role").toString()); boolean Me = Op.get("Username").toString().equals(OperatorName); String Tag = Me ? AnsiColor.Green + " ◀ YOU" + AnsiColor.White : ""; Logger.Custom(" %s%-18s %-14s %-30s %-20s%s%s%n", AnsiColor.White, Op.get("Username"), R.name(), R.PermissionString(), Op.getOrDefault("LastSeen", "Never"), Tag, AnsiColor.Reset); } - System.out.println(); + Logger.Custom("%n"); Logger.Custom(" %sRole Reference:%s%n", AnsiColor.Red, AnsiColor.Reset); for (OperatorRole R : OperatorRole.values()) Logger.Custom(" %s%-14s%s %s%n", AnsiColor.White, R.name(), AnsiColor.Reset, R.PermissionString()); - System.out.println(); + Logger.Custom("%n"); } private void ShowChat() { List> Msgs = Db.GetChatLogs(100); - System.out.println(TerminalHelper.Box("CHAT MESSAGES")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("CHAT MESSAGES")); + Logger.Custom("%n"); if (Msgs.isEmpty()) { Logger.Info(" no messages"); - System.out.println(); + Logger.Custom("%n"); return; } for (Map M : Msgs) { @@ -920,16 +920,16 @@ private void ShowChat() { boolean Mine = From.equals(OperatorName); Logger.Custom(" %s[%s] %s%s%s [%s]: %s%s%n", Mine ? AnsiColor.Green : AnsiColor.White, Ts, Mine ? AnsiColor.Green : AnsiColor.Red, From, AnsiColor.Reset, To.equals("all") ? "all" : "→ " + To, M.getOrDefault("Message", ""), AnsiColor.Reset); } - System.out.println(); + Logger.Custom("%n"); } private void ShowChatHistory(int Limit) { List> Msgs = Db.GetChatLogs(Limit); - System.out.println(TerminalHelper.Box("CHAT HISTORY (DB — last " + Limit + ")")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("CHAT HISTORY (DB — last " + Limit + ")")); + Logger.Custom("%n"); if (Msgs.isEmpty()) { Logger.Info(" no chat history"); - System.out.println(); + Logger.Custom("%n"); return; } for (Map M : Msgs) { @@ -940,7 +940,7 @@ private void ShowChatHistory(int Limit) { boolean Mine = From.equals(OperatorName); Logger.Custom(" %s[%s] %s%s%s [%s]: %s%s%n", Mine ? AnsiColor.Green : AnsiColor.White, Ts, Mine ? AnsiColor.Green : AnsiColor.Red, From, AnsiColor.Reset, To.equals("all") ? "all" : "→ " + To, M.getOrDefault("Message", ""), AnsiColor.Reset); } - System.out.println(); + Logger.Custom("%n"); } private void Shutdown() { diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/core/operator/OperatorCommands.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/core/operator/OperatorCommands.java index e56c54c..452da2a 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/core/operator/OperatorCommands.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/core/operator/OperatorCommands.java @@ -49,8 +49,8 @@ public boolean CanExecute() { } public boolean Login(BufferedReader Reader) throws IOException { - System.out.println(TerminalHelper.Box("TEAMSERVER LOGIN")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("TEAMSERVER LOGIN")); + Logger.Custom("%n"); Logger.Custom(" %sDefault credentials: admin / admin (change after first login)%s%n%n", AnsiColor.White, AnsiColor.Reset); for (int Attempt = 1; Attempt <= 3; Attempt++) { @@ -91,23 +91,23 @@ public boolean Login(BufferedReader Reader) throws IOException { } public void ShowHelp() { - System.out.println(TerminalHelper.Box("COMMAND REFERENCE")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("COMMAND REFERENCE")); + Logger.Custom("%n"); CLIBanner.Print(); if (IsTeamServerMode && OperatorName != null) { - System.out.println(); + Logger.Custom("%n"); Logger.Custom(" %s[TEAMSERVER MODE]%s Operator: %s%s%s Role: %s%s%s%n", AnsiColor.Red, AnsiColor.Reset, AnsiColor.White, OperatorName, AnsiColor.Reset, AnsiColor.White, OperatorRoleValue != null ? OperatorRoleValue.name() : "?", AnsiColor.Reset); if (OperatorRoleValue != null) Logger.Custom(" %sPermissions:%s %s%n", AnsiColor.Red, AnsiColor.White, OperatorRoleValue.PermissionString()); } - System.out.println(); + Logger.Custom("%n"); } public void ShowOperators() { List> Operators = Database.GetOperators(); - System.out.println(TerminalHelper.Box("OPERATORS (" + Operators.size() + ")")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("OPERATORS (" + Operators.size() + ")")); + Logger.Custom("%n"); Logger.Custom(" %s%-18s %-14s %-30s %-20s%s%n", AnsiColor.Green, "USERNAME", "ROLE", "PERMISSIONS", "LAST SEEN", AnsiColor.Reset); - System.out.println(TerminalHelper.Divider()); + Logger.Custom("%s%n", TerminalHelper.Divider()); for (Map Operator : Operators) { OperatorRole Role = OperatorRole.FromString(Operator.get("Role").toString()); @@ -116,10 +116,10 @@ public void ShowOperators() { Logger.Custom(" %s%-18s %-14s %-30s %-20s%s%s%n", AnsiColor.White, Operator.get("Username"), Role.name(), Role.PermissionString(), Operator.getOrDefault("LastSeen", "Never"), Mark, AnsiColor.Reset); } - System.out.println(); + Logger.Custom("%n"); Logger.Custom(" %sRole Reference:%s%n", AnsiColor.Red, AnsiColor.Reset); for (OperatorRole Role : OperatorRole.values()) Logger.Custom(" %s%-14s%s %s%n", AnsiColor.White, Role.name(), AnsiColor.Reset, Role.PermissionString()); - System.out.println(); + Logger.Custom("%n"); } public void AddOperator(String Username, String Password, String RoleName, String AdminUsername) { diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/core/server/ServerManager.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/core/server/ServerManager.java index b167ff9..239cc6e 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/core/server/ServerManager.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/core/server/ServerManager.java @@ -103,8 +103,8 @@ public void ShowStatus(String DatabaseState, String DatabaseType) { long UptimeSeconds = ServerStartTime != null ? Duration.between(ServerStartTime, Instant.now()).getSeconds() : 0; - System.out.println(TerminalHelper.Box("SERVER STATUS")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("SERVER STATUS")); + Logger.Custom("%n"); if (Server == null || !Server.IsRunning()) { if (IsTeamServerMode && ServerStartTime != null) { @@ -127,7 +127,7 @@ public void ShowStatus(String DatabaseState, String DatabaseType) { Logger.Custom(" %sDatabase %s%s (%s)%n", AnsiColor.Red, AnsiColor.White, DatabaseState, DatabaseType); if (IsTeamServerMode && OperatorName != null) Logger.Custom(" %sOperator %s%s%n", AnsiColor.Red, AnsiColor.White, OperatorName); - System.out.println(); + Logger.Custom("%n"); } private void HandleEvent(EventType Type, Map Data) { diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/core/session/SessionCommands.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/core/session/SessionCommands.java index 8ba0f25..fec57c6 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/core/session/SessionCommands.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/core/session/SessionCommands.java @@ -34,8 +34,8 @@ public SessionCommands(LogManager LogManager, TeamDatabase Database) { public int GetCurrentSessionId() { return CurrentSessionId; } public void ShowSessions() { - System.out.println(TerminalHelper.Box("ACTIVE SESSIONS")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("ACTIVE SESSIONS")); + Logger.Custom("%n"); if (Server == null) { Logger.Info("running in cross-process mode - session list unavailable."); @@ -48,7 +48,7 @@ public void ShowSessions() { Logger.Custom(" %s%-5s %-14s %-14s %-16s %-10s %-10s %s%s%n", AnsiColor.Blue, "ID", "NAME/CERT", "TYPE", "IP", "OS", "USER", "SESSION-KEY", AnsiColor.Reset); - System.out.println(TerminalHelper.Divider()); + Logger.Custom("%s%n", TerminalHelper.Divider()); for (Session ActiveSession : Sessions) { String DisplayName = ActiveSession.GetDisplayName(); @@ -64,7 +64,7 @@ public void ShowSessions() { ActiveSession.GetSessionKey(), AnsiColor.Reset); } - System.out.println(); + Logger.Custom("%n"); } public void ShowSessionInfo(int SessionId) { @@ -73,8 +73,8 @@ public void ShowSessionInfo(int SessionId) { if (Found.isEmpty()) { Logger.Warn("session not found"); return; } Session ActiveSession = Found.get(); - System.out.println(TerminalHelper.Box("SESSION INFO - #" + SessionId)); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("SESSION INFO - #" + SessionId)); + Logger.Custom("%n"); Logger.Custom(" %sID %s%d%n", AnsiColor.Red, AnsiColor.White, ActiveSession.GetId()); Logger.Custom(" %sName %s%s%n", AnsiColor.Red, AnsiColor.White, ActiveSession.GetDisplayName()); Logger.Custom(" %sType %s%s%n", AnsiColor.Red, AnsiColor.White, ActiveSession.GetSessionType().name()); @@ -90,15 +90,15 @@ public void ShowSessionInfo(int SessionId) { Logger.Custom(" %sShell Mode %s%s%n", AnsiColor.Red, AnsiColor.White, ActiveSession.GetShellMode()); String Note = Database.GetAgentNote(SessionId); Logger.Custom(" %sNote %s%s%n", AnsiColor.Red, AnsiColor.White, Note.isEmpty() ? "(none)" : Note); - System.out.println(); + Logger.Custom("%n"); } public void ShowStats() { - System.out.println(TerminalHelper.Box("SESSION STATISTICS")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("SESSION STATISTICS")); + Logger.Custom("%n"); if (Server == null) { Logger.Custom(" %sSessions %s(N/A - cross-process mode)%n", AnsiColor.Red, AnsiColor.White); - System.out.println(); + Logger.Custom("%n"); return; } Map Stats = Server.GetSessions().GetStats(); @@ -106,7 +106,7 @@ public void ShowStats() { Logger.Custom(" %sTotal %s%d%n", AnsiColor.Red, AnsiColor.White, Stats.get("Total")); Logger.Custom(" %sRaven %s%d%n", AnsiColor.Red, AnsiColor.White, Stats.get("RAVEN")); Logger.Custom(" %sRaw %s%d%n", AnsiColor.Red, AnsiColor.White, Stats.get("ReverseShell")); - System.out.println(); + Logger.Custom("%n"); } public void Execute(int SessionId, String Command) { @@ -116,7 +116,7 @@ public void Execute(int SessionId, String Command) { boolean Success = Boolean.parseBoolean(Result[0]); if (Success) { - System.out.println(TerminalHelper.OutputBox(Result[1])); + Logger.Custom("%s%n", TerminalHelper.OutputBox(Result[1])); LogManager.Add(AnsiColor.Green + "session-" + SessionId + " OK" + AnsiColor.Reset, false); } else { Logger.Info(Result[1]); @@ -130,12 +130,12 @@ public void Broadcast(List SessionIds, String Command) { String Operator = OperatorName != null ? OperatorName : "operator"; Logger.Custom(" broadcasting to %d session(s): %s%n", SessionIds.size(), Command); Map Results = Server.BroadcastCommand(SessionIds, Command); - System.out.println(TerminalHelper.Box("BROADCAST RESULTS - " + Results.size() + " sessions")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("BROADCAST RESULTS - " + Results.size() + " sessions")); + Logger.Custom("%n"); for (Map.Entry Entry : Results.entrySet()) { boolean Success = Boolean.parseBoolean(Entry.getValue()[0]); Logger.Custom(" %ssession-%-3d %s%n", Success ? AnsiColor.Green : AnsiColor.Red, Entry.getKey(), AnsiColor.Reset); - System.out.println(TerminalHelper.OutputBox(Entry.getValue()[1])); + Logger.Custom("%s%n", TerminalHelper.OutputBox(Entry.getValue()[1])); Database.SaveCommandLog(Entry.getKey(), Operator, Command, Entry.getValue()[1], Success); } } @@ -147,12 +147,12 @@ public void BroadcastAll(String Command) { String Operator = OperatorName != null ? OperatorName : "operator"; Logger.Custom(" broadcasting to all %d session(s): %s%n", Total, Command); Map Results = Server.BroadcastAll(Command); - System.out.println(TerminalHelper.Box("BROADCAST-ALL RESULTS")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("BROADCAST-ALL RESULTS")); + Logger.Custom("%n"); for (Map.Entry Entry : Results.entrySet()) { boolean Success = Boolean.parseBoolean(Entry.getValue()[0]); Logger.Custom(" %ssession-%-3d %s%n", Success ? AnsiColor.Green : AnsiColor.Red, Entry.getKey(), AnsiColor.Reset); - System.out.println(TerminalHelper.OutputBox(Entry.getValue()[1])); + Logger.Custom("%s%n", TerminalHelper.OutputBox(Entry.getValue()[1])); Database.SaveCommandLog(Entry.getKey(), Operator, Command, Entry.getValue()[1], Success); } } @@ -163,7 +163,7 @@ public void Interactive(int SessionId) { if (Found.isEmpty()) { Logger.Warn("session not found"); return; } Session ActiveSession = Found.get(); - System.out.println(TerminalHelper.Box("INTERACTIVE SESSION")); + Logger.Custom("%s%n", TerminalHelper.Box("INTERACTIVE SESSION")); Logger.Custom( "%n %s[%s%s%s] %sID: %s%d %sUser: %s%s@%s %sOS: %s%s %sArch: %s%s %sIP: %s%s %sType: %s%s %sKey: %s%s%s%n", AnsiColor.Blue, AnsiColor.White, ActiveSession.GetDisplayName(), AnsiColor.Blue, @@ -210,11 +210,11 @@ public void Kill(int SessionId) { } public void ShowTasksQueue() { - System.out.println(TerminalHelper.Box("PENDING TASKS")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("PENDING TASKS")); + Logger.Custom("%n"); int Total = Server != null ? Server.GetSessions().Count() : 0; Logger.Custom(" %sActive sessions: %s%d%s%n", AnsiColor.Red, AnsiColor.White, Total, AnsiColor.Reset); Logger.Info(" use 'broadcast' or 'exec' to queue commands to sessions"); - System.out.println(); + Logger.Custom("%n"); } } diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/core/task/TaskCommands.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/core/task/TaskCommands.java index 1f73c00..e11aaf3 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/core/task/TaskCommands.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/core/task/TaskCommands.java @@ -29,13 +29,13 @@ public void ShowCommandHistory(int SessionId, int Limit) { String Title = SessionId == 0 ? "COMMAND HISTORY (all sessions, last " + Limit + ")" : "COMMAND HISTORY - session-" + SessionId + " (last " + Limit + ")"; - System.out.println(TerminalHelper.Box(Title)); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box(Title)); + Logger.Custom("%n"); if (History.isEmpty()) { Logger.Info("no command history\n"); return; } Logger.Custom(" %s%-5s %-12s %-8s %-36s %s%s%n", AnsiColor.Red, "SID", "OPERATOR", "STATUS", "COMMAND", "TIMESTAMP", AnsiColor.Reset); - System.out.println(TerminalHelper.Divider()); + Logger.Custom("%s%n", TerminalHelper.Divider()); for (Map Record : History) { boolean Success = Boolean.parseBoolean(Record.getOrDefault("Success", "false").toString()); @@ -52,7 +52,7 @@ public void ShowCommandHistory(int SessionId, int Limit) { Record.getOrDefault("Timestamp", ""), AnsiColor.Reset); } - System.out.println(); + Logger.Custom("%n"); } public void SetNote(int SessionId, String NoteText) { diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/module/chat/ChatManager.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/module/chat/ChatManager.java index 1d56720..2561405 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/module/chat/ChatManager.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/module/chat/ChatManager.java @@ -43,8 +43,8 @@ public void Send(String Recipient, String Message) { } public void ShowLocalMessages() { - System.out.println(TerminalHelper.Box("CHAT MESSAGES")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("CHAT MESSAGES")); + Logger.Custom("%n"); if (MessageHistory.isEmpty()) { Logger.Info("no messages\n"); return; } String CurrentOperator = OperatorName != null ? OperatorName : ""; for (Map Message : MessageHistory) { @@ -61,13 +61,13 @@ public void ShowLocalMessages() { From, AnsiColor.Reset, ToLabel, Content, AnsiColor.Reset); } - System.out.println(); + Logger.Custom("%n"); } public void ShowDatabaseHistory() { List> Records = Database.GetChatLogs(100); - System.out.println(TerminalHelper.Box("CHAT HISTORY (Database - last 100)")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("CHAT HISTORY (Database - last 100)")); + Logger.Custom("%n"); if (Records.isEmpty()) { Logger.Info("no chat history in database\n"); return; } String CurrentOperator = OperatorName != null ? OperatorName : ""; for (Map Record : Records) { @@ -85,6 +85,6 @@ public void ShowDatabaseHistory() { From, AnsiColor.Reset, ToLabel, Content, AnsiColor.Reset); } - System.out.println(); + Logger.Custom("%n"); } } diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/module/log/LogManager.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/module/log/LogManager.java index 4d01608..cf99777 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/module/log/LogManager.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/CLI/module/log/LogManager.java @@ -30,8 +30,8 @@ public EventLog GetEventLog() { } public void Show() { - System.out.println(TerminalHelper.Box("RECENT LOGS")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("RECENT LOGS")); + Logger.Custom("%n"); List Last = Log.GetLast(25); if (Last.isEmpty()) { Logger.Info(TerminalHelper.Indent("no logs") + "\n"); @@ -40,6 +40,6 @@ public void Show() { for (String Entry : Last) { Logger.Info(TerminalHelper.Indent(Entry)); } - System.out.println(); + Logger.Custom("%n"); } } diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/TeamClient.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/TeamClient.java index fb3e260..db544f4 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/TeamClient.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/TeamClient.java @@ -42,13 +42,15 @@ public final class TeamClient { private volatile boolean Running = true; private volatile String LastEventTimestamp = ""; private BufferedReader ConsoleReader; + private String StoredUsername; + private char[] StoredPassword; public TeamClient(ServerConfig Config, String TsHost, int TsPort) { this.Config = Config; this.TsHost = TsHost; this.TsPort = TsPort; this.Http = HttpClient.newBuilder().connectTimeout(Duration.ofSeconds(5)).build(); - PromptManager.SetPrompt(PROMPT_BOTTOM); + PromptManager.SetPrompt(PROMPT_TOP + "\n" + PROMPT_BOTTOM); } public void Run() { @@ -57,10 +59,8 @@ public void Run() { ConsoleReader = new BufferedReader(new InputStreamReader(System.in)); while (Running) { try { - System.out.println(); - System.out.println(PROMPT_TOP); - System.out.print(PROMPT_BOTTOM); - System.out.flush(); + Logger.Custom("%n"); + PromptManager.Redraw(); PromptManager.MarkVisible(true); String Input = ConsoleReader.readLine(); PromptManager.MarkVisible(false); @@ -74,6 +74,7 @@ public void Run() { break; } } + WipeCredentials(); Logger.Ok("Disconnected from TeamServer"); System.exit(0); } @@ -392,8 +393,8 @@ private void Dispatch(String Cmd, String[] P, String Line) { Map R = Get("/api/agents"); @SuppressWarnings("unchecked") List> Agents = (List>) R.getOrDefault("Agents", new ArrayList<>()); - System.out.println(TerminalHelper.Box("SESSION STATS")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("SESSION STATS")); + Logger.Custom("%n"); long Raw = Agents.stream().filter(A -> "ReverseShell".equals(A.getOrDefault("Type", ""))).count(); long Raven = Agents.stream().filter(A -> "RAVEN".equals(A.getOrDefault("Type", ""))).count(); long Http = Agents.stream().filter(A -> "HttpBeacon".equals(A.getOrDefault("Type", ""))).count(); @@ -401,7 +402,7 @@ private void Dispatch(String Cmd, String[] P, String Line) { if (Raw > 0) Logger.Custom(" %sRaw Shell %s%d%n", AnsiColor.Red, AnsiColor.White, Raw); if (Raven > 0) Logger.Custom(" %sRAVEN Agent %s%d%n", AnsiColor.Red, AnsiColor.White, Raven); if (Http > 0) Logger.Custom(" %sHTTP Beacon %s%d%n", AnsiColor.Red, AnsiColor.White, Http); - System.out.println(); + Logger.Custom("%n"); } catch (Exception Ex) { Logger.Error(Ex.getMessage()); } } case "tasks" -> { @@ -409,12 +410,12 @@ private void Dispatch(String Cmd, String[] P, String Line) { Map R = Get("/api/tasks"); @SuppressWarnings("unchecked") List> Tasks = (List>) R.getOrDefault("Tasks", new ArrayList<>()); - System.out.println(TerminalHelper.Box("PENDING TASKS (" + Tasks.size() + ")")); - System.out.println(); - if (Tasks.isEmpty()) { Logger.Info(INDENT + "no pending tasks"); System.out.println(); break; } + Logger.Custom("%s%n", TerminalHelper.Box("PENDING TASKS (" + Tasks.size() + ")")); + Logger.Custom("%n"); + if (Tasks.isEmpty()) { Logger.Info(INDENT + "no pending tasks"); Logger.Custom("%n"); break; } for (Map T : Tasks) Logger.Custom(" [%s] session-%s %s%n", T.getOrDefault("Queued", "?"), T.getOrDefault("AgentId", "?"), T.getOrDefault("Command", "?")); - System.out.println(); + Logger.Custom("%n"); } catch (Exception Ex) { Logger.Error(Ex.getMessage()); } } case "addopt" -> { @@ -472,9 +473,15 @@ private void Dispatch(String Cmd, String[] P, String Line) { String ListenMode = "MULTI"; for (int Idx = 1; Idx < P.length; Idx++) { switch (P[Idx]) { - case "-lhost" -> { if (Idx + 1 < P.length) ListenHost = P[++Idx]; } - case "-lport" -> { if (Idx + 1 < P.length) ListenPort = ParseIntSafe(P[++Idx], ListenPort); } - case "-M" -> { if (Idx + 1 < P.length) ListenMode = P[++Idx].toUpperCase(); } + case "-lhost", "-host", "-h" -> { + if (Idx + 1 < P.length && !P[Idx + 1].startsWith("-")) ListenHost = P[++Idx]; + } + case "-lport", "-port", "-p" -> { + if (Idx + 1 < P.length && !P[Idx + 1].startsWith("-")) ListenPort = ParseIntSafe(P[++Idx], ListenPort); + } + case "-M", "-mode", "-m" -> { + if (Idx + 1 < P.length && !P[Idx + 1].startsWith("-")) ListenMode = P[++Idx].toUpperCase(); + } } } try { @@ -495,8 +502,18 @@ private void Dispatch(String Cmd, String[] P, String Line) { } catch (Exception Ex) { Logger.Error(Ex.getMessage()); } } case "webstart" -> { - String WHost = P.length > 1 ? P[1] : Config.GetWebHost(); - int WPort = P.length > 2 ? ParseIntSafe(P[2], Config.GetWebPort()) : Config.GetWebPort(); + String WHost = Config.GetWebHost(); + int WPort = Config.GetWebPort(); + for (int Idx = 1; Idx < P.length; Idx++) { + switch (P[Idx]) { + case "-lhost", "-host", "-h" -> { if (Idx + 1 < P.length) WHost = P[++Idx]; } + case "-lport", "-port", "-p" -> { if (Idx + 1 < P.length) WPort = ParseIntSafe(P[++Idx], WPort); } + default -> { + if (P[Idx].matches("\\d+")) WPort = ParseIntSafe(P[Idx], WPort); + else if (!P[Idx].startsWith("-")) WHost = P[Idx]; + } + } + } try { Map R = Post("/api/server/webpanel/start", Map.of("Host", WHost, "Port", WPort, "Operator", OperatorName)); @@ -555,15 +572,15 @@ private void InteractiveSession(int AgentId) { } private boolean Login() { - System.out.println(); - System.out.println(TerminalHelper.Box("TEAMCLIENT — CONNECT TO TEAMSERVER")); - System.out.println(); + Logger.Custom("%n"); + Logger.Custom("%s%n", TerminalHelper.Box("TEAMCLIENT — CONNECT TO TEAMSERVER")); + Logger.Custom("%n"); Logger.Custom(INDENT + "%sTeamServer:%s %s:%d%n%n", AnsiColor.Red, AnsiColor.White, TsHost, TsPort, AnsiColor.Reset); try { Get("/api/server/status"); } catch (java.net.ConnectException Ex) { Logger.Error("connection refused — " + TsHost + ":" + TsPort); - System.out.println(); + Logger.Custom("%n"); Logger.Custom(INDENT + "TeamClient requires a running TeamServer backend.%n"); Logger.Custom(INDENT + "Start with: java -jar raven.jar -TS -tp %d%n%n", TsPort); return false; @@ -590,15 +607,20 @@ private boolean Login() { Body.put("Username", User.trim()); Body.put("Password", Pass.trim()); Map Resp = Post("/api/auth/login", Body); + Body.remove("Password"); + Pass = null; if (Resp.containsKey("Error")) { Logger.Error(Resp.get("Error").toString() + " (" + (Try + 1) + "/3)"); continue; } - Token = Resp.getOrDefault("Token", "").toString(); - OperatorName = Resp.getOrDefault("Username", User.trim()).toString(); - OperatorRoleValue = OperatorRole.FromString(Resp.getOrDefault("Role", "MEMBER").toString()); + Token = Resp.getOrDefault("Token", "").toString(); + OperatorName = Resp.getOrDefault("Username", User.trim()).toString(); + OperatorRoleValue = OperatorRole.FromString(Resp.getOrDefault("Role", "MEMBER").toString()); + StoredUsername = User.trim(); + StoredPassword = new char[PassChars.length]; + System.arraycopy(PassChars, 0, StoredPassword, 0, PassChars.length); LastEventTimestamp = java.time.LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); - System.out.println(); + Logger.Custom("%n"); Logger.Ok("Welcome, " + OperatorName + " [" + OperatorRoleValue + "]"); Logger.Custom(INDENT + "%sConnected to TeamServer at %s:%d%s%n%n", AnsiColor.White, TsHost, TsPort, AnsiColor.Reset); return true; @@ -610,16 +632,44 @@ private boolean Login() { return false; } + private void WipeCredentials() { + StoredUsername = null; + if (StoredPassword != null) { + java.util.Arrays.fill(StoredPassword, '\0'); + StoredPassword = null; + } + Token = null; + } + + private boolean ReAuthenticate() { + if (StoredUsername == null || StoredPassword == null) return false; + try { + Map Body = new LinkedHashMap<>(); + Body.put("Username", StoredUsername); + Body.put("Password", new String(StoredPassword)); + Map Resp = Post("/api/auth/login", Body); + Body.remove("Password"); + if (Resp.containsKey("Error")) return false; + Token = Resp.getOrDefault("Token", "").toString(); + OperatorName = Resp.getOrDefault("Username", StoredUsername).toString(); + OperatorRoleValue = OperatorRole.FromString(Resp.getOrDefault("Role", "MEMBER").toString()); + LastEventTimestamp = java.time.LocalDateTime.now().format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); + return !Token.isEmpty(); + } catch (Exception ReAuthException) { + return false; + } + } + private void ShowHelp() { - System.out.println(TerminalHelper.Box("TEAMCLIENT COMMANDS")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("TEAMCLIENT COMMANDS")); + Logger.Custom("%n"); Logger.Custom(INDENT + "%sConnected as:%s %s[%s / %s]%s Server: %s%s:%d%s%n%n", AnsiColor.Red, AnsiColor.White, AnsiColor.Green, OperatorName != null ? OperatorName : "—", OperatorRoleValue != null ? OperatorRoleValue.name() : "—", AnsiColor.White, AnsiColor.Red, TsHost, TsPort, AnsiColor.Reset); for (Category Cat : Category.values()) { List Cmds = CommandRegistry.ByCategory(Cat); if (Cmds.isEmpty()) continue; Logger.Custom(INDENT + "%s%s%s%n", AnsiColor.Red, Cat.name(), AnsiColor.Reset); for (CommandDef Def : Cmds) Logger.Custom(INDENT + " %s%-42s%s %s%n", AnsiColor.White, Def.Usage(), AnsiColor.Reset, Def.Description()); - System.out.println(); + Logger.Custom("%n"); } } @@ -628,19 +678,19 @@ private void ShowSessions() { Map R = Get("/api/agents"); @SuppressWarnings("unchecked") List> Agents = (List>) R.getOrDefault("Agents", new ArrayList<>()); - System.out.println(TerminalHelper.Box("ACTIVE SESSIONS (" + Agents.size() + ")")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("ACTIVE SESSIONS (" + Agents.size() + ")")); + Logger.Custom("%n"); if (Agents.isEmpty()) { Logger.Info(INDENT + "no active sessions"); - System.out.println(); + Logger.Custom("%n"); return; } Logger.Custom(INDENT + "%s%-5s %-14s %-16s %-14s %-10s %-10s %s%s%n", AnsiColor.Red, "ID", "NAME", "IP", "TYPE", "OS", "USER", "KEY", AnsiColor.Reset); - System.out.println(TerminalHelper.Divider()); + Logger.Custom("%s%n", TerminalHelper.Divider()); for (Map A : Agents) { Logger.Custom(INDENT + "%s#%-4s %-14s %-16s %-14s %-10s %-10s %s%s%n", AnsiColor.White, ((Number) A.getOrDefault("ID", 0.0)).intValue(), TerminalHelper.Truncate(A.getOrDefault("AgentName", "?").toString(), 14), TerminalHelper.Truncate(A.getOrDefault("AgentIP", "?").toString(), 16), A.getOrDefault("Type", "?"), TerminalHelper.Truncate(A.getOrDefault("OS", "?").toString(), 10), TerminalHelper.Truncate(A.getOrDefault("User", "?").toString(), 10), A.getOrDefault("SessionKey", "—"), AnsiColor.Reset); } - System.out.println(); + Logger.Custom("%n"); } catch (Exception Ex) { Logger.Error(Ex.getMessage()); } @@ -659,8 +709,8 @@ private void ShowSessionInfo(int Id) { Logger.Warn("session not found"); return; } - System.out.println(TerminalHelper.Box("SESSION INFO — #" + Id)); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("SESSION INFO — #" + Id)); + Logger.Custom("%n"); A.forEach((K, V) -> Logger.Custom(INDENT + "%s%-14s%s %s%n", AnsiColor.Red, K, AnsiColor.White, V)); Logger.Custom("%s%n", AnsiColor.Reset); } catch (Exception Ex) { @@ -671,8 +721,12 @@ private void ShowSessionInfo(int Id) { private void ShowStatus() { try { Map R = Get("/api/server/status"); - System.out.println(TerminalHelper.Box("SERVER STATUS")); - System.out.println(); + if (R.containsKey("Error")) { + Logger.Error("status: " + R.get("Error")); + return; + } + Logger.Custom("%s%n", TerminalHelper.Box("SERVER STATUS")); + Logger.Custom("%n"); Logger.Custom(INDENT + "%sStatus %s%s%s%n", AnsiColor.Red, AnsiColor.Green, R.getOrDefault("Status", "?"), AnsiColor.Reset); Logger.Custom(INDENT + "%sMode %s%s%n", AnsiColor.Red, AnsiColor.White, R.getOrDefault("Mode", "?").toString().toUpperCase()); Logger.Custom(INDENT + "%sAddress %s%s:%d%n", AnsiColor.Red, AnsiColor.White, R.getOrDefault("Host", "?"), ((Number) R.getOrDefault("Port", 0.0)).intValue()); @@ -686,7 +740,7 @@ private void ShowStatus() { Logger.Custom(INDENT + "%sDB %s%s (%s)%n", AnsiColor.Red, AnsiColor.White, DbUp ? "connected" : "offline", DbType); Logger.Custom(INDENT + "%sServer %shttp://%s:%d%s%n%n", AnsiColor.Red, AnsiColor.White, TsHost, TsPort, AnsiColor.Reset); } catch (Exception Ex) { - Logger.Error(Ex.getMessage()); + Logger.Error("status: " + (Ex.getMessage() != null ? Ex.getMessage() : Ex.getClass().getSimpleName())); } } @@ -695,14 +749,22 @@ private void ShowLogs() { Map R = Get("/api/logs"); @SuppressWarnings("unchecked") List Logs = (List) R.getOrDefault("Logs", new ArrayList<>()); - System.out.println(TerminalHelper.Box("RECENT LOGS (last 30)")); - System.out.println(); - Logs.stream() - .skip(Math.max(0, Logs.size() - 30)) - .forEach(L -> Logger.Custom(INDENT + "%s%s%s%n", AnsiColor.White, L, AnsiColor.Reset)); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("RECENT LOGS (last 30)")); + Logger.Custom("%n"); + List Recent = Logs.stream().skip(Math.max(0, Logs.size() - 30)).toList(); + for (String Line : Recent) { + String Color = AnsiColor.White; + if (Line.contains("[SESSION]") || Line.contains("[+]") || Line.contains("[-]")) Color = AnsiColor.Green; + else if (Line.contains("[AUTH]")) Color = AnsiColor.Yellow; + else if (Line.contains("[TEAM]")) Color = AnsiColor.Cyan; + else if (Line.contains("[CMD]")) Color = AnsiColor.Blue; + else if (Line.contains("[WARN]")) Color = AnsiColor.Yellow; + else if (Line.contains("[ERROR]")) Color = AnsiColor.Red; + Logger.Custom(INDENT + "%s%s%s%n", Color, Line, AnsiColor.Reset); + } + Logger.Custom("%n"); } catch (Exception Ex) { - Logger.Error(Ex.getMessage()); + Logger.Error("logs: " + (Ex.getMessage() != null ? Ex.getMessage() : Ex.getClass().getSimpleName())); } } @@ -711,11 +773,11 @@ private void ShowChat() { Map R = Get("/api/team/chat/messages"); @SuppressWarnings("unchecked") List> Msgs = (List>) R.getOrDefault("Messages", new ArrayList<>()); - System.out.println(TerminalHelper.Box("CHAT MESSAGES")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("CHAT MESSAGES")); + Logger.Custom("%n"); if (Msgs.isEmpty()) { Logger.Info(INDENT + "no messages"); - System.out.println(); + Logger.Custom("%n"); return; } for (Map M : Msgs) { @@ -724,7 +786,7 @@ private void ShowChat() { boolean Mine = From.equals(OperatorName); Logger.Custom(INDENT + "%s[%s] %s%s%s [%s]: %s%s%n", Mine ? AnsiColor.Green : AnsiColor.White, M.getOrDefault("Timestamp", ""), Mine ? AnsiColor.Green : AnsiColor.Red, From, AnsiColor.Reset, To.equals("all") ? "all" : "→ " + To, M.getOrDefault("Message", ""), AnsiColor.Reset); } - System.out.println(); + Logger.Custom("%n"); } catch (Exception Ex) { Logger.Error(Ex.getMessage()); } @@ -735,11 +797,11 @@ private void ShowChatHistory(int Limit) { Map R = Post("/api/team/chat/logs", Map.of("Limit", Limit)); @SuppressWarnings("unchecked") List> Messages = (List>) R.getOrDefault("Logs", new ArrayList<>()); - System.out.println(TerminalHelper.Box("CHAT HISTORY (last " + Limit + ")")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("CHAT HISTORY (last " + Limit + ")")); + Logger.Custom("%n"); if (Messages.isEmpty()) { Logger.Info(INDENT + "no chat history"); - System.out.println(); + Logger.Custom("%n"); return; } for (Map Message : Messages) { @@ -750,7 +812,7 @@ private void ShowChatHistory(int Limit) { boolean Mine = From.equals(OperatorName); Logger.Custom(INDENT + "%s[%s] %s%s%s [%s]: %s%s%n", Mine ? AnsiColor.Green : AnsiColor.White, Ts, Mine ? AnsiColor.Green : AnsiColor.Red, From, AnsiColor.Reset, To.equals("all") ? "all" : "→ " + To, Message.getOrDefault("Message", ""), AnsiColor.Reset); } - System.out.println(); + Logger.Custom("%n"); } catch (Exception Ex) { Logger.Error(Ex.getMessage()); } @@ -761,16 +823,16 @@ private void ShowOperators() { Map R = Get("/api/team/operators"); @SuppressWarnings("unchecked") List> Ops = (List>) R.getOrDefault("Operators", new ArrayList<>()); - System.out.println(TerminalHelper.Box("OPERATORS (" + Ops.size() + ")")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("OPERATORS (" + Ops.size() + ")")); + Logger.Custom("%n"); Logger.Custom(INDENT + "%s%-18s %-10s %-24s %-20s%s%n", AnsiColor.Red, "USERNAME", "ROLE", "PERMISSIONS", "LAST SEEN", AnsiColor.Reset); - System.out.println(TerminalHelper.Divider()); + Logger.Custom("%s%n", TerminalHelper.Divider()); for (Map Op : Ops) { OperatorRole R2 = OperatorRole.FromString(Op.getOrDefault("Role", "MEMBER").toString()); boolean Me = Op.getOrDefault("Username", "").toString().equals(OperatorName); Logger.Custom(INDENT + "%s%-18s %-10s %-24s %-20s%s%s%n", AnsiColor.White, Op.getOrDefault("Username", "?"), R2.name(), R2.PermissionString(), Op.getOrDefault("LastSeen", "Never"), Me ? AnsiColor.Green + " ◀ YOU" : "", AnsiColor.Reset); } - System.out.println(); + Logger.Custom("%n"); } catch (Exception Ex) { Logger.Error(Ex.getMessage()); } @@ -782,21 +844,21 @@ private void ShowHistory(int AgentId, int Limit) { Map R = Post("/api/command/history", Body); @SuppressWarnings("unchecked") List> Hist = (List>) R.getOrDefault("History", new ArrayList<>()); - System.out.println(TerminalHelper.Box("COMMAND HISTORY (last " + Limit + (AgentId > 0 ? " — session-" + AgentId : "") + ")")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("COMMAND HISTORY (last " + Limit + (AgentId > 0 ? " — session-" + AgentId : "") + ")")); + Logger.Custom("%n"); if (Hist.isEmpty()) { Logger.Info(INDENT + "no history"); - System.out.println(); + Logger.Custom("%n"); return; } Logger.Custom(INDENT + "%s%-5s %-12s %-10s %-36s %s%s%n", AnsiColor.Red, "SID", "OPERATOR", "STATUS", "COMMAND", "TIMESTAMP", AnsiColor.Reset); - System.out.println(TerminalHelper.Divider()); + Logger.Custom("%s%n", TerminalHelper.Divider()); for (Map H : Hist) { boolean Ok = Boolean.parseBoolean(H.getOrDefault("Success", "false").toString()); String Cmd = TerminalHelper.Truncate(H.getOrDefault("Command", "").toString(), 36); Logger.Custom(INDENT + "%s%-5s %-12s %s%-10s%s %-36s %s%s%n", AnsiColor.White, H.getOrDefault("AgentId", "?"), TerminalHelper.Truncate(H.getOrDefault("Operator", "?").toString(), 12), Ok ? AnsiColor.Green : AnsiColor.Red, Ok ? "✔ ok" : "✘ fail", AnsiColor.White, Cmd, H.getOrDefault("Timestamp", ""), AnsiColor.Reset); } - System.out.println(); + Logger.Custom("%n"); } catch (Exception Ex) { Logger.Error(Ex.getMessage()); } @@ -807,10 +869,10 @@ private void ShowSessionHistory(int Limit) { Map R = Post("/api/sessions/history", Map.of("Limit", Limit)); @SuppressWarnings("unchecked") List> Sess = (List>) R.getOrDefault("Sessions", new ArrayList<>()); - System.out.println(TerminalHelper.Box("SESSION HISTORY (last " + Limit + ")")); - System.out.println(); + Logger.Custom("%s%n", TerminalHelper.Box("SESSION HISTORY (last " + Limit + ")")); + Logger.Custom("%n"); Sess.forEach(S -> Logger.Custom(INDENT + "%s%s%s%n", AnsiColor.White, S, AnsiColor.Reset)); - System.out.println(); + Logger.Custom("%n"); } catch (Exception Ex) { Logger.Error(Ex.getMessage()); } @@ -828,7 +890,12 @@ private void StartEventPoller() { if (ConsecutiveFailures > 0) { ConsecutiveFailures = 0; DropReported = false; - PromptManager.PrintLine(INDENT + AnsiColor.Green + "⟳ reconnected to TeamServer" + AnsiColor.Reset); + if (!ReAuthenticate()) { + Logger.Warn("⚠ Re-authentication failed — session ended"); + Running = false; + break; + } + Logger.Ok("⟳ reconnected and re-authenticated to TeamServer"); } Object RawLogs = Response.get("Logs"); if (!(RawLogs instanceof java.util.List)) continue; @@ -850,7 +917,7 @@ private void StartEventPoller() { boolean IsTeam = Message.contains("[TEAM]") || Message.contains("[>]"); boolean IsError = Message.contains("[!]") || Message.contains("ERROR"); String Color = IsSession ? AnsiColor.Green : IsAuth ? AnsiColor.Yellow : IsTeam ? AnsiColor.Cyan : IsError ? AnsiColor.Red : AnsiColor.White; - PromptManager.PrintLine(INDENT + Color + "[" + Timestamp + "] " + Message + AnsiColor.Reset); + PromptManager.PrintLine(Color + "[" + Timestamp + "] " + Message + AnsiColor.Reset); } } catch (InterruptedException InterruptedException) { Thread.currentThread().interrupt(); @@ -859,7 +926,7 @@ private void StartEventPoller() { ConsecutiveFailures++; if (ConsecutiveFailures >= 3 && !DropReported) { DropReported = true; - PromptManager.PrintLine(INDENT + AnsiColor.Red + "⚠ TeamServer connection lost — retrying..." + AnsiColor.Reset); + Logger.Warn("⚠ TeamServer connection lost — retrying..."); } } } @@ -1000,9 +1067,9 @@ private void SendChat(String To, String Msg) { } private void PrintOutput(boolean Ok, String Out) { - if (Ok) System.out.println(TerminalHelper.OutputBox(Out)); + if (Ok) Logger.Custom("%s%n", TerminalHelper.OutputBox(Out)); else Logger.Error(Out); - System.out.println(); + Logger.Custom("%n"); } private Map Post(String Path, Map Body) throws Exception { @@ -1057,7 +1124,7 @@ static void Error(String Message) { } static void Info(String Message) { - System.out.println(Message); + Logger.Custom("%s%n", Message); } static void Custom(String Format, Object... Args) { diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/TeamServer.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/TeamServer.java index a99c315..2bda739 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/TeamServer.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/interfaces/TeamServer.java @@ -80,7 +80,7 @@ public void RunAsBackend(String ApiHost, int ApiPort) throws Exception { Logger.Info(" Connect CLI : java -jar raven.jar -TSC -ts " + ApiHost + " -tp " + ApiPort); Logger.Info(" Connect Web : java -jar raven.jar -TSW -ts " + ApiHost + " -tp " + ApiPort + " -wp "); Logger.Info(" Listener : use 'start' command in CLI/Web/GUI to configure"); - AddLog("TeamServer backend initialized"); + AddLog("INFO", "TeamServer backend initialized"); } public void StartWebPanel(String WebHost, int WebPort) throws Exception { @@ -104,7 +104,7 @@ public void StartWebPanel(String WebHost, int WebPort) throws Exception { WebPanelPort = WebPort; String DisplayHost = WebHost.equals("0.0.0.0") ? "localhost" : WebHost; Logger.Info(" Web panel : http://" + DisplayHost + ":" + WebPort + "/"); - AddLog("Web panel started on port " + WebPort); + AddLog("INFO", "Web panel started on port " + WebPort); } catch (java.net.BindException BindException) { throw new Exception("Port " + WebPort + " is already in use — choose a different -wp port"); } @@ -180,7 +180,7 @@ public void RunWebFrontend(String BackendHost, int BackendPort, String LocalHost String DisplayLocal = LocalHost.equals("0.0.0.0") ? "localhost" : LocalHost; Logger.Info("TeamServer web panel (proxy) : http://" + DisplayLocal + ":" + LocalPort + "/"); Logger.Info(" Proxying API to backend : http://" + BackendHost + ":" + BackendPort + "/api/"); - AddLog("TSW proxy frontend started on port " + LocalPort + " → backend " + BackendHost + ":" + BackendPort); + AddLog("INFO", "TSW proxy frontend started on port " + LocalPort + " → backend " + BackendHost + ":" + BackendPort); } public void RunStandalone(String ApiHost, int ApiPort, String WebHost, int WebPort) throws Exception { @@ -200,7 +200,7 @@ public void RunStandalone(String ApiHost, int ApiPort, String WebHost, int WebPo WebPanelPort = WebPort; String DisplayHost = WebHost.equals("0.0.0.0") ? "localhost" : WebHost; Logger.Info(" Web frontend : http://" + DisplayHost + ":" + WebPort + "/"); - AddLog("Web frontend started on port " + WebPort); + AddLog("INFO", "Web frontend started on port " + WebPort); } public void Stop() { @@ -318,9 +318,13 @@ private Map Body(HttpExchange Exchange) throws Exception { private String Str(Map DataMap, String Key, String Default) { return HttpHelper.Str(DataMap, Key, Default); } private int Num(Map DataMap, String Key, int Default) { return HttpHelper.Num(DataMap, Key, Default); } + private void AddLog(String Level, String Message) { + Log.Add(Level, Message, false); + Db.SaveLog("[" + Level + "] " + Message); + } + private void AddLog(String Message) { - Log.Add(Message, false); - Db.SaveLog(Message); + AddLog("INFO", Message); } private String Uptime() { @@ -345,7 +349,7 @@ private String ApiAuthLogin(HttpExchange Exchange, TokenInfo Ignored) throws Exc String Token = UUID.randomUUID().toString().replace("-", ""); Tokens.put(Token, new TokenInfo(Username, Role, System.currentTimeMillis() + TokenTtlMs)); Logger.Info("[AUTH] Login: " + Username + " [" + Role + "]"); - AddLog("[AUTH] Login: " + Username + " [" + Role + "]"); + AddLog("AUTH", "Login: " + Username + " [" + Role + "]"); return HttpHelper.Json(Map.of( "Token", Token, "Role", Role.name(), @@ -359,7 +363,7 @@ private String ApiAuthLogout(HttpExchange Exchange, TokenInfo Token) throws Exce String Header = Exchange.getRequestHeaders().getFirst("Authorization"); if (Header != null && Header.startsWith("Bearer ")) { Tokens.remove(Header.substring(7)); - AddLog("[AUTH] Logout: " + Token.Username()); + AddLog("AUTH", "Logout: " + Token.Username()); } return HttpHelper.Json(Map.of("Success", true)); } @@ -427,7 +431,7 @@ private String ApiServerStop(HttpExchange Exchange, TokenInfo Token) { RavenServer ToStop = Server; Server = null; ServerStartTime = null; - AddLog("Listener stopped by " + Token.Username()); + AddLog("INFO", "Listener stopped by " + Token.Username()); Thread Stopper = new Thread(() -> { try { Thread.sleep(200); } catch (InterruptedException Ignored) {} ToStop.StopServer(); @@ -476,7 +480,7 @@ private String ApiAgentKill(HttpExchange Exchange, TokenInfo Token) throws Excep return HttpHelper.Json(Map.of("Error", "AgentId required")); } Server.RemoveSession(AgentId); - AddLog("[KILL] session-" + AgentId + " by " + Token.Username()); + AddLog("WARN", "session-" + AgentId + " killed by " + Token.Username()); return HttpHelper.Json(Map.of("Success", true)); } @@ -512,7 +516,7 @@ private String ApiCmdExec(HttpExchange Exchange, TokenInfo Token) throws Excepti SetStatus(400); return HttpHelper.Json(Map.of("Error", "AgentId and Command required")); } - AddLog("[>] [" + Token.Username() + "] session-" + AgentId + " » " + Command); + AddLog("CMD", "[" + Token.Username() + "] session-" + AgentId + " » " + Command); String[] Result = Server.ExecuteCommand(AgentId, Command); boolean Ok = Boolean.parseBoolean(Result[0]); Db.SaveCommandLog(AgentId, Token.Username(), Command, Result[1], Ok); @@ -543,7 +547,7 @@ private String ApiCmdBroadcast(HttpExchange Exchange, TokenInfo Token) throws Ex SetStatus(400); return HttpHelper.Json(Map.of("Error", "AgentIds required")); } - AddLog("[BROADCAST] [" + Token.Username() + "] > " + Ids.size() + " agents » " + Command); + AddLog("CMD", "[BROADCAST] [" + Token.Username() + "] > " + Ids.size() + " agents » " + Command); return BuildBroadcastResult(Server.BroadcastCommand(Ids, Command), Token.Username(), Command); } @@ -561,7 +565,7 @@ private String ApiCmdBroadcastAll(HttpExchange Exchange, TokenInfo Token) throws SetStatus(400); return HttpHelper.Json(Map.of("Error", "Command required")); } - AddLog("[BROADCAST-ALL] [" + Token.Username() + "] > " + Server.GetSessions().Count() + " agents » " + Command); + AddLog("CMD", "[BROADCAST-ALL] [" + Token.Username() + "] > " + Server.GetSessions().Count() + " agents » " + Command); return BuildBroadcastResult(Server.BroadcastAll(Command), Token.Username(), Command); } @@ -687,7 +691,7 @@ private String ApiOpCreate(HttpExchange Exchange, TokenInfo Token) throws Except OperatorRole NewRole = OperatorRole.FromString(Role); if (NewRole == OperatorRole.SUPER && !Token.Role().IsSuperAdmin()) { SetStatus(403); return HttpHelper.Json(Map.of("Error", "Only SUPER can create SUPER")); } if (!Db.CreateOperator(Username, Password, NewRole)) { SetStatus(409); return HttpHelper.Json(Map.of("Error", "Username already exists")); } - AddLog("[TEAM] Created operator: " + Username + " [" + NewRole + "] by " + Token.Username()); + AddLog("TEAM", "Created operator: " + Username + " [" + NewRole + "] by " + Token.Username()); return HttpHelper.Json(Map.of("Success", true, "Username", Username, "Role", NewRole.name())); } @@ -698,7 +702,7 @@ private String ApiOpDelete(HttpExchange Exchange, TokenInfo Token) throws Except if (Username.equalsIgnoreCase(Config.GetAdminUsername())) { SetStatus(403); return HttpHelper.Json(Map.of("Error", "Cannot delete admin")); } if (!Db.DeleteOperator(Username)) { SetStatus(404); return HttpHelper.Json(Map.of("Error", "Operator not found")); } Tokens.entrySet().removeIf(Entry -> Entry.getValue().Username().equals(Username)); - AddLog("[TEAM] Deleted operator: " + Username + " by " + Token.Username()); + AddLog("TEAM", "Deleted operator: " + Username + " by " + Token.Username()); return HttpHelper.Json(Map.of("Success", true)); } @@ -711,7 +715,7 @@ private String ApiOpRole(HttpExchange Exchange, TokenInfo Token) throws Exceptio if (Username.equalsIgnoreCase(Config.GetAdminUsername())) { SetStatus(403); return HttpHelper.Json(Map.of("Error", "Cannot change admin role")); } OperatorRole NewRole = OperatorRole.FromString(Role); if (!Db.UpdateOperatorRole(Username, NewRole)) { SetStatus(404); return HttpHelper.Json(Map.of("Error", "Operator not found")); } - AddLog("[TEAM] Role updated: " + Username + " → " + NewRole + " by " + Token.Username()); + AddLog("TEAM", "Role updated: " + Username + " → " + NewRole + " by " + Token.Username()); return HttpHelper.Json(Map.of("Success", true)); } @@ -723,7 +727,7 @@ private String ApiOpPassword(HttpExchange Exchange, TokenInfo Token) throws Exce if (Username.isEmpty() || Password.isEmpty()) { SetStatus(400); return HttpHelper.Json(Map.of("Error", "Username and Password required")); } if (Password.length() < 8) { SetStatus(400); return HttpHelper.Json(Map.of("Error", "Password must be at least 8 characters")); } if (!Db.UpdateOperatorPassword(Username, Password)) { SetStatus(404); return HttpHelper.Json(Map.of("Error", "Operator not found")); } - AddLog("[TEAM] Password changed: " + Username + " by " + Token.Username()); + AddLog("TEAM", "Password changed: " + Username + " by " + Token.Username()); return HttpHelper.Json(Map.of("Success", true)); } @@ -737,7 +741,7 @@ private String ApiOpKick(HttpExchange Exchange, TokenInfo Token) throws Exceptio .filter(Entry -> Entry.getValue().Username().equals(Username)) .peek(Entry -> Tokens.remove(Entry.getKey())) .count(); - AddLog("[TEAM] Kicked (tokens revoked=" + RevokedCount + "): " + Username + " by " + Token.Username()); + AddLog("TEAM", "Kicked: " + Username + " (tokens revoked=" + RevokedCount + ") by " + Token.Username()); return HttpHelper.Json(Map.of("Success", true, "TokensRevoked", RevokedCount)); } @@ -782,7 +786,7 @@ private String ApiWebPanelStart(HttpExchange Exchange, TokenInfo Token) throws E String DisplayHost = RequestedHost.equals("0.0.0.0") ? "localhost" : RequestedHost; String Url = "http://" + DisplayHost + ":" + RequestedPort + "/"; Logger.Info("Web panel enabled on " + Url + " by " + Token.Username()); - AddLog("Web panel started on " + Url + " by " + Token.Username()); + AddLog("INFO", "Web panel started on " + Url + " by " + Token.Username()); return HttpHelper.Json(Map.of("Success", true, "URL", Url)); } catch (Exception Exception) { SetStatus(500); @@ -798,7 +802,7 @@ private String ApiWebPanelStop(HttpExchange Exchange, TokenInfo Token) throws Ex WebPanelHost = null; WebPanelPort = -1; Logger.Info("Web panel stopped by " + Token.Username()); - AddLog("Web panel stopped by " + Token.Username()); + AddLog("INFO", "Web panel stopped by " + Token.Username()); Thread Stopper = new Thread(() -> { try { Thread.sleep(300); } catch (InterruptedException Ignored) {} ToStop.stop(0); @@ -859,17 +863,17 @@ private String ApiChatLogs(HttpExchange Exchange, TokenInfo Token) throws Except private void OnEvent(EventType Type, Map Data) { switch (Type) { - case ServerStarted -> AddLog("Listener started on " + Data.get("Host") + ":" + Data.get("Port") + " [" + Data.get("Mode") + "]"); + case ServerStarted -> AddLog("INFO", "Listener started on " + Data.get("Host") + ":" + Data.get("Port") + " [" + Data.get("Mode") + "]"); case AgentConnected -> { - AddLog("[+] session-" + Data.get("ID") + " [" + Data.get("Type") + "] " + Data.get("User") + "@" + Data.get("Hostname") + " " + Data.get("OS") + " key=" + Data.get("SessionKey")); + AddLog("SESSION", "[+] session-" + Data.get("ID") + " [" + Data.get("Type") + "] " + Data.get("User") + "@" + Data.get("Hostname") + " " + Data.get("OS") + " key=" + Data.get("SessionKey")); Db.SaveSessionEvent(Data, "connected"); } case AgentDisconnected -> { - AddLog("[-] session-" + Data.get("ID") + " disconnected: " + Data.get("Reason")); + AddLog("SESSION", "[-] session-" + Data.get("ID") + " disconnected: " + Data.get("Reason")); Db.SaveSessionEvent(Data, "disconnected"); } - case AgentRemoved -> AddLog("[-] session-" + Data.get("ID") + " removed"); - case Error -> AddLog("[!] " + Data.get("Message")); + case AgentRemoved -> AddLog("SESSION", "[-] session-" + Data.get("ID") + " removed"); + case Error -> AddLog("ERROR", Data.get("Message").toString()); } } } diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/utils/Helper.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/utils/Helper.java index ea13167..c8fd191 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/utils/Helper.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/utils/Helper.java @@ -1,5 +1,6 @@ package com.raven.utils; +import com.raven.core.output.Logger; import java.util.List; public final class Helper { @@ -8,7 +9,7 @@ private Helper() {} public static void PrintHelp() { String Newline = "\n"; - System.out.println( + Logger.Custom("%s%n", String.join( Newline, "", diff --git a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/utils/ServerConfig.java b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/utils/ServerConfig.java index e45f6ed..66a1865 100644 --- a/RAVEN/RAVEN-SERVER/src/main/java/com/raven/utils/ServerConfig.java +++ b/RAVEN/RAVEN-SERVER/src/main/java/com/raven/utils/ServerConfig.java @@ -114,6 +114,8 @@ private void LoadFromFile(String Path) { public boolean IsFileLoggingEnabled() { return Bool("logging.file.enabled"); } public String GetInterfaceMode() { return Str("mode.interface").toLowerCase(); } public String GetExportDir() { return Str("export.dir"); } + public String GetAgentOutputDir() { return Str("agent.output.dir"); } + public String GetDownloadDir() { return Str("agent.download.dir"); } public boolean IsMtlsEnabled() { String Mode = GetServerMode(); return Mode.equals("mtls") || Mode.equals("fmtls"); } public String GetAdminUsername() { return OperatorCfg.GetAdminUsername(); } public String GetAdminPassword() { return OperatorCfg.GetAdminPassword(); } diff --git a/RAVEN/RAVEN-SERVER/src/main/resources/config/raven-defaults.properties b/RAVEN/RAVEN-SERVER/src/main/resources/config/raven-defaults.properties index bd58621..ac7041b 100644 --- a/RAVEN/RAVEN-SERVER/src/main/resources/config/raven-defaults.properties +++ b/RAVEN/RAVEN-SERVER/src/main/resources/config/raven-defaults.properties @@ -87,3 +87,5 @@ mode.interface = cli # ── EXPORTS ───────────────────────────────────────────────────── export.dir = exports +agent.output.dir = IMPLANT +agent.download.dir = downloads