From f262f3e663b64c5b5f1cb0db4414c7333c7076ea Mon Sep 17 00:00:00 2001 From: tux_mind Date: Fri, 2 Oct 2015 16:41:36 +0200 Subject: [PATCH 01/15] first msf library draft --- msf/.gitignore | 1 + msf/build.gradle | 8 + msf/src/main/java/org/csploit/msf/Author.java | 37 ++++ .../main/java/org/csploit/msf/DataHolder.java | 8 + .../main/java/org/csploit/msf/DataStore.java | 113 ++++++++++ .../main/java/org/csploit/msf/Exploit.java | 67 ++++++ .../main/java/org/csploit/msf/Framework.java | 24 +++ .../main/java/org/csploit/msf/License.java | 32 +++ msf/src/main/java/org/csploit/msf/Module.java | 98 +++++++++ .../java/org/csploit/msf/ModuleManager.java | 101 +++++++++ .../main/java/org/csploit/msf/ModuleSet.java | 68 ++++++ .../main/java/org/csploit/msf/Offspring.java | 10 + msf/src/main/java/org/csploit/msf/Option.java | 88 ++++++++ .../java/org/csploit/msf/OptionContainer.java | 50 +++++ .../main/java/org/csploit/msf/arch/Arch.java | 32 +++ .../java/org/csploit/msf/module/ArchSet.java | 57 +++++ .../csploit/msf/module/ModuleDataStore.java | 37 ++++ .../java/org/csploit/msf/module/Platform.java | 118 +++++++++++ .../org/csploit/msf/module/PlatformList.java | 43 ++++ .../java/org/csploit/msf/module/Rank.java | 43 ++++ .../org/csploit/msf/module/Reference.java | 37 ++++ .../org/csploit/msf/module/SiteReference.java | 51 +++++ .../java/org/csploit/msf/module/Target.java | 32 +++ .../csploit/msf/options/AddressOption.java | 37 ++++ .../msf/options/AddressRangeOption.java | 81 ++++++++ .../csploit/msf/options/BooleanOption.java | 26 +++ .../org/csploit/msf/options/EnumOption.java | 36 ++++ .../csploit/msf/options/IntegerOption.java | 29 +++ .../org/csploit/msf/options/PathOption.java | 35 ++++ .../org/csploit/msf/options/PortOption.java | 33 +++ .../org/csploit/msf/options/RawOption.java | 42 ++++ .../org/csploit/msf/options/RegexpOption.java | 29 +++ .../org/csploit/msf/options/StringOption.java | 38 ++++ .../java/org/csploit/msf/DataStoreTest.java | 59 ++++++ .../java/org/csploit/msf/RpcSampleTest.java | 196 ++++++++++++++++++ .../csploit/msf/module/PlatformListTest.java | 24 +++ .../org/csploit/msf/module/PlatformTest.java | 33 +++ settings.gradle | 2 +- 38 files changed, 1854 insertions(+), 1 deletion(-) create mode 100644 msf/.gitignore create mode 100644 msf/build.gradle create mode 100644 msf/src/main/java/org/csploit/msf/Author.java create mode 100644 msf/src/main/java/org/csploit/msf/DataHolder.java create mode 100644 msf/src/main/java/org/csploit/msf/DataStore.java create mode 100644 msf/src/main/java/org/csploit/msf/Exploit.java create mode 100644 msf/src/main/java/org/csploit/msf/Framework.java create mode 100644 msf/src/main/java/org/csploit/msf/License.java create mode 100644 msf/src/main/java/org/csploit/msf/Module.java create mode 100644 msf/src/main/java/org/csploit/msf/ModuleManager.java create mode 100644 msf/src/main/java/org/csploit/msf/ModuleSet.java create mode 100644 msf/src/main/java/org/csploit/msf/Offspring.java create mode 100644 msf/src/main/java/org/csploit/msf/Option.java create mode 100644 msf/src/main/java/org/csploit/msf/OptionContainer.java create mode 100644 msf/src/main/java/org/csploit/msf/arch/Arch.java create mode 100644 msf/src/main/java/org/csploit/msf/module/ArchSet.java create mode 100644 msf/src/main/java/org/csploit/msf/module/ModuleDataStore.java create mode 100644 msf/src/main/java/org/csploit/msf/module/Platform.java create mode 100644 msf/src/main/java/org/csploit/msf/module/PlatformList.java create mode 100644 msf/src/main/java/org/csploit/msf/module/Rank.java create mode 100644 msf/src/main/java/org/csploit/msf/module/Reference.java create mode 100644 msf/src/main/java/org/csploit/msf/module/SiteReference.java create mode 100644 msf/src/main/java/org/csploit/msf/module/Target.java create mode 100644 msf/src/main/java/org/csploit/msf/options/AddressOption.java create mode 100644 msf/src/main/java/org/csploit/msf/options/AddressRangeOption.java create mode 100644 msf/src/main/java/org/csploit/msf/options/BooleanOption.java create mode 100644 msf/src/main/java/org/csploit/msf/options/EnumOption.java create mode 100644 msf/src/main/java/org/csploit/msf/options/IntegerOption.java create mode 100644 msf/src/main/java/org/csploit/msf/options/PathOption.java create mode 100644 msf/src/main/java/org/csploit/msf/options/PortOption.java create mode 100644 msf/src/main/java/org/csploit/msf/options/RawOption.java create mode 100644 msf/src/main/java/org/csploit/msf/options/RegexpOption.java create mode 100644 msf/src/main/java/org/csploit/msf/options/StringOption.java create mode 100644 msf/src/test/java/org/csploit/msf/DataStoreTest.java create mode 100644 msf/src/test/java/org/csploit/msf/RpcSampleTest.java create mode 100644 msf/src/test/java/org/csploit/msf/module/PlatformListTest.java create mode 100644 msf/src/test/java/org/csploit/msf/module/PlatformTest.java diff --git a/msf/.gitignore b/msf/.gitignore new file mode 100644 index 0000000000..796b96d1c4 --- /dev/null +++ b/msf/.gitignore @@ -0,0 +1 @@ +/build diff --git a/msf/build.gradle b/msf/build.gradle new file mode 100644 index 0000000000..5b04692e32 --- /dev/null +++ b/msf/build.gradle @@ -0,0 +1,8 @@ +apply plugin: 'java' + +dependencies { + compile fileTree(dir: 'libs', include: ['*.jar']) + compile 'junit:junit:4.12' + compile 'commons-io:commons-io:2.4' + compile 'org.apache.commons:commons-lang3:3.4' +} \ No newline at end of file diff --git a/msf/src/main/java/org/csploit/msf/Author.java b/msf/src/main/java/org/csploit/msf/Author.java new file mode 100644 index 0000000000..7e3b3bd062 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/Author.java @@ -0,0 +1,37 @@ +package org.csploit.msf; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Represent an author + */ +public class Author { + private static Pattern MAIL = Pattern.compile("<(.+)>"); + + private String name; + private String email; + + public Author(String name, String email) { + this.name = name; + this.email = email; + } + + @Override + public String toString() { + if(email != null) { + return name + " <" + email + ">"; + } else { + return name; + } + } + + public static Author fromString(String s) { + Matcher matcher = MAIL.matcher(s); + if(matcher.matches()) { + return new Author(s.substring(0, matcher.start()), matcher.group(1)); + } else { + return new Author(s, null); + } + } +} diff --git a/msf/src/main/java/org/csploit/msf/DataHolder.java b/msf/src/main/java/org/csploit/msf/DataHolder.java new file mode 100644 index 0000000000..e6acb5b292 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/DataHolder.java @@ -0,0 +1,8 @@ +package org.csploit.msf; + +/** + * A class that hold a DataStore instance + */ +public interface DataHolder { + DataStore getDataStore(); +} diff --git a/msf/src/main/java/org/csploit/msf/DataStore.java b/msf/src/main/java/org/csploit/msf/DataStore.java new file mode 100644 index 0000000000..7709c71692 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/DataStore.java @@ -0,0 +1,113 @@ +package org.csploit.msf; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * The data store is just a bitbucket that holds keyed values. It is used + * by various classes to hold option values and other state information. + */ +public class DataStore extends HashMap { + protected Set imported = new HashSet<>(); + protected Set defaults = new HashSet<>(); + + @Override + public String put(String key, String value) { + key = findKeyCase(key); + + defaults.remove(key); + imported.remove(key); + + return super.put(key, value); + } + + @Override + public String get(Object key) { + String k = (key instanceof String) ? (String) key : key.toString(); + return super.get(findKeyCase(k)); + } + + public void updateValue(String key, String value) { + super.put(key, value); + } + + /** + * This method is a helper method that imports the default value for + * all of the supplied options + */ + public void importOptions(OptionContainer options, boolean isDefault, boolean overwrite) { + for(Option opt : options.values()) { + String name = opt.getName(); + if(containsKey(name) && !overwrite) { + continue; + } + if(opt.haveDefaultValue() && (overwrite || get(name) == null)) { + String val = opt.display(opt.defaultValue); + importOption(name, val, true, isDefault); + } + } + } + + public void importOptions(OptionContainer options, boolean isDefault) { + importOptions(options, isDefault, false); + } + + public void importOptions(OptionContainer options) { + importOptions(options, false, false); + } + + public void importOption(String name, String val, boolean imported, boolean isDefault) { + if(imported) { + this.imported.add(name); + } + + if(isDefault) { + defaults.add(name); + } + + super.put(name, val); + } + + public void importOption(String name, String val, boolean imported) { + importOption(name, val, imported, false); + } + + public void importOption(String name, String val) { + importOption(name, val, true, false); + } + + public synchronized Map userDefined() { + Map res = new HashMap<>(); + + for (String key : keySet()) { + if (!imported.contains(key)) { + res.put(key, super.get(key)); + } + } + + return res; + } + + public void clearNotUserDefined() { + for(String key : imported) { + if(defaults.remove(key)) { + remove(key); + } + } + } + + protected String findKeyCase(String k) { + + if(k == null) + return null; + + for(String key : keySet()) { + if(key.toLowerCase().equals(k.toLowerCase())) + return key; + } + + return k; + } +} diff --git a/msf/src/main/java/org/csploit/msf/Exploit.java b/msf/src/main/java/org/csploit/msf/Exploit.java new file mode 100644 index 0000000000..151793a01f --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/Exploit.java @@ -0,0 +1,67 @@ +package org.csploit.msf; + +import org.csploit.msf.module.ArchSet; +import org.csploit.msf.module.PlatformList; +import org.csploit.msf.module.Reference; +import org.csploit.msf.module.Target; + +/** + * Represent an exploit module + */ +public class Exploit extends Module { + private Target[] targets; + private int defaultTarget = -1; + + public Exploit() { + super(); + } + + // we may should use a Builder + public Exploit(String name, + String description, + String version, + Author[] authors, + ArchSet arch, + PlatformList platform, + Reference[] references, + boolean privileged, + License license, + Target[] targets, + int defaultTarget + ) { + super(name, description, version, authors, arch, platform, references, privileged, license); + this.targets = targets; + this.defaultTarget = defaultTarget; + } + + @Override + public String getType() { + return "exploit"; + } + + protected void setTargets(Target[] targets) { + this.targets = targets; + } + + public Target[] getTargets() { + return targets; + } + + public Target getTarget() { + String val = datastore.get("TARGET"); + + if(val != null) { + try { + return targets[Integer.parseInt(val)]; + } catch (NumberFormatException | IndexOutOfBoundsException e) { + // ignore + } + } + + if(defaultTarget >= 0 && defaultTarget < targets.length) { + return targets[defaultTarget]; + } + + return null; + } +} diff --git a/msf/src/main/java/org/csploit/msf/Framework.java b/msf/src/main/java/org/csploit/msf/Framework.java new file mode 100644 index 0000000000..10ed7e57b1 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/Framework.java @@ -0,0 +1,24 @@ +package org.csploit.msf; + +/** + * Represent a MetaSploit Framework instance + */ +public class Framework implements DataHolder { + + private DataStore dataStore; + private ModuleManager moduleManager; + + public Framework() { + dataStore = new DataStore(); + moduleManager = new ModuleManager(this, "all"); + } + + @Override + public DataStore getDataStore() { + return dataStore; + } + + public ModuleManager getModuleManager() { + return moduleManager; + } +} diff --git a/msf/src/main/java/org/csploit/msf/License.java b/msf/src/main/java/org/csploit/msf/License.java new file mode 100644 index 0000000000..4672e34dd3 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/License.java @@ -0,0 +1,32 @@ +package org.csploit.msf; + +/** + * A license + */ +public enum License { + MSF("Metasploit Framework License (BSD)"), + GPL("GNU Public License v2.0"), + BSD("BSD License"), + ARTISTIC("Perl Artistic License"), + UNKNOWN("Unknown License"); + + String name; + + License(String name) { + this.name = name; + } + + public String toString() { + return name; + } + + public static License fromString(String value) { + if(value != null) { + for (License l : values()) { + if (l.name.toLowerCase().startsWith(value.toLowerCase())) + return l; + } + } + return UNKNOWN; + } +} diff --git a/msf/src/main/java/org/csploit/msf/Module.java b/msf/src/main/java/org/csploit/msf/Module.java new file mode 100644 index 0000000000..5b41db0404 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/Module.java @@ -0,0 +1,98 @@ +package org.csploit.msf; + +import org.csploit.msf.module.ArchSet; +import org.csploit.msf.module.ModuleDataStore; +import org.csploit.msf.module.PlatformList; +import org.csploit.msf.module.Reference; + +import java.util.Collection; + +/** + * Represent a module of the MSF + */ +public abstract class Module implements Offspring, DataHolder { + protected Author[] authors; + protected ArchSet arch; + protected PlatformList platform; + protected Reference[] references; + protected OptionContainer options; + protected Framework framework; + protected ModuleDataStore datastore; + protected boolean privileged; + protected License license; + + protected String name; + protected String refname; + protected String description; + protected String version; + + public Module(String name, String description, String version, Author[] authors, ArchSet arch, PlatformList platform, Reference[] references, boolean privileged, License license ) { + this.name = name; + this.description = description; + this.version = version; + this.authors = authors; + this.arch = arch; + this.platform = platform; + this.references = references; + this.privileged = privileged; + this.license = license; + this.options = new OptionContainer(); + this.datastore = new ModuleDataStore(this); + } + + public Module() { + this("No module name", "No module description", "0", null, new ArchSet(), new PlatformList(), null, false, License.MSF); + } + + @Override + public boolean haveFramework() { + return framework != null; + } + + @Override + public Framework getFramework() { + return framework; + } + + @Override + public void setFramework(Framework framework) { + this.framework = framework; + } + + @Override + public DataStore getDataStore() { + return datastore; + } + + public String getRefname() { + return refname; + } + + public void setRefname(String refname) { + this.refname = refname; + } + + public abstract String getType(); + + public String getFullName() { + return getType() + "/" + getRefname(); + } + + public String getShortName() { + String[] parts = getRefname().split("/"); + return parts[parts.length - 1]; + } + + public void registerOption(String name, Option option, boolean advanced, boolean evasion) { + options.addOption(name, option, advanced, evasion); + } + + public Collection getinvalidOptions() { + return options.getInvalidOptions(getDataStore()); + } + + @Override + public int hashCode() { + return refname != null ? refname.hashCode() : 0; + } +} diff --git a/msf/src/main/java/org/csploit/msf/ModuleManager.java b/msf/src/main/java/org/csploit/msf/ModuleManager.java new file mode 100644 index 0000000000..a87a532e93 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/ModuleManager.java @@ -0,0 +1,101 @@ +package org.csploit.msf; + +import java.util.HashMap; +import java.util.Map; + +/** + * Manage all framework modules + */ +public class ModuleManager implements Offspring { + + private final static String[] validModuleTypes = { + "encoder", + "exploit", + "nop", + "auxiliary", + "payload", + "post" + }; + + private Map sets = new HashMap<>(); + private Framework framework; + + public ModuleManager(Framework framework, String types) { + this(framework, types.equals("all") ? validModuleTypes : types.split(",")); + } + + public ModuleManager(Framework framework, String[] types) { + setFramework(framework); + for(String type : types) { + type = type.trim(); + if(isValidType(type)) + initSet(type); + } + } + + private void initSet(String type) { + if(sets.containsKey(type)) + return; + + ModuleSet set = ModuleSet.forType(type); + set.setFramework(getFramework()); + sets.put(type, set); + } + + private static boolean isValidType(String type) { + for(String t : validModuleTypes) { + if(t.equals(type)) + return true; + } + return false; + } + + public Module get(String name) { + String[] parts = name.split("/"); + String refname; + + if(!sets.containsKey(parts[0])) { + if(!isValidType(parts[0])) { + return worldSearch(name); + } else { + return null; + } + } + + refname = name.substring(parts[0].length() + 1); + + return sets.get(parts[0]).get(refname); + } + + private Module worldSearch(String name) { + for(ModuleSet set : sets.values()) { + Module m = set.get(name); + if(m != null) + return m; + } + return null; + } + + public void put(Module module) { + String type = module.getType(); + if(!sets.containsKey(type)) { + return; + } + sets.get(type).add(module); + } + + @Override + public boolean haveFramework() { + return framework != null; + } + + @Override + public Framework getFramework() { + return framework; + } + + @Override + public void setFramework(Framework framework) { + this.framework = framework; + } +} diff --git a/msf/src/main/java/org/csploit/msf/ModuleSet.java b/msf/src/main/java/org/csploit/msf/ModuleSet.java new file mode 100644 index 0000000000..d4d1a5f49c --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/ModuleSet.java @@ -0,0 +1,68 @@ +package org.csploit.msf; + +import org.csploit.msf.module.ArchSet; +import org.csploit.msf.module.PlatformList; + +import java.util.HashMap; + +/** + * A module set contains zero or more named module classes of an arbitrary + * type. + */ +public class ModuleSet extends HashMap implements Offspring { + protected String type; + private Framework framework; + + public ModuleSet(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + @Override + public boolean haveFramework() { + return framework != null; + } + + @Override + public Framework getFramework() { + return framework; + } + + @Override + public void setFramework(Framework framework) { + this.framework = framework; + } + + public void add(Module module) { + module.setFramework(framework); + put(module.getRefname(), module); + } + + public ModuleSet filter(ArchSet architectures, PlatformList platforms) { + ModuleSet res = new ModuleSet(getType()); + res.setFramework(framework); + for(Module m : values()) { + + if(architectures != null && m.arch.intersect(architectures).isEmpty()) { + continue; + } + + if(platforms != null && m.platform.intersect(platforms).isEmpty()) { + continue; + } + + //TODO: custom filter + + res.add(m); + } + return res; + } + + public static ModuleSet forType(String type) { + //TODO: PayloadSet + return new ModuleSet(type); + } +} diff --git a/msf/src/main/java/org/csploit/msf/Offspring.java b/msf/src/main/java/org/csploit/msf/Offspring.java new file mode 100644 index 0000000000..fb2015cf85 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/Offspring.java @@ -0,0 +1,10 @@ +package org.csploit.msf; + +/** + * CLasses that ave a reference to the framework + */ +public interface Offspring { + boolean haveFramework(); + Framework getFramework(); + void setFramework(Framework framework); +} diff --git a/msf/src/main/java/org/csploit/msf/Option.java b/msf/src/main/java/org/csploit/msf/Option.java new file mode 100644 index 0000000000..c246ce3159 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/Option.java @@ -0,0 +1,88 @@ +package org.csploit.msf; + +import org.csploit.msf.options.StringOption; + +/** + * Represent an option + */ +public abstract class Option { + protected boolean advanced; + protected T defaultValue; + protected String description; + protected boolean evasion; + protected String name; + protected Module owner; + protected boolean required; + + public Option(String name, boolean required, String description, T defaultValue) { + this.name = name; + this.required = required; + this.description = description; + this.defaultValue = defaultValue; + } + + public Option(String name, String description, T defaultValue) { + this(name, false, description, defaultValue); + } + + public boolean isAdvanced() { + return advanced; + } + + public void setAdvanced(boolean advanced) { + this.advanced = advanced; + } + + public T getDefaultValue() { + return defaultValue; + } + + public boolean haveDefaultValue() { + return defaultValue != null; + } + + public String getDescription() { + return description; + } + + public boolean isEvasion() { + return evasion; + } + + public void setEvasion(boolean evasion) { + this.evasion = evasion; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Module getOwner() { + return owner; + } + + public void setOwner(Module owner) { + this.owner = owner; + } + + public boolean isRequired() { + return required; + } + + protected abstract T normalize(String input); + + protected String display(T value) { + return value.toString(); + } + + protected boolean isValid(T input) { + if(isRequired() && (input == null || input.toString().isEmpty())) { + return false; + } + return true; + } +} diff --git a/msf/src/main/java/org/csploit/msf/OptionContainer.java b/msf/src/main/java/org/csploit/msf/OptionContainer.java new file mode 100644 index 0000000000..68de7115fa --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/OptionContainer.java @@ -0,0 +1,50 @@ +package org.csploit.msf; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +/** + * A container of options + */ +class OptionContainer extends HashMap { + + public void addAdvancedOption(String name, Option option) { + addOption(name, option, true, false); + } + + public void addEvasionOption(String name, Option option) { + addOption(name, option, false, true); + } + + public void addOption(String name, Option option, boolean advanced, boolean evasion) { + option.setEvasion(evasion); + option.setAdvanced(advanced); + put(name, option); + } + + /** + * this should be the validate method in the MSF. + * I decided to change it because updating dataStore + * within modules will write global values into it. + */ + @SuppressWarnings("unchecked") + public Collection getInvalidOptions(DataStore dataStore) { + ArrayList errors = new ArrayList<>(); + + for(Map.Entry entry : entrySet()) { + String name = entry.getKey(); + Option option = entry.getValue(); + + String val = dataStore.get(name); + Object normalized = option.normalize(val); + + if(!option.isValid(normalized)) { + errors.add(name); + } + } + + return errors; + } +} diff --git a/msf/src/main/java/org/csploit/msf/arch/Arch.java b/msf/src/main/java/org/csploit/msf/arch/Arch.java new file mode 100644 index 0000000000..54e5137ad8 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/arch/Arch.java @@ -0,0 +1,32 @@ +package org.csploit.msf.arch; + +/** + * Machines architectures + * + * source: lib/rex/constants.rb + */ +public enum Arch { + ANY, + X86, + X86_64, + X64, + MIPS, + MIPSLE, + MIPSBE, + PPC, + PPC64, + CBEA, + CBEA64, + SPARC, + CMD, + PHP, + TTY, + ARMLE, + ARMBE, + JAVA, + RUBY, + DALVIK, + PYTHON, + NODEJS, + FIREFOX; +} \ No newline at end of file diff --git a/msf/src/main/java/org/csploit/msf/module/ArchSet.java b/msf/src/main/java/org/csploit/msf/module/ArchSet.java new file mode 100644 index 0000000000..36c407f490 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/module/ArchSet.java @@ -0,0 +1,57 @@ +package org.csploit.msf.module; + +import java.util.Collection; +import java.util.HashSet; +import org.csploit.msf.arch.Arch; + +/** + * A container for architectures supported by a module + */ +public class ArchSet extends HashSet { + + public ArchSet() { + super(); + } + + public ArchSet(String s) { + this(s.split(",")); + } + + public ArchSet(String[] a) { + super(a.length); + + for(String arch : a) { + add(Arch.valueOf(arch.trim().toUpperCase())); + } + } + + private ArchSet(Collection other) { + super(other); + } + + public boolean isSupported(Arch arch) { + return arch == Arch.ANY || contains(arch); + } + + public ArchSet intersect(ArchSet other) { + ArchSet res = new ArchSet(this); + res.retainAll(other); + return res; + } + + @Override + public String toString() { + if(isEmpty()) + return ""; + StringBuilder sb = new StringBuilder(); + + for (Arch a : this) { + if(sb.length() > 0) { + sb.append(", "); + } + sb.append(a.toString()); + } + + return sb.toString(); + } +} diff --git a/msf/src/main/java/org/csploit/msf/module/ModuleDataStore.java b/msf/src/main/java/org/csploit/msf/module/ModuleDataStore.java new file mode 100644 index 0000000000..931a4750de --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/module/ModuleDataStore.java @@ -0,0 +1,37 @@ +package org.csploit.msf.module; + +import org.csploit.msf.Module; + +/** + * DataStore wrapper for modules that will attempt to back values against the + * framework's datastore if they aren't found in the module's datastore. This + * is done to simulate global data store values. + */ +public class ModuleDataStore extends org.csploit.msf.DataStore { + private Module module; + + public ModuleDataStore(Module module) { + this.module = module; + } + + public boolean isDefault(String key) { + return defaults.contains(key); + } + + @Override + public String get(Object key) { + String k, res; + + k = key != null ? key.toString() : null; + k = findKeyCase(k); + res = null; + if(!isDefault(k)) + res = super.get(key); + + if(res == null && module != null && module.haveFramework()) { + res = module.getFramework().getDataStore().get(k); + } + + return res != null ? res : super.get(k); + } +} diff --git a/msf/src/main/java/org/csploit/msf/module/Platform.java b/msf/src/main/java/org/csploit/msf/module/Platform.java new file mode 100644 index 0000000000..083a0893cf --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/module/Platform.java @@ -0,0 +1,118 @@ +package org.csploit.msf.module; + +/** + * A platform + */ +public enum Platform { + WINDOWS("Windows", 1, 0, 0), + WINDOWS_95("Windows 95", 1, 1, 0), + WINDOWS_98("Windows 98", 1, 2, 0), + WINDOWS_98_FE("Windows 98 FE", 1, 2, 1), + WINDOWS_98_SE("Windows 98 SE", 1, 2, 2), + WINDOWS_ME("Windows ME", 1, 3, 0), + WINDOWS_NT("Windows NT", 1, 4, 0), + WINDOWS_NT_SP0("Windows NT SP0", 1, 4, 1), + WINDOWS_NT_SP1("Windows NT SP1", 1, 4, 2), + WINDOWS_NT_SP2("Windows NT SP2", 1, 4, 3), + WINDOWS_NT_SP3("Windows NT SP3", 1, 4, 4), + WINDOWS_NT_SP4("Windows NT SP4", 1, 4, 5), + WINDOWS_NT_SP5("Windows NT SP5", 1, 4, 6), + WINDOWS_NT_SP6("Windows NT SP6", 1, 4, 7), + WINDOWS_NT_SP6A("Windows NT SP6a", 1, 4, 8), + WINDOWS_2000("Windows 2000", 1, 5, 0), + WINDOWS_2000_SP0("Windows 2000 SP0", 1, 5, 1), + WINDOWS_2000_SP1("Windows 2000 SP1", 1, 5, 2), + WINDOWS_2000_SP2("Windows 2000 SP2", 1, 5, 3), + WINDOWS_2000_SP3("Windows 2000 SP3", 1, 5, 4), + WINDOWS_2000_SP4("Windows 2000 SP4", 1, 5, 5), + WINDOWS_XP("Windows XP", 1, 6, 0), + WINDOWS_XP_SP0("Windows XP SP0", 1, 6, 1), + WINDOWS_XP_SP1("Windows XP SP1", 1, 6, 2), + WINDOWS_XP_SP2("Windows XP SP2", 1, 6, 3), + WINDOWS_XP_SP3("Windows XP SP3", 1, 6, 4), + WINDOWS_2003("Windows 2003", 1, 7, 0), + WINDOWS_2003_SP0("Windows 2003 SP0", 1, 7, 1), + WINDOWS_2003_SP1("Windows 2003 SP1", 1, 7, 2), + WINDOWS_VISTA("Windows Vista", 1, 8, 0), + WINDOWS_VISTA_SP0("Windows Vista SP0", 1, 8, 1), + WINDOWS_VISTA_SP1("Windows Vista SP1", 1, 8, 2), + WINDOWS_7("Windows 7", 1, 9, 0), + WINDOWS_8("Windows 8", 1, 10, 0), + NETWARE("Netware", 2, 0, 0), + ANDROID("Android", 3, 0, 0), + JAVA("Java", 4, 0, 0), + RUBY("Ruby", 5, 0, 0), + LINUX("Linux", 6, 0, 0), + CISCO("Cisco", 7, 0, 0), + SOLARIS("Solaris", 8, 0, 0), + SOLARIS_V4("Solaris V4", 8, 1, 0), + SOLARIS_V5("Solaris V5", 8, 2, 0), + SOLARIS_V6("Solaris V6", 8, 3, 0), + SOLARIS_V7("Solaris V7", 8, 4, 0), + SOLARIS_V8("Solaris V8", 8, 5, 0), + SOLARIS_V9("Solaris V9", 8, 6, 0), + SOLARIS_V10("Solaris V10", 8, 7, 0), + OSX("OSX", 9, 0, 0), + BSD("BSD", 10, 0, 0), + OPENBSD("OpenBSD", 11, 0, 0), + BSDI("BSDi", 12, 0, 0), + NETBSD("NetBSD", 13, 0, 0), + FREEBSD("FreeBSD", 14, 0, 0), + AIX("AIX", 15, 0, 0), + HPUX("HPUX", 16, 0, 0), + IRIX("Irix", 17, 0, 0), + UNIX("Unix", 18, 0, 0), + PHP("PHP", 19, 0, 0), + JAVASCRIPT("JavaScript", 20, 0, 0), + PYTHON("Python", 21, 0, 0), + NODEJS("NodeJS", 22, 0, 0), + FIREFOX("Firefox", 23, 0, 0), + MAINFRAME("Mainframe", 24, 0, 0); + + protected String realName; + protected int major; + protected int minor; + protected int patch; + + Platform(String realName, int major, int minor, int patch) { + this.realName = realName; + this.major = major; + this.minor = minor; + this.patch = patch; + } + + public String getRealName() { + return realName; + } + + /** + * is a platform a subset of another ? + * @param other possible ancestor to test + * @return true if {@code other} is a platform that contains {@code this} + */ + public boolean subsetOf(Platform other) { + if(other.major != major) + return false; + if(other.minor == 0) + return true; + if(other.minor != minor) + return false; + if(other.patch == 0) + return true; + if(other.patch != patch) + return false; + return true; + } + + public static Platform fromString(String s) { + if(s != null) { + s = s.trim(); + for (Platform pl : values()) { + if (pl.getRealName().equals(s)) + return pl; + } + } + return null; + } + +} diff --git a/msf/src/main/java/org/csploit/msf/module/PlatformList.java b/msf/src/main/java/org/csploit/msf/module/PlatformList.java new file mode 100644 index 0000000000..a4f5cdc464 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/module/PlatformList.java @@ -0,0 +1,43 @@ +package org.csploit.msf.module; + +import java.util.HashSet; + +/** + * A list of platforms + */ +public class PlatformList extends HashSet { + + public PlatformList() { + super(); + } + + public PlatformList(String s) { + this(s.split(",")); + } + + public PlatformList(String[] plats) { + super(plats.length); + for(String s : plats) { + Platform platform = Platform.fromString(s); + if(platform != null) { + add(platform); + } + } + } + + public PlatformList intersect(PlatformList other) { + PlatformList res = new PlatformList(); + + for(Platform pl1 : this) { + for(Platform pl2 : other) { + if(pl1.subsetOf(pl2)) { + res.add(pl1); + } else if(pl2.subsetOf(pl1)) { + res.add(pl2); + } + } + } + + return res; + } +} diff --git a/msf/src/main/java/org/csploit/msf/module/Rank.java b/msf/src/main/java/org/csploit/msf/module/Rank.java new file mode 100644 index 0000000000..b74854255b --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/module/Rank.java @@ -0,0 +1,43 @@ +package org.csploit.msf.module; + +/** + * A module rank + */ +public enum Rank { + MANUAL(0, "manual"), + LOW(100, "low"), + AVERAGE(200, "average"), + NORMAL(300, "normal"), + GOOD(400, "good"), + GREAT(500, "great"), + EXCELLENT(600, "excellent") + ; + + private String name; + private int value; + + Rank(int value, String name) { + this.value = value; + this.name = name; + } + + public static Rank fromName(String name) { + name = name.trim(); + name = name.toLowerCase(); + for (Rank r : values()) { + if (r.name.toLowerCase().equals(name)) { + return r; + } + } + return null; + } + + public static Rank fromValue(int value) { + for (Rank r : values()) { + if (r.value <= value) { + return r; + } + } + return null; + } +} diff --git a/msf/src/main/java/org/csploit/msf/module/Reference.java b/msf/src/main/java/org/csploit/msf/module/Reference.java new file mode 100644 index 0000000000..8ad1c18a23 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/module/Reference.java @@ -0,0 +1,37 @@ +package org.csploit.msf.module; + +/** + * A reference to some sort of information. This is typically a URL, but could + * be any type of referential value that people could use to research a topic. + */ +public class Reference { + protected String str; + + public Reference(String str) { + this.str = "" + str; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Reference reference = (Reference) o; + + return str.equals(reference.str); + } + + @Override + public int hashCode() { + return str.hashCode(); + } + + @Override + public String toString() { + return str; + } + + public static Reference fromString(String s) { + return new Reference(s); + } +} diff --git a/msf/src/main/java/org/csploit/msf/module/SiteReference.java b/msf/src/main/java/org/csploit/msf/module/SiteReference.java new file mode 100644 index 0000000000..8b012171a1 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/module/SiteReference.java @@ -0,0 +1,51 @@ +package org.csploit.msf.module; + +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Pattern; + +/** + * A reference to a website. + */ +public class SiteReference extends Reference { + protected String ctx_id; + protected String ctx_val; + + private final static Pattern SIMPLE_URL_PATTERN = Pattern.compile("(http://|https://|ftp://)"); + + private final static Map formats = new HashMap() {{ + put("OSVDB", "http://www.osvdb.org/%s"); + put("CVE", "http://cvedetails.com/cve/%s/"); + put("CWE", "https://cwe.mitre.org/data/definitions/%s.html"); + put("BID", "http://www.securityfocus.com/bid/%s"); + put("MSB", "http://technet.microsoft.com/en-us/security/bulletin/%s"); + put("EDB", "https://www.exploit-db.com/exploits/%s"); + put("US-CERT-VU", "http://www.kb.cert.org/vuls/id/%s"); + put("ZDI", "http://www.zerodayinitiative.com/advisories/ZDI-%s"); + put("WPVDB", "https://wpvulndb.com/vulnerabilities/%s"); + put("PACKETSTORM", "https://packetstormsecurity.com/files/%s"); + put("URL", "%s"); + }}; + + public SiteReference(String ctx_id, String ctx_val) { + super(""); + this.ctx_id = ctx_id; + this.ctx_val = ctx_val; + + if(formats.containsKey(ctx_id)) { + str = String.format(formats.get(ctx_id), ctx_val); + } else { + str = ctx_id; + if(ctx_val != null) { + str += " (" + ctx_val + ")"; + } + } + } + + public static SiteReference fromString(String str) { + if(!SIMPLE_URL_PATTERN.matcher(str).matches()) { + return null; + } + return new SiteReference("URL", str); + } +} diff --git a/msf/src/main/java/org/csploit/msf/module/Target.java b/msf/src/main/java/org/csploit/msf/module/Target.java new file mode 100644 index 0000000000..9262f7d25f --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/module/Target.java @@ -0,0 +1,32 @@ +package org.csploit.msf.module; + +/** + * Represent a target + */ +public class Target { + private String name; + private PlatformList platform; + private ArchSet arch; + + public Target(String name, PlatformList platform, ArchSet arch) { + this.name = name; + this.platform = platform; + this.arch = arch; + } + + public Target(String name) { + this(name, new PlatformList(), new ArchSet()); + } + + public String getName() { + return name; + } + + public PlatformList getPlatform() { + return platform; + } + + public ArchSet getArch() { + return arch; + } +} diff --git a/msf/src/main/java/org/csploit/msf/options/AddressOption.java b/msf/src/main/java/org/csploit/msf/options/AddressOption.java new file mode 100644 index 0000000000..2c0d502217 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/options/AddressOption.java @@ -0,0 +1,37 @@ +package org.csploit.msf.options; + +import org.csploit.msf.Option; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +/** + * Network address option. + */ +public class AddressOption extends Option { + + public AddressOption(String name, boolean required, String description, InetAddress defaultValue) { + super(name, required, description, defaultValue); + } + + public AddressOption(String name, boolean required, String description, String defaultValue) { + super(name, required, description, sNormalize(defaultValue)); + } + + public AddressOption(String name, String description, InetAddress defaultValue) { + super(name, description, defaultValue); + } + + @Override + protected InetAddress normalize(String input) { + return sNormalize(input); + } + + private static InetAddress sNormalize(String input) { + try { + return input != null ? InetAddress.getByName(input) : null; + } catch (UnknownHostException e) { + return null; + } + } +} diff --git a/msf/src/main/java/org/csploit/msf/options/AddressRangeOption.java b/msf/src/main/java/org/csploit/msf/options/AddressRangeOption.java new file mode 100644 index 0000000000..422830b518 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/options/AddressRangeOption.java @@ -0,0 +1,81 @@ +package org.csploit.msf.options; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.csploit.msf.Option; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.InetAddress; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.List; + +/** + * Network address range option. + */ +public class AddressRangeOption extends Option { + + public AddressRangeOption(String name, boolean required, String description, InetAddress[] defaultValue) { + super(name, required, description, defaultValue); + } + + public AddressRangeOption(String name, String description, InetAddress[] defaultValue) { + super(name, description, defaultValue); + } + + @Override + protected InetAddress[] normalize(String input) { + if(input == null) + return null; + + if(input.startsWith("file:")) { + InputStream is = null; + try { + input = input.substring(5).trim(); + is = new FileInputStream(new File(input)); + List lines = IOUtils.readLines(is); + ArrayList result = new ArrayList<>(); + + for(String line : lines) { + try { + result.add(InetAddress.getByName(line.trim())); + } catch (UnknownHostException e) { + // ignore + } + } + + return result.toArray(new InetAddress[result.size()]); + } catch (IOException e) { + // ignore + } finally { + IOUtils.closeQuietly(is); + } + } else if ( input.startsWith("rand:")) { + throw new UnsupportedOperationException("random address ranges not supported"); + } else { + String[] parts = input.split(" "); + ArrayList result = new ArrayList<>(); + + for(String part : parts) { + try { + result.add(InetAddress.getByName(part)); + } catch (UnknownHostException e) { + // ignore + } + } + + return result.toArray(new InetAddress[result.size()]); + } + return null; + } + + @Override + protected String display(InetAddress[] value) { + return StringUtils.join(value, " "); + } +} diff --git a/msf/src/main/java/org/csploit/msf/options/BooleanOption.java b/msf/src/main/java/org/csploit/msf/options/BooleanOption.java new file mode 100644 index 0000000000..768553640f --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/options/BooleanOption.java @@ -0,0 +1,26 @@ +package org.csploit.msf.options; + +import org.csploit.msf.Option; + +import java.util.regex.Pattern; + +/** + * Boolean option. + */ +public class BooleanOption extends Option { + private static final Pattern TRUE = Pattern.compile("^(y|yes|t|1|true)$", Pattern.CASE_INSENSITIVE); + private static final Pattern BOOLEAN = Pattern.compile("^(y|yes|n|no|t|f|0|1|true|false)$", Pattern.CASE_INSENSITIVE); + + public BooleanOption(String name, boolean required, String description, Boolean defaultValue) { + super(name, required, description, defaultValue); + } + + public BooleanOption(String name, String description, Boolean defaultValue) { + super(name, description, defaultValue); + } + + @Override + protected Boolean normalize(String input) { + return input != null && TRUE.matcher(input).matches(); + } +} diff --git a/msf/src/main/java/org/csploit/msf/options/EnumOption.java b/msf/src/main/java/org/csploit/msf/options/EnumOption.java new file mode 100644 index 0000000000..d7a276710b --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/options/EnumOption.java @@ -0,0 +1,36 @@ +package org.csploit.msf.options; + +import org.csploit.msf.Option; + +/** + * Enum option. + */ +public class EnumOption extends Option { + + private String[] enums; + + public EnumOption(String name, boolean required, String description, String defaultValue, String[] enums) { + super(name, required, description, defaultValue); + this.enums = enums; + } + + public EnumOption(String name, String description, String defaultValue, String[] enums) { + super(name, description, defaultValue); + this.enums = enums; + } + + @Override + protected String normalize(String input) { + for(String s : enums) { + if(s.equals(input)) { + return s; + } + } + return null; + } + + @Override + protected boolean isValid(String input) { + return super.isValid(input) && (input == null || normalize(input) != null); + } +} diff --git a/msf/src/main/java/org/csploit/msf/options/IntegerOption.java b/msf/src/main/java/org/csploit/msf/options/IntegerOption.java new file mode 100644 index 0000000000..72bec85aa3 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/options/IntegerOption.java @@ -0,0 +1,29 @@ +package org.csploit.msf.options; + +import org.csploit.msf.Option; + +/** + * Integer option. + */ +public class IntegerOption extends Option { + public IntegerOption(String name, boolean required, String description, Integer defaultValue) { + super(name, required, description, defaultValue); + } + + public IntegerOption(String name, String description, Integer defaultValue) { + super(name, description, defaultValue); + } + + @Override + protected Integer normalize(String input) { + try { + if (input.startsWith("0x")) { + return Integer.parseInt(input.substring(2), 16); + } else { + return Integer.parseInt(input); + } + } catch (NumberFormatException e) { + return null; + } + } +} diff --git a/msf/src/main/java/org/csploit/msf/options/PathOption.java b/msf/src/main/java/org/csploit/msf/options/PathOption.java new file mode 100644 index 0000000000..1443fc09f7 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/options/PathOption.java @@ -0,0 +1,35 @@ +package org.csploit.msf.options; + +import org.csploit.msf.Option; + +import java.io.File; + +/** + * File system path option. + */ +public class PathOption extends Option { + + public PathOption(String name, boolean required, String description, File defaultValue) { + super(name, required, description, defaultValue); + } + + public PathOption(String name, String description, File defaultValue) { + super(name, description, defaultValue); + } + + @Override + protected File normalize(String input) { + File res = new File(input); + return res.exists() ? res : null; + } + + @Override + protected boolean isValid(File input) { + return super.isValid(input) && (input == null || input.exists()); + } + + @Override + protected String display(File value) { + return value.getAbsolutePath(); + } +} diff --git a/msf/src/main/java/org/csploit/msf/options/PortOption.java b/msf/src/main/java/org/csploit/msf/options/PortOption.java new file mode 100644 index 0000000000..8094bb719f --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/options/PortOption.java @@ -0,0 +1,33 @@ +package org.csploit.msf.options; + +import org.csploit.msf.Option; + +/** + * Network port option. + */ +public class PortOption extends Option { + + public PortOption(String name, boolean required, String description, Integer defaultValue) { + super(name, required, description, defaultValue); + } + + public PortOption(String name, String description, Integer defaultValue) { + super(name, description, defaultValue); + } + + @Override + protected Integer normalize(String input) { + try { + int val = Integer.parseInt(input); + return isValid(val) ? val : null; + } catch (NumberFormatException e) { + // ignore + } + return null; + } + + @Override + protected boolean isValid(Integer input) { + return super.isValid(input) && (input == null || input >= 0 && input <= 65535); + } +} diff --git a/msf/src/main/java/org/csploit/msf/options/RawOption.java b/msf/src/main/java/org/csploit/msf/options/RawOption.java new file mode 100644 index 0000000000..d6868ba70a --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/options/RawOption.java @@ -0,0 +1,42 @@ +package org.csploit.msf.options; + +import org.apache.commons.io.IOUtils; +import org.csploit.msf.Option; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.Arrays; + +/** + * Raw, arbitrary data option. + */ +public class RawOption extends Option { + + public RawOption(String name, boolean required, String description, byte[] defaultValue) { + super(name, required, description, defaultValue); + } + + public RawOption(String name, String description, byte[] defaultValue) { + super(name, description, defaultValue); + } + + @Override + protected byte[] normalize(String input) { + if(input.startsWith("file:")) { + try { + IOUtils.toByteArray(new URI(input)); + } catch (IOException | URISyntaxException e) { + //ignore + } + return null; + } + return input.getBytes(); + } + + @Override + protected String display(byte[] value) { + return Arrays.toString(value); + } +} diff --git a/msf/src/main/java/org/csploit/msf/options/RegexpOption.java b/msf/src/main/java/org/csploit/msf/options/RegexpOption.java new file mode 100644 index 0000000000..74d57cde35 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/options/RegexpOption.java @@ -0,0 +1,29 @@ +package org.csploit.msf.options; + +import org.csploit.msf.Option; + +import java.util.regex.Pattern; + +/** + * A regex option + */ +public class RegexpOption extends Option { + + public RegexpOption(String name, boolean required, String description, Pattern defaultValue) { + super(name, required, description, defaultValue); + } + + public RegexpOption(String name, String description, Pattern defaultValue) { + super(name, description, defaultValue); + } + + @Override + protected Pattern normalize(String input) { + return Pattern.compile(input); + } + + @Override + protected String display(Pattern value) { + return value.pattern(); + } +} diff --git a/msf/src/main/java/org/csploit/msf/options/StringOption.java b/msf/src/main/java/org/csploit/msf/options/StringOption.java new file mode 100644 index 0000000000..449f99da13 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/options/StringOption.java @@ -0,0 +1,38 @@ +package org.csploit.msf.options; + +import org.apache.commons.io.IOUtils; +import org.csploit.msf.Option; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; + +/** + * Option string + */ +public class StringOption extends Option { + + public StringOption(String name, boolean required, String description, String defaultValue) { + super(name, required, description, defaultValue); + } + + public StringOption(String name, String description, String defaultValue) { + super(name, description, defaultValue); + } + + @Override + protected String normalize(String input) { + if(input.startsWith("file:")) { + try { + return IOUtils.toString(new URI(input)); + } catch (IOException | URISyntaxException e) { + //ignore + } + return null; + } + return input; + } +} diff --git a/msf/src/test/java/org/csploit/msf/DataStoreTest.java b/msf/src/test/java/org/csploit/msf/DataStoreTest.java new file mode 100644 index 0000000000..737ccfe511 --- /dev/null +++ b/msf/src/test/java/org/csploit/msf/DataStoreTest.java @@ -0,0 +1,59 @@ +package org.csploit.msf; + +import org.csploit.msf.options.StringOption; +import org.junit.Test; + +import java.util.Set; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +/** + * Test the DataStore class + */ +public class DataStoreTest { + + private DataStore buildDataStoreWithDefaultOption() { + DataStore store = new DataStore(); + OptionContainer options = new OptionContainer(); + + options.addOption("A", + new StringOption("A", "description", "default value"), false, false); + + store.importOptions(options, true); + + return store; + } + + @Test + public void testImportOptions() throws Exception { + DataStore store = buildDataStoreWithDefaultOption(); + + assertThat(store.get("A"), is("default value")); + } + + @Test + public void testUserDefined() throws Exception { + DataStore store = buildDataStoreWithDefaultOption(); + + assertThat(store.userDefined().isEmpty(), is(true)); + + store.put("A", "user-defined value"); + + assertThat(store.userDefined().isEmpty(), is(false)); + } + + @Test + public void testClearNotUserDefined() throws Exception { + DataStore store = buildDataStoreWithDefaultOption(); + + store.put("B", "user-defined value"); + + store.clearNotUserDefined(); + + Set keys = store.keySet(); + + assertThat(keys.contains("B"), is(true)); + assertThat(keys.contains("A"), is(false)); + } +} \ No newline at end of file diff --git a/msf/src/test/java/org/csploit/msf/RpcSampleTest.java b/msf/src/test/java/org/csploit/msf/RpcSampleTest.java new file mode 100644 index 0000000000..3c0c414b1c --- /dev/null +++ b/msf/src/test/java/org/csploit/msf/RpcSampleTest.java @@ -0,0 +1,196 @@ +package org.csploit.msf; + +import static org.junit.Assert.*; +import static org.hamcrest.CoreMatchers.*; + +import org.csploit.msf.module.ArchSet; +import org.csploit.msf.module.PlatformList; +import org.csploit.msf.module.Reference; +import org.csploit.msf.module.SiteReference; +import org.csploit.msf.module.Target; +import org.csploit.msf.options.AddressOption; +import org.csploit.msf.options.BooleanOption; +import org.csploit.msf.options.EnumOption; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +/** + * Test msf library usage for rpc usage + */ +public class RpcSampleTest { + + private class ModuleInfoBase { + public String name,description,license,filepath; + public int rank; + public String[][] references; + public String[] authors; + } + + private class ExploitInfo extends ModuleInfoBase { + public String[] targets; + public int defaultTarget; + } + + private class AuxInfo extends ModuleInfoBase { + public String[] actions; + public int defaultAction; + } + + private class ModuleOptionInfo { + public String type, description; + public boolean required, advanced, evasion; + public T defaultValue; + public String[] enums; + + public ModuleOptionInfo(String type, String description, boolean required, boolean advanced, boolean evasion, T defaultValue, String[] enums) { + this.type = type; + this.description = description; + this.required = required; + this.advanced = advanced; + this.evasion = evasion; + this.defaultValue = defaultValue; + this.enums = enums; + } + + public ModuleOptionInfo(String type, String description, boolean required, boolean advanced, boolean evasion, T defaultValue) { + this(type, description, required, advanced, evasion, defaultValue, null); + } + + public ModuleOptionInfo(String type, String description, boolean required, boolean advanced, boolean evasion) { + this(type, description, required, advanced, evasion, null, null); + } + } + + @Test + public void putExploitTest() { + + ExploitInfo info = new ExploitInfo(); + + info.name = "A funny exploit"; + info.description = "a very long description"; + info.license = License.GPL.toString(); + info.filepath = "whocares"; + info.rank = 300; + info.references = new String[][] { + {"URL", "http://nowhere.com/index.html"}, + {"OSVDB", "12345"} + }; + info.authors = new String[] { + "Someone " + }; + info.targets = new String[] { + "IE / RealOne Player 2", + "IE / RealOne Player 3" + }; + info.defaultTarget = 0; + + + Framework framework = new Framework(); + + ModuleManager mgr = framework.getModuleManager(); + + // deserialize rpc stuff + + Target[] targets = new Target[info.targets.length]; + Author[] authors = new Author[info.authors.length]; + Reference[] references = new Reference[info.references.length]; + License license = License.fromString(info.license); + + for(int i = 0; i < info.targets.length; i++) { + targets[i] = new Target(info.targets[i]); + } + + for(int i = 0; i < info.authors.length; i++) { + authors[i] = Author.fromString(info.authors[i]); + } + + for(int i = 0; i < info.references.length; i++) { + String[] pair = info.references[i]; + String id = pair[0]; + String val = pair[1]; + references[i] = new SiteReference(id, val); + } + + Exploit exploit = new Exploit( + info.name, info.description, "0", authors, + new ArchSet(), new PlatformList(), references, + false, license, targets, 0); + + mgr.put(exploit); + + assertThat(exploit.getFramework(), is(framework)); + assertThat(exploit.license, is(License.GPL)); + assertThat(exploit.getTarget(), is(exploit.getTargets()[0])); + + // receive exploit options + Map options = new HashMap<>(); + + options.put("NTLM::SendNTLM", + new ModuleOptionInfo<>( + "bool", "A", true, true, false, true + )); + options.put("HTTP::uri_encode_mode", + new ModuleOptionInfo<>( + "enum", "B", false, false, true, "hex-normal", new String[] { + "none", "hex-normal", "hex-noslashes", "hex-random", + "hex-all", "u-normal", "u-all", "u-random" + } + )); + options.put("RHOST", + new ModuleOptionInfo<>( + "address", "C", true, false, false + )); + + // put them into the exploit + + for (Map.Entry entry : options.entrySet()) { + ModuleOptionInfo info1 = entry.getValue(); + String name = entry.getKey(); + + exploit.registerOption(name, getOptionForInfo(name, info1), info1.advanced, info1.evasion); + } + + // let's now try to edit an option + + // first in the local datastore + exploit.getDataStore().put("TARGET", "1"); + assertThat(exploit.getTarget(), is(exploit.getTargets()[1])); + exploit.getDataStore().remove("TARGET"); + assertThat(exploit.getTarget(), is(exploit.getTargets()[0])); + + // from global datastore + framework.getDataStore().put("TARGET", "1"); + assertThat(exploit.getTarget(), is(exploit.getTargets()[1])); + framework.getDataStore().remove("TARGET"); + assertThat(exploit.getTarget(), is(exploit.getTargets()[0])); + + // exploit settings should not be valid without the required RHOST options + + assertThat(exploit.getinvalidOptions().isEmpty(), is(false)); + + framework.getDataStore().put("RHOST", "invalid address"); + + assertThat(exploit.getinvalidOptions().isEmpty(), is(false)); + + framework.getDataStore().put("RHOST", "127.0.0.1"); + + assertThat(exploit.getinvalidOptions().isEmpty(), is(true)); + } + + private static Option getOptionForInfo(String name, ModuleOptionInfo info) { + switch (info.type) { + case "bool": + return new BooleanOption(name, info.required, info.description, + ((ModuleOptionInfo)info).defaultValue); + case "enum": + return new EnumOption(name, info.required, info.description, + ((ModuleOptionInfo)info).defaultValue, info.enums); + case "address": + return new AddressOption(name, info.required, info.description, + ((ModuleOptionInfo)info).defaultValue); + } + return null; + } +} diff --git a/msf/src/test/java/org/csploit/msf/module/PlatformListTest.java b/msf/src/test/java/org/csploit/msf/module/PlatformListTest.java new file mode 100644 index 0000000000..b9bbec1d2d --- /dev/null +++ b/msf/src/test/java/org/csploit/msf/module/PlatformListTest.java @@ -0,0 +1,24 @@ +package org.csploit.msf.module; + +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; + +/** + * Test unit for PlatformList class + */ +public class PlatformListTest { + + @Test + public void testIntersect() throws Exception { + PlatformList l1, l2, ex; + + l1 = new PlatformList("Windows 98, Solaris V4"); + l2 = new PlatformList("Windows 98 FE, Solaris"); + ex = new PlatformList("Windows 98 FE, Solaris V4"); + + assertThat(l1.intersect(l2), is(ex)); + assertThat(l2.intersect(l1), is(ex)); + } +} \ No newline at end of file diff --git a/msf/src/test/java/org/csploit/msf/module/PlatformTest.java b/msf/src/test/java/org/csploit/msf/module/PlatformTest.java new file mode 100644 index 0000000000..0735e860e4 --- /dev/null +++ b/msf/src/test/java/org/csploit/msf/module/PlatformTest.java @@ -0,0 +1,33 @@ +package org.csploit.msf.module; + +import static org.junit.Assert.*; +import static org.hamcrest.CoreMatchers.*; +import org.junit.Test; + +/** + * Test unit for Platform enum + */ +public class PlatformTest { + + @Test + public void testFromString() throws Exception { + assertThat(Platform.fromString("Windows"), is(Platform.WINDOWS)); + assertThat(Platform.fromString("Windows NT SP3"), is(Platform.WINDOWS_NT_SP3)); + assertThat(Platform.fromString(null), nullValue()); + assertThat(Platform.fromString("Unknown"), nullValue()); + assertThat(Platform.fromString("Unix"), is(Platform.UNIX)); + } + + @Test + public void testSubsetOf() throws Exception { + assertThat(Platform.WINDOWS_2000_SP0.subsetOf(Platform.WINDOWS), is(true)); + assertThat(Platform.WINDOWS.subsetOf(Platform.WINDOWS_2000), is(false)); + assertThat(Platform.WINDOWS_VISTA_SP0.subsetOf(Platform.WINDOWS_NT_SP0), is(false)); + assertThat(Platform.UNIX.subsetOf(Platform.AIX), is(false)); + assertThat(Platform.SOLARIS_V10.subsetOf(Platform.SOLARIS), is(true)); + + for(Platform platform : Platform.values()) { + assertThat(platform.subsetOf(platform), is(true)); + } + } +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 47bb48eb2b..d07762bec5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1 +1 @@ -include ':cSploit' +include ':cSploit', ':msf' From bda9c1c6f491bf306497ddd815561f9099907ba0 Mon Sep 17 00:00:00 2001 From: tux_mind Date: Sat, 3 Oct 2015 10:02:10 +0200 Subject: [PATCH 02/15] created simple class for Auxiliary, Post and Payload --- .../main/java/org/csploit/msf/Auxiliary.java | 27 +++++++++++++++++++ .../main/java/org/csploit/msf/Payload.java | 25 +++++++++++++++++ msf/src/main/java/org/csploit/msf/Post.java | 24 +++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 msf/src/main/java/org/csploit/msf/Auxiliary.java create mode 100644 msf/src/main/java/org/csploit/msf/Payload.java create mode 100644 msf/src/main/java/org/csploit/msf/Post.java diff --git a/msf/src/main/java/org/csploit/msf/Auxiliary.java b/msf/src/main/java/org/csploit/msf/Auxiliary.java new file mode 100644 index 0000000000..4c04b12aa3 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/Auxiliary.java @@ -0,0 +1,27 @@ +package org.csploit.msf; + +import org.csploit.msf.module.ArchSet; +import org.csploit.msf.module.PlatformList; +import org.csploit.msf.module.Reference; + +/** + * The auxiliary class acts as a base class for all modules that perform + * reconnaissance, retrieve data, brute force logins, or any other action + * that doesn't fit our concept of an 'exploit' (involving payloads and + * targets and whatnot). + */ +public class Auxiliary extends Module { + + public Auxiliary(String name, String description, String version, Author[] authors, ArchSet arch, PlatformList platform, Reference[] references, boolean privileged, License license) { + super(name, description, version, authors, arch, platform, references, privileged, license); + } + + public Auxiliary() { + super(); + } + + @Override + public String getType() { + return "auxiliary"; + } +} diff --git a/msf/src/main/java/org/csploit/msf/Payload.java b/msf/src/main/java/org/csploit/msf/Payload.java new file mode 100644 index 0000000000..1db49409a8 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/Payload.java @@ -0,0 +1,25 @@ +package org.csploit.msf; + +import org.csploit.msf.module.ArchSet; +import org.csploit.msf.module.PlatformList; +import org.csploit.msf.module.Reference; + +/** + * This class represents the base class for a logical payload. The framework + * automatically generates payload combinations at runtime which are all + * extended for this Payload as a base class. + */ +public class Payload extends Module { + public Payload(String name, String description, String version, Author[] authors, ArchSet arch, PlatformList platform, Reference[] references, boolean privileged, License license) { + super(name, description, version, authors, arch, platform, references, privileged, license); + } + + public Payload() { + super(); + } + + @Override + public String getType() { + return "payload"; + } +} diff --git a/msf/src/main/java/org/csploit/msf/Post.java b/msf/src/main/java/org/csploit/msf/Post.java new file mode 100644 index 0000000000..9804a69cea --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/Post.java @@ -0,0 +1,24 @@ +package org.csploit.msf; + +import org.csploit.msf.module.ArchSet; +import org.csploit.msf.module.PlatformList; +import org.csploit.msf.module.Reference; + +/** + * A Post-exploitation module. + */ +public class Post extends Module { + + public Post(String name, String description, String version, Author[] authors, ArchSet arch, PlatformList platform, Reference[] references, boolean privileged, License license) { + super(name, description, version, authors, arch, platform, references, privileged, license); + } + + public Post() { + super(); + } + + @Override + public String getType() { + return "post"; + } +} From 3f2e76f7a38114625a0a4ec31ea31280fcd21828 Mon Sep 17 00:00:00 2001 From: tux_mind Date: Sat, 3 Oct 2015 10:28:20 +0200 Subject: [PATCH 03/15] created Job and Session classes and interfaces --- msf/src/main/java/org/csploit/msf/Job.java | 44 +++++ .../java/org/csploit/msf/JobContainer.java | 12 ++ .../main/java/org/csploit/msf/Session.java | 155 ++++++++++++++++++ .../java/org/csploit/msf/SessionManager.java | 37 +++++ .../org/csploit/msf/session/CommandShell.java | 19 +++ .../org/csploit/msf/session/Meterpreter.java | 19 +++ .../msf/session/MultiCommandExecution.java | 12 ++ .../msf/session/MultiCommandShell.java | 14 ++ .../org/csploit/msf/session/Scriptable.java | 9 + .../msf/session/SingleCommandExecution.java | 14 ++ .../msf/session/SingleCommandShell.java | 12 ++ 11 files changed, 347 insertions(+) create mode 100644 msf/src/main/java/org/csploit/msf/Job.java create mode 100644 msf/src/main/java/org/csploit/msf/JobContainer.java create mode 100644 msf/src/main/java/org/csploit/msf/Session.java create mode 100644 msf/src/main/java/org/csploit/msf/SessionManager.java create mode 100644 msf/src/main/java/org/csploit/msf/session/CommandShell.java create mode 100644 msf/src/main/java/org/csploit/msf/session/Meterpreter.java create mode 100644 msf/src/main/java/org/csploit/msf/session/MultiCommandExecution.java create mode 100644 msf/src/main/java/org/csploit/msf/session/MultiCommandShell.java create mode 100644 msf/src/main/java/org/csploit/msf/session/Scriptable.java create mode 100644 msf/src/main/java/org/csploit/msf/session/SingleCommandExecution.java create mode 100644 msf/src/main/java/org/csploit/msf/session/SingleCommandShell.java diff --git a/msf/src/main/java/org/csploit/msf/Job.java b/msf/src/main/java/org/csploit/msf/Job.java new file mode 100644 index 0000000000..e351cc5954 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/Job.java @@ -0,0 +1,44 @@ +package org.csploit.msf; + +import java.util.Date; + +/** + * This class is the concrete representation of an abstract job. + */ +public class Job { + + private JobContainer container; + private int id; + private String name; + protected Exploit exploit; + protected Payload payload; + private Date startTime; + + public Job(JobContainer container, int id, String name, Exploit exploit, Payload payload) { + this.container = container; + this.id = id; + this.name = name; + this.exploit = exploit; + this.payload = payload; + } + + public void setStartTime(Date startTime) { + this.startTime = startTime; + } + + public int getId() { + return id; + } + + public String getName() { + return name; + } + + public Date getStartTime() { + return startTime; + } + + public void stop() { + container.remove(id); + } +} diff --git a/msf/src/main/java/org/csploit/msf/JobContainer.java b/msf/src/main/java/org/csploit/msf/JobContainer.java new file mode 100644 index 0000000000..df34ef9ef6 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/JobContainer.java @@ -0,0 +1,12 @@ +package org.csploit.msf; + +import java.util.HashMap; + +/** + * This class contains zero or more abstract jobs that can be enumerated and + * stopped in a generic fashion. This is used to provide a mechanism for + * keeping track of arbitrary contexts that may or may not require a dedicated + * thread. + */ +public class JobContainer extends HashMap { +} diff --git a/msf/src/main/java/org/csploit/msf/Session.java b/msf/src/main/java/org/csploit/msf/Session.java new file mode 100644 index 0000000000..4ea92942f4 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/Session.java @@ -0,0 +1,155 @@ +package org.csploit.msf; + +import java.util.ArrayList; +import java.util.List; + +/** + * The session class represents a post-exploitation, uh, session. + * Sessions can be written to, read from, and interacted with. The + * underlying medium on which they are backed is arbitrary. For + * instance, when an exploit is provided with a command shell, + * either through a network connection or locally, the session's + * read and write operations end up reading from and writing to + * the shell that was spawned. The session object can be seen + * as a general means of interacting with various post-exploitation + * payloads through a common interface that is not necessarily + * tied to a network connection. + */ +public abstract class Session implements Offspring { + private Framework framework; + private int id; + private String localTunnel; + private String peerTunnel; + private Exploit exploit; + private Payload payload; + private String description; + private String info; + private String workspace; + private String sessionHost; + private int sessionPort; + private String targetHost; + private String username; + private String uuid; + private List routes = new ArrayList<>(); + + public Session(int id) { + this.id = id; + } + + public int getId() { + return id; + } + + public String getLocalTunnel() { + return localTunnel; + } + + public void setLocalTunnel(String localTunnel) { + this.localTunnel = localTunnel; + } + + public String getPeerTunnel() { + return peerTunnel; + } + + public void setPeerTunnel(String peerTunnel) { + this.peerTunnel = peerTunnel; + } + + public Exploit getExploit() { + return exploit; + } + + public void setExploit(Exploit exploit) { + this.exploit = exploit; + } + + public Payload getPayload() { + return payload; + } + + public void setPayload(Payload payload) { + this.payload = payload; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getInfo() { + return info; + } + + public void setInfo(String info) { + this.info = info; + } + + public String getWorkspace() { + return workspace; + } + + public void setWorkspace(String workspace) { + this.workspace = workspace; + } + + public String getSessionHost() { + return sessionHost; + } + + public void setSessionHost(String sessionHost) { + this.sessionHost = sessionHost; + } + + public int getSessionPort() { + return sessionPort; + } + + public void setSessionPort(int sessionPort) { + this.sessionPort = sessionPort; + } + + public String getTargetHost() { + return targetHost; + } + + public void setTargetHost(String targetHost) { + this.targetHost = targetHost; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + @Override + public boolean haveFramework() { + return framework != null; + } + + @Override + public Framework getFramework() { + return framework; + } + + @Override + public void setFramework(Framework framework) { + this.framework = framework; + } + + public abstract String getType(); +} diff --git a/msf/src/main/java/org/csploit/msf/SessionManager.java b/msf/src/main/java/org/csploit/msf/SessionManager.java new file mode 100644 index 0000000000..74bedb1d4b --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/SessionManager.java @@ -0,0 +1,37 @@ +package org.csploit.msf; + +import java.util.HashMap; + +/** + * The purpose of the session manager is to keep track of sessions that are + * created during the course of a framework instance's lifetime. When + * exploits succeed, the payloads they use will create a session object, + * where applicable, there will implement zero or more of the core + * supplied interfaces for interacting with that session. For instance, + * if the payload supports reading and writing from an executed process, + * the session would implement SimpleCommandShell in a method that is + * applicable to the way that the command interpreter is communicated + * with. + */ +public class SessionManager extends HashMap implements Offspring { + private Framework framework; + + public SessionManager(Framework framework) { + this.framework = framework; + } + + @Override + public Framework getFramework() { + return framework; + } + + @Override + public boolean haveFramework() { + return framework != null; + } + + @Override + public void setFramework(Framework framework) { + this.framework = framework; + } +} diff --git a/msf/src/main/java/org/csploit/msf/session/CommandShell.java b/msf/src/main/java/org/csploit/msf/session/CommandShell.java new file mode 100644 index 0000000000..5dfad87e68 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/session/CommandShell.java @@ -0,0 +1,19 @@ +package org.csploit.msf.session; + +import org.csploit.msf.Session; + +/** + * This class provides basic interaction with a command shell on the remote + * endpoint. This session is initialized with a stream that will be used + * as the pipe for reading and writing the command shell. + */ +public abstract class CommandShell extends Session implements SingleCommandShell, Scriptable { + public CommandShell(int id) { + super(id); + } + + @Override + public String getType() { + return "shell"; + } +} diff --git a/msf/src/main/java/org/csploit/msf/session/Meterpreter.java b/msf/src/main/java/org/csploit/msf/session/Meterpreter.java new file mode 100644 index 0000000000..3294cb24f2 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/session/Meterpreter.java @@ -0,0 +1,19 @@ +package org.csploit.msf.session; + +import org.csploit.msf.Session; + +/** + * This class represents a session compatible interface to a meterpreter server + * instance running on a remote machine. It provides the means of interacting + * with the server instance both at an API level as well as at a console level. + */ +public abstract class Meterpreter extends Session implements SingleCommandShell, Scriptable { + public Meterpreter(int id) { + super(id); + } + + @Override + public String getType() { + return "meterpreter"; + } +} diff --git a/msf/src/main/java/org/csploit/msf/session/MultiCommandExecution.java b/msf/src/main/java/org/csploit/msf/session/MultiCommandExecution.java new file mode 100644 index 0000000000..a82bd7c54d --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/session/MultiCommandExecution.java @@ -0,0 +1,12 @@ +package org.csploit.msf.session; + +/** + * Executes multiple commands and optionally allows for reading/writing I/O + * to the new processes. + */ +public interface MultiCommandExecution extends SingleCommandExecution { + int exec(String cmd, String[] args, boolean hidden); + String read(int length, int id); + int write(String data, int id); + void close(int id); +} diff --git a/msf/src/main/java/org/csploit/msf/session/MultiCommandShell.java b/msf/src/main/java/org/csploit/msf/session/MultiCommandShell.java new file mode 100644 index 0000000000..99949732e8 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/session/MultiCommandShell.java @@ -0,0 +1,14 @@ +package org.csploit.msf.session; + +/** + * This interface is to be implemented by a session that is capable of + * providing multiple command shell interfaces simultaneously. Inherently, + * MultiCommandShell classes must also provide a mechanism by which they can + * implement the SingleCommandShell interface. + */ +public interface MultiCommandShell extends SingleCommandShell { + int open(); + String read(int length, int id); + int write(String data, int id); + void close(int id); +} diff --git a/msf/src/main/java/org/csploit/msf/session/Scriptable.java b/msf/src/main/java/org/csploit/msf/session/Scriptable.java new file mode 100644 index 0000000000..96f46800c0 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/session/Scriptable.java @@ -0,0 +1,9 @@ +package org.csploit.msf.session; + +/** + * Represent a session that can run scripts + */ +public interface Scriptable { + boolean executeFile(String path, String[] args); + int executeScript(String scriptName, String[] args); +} diff --git a/msf/src/main/java/org/csploit/msf/session/SingleCommandExecution.java b/msf/src/main/java/org/csploit/msf/session/SingleCommandExecution.java new file mode 100644 index 0000000000..30f43557fb --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/session/SingleCommandExecution.java @@ -0,0 +1,14 @@ +package org.csploit.msf.session; + +/** + * Executes a single command and optionally allows for reading/writing I/O + * to the new process. + * + * footnote: I didn't found any implementors of this interface in the framework + */ +public interface SingleCommandExecution { + void init(String cmd, String[] args); // TODO: options ?? + String read(int length); + int write(String data); + void close(); +} diff --git a/msf/src/main/java/org/csploit/msf/session/SingleCommandShell.java b/msf/src/main/java/org/csploit/msf/session/SingleCommandShell.java new file mode 100644 index 0000000000..71248afa26 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/session/SingleCommandShell.java @@ -0,0 +1,12 @@ +package org.csploit.msf.session; + +/** + * This interface is to be implemented by a session that is only capable of + * providing an interface to a single command shell. + */ +public interface SingleCommandShell { + void init(); + String read(int length); + int write(String data); + void close(); +} From c0fcf8ea2d920feec3feb94a046756396b1e267f Mon Sep 17 00:00:00 2001 From: tux_mind Date: Sat, 3 Oct 2015 11:13:15 +0200 Subject: [PATCH 04/15] expose stuff as less as possible --- .../java/org/csploit/msf/Customizable.java | 14 +++++++++++++ .../main/java/org/csploit/msf/DataHolder.java | 2 +- .../main/java/org/csploit/msf/Framework.java | 10 ++++++++++ .../java/org/csploit/msf/JobContainer.java | 2 +- msf/src/main/java/org/csploit/msf/Module.java | 20 +++++++++++++++++-- .../java/org/csploit/msf/ModuleManager.java | 2 +- .../main/java/org/csploit/msf/ModuleSet.java | 2 +- .../main/java/org/csploit/msf/Offspring.java | 2 +- .../java/org/csploit/msf/SessionManager.java | 2 +- .../java/org/csploit/msf/RpcSampleTest.java | 6 +++--- 10 files changed, 51 insertions(+), 11 deletions(-) create mode 100644 msf/src/main/java/org/csploit/msf/Customizable.java diff --git a/msf/src/main/java/org/csploit/msf/Customizable.java b/msf/src/main/java/org/csploit/msf/Customizable.java new file mode 100644 index 0000000000..9bd61b7039 --- /dev/null +++ b/msf/src/main/java/org/csploit/msf/Customizable.java @@ -0,0 +1,14 @@ +package org.csploit.msf; + +import java.util.Collection; + +/** + * An object that can be tuned up + * by editing it's options. + */ +public interface Customizable { + void setOption(String key, String value); + Collection