├── dist ├── mac │ ├── Armitage.app │ │ └── Contents │ │ │ ├── Java │ │ │ └── index.txt │ │ │ ├── PkgInfo │ │ │ ├── Resources │ │ │ ├── Java │ │ │ │ └── index.txt │ │ │ └── aquaicon2.icns │ │ │ ├── MacOS │ │ │ └── JavaAppLauncher │ │ │ └── Info.plist │ ├── build.sh │ └── readme-osx.rtf ├── unix │ ├── armitage │ ├── armitage-logo.png │ └── teamserver └── windows │ └── armitage.exe ├── run.sh ├── lib ├── sleep.jar ├── jgraphx.jar ├── javassist-3.15.0-GA.jar ├── msgpack-0.6.12-devel.jar └── postgresql-9.1-901.jdbc4.jar ├── resources ├── bsd.png ├── ios.png ├── cisco.png ├── linux.png ├── android.png ├── computer.png ├── firewall.png ├── hacked.png ├── macosx.png ├── printer.png ├── solaris.png ├── unknown.png ├── vmware.png ├── windows7.png ├── windows8.png ├── windowsxp.png ├── armitage-icon.gif ├── armitage-logo.gif ├── windows2000.png ├── eventlog.style ├── about.html ├── msfconsole.style ├── msfrpcd.bat ├── error.txt ├── msfrpcd_new.bat └── armitage.prop ├── release ├── armitage-unix │ ├── armitage │ ├── armitage.jar │ ├── cortana.jar │ ├── armitage-logo.png │ ├── teamserver │ └── readme.txt └── armitage-windows │ ├── armitage.exe │ ├── armitage.jar │ ├── cortana.jar │ └── readme.txt ├── src ├── msf │ ├── RpcCallback.java │ ├── Async.java │ ├── RpcConnection.java │ ├── RpcQueue.java │ ├── RpcAsync.java │ ├── ConsolePool.java │ └── Base64.java ├── ui │ ├── KeyHandler.java │ ├── ScreenshotManager.java │ ├── ATree.java │ ├── SafeMouseListener.java │ ├── DynamicMenu.java │ ├── CopyPopup.java │ ├── ModuleTransferHandler.java │ ├── CutCopyPastePopup.java │ ├── ATextField.java │ ├── ZoomableImage.java │ ├── APasswordField.java │ ├── SafeDialogs.java │ ├── DraggableTabbedPane.java │ └── UploadFile.java ├── ssl │ ├── ArmitageTrustListener.java │ ├── ArmitageTrustManager.java │ └── SecureSocket.java ├── armitage │ ├── Activity.java │ ├── ConsoleCallback.java │ ├── ArmitageThreadClient.java │ ├── QueueTabCompletion.java │ ├── ArmitageTimerClient.java │ ├── ArmitageThread.java │ ├── DisconnectNotifier.java │ ├── SimpleTimer.java │ ├── ActivityConsole.java │ ├── TabCompletion.java │ ├── EventLogTabCompletion.java │ ├── GenericTabCompletion.java │ ├── MeterpreterClient.java │ ├── ArmitageBuffer.java │ └── ArmitageTimer.java ├── console │ ├── ConsolePopup.java │ └── SearchPanel.java ├── graph │ ├── GraphPopup.java │ ├── Refreshable.java │ ├── TouchList.java │ ├── TouchMap.java │ ├── CircleLayout.java │ ├── RefreshGraph.java │ └── Route.java ├── cortana │ ├── data │ │ ├── CortanaTimer.java │ │ ├── DataUtils.java │ │ ├── ManagedData.java │ │ ├── Service.java │ │ ├── Host.java │ │ ├── Credential.java │ │ ├── Loots.java │ │ ├── Credentials.java │ │ ├── Routes.java │ │ ├── Hosts.java │ │ └── Services.java │ ├── gui │ │ ├── CortanaTabCompletion.java │ │ ├── ScriptedMenuItem.java │ │ ├── ScriptedMenu.java │ │ ├── UIBridge.java │ │ ├── MenuBuilder.java │ │ └── KeyBridge.java │ ├── CortanaTabCompletion.java │ ├── core │ │ ├── EventQueue.java │ │ ├── Commands.java │ │ ├── Events.java │ │ ├── Filters.java │ │ ├── CommandManager.java │ │ ├── EventManager.java │ │ └── FilterManager.java │ ├── CortanaPipe.java │ ├── Safety.java │ ├── support │ │ ├── Heartbeat.java │ │ ├── Shared.java │ │ └── LockBridge.java │ ├── metasploit │ │ └── EventLogBridge.java │ └── Loader.java └── tree │ └── SimpleTreeNode.java ├── fixfiles.sh ├── package.sh ├── license.txt ├── scripts ├── log.sl ├── downloads.sl ├── tokens.sl ├── hosts.sl ├── process.sl ├── screenshot.sl └── services.sl ├── readme.txt └── scripts-cortana └── cortanadb.sl /dist/mac/Armitage.app/Contents/Java/index.txt: -------------------------------------------------------------------------------- 1 | . 2 | -------------------------------------------------------------------------------- /dist/mac/Armitage.app/Contents/PkgInfo: -------------------------------------------------------------------------------- 1 | APPLarmi 2 | -------------------------------------------------------------------------------- /run.sh: -------------------------------------------------------------------------------- 1 | java -classpath bin:lib/\*:. armitage.ArmitageMain $* 2 | -------------------------------------------------------------------------------- /lib/sleep.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/lib/sleep.jar -------------------------------------------------------------------------------- /lib/jgraphx.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/lib/jgraphx.jar -------------------------------------------------------------------------------- /resources/bsd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/resources/bsd.png -------------------------------------------------------------------------------- /resources/ios.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/resources/ios.png -------------------------------------------------------------------------------- /resources/cisco.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/resources/cisco.png -------------------------------------------------------------------------------- /resources/linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/resources/linux.png -------------------------------------------------------------------------------- /dist/mac/Armitage.app/Contents/Resources/Java/index.txt: -------------------------------------------------------------------------------- 1 | armitage.jar goes in this directory. 2 | -------------------------------------------------------------------------------- /resources/android.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/resources/android.png -------------------------------------------------------------------------------- /resources/computer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/resources/computer.png -------------------------------------------------------------------------------- /resources/firewall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/resources/firewall.png -------------------------------------------------------------------------------- /resources/hacked.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/resources/hacked.png -------------------------------------------------------------------------------- /resources/macosx.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/resources/macosx.png -------------------------------------------------------------------------------- /resources/printer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/resources/printer.png -------------------------------------------------------------------------------- /resources/solaris.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/resources/solaris.png -------------------------------------------------------------------------------- /resources/unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/resources/unknown.png -------------------------------------------------------------------------------- /resources/vmware.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/resources/vmware.png -------------------------------------------------------------------------------- /resources/windows7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/resources/windows7.png -------------------------------------------------------------------------------- /resources/windows8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/resources/windows8.png -------------------------------------------------------------------------------- /dist/unix/armitage: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | java -XX:+AggressiveHeap -XX:+UseParallelGC -jar armitage.jar $@ 3 | -------------------------------------------------------------------------------- /resources/windowsxp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/resources/windowsxp.png -------------------------------------------------------------------------------- /dist/unix/armitage-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/dist/unix/armitage-logo.png -------------------------------------------------------------------------------- /dist/windows/armitage.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/dist/windows/armitage.exe -------------------------------------------------------------------------------- /lib/javassist-3.15.0-GA.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/lib/javassist-3.15.0-GA.jar -------------------------------------------------------------------------------- /resources/armitage-icon.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/resources/armitage-icon.gif -------------------------------------------------------------------------------- /resources/armitage-logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/resources/armitage-logo.gif -------------------------------------------------------------------------------- /resources/windows2000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/resources/windows2000.png -------------------------------------------------------------------------------- /lib/msgpack-0.6.12-devel.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/lib/msgpack-0.6.12-devel.jar -------------------------------------------------------------------------------- /release/armitage-unix/armitage: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | java -XX:+AggressiveHeap -XX:+UseParallelGC -jar armitage.jar $@ 3 | -------------------------------------------------------------------------------- /lib/postgresql-9.1-901.jdbc4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/lib/postgresql-9.1-901.jdbc4.jar -------------------------------------------------------------------------------- /release/armitage-unix/armitage.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/release/armitage-unix/armitage.jar -------------------------------------------------------------------------------- /release/armitage-unix/cortana.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/release/armitage-unix/cortana.jar -------------------------------------------------------------------------------- /release/armitage-windows/armitage.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/release/armitage-windows/armitage.exe -------------------------------------------------------------------------------- /release/armitage-windows/armitage.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/release/armitage-windows/armitage.jar -------------------------------------------------------------------------------- /release/armitage-windows/cortana.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/release/armitage-windows/cortana.jar -------------------------------------------------------------------------------- /src/msf/RpcCallback.java: -------------------------------------------------------------------------------- 1 | package msf; 2 | 3 | public interface RpcCallback { 4 | public void result(Object result); 5 | } 6 | -------------------------------------------------------------------------------- /release/armitage-unix/armitage-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/release/armitage-unix/armitage-logo.png -------------------------------------------------------------------------------- /src/ui/KeyHandler.java: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | public interface KeyHandler { 4 | public void key_pressed(String description); 5 | } 6 | -------------------------------------------------------------------------------- /dist/mac/Armitage.app/Contents/MacOS/JavaAppLauncher: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/dist/mac/Armitage.app/Contents/MacOS/JavaAppLauncher -------------------------------------------------------------------------------- /src/ssl/ArmitageTrustListener.java: -------------------------------------------------------------------------------- 1 | package ssl; 2 | 3 | public interface ArmitageTrustListener { 4 | public boolean trust(String fingerprint); 5 | } 6 | -------------------------------------------------------------------------------- /dist/mac/Armitage.app/Contents/Resources/aquaicon2.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rsmudge/armitage/master/dist/mac/Armitage.app/Contents/Resources/aquaicon2.icns -------------------------------------------------------------------------------- /fixfiles.sh: -------------------------------------------------------------------------------- 1 | # 2 | # fix the line formats so windows users can read the files too 3 | # 4 | perl -pi -e 's/\n/\r\n/g' readme.txt 5 | perl -pi -e 's/\n/\r\n/g' whatsnew.txt 6 | 7 | -------------------------------------------------------------------------------- /src/ui/ScreenshotManager.java: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | import java.awt.Image; 4 | 5 | public interface ScreenshotManager { 6 | public void saveScreenshot(Image screenshot, String title); 7 | } 8 | -------------------------------------------------------------------------------- /src/armitage/Activity.java: -------------------------------------------------------------------------------- 1 | package armitage; 2 | 3 | import javax.swing.JLabel; 4 | 5 | public interface Activity { 6 | public void registerLabel(JLabel label); 7 | public void resetNotification(); 8 | } 9 | -------------------------------------------------------------------------------- /src/armitage/ConsoleCallback.java: -------------------------------------------------------------------------------- 1 | package armitage; 2 | 3 | public interface ConsoleCallback { 4 | public void sessionRead(String sessionid, String text); 5 | public void sessionWrote(String sessionid, String text); 6 | } 7 | -------------------------------------------------------------------------------- /resources/eventlog.style: -------------------------------------------------------------------------------- 1 | ^(../.. ..:..:..) \[\*\] (.*) $1 \cC[*]\o $2 2 | ^\[\*\] (.*) \cC[*]\o $1 3 | ^(../.. ..:..:..) \* (.*) $1 \cD*\o $2 4 | ^(../.. ..:..:..) <(.*?)> (.*?$ME$.*) $1 <\c7$2\o> $3 5 | ^(\w+)> \u$1\o> 6 | -------------------------------------------------------------------------------- /src/armitage/ArmitageThreadClient.java: -------------------------------------------------------------------------------- 1 | package armitage; 2 | 3 | import java.util.*; 4 | 5 | public interface ArmitageThreadClient { 6 | /** return -1 to stop the thread, return >=0 value to have the thread call this client again */ 7 | public long execute(); 8 | } 9 | -------------------------------------------------------------------------------- /src/ui/ATree.java: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | import java.awt.*; 4 | import javax.swing.*; 5 | import javax.swing.tree.*; 6 | import java.util.*; 7 | 8 | public class ATree extends JTree { 9 | public ATree(TreeNode root) { 10 | super(root); 11 | } 12 | 13 | public boolean getScrollableTracksViewportWidth() { 14 | return true; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/console/ConsolePopup.java: -------------------------------------------------------------------------------- 1 | package console; 2 | 3 | import java.awt.event.MouseEvent; 4 | 5 | /** an interface to accept a clicked on word and a mouse event... it's up to the implementor to decide 6 | what should happen with this magical information */ 7 | public interface ConsolePopup { 8 | public void showPopup(String word, MouseEvent ev); 9 | } 10 | -------------------------------------------------------------------------------- /src/graph/GraphPopup.java: -------------------------------------------------------------------------------- 1 | package graph; 2 | 3 | import java.awt.event.MouseEvent; 4 | 5 | /** an interface to accept a clicked on word and a mouse event... it's up to the implementor to decide 6 | what should happen with this magical information */ 7 | public interface GraphPopup { 8 | public void showGraphPopup(String[] nodes, MouseEvent ev); 9 | } 10 | -------------------------------------------------------------------------------- /dist/mac/build.sh: -------------------------------------------------------------------------------- 1 | # 2 | # unzip armitage.tgz in this directory first. 3 | # 4 | 5 | rm -rf dist 6 | mkdir dist 7 | cp -r Armitage.app dist 8 | cp armitage/armitage.jar dist/Armitage.app/Contents/Java 9 | cp armitage/*.txt dist/ 10 | cp *.rtf dist/ 11 | rm -rf armitage 12 | mv dist Armitage 13 | hdiutil create -ov -volname Armitage -srcfolder ./Armitage armitage.dmg 14 | rm -rf armitage 15 | -------------------------------------------------------------------------------- /resources/about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

Armitage 1.4.11

4 | 5 |

An attack management tool for Metasploit® 6 |
Release: 13 August 2015

7 |
8 |

Developed by:

9 | 12 | 13 |

Metasploit® is a registered trademark of Rapid7

14 | 15 | 16 | -------------------------------------------------------------------------------- /resources/msfconsole.style: -------------------------------------------------------------------------------- 1 | ^msf> \umsf\u> 2 | ^meterpreter > \umeterpreter\u > 3 | ^msf > \umsf\u > 4 | ^msf (.*?)\((.*?)\) > \umsf\u $1(\c4$2\o) > 5 | ^\[\*\] (.*) \cC[*]\o $1 6 | ^\[\+\] (.*) \c9[+]\o $1 7 | ^\[\!\] (.*) \c8[!]\o $1 8 | ^\[\-\] (.*) \c4[-]\o $1 9 | ^ =\[ (.*) =[\c7 $1 10 | ^(=[=\s]+) \cE$1 11 | ^(\s*-[-\s]+) \cE$1 12 | ^(.*?): (.*) $1\cE:\o $2 13 | -------------------------------------------------------------------------------- /src/msf/Async.java: -------------------------------------------------------------------------------- 1 | package msf; 2 | 3 | import java.io.*; 4 | 5 | public interface Async { 6 | public void execute_async(String methodName); 7 | public void execute_async(String methodName, Object[] args); 8 | public void execute_async(String methodName, Object[] args, RpcCallback callback); 9 | public boolean isConnected(); 10 | public void disconnect(); 11 | public boolean isResponsive(); 12 | } 13 | -------------------------------------------------------------------------------- /resources/msfrpcd.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | set BASE=$$BASE$$ 3 | cd "%BASE%" 4 | set PATH=%BASE%ruby\bin;%BASE%java\bin;%BASE%tools;%BASE%svn\bin;%BASE%nmap;%BASE%postgresql\bin;%PATH% 5 | IF NOT EXIST "%BASE%java" GOTO NO_JAVA 6 | set JAVA_HOME="%BASE%java" 7 | :NO_JAVA 8 | set MSF_DATABASE_CONFIG="%BASE%\config\database.yml" 9 | cd "%BASE%msf3" 10 | rubyw msfrpcd -a 127.0.0.1 -U $$USER$$ -P $$PASS$$ -S -f -p $$PORT$$ 11 | -------------------------------------------------------------------------------- /resources/error.txt: -------------------------------------------------------------------------------- 1 | Metasploit's RPC daemon shut down. This is the 2 | service Armitage uses to talk to Metasploit. 3 | 4 | When this happens, it means something is wrong. 5 | The developer of Armitage feels your pain from 6 | afar. Would you like help troubleshooting this? 7 | 8 | P.S. yes you would--the answer is known and it's 9 | easy to deal with. Click Yes to visit the 10 | troubleshooting guide at: 11 | 12 | http://www.fastandeasyhacking.com/nomsfrpcd 13 | -------------------------------------------------------------------------------- /resources/msfrpcd_new.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | set BASE=$$BASE$$..\..\ 3 | cd "%BASE%" 4 | set PATH=%BASE%ruby\bin;%BASE%java\bin;%BASE%tools;%BASE%nmap;%BASE%postgresql\bin;%PATH% 5 | IF NOT EXIST "%BASE%java" GOTO NO_JAVA 6 | set JAVA_HOME="%BASE%java" 7 | :NO_JAVA 8 | set MSF_DATABASE_CONFIG="%BASE%apps\pro\ui\config\database.yml" 9 | set MSF_BUNDLE_GEMS=0 10 | set BUNDLE_GEMFILE=%BASE%apps\pro\ui\Gemfile 11 | cd "%BASE%apps\pro\msf3" 12 | rubyw msfrpcd -a 127.0.0.1 -U $$USER$$ -P $$PASS$$ -S -f -p $$PORT$$ 13 | -------------------------------------------------------------------------------- /src/armitage/QueueTabCompletion.java: -------------------------------------------------------------------------------- 1 | package armitage; 2 | 3 | import console.Console; 4 | import java.util.*; 5 | 6 | /* uses a console queue as a tab completion source */ 7 | public class QueueTabCompletion extends GenericTabCompletion { 8 | protected ConsoleQueue queue; 9 | 10 | public QueueTabCompletion(Console window, ConsoleQueue queue) { 11 | super(window); 12 | this.queue = queue; 13 | } 14 | 15 | public Collection getOptions(String text) { 16 | return queue.tabComplete(text); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/cortana/data/CortanaTimer.java: -------------------------------------------------------------------------------- 1 | package cortana.data; 2 | 3 | import armitage.*; 4 | import msf.*; 5 | 6 | public class CortanaTimer extends ArmitageTimer { 7 | protected DataManager clientz; 8 | 9 | protected boolean alwaysFire() { 10 | return !clientz.isReady(); 11 | } 12 | 13 | public CortanaTimer(RpcConnection connection, String command, long sleepPeriod, DataManager client, boolean doCache) { 14 | super(connection, command, sleepPeriod, client, doCache); 15 | this.clientz = client; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/armitage/ArmitageTimerClient.java: -------------------------------------------------------------------------------- 1 | package armitage; 2 | 3 | import java.util.*; 4 | 5 | /** A client for the ArmitageTimer class. It's easier to have a Java class handle all this vs. using Sleep's fork mechanism. This way we get thread safety 6 | for any Sleep data structures by default. */ 7 | public interface ArmitageTimerClient { 8 | /** return true if you want the timer to continue running. The arguments are the command, arguments, and the result of them. */ 9 | public boolean result(String command, Object[] arguments, Map result); 10 | } 11 | -------------------------------------------------------------------------------- /src/cortana/data/DataUtils.java: -------------------------------------------------------------------------------- 1 | package cortana.data; 2 | 3 | import sleep.runtime.*; 4 | import java.util.*; 5 | 6 | public class DataUtils { 7 | /* calculate the difference between two sets */ 8 | public static Set difference(Set a, Set b) { 9 | Set temp = new HashSet(); 10 | temp.addAll(a); 11 | temp.removeAll(b); 12 | return temp; 13 | } 14 | 15 | /* calculate the intersection of two sets */ 16 | public static Set intersection(Set a, Set b) { 17 | Set temp = new HashSet(); 18 | temp.addAll(a); 19 | temp.retainAll(b); 20 | return temp; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/ui/SafeMouseListener.java: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | import java.awt.*; 4 | import java.awt.event.*; 5 | 6 | public class SafeMouseListener extends MouseAdapter { 7 | protected MouseListener listener; 8 | 9 | public SafeMouseListener(MouseListener listener) { 10 | this.listener = listener; 11 | } 12 | 13 | public void mouseClicked(MouseEvent ev) { 14 | listener.mouseClicked(ev); 15 | } 16 | 17 | public void mousePressed(MouseEvent ev) { 18 | listener.mousePressed(ev); 19 | } 20 | 21 | public void mouseReleased(MouseEvent ev) { 22 | listener.mouseReleased(ev); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/msf/RpcConnection.java: -------------------------------------------------------------------------------- 1 | package msf; 2 | 3 | import java.io.*; 4 | import java.net.*; 5 | import java.text.*; 6 | import java.util.*; 7 | import javax.xml.*; 8 | import javax.xml.parsers.*; 9 | import javax.xml.transform.*; 10 | import javax.xml.transform.dom.*; 11 | import javax.xml.transform.stream.*; 12 | import org.w3c.dom.*; 13 | 14 | /** 15 | * This is a modification of msfgui/RpcConnection.java by scriptjunkie. Taken from 16 | * the Metasploit Framework Java GUI. 17 | */ 18 | public interface RpcConnection { 19 | public Object execute(String methodName) throws IOException; 20 | public Object execute(String methodName, Object[] params) throws IOException; 21 | } 22 | -------------------------------------------------------------------------------- /src/graph/Refreshable.java: -------------------------------------------------------------------------------- 1 | package graph; 2 | 3 | import java.awt.Image; 4 | 5 | public interface Refreshable { 6 | /* called to indicate that we're starting an update */ 7 | public void start(); 8 | 9 | /* add a node */ 10 | public Object addNode(String id, String label, String description, Image image, String tooltip); 11 | 12 | /* setup all of our routes in one fell swoop */ 13 | public void setRoutes(Route[] routes); 14 | 15 | /* highlight a pivot line please */ 16 | public void highlightRoute(String src, String dst); 17 | 18 | /* clear any untouched nodes */ 19 | public void deleteNodes(); 20 | 21 | /* called to indicate that we're ending an update */ 22 | public void end(); 23 | } 24 | -------------------------------------------------------------------------------- /src/cortana/data/ManagedData.java: -------------------------------------------------------------------------------- 1 | package cortana.data; 2 | 3 | import cortana.core.*; 4 | 5 | import armitage.ArmitageTimerClient; 6 | import armitage.ArmitageTimer; 7 | 8 | import graph.Route; 9 | 10 | import sleep.bridges.*; 11 | import sleep.interfaces.*; 12 | import sleep.runtime.*; 13 | import sleep.engine.*; 14 | 15 | import java.util.*; 16 | 17 | import java.io.IOException; 18 | 19 | import msf.*; 20 | 21 | public abstract class ManagedData { 22 | protected boolean initial = true; 23 | protected Scalar cache = null; 24 | 25 | public boolean isInitial() { 26 | return initial; 27 | } 28 | 29 | public abstract Scalar getScalar(); 30 | 31 | public void reset() { 32 | initial = true; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/graph/TouchList.java: -------------------------------------------------------------------------------- 1 | package graph; 2 | 3 | import java.util.*; 4 | 5 | /** A touch map lets me start an operation, "touch" each updated node, and then delete any untouched node */ 6 | public class TouchList extends LinkedList { 7 | protected Set touched = new HashSet(); 8 | 9 | public void startUpdates() { 10 | touched.clear(); 11 | } 12 | 13 | public void touch(Object key) { 14 | touched.add(key); 15 | } 16 | 17 | public List clearUntouched() { 18 | List results = new LinkedList(); 19 | 20 | Iterator i = this.iterator(); 21 | while (i.hasNext()) { 22 | Object j = i.next(); 23 | if (!touched.contains(j)) { 24 | results.add(j); 25 | i.remove(); 26 | } 27 | } 28 | 29 | return results; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/cortana/gui/CortanaTabCompletion.java: -------------------------------------------------------------------------------- 1 | package cortana.gui; 2 | 3 | import console.Console; 4 | import msf.*; 5 | import armitage.*; 6 | import java.util.*; 7 | import java.awt.*; 8 | import java.awt.event.*; 9 | import javax.swing.*; 10 | 11 | import java.io.IOException; 12 | 13 | /* scriptable tab completion... */ 14 | public class CortanaTabCompletion extends GenericTabCompletion { 15 | public static interface Completer { 16 | public Collection getOptions(String text); 17 | } 18 | 19 | protected Completer completer; 20 | 21 | public CortanaTabCompletion(Console window, Completer c) { 22 | super(window); 23 | this.completer = c; 24 | } 25 | 26 | public Collection getOptions(String text) { 27 | return completer.getOptions(text); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/graph/TouchMap.java: -------------------------------------------------------------------------------- 1 | package graph; 2 | 3 | import java.util.*; 4 | 5 | /** A touch map lets me start an operation, "touch" each updated node, and then delete any untouched node */ 6 | public class TouchMap extends HashMap { 7 | protected Set touched = new HashSet(); 8 | 9 | public void startUpdates() { 10 | touched.clear(); 11 | } 12 | 13 | public void touch(Object key) { 14 | touched.add(key); 15 | } 16 | 17 | public List clearUntouched() { 18 | List results = new LinkedList(); 19 | 20 | Iterator i = this.entrySet().iterator(); 21 | while (i.hasNext()) { 22 | Map.Entry j = (Map.Entry)i.next(); 23 | if (!touched.contains(j.getKey())) { 24 | results.add(j); 25 | i.remove(); 26 | } 27 | } 28 | 29 | return results; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/armitage/ArmitageThread.java: -------------------------------------------------------------------------------- 1 | package armitage; 2 | 3 | import console.Console; 4 | import msf.*; 5 | import java.util.*; 6 | 7 | /** A generic class to execute several queries and return their results */ 8 | public class ArmitageThread implements Runnable { 9 | protected ArmitageThreadClient client; 10 | 11 | public ArmitageThread(ArmitageThreadClient c) { 12 | this.client = c; 13 | } 14 | 15 | public void start() { 16 | new Thread(this).start(); 17 | } 18 | 19 | public void run() { 20 | while (true) { 21 | long sleepFor = client.execute(); 22 | 23 | if (sleepFor <= 0) { 24 | return; 25 | } 26 | else { 27 | try { 28 | Thread.sleep(sleepFor); 29 | } 30 | catch (Exception ex) { 31 | 32 | } 33 | } 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/ui/DynamicMenu.java: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | import java.awt.*; 4 | import java.awt.event.*; 5 | 6 | import javax.swing.*; 7 | import javax.swing.event.*; 8 | 9 | public class DynamicMenu extends JMenu implements MenuListener { 10 | public DynamicMenu(String s) { 11 | super(s); 12 | addMenuListener(this); 13 | } 14 | 15 | public void setHandler(DynamicMenuHandler h) { 16 | handler = h; 17 | } 18 | 19 | protected DynamicMenuHandler handler = null; 20 | 21 | public interface DynamicMenuHandler { 22 | public void setupMenu(JMenu parent); 23 | } 24 | 25 | public void menuSelected(MenuEvent ev) { 26 | if (handler != null) { 27 | handler.setupMenu(this); 28 | } 29 | } 30 | 31 | public void menuCanceled(MenuEvent ev) { 32 | removeAll(); 33 | } 34 | 35 | public void menuDeselected(MenuEvent ev) { 36 | removeAll(); 37 | } 38 | } 39 | 40 | -------------------------------------------------------------------------------- /src/cortana/CortanaTabCompletion.java: -------------------------------------------------------------------------------- 1 | package cortana; 2 | 3 | import armitage.GenericTabCompletion; 4 | import console.Console; 5 | import msf.*; 6 | import java.util.*; 7 | import java.awt.*; 8 | import java.awt.event.*; 9 | import javax.swing.*; 10 | 11 | /* A generic class to manage reading/writing to a console. Keeps the code simpler (although the Sleep code to do this is 12 | simpler than this Java code. *sigh* */ 13 | public class CortanaTabCompletion extends GenericTabCompletion { 14 | protected Cortana engine; 15 | 16 | public String transformText(String text) { 17 | return text.replace(" ~", " " + System.getProperty("user.home")); 18 | } 19 | 20 | public CortanaTabCompletion(Console window, Cortana engine) { 21 | super(window); 22 | this.engine = engine; 23 | } 24 | 25 | public Collection getOptions(String text) { 26 | return engine.commandList(text); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/armitage/DisconnectNotifier.java: -------------------------------------------------------------------------------- 1 | package armitage; 2 | 3 | import java.util.*; 4 | 5 | /* an object to track listeners for disconnects... */ 6 | public class DisconnectNotifier { 7 | public interface DisconnectListener { 8 | public void disconnected(String reason); 9 | } 10 | 11 | protected List listeners = new LinkedList(); 12 | protected boolean connected = true; 13 | 14 | public void addDisconnectListener(DisconnectListener l) { 15 | synchronized (listeners) { 16 | listeners.add(l); 17 | } 18 | } 19 | 20 | public void fireDisconnectEvent(final String reason) { 21 | new Thread(new Runnable() { 22 | public void run() { 23 | synchronized (listeners) { 24 | if (!connected) 25 | return; 26 | 27 | Iterator i = listeners.iterator(); 28 | while (i.hasNext()) { 29 | DisconnectListener l = (DisconnectListener)i.next(); 30 | l.disconnected(reason); 31 | } 32 | 33 | connected = false; 34 | } 35 | } 36 | }).start(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/armitage/SimpleTimer.java: -------------------------------------------------------------------------------- 1 | package armitage; 2 | 3 | import console.Console; 4 | import msf.*; 5 | import java.util.*; 6 | 7 | /** A generic class to execute several queries and return their results */ 8 | public class SimpleTimer implements Runnable { 9 | protected long sleepPeriod; 10 | protected Runnable doit; 11 | protected boolean flag; 12 | 13 | public SimpleTimer(long period) { 14 | sleepPeriod = period; 15 | flag = true; 16 | } 17 | 18 | public void setRunnable(Runnable r) { 19 | doit = r; 20 | new Thread(this).start(); 21 | } 22 | 23 | /* this should only be called within the thread executing the runnable */ 24 | public void stop() { 25 | flag = false; 26 | } 27 | 28 | public void run() { 29 | try { 30 | while (flag) { 31 | doit.run(); 32 | Thread.sleep(sleepPeriod); 33 | } 34 | } 35 | catch (Exception ex) { 36 | System.err.println("TIMER DIED | continue: " + flag + ", " + sleepPeriod + "ms, " + doit); 37 | ex.printStackTrace(); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/cortana/data/Service.java: -------------------------------------------------------------------------------- 1 | package cortana.data; 2 | 3 | import java.util.*; 4 | import sleep.runtime.*; 5 | 6 | /* represent a host/port pair in a Set */ 7 | public class Service { 8 | protected String host; 9 | protected String port; 10 | 11 | public String getHost() { 12 | return host; 13 | } 14 | 15 | public String getPort() { 16 | return port; 17 | } 18 | 19 | public Service(String host, String port) { 20 | this.host = host; 21 | this.port = port; 22 | } 23 | 24 | public Stack arguments() { 25 | Stack arguments = new Stack(); 26 | arguments.push(SleepUtils.getScalar(port)); 27 | arguments.push(SleepUtils.getScalar(host)); 28 | return arguments; 29 | } 30 | 31 | public boolean equals(Object o) { 32 | if (o instanceof Service) { 33 | Service t = (Service)o; 34 | return (t.host.equals(host) && t.port.equals(port)); 35 | } 36 | return false; 37 | } 38 | 39 | public int hashCode() { 40 | return host.hashCode() + port.hashCode(); 41 | } 42 | 43 | public String toString() { 44 | return host + ":" + port; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/armitage/ActivityConsole.java: -------------------------------------------------------------------------------- 1 | package armitage; 2 | 3 | import javax.swing.*; 4 | import javax.swing.event.*; 5 | import javax.swing.border.*; 6 | import javax.swing.text.*; 7 | 8 | import java.awt.*; 9 | import java.awt.event.*; 10 | 11 | import java.io.PrintStream; 12 | 13 | import java.util.*; 14 | 15 | import console.*; 16 | 17 | /** A generic multi-feature console for use in the Armitage network attack tool */ 18 | public class ActivityConsole extends Console implements Activity { 19 | protected JLabel label; 20 | protected Color original; 21 | public void registerLabel(JLabel l) { 22 | label = l; 23 | original = l.getForeground(); 24 | } 25 | 26 | public void resetNotification() { 27 | label.setForeground(original); 28 | } 29 | 30 | protected void appendToConsole(String _text) { 31 | super.appendToConsole(_text); 32 | 33 | if (_text.length() > 0 && label != null && !isShowing()) { 34 | label.setForeground(Color.decode(display.getProperty("tab.highlight.color", "#0000ff"))); 35 | } 36 | } 37 | 38 | public ActivityConsole(Properties preferences) { 39 | super(preferences); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/cortana/gui/ScriptedMenuItem.java: -------------------------------------------------------------------------------- 1 | package cortana.gui; 2 | 3 | import sleep.runtime.*; 4 | import sleep.bridges.*; 5 | 6 | import java.awt.*; 7 | import java.awt.event.*; 8 | 9 | import javax.swing.*; 10 | 11 | import java.util.*; 12 | 13 | public class ScriptedMenuItem extends JMenuItem implements ActionListener { 14 | protected String label; 15 | protected SleepClosure code; 16 | protected MenuBridge bridge; 17 | protected Stack args; 18 | 19 | public ScriptedMenuItem(String label, SleepClosure code, MenuBridge bridge) { 20 | if (label.indexOf('&') > -1) { 21 | setText( label.substring(0, label.indexOf('&')) + 22 | label.substring(label.indexOf('&') + 1, label.length()) 23 | ); 24 | setMnemonic(label.charAt(label.indexOf('&') + 1)); 25 | } 26 | else { 27 | setText(label); 28 | } 29 | 30 | this.code = code; 31 | this.bridge = bridge; 32 | this.label = label; 33 | args = bridge.getArguments(); 34 | addActionListener(this); 35 | } 36 | 37 | public void actionPerformed(ActionEvent ev) { 38 | SleepUtils.runCode(code, label, null, cortana.core.EventManager.shallowCopy(args)); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/armitage/TabCompletion.java: -------------------------------------------------------------------------------- 1 | package armitage; 2 | 3 | import console.Console; 4 | import msf.*; 5 | import java.util.*; 6 | import java.awt.*; 7 | import java.awt.event.*; 8 | import javax.swing.*; 9 | 10 | import java.io.IOException; 11 | 12 | /* A generic class to manage reading/writing to a console. Keeps the code simpler (although the Sleep code to do this is 13 | simpler than this Java code. *sigh* */ 14 | public class TabCompletion extends GenericTabCompletion { 15 | protected RpcConnection connection; 16 | protected String session; 17 | protected String tabsCommand; 18 | 19 | public TabCompletion(Console window, RpcConnection connection, String session, String tabsCommand) { 20 | super(window); 21 | this.connection = connection; 22 | this.session = session; 23 | this.tabsCommand = tabsCommand; 24 | } 25 | 26 | public Collection getOptions(String text) { 27 | try { 28 | Map response = (Map)connection.execute(tabsCommand, new Object[] { session, text }); 29 | 30 | if (response.get("tabs") == null) 31 | return null; 32 | 33 | Collection options = (Collection)response.get("tabs"); 34 | return options; 35 | } 36 | catch (IOException ioex) { 37 | ioex.printStackTrace(); 38 | } 39 | return null; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /package.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # I know Apache Ant does all of this stuff... I hate working with XML though 4 | # 5 | 6 | rm -f armitage.zip 7 | rm -f armitage.tgz 8 | 9 | ant clean 10 | ant compile 11 | cp -r resources/ bin/ 12 | cp -r scripts/ bin/ 13 | rm -rf bin/*/*/.svn 14 | rm -rf bin/*/.svn 15 | ant jar 16 | 17 | # 18 | # build *NIX package 19 | # 20 | mkdir armitage 21 | cp armitage.jar armitage 22 | cp cortana.jar armitage 23 | cp readme.txt armitage 24 | cp whatsnew.txt armitage 25 | cp -r dist/unix/* armitage 26 | 27 | # kill the silly .svn file 28 | rm -rf armitage/.svn 29 | tar zcvf armitage.tgz armitage 30 | 31 | rm -rf armitage 32 | 33 | # 34 | # build Windows package 35 | # 36 | mkdir armitage 37 | cp -r dist/windows/* armitage 38 | cp armitage.jar armitage/ 39 | cp cortana.jar armitage/ 40 | cp readme.txt armitage/readme.txt 41 | cp whatsnew.txt armitage/whatsnew.txt 42 | 43 | # kill that silly .svn file 44 | rm -rf armitage/.svn 45 | rm -rf armitage/*/*/.svn 46 | rm -rf armitage/*/.svn 47 | cd armitage 48 | zip -r ../armitage.zip . 49 | cd .. 50 | 51 | rm -rf armitage 52 | 53 | # 54 | # update the release directory 55 | # 56 | cd release/ 57 | tar zxvf ../armitage.tgz 58 | mv armitage/* armitage-unix 59 | rm -rf armitage 60 | 61 | cd ../release/ 62 | cd armitage-windows 63 | unzip -o ../../armitage.zip 64 | -------------------------------------------------------------------------------- /src/cortana/core/EventQueue.java: -------------------------------------------------------------------------------- 1 | package cortana.core; 2 | 3 | import java.util.*; 4 | import sleep.runtime.*; 5 | 6 | /* an event for firing events outside of the data management threads */ 7 | public class EventQueue implements Runnable { 8 | protected EventManager manager; 9 | protected LinkedList queue = new LinkedList(); 10 | 11 | private static class Event { 12 | public String name; 13 | public Stack args; 14 | } 15 | 16 | public EventQueue(EventManager manager) { 17 | this.manager = manager; 18 | new Thread(this).start(); 19 | } 20 | 21 | public void add(String name, Stack args) { 22 | Event e = new Event(); 23 | e.name = name; 24 | e.args = args; 25 | 26 | synchronized (this) { 27 | queue.add(e); 28 | } 29 | } 30 | 31 | protected Event grabEvent() { 32 | synchronized (this) { 33 | return (Event)queue.pollFirst(); 34 | } 35 | } 36 | 37 | public void run() { 38 | while (true) { 39 | Event ev = grabEvent(); 40 | 41 | try { 42 | if (ev != null) { 43 | manager.fireEvent(ev.name, ev.args, null); 44 | } 45 | else { 46 | Thread.sleep(25); 47 | } 48 | } 49 | catch (Exception ex) { 50 | if (ev != null) 51 | System.err.println(ev.name + " => " + SleepUtils.describe(ev.args)); 52 | ex.printStackTrace(); 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/ui/CopyPopup.java: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | import javax.swing.*; 4 | import javax.swing.event.*; 5 | import javax.swing.text.*; 6 | 7 | import java.awt.*; 8 | import java.awt.event.*; 9 | 10 | 11 | /* A textfield with a popup menu to cut, copy, paste, and clear the textfield */ 12 | public class CopyPopup { 13 | protected JPopupMenu menu = null; 14 | protected JTextComponent component = null; 15 | 16 | public CopyPopup(JTextComponent component) { 17 | this.component = component; 18 | createMenu(); 19 | } 20 | 21 | public void createMenu() { 22 | if (menu != null) 23 | return; 24 | 25 | menu = new JPopupMenu(); 26 | JMenuItem copy = new JMenuItem("Copy", 'o'); 27 | 28 | copy.addActionListener(new ActionListener() { 29 | public void actionPerformed(ActionEvent ev) { 30 | component.copy(); 31 | } 32 | }); 33 | 34 | menu.add(copy); 35 | 36 | component.addMouseListener(new MouseAdapter() { 37 | public void handle(MouseEvent ev) { 38 | if (ev.isPopupTrigger()) { 39 | menu.show((JComponent)ev.getSource(), ev.getX(), ev.getY()); 40 | } 41 | } 42 | 43 | public void mousePressed(MouseEvent ev) { 44 | handle(ev); 45 | } 46 | 47 | public void mouseClicked(MouseEvent ev) { 48 | handle(ev); 49 | } 50 | 51 | public void mouseReleased(MouseEvent ev) { 52 | handle(ev); 53 | } 54 | }); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/cortana/gui/ScriptedMenu.java: -------------------------------------------------------------------------------- 1 | package cortana.gui; 2 | 3 | import java.awt.*; 4 | import java.awt.event.*; 5 | 6 | import javax.swing.*; 7 | import javax.swing.event.*; 8 | 9 | import sleep.runtime.*; 10 | import sleep.engine.*; 11 | import sleep.bridges.*; 12 | 13 | import java.util.*; 14 | 15 | /* implements a scripted menu */ 16 | public class ScriptedMenu extends JMenu implements MenuListener { 17 | protected MenuBridge bridge; 18 | protected SleepClosure f; 19 | protected String label; 20 | protected Stack args; 21 | 22 | public ScriptedMenu(String _label, SleepClosure f, MenuBridge bridge) { 23 | if (_label.indexOf('&') > -1) { 24 | setText( _label.substring(0, _label.indexOf('&')) + _label.substring(_label.indexOf('&') + 1, _label.length()) ); 25 | setMnemonic(_label.charAt(_label.indexOf('&') + 1)); 26 | } 27 | else { 28 | setText(_label); 29 | } 30 | 31 | this.label = _label; 32 | this.bridge = bridge; 33 | this.f = f; 34 | this.args = bridge.getArguments(); 35 | addMenuListener(this); 36 | } 37 | 38 | public void menuSelected(MenuEvent e) { 39 | bridge.push(this, args); 40 | SleepUtils.runCode(f, label, null, cortana.core.EventManager.shallowCopy(args)); 41 | bridge.pop(); 42 | } 43 | 44 | public void menuDeselected(MenuEvent e) { 45 | removeAll(); 46 | } 47 | 48 | public void menuCanceled(MenuEvent e) { 49 | removeAll(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/cortana/gui/UIBridge.java: -------------------------------------------------------------------------------- 1 | package cortana.gui; 2 | 3 | import cortana.core.*; 4 | import msf.*; 5 | import armitage.*; 6 | import ui.*; 7 | 8 | import sleep.bridges.*; 9 | import sleep.interfaces.*; 10 | import sleep.runtime.*; 11 | import sleep.engine.*; 12 | 13 | import java.awt.*; 14 | import java.awt.event.*; 15 | import javax.swing.*; 16 | 17 | import java.util.*; 18 | 19 | import java.io.IOException; 20 | 21 | /* some methods to help out with user interface stuff */ 22 | public class UIBridge implements Loadable, Function { 23 | protected ArmitageApplication armitage; 24 | 25 | public UIBridge(ArmitageApplication a) { 26 | armitage = a; 27 | } 28 | 29 | public Scalar evaluate(String name, ScriptInstance script, Stack args) { 30 | if (name.equals("&later")) { 31 | final SleepClosure f = BridgeUtilities.getFunction(args, script); 32 | final Stack argz = EventManager.shallowCopy(args); 33 | if (SwingUtilities.isEventDispatchThread()) { 34 | SleepUtils.runCode(f, "laterz", null, argz); 35 | } 36 | else { 37 | SwingUtilities.invokeLater(new Runnable() { 38 | public void run() { 39 | SleepUtils.runCode(f, "laterz", null, argz); 40 | } 41 | }); 42 | } 43 | } 44 | 45 | return SleepUtils.getEmptyScalar(); 46 | } 47 | 48 | public void scriptLoaded(ScriptInstance si) { 49 | si.getScriptEnvironment().getEnvironment().put("&later", this); 50 | } 51 | 52 | public void scriptUnloaded(ScriptInstance si) { 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /dist/mac/Armitage.app/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleName 6 | Armitage 7 | CFBundleVersion 8 | 03.03.11 9 | CFBundleAllowMixedLocalizations 10 | true 11 | CFBundleExecutable 12 | JavaAppLauncher 13 | CFBundleDevelopmentRegion 14 | English 15 | CFBundlePackageType 16 | APPL 17 | CFBundleSignature 18 | faha 19 | CFBundleInfoDictionaryVersion 20 | 6.0 21 | CFBundleIdentifier 22 | Armitage 23 | CFBundleDisplayName 24 | Armitage 25 | CFBundlePackageType 26 | APPL 27 | CFBundleShortVersionString 28 | MacOS X Client 29 | CFBundleSignature 30 | cblt 31 | CFBundleVersion 32 | 1 33 | NSHumanReadableCopyright 34 | 35 | JVMMainClassName 36 | armitage.ArmitageMain 37 | CFBundleIconFile 38 | aquaicon2 39 | JVMOptions 40 | 41 | -XX:+AggressiveHeap 42 | -XX:+UseParallelGC 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/armitage/EventLogTabCompletion.java: -------------------------------------------------------------------------------- 1 | package armitage; 2 | 3 | import console.Console; 4 | import msf.*; 5 | import java.util.*; 6 | import java.awt.*; 7 | import java.awt.event.*; 8 | import javax.swing.*; 9 | 10 | import java.io.IOException; 11 | 12 | public class EventLogTabCompletion extends GenericTabCompletion { 13 | protected RpcConnection connection; 14 | 15 | public EventLogTabCompletion(Console window, RpcConnection connection) { 16 | super(window); 17 | this.connection = connection; 18 | } 19 | 20 | public Collection getOptions(String text) { 21 | try { 22 | Map response = (Map)connection.execute("armitage.lusers", new Object[] {}); 23 | 24 | if (response.get("lusers") == null) 25 | return null; 26 | 27 | Iterator users = ((Collection)response.get("lusers")).iterator(); 28 | 29 | LinkedList options = new LinkedList(); 30 | String word; 31 | String pre; 32 | 33 | if (text.endsWith(" ")) { 34 | word = ""; 35 | pre = text; 36 | } 37 | if (text.lastIndexOf(" ") != -1) { 38 | word = text.substring(text.lastIndexOf(" ") + 1); 39 | pre = text.substring(0, text.lastIndexOf(" ") + 1); 40 | } 41 | else { 42 | word = text; 43 | pre = ""; 44 | } 45 | 46 | while (users.hasNext()) { 47 | String user = users.next() + ""; 48 | if (user.startsWith(word)) { 49 | options.add(pre + user); 50 | } 51 | } 52 | 53 | return options; 54 | } 55 | catch (IOException ioex) { 56 | ioex.printStackTrace(); 57 | } 58 | return null; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/cortana/data/Host.java: -------------------------------------------------------------------------------- 1 | package cortana.data; 2 | 3 | import java.util.*; 4 | 5 | /* A container for a host. */ 6 | public class Host { 7 | protected Map sessions; 8 | protected Map services; 9 | protected String address; 10 | protected Map data; 11 | 12 | public Host(String address, Map data) { 13 | this.address = address; 14 | this.data = data; 15 | sessions = new HashMap(); 16 | services = new HashMap(); 17 | 18 | fixOSValues(); 19 | 20 | data.put("sessions", sessions); 21 | data.put("services", services); 22 | } 23 | 24 | public Map getData() { 25 | return data; 26 | } 27 | 28 | public Map getSessions() { 29 | return sessions; 30 | } 31 | 32 | public Map getServices() { 33 | return services; 34 | } 35 | 36 | public boolean hasService(String port) { 37 | return services.containsKey(port); 38 | } 39 | 40 | public Set serviceSet() { 41 | Set rv = new HashSet(); 42 | Iterator i = services.keySet().iterator(); 43 | while (i.hasNext()) { 44 | rv.add(new Service(address, i.next() + "")); 45 | } 46 | return rv; 47 | } 48 | 49 | /* fix up some operating system identifying information */ 50 | protected void fixOSValues() { 51 | if ("".equals(data.get("os_name"))) { 52 | data.put("os_name", "Unknown"); 53 | } 54 | else { 55 | data.put("os_match", data.get("os_name") + " " + data.get("os_flavor") + " " + data.get("os_sp")); 56 | } 57 | data.put("show", Boolean.TRUE); 58 | } 59 | 60 | public void update(Map data) { 61 | this.data.putAll(data); 62 | fixOSValues(); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Raphael Mudge 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, 5 | are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation and/or 12 | other materials provided with the distribution. 13 | 14 | 3. Neither the name of the copyright holder nor the names of its contributors 15 | may be used to endorse or promote products derived from this software without 16 | specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /src/cortana/data/Credential.java: -------------------------------------------------------------------------------- 1 | package cortana.data; 2 | 3 | import java.util.*; 4 | import sleep.runtime.*; 5 | 6 | /* represent a credential in a Set */ 7 | public class Credential { 8 | protected String host; 9 | protected String port; 10 | protected String user; 11 | protected String pass; 12 | protected String type; 13 | 14 | public String getHost() { 15 | return host; 16 | } 17 | 18 | public String getPort() { 19 | return port; 20 | } 21 | 22 | public Credential(String host, String port, String user, String pass, String type) { 23 | this.host = host; 24 | this.port = port; 25 | this.user = user; 26 | this.pass = pass; 27 | this.type = type; 28 | } 29 | 30 | public Stack arguments() { 31 | Stack arguments = new Stack(); 32 | arguments.push(SleepUtils.getScalar(type)); 33 | arguments.push(SleepUtils.getScalar(pass)); 34 | arguments.push(SleepUtils.getScalar(user)); 35 | arguments.push(SleepUtils.getScalar(port)); 36 | arguments.push(SleepUtils.getScalar(host)); 37 | return arguments; 38 | } 39 | 40 | public boolean equals(Object o) { 41 | if (o instanceof Credential) { 42 | Credential t = (Credential)o; 43 | return (t.host.equals(host) && t.port.equals(port) && t.user.equals(user) && t.pass.equals(pass) && t.type.equals(type)); 44 | } 45 | return false; 46 | } 47 | 48 | public int hashCode() { 49 | return host.hashCode() + port.hashCode() + user.hashCode() + pass.hashCode() + type.hashCode(); 50 | } 51 | 52 | public String toString() { 53 | return user + ":" + pass + "@" + host + ":" + port + "/" + type; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/ssl/ArmitageTrustManager.java: -------------------------------------------------------------------------------- 1 | package ssl; 2 | 3 | import java.net.*; 4 | import java.io.*; 5 | import javax.net.ssl.*; 6 | import javax.net.*; 7 | import java.util.*; 8 | 9 | import java.security.*; 10 | import java.security.cert.*; 11 | 12 | import java.math.*; 13 | 14 | import javax.swing.*; 15 | 16 | public class ArmitageTrustManager implements X509TrustManager { 17 | protected ArmitageTrustListener checker; 18 | 19 | public ArmitageTrustManager(ArmitageTrustListener checker) { 20 | this.checker = checker; 21 | } 22 | 23 | public void checkClientTrusted(X509Certificate ax509certificate[], String authType) { 24 | return; 25 | } 26 | 27 | public void checkServerTrusted(X509Certificate ax509certificate[], String authType) throws CertificateException { 28 | try { 29 | for (int x = 0; x < ax509certificate.length; x++) { 30 | byte[] bytesOfMessage = ax509certificate[x].getEncoded(); 31 | MessageDigest md = MessageDigest.getInstance("SHA1"); 32 | byte[] thedigest = md.digest(bytesOfMessage); 33 | 34 | BigInteger bi = new BigInteger(1, thedigest); 35 | String fingerprint = bi.toString(16); 36 | 37 | if (checker != null && !checker.trust(fingerprint)) 38 | throw new CertificateException("Certificate Rejected. Press Cancel."); 39 | } 40 | 41 | return; 42 | } 43 | catch (CertificateException cex) { 44 | throw cex; 45 | } 46 | catch (Exception ex) { 47 | throw new CertificateException(ex.getMessage()); 48 | } 49 | } 50 | 51 | public X509Certificate[] getAcceptedIssuers() { 52 | return new X509Certificate[0]; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /dist/mac/readme-osx.rtf: -------------------------------------------------------------------------------- 1 | {\rtf1\ansi\ansicpg1252\cocoartf1265 2 | \cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;} 3 | {\colortbl;\red255\green255\blue255;} 4 | {\*\listtable{\list\listtemplateid1\listhybrid{\listlevel\levelnfc23\levelnfcn23\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace360\levelindent0{\*\levelmarker \{disc\}}{\leveltext\leveltemplateid1\'01\uc0\u8226 ;}{\levelnumbers;}\fi-360\li720\lin720 }{\listname ;}\listid1}} 5 | {\*\listoverridetable{\listoverride\listid1\listoverridecount0\ls1}} 6 | \margl1440\margr1440\vieww10980\viewh8600\viewkind0 7 | \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural 8 | 9 | \f0\fs24 \cf0 Welcome to 10 | \b Armitage for Mac OS X 11 | \b0 .\ 12 | \ 13 | A few things to note:\ 14 | \ 15 | \pard\tx220\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\li720\fi-720\pardirnatural 16 | \ls1\ilvl0\cf0 {\listtext \'95 }Armitage requires Oracle\'92s Java 1.7. \ 17 | {\listtext \'95 }I do not provide help installing Metasploit on MacOS X. You're on your own.\ 18 | \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural 19 | \cf0 \ 20 | \pard\tx560\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\pardirnatural 21 | \cf0 That said, you may use Armitage to connect to a remote Metasploit instance and collaborate with your team. It's for this use case I have created this package.\ 22 | \ 23 | If you opt to install Metasploit on MacOS X, make sure msfrpcd is in your $PATH. Consider using sudo -E to start armitage (to inherit the necessary environment info to start MSF).\ 24 | } -------------------------------------------------------------------------------- /src/cortana/CortanaPipe.java: -------------------------------------------------------------------------------- 1 | package cortana; 2 | 3 | import java.io.*; 4 | import java.util.*; 5 | 6 | /* a pipe to receive output from Cortana and make it available in an event driven way to the user */ 7 | public class CortanaPipe implements Runnable { 8 | protected PipedInputStream readme; 9 | protected PipedOutputStream writeme; 10 | 11 | public OutputStream getOutput() { 12 | return writeme; 13 | } 14 | 15 | public CortanaPipe() { 16 | try { 17 | readme = new PipedInputStream(1024 * 1024 * 1); 18 | writeme = new PipedOutputStream(readme); 19 | } 20 | catch (IOException ioex) { 21 | ioex.printStackTrace(); 22 | } 23 | } 24 | 25 | public interface CortanaPipeListener { 26 | public void read(String text); 27 | } 28 | 29 | protected List listeners = new LinkedList(); 30 | 31 | public void addCortanaPipeListener(CortanaPipeListener l) { 32 | synchronized (this) { 33 | listeners.add(l); 34 | } 35 | 36 | if (listeners.size() == 1) { 37 | new Thread(this).start(); 38 | } 39 | } 40 | 41 | public void run() { 42 | BufferedReader in = new BufferedReader(new InputStreamReader(readme)); 43 | while (true) { 44 | try { 45 | String entry = in.readLine(); 46 | if (entry != null) { 47 | synchronized (this) { 48 | Iterator i = listeners.iterator(); 49 | while (i.hasNext()) { 50 | CortanaPipeListener l = (CortanaPipeListener)i.next(); 51 | l.read(entry); 52 | } 53 | } 54 | } 55 | } 56 | catch (IOException ioex) { 57 | try { 58 | Thread.sleep(500); 59 | } 60 | catch (Exception ex) { } 61 | //ioex.printStackTrace(); 62 | } 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/cortana/Safety.java: -------------------------------------------------------------------------------- 1 | package cortana; 2 | 3 | import javax.swing.*; 4 | import sleep.runtime.*; 5 | 6 | /** Safety utilities */ 7 | public class Safety { 8 | /* should we ask the user what they want in life? */ 9 | public static boolean shouldAsk(ScriptInstance script) { 10 | return (script.getDebugFlags() & Cortana.DEBUG_INTERACT_ASK) == Cortana.DEBUG_INTERACT_ASK; 11 | } 12 | 13 | /* should we log what the script is d oing? */ 14 | public static boolean shouldLog(ScriptInstance script) { 15 | return (script.getDebugFlags() & Cortana.DEBUG_INTERACT_LOG) == Cortana.DEBUG_INTERACT_LOG; 16 | } 17 | 18 | /* let's log what the script is doing... for giggles */ 19 | public static void log(ScriptInstance script, String text) { 20 | script.getScriptEnvironment().showDebugMessage(text); 21 | } 22 | 23 | /* let's prompt the user and act accordingly */ 24 | public static boolean ask(ScriptInstance script, String description, String shortd) { 25 | int result = JOptionPane.showConfirmDialog(null, description, "Approve Script Action?", JOptionPane.YES_NO_CANCEL_OPTION); 26 | if (result == JOptionPane.YES_OPTION) { 27 | return true; 28 | } 29 | else if (result == JOptionPane.NO_OPTION) { 30 | Safety.log(script, "blocked " + shortd); 31 | return false; 32 | } 33 | else if (result == JOptionPane.CANCEL_OPTION) { 34 | //int flags = script.getDebugFlags() & ~Cortana.DEBUG_INTERACT_ASK; 35 | //script.setDebugFlags(flags); 36 | Safety.log(script, "user canceled script"); 37 | script.getScriptEnvironment().flagReturn(SleepUtils.getScalar("user canceled script"), ScriptEnvironment.FLOW_CONTROL_THROW); 38 | return true; 39 | } 40 | 41 | return false; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/cortana/core/Commands.java: -------------------------------------------------------------------------------- 1 | package cortana.core; 2 | 3 | import java.util.*; 4 | 5 | import sleep.runtime.*; 6 | import sleep.interfaces.*; 7 | import sleep.engine.*; 8 | import sleep.bridges.*; 9 | 10 | public class Commands implements Function, Environment, Loadable { 11 | protected CommandManager manager; 12 | 13 | public void scriptLoaded(ScriptInstance si) { 14 | Hashtable environment = si.getScriptEnvironment().getEnvironment(); 15 | 16 | environment.put("&command", this); 17 | environment.put("command", this); 18 | 19 | environment.put("&fire_command", this); 20 | } 21 | 22 | public void scriptUnloaded(ScriptInstance si) { 23 | } 24 | 25 | public void bindFunction(ScriptInstance si, String type, String command, Block body) { 26 | SleepClosure f = new SleepClosure(si, body); 27 | manager.registerCommand(command, f); 28 | } 29 | 30 | public Scalar evaluate(String name, ScriptInstance script, Stack args) { 31 | String command = BridgeUtilities.getString(args, ""); 32 | if (name.equals("&fire_command")) { 33 | StringBuffer arstring = new StringBuffer(); 34 | LinkedList l = new LinkedList(args); 35 | l.add(command); 36 | Collections.reverse(l); 37 | Iterator i = l.iterator(); 38 | while (i.hasNext()) { 39 | arstring.append(i.next() + ""); 40 | if (i.hasNext()) 41 | arstring.append(" "); 42 | } 43 | 44 | manager.fireCommand(command, arstring + "", args); 45 | return SleepUtils.getEmptyScalar(); 46 | } 47 | else { 48 | SleepClosure f = BridgeUtilities.getFunction(args, script); 49 | manager.registerCommand(command, f); 50 | return SleepUtils.getEmptyScalar(); 51 | } 52 | } 53 | 54 | public Commands(CommandManager m) { 55 | this.manager = m; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/cortana/gui/MenuBuilder.java: -------------------------------------------------------------------------------- 1 | package cortana.gui; 2 | 3 | import cortana.core.*; 4 | import msf.*; 5 | import armitage.*; 6 | import ui.*; 7 | 8 | import sleep.bridges.*; 9 | import sleep.interfaces.*; 10 | import sleep.runtime.*; 11 | import sleep.engine.*; 12 | 13 | import java.util.*; 14 | 15 | import java.awt.*; 16 | import java.awt.event.*; 17 | import javax.swing.*; 18 | import javax.swing.event.*; 19 | 20 | import java.io.IOException; 21 | 22 | /* an API to bind new menus in Armitage */ 23 | public class MenuBuilder { 24 | protected ArmitageApplication armitage; 25 | protected MenuBridge bridge; 26 | 27 | public MenuBuilder(ArmitageApplication a) { 28 | armitage = a; 29 | bridge = new MenuBridge(a); 30 | } 31 | 32 | public Loadable getBridge() { 33 | return bridge; 34 | } 35 | 36 | public void installMenu(MouseEvent ev, String key, Stack argz) { 37 | if (ev.isPopupTrigger() && bridge.isPopulated(key)) { 38 | JPopupMenu menu = new JPopupMenu(); 39 | setupMenu(menu, key, argz); 40 | 41 | /* we check, because it may have changed its mind after setupMenu failed */ 42 | if (bridge.isPopulated(key)) { 43 | menu.show((JComponent)ev.getSource(), ev.getX(), ev.getY()); 44 | ev.consume(); 45 | } 46 | } 47 | } 48 | 49 | public void setupMenu(JComponent parent, String key, Stack argz) { 50 | if (!bridge.isPopulated(key)) 51 | return; 52 | 53 | /* setup the menu */ 54 | bridge.push(parent, argz); 55 | 56 | Iterator i = bridge.getMenus(key).iterator(); 57 | while (i.hasNext()) { 58 | SleepClosure f = (SleepClosure)i.next(); 59 | if (f.getOwner().isLoaded()) { 60 | SleepUtils.runCode(f, key, null, cortana.core.EventManager.shallowCopy(argz)); 61 | } 62 | else { 63 | i.remove(); 64 | } 65 | } 66 | 67 | bridge.pop(); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/ui/ModuleTransferHandler.java: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | import java.awt.*; 4 | import java.awt.event.*; 5 | import javax.swing.*; 6 | 7 | import java.awt.datatransfer.*; 8 | import java.awt.dnd.*; 9 | import javax.swing.tree.*; 10 | 11 | public class ModuleTransferHandler extends TransferHandler { 12 | public int getSourceActions(JComponent c) { 13 | return COPY_OR_MOVE; 14 | } 15 | 16 | public Transferable createTransferable(JComponent c) { 17 | if (c instanceof JTree) { 18 | JTree temp = (JTree)c; 19 | TreePath path = temp.getSelectionPath(); 20 | 21 | if (path != null) { 22 | StringBuffer pathz = new StringBuffer(); 23 | Object o[] = path.getPath(); 24 | for (int x = 1; x < o.length; x++) { 25 | pathz.append(o[x] + ""); 26 | 27 | if ((x + 1) < o.length) 28 | pathz.append("/"); 29 | } 30 | 31 | return new StringSelection(pathz + ""); 32 | } 33 | } 34 | return null; 35 | } 36 | 37 | public void exportDone(JComponent c, Transferable t, int action) { 38 | } 39 | 40 | public boolean canImport(TransferHandler.TransferSupport blah) { 41 | if (blah.getComponent() instanceof JTree) { 42 | return false; 43 | } 44 | return true; 45 | } 46 | 47 | public interface ModuleTransferListener { 48 | public void completeTransfer(String text, Point location); 49 | } 50 | 51 | protected ModuleTransferListener completeJob = null; 52 | public void setHandler(ModuleTransferListener l) { 53 | completeJob = l; 54 | } 55 | 56 | public boolean importData(TransferHandler.TransferSupport blah) { 57 | try { 58 | Point coords = blah.getDropLocation().getDropPoint(); 59 | String text = blah.getTransferable().getTransferData(DataFlavor.stringFlavor) + ""; 60 | if (completeJob != null) 61 | completeJob.completeTransfer(text, coords); 62 | } 63 | catch (Exception ex) { 64 | 65 | } 66 | return true; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/cortana/gui/KeyBridge.java: -------------------------------------------------------------------------------- 1 | package cortana.gui; 2 | 3 | import cortana.core.*; 4 | import msf.*; 5 | import armitage.*; 6 | import ui.*; 7 | 8 | import sleep.bridges.*; 9 | import sleep.interfaces.*; 10 | import sleep.runtime.*; 11 | import sleep.engine.*; 12 | 13 | import java.util.*; 14 | 15 | import java.io.IOException; 16 | 17 | /* an API to bind new keys in Armitage */ 18 | public class KeyBridge implements Loadable, Function, Environment { 19 | protected ArmitageApplication armitage; 20 | 21 | public KeyBridge(ArmitageApplication a) { 22 | armitage = a; 23 | } 24 | 25 | private static class Binding implements KeyHandler { 26 | protected SleepClosure code; 27 | 28 | public Binding(SleepClosure c) { 29 | code = c; 30 | } 31 | 32 | public void key_pressed(String description) { 33 | if (code != null && code.getOwner().isLoaded()) { 34 | SleepUtils.runCode(code, description, null, new Stack()); 35 | } 36 | else { 37 | code = null; 38 | } 39 | } 40 | } 41 | 42 | protected void registerKey(String combination, SleepClosure closure) { 43 | Binding b = new Binding(closure); 44 | armitage.bindKey(combination, b); 45 | } 46 | 47 | public void bindFunction(ScriptInstance si, String type, String event, Block body) { 48 | SleepClosure f = new SleepClosure(si, body); 49 | registerKey(event, f); 50 | } 51 | 52 | public Scalar evaluate(String name, ScriptInstance script, Stack args) { 53 | String desc = BridgeUtilities.getString(args, ""); 54 | SleepClosure f = BridgeUtilities.getFunction(args, script); 55 | registerKey(desc, f); 56 | return SleepUtils.getEmptyScalar(); 57 | } 58 | 59 | public void scriptLoaded(ScriptInstance si) { 60 | si.getScriptEnvironment().getEnvironment().put("bind", this); 61 | si.getScriptEnvironment().getEnvironment().put("&bind", this); 62 | } 63 | 64 | public void scriptUnloaded(ScriptInstance si) { 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/cortana/support/Heartbeat.java: -------------------------------------------------------------------------------- 1 | package cortana.support; 2 | 3 | import cortana.core.*; 4 | import cortana.*; 5 | 6 | import java.util.*; 7 | 8 | /* a thread to keep track of different timer events and fire them off when it's appropriate */ 9 | public class Heartbeat implements Runnable { 10 | protected EventManager events; 11 | protected List beats; 12 | 13 | private class Beat { 14 | protected long next = 0L; 15 | protected long mark; 16 | protected String event; 17 | 18 | public Beat(String event, long mark) { 19 | this.mark = mark; 20 | this.event = event; 21 | next = System.currentTimeMillis() + mark; 22 | } 23 | 24 | public void check(long now) { 25 | if (next <= now) { 26 | next = System.currentTimeMillis() + mark; 27 | events.fireEvent(event, new Stack()); 28 | } 29 | } 30 | } 31 | 32 | public Heartbeat(EventManager e) { 33 | events = e; 34 | beats = new LinkedList(); 35 | beats.add(new Beat("heartbeat_1s", 1 * 1000)); 36 | beats.add(new Beat("heartbeat_5s", 5 * 1000)); 37 | beats.add(new Beat("heartbeat_10s", 10 * 1000)); 38 | beats.add(new Beat("heartbeat_15s", 15 * 1000)); 39 | beats.add(new Beat("heartbeat_30s", 30 * 1000)); 40 | beats.add(new Beat("heartbeat_1m", 60 * 1000)); 41 | beats.add(new Beat("heartbeat_5m", 5 * 60 * 1000)); 42 | beats.add(new Beat("heartbeat_10m", 10 * 60 * 1000)); 43 | beats.add(new Beat("heartbeat_15m", 15 * 60 * 1000)); 44 | beats.add(new Beat("heartbeat_20m", 20 * 60 * 1000)); 45 | beats.add(new Beat("heartbeat_30m", 30 * 60 * 1000)); 46 | beats.add(new Beat("heartbeat_60m", 60 * 60 * 1000)); 47 | } 48 | 49 | public void start() { 50 | new Thread(this).start(); 51 | } 52 | 53 | public void run() { 54 | while (true) { 55 | try { 56 | long now = System.currentTimeMillis(); 57 | Iterator i = beats.iterator(); 58 | while (i.hasNext()) { 59 | Beat temp = (Beat)i.next(); 60 | temp.check(now); 61 | } 62 | Thread.sleep(1000); 63 | } 64 | catch (Exception ex) { 65 | ex.printStackTrace(); 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/ui/CutCopyPastePopup.java: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | import javax.swing.*; 4 | import javax.swing.event.*; 5 | import javax.swing.text.*; 6 | 7 | import java.awt.*; 8 | import java.awt.event.*; 9 | 10 | 11 | /* A textfield with a popup menu to cut, copy, paste, and clear the textfield */ 12 | public class CutCopyPastePopup { 13 | protected JPopupMenu menu = null; 14 | protected JTextComponent component = null; 15 | 16 | public CutCopyPastePopup(JTextComponent component) { 17 | this.component = component; 18 | createMenu(); 19 | } 20 | 21 | public void createMenu() { 22 | if (menu != null) 23 | return; 24 | 25 | menu = new JPopupMenu(); 26 | JMenuItem cut = new JMenuItem("Cut", 'C'); 27 | 28 | cut.addActionListener(new ActionListener() { 29 | public void actionPerformed(ActionEvent ev) { 30 | component.cut(); 31 | } 32 | }); 33 | 34 | JMenuItem copy = new JMenuItem("Copy", 'o'); 35 | 36 | copy.addActionListener(new ActionListener() { 37 | public void actionPerformed(ActionEvent ev) { 38 | component.copy(); 39 | } 40 | }); 41 | 42 | JMenuItem paste = new JMenuItem("Paste", 'p'); 43 | 44 | paste.addActionListener(new ActionListener() { 45 | public void actionPerformed(ActionEvent ev) { 46 | component.paste(); 47 | } 48 | }); 49 | 50 | JMenuItem clear = new JMenuItem("Clear", 'l'); 51 | 52 | clear.addActionListener(new ActionListener() { 53 | public void actionPerformed(ActionEvent ev) { 54 | component.setText(""); 55 | } 56 | }); 57 | 58 | menu.add(cut); 59 | menu.add(copy); 60 | menu.add(paste); 61 | menu.add(clear); 62 | 63 | component.addMouseListener(new MouseAdapter() { 64 | public void handle(MouseEvent ev) { 65 | if (ev.isPopupTrigger()) { 66 | menu.show((JComponent)ev.getSource(), ev.getX(), ev.getY()); 67 | } 68 | } 69 | 70 | public void mousePressed(MouseEvent ev) { 71 | handle(ev); 72 | } 73 | 74 | public void mouseClicked(MouseEvent ev) { 75 | handle(ev); 76 | } 77 | 78 | public void mouseReleased(MouseEvent ev) { 79 | handle(ev); 80 | } 81 | }); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/cortana/core/Events.java: -------------------------------------------------------------------------------- 1 | package cortana.core; 2 | 3 | import java.util.*; 4 | 5 | import sleep.runtime.*; 6 | import sleep.interfaces.*; 7 | import sleep.engine.*; 8 | import sleep.bridges.*; 9 | 10 | public class Events implements Function, Environment, Loadable { 11 | protected EventManager manager; 12 | 13 | public void scriptLoaded(ScriptInstance si) { 14 | Hashtable environment = si.getScriptEnvironment().getEnvironment(); 15 | 16 | environment.put("&on", this); 17 | environment.put("on", this); 18 | 19 | environment.put("&when", this); 20 | environment.put("when", this); 21 | 22 | environment.put("&fire_event", this); 23 | environment.put("&fire_event_async", this); 24 | environment.put("&fire_event_local", this); 25 | } 26 | 27 | public void scriptUnloaded(ScriptInstance si) { 28 | } 29 | 30 | protected void addListener(String name, SleepClosure c, boolean temp) { 31 | manager.addListener(name, c, temp); 32 | } 33 | 34 | public void bindFunction(ScriptInstance si, String type, String event, Block body) { 35 | boolean temporary = type.equals("when") ? true : false; 36 | SleepClosure f = new SleepClosure(si, body); 37 | addListener(event, f, temporary); 38 | } 39 | 40 | public Scalar evaluate(String name, ScriptInstance script, Stack args) { 41 | if (name.equals("&fire_event_async") || name.equals("&fire_event")) { 42 | String event = BridgeUtilities.getString(args, ""); 43 | manager.fireEventAsync(event, EventManager.shallowCopy(args)); 44 | return SleepUtils.getEmptyScalar(); 45 | } 46 | else if (name.equals("&fire_event_local")) { 47 | String event = BridgeUtilities.getString(args, ""); 48 | manager.fireEvent(event, args, script); 49 | return SleepUtils.getEmptyScalar(); 50 | } 51 | else { 52 | boolean temporary = name.equals("&when") ? true : false; 53 | String event = BridgeUtilities.getString(args, ""); 54 | SleepClosure f = BridgeUtilities.getFunction(args, script); 55 | addListener(event, f, temporary); 56 | return SleepUtils.getEmptyScalar(); 57 | } 58 | } 59 | 60 | public Events(EventManager m) { 61 | this.manager = m; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/cortana/core/Filters.java: -------------------------------------------------------------------------------- 1 | package cortana.core; 2 | 3 | import java.util.*; 4 | 5 | import sleep.runtime.*; 6 | import sleep.interfaces.*; 7 | import sleep.engine.*; 8 | import sleep.bridges.*; 9 | 10 | public class Filters implements Function, Environment, Loadable { 11 | protected FilterManager manager; 12 | 13 | public void scriptLoaded(ScriptInstance si) { 14 | Hashtable environment = si.getScriptEnvironment().getEnvironment(); 15 | 16 | environment.put("filter", this); 17 | environment.put("&filter_data", this); 18 | environment.put("&filter_data_array", this); 19 | environment.put("&filterd", this); 20 | } 21 | 22 | public void scriptUnloaded(ScriptInstance si) { 23 | } 24 | 25 | protected void addFilter(String name, SleepClosure c) { 26 | manager.addFilter(name, c); 27 | } 28 | 29 | public void bindFunction(ScriptInstance si, String type, String event, Block body) { 30 | SleepClosure f = new SleepClosure(si, body); 31 | addFilter(event, f); 32 | } 33 | 34 | public Scalar evaluate(String name, ScriptInstance script, Stack args) { 35 | args = (Stack)args.clone(); 36 | 37 | if (name.equals("&filter_data")) { 38 | String event = BridgeUtilities.getString(args, ""); 39 | Stack results = manager.filterScalarData(event, args); 40 | Scalar r = SleepUtils.getArrayScalar(); 41 | 42 | while (!results.isEmpty()) { 43 | r.getArray().push((Scalar)results.pop()); 44 | } 45 | 46 | return r; 47 | } 48 | else if (name.equals("&filter_data_array")) { 49 | Stack argz = new Stack(); 50 | Scalar event = BridgeUtilities.getScalar(args); 51 | 52 | ScalarArray temp = BridgeUtilities.getArray(args); 53 | while (temp.size() > 0) { 54 | argz.push(temp.pop()); 55 | } 56 | 57 | argz.push(event); 58 | return evaluate("&filter_data", script, argz); 59 | } 60 | else { 61 | String event = BridgeUtilities.getString(args, ""); 62 | SleepClosure f = BridgeUtilities.getFunction(args, script); 63 | addFilter(event, f); 64 | return SleepUtils.getEmptyScalar(); 65 | } 66 | } 67 | 68 | public Filters(FilterManager m) { 69 | this.manager = m; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/graph/CircleLayout.java: -------------------------------------------------------------------------------- 1 | package graph; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.mxgraph.model.mxIGraphModel; 7 | import com.mxgraph.util.mxRectangle; 8 | import com.mxgraph.view.mxGraph; 9 | import com.mxgraph.layout.*; 10 | 11 | public class CircleLayout extends mxCircleLayout 12 | { 13 | public CircleLayout(mxGraph graph, double r) { 14 | super(graph, r); 15 | } 16 | 17 | /* override this so it doesn't make the circle so damned big :P */ 18 | public void execute(Object parent, int width, int height, double zoom) 19 | { 20 | mxIGraphModel model = graph.getModel(); 21 | model.beginUpdate(); 22 | try 23 | { 24 | double max = 0; 25 | Double top = null; 26 | Double left = null; 27 | List vertices = new ArrayList(); 28 | int childCount = model.getChildCount(parent); 29 | 30 | for (int i = 0; i < childCount; i++) 31 | { 32 | Object cell = model.getChildAt(parent, i); 33 | 34 | if (!isVertexIgnored(cell)) 35 | { 36 | vertices.add(cell); 37 | mxRectangle bounds = getVertexBounds(cell); 38 | 39 | if (top == null) 40 | { 41 | top = bounds.getY(); 42 | } 43 | else 44 | { 45 | top = Math.min(top, bounds.getY()); 46 | } 47 | 48 | if (left == null) 49 | { 50 | left = bounds.getX(); 51 | } 52 | else 53 | { 54 | left = Math.min(left, bounds.getX()); 55 | } 56 | 57 | max = Math.min(max, Math.max(bounds.getWidth(), bounds.getHeight())); 58 | } 59 | else if (!isEdgeIgnored(cell)) 60 | { 61 | if (isResetEdges()) 62 | { 63 | graph.resetEdge(cell); 64 | } 65 | 66 | if (isDisableEdgeStyle()) 67 | { 68 | setEdgeStyleEnabled(cell, false); 69 | } 70 | } 71 | } 72 | 73 | int vertexCount = vertices.size(); 74 | double r = (width > height ? height : width) / (2.80 * zoom); 75 | 76 | // Moves the circle to the specified origin 77 | if (moveCircle) 78 | { 79 | top = x0; 80 | left = y0; 81 | } 82 | 83 | circle(vertices.toArray(), r, left.doubleValue(), top.doubleValue()); 84 | } 85 | finally 86 | { 87 | model.endUpdate(); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/graph/RefreshGraph.java: -------------------------------------------------------------------------------- 1 | package graph; 2 | 3 | import java.util.*; 4 | import java.awt.Image; 5 | import javax.swing.SwingUtilities; 6 | 7 | public class RefreshGraph implements Runnable { 8 | protected List nodes = new LinkedList(); 9 | protected List highlights = new LinkedList(); 10 | protected List routes = new LinkedList(); 11 | protected Refreshable graph = null; 12 | 13 | private static class Highlight { 14 | public String gateway = ""; 15 | public String host = ""; 16 | } 17 | 18 | private static class Node { 19 | public String id = ""; 20 | public String label = ""; 21 | public String description = ""; 22 | public Image iconz = null; 23 | public String tooltip = ""; 24 | } 25 | 26 | public RefreshGraph(Refreshable graph) { 27 | this.graph = graph; 28 | } 29 | 30 | /* call this when our data is built up and ready to be used to update our display */ 31 | public void go() { 32 | SwingUtilities.invokeLater(this); 33 | } 34 | 35 | public void addRoute(Route route) { 36 | routes.add(route); 37 | } 38 | 39 | public void addNode(String id, String label, String description, Image iconz, String tooltip) { 40 | Node n = new Node(); 41 | n.id = id; 42 | n.label = label; 43 | n.description = description; 44 | n.iconz = iconz; 45 | n.tooltip = tooltip; 46 | nodes.add(n); 47 | } 48 | 49 | public void addHighlight(String gateway, String host) { 50 | Highlight h = new Highlight(); 51 | h.gateway = gateway; 52 | h.host = host; 53 | highlights.add(h); 54 | } 55 | 56 | public void run() { 57 | graph.start(); 58 | 59 | /* add nodes to the graph */ 60 | Iterator i = nodes.iterator(); 61 | while (i.hasNext()) { 62 | Node n = (Node)i.next(); 63 | graph.addNode(n.id, n.label, n.description, n.iconz, n.tooltip); 64 | } 65 | 66 | /* setup routes */ 67 | graph.setRoutes((Route[])routes.toArray(new Route[0])); 68 | 69 | /* highlight routes */ 70 | i = highlights.iterator(); 71 | while (i.hasNext()) { 72 | Highlight h = (Highlight)i.next(); 73 | graph.highlightRoute(h.gateway, h.host); 74 | } 75 | 76 | /* anything we didn't touch should go */ 77 | graph.deleteNodes(); 78 | 79 | 80 | graph.end(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/ui/ATextField.java: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | import javax.swing.*; 4 | import javax.swing.event.*; 5 | import javax.swing.text.*; 6 | 7 | import java.awt.*; 8 | import java.awt.event.*; 9 | 10 | 11 | /* A textfield with a popup menu to cut, copy, paste, and clear the textfield */ 12 | public class ATextField extends JTextField { 13 | protected JPopupMenu menu = null; 14 | 15 | public ATextField(int cols) { 16 | super(cols); 17 | createMenu(); 18 | } 19 | 20 | public ATextField(Document doc, String text, int cols) { 21 | super(doc, text, cols); 22 | createMenu(); 23 | } 24 | 25 | public ATextField(String text, int cols) { 26 | super(text, cols); 27 | createMenu(); 28 | } 29 | 30 | public ATextField() { 31 | super(); 32 | createMenu(); 33 | } 34 | 35 | public void createMenu() { 36 | if (menu != null) 37 | return; 38 | 39 | menu = new JPopupMenu(); 40 | JMenuItem cut = new JMenuItem("Cut", 'C'); 41 | JMenuItem copy = new JMenuItem("Copy", 'o'); 42 | JMenuItem paste = new JMenuItem("Paste", 'P'); 43 | JMenuItem clear = new JMenuItem("Clear", 'l'); 44 | 45 | cut.addActionListener(new ActionListener() { 46 | public void actionPerformed(ActionEvent ev) { 47 | cut(); 48 | } 49 | }); 50 | 51 | copy.addActionListener(new ActionListener() { 52 | public void actionPerformed(ActionEvent ev) { 53 | copy(); 54 | } 55 | }); 56 | 57 | paste.addActionListener(new ActionListener() { 58 | public void actionPerformed(ActionEvent ev) { 59 | paste(); 60 | } 61 | }); 62 | 63 | clear.addActionListener(new ActionListener() { 64 | public void actionPerformed(ActionEvent ev) { 65 | setText(""); 66 | } 67 | }); 68 | 69 | menu.add(cut); 70 | menu.add(copy); 71 | menu.add(paste); 72 | menu.add(clear); 73 | 74 | addMouseListener(new MouseAdapter() { 75 | public void handle(MouseEvent ev) { 76 | if (ev.isPopupTrigger()) { 77 | menu.show((JComponent)ev.getSource(), ev.getX(), ev.getY()); 78 | } 79 | } 80 | 81 | public void mousePressed(MouseEvent ev) { 82 | handle(ev); 83 | } 84 | 85 | public void mouseClicked(MouseEvent ev) { 86 | handle(ev); 87 | } 88 | 89 | public void mouseReleased(MouseEvent ev) { 90 | handle(ev); 91 | } 92 | }); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/ui/ZoomableImage.java: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | import javax.swing.*; 4 | import java.awt.*; 5 | import java.awt.image.*; 6 | import java.awt.event.*; 7 | import java.util.*; 8 | 9 | public class ZoomableImage extends JLabel { 10 | protected Icon original = null; 11 | protected double zoom = 1.0; 12 | 13 | private JMenuItem zoomMenu(String label, final double level) { 14 | JMenuItem i = new JMenuItem(label); 15 | i.addActionListener(new ActionListener() { 16 | public void actionPerformed(ActionEvent ev) { 17 | zoom = level; 18 | updateIcon(); 19 | } 20 | }); 21 | return i; 22 | } 23 | 24 | public ZoomableImage() { 25 | super(); 26 | 27 | final JPopupMenu menu = new JPopupMenu(); 28 | menu.add(zoomMenu("25%", 0.25)); 29 | menu.add(zoomMenu("50%", 0.50)); 30 | menu.add(zoomMenu("75%", 0.75)); 31 | menu.add(zoomMenu("100%", 1.0)); 32 | menu.add(zoomMenu("125%", 1.25)); 33 | menu.add(zoomMenu("150%", 1.5)); 34 | menu.add(zoomMenu("200%", 2.0)); 35 | menu.add(zoomMenu("250%", 2.5)); 36 | 37 | addMouseListener(new MouseAdapter() { 38 | public void check(MouseEvent ev) { 39 | if (ev.isPopupTrigger()) { 40 | menu.show((JComponent)ev.getSource(), ev.getX(), ev.getY()); 41 | ev.consume(); 42 | } 43 | } 44 | 45 | public void mouseClicked(MouseEvent ev) { 46 | check(ev); 47 | } 48 | 49 | public void mousePressed(MouseEvent ev) { 50 | check(ev); 51 | } 52 | 53 | public void mouseReleased(MouseEvent ev) { 54 | check(ev); 55 | } 56 | }); 57 | 58 | setHorizontalAlignment(SwingConstants.CENTER); 59 | } 60 | 61 | protected void updateIcon() { 62 | super.setIcon(resizeImage((ImageIcon)original)); 63 | } 64 | 65 | public void setIcon(Icon image) { 66 | original = image; 67 | updateIcon(); 68 | } 69 | 70 | protected Icon resizeImage(ImageIcon image) { 71 | if (zoom == 1.0 || image == null) { 72 | return image; 73 | } 74 | 75 | int width = image.getIconWidth(); 76 | int height = image.getIconHeight(); 77 | 78 | BufferedImage buffer = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); 79 | Graphics g = buffer.createGraphics(); 80 | g.drawImage(image.getImage(), 0, 0, width, height, null); 81 | g.dispose(); 82 | return new ImageIcon(buffer.getScaledInstance( (int)(width * zoom), (int)(height * zoom), Image.SCALE_SMOOTH)); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/ui/APasswordField.java: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | import javax.swing.*; 4 | import javax.swing.event.*; 5 | import javax.swing.text.*; 6 | 7 | import java.awt.*; 8 | import java.awt.event.*; 9 | 10 | 11 | /* A textfield with a popup menu to cut, copy, paste, and clear the textfield */ 12 | public class APasswordField extends JPasswordField { 13 | protected JPopupMenu menu = null; 14 | 15 | public APasswordField(int cols) { 16 | super(cols); 17 | createMenu(); 18 | } 19 | 20 | public APasswordField(Document doc, String text, int cols) { 21 | super(doc, text, cols); 22 | createMenu(); 23 | } 24 | 25 | public APasswordField(String text, int cols) { 26 | super(text, cols); 27 | createMenu(); 28 | } 29 | 30 | public APasswordField() { 31 | super(); 32 | createMenu(); 33 | } 34 | 35 | public String getPass() { 36 | return new String(getPassword()); 37 | } 38 | 39 | public void createMenu() { 40 | if (menu != null) 41 | return; 42 | 43 | menu = new JPopupMenu(); 44 | JMenuItem cut = new JMenuItem("Cut", 'C'); 45 | JMenuItem copy = new JMenuItem("Copy", 'o'); 46 | JMenuItem paste = new JMenuItem("Paste", 'P'); 47 | JMenuItem clear = new JMenuItem("Clear", 'l'); 48 | 49 | cut.addActionListener(new ActionListener() { 50 | public void actionPerformed(ActionEvent ev) { 51 | cut(); 52 | } 53 | }); 54 | 55 | copy.addActionListener(new ActionListener() { 56 | public void actionPerformed(ActionEvent ev) { 57 | copy(); 58 | } 59 | }); 60 | 61 | paste.addActionListener(new ActionListener() { 62 | public void actionPerformed(ActionEvent ev) { 63 | paste(); 64 | } 65 | }); 66 | 67 | clear.addActionListener(new ActionListener() { 68 | public void actionPerformed(ActionEvent ev) { 69 | setText(""); 70 | } 71 | }); 72 | 73 | menu.add(cut); 74 | menu.add(copy); 75 | menu.add(paste); 76 | menu.add(clear); 77 | 78 | addMouseListener(new MouseAdapter() { 79 | public void handle(MouseEvent ev) { 80 | if (ev.isPopupTrigger()) { 81 | menu.show((JComponent)ev.getSource(), ev.getX(), ev.getY()); 82 | } 83 | } 84 | 85 | public void mousePressed(MouseEvent ev) { 86 | handle(ev); 87 | } 88 | 89 | public void mouseClicked(MouseEvent ev) { 90 | handle(ev); 91 | } 92 | 93 | public void mouseReleased(MouseEvent ev) { 94 | handle(ev); 95 | } 96 | }); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /resources/armitage.prop: -------------------------------------------------------------------------------- 1 | #Armitage Configuration 2 | #Fri Oct 15 18:08:08 EDT 2010 3 | graph.font.font=Monospaced-BOLD-14 4 | console.clear_screen.shortcut=ctrl pressed K 5 | graph.zoom_out.shortcut=ctrl pressed MINUS 6 | graph.save_screenshot.shortcut=ctrl pressed P 7 | console.font_size_reset.shortcut=ctrl pressed 0 8 | console.page_down.shortcut=pressed PAGE_DOWN 9 | graph.arrange_icons_circle.shortcut=ctrl pressed C 10 | graph.selection.color=\#00ff00 11 | graph.zoom_in.shortcut=ctrl pressed EQUALS 12 | console.find.shortcut=ctrl pressed F 13 | console.history_previous.shortcut=pressed UP 14 | console.history_next.shortcut=pressed DOWN 15 | console.page_up.shortcut=pressed PAGE_UP 16 | console.highlight.color=\#0000cc 17 | console.font_size_plus.shortcut=ctrl pressed EQUALS 18 | console.font_size_minus.shortcut=ctrl pressed MINUS 19 | console.foreground.color=\#cccccc 20 | console.background.color=\#000000 21 | console.font.font=Monospaced-BOLD-14 22 | graph.arrange_icons_hierarchical.shortcut=ctrl pressed H 23 | graph.foreground.color=\#cccccc 24 | graph.background.color=\#111111 25 | graph.zoom_reset.shortcut=ctrl pressed 0 26 | console.clear_buffer.shortcut=pressed ESCAPE 27 | graph.edge.color=\#3c6318 28 | graph.arrange_icons_stack.shortcut=ctrl pressed S 29 | graph.edge_highlight.color=\#00ff00 30 | graph.default_layout.layout=stack 31 | application.skin.skin=Nimbus 32 | graph.clear_selection.shortcut=pressed ESCAPE 33 | graph.select_all.shortcut=ctrl pressed A 34 | armitage.required_exploit_rank.string=great 35 | armitage.string.target_view=graph 36 | console.select_all.shortcut=ctrl pressed A 37 | armitage.log_everything.boolean=true 38 | armitage.no_msf_banner.boolean=true 39 | tab.highlight.color=#0000ff 40 | armitage.show_all_commands.boolean=true 41 | armitage.application_title.string=Armitage 42 | console.color_0.color=\#ffffff 43 | console.color_1.color=\#000000 44 | console.color_2.color=\#3465A4 45 | console.color_3.color=\#4E9A06 46 | console.color_4.color=\#EF2929 47 | console.color_5.color=\#CC0000 48 | console.color_6.color=\#75507B 49 | console.color_7.color=\#C4A000 50 | console.color_8.color=\#FCE94F 51 | console.color_9.color=\#8AE234 52 | console.color_10.color=\#069A9A 53 | console.color_11.color=\#34E2E2 54 | console.color_12.color=\#729FCF 55 | console.color_13.color=\#AD7FA8 56 | console.color_14.color=\#808080 57 | console.color_15.color=\#c0c0c0 58 | console.show_colors.boolean=true 59 | -------------------------------------------------------------------------------- /src/cortana/data/Loots.java: -------------------------------------------------------------------------------- 1 | package cortana.data; 2 | 3 | import cortana.core.*; 4 | 5 | import armitage.ArmitageTimerClient; 6 | import armitage.ArmitageTimer; 7 | 8 | import graph.Route; 9 | 10 | import sleep.bridges.*; 11 | import sleep.interfaces.*; 12 | import sleep.runtime.*; 13 | import sleep.engine.*; 14 | 15 | import java.util.*; 16 | 17 | import java.io.IOException; 18 | 19 | import msf.*; 20 | 21 | public class Loots extends ManagedData { 22 | protected RpcConnection client; 23 | protected EventManager manager; 24 | protected Map loots = new HashMap(); 25 | 26 | public Collection getLoots() { 27 | return loots.values(); 28 | } 29 | 30 | public Scalar getScalar() { 31 | if (cache == null) 32 | cache = FilterManager.convertAll(getLoots()); 33 | 34 | return cache; 35 | } 36 | 37 | public Loots(RpcConnection client, EventManager manager) { 38 | this.client = client; 39 | this.manager = manager; 40 | } 41 | 42 | /* a shortcut to fire route events */ 43 | protected void fireLootEvents(String name, Iterator changes) { 44 | if (initial) 45 | return; 46 | 47 | while (changes.hasNext()) { 48 | String temp = (String)changes.next(); 49 | Stack arg = new Stack(); 50 | arg.push( FilterManager.convertAll(loots.get(temp)) ); 51 | manager.fireEventAsync(name, arg); 52 | } 53 | } 54 | 55 | public void processLoots(Map results) { 56 | if (!results.containsKey("loots")) 57 | return; 58 | 59 | /* invalidate the cache */ 60 | cache = null; 61 | 62 | /* create a set of existing loots */ 63 | Set oldLoots = new HashSet(); 64 | oldLoots.addAll(loots.keySet()); 65 | loots.clear(); 66 | 67 | /* parse and add loots */ 68 | 69 | Iterator i = ((Collection)results.get("loots")).iterator(); 70 | while (i.hasNext()) { 71 | Map temp = (Map)i.next(); 72 | loots.put(temp.get("path") + "", temp); 73 | } 74 | 75 | /* setup a set of our new loots */ 76 | Set currentLoots = new HashSet(); 77 | currentLoots.addAll(loots.keySet()); 78 | 79 | /* now... bucket our loots and fire some events */ 80 | Set newLoots = DataUtils.difference(currentLoots, oldLoots); 81 | fireLootEvents("loot_add", newLoots.iterator()); 82 | 83 | //Set goneLoots = DataUtils.difference(oldLoots, currentLoots); 84 | /* there's no such thing as a loot_delete event since loot goes away when a host is deleted */ 85 | 86 | /* ok, we've refreshed the loots too, let the world know eh? */ 87 | Stack arg = new Stack(); 88 | arg.push(FilterManager.convertAll(loots.values())); 89 | manager.fireEventAsync("loots", arg); 90 | 91 | initial = false; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/cortana/core/CommandManager.java: -------------------------------------------------------------------------------- 1 | package cortana.core; 2 | 3 | import java.util.*; 4 | import sleep.runtime.*; 5 | import sleep.bridges.*; 6 | import sleep.interfaces.*; 7 | 8 | public class CommandManager { 9 | protected Map commands; 10 | 11 | protected SleepClosure getCommand(String name) { 12 | if (commands.containsKey(name)) { 13 | SleepClosure temp = (SleepClosure)commands.get(name); 14 | if (temp.getOwner().isLoaded()) 15 | return temp; 16 | else 17 | commands.remove(name); 18 | } 19 | 20 | return null; 21 | } 22 | 23 | /* a function to help out with tab completion */ 24 | public List commandList(String filter) { 25 | Iterator i = commands.entrySet().iterator(); 26 | List res = new LinkedList(); 27 | while (i.hasNext()) { 28 | Map.Entry temp = (Map.Entry)i.next(); 29 | String command = temp.getKey() + ""; 30 | SleepClosure f = (SleepClosure)temp.getValue(); 31 | if (filter == null || command.startsWith(filter)) { 32 | if (f.getOwner().isLoaded()) { 33 | res.add(command); 34 | } 35 | else { 36 | i.remove(); 37 | } 38 | } 39 | } 40 | return res; 41 | } 42 | 43 | public Loadable getBridge() { 44 | return new Commands(this); 45 | } 46 | 47 | public CommandManager() { 48 | commands = new HashMap(); 49 | } 50 | 51 | public void registerCommand(String command, SleepClosure c) { 52 | commands.put(command, c); 53 | } 54 | 55 | public boolean fireCommand(String command, String args) { 56 | Stack tokens = new Stack(); 57 | StringBuffer token = new StringBuffer(); 58 | for (int x = 0; x < args.length(); x++) { 59 | char temp = args.charAt(x); 60 | if (temp == ' ') { 61 | if (token.length() > 0) 62 | tokens.add(0, SleepUtils.getScalar(token.toString())); 63 | token = new StringBuffer(); 64 | } 65 | else if (temp == '"' && token.length() == 0) { 66 | for (x++ ; x < args.length() && args.charAt(x) != '"'; x++) { 67 | token.append(args.charAt(x)); 68 | } 69 | tokens.add(0, SleepUtils.getScalar(token.toString())); 70 | token = new StringBuffer(); 71 | } 72 | else { 73 | token.append(temp); 74 | } 75 | } 76 | 77 | if (token.length() > 0) 78 | tokens.add(0, SleepUtils.getScalar(token.toString())); 79 | 80 | tokens.pop(); 81 | 82 | return fireCommand(command, args, tokens); 83 | } 84 | 85 | public boolean fireCommand(String command, String argz, Stack args) { 86 | SleepClosure c = getCommand(command); 87 | if (c == null) 88 | return false; 89 | 90 | SleepUtils.runCode(c, argz, null, EventManager.shallowCopy(args)); 91 | return true; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/msf/RpcQueue.java: -------------------------------------------------------------------------------- 1 | package msf; 2 | 3 | import console.*; 4 | 5 | import java.util.*; 6 | import java.awt.*; 7 | import java.awt.event.*; 8 | 9 | import msf.*; 10 | import java.math.*; 11 | import java.security.*; 12 | 13 | /* A pretty quick and dirty queue for executing RPC commands in turn and discarding their output. This 14 | has to be 100x better than creating a thread for every async thing I want to have happen via an RPC 15 | call */ 16 | public class RpcQueue implements Runnable { 17 | protected RpcConnection connection; 18 | protected LinkedList requests = new LinkedList(); 19 | 20 | private static class Request { 21 | public String method; 22 | public Object[] args; 23 | public RpcCallback callback = null; 24 | } 25 | 26 | public RpcQueue(RpcConnection connection) { 27 | this.connection = connection; 28 | new Thread(this).start(); 29 | } 30 | 31 | protected void processRequest(Request r) { 32 | try { 33 | Object result = connection.execute(r.method, r.args); 34 | if (r.callback != null) { 35 | r.callback.result(result); 36 | } 37 | } 38 | catch (Exception ex) { 39 | armitage.ArmitageMain.print_error("RpcQueue Method '" + r.method + "' failed: " + ex.getMessage()); 40 | for (int x = 0; x < r.args.length; x++) { 41 | System.err.println("\t" + x + ": " + r.args[x]); 42 | } 43 | ex.printStackTrace(); 44 | 45 | /* let the user know something went wrong */ 46 | if (r.callback != null) { 47 | Map result = new HashMap(); 48 | result.put("error", ex.getMessage()); 49 | r.callback.result((Object)result); 50 | } 51 | } 52 | } 53 | 54 | public void execute(String method, Object[] args) { 55 | execute(method, args, null); 56 | } 57 | 58 | public void execute(String method, Object[] args, RpcCallback callback) { 59 | synchronized (this) { 60 | Request temp = new Request(); 61 | temp.method = method; 62 | if (args == null) 63 | temp.args = new Object[0]; 64 | else 65 | temp.args = args; 66 | temp.callback = callback; 67 | requests.add(temp); 68 | } 69 | } 70 | 71 | protected Request grabRequest() { 72 | synchronized (this) { 73 | return (Request)requests.pollFirst(); 74 | } 75 | } 76 | 77 | /* keep grabbing requests */ 78 | public void run() { 79 | try { 80 | while (true) { 81 | Request next = grabRequest(); 82 | if (next != null) { 83 | processRequest(next); 84 | Thread.yield(); 85 | } 86 | else { 87 | Thread.sleep(50); 88 | } 89 | } 90 | } 91 | catch (Exception ex) { 92 | ex.printStackTrace(); 93 | return; 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/ssl/SecureSocket.java: -------------------------------------------------------------------------------- 1 | package ssl; 2 | 3 | import java.net.*; 4 | import java.io.*; 5 | import javax.net.ssl.*; 6 | import javax.net.*; 7 | 8 | import java.security.*; 9 | import java.security.cert.*; 10 | 11 | import sleep.bridges.io.*; 12 | 13 | /* taken from jIRCii, I developed it, so I get to do what I want ;) */ 14 | public class SecureSocket { 15 | protected SSLSocket socket; 16 | 17 | public SecureSocket(String host, int port, ArmitageTrustListener checker) throws Exception { 18 | socket = null; 19 | 20 | SSLContext sslcontext = SSLContext.getInstance("SSL"); 21 | sslcontext.init(null, new TrustManager[] { new ArmitageTrustManager(checker) }, new java.security.SecureRandom()); 22 | SSLSocketFactory factory = (SSLSocketFactory) sslcontext.getSocketFactory(); 23 | 24 | socket = (SSLSocket)factory.createSocket(host, port); 25 | 26 | socket.setSoTimeout(4048); 27 | socket.startHandshake(); 28 | } 29 | 30 | public void authenticate(String password) { 31 | try { 32 | /* we're past the handshake, so let's allow reads time to happen */ 33 | socket.setSoTimeout(0); 34 | 35 | DataInputStream datain = new DataInputStream(socket.getInputStream()); 36 | DataOutputStream dataout = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream())); 37 | 38 | /* write our magic header */ 39 | dataout.writeInt(0xBEEF); 40 | 41 | /* write our password's length */ 42 | dataout.writeByte(password.length()); 43 | 44 | /* write our password out */ 45 | for (int x = 0; x < password.length(); x++) 46 | dataout.writeByte((byte)password.charAt(x)); 47 | 48 | /* pad the password please */ 49 | for (int x = password.length(); x < 256; x++) 50 | dataout.writeByte('A'); 51 | 52 | /* flush! */ 53 | dataout.flush(); 54 | 55 | /* read in a byte to indicate status */ 56 | int result = datain.readInt(); 57 | 58 | if (result == 0xCAFE) 59 | return; 60 | else 61 | throw new RuntimeException("authentication failure!"); 62 | } 63 | catch (RuntimeException rex) { 64 | throw rex; 65 | } 66 | catch (Exception ex) { 67 | ex.printStackTrace(); 68 | throw new RuntimeException(ex); 69 | } 70 | } 71 | 72 | public IOObject client() { 73 | try { 74 | IOObject temp = new IOObject(); 75 | temp.openRead(socket.getInputStream()); 76 | temp.openWrite(new BufferedOutputStream(socket.getOutputStream(), 8192 * 8)); 77 | socket.setSoTimeout(0); 78 | return temp; 79 | } 80 | catch (Exception ex) { 81 | throw new RuntimeException(ex); 82 | } 83 | } 84 | 85 | public Socket getSocket() { 86 | return socket; 87 | } 88 | } 89 | 90 | -------------------------------------------------------------------------------- /scripts/log.sl: -------------------------------------------------------------------------------- 1 | # 2 | # Logging... yeap, this is very important y0. 3 | # 4 | 5 | import java.io.*; 6 | 7 | global('%logs'); 8 | %logs = ohash(); 9 | setMissPolicy(%logs, { 10 | return [[$cortana getSharedData] getLogger: $2]; 11 | }); 12 | 13 | # logNow("file", "host|all", "text to log"); 14 | sub logNow { 15 | if ([$preferences getProperty: "armitage.log_everything.boolean", "true"] eq "true") { 16 | local('$today $stream'); 17 | $today = formatDate("yyMMdd"); 18 | $host = strrep($2, ':', '_'); 19 | mkdir(getFileProper(dataDirectory(), $today, $DESCRIBE, $host)); 20 | $stream = %logs[ getFileProper(dataDirectory(), $today, $DESCRIBE, $host, "$1 $+ .log") ]; 21 | [$stream println: $3]; 22 | } 23 | } 24 | 25 | sub logCheck { 26 | if ([$preferences getProperty: "armitage.log_everything.boolean", "true"] eq "true") { 27 | local('$today $host'); 28 | $host = strrep($2, ':', '_'); 29 | $today = formatDate("yyMMdd"); 30 | if ($host ne "") { 31 | mkdir(getFileProper(dataDirectory(), $today, $DESCRIBE, $host)); 32 | [$1 writeToLog: %logs[ getFileProper(dataDirectory(), $today, $DESCRIBE, $host, "$3 $+ .log") ]]; 33 | } 34 | } 35 | } 36 | 37 | # logFile("filename", "all|host", "type") 38 | sub logFile { 39 | if ([$preferences getProperty: "armitage.log_everything.boolean", "true"] eq "true") { 40 | local('$today $handle $data $out $host'); 41 | $host = strrep($2, ':', '_'); 42 | $today = formatDate("yyMMdd"); 43 | if (-exists $1 && -canread $1) { 44 | mkdir(getFileProper(dataDirectory(), $today, $DESCRIBE, $host, $3)); 45 | 46 | # read in the file 47 | $handle = openf($1); 48 | $data = readb($handle, -1); 49 | closef($handle); 50 | 51 | # write it out. 52 | $out = getFileProper(dataDirectory(), $today, $DESCRIBE, $host, $3, getFileName($1)); 53 | $handle = openf("> $+ $out"); 54 | writeb($handle, $data); 55 | closef($handle); 56 | } 57 | else { 58 | print_error("Could not find file: $1"); 59 | } 60 | } 61 | } 62 | 63 | sub initLogSystem { 64 | [$frame setScreenshotManager: { 65 | local('$image $title'); 66 | ($image, $title) = @_; 67 | thread(lambda({ 68 | local('$file'); 69 | $title = tr($title, '0-9\W', '0-9_'); 70 | $file = [new java.io.File: getFileProper(formatDate("HH.mm.ss") . " $title $+ .png")]; 71 | 72 | [javax.imageio.ImageIO write: $image, "png", $file]; 73 | logFile([$file getAbsolutePath], "screenshots", "."); 74 | deleteFile([$file getAbsolutePath]); 75 | 76 | showError("Saved " . getFileName($file) . "\nGo to View -> Reporting -> Activity Logs\n\nThe file is in:\n[today's date]/ $+ $DESCRIBE $+ /screenshots"); 77 | }, \$image, \$title)); 78 | }]; 79 | } 80 | -------------------------------------------------------------------------------- /src/msf/RpcAsync.java: -------------------------------------------------------------------------------- 1 | package msf; 2 | 3 | import java.io.*; 4 | import java.util.*; 5 | 6 | public class RpcAsync implements RpcConnection, Async, Runnable { 7 | protected RpcQueue queue; 8 | protected RpcConnection connection; 9 | protected boolean connected = true; 10 | protected long last = 0; 11 | 12 | public boolean isConnected() { 13 | return connected; 14 | } 15 | 16 | /* if we've talked in the last 10s, assume that we're OK */ 17 | public boolean isResponsive() { 18 | return (System.currentTimeMillis() - last) < 10000; 19 | } 20 | 21 | public RpcAsync(RpcConnection connection) { 22 | this.connection = connection; 23 | new Thread(this).start(); 24 | } 25 | 26 | public void disconnect() { 27 | connected = false; 28 | } 29 | 30 | public void execute_async(String methodName) { 31 | execute_async(methodName, new Object[]{}, null); 32 | } 33 | 34 | public void execute_async(String methodName, Object[] args) { 35 | execute_async(methodName, args, null); 36 | } 37 | 38 | public void execute_async(String methodName, Object[] args, RpcCallback callback) { 39 | if (queue == null) { 40 | queue = new RpcQueue(connection); 41 | } 42 | queue.execute(methodName, args, callback); 43 | } 44 | 45 | public Object execute(String methodName) throws IOException { 46 | last = System.currentTimeMillis(); 47 | return connection.execute(methodName); 48 | } 49 | 50 | protected Map cache = new HashMap(); 51 | 52 | /* issue a keep-alive every 1-2 minutes, if we're idle */ 53 | public void run() { 54 | try { 55 | while (isConnected()) { 56 | Thread.sleep((60 * 1000) + (int)(Math.random() * 60 * 1000)); 57 | if (!isResponsive()) { 58 | execute_async("core.version", new Object[0]); 59 | } 60 | } 61 | } 62 | catch (InterruptedException ie) { 63 | ie.printStackTrace(); 64 | } 65 | } 66 | 67 | public Object execute(String methodName, Object[] params) throws IOException { 68 | if (methodName.equals("module.info") || methodName.equals("module.options") || methodName.equals("module.compatible_payloads")) { 69 | StringBuilder keysb = new StringBuilder(methodName); 70 | 71 | for(int i = 0; i < params.length; i++) 72 | keysb.append(params[i].toString()); 73 | 74 | String key = keysb.toString(); 75 | Object result = cache.get(key); 76 | 77 | if(result != null) { 78 | return result; 79 | } 80 | 81 | last = System.currentTimeMillis(); 82 | result = connection.execute(methodName, params); 83 | cache.put(key, result); 84 | return result; 85 | } 86 | else { 87 | last = System.currentTimeMillis(); 88 | return connection.execute(methodName, params); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/cortana/data/Credentials.java: -------------------------------------------------------------------------------- 1 | package cortana.data; 2 | 3 | import cortana.core.*; 4 | 5 | import armitage.ArmitageTimerClient; 6 | import armitage.ArmitageTimer; 7 | 8 | import graph.Route; 9 | 10 | import sleep.bridges.*; 11 | import sleep.interfaces.*; 12 | import sleep.runtime.*; 13 | import sleep.engine.*; 14 | 15 | import java.util.*; 16 | 17 | import java.io.IOException; 18 | 19 | import msf.*; 20 | 21 | public class Credentials extends ManagedData { 22 | protected RpcConnection client; 23 | protected EventManager manager; 24 | protected List creds = new LinkedList(); 25 | 26 | public Credentials(RpcConnection client, EventManager manager) { 27 | this.client = client; 28 | this.manager = manager; 29 | } 30 | 31 | public List getCredentials() { 32 | return creds; 33 | } 34 | 35 | public Scalar getScalar() { 36 | if (cache == null) 37 | cache = FilterManager.convertAll(getCredentials()); 38 | 39 | return cache; 40 | } 41 | 42 | protected void fireCredentialEvent(String event, Iterator crds) { 43 | if (isInitial()) 44 | return; 45 | 46 | while (crds.hasNext()) { 47 | Credential t = (Credential)crds.next(); 48 | manager.fireEventAsync(event, t.arguments()); 49 | } 50 | } 51 | 52 | protected Set toSet(List results) { 53 | Set temp = new HashSet(); 54 | Iterator i = results.iterator(); 55 | while (i.hasNext()) { 56 | Map data = (Map)i.next(); 57 | String host = data.get("host") + ""; 58 | String port = data.get("port") + ""; 59 | String user = data.get("user") + ""; 60 | String pass = data.get("pass") + ""; 61 | String type = data.get("ptype") + ""; 62 | 63 | temp.add(new Credential(host, port, user, pass, type)); 64 | } 65 | return temp; 66 | } 67 | 68 | public void processCreds(Map results) { 69 | if (!results.containsKey("creds")) 70 | return; 71 | 72 | /* invalidate our cache */ 73 | cache = null; 74 | 75 | /* old creds */ 76 | Set oldCredentials = toSet(creds); 77 | 78 | /* creeedz baby */ 79 | creds = (List)results.get("creds"); 80 | Set newCredentials = toSet(creds); 81 | 82 | /* fire a message for the creds that we now see */ 83 | if (!initial) { 84 | Set newStuff = DataUtils.difference(newCredentials, oldCredentials); 85 | fireCredentialEvent("credential_add", newStuff.iterator()); 86 | 87 | Set deletedStuff = DataUtils.difference(oldCredentials, newCredentials); 88 | fireCredentialEvent("credential_delete", deletedStuff.iterator()); 89 | } 90 | 91 | /* fire a generic updated message */ 92 | Stack args = new Stack(); 93 | args.push(FilterManager.convertAll(creds)); 94 | manager.fireEventAsync("credentials", args); 95 | 96 | initial = false; 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /scripts/downloads.sl: -------------------------------------------------------------------------------- 1 | # 2 | # Loot browser (not yet complete... on hold until more post/ modules have loot) 3 | # 4 | 5 | import table.*; 6 | 7 | import java.awt.*; 8 | import java.awt.event.*; 9 | 10 | import javax.swing.*; 11 | import javax.swing.event.*; 12 | import javax.swing.table.*; 13 | import ui.*; 14 | 15 | sub updateDownloadModel { 16 | fork({ 17 | local('$root $files $entry $findf $hosts $host'); 18 | 19 | if ($client !is $mclient) { 20 | $files = call($mclient, "armitage.downloads"); 21 | } 22 | else { 23 | $files = listDownloads(downloadDirectory()); 24 | } 25 | 26 | [$model clear: 256]; 27 | 28 | foreach $entry ($files) { 29 | $entry["date"] = rtime($entry["updated_at"] / 1000.0); 30 | [$model addEntry: $entry]; 31 | } 32 | [$model fireListeners]; 33 | }, \$model, \$mclient, \$client, \$preferences); 34 | } 35 | 36 | sub createDownloadBrowser { 37 | local('$table $model $panel $refresh $sorter $host $view $sync'); 38 | 39 | $model = [new GenericTableModel: @("host", "name", "path", "size", "date"), "location", 16]; 40 | 41 | $panel = [new JPanel]; 42 | [$panel setLayout: [new BorderLayout]]; 43 | 44 | $table = [new ATable: $model]; 45 | setupSizeRenderer($table, "size"); 46 | $sorter = [new TableRowSorter: $model]; 47 | [$sorter toggleSortOrder: 0]; 48 | [$sorter setComparator: 0, &compareHosts]; 49 | [$sorter setComparator: 3, { 50 | return $1 <=> $2; 51 | }]; 52 | [$sorter setComparator: 4, { 53 | return convertDate($1) <=> convertDate($2); 54 | }]; 55 | [$table setRowSorter: $sorter]; 56 | 57 | [$panel add: [new JScrollPane: $table], [BorderLayout CENTER]]; 58 | 59 | addMouseListener($table, lambda({ 60 | if ($0 eq "mousePressed" && [$1 getClickCount] >= 2) { 61 | showLoot(\$model, \$table, $getme => "location"); 62 | } 63 | }, \$model, \$table)); 64 | 65 | $view = [new JButton: "View"]; 66 | 67 | if ($client is $mclient) { 68 | $sync = [new JButton: "Open Folder"]; 69 | [$sync addActionListener: gotoFile([new java.io.File: getFileProper(dataDirectory(), "downloads")])]; 70 | } 71 | else { 72 | $sync = [new JButton: "Sync Files"]; 73 | [$sync addActionListener: lambda({ 74 | downloadLoot(\$model, \$table, $getme => "location", $type => "downloads"); 75 | }, \$model, \$table)]; 76 | } 77 | 78 | [$view addActionListener: lambda({ 79 | showLoot(\$model, \$table, $getme => "location"); 80 | }, \$model, \$table)]; 81 | 82 | $refresh = [new JButton: "Refresh"]; 83 | [$refresh addActionListener: lambda({ 84 | updateDownloadModel(\$model); 85 | }, \$model)]; 86 | 87 | updateDownloadModel(\$model); 88 | 89 | [$panel add: center($view, $sync, $refresh), [BorderLayout SOUTH]]; 90 | 91 | [$frame addTab: "Downloads", $panel, $null]; 92 | } 93 | -------------------------------------------------------------------------------- /src/cortana/metasploit/EventLogBridge.java: -------------------------------------------------------------------------------- 1 | package cortana.metasploit; 2 | 3 | import cortana.core.*; 4 | import msf.*; 5 | import armitage.*; 6 | 7 | import sleep.bridges.*; 8 | import sleep.interfaces.*; 9 | import sleep.runtime.*; 10 | import sleep.engine.*; 11 | 12 | import java.util.*; 13 | 14 | import java.io.IOException; 15 | 16 | /* add an API for interfacing with the event log... */ 17 | public class EventLogBridge implements Loadable, Function, ConsoleCallback { 18 | protected EventManager events; 19 | protected FilterManager filters; 20 | protected RpcConnection client; 21 | protected RpcConnection dserver; 22 | 23 | protected ConsoleClient console; 24 | 25 | public void sessionRead(String sessionid, String text) { 26 | String[] lines = text.trim().split("\n"); 27 | 28 | for (int x = 0; x < lines.length; x++) { 29 | Stack args = new Stack(); 30 | args.push(SleepUtils.getScalar(lines[x])); 31 | events.fireEvent("event_read", args); 32 | } 33 | } 34 | 35 | public void sessionWrote(String sessionid, String text) { 36 | Stack args = new Stack(); 37 | args.push(SleepUtils.getScalar(sessionid)); 38 | args.push(SleepUtils.getScalar(text.trim())); 39 | 40 | events.fireEvent("event_write", args); 41 | } 42 | 43 | public ConsoleClient start(console.Console window) { 44 | if (dserver != client) { 45 | console = new ConsoleClient(window, dserver, "armitage.poll", "armitage.push", null, "", false); 46 | console.addSessionListener(this); 47 | return console; 48 | } 49 | return null; 50 | } 51 | 52 | public EventLogBridge(RpcConnection client, RpcConnection dserver, EventManager events, FilterManager filters) { 53 | this.client = client; 54 | this.dserver = dserver; 55 | this.events = events; 56 | this.filters = filters; 57 | } 58 | 59 | public Scalar evaluate(String name, ScriptInstance script, Stack args) { 60 | if (dserver == client) 61 | return SleepUtils.getEmptyScalar(); 62 | 63 | String text = BridgeUtilities.getString(args, ""); 64 | 65 | try { 66 | if (name.equals("&elog")) { 67 | Object[] arg = new Object[1]; 68 | arg[0] = text; 69 | dserver.execute("armitage.log", arg); 70 | sessionWrote("log", text + "\n"); 71 | } 72 | else if (name.equals("&say")) { 73 | console.sendString(text + "\n"); 74 | } 75 | } 76 | catch (java.io.IOException ex) { 77 | throw new RuntimeException(ex); 78 | } 79 | 80 | return SleepUtils.getEmptyScalar(); 81 | } 82 | 83 | public void scriptLoaded(ScriptInstance si) { 84 | si.getScriptEnvironment().getEnvironment().put("&elog", this); 85 | si.getScriptEnvironment().getEnvironment().put("&say", this); 86 | } 87 | 88 | public void scriptUnloaded(ScriptInstance si) { 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/cortana/core/EventManager.java: -------------------------------------------------------------------------------- 1 | package cortana.core; 2 | 3 | import java.util.*; 4 | import sleep.runtime.*; 5 | import sleep.bridges.*; 6 | import sleep.interfaces.*; 7 | 8 | public class EventManager { 9 | protected Map listeners; 10 | protected EventQueue queue; 11 | 12 | protected List getListener(String name) { 13 | if (listeners.containsKey(name)) { 14 | return (List)listeners.get(name); 15 | } 16 | else { 17 | listeners.put(name, new LinkedList()); 18 | return (List)listeners.get(name); 19 | } 20 | } 21 | 22 | public Loadable getBridge() { 23 | return new Events(this); 24 | } 25 | 26 | public EventManager() { 27 | listeners = new HashMap(); 28 | queue = new EventQueue(this); 29 | } 30 | 31 | private static class Listener { 32 | protected SleepClosure listener; 33 | protected boolean temporary; 34 | 35 | public Listener(SleepClosure listener, boolean temporary) { 36 | this.listener = listener; 37 | this.temporary = temporary; 38 | } 39 | 40 | public SleepClosure getClosure() { 41 | return listener; 42 | } 43 | 44 | public boolean isTemporary() { 45 | return temporary; 46 | } 47 | } 48 | 49 | public void addListener(String listener, SleepClosure c, boolean temporary) { 50 | getListener(listener).add(new Listener(c, temporary)); 51 | } 52 | 53 | public static Stack shallowCopy(Stack args) { 54 | Stack copy = new Stack(); 55 | Iterator i = args.iterator(); 56 | while (i.hasNext()) { 57 | copy.push(i.next()); 58 | } 59 | return copy; 60 | } 61 | 62 | public void fireEvent(String eventName, Stack args) { 63 | fireEvent(eventName, args, null); 64 | } 65 | 66 | public void fireEventAsync(String eventName, Stack args) { 67 | queue.add(eventName, args); 68 | } 69 | 70 | public void fireEvent(String eventName, Stack args, ScriptInstance local) { 71 | List listeners = getListener(eventName); 72 | if (listeners.size() == 0) 73 | return; 74 | 75 | Iterator i = listeners.iterator(); 76 | 77 | List callme = new LinkedList(); 78 | Object lid = null; 79 | 80 | if (local != null) 81 | lid = local.getMetadata().get("%scriptid%"); 82 | 83 | while (i.hasNext()) { 84 | Listener l = (Listener)i.next(); 85 | if (!l.getClosure().getOwner().isLoaded()) { 86 | /* remove scripts that have quit() on us */ 87 | i.remove(); 88 | } 89 | else if (lid == null || lid.equals(l.getClosure().getOwner().getMetadata().get("%scriptid%"))) { 90 | callme.add(l.getClosure()); 91 | 92 | if (l.isTemporary()) 93 | i.remove(); 94 | } 95 | } 96 | 97 | i = callme.iterator(); 98 | while (i.hasNext()) { 99 | SleepClosure c = (SleepClosure)i.next(); 100 | SleepUtils.runCode(c, eventName, null, shallowCopy(args)); 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/cortana/data/Routes.java: -------------------------------------------------------------------------------- 1 | package cortana.data; 2 | 3 | import cortana.core.*; 4 | 5 | import armitage.ArmitageTimerClient; 6 | import armitage.ArmitageTimer; 7 | 8 | import graph.Route; 9 | 10 | import sleep.bridges.*; 11 | import sleep.interfaces.*; 12 | import sleep.runtime.*; 13 | import sleep.engine.*; 14 | 15 | import java.util.*; 16 | 17 | import java.io.IOException; 18 | 19 | import msf.*; 20 | 21 | public class Routes extends ManagedData { 22 | protected RpcConnection client; 23 | protected EventManager manager; 24 | protected List routes = new LinkedList(); 25 | 26 | public List getRoutes() { 27 | return routes; 28 | } 29 | 30 | public Scalar getScalar() { 31 | if (cache == null) 32 | cache = FilterManager.convertAll(getRoutes()); 33 | 34 | return cache; 35 | } 36 | 37 | public Routes(RpcConnection client, EventManager manager) { 38 | this.client = client; 39 | this.manager = manager; 40 | } 41 | 42 | /* a shortcut to fire route events */ 43 | protected void fireRouteEvents(String name, Iterator routes) { 44 | if (initial) 45 | return; 46 | 47 | while (routes.hasNext()) { 48 | Route temp = (Route)routes.next(); 49 | Stack arg = new Stack(); 50 | arg.push(FilterManager.convertAll(temp)); 51 | manager.fireEventAsync(name, arg); 52 | } 53 | } 54 | 55 | public void processRoutes(Map results) { 56 | /* invalidate the cache */ 57 | cache = null; 58 | 59 | /* create a set of existing routes */ 60 | Set oldRoutes = new HashSet(); 61 | oldRoutes.addAll(routes); 62 | 63 | routes.clear(); 64 | 65 | /* parse and add routes */ 66 | 67 | Iterator i = results.entrySet().iterator(); 68 | while (i.hasNext()) { 69 | Map.Entry temp = (Map.Entry)i.next(); 70 | String sid = temp.getKey() + ""; 71 | Map session = (Map)temp.getValue(); 72 | 73 | if (!"".equals(session.get("routes") + "")) { 74 | String[] routez = (session.get("routes") + "").split(","); 75 | for (int x = 0; x < routez.length; x++) { 76 | String zz[] = routez[x].split("/"); 77 | routes.add(new Route(zz[0], zz[1], sid)); 78 | } 79 | } 80 | } 81 | 82 | /* setup a set of our new routes */ 83 | Set currentRoutes = new HashSet(); 84 | currentRoutes.addAll(routes); 85 | 86 | /* now... bucket our routes and fire some events */ 87 | Set newRoutes = DataUtils.difference(currentRoutes, oldRoutes); 88 | fireRouteEvents("route_add", newRoutes.iterator()); 89 | 90 | Set goneRoutes = DataUtils.difference(oldRoutes, currentRoutes); 91 | fireRouteEvents("route_delete", goneRoutes.iterator()); 92 | 93 | /* ok, we've refreshed the routes too, let the world know eh? */ 94 | Stack arg = new Stack(); 95 | arg.push(FilterManager.convertAll(routes)); 96 | manager.fireEventAsync("routes", arg); 97 | 98 | initial = false; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/cortana/support/Shared.java: -------------------------------------------------------------------------------- 1 | package cortana.support; 2 | 3 | import java.io.*; 4 | import java.util.*; 5 | 6 | import cortana.core.*; 7 | 8 | import sleep.runtime.*; 9 | import sleep.interfaces.*; 10 | import sleep.bridges.*; 11 | 12 | /* an abstraction for tracking data shared between Cortana and Armitage */ 13 | public class Shared implements Function, Loadable { 14 | public void scriptLoaded(ScriptInstance script) { 15 | /* this is a very weird thing to call a function in Armitage from Cortana. 16 | the armitage function must register itself though */ 17 | script.getScriptEnvironment().getEnvironment().put("&_call_", this); 18 | script.getScriptEnvironment().getEnvironment().put("&_call_async_", this); 19 | script.getScriptEnvironment().getEnvironment().put("&_call_later_", this); 20 | } 21 | 22 | public void scriptUnloaded(ScriptInstance script) { 23 | } 24 | 25 | public Scalar evaluate(String name, ScriptInstance script, Stack args) { 26 | final String function = BridgeUtilities.getString(args, ""); 27 | if (values.containsKey(function)) { 28 | if (name.equals("&_call_")) { 29 | SleepClosure f = (SleepClosure)values.get(function); 30 | return SleepUtils.runCode(f, function, f.getOwner(), EventManager.shallowCopy(args)); 31 | } 32 | else if (name.equals("&_call_async_")) { 33 | final SleepClosure f = (SleepClosure)values.get(function); 34 | final Stack argz = EventManager.shallowCopy(args); 35 | new Thread(new Runnable() { 36 | public void run() { 37 | SleepUtils.runCode(f, function, f.getOwner(), argz); 38 | } 39 | }).start(); 40 | return SleepUtils.getEmptyScalar(); 41 | } 42 | else if (name.equals("&_call_later_")) { 43 | final SleepClosure f = (SleepClosure)values.get(function); 44 | final Stack argz = EventManager.shallowCopy(args); 45 | javax.swing.SwingUtilities.invokeLater(new Runnable() { 46 | public void run() { 47 | SleepUtils.runCode(f, function, f.getOwner(), argz); 48 | } 49 | }); 50 | return SleepUtils.getEmptyScalar(); 51 | } 52 | } 53 | 54 | throw new RuntimeException("'" + function + "' does not exist"); 55 | } 56 | 57 | /* 58 | * Some generic stuff to share 59 | */ 60 | protected Map values = new HashMap(); 61 | 62 | public void put(String key, Object value) { 63 | synchronized (this) { 64 | values.put(key, value); 65 | } 66 | } 67 | 68 | public Object get(String key) { 69 | synchronized (this) { 70 | return values.get(key); 71 | } 72 | } 73 | 74 | /* 75 | * Shared PrintStreams for logging purposes. 76 | */ 77 | protected Map logs = new HashMap(); 78 | 79 | public PrintStream getLogger(String key) { 80 | if (!logs.containsKey(key)) { 81 | try { 82 | logs.put(key, new PrintStream(new FileOutputStream(key, true), true, "UTF-8")); 83 | } 84 | catch (IOException ex) { 85 | throw new RuntimeException(ex); 86 | } 87 | } 88 | return (PrintStream)logs.get(key); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /scripts/tokens.sl: -------------------------------------------------------------------------------- 1 | # 2 | # Token Stealing... 3 | # 4 | 5 | import java.awt.*; 6 | import java.awt.event.*; 7 | 8 | import javax.swing.*; 9 | 10 | sub updateTokenList { 11 | # update the dialog to indicate that things are changing... 12 | [$3 setEnabled: 0]; 13 | [$3 setText: "Grabbing tokens..."]; 14 | 15 | # setup incognito and list the tokens... 16 | m_cmd_callback($1, "use incognito", {}); 17 | m_cmd_callback($1, "sysinfo", {}); 18 | m_cmd_callback($1, "sysinfo", {}); 19 | m_cmd_callback($1, "sysinfo", {}); 20 | m_cmd_callback($1, "list_tokens -u", lambda({ 21 | if ($0 eq "end") { 22 | local('$entry $row $type'); 23 | [$model clear: 32]; 24 | foreach $entry (split("\n", $2)) { 25 | $entry = ["$entry" trim]; 26 | if ($entry eq "Delegation Tokens Available") { 27 | $type = "delegation"; 28 | } 29 | else if ($entry eq "Impersonation Tokens Available") { 30 | $type = "impersonation"; 31 | } 32 | else if ($entry ismatch '=*' || $entry eq "No tokens available" || " " isin $entry) { 33 | # do nothing... 34 | } 35 | else if ($entry ne "") { 36 | $row = %(); 37 | $row['Token Type'] = $type; 38 | $row['Name'] = $entry; 39 | [$model addEntry: $row]; 40 | } 41 | } 42 | [$model fireListeners]; 43 | 44 | dispatchEvent(lambda({ 45 | [$refresh setEnabled: 1]; 46 | [$refresh setText: "Refresh"]; 47 | }, \$refresh)); 48 | } 49 | }, $model => $2, $refresh => $3)); 50 | } 51 | 52 | sub stealToken { 53 | local('$dialog $table $model $steal $revert $whoami $refresh'); 54 | $dialog = [new JPanel]; 55 | [$dialog setLayout: [new BorderLayout]]; 56 | 57 | ($table, $model) = setupTable("Name", @("Token Type", "Name"), @()); 58 | [$table setSelectionMode: [ListSelectionModel SINGLE_SELECTION]]; 59 | [$dialog add: [new JScrollPane: $table], [BorderLayout CENTER]]; 60 | 61 | $steal = [new JButton: "Steal Token"]; 62 | [$steal addActionListener: lambda({ 63 | local('$value'); 64 | $value = [$model getSelectedValue: $table]; 65 | oneTimeShow("impersonate_token"); 66 | m_cmd($sid, "impersonate_token ' $+ $value $+ '"); 67 | }, $sid => $1, \$table, \$model)]; 68 | 69 | $revert = [new JButton: "Revert to Self"]; 70 | [$revert addActionListener: lambda({ 71 | oneTimeShow("getuid"); 72 | m_cmd($sid, "rev2self"); 73 | m_cmd($sid, "getuid"); 74 | }, $sid => $1)]; 75 | 76 | $whoami = [new JButton: "Get UID"]; 77 | [$whoami addActionListener: lambda({ 78 | oneTimeShow("getuid"); 79 | m_cmd($sid, "getuid"); 80 | }, $sid => $1)]; 81 | 82 | $refresh = [new JButton: "Refresh"]; 83 | [$refresh addActionListener: lambda({ 84 | updateTokenList($sid, $model, $refresh); 85 | }, $sid => $1, \$model, \$refresh)]; 86 | 87 | updateTokenList($1, $model, $refresh); 88 | 89 | [$dialog add: center($steal, $revert, $whoami, $refresh), [BorderLayout SOUTH]]; 90 | [$frame addTab: "Tokens $1", $dialog, $null, "Tokens " . sessionToHost($1)]; 91 | } 92 | -------------------------------------------------------------------------------- /dist/unix/teamserver: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # start msfrpcd and the deconfliction server. Check for common mistakes 3 | # to save some time and head scratching... 4 | 5 | # make pretty looking messages (thanks Carlos) 6 | function print_good () { 7 | echo -e "\x1B[01;32m[+]\x1B[0m $1" 8 | } 9 | 10 | function print_error () { 11 | echo -e "\x1B[01;31m[-]\x1B[0m $1" 12 | } 13 | 14 | function print_info () { 15 | echo -e "\x1B[01;34m[*]\x1B[0m $1" 16 | } 17 | 18 | # check the arguments 19 | EXPECTED=2 20 | if [ $# -ne $EXPECTED ]; then 21 | print_info "You must provide: " 22 | echo " must be reachable by Armitage" 23 | echo " clients on port 55553" 24 | echo " is a shared password your team uses to" 25 | echo " authenticate to the Armitage team server" 26 | exit 27 | fi 28 | 29 | # check that we're r00t 30 | if [ $UID -ne 0 ]; then 31 | print_error "Superuser privileges are required to run the team server" 32 | exit 33 | fi 34 | 35 | # check if java is available... 36 | if [ $(command -v java) ]; then 37 | true 38 | else 39 | print_error "java is not in \$PATH" 40 | echo " is Java installed?" 41 | exit 42 | fi 43 | 44 | # check if keytool is available... 45 | if [ $(command -v keytool) ]; then 46 | true 47 | else 48 | print_error "keytool is not in \$PATH" 49 | echo " install the Java Developer Kit" 50 | exit 51 | fi 52 | 53 | # check if msfrpcd is available 54 | if [ $(command -v msfrpcd) ]; then 55 | true 56 | else 57 | print_error "msfrpcd is not in \$PATH" 58 | echo " is Metasploit installed?" 59 | exit 60 | fi 61 | 62 | # check if msfrpcd is running or not 63 | if [ "$(pidof msfrpcd)" ]; then 64 | print_error "msfrpcd is already running. Kill it before running this script" 65 | echo " try: killall -9 msfrpcd" 66 | exit 67 | fi 68 | 69 | # generate a certificate 70 | # naturally you're welcome to replace this step with your own permanent certificate. 71 | # just make sure you pass -Djavax.net.ssl.keyStore="/path/to/whatever" and 72 | # -Djavax.net.ssl.keyStorePassword="password" to java. This is used for setting up 73 | # an SSL server socket. Also, the SHA-1 digest of the first certificate in the store 74 | # is printed so users may have a chance to verify they're not being owned. 75 | print_info "Generating X509 certificate and keystore (for SSL)" 76 | rm -f ./armitage.store 77 | keytool -keystore ./armitage.store -storepass 123456 -keypass 123456 -genkey -keyalg RSA -alias armitage -dname "CN=Armitage Hacker, OU=FastAndEasyHacking, O=Armitage, L=Somewhere, S=Cyberspace, C=Earth" 78 | 79 | # start everything up 80 | print_info "Starting RPC daemon" 81 | msfrpcd -U msf -P $2 -a 127.0.0.1 -p 55554 -S 82 | print_info "sleeping for 20s (to let msfrpcd initialize)" 83 | sleep 20 84 | print_info "Starting Armitage team server" 85 | java -Djavax.net.ssl.keyStore=./armitage.store -Djavax.net.ssl.keyStorePassword=123456 -server -XX:+UseParallelGC -jar armitage.jar --server $1 55554 msf $2 55553 86 | -------------------------------------------------------------------------------- /release/armitage-unix/teamserver: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # start msfrpcd and the deconfliction server. Check for common mistakes 3 | # to save some time and head scratching... 4 | 5 | # make pretty looking messages (thanks Carlos) 6 | function print_good () { 7 | echo -e "\x1B[01;32m[+]\x1B[0m $1" 8 | } 9 | 10 | function print_error () { 11 | echo -e "\x1B[01;31m[-]\x1B[0m $1" 12 | } 13 | 14 | function print_info () { 15 | echo -e "\x1B[01;34m[*]\x1B[0m $1" 16 | } 17 | 18 | # check the arguments 19 | EXPECTED=2 20 | if [ $# -ne $EXPECTED ]; then 21 | print_info "You must provide: " 22 | echo " must be reachable by Armitage" 23 | echo " clients on port 55553" 24 | echo " is a shared password your team uses to" 25 | echo " authenticate to the Armitage team server" 26 | exit 27 | fi 28 | 29 | # check that we're r00t 30 | if [ $UID -ne 0 ]; then 31 | print_error "Superuser privileges are required to run the team server" 32 | exit 33 | fi 34 | 35 | # check if java is available... 36 | if [ $(command -v java) ]; then 37 | true 38 | else 39 | print_error "java is not in \$PATH" 40 | echo " is Java installed?" 41 | exit 42 | fi 43 | 44 | # check if keytool is available... 45 | if [ $(command -v keytool) ]; then 46 | true 47 | else 48 | print_error "keytool is not in \$PATH" 49 | echo " install the Java Developer Kit" 50 | exit 51 | fi 52 | 53 | # check if msfrpcd is available 54 | if [ $(command -v msfrpcd) ]; then 55 | true 56 | else 57 | print_error "msfrpcd is not in \$PATH" 58 | echo " is Metasploit installed?" 59 | exit 60 | fi 61 | 62 | # check if msfrpcd is running or not 63 | if [ "$(pidof msfrpcd)" ]; then 64 | print_error "msfrpcd is already running. Kill it before running this script" 65 | echo " try: killall -9 msfrpcd" 66 | exit 67 | fi 68 | 69 | # generate a certificate 70 | # naturally you're welcome to replace this step with your own permanent certificate. 71 | # just make sure you pass -Djavax.net.ssl.keyStore="/path/to/whatever" and 72 | # -Djavax.net.ssl.keyStorePassword="password" to java. This is used for setting up 73 | # an SSL server socket. Also, the SHA-1 digest of the first certificate in the store 74 | # is printed so users may have a chance to verify they're not being owned. 75 | print_info "Generating X509 certificate and keystore (for SSL)" 76 | rm -f ./armitage.store 77 | keytool -keystore ./armitage.store -storepass 123456 -keypass 123456 -genkey -keyalg RSA -alias armitage -dname "CN=Armitage Hacker, OU=FastAndEasyHacking, O=Armitage, L=Somewhere, S=Cyberspace, C=Earth" 78 | 79 | # start everything up 80 | print_info "Starting RPC daemon" 81 | msfrpcd -U msf -P $2 -a 127.0.0.1 -p 55554 -S 82 | print_info "sleeping for 20s (to let msfrpcd initialize)" 83 | sleep 20 84 | print_info "Starting Armitage team server" 85 | java -Djavax.net.ssl.keyStore=./armitage.store -Djavax.net.ssl.keyStorePassword=123456 -server -XX:+UseParallelGC -jar armitage.jar --server $1 55554 msf $2 55553 86 | -------------------------------------------------------------------------------- /src/cortana/data/Hosts.java: -------------------------------------------------------------------------------- 1 | package cortana.data; 2 | 3 | import cortana.core.*; 4 | 5 | import armitage.ArmitageTimerClient; 6 | import armitage.ArmitageTimer; 7 | 8 | import graph.Route; 9 | 10 | import sleep.bridges.*; 11 | import sleep.interfaces.*; 12 | import sleep.runtime.*; 13 | import sleep.engine.*; 14 | 15 | import java.util.*; 16 | 17 | import java.io.IOException; 18 | 19 | import msf.*; 20 | 21 | public class Hosts extends ManagedData { 22 | protected RpcConnection client; 23 | protected EventManager manager; 24 | protected Map hosts = new HashMap(); 25 | 26 | public Map getHostsData() { 27 | Map r = new HashMap(); 28 | 29 | Iterator i = hosts.entrySet().iterator(); 30 | while (i.hasNext()) { 31 | Map.Entry temp = (Map.Entry)i.next(); 32 | r.put(temp.getKey(), ((Host)temp.getValue()).getData()); 33 | } 34 | 35 | return r; 36 | } 37 | 38 | public Scalar getScalar() { 39 | if (cache == null) 40 | cache = FilterManager.convertAll(getHostsData()); 41 | 42 | return cache; 43 | } 44 | 45 | public Map getHosts() { 46 | return hosts; 47 | } 48 | 49 | public Hosts(RpcConnection client, EventManager manager) { 50 | this.client = client; 51 | this.manager = manager; 52 | } 53 | 54 | protected void fireHostEvent(String event, Iterator changes) { 55 | while (changes.hasNext()) { 56 | String addr = (String)changes.next(); 57 | Stack argz = new Stack(); 58 | argz.push(SleepUtils.getScalar(addr)); 59 | manager.fireEventAsync(event, argz); 60 | } 61 | } 62 | 63 | public void processHosts(Map results) { 64 | if (!results.containsKey("hosts")) 65 | return; 66 | 67 | /* invalidate the cache */ 68 | cache = null; 69 | 70 | Set currentHosts = new HashSet(); 71 | currentHosts.addAll(hosts.keySet()); 72 | 73 | Map newHosts = new HashMap(); 74 | 75 | List hostl = (List)results.get("hosts"); 76 | Iterator i = hostl.iterator(); 77 | 78 | while (i.hasNext()) { 79 | Map data = (Map)i.next(); 80 | String address = data.get("address") + ""; 81 | 82 | Host temp; 83 | if (hosts.containsKey(address)) { 84 | temp = (Host)hosts.get(address); 85 | temp.update(data); 86 | } 87 | else { 88 | temp = new Host(address, data); 89 | } 90 | 91 | newHosts.put(address, temp); 92 | } 93 | 94 | /* set the hosts info to the old host info */ 95 | hosts = newHosts; 96 | 97 | /* fire eventz for host changes */ 98 | if (!initial) { 99 | Set oldHosts = DataUtils.difference(currentHosts, newHosts.keySet()); 100 | fireHostEvent("host_delete", oldHosts.iterator()); 101 | 102 | Set newStuff = DataUtils.difference(newHosts.keySet(), currentHosts); 103 | fireHostEvent("host_add", newStuff.iterator()); 104 | } 105 | 106 | /* fire an event for all hosts */ 107 | Stack arg = new Stack(); 108 | arg.push(FilterManager.convertAll(hostl)); 109 | manager.fireEventAsync("hosts", arg); 110 | 111 | initial = false; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/graph/Route.java: -------------------------------------------------------------------------------- 1 | package graph; 2 | 3 | import java.util.*; 4 | 5 | public class Route { 6 | /** convert a long to an ip address */ 7 | public static long ipToLong(String address) { 8 | if (address == null) 9 | return 0L; 10 | 11 | String[] quads = address.split("\\."); 12 | long result = 0; 13 | 14 | /* this is a fallback in case one of the IP addresses is malformed */ 15 | if (quads.length != 4) 16 | return 0L; 17 | 18 | try { 19 | result += Integer.parseInt(quads[3]); 20 | result += Long.parseLong(quads[2]) << 8L; 21 | result += Long.parseLong(quads[1]) << 16L; 22 | result += Long.parseLong(quads[0]) << 24L; 23 | } 24 | catch (Exception ex) { 25 | return result; 26 | } 27 | return result; 28 | } 29 | 30 | private static final long RANGE_MAX = ipToLong("255.255.255.255"); 31 | 32 | protected long begin; 33 | protected long end; 34 | protected String gateway; 35 | protected String network; 36 | protected String mask; 37 | 38 | public Route(String address) { 39 | String[] description = address.split("/"); 40 | String host = "", network = ""; 41 | 42 | if (description.length == 1) { 43 | host = address; 44 | 45 | String[] quads = address.split("\\."); 46 | if (quads[0].equals("0")) { 47 | network = "1"; 48 | } 49 | else if (quads[1].equals("0")) { 50 | network = "8"; 51 | } 52 | else if (quads[2].equals("0")) { 53 | network = "16"; 54 | } 55 | else if (quads[3].equals("0")) { 56 | network = "24"; 57 | } 58 | else { 59 | network = "32"; 60 | } 61 | } 62 | else { 63 | host = description[0]; 64 | network = description[1]; 65 | } 66 | 67 | this.network = host; 68 | this.mask = network; 69 | this.gateway = "undefined"; 70 | 71 | begin = ipToLong(host); 72 | try { 73 | end = begin + (RANGE_MAX >> Integer.parseInt(network)); 74 | } 75 | catch (Exception ex) { 76 | System.err.println(network + " is malformed!"); 77 | } 78 | } 79 | 80 | /** create an object to represent a network and where it's routing through */ 81 | public Route(String address, String networkMask, String gateway) { 82 | begin = ipToLong(address); 83 | end = begin + (RANGE_MAX - ipToLong(networkMask)); 84 | 85 | this.gateway = gateway; 86 | 87 | this.network = address; 88 | this.mask = networkMask; 89 | } 90 | 91 | public boolean equals(Object o) { 92 | if (o instanceof Route) { 93 | Route p = (Route)o; 94 | return p.begin == begin && p.end == end && p.gateway.equals(gateway); 95 | } 96 | return false; 97 | } 98 | 99 | public int hashCode() { 100 | return (int)(begin + end + gateway.hashCode()); 101 | } 102 | 103 | /** return the gateway */ 104 | public String getGateway() { 105 | return gateway; 106 | } 107 | 108 | /** check if this route applies to the specified network address */ 109 | public boolean shouldRoute(String address) { 110 | long check = ipToLong(address); 111 | return check >= begin && check <= end; 112 | } 113 | 114 | public String toString() { 115 | return network + "/" + mask + " via " + gateway; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/armitage/GenericTabCompletion.java: -------------------------------------------------------------------------------- 1 | package armitage; 2 | 3 | import console.Console; 4 | import msf.*; 5 | import java.util.*; 6 | import java.awt.*; 7 | import java.awt.event.*; 8 | import javax.swing.*; 9 | 10 | /* A generic class to manage reading/writing to a console. Keeps the code simpler (although the Sleep code to do this is 11 | simpler than this Java code. *sigh* */ 12 | public abstract class GenericTabCompletion { 13 | protected Console window; 14 | 15 | /* state for the actual tab completion */ 16 | protected String last = null; 17 | protected Iterator tabs = null; 18 | 19 | public Console getWindow() { 20 | return window; 21 | } 22 | 23 | public GenericTabCompletion(Console windowz) { 24 | this.window = windowz; 25 | 26 | window.addActionForKey("pressed TAB", new AbstractAction() { 27 | public void actionPerformed(final ActionEvent ev) { 28 | tabComplete(ev); 29 | } 30 | }); 31 | } 32 | 33 | public abstract Collection getOptions(String text); 34 | 35 | /* give tab completion routine a chance to change the text */ 36 | public String transformText(String text) { 37 | return text; 38 | } 39 | 40 | private void tabCompleteFirst(String text) { 41 | try { 42 | text = transformText(text); 43 | 44 | LinkedHashSet responses = new LinkedHashSet(); 45 | Collection options = getOptions(text); 46 | 47 | if (options == null) 48 | return; 49 | 50 | /* cycle through all of our options, we want to split items up to the 51 | first slash. We also want them to be unique and ordered (hence the 52 | linked hash set */ 53 | Iterator i = options.iterator(); 54 | while (i.hasNext()) { 55 | String option = i.next() + ""; 56 | 57 | String begin; 58 | String end; 59 | 60 | if (text.length() > option.length()) { 61 | begin = option; 62 | end = ""; 63 | } 64 | else { 65 | begin = option.substring(0, text.length()); 66 | end = option.substring(text.length()); 67 | } 68 | 69 | int nextSlash; 70 | if ((nextSlash = end.indexOf('/')) > -1 && (nextSlash + 1) < end.length()) { 71 | end = end.substring(0, nextSlash); 72 | } 73 | 74 | responses.add(begin + end); 75 | } 76 | 77 | responses.add(text); 78 | 79 | synchronized (window) { 80 | tabs = responses.iterator(); 81 | last = (String)tabs.next(); 82 | } 83 | 84 | SwingUtilities.invokeLater(new Runnable() { 85 | public void run() { 86 | window.getInput().setText(last); 87 | } 88 | }); 89 | } 90 | catch (Exception ex) { 91 | ex.printStackTrace(); 92 | } 93 | } 94 | 95 | public void tabComplete(ActionEvent ev) { 96 | final String text = window.getInput().getText(); 97 | if (text.length() == 0) 98 | return; 99 | 100 | synchronized (window) { 101 | if (tabs != null && tabs.hasNext() && text.equals(last)) { 102 | last = (String)tabs.next(); 103 | window.getInput().setText(last); 104 | return; 105 | } 106 | else { 107 | new Thread(new Runnable() { 108 | public void run() { 109 | tabCompleteFirst(text); 110 | } 111 | }).start(); 112 | } 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /src/cortana/data/Services.java: -------------------------------------------------------------------------------- 1 | package cortana.data; 2 | 3 | import cortana.core.*; 4 | 5 | import armitage.ArmitageTimerClient; 6 | import armitage.ArmitageTimer; 7 | 8 | import graph.Route; 9 | 10 | import sleep.bridges.*; 11 | import sleep.interfaces.*; 12 | import sleep.runtime.*; 13 | import sleep.engine.*; 14 | 15 | import java.util.*; 16 | 17 | import java.io.IOException; 18 | 19 | import msf.*; 20 | 21 | public class Services extends ManagedData { 22 | protected RpcConnection client; 23 | protected EventManager manager; 24 | protected Hosts hosts; 25 | protected List services = new LinkedList(); 26 | 27 | public Services(Hosts hosts, RpcConnection client, EventManager manager) { 28 | this.client = client; 29 | this.manager = manager; 30 | this.hosts = hosts; 31 | } 32 | 33 | public List getServices() { 34 | return services; 35 | } 36 | 37 | public Scalar getScalar() { 38 | if (cache == null) 39 | cache = FilterManager.convertAll(getServices()); 40 | 41 | return cache; 42 | } 43 | 44 | protected void fireServiceEvent(String event, Iterator services) { 45 | while (services.hasNext()) { 46 | Service t = (Service)services.next(); 47 | if (event.equals("service_add")) { 48 | manager.fireEventAsync("service_add_" + t.getPort(), t.arguments()); 49 | manager.fireEventAsync("service_add", t.arguments()); 50 | } 51 | else { 52 | manager.fireEventAsync(event, t.arguments()); 53 | } 54 | } 55 | } 56 | 57 | public void processServices(Map results) { 58 | if (hosts.isInitial()) 59 | return; 60 | 61 | if (!results.containsKey("services")) 62 | return; 63 | 64 | /* invalidate the cache */ 65 | cache = null; 66 | hosts.cache = null; 67 | 68 | Set oldServices = new HashSet(); 69 | Set newServices = new HashSet(); 70 | 71 | /* clear all of the services */ 72 | Iterator j = hosts.getHosts().values().iterator(); 73 | while (j.hasNext()) { 74 | Host host = (Host)j.next(); 75 | oldServices.addAll(host.serviceSet()); 76 | host.getServices().clear(); 77 | } 78 | 79 | /* install all the services into our hosts data */ 80 | services = (List)results.get("services"); 81 | Iterator i = services.iterator(); 82 | while (i.hasNext()) { 83 | Map data = (Map)i.next(); 84 | String host = data.get("host") + ""; 85 | String port = data.get("port") + ""; 86 | 87 | Host temp = (Host)hosts.getHosts().get(host); 88 | if (temp != null) { 89 | Map srvc = temp.getServices(); 90 | srvc.put(port, data); 91 | newServices.add(new Service(host, port)); 92 | } 93 | } 94 | 95 | /* fire a message for various services that we now see */ 96 | if (!initial) { 97 | Set newStuff = DataUtils.difference(newServices, oldServices); 98 | fireServiceEvent("service_add", newStuff.iterator()); 99 | 100 | Set deletedStuff = DataUtils.difference(oldServices, newServices); 101 | fireServiceEvent("service_delete", deletedStuff.iterator()); 102 | } 103 | 104 | /* fire a generic services updated message */ 105 | Stack args = new Stack(); 106 | args.push(FilterManager.convertAll(services)); 107 | manager.fireEventAsync("services", args); 108 | 109 | initial = false; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/armitage/MeterpreterClient.java: -------------------------------------------------------------------------------- 1 | package armitage; 2 | 3 | import console.Console; 4 | import msf.*; 5 | import java.util.*; 6 | import java.awt.*; 7 | import java.awt.event.*; 8 | import javax.swing.*; 9 | 10 | /* This is a rewritten client class to keep compatible with ConsoleClient but interface with the new 11 | MeterpreterSession class. This new class makes sure each command is executed and receives its output 12 | before the next one is executed. This prevents the Armitage UI from becoming confused */ 13 | 14 | public class MeterpreterClient implements ActionListener, MeterpreterSession.MeterpreterCallback { 15 | protected Console window; 16 | protected MeterpreterSession session; 17 | protected ActionListener shellCommand; 18 | 19 | public Console getWindow() { 20 | return window; 21 | } 22 | 23 | public void commandComplete(String sid, Object token, Map response) { 24 | if (token == this || token == null) 25 | processRead(response); 26 | } 27 | 28 | public void commandTimeout(String sid, Object token, Map response) { 29 | window.append("[*] Timed out waiting for command to complete.\n"); 30 | } 31 | 32 | private void processRead(Map read) { 33 | try { 34 | if (! "".equals( read.get("data") )) { 35 | String text = read.get("data") + ""; 36 | window.append(text); 37 | } 38 | 39 | if (! "".equals( read.get("prompt") )) { 40 | window.updatePrompt(ConsoleClient.cleanText(read.get("prompt") + "")); 41 | } 42 | } 43 | catch (Exception ex) { 44 | throw new RuntimeException(ex); 45 | } 46 | } 47 | 48 | public MeterpreterClient(Console window, MeterpreterSession session, ActionListener shellCommand) { 49 | this.window = window; 50 | this.session = session; 51 | this.shellCommand = shellCommand; 52 | this.session.addListener(this); 53 | 54 | setupListener(); 55 | 56 | window.updatePrompt("meterpreter > "); 57 | } 58 | 59 | /* called when the associated tab is closed */ 60 | public void actionPerformed(ActionEvent ev) { 61 | /* nothing we need to do for now */ 62 | } 63 | 64 | protected void finalize() { 65 | actionPerformed(null); 66 | } 67 | 68 | public void sendString(String text) { 69 | window.append(window.getPromptText() + text); 70 | session.addCommand(this, text); 71 | } 72 | 73 | protected void setupListener() { 74 | window.getInput().addActionListener(new ActionListener() { 75 | public void actionPerformed(ActionEvent ev) { 76 | String text = window.getInput().getText() + "\n"; 77 | window.getInput().setText(""); 78 | 79 | /* too many users typing "shell whatever" inside of a meterpreter window... need to prevent problems */ 80 | if (shellCommand != null && text.trim().startsWith("shell")) { 81 | shellCommand.actionPerformed(new ActionEvent(window, 0, "shell")); 82 | } 83 | else if (shellCommand != null && text.trim().equals("screenshot")) { 84 | shellCommand.actionPerformed(new ActionEvent(window, 0, "screenshot")); 85 | } 86 | else if (shellCommand != null && text.trim().equals("webcam_snap")) { 87 | shellCommand.actionPerformed(new ActionEvent(window, 0, "webcam_snap")); 88 | } 89 | else if (shellCommand != null && text.trim().equals("upload")) { 90 | shellCommand.actionPerformed(new ActionEvent(window, 0, "upload")); 91 | } 92 | else { 93 | sendString(text); 94 | } 95 | } 96 | }); 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/msf/ConsolePool.java: -------------------------------------------------------------------------------- 1 | package msf; 2 | 3 | import java.util.*; 4 | import java.io.IOException; 5 | 6 | /* Pool Metasploit console ids and make them available for reuse. Why? Two reasons. One, 7 | Metasploit 4.3-release has a nice race condition where every console.create call is 8 | a game of Russian roulette with an opportunity to bring the entire Metasploit daemon 9 | down. Two, each console.create call takes around 300ms. Armitage uses temporary consoles 10 | for a lot of things, this will help make these uses slightly snappier. */ 11 | public class ConsolePool implements RpcConnection { 12 | protected RpcConnection client; 13 | protected Set inactive = new HashSet(); 14 | protected Set tracked = new HashSet(); 15 | 16 | public Object execute(String methodName) throws IOException { 17 | return execute(methodName, new Object[0]); 18 | } 19 | 20 | public Object execute(String methodName, Object[] params) throws IOException { 21 | if (methodName.equals("console.allocate")) { 22 | return allocate(); 23 | } 24 | else if (methodName.equals("console.release")) { 25 | release((String)params[0]); 26 | } 27 | else if (methodName.equals("console.release_and_destroy")) { 28 | synchronized (this) { 29 | tracked.remove((String)params[0]); 30 | } 31 | release((String)params[0]); 32 | } 33 | return new HashMap(); 34 | } 35 | 36 | public ConsolePool(RpcConnection client) { 37 | this.client = client; 38 | } 39 | 40 | public Map allocate() throws IOException { 41 | synchronized (this) { 42 | while (inactive.size() > 0) { 43 | Iterator i = inactive.iterator(); 44 | Map rv = (Map)i.next(); 45 | i.remove(); 46 | 47 | /* clear any data from the console before we return it */ 48 | Map temp = (Map)client.execute("console.read", new Object[] { rv.get("id") + "" }); 49 | 50 | /* this is a sanity check to make sure this console is not dead or hung */ 51 | if ("failure".equals(temp.get("result")) || "true".equals(temp.get("busy") + "") || "".equals(temp.get("prompt") + "")) { 52 | armitage.ArmitageMain.print_info("kill Console: " + rv + " => " + temp); 53 | client.execute("console.destroy", new Object[] { rv.get("id") + "" }); 54 | } 55 | else { 56 | return rv; 57 | } 58 | } 59 | } 60 | 61 | Map result = (Map)client.execute("console.create"); 62 | 63 | /* keep track of consoles that are in the pool, so we know whether to 64 | destroy or release them when asked to. We only release pooled consoles 65 | because we know they're used a certain way (e.g., for temporary purposes, 66 | not long running tasks that a user may have setup) */ 67 | synchronized (this) { 68 | tracked.add(result.get("id") + ""); 69 | } 70 | 71 | /* swallow the banner... making sure this is done will be part of the 72 | contract of the console pool */ 73 | client.execute("console.read", new Object[] { result.get("id") }); 74 | return result; 75 | } 76 | 77 | public void release(String id) throws IOException { 78 | /* make sure we're in a "clean" console */ 79 | HashMap rv = new HashMap(); 80 | rv.put("id", id); 81 | 82 | boolean b; 83 | synchronized (this) { 84 | b = tracked.contains(id); 85 | } 86 | 87 | if (b) { 88 | client.execute("console.write", new Object[] { id, "back\n" }); 89 | synchronized (this) { 90 | inactive.add(rv); 91 | } 92 | } 93 | else { 94 | client.execute("console.destroy", new Object[] { id }); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/armitage/ArmitageBuffer.java: -------------------------------------------------------------------------------- 1 | package armitage; 2 | 3 | import java.util.*; 4 | 5 | /* 6 | * Implement a thread safe store that any client may write to and 7 | * any client may read from (keeping track of their cursor into 8 | * the console) 9 | */ 10 | public class ArmitageBuffer { 11 | private static final class Message { 12 | public String message = null; 13 | public Message next = null; 14 | } 15 | 16 | /* store our messages... */ 17 | public Message first = null; 18 | public Message last = null; 19 | public long size = 0; 20 | public long max = 0; 21 | public String prompt = ""; 22 | 23 | /* store indices into this buffer */ 24 | public Map indices = new HashMap(); 25 | 26 | /* setup the buffer?!? :) */ 27 | public ArmitageBuffer(long max) { 28 | this.max = max; 29 | } 30 | 31 | /* store a prompt with this buffer... we're not going to do any indexing magic for now */ 32 | public String getPrompt() { 33 | synchronized (this) { 34 | return prompt; 35 | } 36 | } 37 | 38 | /* set the prompt */ 39 | public void setPrompt(String text) { 40 | synchronized (this) { 41 | prompt = text; 42 | } 43 | } 44 | 45 | /* post a message to this buffer */ 46 | public void put(String text) { 47 | synchronized (this) { 48 | /* create our message */ 49 | Message m = new Message(); 50 | m.message = text; 51 | 52 | /* store our message */ 53 | if (last == null && first == null) { 54 | first = m; 55 | last = m; 56 | } 57 | else { 58 | last.next = m; 59 | last = m; 60 | } 61 | 62 | /* increment number of stored messages */ 63 | size += 1; 64 | 65 | /* limit the total number of past messages to the max size */ 66 | if (size > max) { 67 | first = first.next; 68 | } 69 | } 70 | } 71 | 72 | /* retrieve a set of all clients consuming this buffer */ 73 | public Collection clients() { 74 | synchronized (this) { 75 | LinkedList clients = new LinkedList(indices.keySet()); 76 | return clients; 77 | } 78 | } 79 | 80 | /* free a client */ 81 | public void free(String id) { 82 | synchronized (this) { 83 | indices.remove(id); 84 | } 85 | } 86 | 87 | /* reset our indices too */ 88 | public void reset() { 89 | synchronized (this) { 90 | first = null; 91 | last = null; 92 | indices.clear(); 93 | size = 0; 94 | } 95 | } 96 | 97 | /* retrieve all messages available to the client (if any) */ 98 | public String get(String id) { 99 | synchronized (this) { 100 | /* nadaz */ 101 | if (first == null) 102 | return ""; 103 | 104 | /* get our index into the buffer */ 105 | Message index = null; 106 | if (!indices.containsKey(id)) { 107 | index = first; 108 | } 109 | else { 110 | index = (Message)indices.get(id); 111 | 112 | /* nothing happening */ 113 | if (index.next == null) 114 | return ""; 115 | 116 | index = index.next; 117 | } 118 | 119 | /* now let's walk through it */ 120 | StringBuffer result = new StringBuffer(); 121 | Message temp = index; 122 | while (temp != null) { 123 | result.append(temp.message); 124 | index = temp; 125 | temp = temp.next; 126 | } 127 | 128 | /* store our index */ 129 | indices.put(id, index); 130 | 131 | return result.toString(); 132 | } 133 | } 134 | 135 | public String toString() { 136 | return "[" + size + " messages]"; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /src/ui/SafeDialogs.java: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | import java.awt.*; 4 | import java.awt.event.*; 5 | 6 | import javax.swing.*; 7 | import java.util.*; 8 | 9 | import java.io.*; 10 | 11 | /* Spawn common dialogs in their own thread (so they don't block Sleep interpreter) 12 | and report their results to a callback function */ 13 | public class SafeDialogs { 14 | /* our callback interface... will always return a string I guess */ 15 | public interface SafeDialogCallback { 16 | public void result(String r); 17 | } 18 | 19 | /* prompts the user with a yes/no question. Does not call callback unless the user presses 20 | yes. askYesNo is always a confirm action anyways */ 21 | public static void askYesNo(final String text, final String title, final SafeDialogCallback callback) { 22 | new Thread(new Runnable() { 23 | public void run() { 24 | int result = JOptionPane.showConfirmDialog(null, text, title, JOptionPane.YES_NO_OPTION); 25 | if (result == JOptionPane.YES_OPTION || result == JOptionPane.OK_OPTION) { 26 | callback.result("yes"); 27 | } 28 | } 29 | }).start(); 30 | } 31 | 32 | public static void ask(final String text, final String initial, final SafeDialogCallback callback) { 33 | new Thread(new Runnable() { 34 | public void run() { 35 | String result = JOptionPane.showInputDialog(text, initial); 36 | callback.result(result); 37 | } 38 | }).start(); 39 | } 40 | 41 | /* prompt the user with a saveFile dialog */ 42 | public static void saveFile(final JFrame frame, final String selection, final SafeDialogCallback callback) { 43 | new Thread(new Runnable() { 44 | public void run() { 45 | JFileChooser fc = new JFileChooser(); 46 | 47 | if (selection != null) { 48 | fc.setSelectedFile(new File(selection)); 49 | } 50 | 51 | if (fc.showSaveDialog(frame) == 0) { 52 | File file = fc.getSelectedFile(); 53 | if (file != null) { 54 | callback.result(file + ""); 55 | return; 56 | } 57 | } 58 | } 59 | }).start(); 60 | } 61 | 62 | public static void openFile(final String title, final String sel, final String dir, final boolean multi, final boolean dirsonly, final SafeDialogCallback callback) { 63 | new Thread(new Runnable() { 64 | public void run() { 65 | JFileChooser fc = new JFileChooser(); 66 | 67 | if (title != null) 68 | fc.setDialogTitle(title); 69 | 70 | if (sel != null) 71 | fc.setSelectedFile(new File(sel)); 72 | 73 | if (dir != null) 74 | fc.setCurrentDirectory(new File(dir)); 75 | 76 | fc.setMultiSelectionEnabled(multi); 77 | 78 | if (dirsonly) 79 | fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); 80 | 81 | if (fc.showOpenDialog(null) != JFileChooser.APPROVE_OPTION) 82 | return; 83 | 84 | if (multi) { 85 | StringBuffer buffer = new StringBuffer(); 86 | File[] r = fc.getSelectedFiles(); 87 | 88 | for (int x = 0; x < r.length; x++) { 89 | /* probably always true, but a little defensive coding 90 | never hurt anyone */ 91 | if (r[x] != null && r[x].exists()) { 92 | buffer.append(r[x]); 93 | if ((x + 1) < r.length) 94 | buffer.append(","); 95 | } 96 | } 97 | callback.result(buffer.toString()); 98 | } 99 | else { 100 | if (fc.getSelectedFile() != null && fc.getSelectedFile().exists()) 101 | callback.result(fc.getSelectedFile() + ""); 102 | } 103 | } 104 | }).start(); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | ============================================================================= 2 | Armitage - Cyber Attack Management for Metasploit 3 | ============================================================================= 4 | 5 | *** http://www.fastandeasyhacking.com *** 6 | 7 | 1. What is Armitage? 8 | ----------------- 9 | Armitage is a graphical cyber attack management tool for Metasploit that 10 | visualizes your targets, recommends exploits, and exposes the advanced 11 | capabilities of the framework. 12 | 13 | Advanced users will find Armitage valuable for managing remote Metasploit 14 | instances and collaboration. Armitage's red team collaboration features allow 15 | your team to use the same sessions, share data, and communicate through one 16 | Metasploit instance. 17 | 18 | Armitage aims to make Metasploit usable for security practitioners who 19 | understand hacking but don't use Metasploit every day. If you want to learn 20 | Metasploit and grow into the advanced features, Armitage can help you. 21 | 22 | (c) 2010-2015 Raphael Mudge. This project is licensed under the BSD license. 23 | See license.txt for more information. 24 | 25 | 2. Documentation 26 | ------------- 27 | The documentation for Armitage is located on the Armitage website at: 28 | http://www.fastandeasyhacking.com. Read the FAQ and the Manual for 29 | information on connecting Armitage to Metasploit and using it. 30 | 31 | 3. Install and Update 32 | ---------- 33 | To get started, see the manual at http://www.fastandeasyhacking.com 34 | 35 | 4. Source Code 36 | ----------- 37 | This projected is hosted on Google Code GitHub at: 38 | https://github.com/rsmudge/armitage 39 | 40 | 5. Disclaimer 41 | ---------- 42 | Use this code for your development and don't hack systems that you don't 43 | have permission to hack. The existence of this software does not reflect the 44 | opinions or beliefs of my current employers, past employers, future 45 | employers, or any small animals I come into contact with. Enjoy this 46 | software with my blessing. I hope it helps you learn and become a better 47 | security professional. 48 | 49 | 6. Contact 50 | ------- 51 | Report bugs in the issue tracker at: 52 | https://github.com/rsmudge/armitage/issues 53 | 54 | E-mail contact@fastandeasyhacking.com with other questions/concerns. Make 55 | sure you peruse the FAQ and Manual first. 56 | 57 | You may also visit us on irc.freenode.net in #armitage 58 | 59 | 7. Credits for Third-Party Components 60 | ------- 61 | Draggable Tabbed Pane - (c) Tom Martin (Creative Commons 3.0 Share-Alike [Attribution Required] License) 62 | http://stackoverflow.com/questions/60269/how-to-implement-draggable-tab-using-java-swing 63 | 64 | Javassist 3.15 - (c) Shigeru Chiba 1999-2015 (Apache 2.0 License) 65 | https://github.com/jboss-javassist/javassist 66 | (dependency for MsgPack for Java) 67 | 68 | JGraphX - (c) JGraph Ltd 2006-2012 (BSD License) 69 | http://www.jgraphx.com/ 70 | 71 | Metasploit Framework - (c) Rapid7 Inc. 2012 (BSD License) 72 | http://www.metasploit.com/ 73 | 74 | msfgui - (c) Matt Weeks 2010-2012 (BSD License) 75 | http://www.metasploit.com/ 76 | 77 | MsgPack for Java - (c) F. Sadayuki and M. Nishizawa (Apache 2.0 License) 78 | https://github.com/msgpack/msgpack-java 79 | 80 | PostgreSQL JDBC Connector - (c) 1997-2010, PostgreSQL Global Development Group (BSD License) 81 | http://jdbc.postgresql.org/ 82 | 83 | Sleep 2.1 - (c) 2002-2009, Raphael Mudge (LGPL) 84 | http://sleep.dashnine.org/ 85 | -------------------------------------------------------------------------------- /src/cortana/core/FilterManager.java: -------------------------------------------------------------------------------- 1 | package cortana.core; 2 | 3 | import java.util.*; 4 | import sleep.runtime.*; 5 | import sleep.bridges.*; 6 | import sleep.engine.*; 7 | import sleep.interfaces.*; 8 | 9 | public class FilterManager { 10 | protected Map filters; 11 | 12 | protected List getFilters(String name) { 13 | if (filters.containsKey(name)) { 14 | return (List)filters.get(name); 15 | } 16 | else { 17 | filters.put(name, new LinkedList()); 18 | return (List)filters.get(name); 19 | } 20 | } 21 | 22 | public Loadable getBridge() { 23 | return new Filters(this); 24 | } 25 | 26 | public FilterManager() { 27 | filters = new HashMap(); 28 | } 29 | 30 | private static class Filter { 31 | protected SleepClosure filter; 32 | 33 | public Filter(SleepClosure filter) { 34 | this.filter = filter; 35 | } 36 | 37 | public SleepClosure getClosure() { 38 | return filter; 39 | } 40 | } 41 | 42 | public void addFilter(String filter, SleepClosure c) { 43 | getFilters(filter).add(new Filter(c)); 44 | } 45 | 46 | /* convert the Java object to a Sleep data type (recursively) */ 47 | public static Scalar convertAll(Object data) { 48 | if (data instanceof Collection) { 49 | Scalar temp = SleepUtils.getArrayScalar(); 50 | Iterator i = ((Collection)data).iterator(); 51 | while (i.hasNext()) { 52 | temp.getArray().push(convertAll(i.next())); 53 | } 54 | return temp; 55 | } 56 | else if (data instanceof Map) { 57 | Scalar temp = SleepUtils.getHashScalar(); 58 | Iterator i = ((Map)data).entrySet().iterator(); 59 | while (i.hasNext()) { 60 | Map.Entry entry = (Map.Entry)i.next(); 61 | Scalar key = SleepUtils.getScalar(entry.getKey() + ""); 62 | Scalar value = temp.getHash().getAt(key); 63 | value.setValue(convertAll(entry.getValue())); 64 | } 65 | return temp; 66 | } 67 | else { 68 | return ObjectUtilities.BuildScalar(true, data); 69 | } 70 | } 71 | 72 | public Stack filterScalarData(String eventName, Stack args) { 73 | List filters = getFilters(eventName); 74 | 75 | if (filters.size() == 0) 76 | return args; 77 | 78 | Iterator i = filters.iterator(); 79 | 80 | ScriptInstance script = null; 81 | 82 | while (i.hasNext()) { 83 | Filter f = (Filter)i.next(); 84 | 85 | if (!f.getClosure().getOwner().isLoaded()) { 86 | i.remove(); 87 | continue; 88 | } 89 | 90 | Scalar temp = SleepUtils.runCode(f.getClosure(), eventName, null, args); 91 | script = f.getClosure().getOwner(); 92 | args.clear(); 93 | 94 | if (temp.getArray() != null) { 95 | ScalarArray ar = temp.getArray(); 96 | while (ar.size() > 0) { 97 | Scalar tempz = ar.pop(); 98 | args.push(tempz); 99 | } 100 | } 101 | else { 102 | throw new RuntimeException("filter " + f.getClosure() + " did not return an array"); 103 | } 104 | } 105 | 106 | return args; 107 | } 108 | 109 | public Object[] filterData(String eventName, Object[] data) { 110 | if (getFilters(eventName).size() == 0) 111 | return data; 112 | 113 | Stack args = new Stack(); 114 | int offset = data.length - 1; 115 | for (int x = 0; x < data.length; x++) { 116 | args.push(convertAll(data[offset - x])); 117 | } 118 | 119 | Stack res = filterScalarData(eventName, args); 120 | 121 | Object rv[] = new Object[res.size()]; 122 | //System.err.println("Filter: " + eventName); 123 | for (int x = 0; x < rv.length; x++) { 124 | rv[x] = ObjectUtilities.buildArgument(Object.class, (Scalar)res.pop(), null); 125 | //System.err.println(" '" + rv[x] + "', " + rv[x].getClass()); 126 | } 127 | return rv; 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /scripts/hosts.sl: -------------------------------------------------------------------------------- 1 | import msf.*; 2 | 3 | import javax.swing.*; 4 | import javax.swing.event.*; 5 | 6 | import java.awt.*; 7 | import java.awt.event.*; 8 | 9 | sub addHostDialog { 10 | local('$dialog $label $text $finish $button'); 11 | $dialog = dialog("Add Hosts", 320, 240); 12 | 13 | $label = [new JLabel: "Enter one host/line:"]; 14 | $text = [new JTextArea]; 15 | 16 | $finish = [new JPanel]; 17 | [$finish setLayout: [new FlowLayout: [FlowLayout CENTER]]]; 18 | 19 | $button = [new JButton: "Add"]; 20 | [$finish add: $button]; 21 | 22 | [$button addActionListener: lambda({ 23 | local('@hosts'); 24 | @hosts = split("[\n\s]", [$text getText]); 25 | cmd_safe("hosts -a " . join(" ", @hosts), lambda({ 26 | showError("Added $x host" . iff($x != 1, "s")); 27 | elog("added $x host" . iff($x != 1, "s")); 28 | }, $x => size(@hosts))); 29 | [$dialog setVisible: 0]; 30 | }, \$text, \$dialog)]; 31 | 32 | [$dialog add: $label, [BorderLayout NORTH]]; 33 | [$dialog add: [new JScrollPane: $text], [BorderLayout CENTER]]; 34 | [$dialog add: $finish, [BorderLayout SOUTH]]; 35 | 36 | [$dialog setVisible: 1]; 37 | } 38 | 39 | sub host_items { 40 | local('$i $j $k'); 41 | item($1, "Import Hosts", 'I', &importHosts); 42 | item($1, "Add Hosts...", 'A', &addHostDialog); 43 | setupMenu($1, "hosts_top", @()); 44 | 45 | separator($1); 46 | 47 | $j = menu($1, "Nmap Scan", 'S'); 48 | setupMenu($j, "hosts_nmap", @()); 49 | item($j, "Intense Scan", $null, createNmapFunction("--min-hostgroup 96 -T4 -A -v -n")); 50 | item($j, "Intense Scan + UDP", $null, createNmapFunction("--min-hostgroup 96 -sS -n -sU -T4 -A -v")); 51 | item($j, "Intense Scan, all TCP ports", $null, createNmapFunction("--min-hostgroup 96 -p 1-65535 -n -T4 -A -v")); 52 | item($j, "Intense Scan, no ping", $null, createNmapFunction("--min-hostgroup 96 -T4 -n -A -v -Pn")); 53 | item($j, "Ping Scan", $null, createNmapFunction("--min-hostgroup 96 -T4 -n -sn")); 54 | item($j, "Quick Scan", $null, createNmapFunction("--min-hostgroup 96 -T4 -n -F")); 55 | item($j, "Quick Scan (OS detect)", $null, createNmapFunction("--min-hostgroup 96 -sV -n -T4 -O -F --version-light")); 56 | item($j, "Comprehensive", $null, createNmapFunction("--min-hostgroup 96 -sS -n -sU -T4 -A -v -PE -PP -PS80,443 -PA3389 -PU40125 -PY -g 53")); 57 | 58 | item($1, "MSF Scans...", "M", { 59 | ask_async("Enter scan range (e.g., 192.168.1.0/24):", join(", ", [$targets getSelectedHosts]), $this); 60 | yield; 61 | if ($1 eq "") { return; } 62 | launch_msf_scans($1); 63 | }); 64 | 65 | item($1, "DNS Enumerate", 'D', { 66 | if (size([$targets getSelectedHosts]) > 0) { 67 | launch_dialog("Enumerate DNS", "auxiliary", "gather/enum_dns", 1, $null, %(NS => [$targets getSelectedHosts][0])); 68 | } 69 | else { 70 | launch_dialog("Enumerate DNS", "auxiliary", "gather/enum_dns", 1, $null, %()); 71 | } 72 | }); 73 | 74 | setupMenu($1, "hosts_middle", @()); 75 | separator($1); 76 | setupMenu($1, "hosts_bottom", @()); 77 | item($1, "Clear Database", 'C', &clearDatabase); 78 | } 79 | 80 | # oh yay, Metasploit now normalizes OS info (so I don't have to). Except the new constants 81 | # they use are different than the ones they have used... *sigh* time to future proof my code. 82 | sub normalize { 83 | if ("*Windows*" iswm $1) { 84 | return "Windows"; 85 | } 86 | else if ("*Mac*OS*X*" iswm $1) { 87 | return "Mac OS X"; 88 | } 89 | else if ("*Solaris*" iswm $1) { 90 | return "Solaris"; 91 | } 92 | else if ("*Cisco*" iswm $1) { 93 | return "IOS"; 94 | } 95 | else if ("*Printer*" iswm $1) { 96 | return "Printer"; 97 | } 98 | else { 99 | return $1; 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /src/cortana/support/LockBridge.java: -------------------------------------------------------------------------------- 1 | package cortana.support; 2 | 3 | import cortana.core.*; 4 | import cortana.*; 5 | 6 | import java.util.*; 7 | 8 | import sleep.runtime.*; 9 | import sleep.interfaces.*; 10 | import sleep.bridges.*; 11 | 12 | import msf.*; 13 | 14 | public class LockBridge implements Function, Loadable, Runnable { 15 | protected EventManager events; 16 | protected RpcConnection connection; 17 | protected List locks = new LinkedList(); 18 | 19 | private class LockMinion { 20 | protected String name; 21 | protected ScriptInstance script; 22 | protected boolean keep; 23 | protected Stack args; 24 | 25 | public LockMinion(String name, ScriptInstance script, boolean keep, Stack args) { 26 | this.name = name; 27 | this.script = script; 28 | this.keep = keep; 29 | this.args = args; 30 | } 31 | 32 | public boolean grab() { 33 | if (acquireLock(name, script)) { 34 | events.fireEvent("locked_" + name, args, script); 35 | if (!keep) 36 | releaseLock(name); 37 | return true; 38 | } 39 | return false; 40 | } 41 | } 42 | 43 | public LockBridge(RpcConnection connection, EventManager events) { 44 | this.connection = connection; 45 | this.events = events; 46 | new Thread(this).start(); 47 | } 48 | 49 | public boolean acquireLock(String name, ScriptInstance script) { 50 | try { 51 | Map temp = (Map)connection.execute("armitage.lock", new Object[] { name, script.getName() }); 52 | if (!temp.containsKey("error")) 53 | return true; 54 | } 55 | catch (Exception ex) { 56 | } 57 | return false; 58 | } 59 | 60 | public void releaseLock(String name) { 61 | try { 62 | ((Async)connection).execute_async("armitage.unlock", new Object[] { name }); 63 | } 64 | catch (Exception ex) { 65 | } 66 | } 67 | 68 | public void run() { 69 | while (true) { 70 | List templ; 71 | synchronized (this) { 72 | templ = new LinkedList(locks); 73 | } 74 | 75 | try { 76 | if (templ.size() == 0) { 77 | Thread.sleep(2000); 78 | } 79 | else { 80 | List tempr = new LinkedList(); 81 | 82 | /* loop through our locks (in order) and try to acquire them and release them */ 83 | Iterator i = templ.iterator(); 84 | while (i.hasNext()) { 85 | LockMinion m = (LockMinion)i.next(); 86 | if (m.grab()) 87 | tempr.add(m); 88 | Thread.sleep(100); 89 | } 90 | 91 | /* now, take any locks that were successful and remove them from oust list */ 92 | synchronized (this) { 93 | i = tempr.iterator(); 94 | while (i.hasNext()) { 95 | locks.remove(i.next()); 96 | } 97 | } 98 | 99 | /* now, sleep... */ 100 | Thread.sleep(1000); 101 | } 102 | } 103 | catch (Exception ex) { 104 | ex.printStackTrace(); 105 | } 106 | } 107 | } 108 | 109 | public Scalar evaluate(String name, ScriptInstance script, Stack args) { 110 | String lname = BridgeUtilities.getString(args, ""); 111 | if (name.equals("&lock")) { 112 | Scalar last = BridgeUtilities.getScalar(args); 113 | synchronized (this) { 114 | locks.add( new LockMinion( lname, script, SleepUtils.isTrueScalar(last), (Stack)args.clone() ) ); 115 | } 116 | } 117 | else { 118 | releaseLock(lname); 119 | } 120 | return SleepUtils.getEmptyScalar(); 121 | } 122 | 123 | public void scriptLoaded(ScriptInstance script) { 124 | script.getScriptEnvironment().getEnvironment().put("&lock", this); 125 | script.getScriptEnvironment().getEnvironment().put("&unlock", this); 126 | } 127 | 128 | public void scriptUnloaded(ScriptInstance script) { 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/tree/SimpleTreeNode.java: -------------------------------------------------------------------------------- 1 | package tree; 2 | 3 | import javax.swing.*; 4 | import javax.swing.tree.*; 5 | import java.util.*; 6 | 7 | /** implements a TreeNode that: 8 | 1. stores children in sorted order 9 | 2. requires unique children 10 | 3. provides a thread safe add(), mark(), and reset() operations 11 | 12 | 13 | */ 14 | public class SimpleTreeNode implements TreeNode { 15 | protected TreeNode parent; 16 | protected Object data; 17 | 18 | protected List children = new LinkedList(); 19 | protected Set marked = null; 20 | 21 | protected TreeModel model; 22 | 23 | public SimpleTreeNode(TreeModel model, TreeNode parent, Object data) { 24 | this.model = model; 25 | this.parent = parent; 26 | this.data = data; 27 | } 28 | 29 | public void setModel(TreeModel model) { 30 | this.model = model; 31 | } 32 | 33 | public SimpleTreeNode(TreeNode parent, Object data) { 34 | this.parent = parent; 35 | this.data = data; 36 | } 37 | 38 | public Enumeration children() { 39 | return Collections.enumeration(children); 40 | } 41 | 42 | public void add(final TreeNode node) { 43 | if (SwingUtilities.isEventDispatchThread()) { 44 | _add(node); 45 | } 46 | else { 47 | SwingUtilities.invokeLater(new Runnable() { 48 | public void run() { 49 | _add(node); 50 | } 51 | }); 52 | } 53 | } 54 | 55 | public TreeNode findChild(Object o) { 56 | Iterator i = children.iterator(); 57 | while (i.hasNext()) { 58 | SimpleTreeNode node = (SimpleTreeNode)i.next(); 59 | if (o.equals(node.getData())) 60 | return node; 61 | } 62 | System.err.println("Child not found: " + o + " vs. " + children); 63 | return null; 64 | } 65 | 66 | public Object getData() { 67 | return data; 68 | } 69 | 70 | public void mark() { 71 | synchronized (this) { 72 | marked = new HashSet(); 73 | } 74 | } 75 | 76 | public void reset() { 77 | if (SwingUtilities.isEventDispatchThread()) { 78 | _reset(); 79 | } 80 | else { 81 | SwingUtilities.invokeLater(new Runnable() { 82 | public void run() { 83 | _reset(); 84 | } 85 | }); 86 | } 87 | } 88 | 89 | public void _reset() { 90 | Iterator i = children.iterator(); 91 | while (i.hasNext()) { 92 | Object node = i.next(); 93 | if (!marked.contains(node)) 94 | i.remove(); 95 | } 96 | 97 | if (model instanceof DefaultTreeModel) 98 | ((DefaultTreeModel)model).nodeStructureChanged(this); 99 | } 100 | 101 | public void _add(TreeNode node) { 102 | ListIterator i = children.listIterator(); 103 | String represent = node.toString().toLowerCase(); 104 | while (i.hasNext()) { 105 | Object next = i.next(); 106 | if (next.toString().toLowerCase().equals(represent)) { 107 | synchronized(this) { 108 | marked.add(next); 109 | } 110 | return; 111 | } 112 | else if (represent.compareTo(next.toString().toLowerCase()) < 0) { 113 | synchronized (this) { 114 | i.add(node); 115 | marked.add(node); 116 | } 117 | return; 118 | } 119 | } 120 | children.add(node); 121 | synchronized (this) { 122 | marked.add(node); 123 | } 124 | } 125 | 126 | public boolean getAllowsChildren() { 127 | return true; 128 | } 129 | 130 | public TreeNode getChildAt(int index) { 131 | return (TreeNode)children.get(index); 132 | } 133 | 134 | public int getChildCount() { 135 | return children.size(); 136 | } 137 | 138 | public int getIndex(TreeNode node) { 139 | return children.indexOf(node); 140 | } 141 | 142 | public TreeNode getParent() { 143 | return parent; 144 | } 145 | 146 | public boolean isLeaf() { 147 | return false; 148 | } 149 | 150 | public String toString() { 151 | return data.toString(); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /release/armitage-unix/readme.txt: -------------------------------------------------------------------------------- 1 | ============================================================================= 2 | Armitage - Cyber Attack Management for Metasploit 3 | ============================================================================= 4 | 5 | *** http://www.fastandeasyhacking.com *** 6 | 7 | 1. What is Armitage? 8 | ----------------- 9 | 10 | Armitage is a graphical cyber attack management tool for Metasploit that 11 | visualizes your targets, recommends exploits, and exposes the advanced 12 | capabilities of the framework. 13 | 14 | Advanced users will find Armitage valuable for managing remote Metasploit 15 | instances and collaboration. Armitage's red team collaboration features allow 16 | your team to use the same sessions, share data, and communicate through one 17 | Metasploit instance. 18 | 19 | Armitage aims to make Metasploit usable for security practitioners who 20 | understand hacking but don't use Metasploit every day. If you want to learn 21 | Metasploit and grow into the advanced features, Armitage can help you. 22 | 23 | 2. Documentation 24 | ------------- 25 | 26 | The documentation for Armitage is located on the Armitage website at: 27 | http://www.fastandeasyhacking.com. Read the FAQ and the Manual for 28 | information on connecting Armitage to Metasploit and using it. 29 | 30 | 3. Install and Update 31 | ---------- 32 | 33 | To get started, see the manual at http://www.fastandeasyhacking.com 34 | 35 | 4. Source Code 36 | ----------- 37 | 38 | This projected is hosted on Google Code at: 39 | http://code.google.com/p/armitage/ 40 | 41 | 5. Disclaimer 42 | ---------- 43 | 44 | Use this code for your development and don't hack systems that you don't 45 | have permission to hack. The existence of this software does not reflect the 46 | opinions or beliefs of my current employers, past employers, future 47 | employers, or any small animals I come into contact with. Enjoy this 48 | software with my blessing. I hope it helps you learn and become a better 49 | security professional. 50 | 51 | 6. Contact 52 | ------- 53 | 54 | Report bugs in the issue tracker at: 55 | http://code.google.com/p/armitage/issues/list 56 | 57 | E-mail contact@fastandeasyhacking.com with other questions/concerns. Make 58 | sure you peruse the FAQ and Manual first. 59 | 60 | 7. License 61 | ------- 62 | 63 | (c) 2010-2013 Raphael Mudge. This project is licensed under the BSD license. 64 | See section 8 for more information. 65 | 66 | lib/jgraphx.jar is used here within the terms of the BSD license offered by 67 | JGraphX Ltd. http://www.jgraphx.com/ 68 | - 69 | lib/msgpack-0.5.1-devel.jar and lib/postgresql-9.1-901.jdbc4.jar are both 70 | BSD licensed libraries. 71 | - 72 | Some code in src/msf/* comes from msfgui by scriptjunkie. 73 | - 74 | This project uses the LGPL Sleep scripting language with no modifications. 75 | Sleep's source is available at: http://sleep.dashnine.org/ 76 | 77 | 8. The BSD License 78 | --------------- 79 | 80 | Redistribution and use in source and binary forms are permitted provided 81 | that the above copyright notice and this paragraph are duplicated in all 82 | such forms and that any documentation, advertising materials, and other 83 | materials related to such distribution and use acknowledge that the 84 | software was developed by the copyright holders. The name of the copyright 85 | holders may not be used to endorse or promote products derived from this 86 | software without specific prior written permission. 87 | 88 | THIS SOFTWARE IS PROVIDED ''AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 89 | WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 90 | MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 91 | -------------------------------------------------------------------------------- /release/armitage-windows/readme.txt: -------------------------------------------------------------------------------- 1 | ============================================================================= 2 | Armitage - Cyber Attack Management for Metasploit 3 | ============================================================================= 4 | 5 | *** http://www.fastandeasyhacking.com *** 6 | 7 | 1. What is Armitage? 8 | ----------------- 9 | 10 | Armitage is a graphical cyber attack management tool for Metasploit that 11 | visualizes your targets, recommends exploits, and exposes the advanced 12 | capabilities of the framework. 13 | 14 | Advanced users will find Armitage valuable for managing remote Metasploit 15 | instances and collaboration. Armitage's red team collaboration features allow 16 | your team to use the same sessions, share data, and communicate through one 17 | Metasploit instance. 18 | 19 | Armitage aims to make Metasploit usable for security practitioners who 20 | understand hacking but don't use Metasploit every day. If you want to learn 21 | Metasploit and grow into the advanced features, Armitage can help you. 22 | 23 | 2. Documentation 24 | ------------- 25 | 26 | The documentation for Armitage is located on the Armitage website at: 27 | http://www.fastandeasyhacking.com. Read the FAQ and the Manual for 28 | information on connecting Armitage to Metasploit and using it. 29 | 30 | 3. Install and Update 31 | ---------- 32 | 33 | To get started, see the manual at http://www.fastandeasyhacking.com 34 | 35 | 4. Source Code 36 | ----------- 37 | 38 | This projected is hosted on Google Code at: 39 | http://code.google.com/p/armitage/ 40 | 41 | 5. Disclaimer 42 | ---------- 43 | 44 | Use this code for your development and don't hack systems that you don't 45 | have permission to hack. The existence of this software does not reflect the 46 | opinions or beliefs of my current employers, past employers, future 47 | employers, or any small animals I come into contact with. Enjoy this 48 | software with my blessing. I hope it helps you learn and become a better 49 | security professional. 50 | 51 | 6. Contact 52 | ------- 53 | 54 | Report bugs in the issue tracker at: 55 | http://code.google.com/p/armitage/issues/list 56 | 57 | E-mail contact@fastandeasyhacking.com with other questions/concerns. Make 58 | sure you peruse the FAQ and Manual first. 59 | 60 | 7. License 61 | ------- 62 | 63 | (c) 2010-2013 Raphael Mudge. This project is licensed under the BSD license. 64 | See section 8 for more information. 65 | 66 | lib/jgraphx.jar is used here within the terms of the BSD license offered by 67 | JGraphX Ltd. http://www.jgraphx.com/ 68 | - 69 | lib/msgpack-0.5.1-devel.jar and lib/postgresql-9.1-901.jdbc4.jar are both 70 | BSD licensed libraries. 71 | - 72 | Some code in src/msf/* comes from msfgui by scriptjunkie. 73 | - 74 | This project uses the LGPL Sleep scripting language with no modifications. 75 | Sleep's source is available at: http://sleep.dashnine.org/ 76 | 77 | 8. The BSD License 78 | --------------- 79 | 80 | Redistribution and use in source and binary forms are permitted provided 81 | that the above copyright notice and this paragraph are duplicated in all 82 | such forms and that any documentation, advertising materials, and other 83 | materials related to such distribution and use acknowledge that the 84 | software was developed by the copyright holders. The name of the copyright 85 | holders may not be used to endorse or promote products derived from this 86 | software without specific prior written permission. 87 | 88 | THIS SOFTWARE IS PROVIDED ''AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 89 | WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 90 | MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 91 | -------------------------------------------------------------------------------- /src/armitage/ArmitageTimer.java: -------------------------------------------------------------------------------- 1 | package armitage; 2 | 3 | import console.Console; 4 | import msf.*; 5 | import java.util.*; 6 | 7 | /** A generic class to execute several queries and return their results */ 8 | public class ArmitageTimer implements Runnable { 9 | protected RpcConnection connection; 10 | protected String command; 11 | protected long sleepPeriod; 12 | protected ArmitageTimerClient client; 13 | protected boolean cacheProtocol; 14 | 15 | /* keep track of the last response we got *and* its hashcode... */ 16 | protected Map lastRead = new HashMap(); 17 | protected long lastCode = -1L; /* can't be 0 or we'll never fire an initial event */ 18 | 19 | public ArmitageTimer(RpcConnection connection, String command, long sleepPeriod, ArmitageTimerClient client, boolean doCache) { 20 | this.connection = connection; 21 | this.command = command; 22 | this.sleepPeriod = sleepPeriod; 23 | this.client = client; 24 | cacheProtocol = doCache; 25 | new Thread(this).start(); 26 | } 27 | 28 | public static long dataIdentity(Object v) { 29 | long r = 0L; 30 | 31 | if (v == null) { 32 | return 1L; 33 | } 34 | else if (v instanceof Collection) { 35 | Iterator j = ((Collection)v).iterator(); 36 | while (j.hasNext()) { 37 | r += 11 * dataIdentity(j.next()); 38 | } 39 | } 40 | else if (v instanceof Map) { 41 | Iterator i = ((Map)v).values().iterator(); 42 | while (i.hasNext()) { 43 | r += 13 * dataIdentity(i.next()); 44 | } 45 | } 46 | else if (v instanceof Number) { 47 | return v.hashCode(); 48 | } 49 | else { 50 | return v.toString().hashCode(); 51 | } 52 | return r; 53 | } 54 | 55 | protected boolean changed = false; 56 | 57 | /* we will override this in a subclass if we need to change it */ 58 | protected boolean alwaysFire() { 59 | return false; 60 | } 61 | 62 | private Map readFromClient() throws java.io.IOException { 63 | try { 64 | Object arguments[]; 65 | if (cacheProtocol) { 66 | arguments = new Object[1]; 67 | arguments[0] = new Long(lastCode); 68 | } 69 | else { 70 | arguments = new Object[0]; 71 | } 72 | 73 | Map result = (Map)connection.execute(command, arguments); 74 | 75 | if (!result.containsKey("nochange")) { 76 | lastRead = result; 77 | lastCode = dataIdentity(result); 78 | changed = true; 79 | } 80 | else { 81 | //System.err.println("No change: " + command + ", " + lastCode); 82 | changed = false; 83 | } 84 | 85 | return lastRead; 86 | } 87 | catch (java.net.SocketException sex) { 88 | /* this definitely means we were booted */ 89 | return null; 90 | } 91 | catch (NullPointerException nex) { 92 | /* this means the connection is dead, let's start to respond accordingly */ 93 | return null; 94 | } 95 | } 96 | 97 | public void run() { 98 | Map read = null; 99 | 100 | try { 101 | while ((read = readFromClient()) != null) { 102 | if (changed || command.equals("session.list") || alwaysFire()) { 103 | if (client.result(command, null, read) == false) { 104 | return; 105 | } 106 | } 107 | 108 | if (sleepPeriod <= 0) { 109 | return; 110 | } 111 | else { 112 | Thread.sleep(sleepPeriod); 113 | } 114 | } 115 | 116 | armitage.ArmitageMain.print_error("Read for " + command + " is null. Stopping thread"); 117 | ((Async)connection).disconnect(); 118 | } 119 | catch (Exception javaSucksBecauseItMakesMeCatchEverythingFuckingThing) { 120 | System.err.println("Thread id: " + command + " -> " + read); 121 | javaSucksBecauseItMakesMeCatchEverythingFuckingThing.printStackTrace(); 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /src/ui/DraggableTabbedPane.java: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | import java.awt.Component; 4 | import java.awt.Graphics; 5 | import java.awt.Image; 6 | import java.awt.Point; 7 | import java.awt.Rectangle; 8 | import java.awt.event.MouseAdapter; 9 | import java.awt.event.MouseEvent; 10 | import java.awt.event.MouseMotionAdapter; 11 | import java.awt.image.BufferedImage; 12 | 13 | import javax.swing.JButton; 14 | import javax.swing.JFrame; 15 | import javax.swing.JTabbedPane; 16 | 17 | /* 18 | * Adapted from: http://stackoverflow.com/questions/60269/how-to-implement-draggable-tab-using-java-swing 19 | * Original author: Tom Martin 20 | * StackOverflow.com contents is Creative Commons Share-Alike (Attribution Required) license 21 | * 22 | * Thanks Tom for the excellent example. 23 | */ 24 | public class DraggableTabbedPane extends JTabbedPane { 25 | 26 | private boolean dragging = false; 27 | private Image tabImage = null; 28 | private Point currentMouseLocation = null; 29 | private int draggedTabIndex = 0; 30 | 31 | public DraggableTabbedPane() { 32 | super(); 33 | addMouseMotionListener(new MouseMotionAdapter() { 34 | public void mouseDragged(MouseEvent e) { 35 | if(!dragging) { 36 | // Gets the tab index based on the mouse position 37 | int tabNumber = getUI().tabForCoordinate(DraggableTabbedPane.this, e.getX(), e.getY()); 38 | 39 | if(tabNumber >= 0) { 40 | draggedTabIndex = tabNumber; 41 | Rectangle bounds = getUI().getTabBounds(DraggableTabbedPane.this, tabNumber); 42 | 43 | // Paint the tabbed pane to a buffer 44 | Image totalImage = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB); 45 | Graphics totalGraphics = totalImage.getGraphics(); 46 | totalGraphics.setClip(bounds); 47 | 48 | // Don't be double buffered when painting to a static image. 49 | setDoubleBuffered(false); 50 | paint(totalGraphics); 51 | 52 | // Paint just the dragged tab to the buffer 53 | tabImage = new BufferedImage(bounds.width, bounds.height, BufferedImage.TYPE_INT_ARGB); 54 | Graphics graphics = tabImage.getGraphics(); 55 | graphics.drawImage(totalImage, 0, 0, bounds.width, bounds.height, bounds.x, bounds.y, bounds.x + bounds.width, bounds.y+bounds.height, DraggableTabbedPane.this); 56 | 57 | dragging = true; 58 | repaint(); 59 | 60 | graphics.dispose(); 61 | totalGraphics.dispose(); 62 | } 63 | } 64 | else { 65 | currentMouseLocation = e.getPoint(); 66 | 67 | // Need to repaint 68 | repaint(); 69 | } 70 | 71 | super.mouseDragged(e); 72 | } 73 | }); 74 | 75 | addMouseListener(new MouseAdapter() { 76 | public void mouseReleased(MouseEvent e) { 77 | 78 | if(dragging) { 79 | int tabNumber = getUI().tabForCoordinate(DraggableTabbedPane.this, e.getX(), 10); 80 | 81 | if (e.getX() < 0) { 82 | tabNumber = 0; 83 | } 84 | else if (tabNumber == -1) { 85 | tabNumber = getTabCount() - 1; 86 | } 87 | 88 | if (tabNumber >= 0) { 89 | Component comp = getComponentAt(draggedTabIndex); 90 | Component title = getTabComponentAt(draggedTabIndex); 91 | removeTabAt(draggedTabIndex); 92 | insertTab("", null, comp, null, tabNumber); 93 | setTabComponentAt(tabNumber, title); 94 | setSelectedIndex(tabNumber); 95 | } 96 | } 97 | 98 | dragging = false; 99 | tabImage = null; 100 | } 101 | }); 102 | } 103 | 104 | protected void paintComponent(Graphics g) { 105 | super.paintComponent(g); 106 | 107 | // Are we dragging? 108 | if(dragging && currentMouseLocation != null && tabImage != null) { 109 | // Draw the dragged tab 110 | g.drawImage(tabImage, currentMouseLocation.x, currentMouseLocation.y, this); 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/ui/UploadFile.java: -------------------------------------------------------------------------------- 1 | package ui; 2 | 3 | import java.io.*; 4 | import msf.*; 5 | import javax.swing.*; 6 | import java.util.*; 7 | 8 | /* upload a file to the team server... */ 9 | public class UploadFile implements Runnable { 10 | protected FileInputStream in = null; 11 | protected byte[] buffer = new byte[256 * 1024]; 12 | protected File file = null; 13 | protected RpcConnection client = null; 14 | protected UploadNotify listener = null; 15 | protected Thread thread = null; 16 | protected String rfile = null; 17 | 18 | public static interface UploadNotify { 19 | /* call with the remote path of the file */ 20 | public void complete(String name); 21 | } 22 | 23 | public UploadFile(RpcConnection client, File file, UploadNotify listener) { 24 | this.file = file; 25 | this.client = client; 26 | this.listener = listener; 27 | this.thread = new Thread(this); 28 | thread.start(); 29 | } 30 | 31 | /* wait for the upload to finish and return our file */ 32 | public String getRemoteFile() { 33 | if (SwingUtilities.isEventDispatchThread()) { 34 | System.err.println("DiSS! upload of " + file + " is happening in EDT (unsafe)"); 35 | } 36 | 37 | try { 38 | thread.join(); 39 | } 40 | catch (InterruptedException iex) { 41 | } 42 | 43 | if (rfile == null) 44 | throw new RuntimeException("user canceled upload of file"); 45 | return rfile; 46 | } 47 | 48 | protected Object[] argz(byte[] data, long length) { 49 | /* copy relevant bytes to a temporary byte buffer */ 50 | byte[] me = new byte[(int)length]; 51 | for (int x = 0; x < length; x++) { 52 | me[x] = data[x]; 53 | } 54 | 55 | Object[] args = new Object[2]; 56 | args[0] = file.getName(); 57 | args[1] = me; 58 | return args; 59 | } 60 | 61 | public void run() { 62 | try { 63 | long total = file.length(); 64 | long start = System.currentTimeMillis(); 65 | long read = 0; 66 | long ret = 0; 67 | long sofar = 0; 68 | double time = 0; 69 | 70 | ProgressMonitor progress = new ProgressMonitor(null, "Upload " + file.getName(), "Starting upload", 0, (int)total); 71 | 72 | in = new FileInputStream(file); 73 | 74 | /* read our first round and then call a function to upload the data */ 75 | read = in.read(buffer); 76 | sofar += read; 77 | Map result = (Map)client.execute("armitage.upload", argz(buffer, read)); 78 | 79 | while (sofar < total) { 80 | /* update our progress bar */ 81 | time = (System.currentTimeMillis() - start) / 1000.0; 82 | progress.setProgress((int)sofar); 83 | progress.setNote("Speed: " + Math.round((sofar / 1024) / time) + " KB/s"); 84 | 85 | /* honor the user's request to cancel the upload */ 86 | if (progress.isCanceled()) { 87 | progress.close(); 88 | in.close(); 89 | return; 90 | } 91 | 92 | /* read in some data */ 93 | read = in.read(buffer); 94 | sofar += read; 95 | 96 | /* upload the data to the team server */ 97 | client.execute("armitage.append", argz(buffer, read)); 98 | 99 | /* give it a break */ 100 | Thread.yield(); 101 | } 102 | 103 | /* update our progress bar */ 104 | time = (System.currentTimeMillis() - start) / 1000.0; 105 | progress.setProgress((int)sofar); 106 | progress.setNote("Speed: " + Math.round((sofar / 1024) / time) + " KB/s"); 107 | 108 | /* clean up, now that we're done */ 109 | progress.close(); 110 | in.close(); 111 | 112 | /* call our listener, if it's not null */ 113 | if (listener != null) 114 | listener.complete(result.get("file") + ""); 115 | 116 | /* set the remote file */ 117 | rfile = result.get("file") + ""; 118 | } 119 | catch (Exception ioex) { 120 | JOptionPane.showMessageDialog(null, "Aborted upload of: " + file.getName() + "\n" + ioex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE); 121 | System.err.println("Aborted upload of: " + file); 122 | ioex.printStackTrace(); 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/cortana/Loader.java: -------------------------------------------------------------------------------- 1 | package cortana; 2 | 3 | import cortana.core.*; 4 | 5 | import sleep.runtime.*; 6 | import sleep.interfaces.*; 7 | 8 | import sleep.error.*; 9 | 10 | import java.io.*; 11 | import java.util.*; 12 | 13 | /** The Loader creates an isolated script instance for each Cortana script that we load */ 14 | public class Loader implements Loadable { 15 | protected ScriptLoader loader; 16 | protected Hashtable shared = new Hashtable(); 17 | protected ScriptVariables vars = new ScriptVariables(); 18 | protected Object[] passMe = new Object[4]; 19 | protected List scripts = new LinkedList(); 20 | 21 | public void unsetDebugLevel(int flag) { 22 | Iterator i = scripts.iterator(); 23 | while (i.hasNext()) { 24 | ScriptInstance script = (ScriptInstance)i.next(); 25 | int flags = script.getDebugFlags() & ~flag; 26 | script.setDebugFlags(flags); 27 | } 28 | } 29 | 30 | public void printProfile(OutputStream out) { 31 | Iterator i = scripts.iterator(); 32 | while (i.hasNext()) { 33 | ScriptInstance script = (ScriptInstance)i.next(); 34 | script.printProfileStatistics(out); 35 | return; 36 | } 37 | } 38 | 39 | public void setDebugLevel(int flag) { 40 | Iterator i = scripts.iterator(); 41 | while (i.hasNext()) { 42 | ScriptInstance script = (ScriptInstance)i.next(); 43 | int flags = script.getDebugFlags() | flag; 44 | script.setDebugFlags(flags); 45 | } 46 | } 47 | 48 | public boolean isReady() { 49 | synchronized (this) { 50 | return passMe != null; 51 | } 52 | } 53 | 54 | public void passObjects(Object o, Object p, Object q, Object r) { 55 | synchronized (this) { 56 | passMe[0] = o; 57 | passMe[1] = p; 58 | passMe[2] = q; 59 | passMe[3] = r; 60 | } 61 | } 62 | 63 | public Object[] getPassedObjects() { 64 | synchronized (this) { 65 | return passMe; 66 | } 67 | } 68 | 69 | public void setGlobal(String name, Scalar value) { 70 | vars.getGlobalVariables().putScalar(name, value); 71 | } 72 | 73 | public ScriptLoader getScriptLoader() { 74 | return loader; 75 | } 76 | 77 | protected RuntimeWarningWatcher watcher; 78 | 79 | public Loader(RuntimeWarningWatcher watcher) { 80 | loader = new ScriptLoader(); 81 | loader.addSpecificBridge(this); 82 | this.watcher = watcher; 83 | } 84 | 85 | public void scriptLoaded(ScriptInstance i) { 86 | i.setScriptVariables(vars); 87 | i.addWarningWatcher(watcher); 88 | scripts.add(i); 89 | 90 | /* store a hashcode in metadata so we have a unique way of marking 91 | this script and its children forks */ 92 | i.getMetadata().put("%scriptid%", i.hashCode()); 93 | } 94 | 95 | public void unload() { 96 | Iterator i = scripts.iterator(); 97 | while (i.hasNext()) { 98 | ScriptInstance temp = (ScriptInstance)i.next(); 99 | temp.setUnloaded(); 100 | } 101 | 102 | scripts = null; 103 | vars = null; 104 | shared = null; 105 | passMe = null; 106 | loader = null; 107 | } 108 | 109 | public void scriptUnloaded(ScriptInstance i) { 110 | 111 | } 112 | 113 | public Object loadInternalScript(String file, Object cache) { 114 | try { 115 | /* we cache the compiled version of internal scripts to conserve some memory */ 116 | if (cache == null) { 117 | InputStream i = this.getClass().getClassLoader().getResourceAsStream(file); 118 | if (i == null) 119 | throw new RuntimeException("resource " + file + " does not exist"); 120 | 121 | cache = loader.compileScript(file, i); 122 | } 123 | 124 | ScriptInstance script = loader.loadScript(file, (sleep.engine.Block)cache, shared); 125 | script.runScript(); 126 | } 127 | catch (IOException ex) { 128 | System.err.println("*** Could not load: " + file + " - " + ex.getMessage()); 129 | } 130 | catch (YourCodeSucksException ex) { 131 | ex.printErrors(System.out); 132 | } 133 | return cache; 134 | } 135 | 136 | public ScriptInstance loadScript(String file) throws IOException { 137 | setGlobal("$__script__", SleepUtils.getScalar(file)); 138 | ScriptInstance script = loader.loadScript(file, shared); 139 | script.runScript(); 140 | return script; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /scripts/process.sl: -------------------------------------------------------------------------------- 1 | # 2 | # Process Browser (for Meterpreter) 3 | # 4 | 5 | import table.*; 6 | 7 | import java.awt.*; 8 | import java.awt.event.*; 9 | 10 | import javax.swing.*; 11 | import javax.swing.event.*; 12 | import javax.swing.table.*; 13 | 14 | import ui.*; 15 | 16 | global('%processes'); 17 | %processes = ohash(); 18 | 19 | setMissPolicy(%processes, { return [new GenericTableModel: @("PID", "Name", "Arch", "Session", "User", "Path"), "PID", 128]; }); 20 | 21 | sub parseProcessList { 22 | if ($0 eq "end") { 23 | local('@rows $row'); 24 | [%processes[$1] clear: 128]; 25 | @rows = parseTextTable($2, @("PID", "PPID", "Name", "Arch", "Session", "User", "Path")); 26 | if (size(@rows) == 0) { 27 | # REMOVEME--this is a backwards compatability hack. 28 | @rows = parseTextTable($2, @("PID", "Name", "Arch", "Session", "User", "Path")); 29 | } 30 | 31 | # this is the format for Java meterpreter 32 | if (size(@rows) == 0) { 33 | @rows = parseTextTable($2, @("PID", "Name", "Arch", "User", "Path")); 34 | } 35 | 36 | foreach $row (@rows) { 37 | [%processes[$1] addEntry: $row]; 38 | } 39 | [%processes[$1] fireListeners]; 40 | } 41 | } 42 | 43 | %handlers["ps"] = &parseProcessList; 44 | %handlers["migrate"] = { if ($0 eq "begin") { showError("$2"); } }; 45 | 46 | sub createProcessBrowser { 47 | local('$table $model $panel $sorter'); 48 | 49 | $model = %processes[$1]; 50 | 51 | $panel = [new JPanel]; 52 | [$panel setLayout: [new BorderLayout]]; 53 | 54 | $table = [new ATable: $model]; 55 | $sorter = [new TableRowSorter: $model]; 56 | [$sorter toggleSortOrder: 0]; 57 | [$table setRowSorter: $sorter]; 58 | 59 | # setup popup hook for processes 60 | addMouseListener($table, lambda({ 61 | if ([$1 isPopupTrigger]) { 62 | local('$r'); 63 | $r = [$model getSelectedValuesFromColumns: $table, @("PID", "Name", "User", "Path")]; 64 | if (size($r) > 0) { 65 | installMenu($1, "process", $r); 66 | } 67 | } 68 | }, \$table, \$model)); 69 | 70 | # allow only one row to be selected at a time. 71 | 72 | [$sorter setComparator: 0, { 73 | return $1 <=> $2; 74 | }]; 75 | 76 | [$panel add: [new JScrollPane: $table], [BorderLayout CENTER]]; 77 | 78 | local('$a $b $bb $bbb $c $inject'); 79 | $a = [new JButton: "Kill"]; 80 | [$a addActionListener: lambda({ 81 | local('$procs $v'); 82 | $procs = [$model getSelectedValues: $table]; 83 | foreach $v ($procs) { 84 | m_cmd($m, "kill $v"); 85 | } 86 | sleep(250); 87 | m_cmd($m, "ps"); 88 | }, $m => $1, \$table, \$model)]; 89 | 90 | $b = [new JButton: "Migrate"]; 91 | [$b addActionListener: lambda({ 92 | local('$v'); 93 | $v = [$model getSelectedValue: $table]; 94 | if ($v !is $null) { 95 | m_cmd($m, "migrate $v"); 96 | } 97 | }, $m => $1, \$table, \$model)]; 98 | 99 | $inject = [new JButton: "Inject"]; 100 | [$inject addActionListener: lambda({ 101 | local('$v'); 102 | $v = [$model getSelectedValue: $table]; 103 | if ($v !is $null) { 104 | launch_dialog("Inject", "exploit", "windows/local/payload_inject", 1, $null, %(SESSION => $m, PID => $v)); 105 | } 106 | }, $m => $1, \$table, \$model)]; 107 | 108 | $bb = [new JButton: "Log Keystrokes"]; 109 | [$bb addActionListener: lambda({ 110 | local('$v'); 111 | $v = [$model getSelectedValue: $table]; 112 | if ($v !is $null) { 113 | launch_dialog("Log Keystrokes", "post", "windows/capture/keylog_recorder", 1, $null, %(SESSION => $m, MIGRATE => 1, ShowKeystrokes => 1, PID => $v, CAPTURE_TYPE => "pid")); 114 | } 115 | }, $m => $1, \$table, \$model)]; 116 | 117 | $bbb = [new JButton: "Steal Token"]; 118 | [$bbb addActionListener: lambda({ 119 | local('$v'); 120 | $v = [$model getSelectedValue: $table]; 121 | if ($v !is $null) { 122 | m_cmd_callback($m, "steal_token $v", { if ($0 eq "end") { showError(["$2" trim]); } }); 123 | } 124 | }, $m => $1, \$table, \$model)]; 125 | 126 | $c = [new JButton: "Refresh"]; 127 | [$c addActionListener: 128 | lambda({ 129 | m_cmd($m, "ps"); 130 | }, $m => $1) 131 | ]; 132 | 133 | [$panel add: center($a, $b, $bb, $inject, $bbb, $c), [BorderLayout SOUTH]]; 134 | 135 | [$frame addTab: "Processes $1", $panel, $null, "Processes " . sessionToHost($1)]; 136 | m_cmd($1, "ps"); 137 | } 138 | -------------------------------------------------------------------------------- /src/msf/Base64.java: -------------------------------------------------------------------------------- 1 | package msf; 2 | 3 | import java.io.*; 4 | 5 | /** 6 | * Simple Base64 encoding/decoding. Very loosely based on Apache Base64 class. 7 | * 8 | * @author scriptjunkie 9 | * 10 | * Taken from the MSF Java GUI Framework. 11 | */ 12 | public class Base64 { 13 | private static final char intToBase64[] = { 14 | 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 15 | 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 16 | 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 17 | 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 18 | 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 19 | 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', 20 | '8', '9', '+', '/' 21 | }; 22 | private static final byte base64ToInt[] = { 23 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 24 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 25 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26 | -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 27 | -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 28 | 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, 29 | -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 30 | 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 31 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 32 | 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 33 | 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 34 | 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 35 | 49, 50, 51 36 | }; 37 | 38 | public static String encode(String source) { 39 | try { 40 | return encode(source.getBytes("UTF-8")); 41 | } 42 | catch (Exception ex) { 43 | return encode(source.getBytes()); 44 | } 45 | } 46 | 47 | /** Converts a byte array to a bae64-encoded String. */ 48 | public static String encode(byte source[]) { 49 | int offset = 0; 50 | int num = 0; 51 | int numBytes = 0; 52 | StringBuilder sb = new StringBuilder(); 53 | for (int i = 0; i < source.length; i++) { 54 | int b = source[offset++]; 55 | if (b < 0) 56 | b += 256; 57 | num = (num << 8) + b; 58 | if (++numBytes != 3) 59 | continue; 60 | sb.append(intToBase64[num >> 18]); 61 | sb.append(intToBase64[num >> 12 & 0x3f]); 62 | sb.append(intToBase64[num >> 6 & 0x3f]); 63 | sb.append(intToBase64[num & 0x3f]); 64 | num = 0; 65 | numBytes = 0; 66 | } 67 | if (numBytes > 0) { 68 | if (numBytes == 1) { 69 | sb.append(intToBase64[num >> 2]); 70 | sb.append(intToBase64[num << 4 & 0x3f]); 71 | sb.append("=="); 72 | } else { 73 | sb.append(intToBase64[num >> 10]); 74 | sb.append(intToBase64[num >> 4 & 0x3f]); 75 | sb.append(intToBase64[num << 2 & 0x3f]); 76 | sb.append('='); 77 | } 78 | } 79 | return sb.toString(); 80 | } 81 | /** Decodes a Base64-encoded String to a byte array. */ 82 | public static byte[] decode(String source) { 83 | int num=0; 84 | int numBytes=0; 85 | int eofBytes = 0; 86 | ByteArrayOutputStream bout = new ByteArrayOutputStream(); 87 | for (int i = 0; i < source.length(); i++) { 88 | char c = source.charAt(i); 89 | if (Character.isWhitespace(c)) 90 | continue; 91 | if (c == '=') { 92 | eofBytes++; 93 | num = num << 6; 94 | switch (++numBytes) { 95 | case 1: 96 | case 2: 97 | throw new RuntimeException("Unexpected end of stream character (=)"); 98 | case 3: 99 | break; 100 | case 4: 101 | bout.write((byte) (num >> 16)); 102 | if (eofBytes == 1) 103 | bout.write((byte) (num >> 8)); 104 | break; 105 | case 5: 106 | throw new RuntimeException("Trailing garbage detected"); 107 | default: 108 | throw new IllegalStateException("Invalid value for numBytes"); 109 | } 110 | continue; 111 | } 112 | if (eofBytes > 0) 113 | throw new RuntimeException("Base64 characters after end of stream character (=) detected."); 114 | if (c >= 0 && c < Base64.base64ToInt.length) { 115 | int result = Base64.base64ToInt[c]; 116 | if (result >= 0) { 117 | num = (num << 6) + result; 118 | if (++numBytes != 4) 119 | continue; 120 | bout.write((byte) (num >> 16)); 121 | bout.write((byte) (num >> 8 & 0xff)); 122 | bout.write((byte) (num & 0xff)); 123 | num = 0; 124 | numBytes = 0; 125 | continue; 126 | } 127 | } 128 | if (!Character.isWhitespace(c)) 129 | throw new RuntimeException("Invalid Base64 character: " + (int) c); 130 | } 131 | return bout.toByteArray(); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/console/SearchPanel.java: -------------------------------------------------------------------------------- 1 | package console; 2 | 3 | import javax.swing.*; 4 | import javax.swing.event.*; 5 | import javax.swing.border.*; 6 | import javax.swing.text.*; 7 | 8 | import java.awt.*; 9 | import java.awt.event.*; 10 | 11 | import java.util.*; 12 | 13 | /** a search panel for use with a JTextComponent */ 14 | public class SearchPanel extends JPanel implements ActionListener { 15 | protected JTextField search = null; 16 | protected JLabel status = null; 17 | protected JTextComponent component = null; 18 | protected int index = 0; 19 | protected Color highlight = null; 20 | 21 | public void actionPerformed(ActionEvent event) { 22 | if (event.getActionCommand().equals(">")) { 23 | index++; 24 | scrollToIndex(); 25 | } 26 | else if (event.getActionCommand().equals("<")) { 27 | index--; 28 | scrollToIndex(); 29 | } 30 | else { 31 | searchBuffer(); 32 | scrollToIndex(); 33 | } 34 | } 35 | 36 | private void scrollToIndex() { 37 | Highlighter.Highlight highlights[] = component.getHighlighter().getHighlights(); 38 | 39 | if (highlights.length == 0) { 40 | if (search.getText().trim().length() > 0) 41 | status.setText("Phrase not found"); 42 | return; 43 | } 44 | 45 | try { 46 | if (index < 0) { 47 | index = (highlights.length - 1) - index; 48 | } 49 | 50 | int offset = index % highlights.length; 51 | 52 | status.setText((offset + 1) + " of " + highlights.length); 53 | 54 | int position = highlights[offset].getStartOffset(); 55 | Rectangle location = component.modelToView(position); 56 | component.scrollRectToVisible(location); 57 | } 58 | catch (BadLocationException ex) { 59 | //... 60 | } 61 | } 62 | 63 | private void searchBuffer() { 64 | clear(); 65 | 66 | String searchstr = search.getText().trim(); 67 | 68 | if (searchstr.length() == 0) 69 | return; 70 | 71 | Highlighter.HighlightPainter painter = new DefaultHighlighter.DefaultHighlightPainter( highlight ); 72 | 73 | try { 74 | String text = component.getText(); 75 | 76 | /* another windows work-around... */ 77 | if ((System.getProperty("os.name") + "").indexOf("Windows") != -1) { 78 | text = text.replaceAll("\r\n", "\n"); 79 | } 80 | 81 | int lastIndex = -1; 82 | while ((lastIndex = text.indexOf(searchstr, lastIndex + 1)) != -1) { 83 | component.getHighlighter().addHighlight( 84 | lastIndex, 85 | lastIndex + searchstr.length(), 86 | painter); 87 | } 88 | } 89 | catch (Exception ex) { 90 | // ... 91 | } 92 | } 93 | 94 | static void removeBorderFromButton(JButton button) { 95 | button.setOpaque(false); 96 | button.setContentAreaFilled(false); 97 | button.setBorder(new EmptyBorder(2, 2, 2, 2)); 98 | } 99 | 100 | public void requestFocus() { 101 | search.requestFocus(); 102 | } 103 | 104 | public void clear() { 105 | component.getHighlighter().removeAllHighlights(); 106 | index = 0; 107 | status.setText(""); 108 | } 109 | 110 | public SearchPanel(JTextComponent component, Color highlight) { 111 | this.component = component; 112 | this.highlight = highlight; 113 | 114 | setLayout(new BorderLayout()); 115 | setBorder(new EmptyBorder(1, 1, 1, 1)); 116 | 117 | /* init the buttons */ 118 | 119 | JButton previous = new JButton("<"); 120 | previous.setActionCommand("<"); 121 | 122 | JButton next = new JButton(">"); 123 | next.setActionCommand(">"); 124 | 125 | removeBorderFromButton(previous); 126 | removeBorderFromButton(next); 127 | 128 | previous.addActionListener(this); 129 | next.addActionListener(this); 130 | 131 | JPanel buttons = new JPanel(); 132 | buttons.setLayout(new GridLayout(1, 2)); 133 | 134 | buttons.add(previous); 135 | buttons.add(next); 136 | 137 | /* init the search field */ 138 | 139 | search = new JTextField(15); 140 | search.addActionListener(this); 141 | 142 | add(search, BorderLayout.WEST); 143 | 144 | /* holder */ 145 | 146 | JPanel holder = new JPanel(); 147 | holder.setLayout(new FlowLayout()); 148 | 149 | holder.add(new JLabel("Find: ")); 150 | holder.add(search); 151 | holder.add(buttons); 152 | 153 | add(holder, BorderLayout.WEST); 154 | 155 | /* label for count information */ 156 | 157 | status = new JLabel(""); 158 | add(status, BorderLayout.CENTER); 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /scripts/screenshot.sl: -------------------------------------------------------------------------------- 1 | # 2 | # Screenshot viewer... whee?!? 3 | # 4 | import java.awt.*; 5 | import java.awt.event.*; 6 | 7 | import javax.swing.*; 8 | import javax.swing.event.*; 9 | import javax.imageio.*; 10 | import java.io.File; 11 | 12 | import ui.*; 13 | 14 | import armitage.*; 15 | 16 | global('%screenshots %webcams %refreshcmd'); 17 | %screenshots = ohash(); 18 | %webcams = ohash(); 19 | 20 | sub image_viewer { 21 | local('$panel $viewer $buttons $refresh $watch'); 22 | 23 | $panel = [new JPanel]; 24 | [$panel setLayout: [new BorderLayout]]; 25 | 26 | $viewer = [new ZoomableImage]; 27 | [$panel add: [new JScrollPane: $viewer], [BorderLayout CENTER]]; 28 | 29 | $buttons = [new JPanel]; 30 | [$buttons setLayout: [new FlowLayout: [FlowLayout CENTER]]]; 31 | $refresh = [new JButton: "Refresh"]; 32 | [$refresh addActionListener: lambda({ 33 | m_cmd($sid, %refreshcmd[$title][$sid]); 34 | }, $sid => $2, \$command, \$title)]; 35 | [$buttons add: $refresh]; 36 | 37 | $watch = [new JButton: "Watch (10s)"]; 38 | [$watch addActionListener: lambda({ 39 | local('$timer'); 40 | $timer = [new SimpleTimer: 10000]; 41 | [$timer setRunnable: lambda({ 42 | if ($sid !in $container) { 43 | [$timer stop]; 44 | } 45 | else { 46 | m_cmd($sid, %refreshcmd[$title][$sid]); 47 | } 48 | }, \$sid, \$timer, \$container, \$title)]; 49 | }, $sid => $2, \$container, \$title)]; 50 | [$buttons add: $watch]; 51 | [$panel add: $buttons, [BorderLayout SOUTH]]; 52 | 53 | [$frame addTab: "$title $2", $panel, lambda({ $container[$key] = $null; size($container); }, $key => $2, \$container), "$title " . sessionToHost($2)]; 54 | return $viewer; 55 | } 56 | 57 | sub update_viewer { 58 | if ($0 eq "execute") { 59 | %refreshcmd[$title][$1] = $2; 60 | } 61 | else if ($0 eq "update" && "*Operation failed*" iswm $2) { 62 | showError($2); 63 | } 64 | else if ($0 eq "update" && $2 ismatch "$type saved to: (.*?)") { 65 | local('$file'); 66 | ($file) = matched(); 67 | 68 | [lambda({ 69 | local('$image $panel'); 70 | 71 | # we're collaborating, so download the file please... 72 | if ($client !is $mclient) { 73 | downloadFile($file, $null, $this); 74 | yield; 75 | $file = getFileProper(cwd(), $1); 76 | } 77 | 78 | logFile($file, sessionToHost($sid), $type); 79 | $image = [ImageIO read: [new File: $file]]; 80 | 81 | fire_event_async("user_" . lc(strrep($type, " ", "_")), $sid, $file); 82 | 83 | dispatchEvent(lambda({ 84 | [$container[$id] setIcon: [new ImageIcon: $image]]; 85 | }, \$container, \$image, $id => $sid)); 86 | 87 | if (-isFile $file && "*.jpeg" iswm $file) { 88 | deleteOnExit($file); 89 | } 90 | }, \$file, $sid => $1, \$type, \$title, \$container)]; 91 | } 92 | } 93 | 94 | setMissPolicy(%screenshots, lambda(&image_viewer, $title => "Screenshot", $container => %screenshots)); 95 | setMissPolicy(%webcams, lambda(&image_viewer, $title => "Webcam", $container => %webcams)); 96 | 97 | %handlers["screenshot"] = lambda(&update_viewer, $type => "Screenshot", $title => "Screenshot", $container => %screenshots); 98 | %handlers["webcam_snap"] = lambda(&update_viewer, $type => "Webcam shot", $title => "Webcam", $container => %webcams); 99 | 100 | sub createScreenshotViewer { 101 | return lambda({ 102 | m_cmd($sid, "screenshot -v false"); 103 | }, $sid => $1); 104 | } 105 | 106 | sub createWebcamViewer { 107 | return lambda({ 108 | m_cmd_callback($sid, "webcam_list", { 109 | if ($0 eq "end") { 110 | local('$cams $cam'); 111 | $cams = map({ return %(Camera => $1); }, split("\n", ["$2" trim])); 112 | 113 | # get rid of non-camera entries please 114 | foreach $cam ($cams) { 115 | if ($cam['Camera'] !ismatch '\d+: .*') { 116 | remove(); 117 | } 118 | } 119 | 120 | # no camera... do nothing. 121 | if (size($cams) == 0) { 122 | showError("Host does not have a camera"); 123 | return; 124 | } 125 | 126 | quickListDialog("Cameras", "Take Picture", @("Camera", "Camera"), $cams, $width => 320, $height => 200, lambda({ 127 | if ($1 !is $null) { 128 | local('$index'); 129 | ($index) = split(': ', $1); 130 | m_cmd($sid, "webcam_snap -i $index -v false"); 131 | } 132 | }, $sid => $1)); 133 | } 134 | }); 135 | }, $sid => $1); 136 | } 137 | -------------------------------------------------------------------------------- /scripts/services.sl: -------------------------------------------------------------------------------- 1 | # 2 | # Process Browser (for Meterpreter) 3 | # 4 | 5 | import table.*; 6 | 7 | import java.awt.*; 8 | import java.awt.event.*; 9 | 10 | import javax.swing.*; 11 | import javax.swing.event.*; 12 | import javax.swing.table.*; 13 | 14 | import ui.*; 15 | 16 | sub updateServiceModel { 17 | local('$port $row $host'); 18 | [$model clear: 256]; 19 | foreach $host ($hosts) { 20 | if ($host in %hosts && 'services' in %hosts[$host]) { 21 | foreach $port => $row (%hosts[$host]['services']) { 22 | [$model addEntry: $row]; 23 | } 24 | } 25 | } 26 | [$model fireListeners]; 27 | } 28 | 29 | sub createServiceBrowser { 30 | local('$table $model $panel $refresh $sorter $host $copy $info $remove'); 31 | 32 | $model = [new GenericTableModel: @("host", "name", "port", "proto", "info"), "host", 16]; 33 | 34 | $panel = [new JPanel]; 35 | [$panel setLayout: [new BorderLayout]]; 36 | 37 | $table = [new ATable: $model]; 38 | $sorter = [new TableRowSorter: $model]; 39 | [$sorter toggleSortOrder: 2]; 40 | [$table setRowSorter: $sorter]; 41 | 42 | $info = lambda({ 43 | [lambda({ 44 | local('$info $val'); 45 | $info = [$model getSelectedValueFromColumn: $table, "info"]; 46 | ask_async("Set info to", $info, $this); 47 | yield; 48 | 49 | # updating service info 50 | foreach $val ([$model getSelectedValuesFromColumns: $table, @("id")]) { 51 | call_async($mclient, "db.report_service", %(id => $val['id'], info => $1)); 52 | } 53 | 54 | local('$services'); 55 | call_async_callback($mclient, "db.services", $this); 56 | yield; 57 | $services = convertAll($1); 58 | if ('services' in $services) { 59 | _refreshServices($services['services']); 60 | updateServiceModel(\$hosts, \$model); 61 | } 62 | }, \$model, \$table, \$hosts)]; 63 | }, \$model, \$table, $hosts => $1); 64 | 65 | $remove = lambda({ 66 | local('$val'); 67 | 68 | # delete services 69 | foreach $val ([$model getSelectedValuesFromColumns: $table, @("id")]) { 70 | call_async($mclient, "db.remove_service", %(id => $val['id'])); 71 | } 72 | 73 | # refresh our table 74 | local('$services'); 75 | call_async_callback($mclient, "db.services", $this); 76 | yield; 77 | $services = convertAll($1); 78 | if ('services' in $services) { 79 | _refreshServices($services['services']); 80 | updateServiceModel(\$hosts, \$model); 81 | } 82 | }, \$model, \$table, $hosts => $1); 83 | 84 | addMouseListener($table, lambda({ 85 | if ([$1 isPopupTrigger]) { 86 | local('$popup $hosts %r $val $m'); 87 | $popup = [new JPopupMenu]; 88 | 89 | %r = %(); 90 | foreach $val ([$model getSelectedValues: $table]) { 91 | %r[$val] = 1; 92 | } 93 | $hosts = keys(%r); 94 | 95 | if (size($hosts) > 0) { 96 | host_selected_items($popup, $hosts); 97 | [$popup addSeparator]; 98 | #$m = menu($popup, "Service", 'S'); 99 | item($popup, "Service Info", 'I', $info); 100 | #item($m, "Remove", 'R', $remove); 101 | [$popup show: [$1 getSource], [$1 getX], [$1 getY]]; 102 | } 103 | } 104 | }, \$table, \$model, \$info, \$remove)); 105 | 106 | [[$table getColumn: "info"] setPreferredWidth: 300]; 107 | [[$table getColumn: "host"] setPreferredWidth: 125]; 108 | [$sorter setComparator: 2, { return $1 <=> $2; }]; 109 | [$sorter setComparator: 0, &compareHosts]; 110 | 111 | [$panel add: [new JScrollPane: $table], [BorderLayout CENTER]]; 112 | 113 | $refresh = [new JButton: "Refresh"]; 114 | [$refresh addActionListener: lambda({ 115 | [lambda({ 116 | local('$services'); 117 | call_async_callback($mclient, "db.services", $this); 118 | yield; 119 | $services = convertAll($1); 120 | if ('services' in $services) { 121 | _refreshServices($services['services']); 122 | updateServiceModel(\$hosts, \$model); 123 | } 124 | }, \$hosts, \$model)]; 125 | }, \$model, $hosts => $1)]; 126 | 127 | $copy = [new JButton: "Copy"]; 128 | [$copy addActionListener: lambda({ 129 | local('%r $val $hosts'); 130 | %r = %(); 131 | foreach $val ([$model getSelectedValues: $table]) { 132 | %r[$val] = 1; 133 | } 134 | $hosts = keys(%r); 135 | setClipboard(join(", ", $hosts)); 136 | showError("Copied selected hosts to clipboard"); 137 | }, \$model, \$table)]; 138 | 139 | updateServiceModel($hosts => $1, \$model); 140 | 141 | [$panel add: center($refresh, $copy), [BorderLayout SOUTH]]; 142 | [$frame addTab: "Services", $panel, $null]; 143 | } 144 | -------------------------------------------------------------------------------- /scripts-cortana/cortanadb.sl: -------------------------------------------------------------------------------- 1 | # This file is part of a stand-alone script environment that connects Cortana to 2 | # Metasploit, Armitage, and a postgresql database. It's a little complicated and 3 | # twisty turny in here. Here are the rough steps: 4 | # 5 | # 1. Connect to the database (&main) 6 | # 2. setup the default reverse handler (&setupHandlers) 7 | # 3. check for the collaboration server (&checkForCollaborationServer) 8 | # 4. setup collaboration (&setup_collaboration) 9 | # 5. call armitage.skip to push the event log pointer to the very end. 10 | # 6. send a flag back to the Cortana load that we're ready ([$loader passObject: ...]) 11 | # 12 | # If any of these steps fails, Cortana will exit with a hopefully helpful error 13 | # message. 14 | 15 | debug(7 | 34); 16 | 17 | import msf.*; 18 | import armitage.*; 19 | import console.*; 20 | import ssl.*; 21 | 22 | # create an RPC client for talking to the deconfliction server. 23 | sub c_client { 24 | # run this thing in its own thread to avoid really stupid deadlock situations 25 | local('$handle $socket'); 26 | $socket = [new SecureSocket: $1, int($2), $null]; 27 | [$socket authenticate: $4]; # doing my job to auth to server 28 | $handle = [$socket client]; 29 | return wait(fork({ 30 | local('$client'); 31 | $client = newInstance(^RpcConnection, lambda({ 32 | writeObject($handle, @_); 33 | [[$handle getOutputStream] flush]; 34 | return readObject($handle); 35 | }, \$handle)); 36 | return [new RpcAsync: $client]; 37 | }, \$handle)); 38 | } 39 | 40 | # this function sets up a default meterpreter reverse handler on a random port. Better tha 41 | # requiring the user to connect a client to make this happen. This function also fires the 42 | # loader ready function which tells the script loader that this script is done processing 43 | # and this Cortana container may continue loading and executing other scripts. 44 | sub setupHandlers { 45 | find_job("Exploit: multi/handler", { 46 | if ($1 == -1) { 47 | # set LPORT for the user... 48 | local('$c'); 49 | $c = call($client, "console.allocate")['id']; 50 | call($client, "console.write", $c, "setg LPORT " . randomPort() . "\n"); 51 | call($client, "console.release", $c); 52 | 53 | # setup a handler for meterpreter 54 | call($client, "module.execute", "exploit", "multi/handler", %( 55 | PAYLOAD => "windows/meterpreter/reverse_tcp", 56 | LHOST => "0.0.0.0", 57 | ExitOnSession => "false" 58 | )); 59 | } 60 | }); 61 | } 62 | 63 | sub main { 64 | global('$client $mclient'); 65 | local('%r $exception $lhost $temp $c $version'); 66 | 67 | setField(^msf.MeterpreterSession, DEFAULT_WAIT => 20000L); 68 | 69 | try { 70 | # connect our first thread... 71 | $mclient = c_client($host, $port, $user, $pass); 72 | 73 | # connect our second thread with an empty nickname 74 | $client = c_client($host, $port, $user, $pass); 75 | } 76 | catch $exception { 77 | println("Could not connect to $host $+ : $+ $port ( $+ $exception $+ )"); 78 | [System exit: 0]; 79 | } 80 | 81 | # setup first thread... 82 | %r = call($mclient, "armitage.validate", $user, $pass, $nick, "armitage", 140921); 83 | if (%r["error"] eq "1") { 84 | println(%r['message']); 85 | [System exit: 0]; 86 | } 87 | 88 | # setup second thread. 89 | %r = call($client, "armitage.validate", $user, $pass, $null, "armitage", 140921); 90 | 91 | # resolve lhost.. 92 | $c = call($client, "console.allocate")['id']; 93 | call($client, "console.write", $c, "setg LHOST\n"); 94 | while ($lhost eq "") { 95 | $temp = call($client, "console.read", $c)['data']; 96 | if (["$temp" startsWith: "LHOST => "]) { 97 | $lhost = substr(["$temp" trim], 9); 98 | } 99 | else { 100 | # this shouldn't happen because having LHOST set is a precondition 101 | # for Cortana to connect to a team server. 102 | sleep(1000); 103 | } 104 | } 105 | call($client, "console.release", $c); 106 | 107 | # 108 | local('$rep $major $minor $update'); 109 | $rep = call($client, "core.version"); 110 | 111 | if ($rep['version'] ismatch '(\d+)\.(\d+)\.(.*?)') { 112 | ($major, $minor, $update) = matched(); 113 | $version = ($major * 10000) + ($minor * 100) + $update; 114 | } 115 | 116 | # pass some objects back yo. 117 | [$loader passObjects: $client, $mclient, $lhost, $version]; 118 | 119 | # don't make previous messages available... 120 | call($mclient, "armitage.skip"); 121 | 122 | # do some other setup stuff... 123 | setupBaseDirectory(); 124 | setupHandlers(); 125 | } 126 | 127 | invoke(&main); 128 | --------------------------------------------------------------------------------