Run meterpreter GUI commands in background to not interfere with active shell or other channel interaction.

Also simplify calling commands in file browser and process viewer.



git-svn-id: file:///home/svn/framework3/trunk@10929 4d416f70-5f16-0410-b530-b9f4589650da
This commit is contained in:
Matt Weeks 2010-11-06 16:51:48 +00:00
parent b3713f9d46
commit bc983ea52c
6 changed files with 88 additions and 124 deletions

Binary file not shown.

View File

@ -79,49 +79,48 @@ public class InteractWindow extends MsfFrame {
this.rpcConn = rpcConn;
this.session = session;
sid = session.get("id");
if(type.equals("console")){ //console stuff
if(type.equals("console")) //console stuff
cmdPrefix = "console.";
inputField.setFocusTraversalKeysEnabled(false);
inputField.addKeyListener(new KeyListener(){
public void keyTyped(KeyEvent ke) {
if(ke.getKeyChar() == '\t'){
try{
Map res = (Map)rpcConn.execute("console.tabs", sid,inputField.getText());
List tabs = (List)res.get("tabs");
//one option: use it
if(tabs.size() == 1){
inputField.setText(tabs.get(0).toString());
//more options: display, and use common prefix
} else if (tabs.size() > 1){
String prefix = tabs.get(0).toString();
for(Object o : tabs){
String s = o.toString();
int len = Math.min(s.length(), prefix.length());
for(int i = 0; i < len; i++){
if(s.charAt(i) != prefix.charAt(i)){
prefix = prefix.substring(0,i);
break;
}
if(s.length()< prefix.length())
prefix = s;
}
outputArea.append("\n"+o.toString());
}
outputArea.append("\n");
inputField.setText(prefix);
}
}catch(MsfException mex){
}// do nothing on error
}
}
public void keyPressed(KeyEvent ke) {
}
public void keyReleased(KeyEvent ke) {
}
});
} else{
else
cmdPrefix = "session." + type + "_";
}
inputField.setFocusTraversalKeysEnabled(false);
inputField.addKeyListener(new KeyListener(){
public void keyTyped(KeyEvent ke) {
if(ke.getKeyChar() == '\t'){
try{
Map res = (Map)rpcConn.execute(cmdPrefix+"tabs", sid,inputField.getText());
List tabs = (List)res.get("tabs");
//one option: use it
if(tabs.size() == 1){
inputField.setText(tabs.get(0).toString());
//more options: display, and use common prefix
} else if (tabs.size() > 1){
String prefix = tabs.get(0).toString();
for(Object o : tabs){
String s = o.toString();
int len = Math.min(s.length(), prefix.length());
for(int i = 0; i < len; i++){
if(s.charAt(i) != prefix.charAt(i)){
prefix = prefix.substring(0,i);
break;
}
if(s.length()< prefix.length())
prefix = s;
}
outputArea.append("\n"+o.toString());
}
outputArea.append("\n");
inputField.setText(prefix);
}
}catch(MsfException mex){
}// do nothing on error
}
}
public void keyPressed(KeyEvent ke) {
}
public void keyReleased(KeyEvent ke) {
}
});
timerCommand = new StringBuffer(""+PAUSE);
prompt = ">>>";

View File

@ -1567,12 +1567,7 @@ nameloop: for (int i = 0; i < names.length; i++) {
meterpreterPopupMenu.add(monitorMenu);
addScript("Start keylogger",monitorMenu,"keylogrecorder");
addScript("Start packet recorder",monitorMenu,"packetrecorder");
addScript("Screenshot",monitorMenu,new RpcAction(this) {
public void action(Map session) throws Exception {
rpcConn.execute("session.meterpreter_write", session.get("id"),
Base64.encode("screenshot\n".getBytes()));
}
});
addScript("Screenshot",monitorMenu,"multi_console_command -cl \"screenshot\"");
JMenu escalateMenu = new JMenu("Privilege escalation");
meterpreterPopupMenu.add(escalateMenu);
@ -1602,14 +1597,11 @@ nameloop: for (int i = 0; i < names.length; i++) {
return "gettelnet.rb "+UserPassDialog.getUserPassOpts(getFrame());
}
});
addSessionItem("Add admin user",accessMenu,new RpcAction(this) {
String[] userPass = null;
public void action(Map session) throws Exception {
if(userPass == null)
userPass = UserPassDialog.showUserPassDialog(getFrame());
rpcConn.execute("session.meterpreter_write", session.get("id"),Base64.encode(
("execute -H -f cmd -a \"/c net user "+userPass[0]+" "+userPass[1]+" /ADD " +
"&& net localgroup Administrators "+userPass[0]+" /ADD\" \n").getBytes()));
addSessionItem("Add admin user",accessMenu,new Object(){
public String toString(){
String[] userPass = UserPassDialog.showUserPassDialog(getFrame());
return "multicommand -cl \"net user "+userPass[0]+" "+userPass[1]+" /ADD\"" +
",\"net localgroup Administrators "+userPass[0]+" /ADD\"";
}
});
addScript("Kill AV",accessMenu,"killav");

View File

@ -117,9 +117,12 @@ public class MeterpFileBrowser extends MsfFrame {
}
/** Calls meterpreter_write with the session ID and Base64 encoded text. */
private Object executeCommand(String text) throws MsfException{
return rpcConn.execute("session.meterpreter_write", session.get("id"),
Base64.encode(text.getBytes()));
private void executeCommand(String cmd){
try{
rpcConn.execute("session.meterpreter_run_single", session.get("id"), cmd);
} catch (Exception ex) {
JOptionPane.showMessageDialog(this, ex);
}
}
/** Handles click events, like popup menu and double-click navigation */
private void setupPopupMenu(final RpcConnection rpcConn, final Map session) {
@ -131,11 +134,7 @@ public class MeterpFileBrowser extends MsfFrame {
return;
String clickedFile = mainTable.getValueAt(indx, 0).toString();
if (files.get(clickedFile).equals("dir")) {
try {
executeCommand("cd \"" + clickedFile + "\"\n");
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, ex);
}
executeCommand("cd \"" + clickedFile + "\"");
getFiles();
} else {
download();
@ -158,14 +157,10 @@ public class MeterpFileBrowser extends MsfFrame {
if (indx == -1)
return;
String clickedFile = mainTable.getValueAt(indx, 0).toString();
try {
if (files.get(clickedFile).equals("dir"))
executeCommand("rmdir \"" + clickedFile + "\"\n");
else
executeCommand("rm \"" + clickedFile + "\"\n");
} catch (MsfException ex) {
JOptionPane.showMessageDialog(null, ex);
}
if (files.get(clickedFile).equals("dir"))
executeCommand("rmdir \"" + clickedFile + "\"");
else
executeCommand("rm \"" + clickedFile + "\"");
getFiles();
}
@ -173,11 +168,7 @@ public class MeterpFileBrowser extends MsfFrame {
protected void getFiles() {
while(model.getRowCount() > 0)
model.removeRow(0);
try {
executeCommand("ls\n");
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, ex);
}
executeCommand("ls");
if(readTimer != null && readTimer.isRunning())
return;
readTimer = new Timer(300, new ActionListener() {
@ -404,11 +395,7 @@ public class MeterpFileBrowser extends MsfFrame {
private void formWindowOpened(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowOpened
lock.lock();
// Some exploits open in C:\Windows\system32. Too many files in there! Try to move to C:\ which should be more manageable
try {
executeCommand("cd \"C:\\\\\"\n");
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, ex);
}
executeCommand("cd \"C:\\\\\"");
getFiles();
}//GEN-LAST:event_formWindowOpened
@ -421,12 +408,8 @@ public class MeterpFileBrowser extends MsfFrame {
fchooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
if(fchooser.showOpenDialog(this) != JFileChooser.APPROVE_OPTION)
return;
try {
executeCommand("lcd \""+MsfguiApp.cleanBackslashes(fchooser.getSelectedFile().getParent()) + "\"\n");
executeCommand("upload \""+fchooser.getSelectedFile().getName() + "\"\n");
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, ex);
}
executeCommand("lcd \""+MsfguiApp.cleanBackslashes(fchooser.getSelectedFile().getParent()) + "\"");
executeCommand("upload \""+fchooser.getSelectedFile().getName() + "\"");
getFiles();
}//GEN-LAST:event_uploadButtonActionPerformed
@ -438,11 +421,7 @@ public class MeterpFileBrowser extends MsfFrame {
String newDir = JOptionPane.showInputDialog(this,"New directory name","Choose Directory Name",JOptionPane.QUESTION_MESSAGE);
if(newDir == null)
return;
try {
executeCommand("mkdir \""+newDir + "\"\n");
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, ex);
}
executeCommand("mkdir \""+newDir + "\"");
getFiles();
}//GEN-LAST:event_dirButtonActionPerformed
@ -451,11 +430,7 @@ public class MeterpFileBrowser extends MsfFrame {
}//GEN-LAST:event_refreshButtonActionPerformed
private void upButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_upButtonActionPerformed
try {
executeCommand("cd ..\n");
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, ex);
}
executeCommand("cd ..");
getFiles();
}//GEN-LAST:event_upButtonActionPerformed
@ -496,11 +471,7 @@ public class MeterpFileBrowser extends MsfFrame {
fchooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
if(fchooser.showSaveDialog(this) != JFileChooser.APPROVE_OPTION)
return;
try {
executeCommand("lcd \""+MsfguiApp.cleanBackslashes(fchooser.getSelectedFile().toString()) + "\"\n");
executeCommand("download \""+clickedFile + "\"\n");
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, ex);
}
executeCommand("lcd \""+MsfguiApp.cleanBackslashes(fchooser.getSelectedFile().toString()) + "\"");
executeCommand("download \""+clickedFile + "\"");
}
}

View File

@ -39,13 +39,8 @@ public class ProcessList extends MsfFrame {
/** Lists the processes that are running */
protected void listProcs() throws HeadlessException {
try {
rpcConn.execute("session.meterpreter_write", session.get("id"), Base64.encode(("ps\n").getBytes()));
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, ex);
if (ex.getMessage().equals("unknown session"))
return;
}
if (runCommand("ps"))
return;
readTimer = new Timer(300, new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
@ -85,6 +80,18 @@ public class ProcessList extends MsfFrame {
readTimer.start();
}
//Runs command, returning whether error was found
private boolean runCommand(String cmd) throws HeadlessException {
try {
rpcConn.execute("session.meterpreter_run_single", session.get("id"),cmd);
} catch (Exception ex) {
JOptionPane.showMessageDialog(this, ex);
if (ex.getMessage().equals("unknown session"))
return true;
}
return false;
}
/** This method is called from within the constructor to
* initialize the form.
* WARNING: Do NOT modify this code. The content of this method is
@ -198,22 +205,12 @@ public class ProcessList extends MsfFrame {
}//GEN-LAST:event_formWindowOpened
private void migrateButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_migrateButtonActionPerformed
try {
rpcConn.execute("session.meterpreter_write", session.get("id"),
Base64.encode(("migrate "+processTable.getModel().getValueAt(processTable.getSelectedRow(),0) + "\n").getBytes()));
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, ex);
}
runCommand("migrate "+processTable.getModel().getValueAt(processTable.getSelectedRow(),0));
listProcs();
}//GEN-LAST:event_migrateButtonActionPerformed
private void killButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_killButtonActionPerformed
try {
rpcConn.execute("session.meterpreter_write", session.get("id"),
Base64.encode(("kill "+processTable.getModel().getValueAt(processTable.getSelectedRow(),0) + "\n").getBytes()));
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, ex);
}
runCommand("kill "+processTable.getModel().getValueAt(processTable.getSelectedRow(),0));
listProcs();
}//GEN-LAST:event_killButtonActionPerformed

View File

@ -149,17 +149,22 @@ class Session < Base
{ "tabs" => s.console.tab_complete(line) }
end
def meterpreter_script(token, sid, data)
# runs a meterpreter command even if interacting with a shell or other channel
def meterpreter_run_single(token, sid, data)
s = _valid_session(token,sid,"meterpreter")
if not s.user_output.respond_to? :dump_buffer
s.init_ui(Rex::Ui::Text::Input::Buffer.new, Rex::Ui::Text::Output::Buffer.new)
end
Thread.new(s) { |sess| sess.console.run_single("run #{data}") }
Thread.new(s) { |sess| sess.console.run_single(data) }
{}
end
def meterpreter_script(token, sid, data)
meterpreter_run_single(token, sid, "run #{data}")
end
protected
def _valid_session(token,sid,type)