Merge remote branch 'rsmudge/armitage'
commit
8d6289d8d6
Binary file not shown.
Binary file not shown.
|
@ -1,6 +1,29 @@
|
|||
Armitage Changelog
|
||||
==================
|
||||
|
||||
26 Nov 12 (tested against msf 16114)
|
||||
---------
|
||||
- Windows command shell tab is now friendlier to commands that prompt
|
||||
for input (e.g., time command)
|
||||
- [host] -> Meterpreter -> Access -> Escalate Privileges now shows all
|
||||
the framework's new exploit/windows/local modules too
|
||||
- [host] -> Shell -> Post Modules now shows the framework's unix/local
|
||||
and exploit/linux/local modules
|
||||
- Added Ctrl+I shortcut. Lets you choose a session to interact with.
|
||||
- Added Steal Token button to Processes dialog.
|
||||
- Armitage now asks Metasploit for a non-expiring authentication token.
|
||||
This will prevent Armitage from losing its access to msfrpcd when you
|
||||
put your computer to sleep or pause the VM running Metasploit.
|
||||
- add_user and add_[local]group_user now show all of their output when
|
||||
the -h flag is used to operate on a remote host.
|
||||
- added a Delete menu to creds table. Right-click a cred to delete it
|
||||
|
||||
Cortana Updates (for scripters)
|
||||
--------
|
||||
- aliased &data_delete to &data_clear to match the documentation.
|
||||
- &file_get, &loot_get, and &file_content no longer delete the remote
|
||||
file when connected to a teamserver.
|
||||
|
||||
16 Oct 12 (tested against msf 15972)
|
||||
---------
|
||||
- Added port 5985 to MSF Scans list.
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<center><h1>Armitage 1.44</h1></center>
|
||||
|
||||
<p>An attack management tool for Metasploit®
|
||||
<br />Release: 16 Oct 12</p>
|
||||
<br />Release: 26 Nov 12</p>
|
||||
<br />
|
||||
<p>Developed by:</p>
|
||||
|
||||
|
|
|
@ -550,6 +550,11 @@ sub data_delete {
|
|||
call("db.key_clear", $1);
|
||||
}
|
||||
|
||||
# data_clear('key') -- clears all data associated with the specified key
|
||||
sub data_clear {
|
||||
data_delete($1);
|
||||
}
|
||||
|
||||
# data_add('key', $object) -- appends value into the database...
|
||||
sub data_add {
|
||||
local('$buffer $data');
|
||||
|
@ -860,7 +865,7 @@ sub file_content {
|
|||
}
|
||||
else {
|
||||
local('%r');
|
||||
%r = call("armitage.download", $1);
|
||||
%r = call("armitage.download_nodelete", $1);
|
||||
return %r['data'];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -623,6 +623,34 @@ sub host_attack_items {
|
|||
}
|
||||
}
|
||||
|
||||
sub chooseSession {
|
||||
local('@data $sid $data $host $hdata $temp $tablef');
|
||||
|
||||
# obtain a list of sessions
|
||||
foreach $host (keys(%hosts)) {
|
||||
foreach $sid => $data (getSessions($host)) {
|
||||
$temp = copy($data);
|
||||
$temp['sid'] = $sid;
|
||||
push(@data, $temp);
|
||||
}
|
||||
}
|
||||
|
||||
# sort the session data
|
||||
@data = sort({ return $1['sid'] <=> $2['sid']; }, @data);
|
||||
|
||||
# update the table widths
|
||||
$tablef = {
|
||||
[[$1 getColumn: "sid"] setPreferredWidth: 100];
|
||||
[[$1 getColumn: "session_host"] setPreferredWidth: 300];
|
||||
[[$1 getColumn: "info"] setPreferredWidth: 1024];
|
||||
};
|
||||
|
||||
# let the user choose a session
|
||||
quickListDialog("Choose a session", "Select", @("sid", "sid", "session_host", "info"), @data, $width => 640, $height => 240, lambda({
|
||||
[$call : $1];
|
||||
}, $call => $4), \$tablef);
|
||||
}
|
||||
|
||||
sub addFileListener {
|
||||
local('$table $model $actions');
|
||||
($table, $model, $actions) = @_;
|
||||
|
@ -652,33 +680,7 @@ sub addFileListener {
|
|||
$actions["WORDLIST"] = $actions["*FILE*"];
|
||||
|
||||
# set up an action to choose a session
|
||||
$actions["SESSION"] = {
|
||||
local('@data $sid $data $host $hdata $temp $tablef');
|
||||
|
||||
# obtain a list of sessions
|
||||
foreach $host (keys(%hosts)) {
|
||||
foreach $sid => $data (getSessions($host)) {
|
||||
$temp = copy($data);
|
||||
$temp['sid'] = $sid;
|
||||
push(@data, $temp);
|
||||
}
|
||||
}
|
||||
|
||||
# sort the session data
|
||||
@data = sort({ return $1['sid'] <=> $2['sid']; }, @data);
|
||||
|
||||
# update the table widths
|
||||
$tablef = {
|
||||
[[$1 getColumn: "sid"] setPreferredWidth: 100];
|
||||
[[$1 getColumn: "session_host"] setPreferredWidth: 300];
|
||||
[[$1 getColumn: "info"] setPreferredWidth: 1024];
|
||||
};
|
||||
|
||||
# let the user choose a session
|
||||
quickListDialog("Choose a session", "Select", @("sid", "sid", "session_host", "info"), @data, $width => 640, $height => 240, lambda({
|
||||
[$call : $1];
|
||||
}, $call => $4), \$tablef);
|
||||
};
|
||||
$actions["SESSION"] = lambda(&chooseSession);
|
||||
|
||||
# set up an action to pop up a file chooser for different file type values.
|
||||
$actions["RHOST"] = {
|
||||
|
|
|
@ -239,6 +239,23 @@ sub init_menus {
|
|||
dynmenu($top, "Help", 'H', &help_items);
|
||||
|
||||
# setup some global keyboard shortcuts...
|
||||
[$frame bindKey: "Ctrl+I", {
|
||||
thread({
|
||||
chooseSession($null, $null, $null, {
|
||||
local('$session');
|
||||
$session = sessionData($1);
|
||||
if ($session is $null) {
|
||||
showError("Session $1 does not exist");
|
||||
}
|
||||
else if ($session['desc'] eq "Meterpreter") {
|
||||
createMeterpreterTab($1);
|
||||
}
|
||||
else {
|
||||
createShellSessionTab(\$session, $sid => $1);
|
||||
}
|
||||
});
|
||||
});
|
||||
}];
|
||||
[$frame bindKey: "Ctrl+N", { thread(&createConsoleTab); }];
|
||||
[$frame bindKey: "Ctrl+W", { [$frame openActiveTab]; }];
|
||||
[$frame bindKey: "Ctrl+D", { [$frame closeActiveTab]; }];
|
||||
|
|
|
@ -104,13 +104,16 @@ sub parseMeterpreter {
|
|||
}
|
||||
|
||||
sub interpretMeterpreterCommand {
|
||||
if ([$1 getActionCommand] eq "shell") {
|
||||
local('$c');
|
||||
$c = [lc([$1 getActionCommand] . "") trim];
|
||||
|
||||
if ($c eq "shell") {
|
||||
createShellTab($sid);
|
||||
}
|
||||
else if ([$1 getActionCommand] eq "screenshot") {
|
||||
else if ($c eq "screenshot") {
|
||||
[createScreenshotViewer($sid)];
|
||||
}
|
||||
else if ([$1 getActionCommand] eq "webcam_snap") {
|
||||
else if ($c eq "webcam_snap") {
|
||||
[createWebcamViewer($sid)];
|
||||
}
|
||||
}
|
||||
|
@ -168,7 +171,9 @@ sub showMeterpreterMenu {
|
|||
}, $sid => "$sid"));
|
||||
|
||||
item($j, "Escalate Privileges", 'E', lambda({
|
||||
showPostModules($sid, "*escalate*");
|
||||
showPostModules($sid, "*escalate*",
|
||||
ohash(exploit => buildTree(filter({ return iff("*windows/local/*" iswm $1, $1); }, @exploits)))
|
||||
);
|
||||
}, $sid => "$sid"));
|
||||
|
||||
item($j, "Steal Token" , "S", lambda({
|
||||
|
|
|
@ -251,7 +251,7 @@ sub showExploitModules {
|
|||
# shows the post modules compatible with a session... for this to work, the
|
||||
# code that creates the module browser must call: let(&showPostModules, $tree => ..., $search => ...)
|
||||
sub showPostModules {
|
||||
local('@allowed $2');
|
||||
local('@allowed $2 $3');
|
||||
@allowed = getOS(sessionToOS($1));
|
||||
fork({
|
||||
local('$modules %list $model');
|
||||
|
@ -270,7 +270,13 @@ sub showPostModules {
|
|||
$modules = filter(lambda({ return iff($filter iswm $1, $1); }, \$filter), $modules);
|
||||
}
|
||||
|
||||
%list = ohash(post => buildTree($modules));
|
||||
if ($base is $null) {
|
||||
%list = ohash(post => buildTree($modules));
|
||||
}
|
||||
else {
|
||||
%list = $base;
|
||||
%list['post'] = buildTree($modules);
|
||||
}
|
||||
$model = treeNodes($null, %list);
|
||||
|
||||
dispatchEvent(lambda({
|
||||
|
@ -282,7 +288,7 @@ sub showPostModules {
|
|||
}
|
||||
[$search setText: ""];
|
||||
}, \$search, \$tree, \$model));
|
||||
}, \$tree, \$search, $sid => $1, \$client, \@allowed, $filter => $2);
|
||||
}, \$tree, \$search, $sid => $1, \$client, \@allowed, $filter => $2, $base => $3);
|
||||
}
|
||||
|
||||
sub createModuleBrowserTab {
|
||||
|
|
|
@ -96,6 +96,33 @@ sub createCredentialsTab {
|
|||
($dialog, $table, $model) = show_hashes("", 320);
|
||||
[$dialog removeAll];
|
||||
|
||||
addMouseListener($table, lambda({
|
||||
if ([$1 isPopupTrigger]) {
|
||||
local('$popup $entries');
|
||||
$popup = [new JPopupMenu];
|
||||
$entries = [$model getSelectedValuesFromColumns: $table, @("user", "pass", "host")];
|
||||
item($popup, "Delete", 'D', lambda({
|
||||
local('$queue $entry $user $pass $host');
|
||||
$queue = [new armitage.ConsoleQueue: $client];
|
||||
foreach $entry ($entries) {
|
||||
($user, $pass, $host) = $entry;
|
||||
[$queue addCommand: $null, "creds -d $host -u $user -P $pass"];
|
||||
}
|
||||
|
||||
[$queue addCommand: "x", "creds -h"];
|
||||
|
||||
[$queue addListener: lambda({
|
||||
[$queue stop];
|
||||
refreshCredsTable($model, $null);
|
||||
}, \$model, \$queue)];
|
||||
|
||||
[$queue start];
|
||||
[$queue stop];
|
||||
}, \$table, \$model, \$entries));
|
||||
[$popup show: [$1 getSource], [$1 getX], [$1 getY]];
|
||||
}
|
||||
}, \$table, \$model));
|
||||
|
||||
$panel = [new JPanel];
|
||||
[$panel setLayout: [new BorderLayout]];
|
||||
[$panel add: [new JScrollPane: $table], [BorderLayout CENTER]];
|
||||
|
|
|
@ -75,7 +75,7 @@ sub createProcessBrowser {
|
|||
|
||||
[$panel add: [new JScrollPane: $table], [BorderLayout CENTER]];
|
||||
|
||||
local('$a $b $bb $c');
|
||||
local('$a $b $bb $bbb $c');
|
||||
$a = [new JButton: "Kill"];
|
||||
[$a addActionListener: lambda({
|
||||
local('$procs $v');
|
||||
|
@ -105,6 +105,15 @@ sub createProcessBrowser {
|
|||
}
|
||||
}, $m => $1, \$table, \$model)];
|
||||
|
||||
$bbb = [new JButton: "Steal Token"];
|
||||
[$bbb addActionListener: lambda({
|
||||
local('$v');
|
||||
$v = [$model getSelectedValue: $table];
|
||||
if ($v !is $null) {
|
||||
m_cmd_callback($m, "steal_token $v", { if ($0 eq "end") { showError(["$2" trim]); } });
|
||||
}
|
||||
}, $m => $1, \$table, \$model)];
|
||||
|
||||
$c = [new JButton: "Refresh"];
|
||||
[$c addActionListener:
|
||||
lambda({
|
||||
|
@ -112,7 +121,7 @@ sub createProcessBrowser {
|
|||
}, $m => $1)
|
||||
];
|
||||
|
||||
[$panel add: center($a, $b, $bb, $c), [BorderLayout SOUTH]];
|
||||
[$panel add: center($a, $b, $bb, $bbb, $c), [BorderLayout SOUTH]];
|
||||
|
||||
[$frame addTab: "Processes $1", $panel, $null, "Processes " . sessionToHost($1)];
|
||||
m_cmd($1, "ps");
|
||||
|
|
|
@ -163,6 +163,10 @@ global('%shells $ashell $achannel %maxq %wait');
|
|||
# make our shell heuristic tolerant of prompts like this.
|
||||
%wait[$achannel] = $null;
|
||||
}
|
||||
else if (size($v) > 0 && $v[-1] ismatch '.*?:') {
|
||||
# make our shell heuristic tolerant of more prompts... this is from the time command
|
||||
%wait[$achannel] = $null;
|
||||
}
|
||||
else if (size($v) > 0 && $v[-1] !ismatch '(.*?):\\\\.*?\\>') {
|
||||
m_cmd($1, "read $achannel");
|
||||
}
|
||||
|
@ -254,7 +258,14 @@ sub showShellMenu {
|
|||
}
|
||||
|
||||
item($1, "Post Modules", 'P', lambda({
|
||||
showPostModules($sid);
|
||||
if ("*Windows*" iswm sessionToOS($sid)) {
|
||||
showPostModules($sid);
|
||||
}
|
||||
else {
|
||||
showPostModules($sid, "*",
|
||||
ohash(exploit => buildTree(filter({ return iff("*u*x/local/*" iswm $1, $1); }, @exploits)))
|
||||
);
|
||||
}
|
||||
}, \$sid));
|
||||
|
||||
separator($1);
|
||||
|
|
|
@ -164,6 +164,21 @@ public class MeterpreterSession implements Runnable {
|
|||
readUntilSuccessful(c, false);
|
||||
return;
|
||||
}
|
||||
else if (c.text.startsWith("add_user") && !teammode) {
|
||||
/* when -h [host] is specified, attempts to add a user on another
|
||||
host. In this case, output is split into multiple chunks.
|
||||
This applies to add_localgroup_user and add_group_user too. */
|
||||
readUntilSuccessful(c, false);
|
||||
return;
|
||||
}
|
||||
else if (c.text.startsWith("add_localgroup_user") && !teammode) {
|
||||
readUntilSuccessful(c, false);
|
||||
return;
|
||||
}
|
||||
else if (c.text.startsWith("add_group_user") && !teammode) {
|
||||
readUntilSuccessful(c, false);
|
||||
return;
|
||||
}
|
||||
|
||||
//System.err.println("(" + session + ") latency: " + (System.currentTimeMillis() - c.start) + " -- " + c.text);
|
||||
|
||||
|
|
|
@ -57,6 +57,13 @@ public class MsgRpcImpl extends RpcConnectionImpl {
|
|||
/* login to msf server */
|
||||
Object[] params = new Object[]{ username, password };
|
||||
Map results = exec("auth.login",params);
|
||||
|
||||
/* save the temp token (lasts for 5 minutes of inactivity) */
|
||||
rpcToken = results.get("token").toString();
|
||||
|
||||
/* generate a non-expiring token and use that */
|
||||
params = new Object[]{ rpcToken };
|
||||
results = exec("auth.token_generate", params);
|
||||
rpcToken = results.get("token").toString();
|
||||
}
|
||||
|
||||
|
|
|
@ -33,10 +33,6 @@ public class KeyBindings implements KeyEventDispatcher {
|
|||
}
|
||||
|
||||
public boolean dispatchKeyEvent(KeyEvent ev) {
|
||||
if (ev.getID() != KeyEvent.KEY_PRESSED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
StringBuffer description = new StringBuffer();
|
||||
if (ev.getModifiers() != 0) {
|
||||
description.append(getKeyModifiers(ev));
|
||||
|
@ -46,9 +42,14 @@ public class KeyBindings implements KeyEventDispatcher {
|
|||
|
||||
synchronized (this) {
|
||||
if (bindings.containsKey(description.toString())) {
|
||||
SwingUtilities.invokeLater(new ExecuteBinding(description.toString(), (KeyHandler)bindings.get(description.toString())));
|
||||
ev.consume();
|
||||
return true;
|
||||
if (ev.getID() != KeyEvent.KEY_PRESSED) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
SwingUtilities.invokeLater(new ExecuteBinding(description.toString(), (KeyHandler)bindings.get(description.toString())));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,29 @@
|
|||
Armitage Changelog
|
||||
==================
|
||||
|
||||
26 Nov 12 (tested against msf 16114)
|
||||
---------
|
||||
- Windows command shell tab is now friendlier to commands that prompt
|
||||
for input (e.g., time command)
|
||||
- [host] -> Meterpreter -> Access -> Escalate Privileges now shows all
|
||||
the framework's new exploit/windows/local modules too
|
||||
- [host] -> Shell -> Post Modules now shows the framework's unix/local
|
||||
and exploit/linux/local modules
|
||||
- Added Ctrl+I shortcut. Lets you choose a session to interact with.
|
||||
- Added Steal Token button to Processes dialog.
|
||||
- Armitage now asks Metasploit for a non-expiring authentication token.
|
||||
This will prevent Armitage from losing its access to msfrpcd when you
|
||||
put your computer to sleep or pause the VM running Metasploit.
|
||||
- add_user and add_[local]group_user now show all of their output when
|
||||
the -h flag is used to operate on a remote host.
|
||||
- added a Delete menu to creds table. Right-click a cred to delete it
|
||||
|
||||
Cortana Updates (for scripters)
|
||||
--------
|
||||
- aliased &data_delete to &data_clear to match the documentation.
|
||||
- &file_get, &loot_get, and &file_content no longer delete the remote
|
||||
file when connected to a teamserver.
|
||||
|
||||
16 Oct 12 (tested against msf 15972)
|
||||
---------
|
||||
- Added port 5985 to MSF Scans list.
|
||||
|
|
Loading…
Reference in New Issue