librex 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +4 -0
- data/lib/rex.rb +101 -0
- data/lib/rex.rb.ts.rb +70 -0
- data/lib/rex/LICENSE +29 -0
- data/lib/rex/arch.rb +103 -0
- data/lib/rex/arch/sparc.rb +75 -0
- data/lib/rex/arch/sparc.rb.ut.rb +18 -0
- data/lib/rex/arch/x86.rb +513 -0
- data/lib/rex/arch/x86.rb.ut.rb +93 -0
- data/lib/rex/assembly/nasm.rb +100 -0
- data/lib/rex/assembly/nasm.rb.ut.rb +22 -0
- data/lib/rex/codepage.map +104 -0
- data/lib/rex/compat.rb +281 -0
- data/lib/rex/constants.rb +113 -0
- data/lib/rex/elfparsey.rb +11 -0
- data/lib/rex/elfparsey/elf.rb +123 -0
- data/lib/rex/elfparsey/elfbase.rb +260 -0
- data/lib/rex/elfparsey/exceptions.rb +27 -0
- data/lib/rex/elfscan.rb +12 -0
- data/lib/rex/elfscan/scanner.rb +207 -0
- data/lib/rex/elfscan/search.rb +46 -0
- data/lib/rex/encoder/alpha2.rb +31 -0
- data/lib/rex/encoder/alpha2/alpha_mixed.rb +68 -0
- data/lib/rex/encoder/alpha2/alpha_upper.rb +79 -0
- data/lib/rex/encoder/alpha2/generic.rb +113 -0
- data/lib/rex/encoder/alpha2/unicode_mixed.rb +117 -0
- data/lib/rex/encoder/alpha2/unicode_upper.rb +129 -0
- data/lib/rex/encoder/ndr.rb +89 -0
- data/lib/rex/encoder/ndr.rb.ut.rb +44 -0
- data/lib/rex/encoder/nonalpha.rb +61 -0
- data/lib/rex/encoder/nonupper.rb +64 -0
- data/lib/rex/encoder/xdr.rb +106 -0
- data/lib/rex/encoder/xdr.rb.ut.rb +29 -0
- data/lib/rex/encoder/xor.rb +69 -0
- data/lib/rex/encoder/xor/dword.rb +13 -0
- data/lib/rex/encoder/xor/dword_additive.rb +13 -0
- data/lib/rex/encoders/xor_dword.rb +35 -0
- data/lib/rex/encoders/xor_dword_additive.rb +53 -0
- data/lib/rex/encoders/xor_dword_additive.rb.ut.rb +12 -0
- data/lib/rex/encoding/xor.rb +20 -0
- data/lib/rex/encoding/xor.rb.ts.rb +14 -0
- data/lib/rex/encoding/xor/byte.rb +15 -0
- data/lib/rex/encoding/xor/byte.rb.ut.rb +21 -0
- data/lib/rex/encoding/xor/dword.rb +21 -0
- data/lib/rex/encoding/xor/dword.rb.ut.rb +15 -0
- data/lib/rex/encoding/xor/dword_additive.rb +92 -0
- data/lib/rex/encoding/xor/dword_additive.rb.ut.rb +15 -0
- data/lib/rex/encoding/xor/exceptions.rb +17 -0
- data/lib/rex/encoding/xor/generic.rb +146 -0
- data/lib/rex/encoding/xor/generic.rb.ut.rb +120 -0
- data/lib/rex/encoding/xor/qword.rb +15 -0
- data/lib/rex/encoding/xor/word.rb +21 -0
- data/lib/rex/encoding/xor/word.rb.ut.rb +13 -0
- data/lib/rex/exceptions.rb +275 -0
- data/lib/rex/exceptions.rb.ut.rb +44 -0
- data/lib/rex/exploitation/cmdstager.rb +133 -0
- data/lib/rex/exploitation/egghunter.rb +143 -0
- data/lib/rex/exploitation/egghunter.rb.ut.rb +25 -0
- data/lib/rex/exploitation/encryptjs.rb +77 -0
- data/lib/rex/exploitation/heaplib.js.b64 +331 -0
- data/lib/rex/exploitation/heaplib.rb +94 -0
- data/lib/rex/exploitation/javascriptosdetect.rb +735 -0
- data/lib/rex/exploitation/obfuscatejs.rb +335 -0
- data/lib/rex/exploitation/opcodedb.rb +818 -0
- data/lib/rex/exploitation/opcodedb.rb.ut.rb +279 -0
- data/lib/rex/exploitation/seh.rb +92 -0
- data/lib/rex/exploitation/seh.rb.ut.rb +19 -0
- data/lib/rex/file.rb +84 -0
- data/lib/rex/file.rb.ut.rb +16 -0
- data/lib/rex/image_source.rb +12 -0
- data/lib/rex/image_source/disk.rb +60 -0
- data/lib/rex/image_source/image_source.rb +46 -0
- data/lib/rex/image_source/memory.rb +37 -0
- data/lib/rex/io/bidirectional_pipe.rb +157 -0
- data/lib/rex/io/datagram_abstraction.rb +35 -0
- data/lib/rex/io/stream.rb +313 -0
- data/lib/rex/io/stream_abstraction.rb +186 -0
- data/lib/rex/io/stream_server.rb +211 -0
- data/lib/rex/job_container.rb +202 -0
- data/lib/rex/logging.rb +4 -0
- data/lib/rex/logging/log_dispatcher.rb +179 -0
- data/lib/rex/logging/log_sink.rb +42 -0
- data/lib/rex/logging/sinks/flatfile.rb +55 -0
- data/lib/rex/logging/sinks/stderr.rb +43 -0
- data/lib/rex/machparsey.rb +9 -0
- data/lib/rex/machparsey/exceptions.rb +34 -0
- data/lib/rex/machparsey/mach.rb +209 -0
- data/lib/rex/machparsey/machbase.rb +408 -0
- data/lib/rex/machscan.rb +9 -0
- data/lib/rex/machscan/scanner.rb +217 -0
- data/lib/rex/mime.rb +9 -0
- data/lib/rex/mime/header.rb +75 -0
- data/lib/rex/mime/message.rb +112 -0
- data/lib/rex/mime/part.rb +20 -0
- data/lib/rex/nop/opty2.rb +108 -0
- data/lib/rex/nop/opty2.rb.ut.rb +23 -0
- data/lib/rex/nop/opty2_tables.rb +300 -0
- data/lib/rex/ole.rb +128 -0
- data/lib/rex/ole/clsid.rb +47 -0
- data/lib/rex/ole/difat.rb +141 -0
- data/lib/rex/ole/directory.rb +230 -0
- data/lib/rex/ole/direntry.rb +240 -0
- data/lib/rex/ole/fat.rb +99 -0
- data/lib/rex/ole/header.rb +204 -0
- data/lib/rex/ole/minifat.rb +77 -0
- data/lib/rex/ole/samples/create_ole.rb +27 -0
- data/lib/rex/ole/samples/dir.rb +35 -0
- data/lib/rex/ole/samples/dump_stream.rb +34 -0
- data/lib/rex/ole/samples/ole_info.rb +23 -0
- data/lib/rex/ole/storage.rb +395 -0
- data/lib/rex/ole/stream.rb +53 -0
- data/lib/rex/ole/substorage.rb +49 -0
- data/lib/rex/ole/util.rb +157 -0
- data/lib/rex/parser/arguments.rb +97 -0
- data/lib/rex/parser/arguments.rb.ut.rb +67 -0
- data/lib/rex/parser/ini.rb +185 -0
- data/lib/rex/parser/ini.rb.ut.rb +29 -0
- data/lib/rex/parser/nmap_xml.rb +111 -0
- data/lib/rex/payloads.rb +1 -0
- data/lib/rex/payloads/win32.rb +2 -0
- data/lib/rex/payloads/win32/common.rb +26 -0
- data/lib/rex/payloads/win32/kernel.rb +53 -0
- data/lib/rex/payloads/win32/kernel/common.rb +54 -0
- data/lib/rex/payloads/win32/kernel/migration.rb +12 -0
- data/lib/rex/payloads/win32/kernel/recovery.rb +50 -0
- data/lib/rex/payloads/win32/kernel/stager.rb +171 -0
- data/lib/rex/peparsey.rb +12 -0
- data/lib/rex/peparsey/exceptions.rb +32 -0
- data/lib/rex/peparsey/pe.rb +188 -0
- data/lib/rex/peparsey/pe_memdump.rb +63 -0
- data/lib/rex/peparsey/pebase.rb +1655 -0
- data/lib/rex/peparsey/section.rb +136 -0
- data/lib/rex/pescan.rb +13 -0
- data/lib/rex/pescan/analyze.rb +309 -0
- data/lib/rex/pescan/scanner.rb +206 -0
- data/lib/rex/pescan/search.rb +56 -0
- data/lib/rex/platforms.rb +1 -0
- data/lib/rex/platforms/windows.rb +51 -0
- data/lib/rex/poly.rb +132 -0
- data/lib/rex/poly/block.rb +468 -0
- data/lib/rex/poly/register.rb +100 -0
- data/lib/rex/poly/register/x86.rb +40 -0
- data/lib/rex/post.rb +8 -0
- data/lib/rex/post/dir.rb +51 -0
- data/lib/rex/post/file.rb +172 -0
- data/lib/rex/post/file_stat.rb +220 -0
- data/lib/rex/post/gen.pl +13 -0
- data/lib/rex/post/io.rb +182 -0
- data/lib/rex/post/meterpreter.rb +4 -0
- data/lib/rex/post/meterpreter/channel.rb +438 -0
- data/lib/rex/post/meterpreter/channel_container.rb +54 -0
- data/lib/rex/post/meterpreter/channels/pool.rb +160 -0
- data/lib/rex/post/meterpreter/channels/pools/file.rb +62 -0
- data/lib/rex/post/meterpreter/channels/pools/stream_pool.rb +103 -0
- data/lib/rex/post/meterpreter/channels/stream.rb +87 -0
- data/lib/rex/post/meterpreter/client.rb +335 -0
- data/lib/rex/post/meterpreter/client_core.rb +274 -0
- data/lib/rex/post/meterpreter/dependencies.rb +3 -0
- data/lib/rex/post/meterpreter/extension.rb +32 -0
- data/lib/rex/post/meterpreter/extensions/espia/espia.rb +58 -0
- data/lib/rex/post/meterpreter/extensions/espia/tlv.rb +16 -0
- data/lib/rex/post/meterpreter/extensions/incognito/incognito.rb +94 -0
- data/lib/rex/post/meterpreter/extensions/incognito/tlv.rb +21 -0
- data/lib/rex/post/meterpreter/extensions/priv/fs.rb +118 -0
- data/lib/rex/post/meterpreter/extensions/priv/passwd.rb +61 -0
- data/lib/rex/post/meterpreter/extensions/priv/priv.rb +104 -0
- data/lib/rex/post/meterpreter/extensions/priv/tlv.rb +28 -0
- data/lib/rex/post/meterpreter/extensions/sniffer/sniffer.rb +100 -0
- data/lib/rex/post/meterpreter/extensions/sniffer/tlv.rb +24 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/constants.rb +333 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +273 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +235 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/file_stat.rb +103 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/io.rb +48 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/net/config.rb +144 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/net/interface.rb +73 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/net/route.rb +56 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/net/socket.rb +137 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_client_channel.rb +167 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_server_channel.rb +167 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb +192 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb +139 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb +97 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log.rb +184 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log_subsystem/event_record.rb +41 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/power.rb +61 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb +361 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/image.rb +129 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/io.rb +55 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb +336 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/thread.rb +141 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry.rb +279 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb +182 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_value.rb +102 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/thread.rb +174 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +185 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/ui.rb +227 -0
- data/lib/rex/post/meterpreter/inbound_packet_handler.rb +30 -0
- data/lib/rex/post/meterpreter/object_aliases.rb +83 -0
- data/lib/rex/post/meterpreter/packet.rb +596 -0
- data/lib/rex/post/meterpreter/packet_dispatcher.rb +409 -0
- data/lib/rex/post/meterpreter/packet_parser.rb +94 -0
- data/lib/rex/post/meterpreter/packet_response_waiter.rb +83 -0
- data/lib/rex/post/meterpreter/ui/console.rb +135 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher.rb +62 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +595 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/espia.rb +108 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/incognito.rb +241 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv.rb +61 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb +98 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/passwd.rb +51 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/timestomp.rb +132 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/sniffer.rb +187 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi.rb +63 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +376 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb +270 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +484 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb +315 -0
- data/lib/rex/post/meterpreter/ui/console/interactive_channel.rb +95 -0
- data/lib/rex/post/permission.rb +26 -0
- data/lib/rex/post/process.rb +57 -0
- data/lib/rex/post/thread.rb +57 -0
- data/lib/rex/post/ui.rb +52 -0
- data/lib/rex/proto.rb +12 -0
- data/lib/rex/proto.rb.ts.rb +8 -0
- data/lib/rex/proto/dcerpc.rb +6 -0
- data/lib/rex/proto/dcerpc.rb.ts.rb +9 -0
- data/lib/rex/proto/dcerpc/client.rb +358 -0
- data/lib/rex/proto/dcerpc/client.rb.ut.rb +491 -0
- data/lib/rex/proto/dcerpc/exceptions.rb +150 -0
- data/lib/rex/proto/dcerpc/handle.rb +47 -0
- data/lib/rex/proto/dcerpc/handle.rb.ut.rb +85 -0
- data/lib/rex/proto/dcerpc/ndr.rb +72 -0
- data/lib/rex/proto/dcerpc/ndr.rb.ut.rb +41 -0
- data/lib/rex/proto/dcerpc/packet.rb +253 -0
- data/lib/rex/proto/dcerpc/packet.rb.ut.rb +56 -0
- data/lib/rex/proto/dcerpc/response.rb +186 -0
- data/lib/rex/proto/dcerpc/response.rb.ut.rb +15 -0
- data/lib/rex/proto/dcerpc/uuid.rb +84 -0
- data/lib/rex/proto/dcerpc/uuid.rb.ut.rb +46 -0
- data/lib/rex/proto/drda.rb +5 -0
- data/lib/rex/proto/drda.rb.ts.rb +17 -0
- data/lib/rex/proto/drda/constants.rb +49 -0
- data/lib/rex/proto/drda/constants.rb.ut.rb +23 -0
- data/lib/rex/proto/drda/packet.rb +252 -0
- data/lib/rex/proto/drda/packet.rb.ut.rb +109 -0
- data/lib/rex/proto/drda/utils.rb +123 -0
- data/lib/rex/proto/drda/utils.rb.ut.rb +84 -0
- data/lib/rex/proto/http.rb +5 -0
- data/lib/rex/proto/http.rb.ts.rb +12 -0
- data/lib/rex/proto/http/client.rb +817 -0
- data/lib/rex/proto/http/client.rb.ut.rb +93 -0
- data/lib/rex/proto/http/handler.rb +46 -0
- data/lib/rex/proto/http/handler/erb.rb +128 -0
- data/lib/rex/proto/http/handler/erb.rb.ut.rb +21 -0
- data/lib/rex/proto/http/handler/erb.rb.ut.rb.rhtml +1 -0
- data/lib/rex/proto/http/handler/proc.rb +54 -0
- data/lib/rex/proto/http/handler/proc.rb.ut.rb +24 -0
- data/lib/rex/proto/http/header.rb +161 -0
- data/lib/rex/proto/http/header.rb.ut.rb +46 -0
- data/lib/rex/proto/http/packet.rb +394 -0
- data/lib/rex/proto/http/packet.rb.ut.rb +165 -0
- data/lib/rex/proto/http/request.rb +356 -0
- data/lib/rex/proto/http/request.rb.ut.rb +214 -0
- data/lib/rex/proto/http/response.rb +85 -0
- data/lib/rex/proto/http/response.rb.ut.rb +149 -0
- data/lib/rex/proto/http/server.rb +367 -0
- data/lib/rex/proto/http/server.rb.ut.rb +79 -0
- data/lib/rex/proto/smb.rb +7 -0
- data/lib/rex/proto/smb.rb.ts.rb +8 -0
- data/lib/rex/proto/smb/client.rb +1733 -0
- data/lib/rex/proto/smb/client.rb.ut.rb +223 -0
- data/lib/rex/proto/smb/constants.rb +1062 -0
- data/lib/rex/proto/smb/constants.rb.ut.rb +18 -0
- data/lib/rex/proto/smb/crypt.rb +95 -0
- data/lib/rex/proto/smb/crypt.rb.ut.rb +20 -0
- data/lib/rex/proto/smb/evasions.rb +65 -0
- data/lib/rex/proto/smb/exceptions.rb +846 -0
- data/lib/rex/proto/smb/simpleclient.rb +292 -0
- data/lib/rex/proto/smb/simpleclient.rb.ut.rb +128 -0
- data/lib/rex/proto/smb/utils.rb +514 -0
- data/lib/rex/proto/smb/utils.rb.ut.rb +20 -0
- data/lib/rex/proto/sunrpc.rb +1 -0
- data/lib/rex/proto/sunrpc/client.rb +195 -0
- data/lib/rex/script.rb +42 -0
- data/lib/rex/script/base.rb +59 -0
- data/lib/rex/script/meterpreter.rb +9 -0
- data/lib/rex/script/shell.rb +9 -0
- data/lib/rex/service.rb +48 -0
- data/lib/rex/service_manager.rb +141 -0
- data/lib/rex/service_manager.rb.ut.rb +32 -0
- data/lib/rex/services/local_relay.rb +423 -0
- data/lib/rex/socket.rb +586 -0
- data/lib/rex/socket.rb.ut.rb +86 -0
- data/lib/rex/socket/comm.rb +119 -0
- data/lib/rex/socket/comm/local.rb +409 -0
- data/lib/rex/socket/comm/local.rb.ut.rb +75 -0
- data/lib/rex/socket/ip.rb +129 -0
- data/lib/rex/socket/parameters.rb +345 -0
- data/lib/rex/socket/parameters.rb.ut.rb +51 -0
- data/lib/rex/socket/range_walker.rb +295 -0
- data/lib/rex/socket/range_walker.rb.ut.rb +55 -0
- data/lib/rex/socket/ssl_tcp.rb +184 -0
- data/lib/rex/socket/ssl_tcp.rb.ut.rb +39 -0
- data/lib/rex/socket/ssl_tcp_server.rb +122 -0
- data/lib/rex/socket/ssl_tcp_server.rb.ut.rb +51 -0
- data/lib/rex/socket/subnet_walker.rb +75 -0
- data/lib/rex/socket/subnet_walker.rb.ut.rb +28 -0
- data/lib/rex/socket/switch_board.rb +272 -0
- data/lib/rex/socket/switch_board.rb.ut.rb +52 -0
- data/lib/rex/socket/tcp.rb +76 -0
- data/lib/rex/socket/tcp.rb.ut.rb +64 -0
- data/lib/rex/socket/tcp_server.rb +67 -0
- data/lib/rex/socket/tcp_server.rb.ut.rb +44 -0
- data/lib/rex/socket/udp.rb +157 -0
- data/lib/rex/socket/udp.rb.ut.rb +44 -0
- data/lib/rex/struct2.rb +5 -0
- data/lib/rex/struct2/c_struct.rb +181 -0
- data/lib/rex/struct2/c_struct_template.rb +39 -0
- data/lib/rex/struct2/constant.rb +26 -0
- data/lib/rex/struct2/element.rb +44 -0
- data/lib/rex/struct2/generic.rb +73 -0
- data/lib/rex/struct2/restraint.rb +54 -0
- data/lib/rex/struct2/s_string.rb +72 -0
- data/lib/rex/struct2/s_struct.rb +111 -0
- data/lib/rex/sync.rb +6 -0
- data/lib/rex/sync/event.rb +94 -0
- data/lib/rex/sync/read_write_lock.rb +176 -0
- data/lib/rex/sync/ref.rb +57 -0
- data/lib/rex/sync/thread_safe.rb +82 -0
- data/lib/rex/test.rb +35 -0
- data/lib/rex/text.rb +1029 -0
- data/lib/rex/text.rb.ut.rb +168 -0
- data/lib/rex/time.rb +65 -0
- data/lib/rex/transformer.rb +115 -0
- data/lib/rex/transformer.rb.ut.rb +38 -0
- data/lib/rex/ui.rb +21 -0
- data/lib/rex/ui/interactive.rb +252 -0
- data/lib/rex/ui/output.rb +80 -0
- data/lib/rex/ui/output/none.rb +18 -0
- data/lib/rex/ui/progress_tracker.rb +96 -0
- data/lib/rex/ui/subscriber.rb +149 -0
- data/lib/rex/ui/text/color.rb +97 -0
- data/lib/rex/ui/text/color.rb.ut.rb +18 -0
- data/lib/rex/ui/text/dispatcher_shell.rb +382 -0
- data/lib/rex/ui/text/input.rb +117 -0
- data/lib/rex/ui/text/input/buffer.rb +75 -0
- data/lib/rex/ui/text/input/readline.rb +129 -0
- data/lib/rex/ui/text/input/socket.rb +95 -0
- data/lib/rex/ui/text/input/stdio.rb +45 -0
- data/lib/rex/ui/text/irb_shell.rb +55 -0
- data/lib/rex/ui/text/output.rb +80 -0
- data/lib/rex/ui/text/output/buffer.rb +65 -0
- data/lib/rex/ui/text/output/file.rb +37 -0
- data/lib/rex/ui/text/output/socket.rb +43 -0
- data/lib/rex/ui/text/output/stdio.rb +40 -0
- data/lib/rex/ui/text/progress_tracker.rb +56 -0
- data/lib/rex/ui/text/progress_tracker.rb.ut.rb +34 -0
- data/lib/rex/ui/text/shell.rb +321 -0
- data/lib/rex/ui/text/table.rb +254 -0
- data/lib/rex/ui/text/table.rb.ut.rb +55 -0
- data/lib/rex/zip.rb +93 -0
- data/lib/rex/zip/archive.rb +91 -0
- data/lib/rex/zip/blocks.rb +182 -0
- data/lib/rex/zip/entry.rb +95 -0
- data/lib/rex/zip/samples/comment.rb +32 -0
- data/lib/rex/zip/samples/mkwar.rb +138 -0
- data/lib/rex/zip/samples/mkzip.rb +19 -0
- data/lib/rex/zip/samples/recursive.rb +58 -0
- metadata +435 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'timeout'
|
|
4
|
+
require 'thread'
|
|
5
|
+
|
|
6
|
+
module Rex
|
|
7
|
+
module Post
|
|
8
|
+
module Meterpreter
|
|
9
|
+
|
|
10
|
+
###
|
|
11
|
+
#
|
|
12
|
+
# This class handles waiting for a response to a given request
|
|
13
|
+
# and the subsequent response association.
|
|
14
|
+
#
|
|
15
|
+
###
|
|
16
|
+
class PacketResponseWaiter
|
|
17
|
+
|
|
18
|
+
#
|
|
19
|
+
# Initializes a response waiter instance for the supplied request
|
|
20
|
+
# identifier.
|
|
21
|
+
#
|
|
22
|
+
def initialize(rid, completion_routine = nil, completion_param = nil)
|
|
23
|
+
self.rid = rid.dup
|
|
24
|
+
self.response = nil
|
|
25
|
+
|
|
26
|
+
if (completion_routine)
|
|
27
|
+
self.completion_routine = completion_routine
|
|
28
|
+
self.completion_param = completion_param
|
|
29
|
+
else
|
|
30
|
+
self.done = false
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
#
|
|
35
|
+
# Checks to see if this waiter instance is waiting for the supplied
|
|
36
|
+
# packet based on its request identifier.
|
|
37
|
+
#
|
|
38
|
+
def waiting_for?(packet)
|
|
39
|
+
return (packet.rid == rid)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
#
|
|
43
|
+
# Notifies the waiter that the supplied response packet has arrived.
|
|
44
|
+
#
|
|
45
|
+
def notify(response)
|
|
46
|
+
self.response = response
|
|
47
|
+
|
|
48
|
+
if (self.completion_routine)
|
|
49
|
+
self.completion_routine.call(response, self.completion_param)
|
|
50
|
+
else
|
|
51
|
+
self.done = true
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
#
|
|
56
|
+
# Waits for a given time interval for the response packet to arrive.
|
|
57
|
+
# If the interval is -1 we can wait forever.
|
|
58
|
+
#
|
|
59
|
+
def wait(interval)
|
|
60
|
+
if( interval and interval == -1 )
|
|
61
|
+
while(not self.done)
|
|
62
|
+
select(nil, nil, nil, 0.1)
|
|
63
|
+
end
|
|
64
|
+
else
|
|
65
|
+
begin
|
|
66
|
+
Timeout.timeout(interval) {
|
|
67
|
+
while(not self.done)
|
|
68
|
+
select(nil, nil, nil, 0.1)
|
|
69
|
+
end
|
|
70
|
+
}
|
|
71
|
+
rescue Timeout::Error
|
|
72
|
+
self.response = nil
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
return self.response
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
attr_accessor :rid, :done, :response # :nodoc:
|
|
79
|
+
attr_accessor :completion_routine, :completion_param # :nodoc:
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
end; end; end
|
|
83
|
+
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
require 'rex/ui'
|
|
2
|
+
require 'rex/post/meterpreter'
|
|
3
|
+
require 'rex/logging'
|
|
4
|
+
|
|
5
|
+
module Rex
|
|
6
|
+
module Post
|
|
7
|
+
module Meterpreter
|
|
8
|
+
module Ui
|
|
9
|
+
|
|
10
|
+
###
|
|
11
|
+
#
|
|
12
|
+
# This class provides a shell driven interface to the meterpreter client API.
|
|
13
|
+
#
|
|
14
|
+
###
|
|
15
|
+
class Console
|
|
16
|
+
|
|
17
|
+
include Rex::Ui::Text::DispatcherShell
|
|
18
|
+
|
|
19
|
+
# Dispatchers
|
|
20
|
+
require 'rex/post/meterpreter/ui/console/interactive_channel'
|
|
21
|
+
require 'rex/post/meterpreter/ui/console/command_dispatcher'
|
|
22
|
+
require 'rex/post/meterpreter/ui/console/command_dispatcher/core'
|
|
23
|
+
|
|
24
|
+
#
|
|
25
|
+
# Initialize the meterpreter console.
|
|
26
|
+
#
|
|
27
|
+
def initialize(client)
|
|
28
|
+
if (Rex::Compat.is_windows())
|
|
29
|
+
super("meterpreter")
|
|
30
|
+
else
|
|
31
|
+
super("%undmeterpreter%clr")
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# The meterpreter client context
|
|
35
|
+
self.client = client
|
|
36
|
+
|
|
37
|
+
# Queued commands array
|
|
38
|
+
self.commands = []
|
|
39
|
+
|
|
40
|
+
# Point the input/output handles elsewhere
|
|
41
|
+
reset_ui
|
|
42
|
+
|
|
43
|
+
enstack_dispatcher(Console::CommandDispatcher::Core)
|
|
44
|
+
|
|
45
|
+
# Set up logging to whatever logsink 'core' is using
|
|
46
|
+
if ! $dispatcher['meterpreter']
|
|
47
|
+
$dispatcher['meterpreter'] = $dispatcher['core']
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
#
|
|
52
|
+
# Called when someone wants to interact with the meterpreter client. It's
|
|
53
|
+
# assumed that init_ui has been called prior.
|
|
54
|
+
#
|
|
55
|
+
def interact(&block)
|
|
56
|
+
# Run queued commands
|
|
57
|
+
commands.delete_if { |ent|
|
|
58
|
+
run_single(ent)
|
|
59
|
+
true
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
# Run the interactive loop
|
|
63
|
+
run { |line|
|
|
64
|
+
# Run the command
|
|
65
|
+
run_single(line)
|
|
66
|
+
|
|
67
|
+
# If a block was supplied, call it, otherwise return false
|
|
68
|
+
if (block)
|
|
69
|
+
block.call
|
|
70
|
+
else
|
|
71
|
+
false
|
|
72
|
+
end
|
|
73
|
+
}
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
#
|
|
77
|
+
# Interacts with the supplied channel.
|
|
78
|
+
#
|
|
79
|
+
def interact_with_channel(channel)
|
|
80
|
+
channel.extend(InteractiveChannel) unless (channel.kind_of?(InteractiveChannel) == true)
|
|
81
|
+
|
|
82
|
+
channel.interact(input, output)
|
|
83
|
+
channel.reset_ui
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
#
|
|
87
|
+
# Queues a command to be run when the interactive loop is entered.
|
|
88
|
+
#
|
|
89
|
+
def queue_cmd(cmd)
|
|
90
|
+
self.commands << cmd
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
#
|
|
94
|
+
# Runs the specified command wrapper in something to catch meterpreter
|
|
95
|
+
# exceptions.
|
|
96
|
+
#
|
|
97
|
+
def run_command(dispatcher, method, arguments)
|
|
98
|
+
begin
|
|
99
|
+
super
|
|
100
|
+
rescue Timeout::Error
|
|
101
|
+
log_error("Operation timed out.")
|
|
102
|
+
rescue RequestError => info
|
|
103
|
+
log_error(info.to_s)
|
|
104
|
+
rescue ::Errno::EPIPE, ::OpenSSL::SSL::SSLError, ::IOError
|
|
105
|
+
self.client.kill
|
|
106
|
+
rescue ::Exception => e
|
|
107
|
+
log_error("Error running command #{method}: #{e.class} #{e}")
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
#
|
|
112
|
+
# Logs that an error occurred and persists the callstack.
|
|
113
|
+
#
|
|
114
|
+
def log_error(msg)
|
|
115
|
+
print_error(msg)
|
|
116
|
+
|
|
117
|
+
elog(msg, 'meterpreter')
|
|
118
|
+
|
|
119
|
+
dlog("Call stack:\n#{$@.join("\n")}", 'meterpreter')
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
attr_reader :client # :nodoc:
|
|
123
|
+
|
|
124
|
+
protected
|
|
125
|
+
|
|
126
|
+
attr_writer :client # :nodoc:
|
|
127
|
+
attr_accessor :commands # :nodoc:
|
|
128
|
+
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
require 'rex/logging'
|
|
2
|
+
|
|
3
|
+
module Rex
|
|
4
|
+
module Post
|
|
5
|
+
module Meterpreter
|
|
6
|
+
module Ui
|
|
7
|
+
|
|
8
|
+
###
|
|
9
|
+
#
|
|
10
|
+
# Base class for all command dispatchers within the meterpreter console user
|
|
11
|
+
# interface.
|
|
12
|
+
#
|
|
13
|
+
###
|
|
14
|
+
module Console::CommandDispatcher
|
|
15
|
+
|
|
16
|
+
include Rex::Ui::Text::DispatcherShell::CommandDispatcher
|
|
17
|
+
|
|
18
|
+
#
|
|
19
|
+
# The hash of file names to class names after a module has already been
|
|
20
|
+
# loaded once on the client side.
|
|
21
|
+
#
|
|
22
|
+
@@file_hash = {}
|
|
23
|
+
|
|
24
|
+
#
|
|
25
|
+
# Checks the file name to hash association to see if the module being
|
|
26
|
+
# requested has already been loaded once.
|
|
27
|
+
#
|
|
28
|
+
def self.check_hash(name)
|
|
29
|
+
@@file_hash[name]
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
#
|
|
33
|
+
# Sets the file path to class name association for future reference.
|
|
34
|
+
#
|
|
35
|
+
def self.set_hash(name, klass)
|
|
36
|
+
@@file_hash[name] = klass
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
#
|
|
40
|
+
# Returns the meterpreter client context.
|
|
41
|
+
#
|
|
42
|
+
def client
|
|
43
|
+
shell.client
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
#
|
|
47
|
+
# Log that an error occurred.
|
|
48
|
+
#
|
|
49
|
+
def log_error(msg)
|
|
50
|
+
print_error(msg)
|
|
51
|
+
|
|
52
|
+
elog(msg, 'meterpreter')
|
|
53
|
+
|
|
54
|
+
dlog("Call stack:\n#{$@.join("\n")}", 'meterpreter')
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,595 @@
|
|
|
1
|
+
require 'rex/post/meterpreter'
|
|
2
|
+
require 'rex/parser/arguments'
|
|
3
|
+
|
|
4
|
+
module Rex
|
|
5
|
+
module Post
|
|
6
|
+
module Meterpreter
|
|
7
|
+
module Ui
|
|
8
|
+
|
|
9
|
+
###
|
|
10
|
+
#
|
|
11
|
+
# Core meterpreter client commands that provide only the required set of
|
|
12
|
+
# commands for having a functional meterpreter client<->server instance.
|
|
13
|
+
#
|
|
14
|
+
###
|
|
15
|
+
class Console::CommandDispatcher::Core
|
|
16
|
+
|
|
17
|
+
include Console::CommandDispatcher
|
|
18
|
+
|
|
19
|
+
#
|
|
20
|
+
# Initializes an instance of the core command set using the supplied shell
|
|
21
|
+
# for interactivity.
|
|
22
|
+
#
|
|
23
|
+
def initialize(shell)
|
|
24
|
+
super
|
|
25
|
+
|
|
26
|
+
self.extensions = []
|
|
27
|
+
self.bgjobs = []
|
|
28
|
+
self.bgjob_id = 0
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
@@use_opts = Rex::Parser::Arguments.new(
|
|
32
|
+
"-l" => [ false, "List all available extensions" ],
|
|
33
|
+
"-h" => [ false, "Help menu." ])
|
|
34
|
+
|
|
35
|
+
#
|
|
36
|
+
# List of supported commands.
|
|
37
|
+
#
|
|
38
|
+
def commands
|
|
39
|
+
{
|
|
40
|
+
"?" => "Help menu",
|
|
41
|
+
"background" => "Backgrounds the current session",
|
|
42
|
+
"close" => "Closes a channel",
|
|
43
|
+
"channel" => "Displays information about active channels",
|
|
44
|
+
"exit" => "Terminate the meterpreter session",
|
|
45
|
+
"help" => "Help menu",
|
|
46
|
+
"interact" => "Interacts with a channel",
|
|
47
|
+
"irb" => "Drop into irb scripting mode",
|
|
48
|
+
"migrate" => "Migrate the server to another process",
|
|
49
|
+
"use" => "Load a one or more meterpreter extensions",
|
|
50
|
+
"quit" => "Terminate the meterpreter session",
|
|
51
|
+
"read" => "Reads data from a channel",
|
|
52
|
+
"run" => "Executes a meterpreter script",
|
|
53
|
+
"bgrun" => "Executes a meterpreter script as a background thread",
|
|
54
|
+
"bgkill" => "Kills a background meterpreter script",
|
|
55
|
+
"bglist" => "Lists running background scripts",
|
|
56
|
+
"write" => "Writes data to a channel",
|
|
57
|
+
}
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
#
|
|
61
|
+
# Core baby.
|
|
62
|
+
#
|
|
63
|
+
def name
|
|
64
|
+
"Core"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def cmd_background
|
|
68
|
+
client.interacting = false
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
#
|
|
72
|
+
# Displays information about active channels
|
|
73
|
+
#
|
|
74
|
+
@@channel_opts = Rex::Parser::Arguments.new(
|
|
75
|
+
"-l" => [ false, "List active channels." ],
|
|
76
|
+
"-h" => [ false, "Help menu." ])
|
|
77
|
+
|
|
78
|
+
#
|
|
79
|
+
# Performs operations on the supplied channel.
|
|
80
|
+
#
|
|
81
|
+
def cmd_channel(*args)
|
|
82
|
+
if (args.length == 0)
|
|
83
|
+
args.unshift("-h")
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
mode = nil
|
|
87
|
+
|
|
88
|
+
# Parse options
|
|
89
|
+
@@channel_opts.parse(args) { |opt, idx, val|
|
|
90
|
+
case opt
|
|
91
|
+
when "-h"
|
|
92
|
+
print(
|
|
93
|
+
"Usage: channel [options]\n\n" +
|
|
94
|
+
"Displays information about active channels.\n" +
|
|
95
|
+
@@channel_opts.usage)
|
|
96
|
+
return true
|
|
97
|
+
when "-l"
|
|
98
|
+
mode = 'list'
|
|
99
|
+
end
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
# No mode, no service.
|
|
103
|
+
if (mode == nil)
|
|
104
|
+
return true
|
|
105
|
+
elsif (mode == 'list')
|
|
106
|
+
tbl = Rex::Ui::Text::Table.new(
|
|
107
|
+
'Indent' => 4,
|
|
108
|
+
'Columns' =>
|
|
109
|
+
[
|
|
110
|
+
'Id',
|
|
111
|
+
'Class',
|
|
112
|
+
'Type'
|
|
113
|
+
])
|
|
114
|
+
items = 0
|
|
115
|
+
|
|
116
|
+
client.channels.each_pair { |cid, channel|
|
|
117
|
+
tbl << [ cid, channel.class.cls, channel.type ]
|
|
118
|
+
items += 1
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (items == 0)
|
|
122
|
+
print_line("No active channels.")
|
|
123
|
+
else
|
|
124
|
+
print("\n" + tbl.to_s + "\n")
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
#
|
|
130
|
+
# Closes a supplied channel.
|
|
131
|
+
#
|
|
132
|
+
def cmd_close(*args)
|
|
133
|
+
if (args.length == 0)
|
|
134
|
+
print_line(
|
|
135
|
+
"Usage: close channel_id\n\n" +
|
|
136
|
+
"Closes the supplied channel.")
|
|
137
|
+
return true
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
cid = args[0].to_i
|
|
141
|
+
channel = client.find_channel(cid)
|
|
142
|
+
|
|
143
|
+
if (!channel)
|
|
144
|
+
print_error("Invalid channel identifier specified.")
|
|
145
|
+
return true
|
|
146
|
+
else
|
|
147
|
+
channel._close # Issue #410
|
|
148
|
+
|
|
149
|
+
print_status("Closed channel #{cid}.")
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
#
|
|
154
|
+
# Terminates the meterpreter session.
|
|
155
|
+
#
|
|
156
|
+
def cmd_exit(*args)
|
|
157
|
+
shell.stop
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
alias cmd_quit cmd_exit
|
|
161
|
+
|
|
162
|
+
#
|
|
163
|
+
# Displays the help menu.
|
|
164
|
+
#
|
|
165
|
+
def cmd_help(*args)
|
|
166
|
+
print(shell.help_to_s)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
alias cmd_? cmd_help
|
|
170
|
+
|
|
171
|
+
#
|
|
172
|
+
# Interacts with a channel.
|
|
173
|
+
#
|
|
174
|
+
def cmd_interact(*args)
|
|
175
|
+
if (args.length == 0)
|
|
176
|
+
print_line(
|
|
177
|
+
"Usage: interact channel_id\n\n" +
|
|
178
|
+
"Interacts with the supplied channel.")
|
|
179
|
+
return true
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
cid = args[0].to_i
|
|
183
|
+
channel = client.find_channel(cid)
|
|
184
|
+
|
|
185
|
+
if (channel)
|
|
186
|
+
print_line("Interacting with channel #{cid}...\n")
|
|
187
|
+
|
|
188
|
+
shell.interact_with_channel(channel)
|
|
189
|
+
else
|
|
190
|
+
print_error("Invalid channel identifier specified.")
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
#
|
|
195
|
+
# Runs the IRB scripting shell
|
|
196
|
+
#
|
|
197
|
+
def cmd_irb(*args)
|
|
198
|
+
print_status("Starting IRB shell")
|
|
199
|
+
print_status("The 'client' variable holds the meterpreter client\n")
|
|
200
|
+
|
|
201
|
+
Rex::Ui::Text::IrbShell.new(binding).run
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
#
|
|
205
|
+
# Migrates the server to the supplied process identifier.
|
|
206
|
+
#
|
|
207
|
+
def cmd_migrate(*args)
|
|
208
|
+
if (args.length == 0)
|
|
209
|
+
print_line(
|
|
210
|
+
"Usage: migrate pid\n\n" +
|
|
211
|
+
"Migrates the server instance to another process.\n" +
|
|
212
|
+
"Note: Any open channels or other dynamic state will be lost.")
|
|
213
|
+
return true
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
pid = args[0].to_i
|
|
217
|
+
if(pid == 0)
|
|
218
|
+
print_error("A process ID must be specified, not a process name")
|
|
219
|
+
return
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
print_status("Migrating to #{pid}...")
|
|
223
|
+
|
|
224
|
+
# Do this thang.
|
|
225
|
+
client.core.migrate(pid)
|
|
226
|
+
|
|
227
|
+
print_status("Migration completed successfully.")
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
#
|
|
231
|
+
# Loads one or more meterpreter extensions.
|
|
232
|
+
#
|
|
233
|
+
def cmd_use(*args)
|
|
234
|
+
if (args.length == 0)
|
|
235
|
+
args.unshift("-h")
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
modules = nil
|
|
239
|
+
|
|
240
|
+
@@use_opts.parse(args) { |opt, idx, val|
|
|
241
|
+
case opt
|
|
242
|
+
when "-l"
|
|
243
|
+
exts = []
|
|
244
|
+
path = ::File.join(Msf::Config.install_root, 'data', 'meterpreter')
|
|
245
|
+
::Dir.entries(path).each { |f|
|
|
246
|
+
if (::File.file?(::File.join(path, f)) && f =~ /ext_server_(.*)\.#{client.binary_suffix}/ )
|
|
247
|
+
exts.push($1)
|
|
248
|
+
end
|
|
249
|
+
}
|
|
250
|
+
print(exts.sort.join("\n") + "\n")
|
|
251
|
+
|
|
252
|
+
return true
|
|
253
|
+
when "-h"
|
|
254
|
+
print(
|
|
255
|
+
"Usage: use ext1 ext2 ext3 ...\n\n" +
|
|
256
|
+
"Loads a meterpreter extension module or modules.\n" +
|
|
257
|
+
@@use_opts.usage)
|
|
258
|
+
return true
|
|
259
|
+
end
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
# Load each of the modules
|
|
263
|
+
args.each { |m|
|
|
264
|
+
md = m.downcase
|
|
265
|
+
|
|
266
|
+
if (extensions.include?(md))
|
|
267
|
+
print_error("The '#{md}' extension has already been loaded.")
|
|
268
|
+
next
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
print("Loading extension #{md}...")
|
|
272
|
+
|
|
273
|
+
begin
|
|
274
|
+
# Use the remote side, then load the client-side
|
|
275
|
+
if (client.core.use(md) == true)
|
|
276
|
+
add_extension_client(md)
|
|
277
|
+
end
|
|
278
|
+
rescue
|
|
279
|
+
print_line
|
|
280
|
+
log_error("Failed to load extension: #{$!}")
|
|
281
|
+
next
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
print_line("success.")
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
return true
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def cmd_use_tabs(str, words)
|
|
291
|
+
tabs = []
|
|
292
|
+
path = ::File.join(Msf::Config.install_root, 'data', 'meterpreter')
|
|
293
|
+
::Dir.entries(path).each { |f|
|
|
294
|
+
if (::File.file?(::File.join(path, f)) && f =~ /ext_server_(.*)\.#{client.binary_suffix}/ )
|
|
295
|
+
if (not extensions.include?($1))
|
|
296
|
+
tabs.push($1)
|
|
297
|
+
end
|
|
298
|
+
end
|
|
299
|
+
}
|
|
300
|
+
return tabs
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
#
|
|
304
|
+
# Reads data from a channel.
|
|
305
|
+
#
|
|
306
|
+
def cmd_read(*args)
|
|
307
|
+
if (args.length == 0)
|
|
308
|
+
print_line(
|
|
309
|
+
"Usage: read channel_id [length]\n\n" +
|
|
310
|
+
"Reads data from the supplied channel.")
|
|
311
|
+
return true
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
cid = args[0].to_i
|
|
315
|
+
length = (args.length >= 2) ? args[1].to_i : 16384
|
|
316
|
+
channel = client.find_channel(cid)
|
|
317
|
+
|
|
318
|
+
if (!channel)
|
|
319
|
+
print_error("Channel #{cid} is not valid.")
|
|
320
|
+
return true
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
data = channel.read(length)
|
|
324
|
+
|
|
325
|
+
if (data and data.length)
|
|
326
|
+
print("Read #{data.length} bytes from #{cid}:\n\n#{data}\n")
|
|
327
|
+
else
|
|
328
|
+
print_error("No data was returned.")
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
return true
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
#
|
|
335
|
+
# Executes a script in the context of the meterpreter session.
|
|
336
|
+
#
|
|
337
|
+
def cmd_run(*args)
|
|
338
|
+
if args.length == 0
|
|
339
|
+
print_line(
|
|
340
|
+
"Usage: run <script> [arguments]\n\n" +
|
|
341
|
+
"Executes a ruby script in the context of the meterpreter session.")
|
|
342
|
+
return true
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
# Get the script name
|
|
346
|
+
begin
|
|
347
|
+
# the rest of the arguments get passed in through the binding
|
|
348
|
+
client.execute_script(args.shift, args)
|
|
349
|
+
rescue
|
|
350
|
+
print_error("Error in script: #{$!.class} #{$!}")
|
|
351
|
+
elog("Error in script: #{$!.class} #{$!}")
|
|
352
|
+
dlog("Callstack: #{$@.join("\n")}")
|
|
353
|
+
end
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
def cmd_run_tabs(str, words)
|
|
357
|
+
if(not words[1] or not words[1].match(/^\//))
|
|
358
|
+
begin
|
|
359
|
+
my_directory = Msf::Config.script_directory + ::File::SEPARATOR + "meterpreter"
|
|
360
|
+
return ::Dir.new(my_directory).find_all { |e|
|
|
361
|
+
path = my_directory + ::File::SEPARATOR + e
|
|
362
|
+
::File.file?(path) and ::File.readable?(path)
|
|
363
|
+
}.map { |e|
|
|
364
|
+
e.sub!(/\.rb$/, '')
|
|
365
|
+
}
|
|
366
|
+
rescue Exception
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
#
|
|
373
|
+
# Executes a script in the context of the meterpreter session in the background
|
|
374
|
+
#
|
|
375
|
+
def cmd_bgrun(*args)
|
|
376
|
+
if args.length == 0
|
|
377
|
+
print_line(
|
|
378
|
+
"Usage: bgrun <script> [arguments]\n\n" +
|
|
379
|
+
"Executes a ruby script in the context of the meterpreter session.")
|
|
380
|
+
return true
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
jid = self.bgjob_id
|
|
384
|
+
self.bgjob_id += 1
|
|
385
|
+
|
|
386
|
+
# Get the script name
|
|
387
|
+
self.bgjobs[jid] = ::Thread.new(jid,args) do |myjid,xargs|
|
|
388
|
+
::Thread.current[:args] = xargs.dup
|
|
389
|
+
begin
|
|
390
|
+
# the rest of the arguments get passed in through the binding
|
|
391
|
+
client.execute_script(args.shift, args)
|
|
392
|
+
rescue ::Exception
|
|
393
|
+
print_error("Error in script: #{$!.class} #{$!}")
|
|
394
|
+
elog("Error in script: #{$!.class} #{$!}")
|
|
395
|
+
dlog("Callstack: #{$@.join("\n")}")
|
|
396
|
+
end
|
|
397
|
+
self.bgjobs[myjid] = nil
|
|
398
|
+
print_status("Background script with Job ID #{myjid} has completed (#{::Thread.current[:args].inspect})")
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
print_status("Executed Meterpreter with Job ID #{jid}")
|
|
402
|
+
end
|
|
403
|
+
|
|
404
|
+
#
|
|
405
|
+
# Map this to the normal run command tab completion
|
|
406
|
+
#
|
|
407
|
+
def cmd_bgrun_tabs(*args)
|
|
408
|
+
cmd_run_tabs(*args)
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
#
|
|
412
|
+
# Kill a background job
|
|
413
|
+
#
|
|
414
|
+
def cmd_bgkill(*args)
|
|
415
|
+
if args.length == 0
|
|
416
|
+
print_line("Usage: bgkill [id]")
|
|
417
|
+
return
|
|
418
|
+
end
|
|
419
|
+
|
|
420
|
+
args.each do |jid|
|
|
421
|
+
jid = jid.to_i
|
|
422
|
+
if self.bgjobs[jid]
|
|
423
|
+
print_status("Killing background job #{jid}...")
|
|
424
|
+
self.bgjobs[jid].kill
|
|
425
|
+
self.bgjobs[jid] = nil
|
|
426
|
+
else
|
|
427
|
+
print_error("Job #{jid} was not running")
|
|
428
|
+
end
|
|
429
|
+
end
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
#
|
|
433
|
+
# List background jobs
|
|
434
|
+
#
|
|
435
|
+
def cmd_bglist(*args)
|
|
436
|
+
self.bgjobs.each_index do |jid|
|
|
437
|
+
if self.bgjobs[jid]
|
|
438
|
+
print_status("Job #{jid}: #{self.bgjobs[jid][:args].inspect}")
|
|
439
|
+
end
|
|
440
|
+
end
|
|
441
|
+
end
|
|
442
|
+
|
|
443
|
+
#
|
|
444
|
+
# Writes data to a channel.
|
|
445
|
+
#
|
|
446
|
+
@@write_opts = Rex::Parser::Arguments.new(
|
|
447
|
+
"-f" => [ true, "Write the contents of a file on disk" ],
|
|
448
|
+
"-h" => [ false, "Help menu." ])
|
|
449
|
+
|
|
450
|
+
def cmd_write(*args)
|
|
451
|
+
if (args.length == 0)
|
|
452
|
+
args.unshift("-h")
|
|
453
|
+
end
|
|
454
|
+
|
|
455
|
+
src_file = nil
|
|
456
|
+
cid = nil
|
|
457
|
+
|
|
458
|
+
@@write_opts.parse(args) { |opt, idx, val|
|
|
459
|
+
case opt
|
|
460
|
+
when "-h"
|
|
461
|
+
print(
|
|
462
|
+
"Usage: write [options] channel_id\n\n" +
|
|
463
|
+
"Writes data to the supplied channel.\n" +
|
|
464
|
+
@@write_opts.usage)
|
|
465
|
+
return true
|
|
466
|
+
when "-f"
|
|
467
|
+
src_file = val
|
|
468
|
+
else
|
|
469
|
+
cid = val.to_i
|
|
470
|
+
end
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
# Find the channel associated with this cid, assuming the cid is valid.
|
|
474
|
+
if ((!cid) or
|
|
475
|
+
(!(channel = client.find_channel(cid))))
|
|
476
|
+
print_error("Invalid channel identifier specified.")
|
|
477
|
+
return true
|
|
478
|
+
end
|
|
479
|
+
|
|
480
|
+
# If they supplied a source file, read in its contents and write it to
|
|
481
|
+
# the channel
|
|
482
|
+
if (src_file)
|
|
483
|
+
begin
|
|
484
|
+
data = ''
|
|
485
|
+
|
|
486
|
+
::File.open(src_file, 'rb') { |f|
|
|
487
|
+
data = f.read(f.stat.size)
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
rescue Errno::ENOENT
|
|
491
|
+
print_error("Invalid source file specified: #{src_file}")
|
|
492
|
+
return true
|
|
493
|
+
end
|
|
494
|
+
|
|
495
|
+
if (data and data.length > 0)
|
|
496
|
+
channel.write(data)
|
|
497
|
+
print_status("Wrote #{data.length} bytes to channel #{cid}.")
|
|
498
|
+
else
|
|
499
|
+
print_error("No data to send from file #{src_file}")
|
|
500
|
+
return true
|
|
501
|
+
end
|
|
502
|
+
# Otherwise, read from the input descriptor until we're good to go.
|
|
503
|
+
else
|
|
504
|
+
print("Enter data followed by a '.' on an empty line:\n\n")
|
|
505
|
+
|
|
506
|
+
data = ''
|
|
507
|
+
|
|
508
|
+
# Keep truckin'
|
|
509
|
+
while (s = shell.input.gets)
|
|
510
|
+
break if (s =~ /^\.\r?\n?$/)
|
|
511
|
+
data += s
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
if (!data or data.length == 0)
|
|
515
|
+
print_error("No data to send.")
|
|
516
|
+
else
|
|
517
|
+
channel.write(data)
|
|
518
|
+
print_status("Wrote #{data.length} bytes to channel #{cid}.")
|
|
519
|
+
end
|
|
520
|
+
end
|
|
521
|
+
|
|
522
|
+
return true
|
|
523
|
+
end
|
|
524
|
+
|
|
525
|
+
#
|
|
526
|
+
# Provide command-specific tab completion
|
|
527
|
+
# Stolen directly from msf/ui/console/command_dispatcher/core.rb
|
|
528
|
+
# perhaps this should be moved into rex/ui/text/dispatcher_shell.rb ?
|
|
529
|
+
#
|
|
530
|
+
def tab_complete_helper(str, words)
|
|
531
|
+
items = []
|
|
532
|
+
|
|
533
|
+
# Is the user trying to tab complete one of our commands?
|
|
534
|
+
if (commands.include?(words[0]))
|
|
535
|
+
if (self.respond_to?('cmd_'+words[0]+'_tabs'))
|
|
536
|
+
res = self.send('cmd_'+words[0]+'_tabs', str, words)
|
|
537
|
+
return nil if res.nil?
|
|
538
|
+
items.concat(res)
|
|
539
|
+
else
|
|
540
|
+
# Avoid the default completion list for known commands
|
|
541
|
+
return nil
|
|
542
|
+
end
|
|
543
|
+
end
|
|
544
|
+
|
|
545
|
+
return items
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
protected
|
|
549
|
+
|
|
550
|
+
attr_accessor :extensions # :nodoc:
|
|
551
|
+
attr_accessor :bgjobs, :bgjob_id # :nodoc:
|
|
552
|
+
|
|
553
|
+
CommDispatcher = Console::CommandDispatcher
|
|
554
|
+
|
|
555
|
+
#
|
|
556
|
+
# Loads the client extension specified in mod
|
|
557
|
+
#
|
|
558
|
+
def add_extension_client(mod)
|
|
559
|
+
path = "post/meterpreter/ui/console/command_dispatcher/#{mod}.rb"
|
|
560
|
+
|
|
561
|
+
if ((klass = CommDispatcher.check_hash(path)) == nil)
|
|
562
|
+
clirb = File.join(Rex::Root, path)
|
|
563
|
+
old = CommDispatcher.constants
|
|
564
|
+
|
|
565
|
+
if (require(clirb))
|
|
566
|
+
new = CommDispatcher.constants
|
|
567
|
+
diff = new - old
|
|
568
|
+
|
|
569
|
+
if (diff.empty? == true)
|
|
570
|
+
print_error("Failed to load client portion of #{mod}.")
|
|
571
|
+
return false
|
|
572
|
+
end
|
|
573
|
+
|
|
574
|
+
klass = CommDispatcher.const_get(diff[0])
|
|
575
|
+
|
|
576
|
+
CommDispatcher.set_hash(path, klass)
|
|
577
|
+
else
|
|
578
|
+
print_error("Failed to load client script file: #{clirb}")
|
|
579
|
+
return false
|
|
580
|
+
end
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
# Enstack the dispatcher
|
|
584
|
+
self.shell.enstack_dispatcher(klass)
|
|
585
|
+
|
|
586
|
+
# Insert the module into the list of extensions
|
|
587
|
+
self.extensions << mod
|
|
588
|
+
end
|
|
589
|
+
end
|
|
590
|
+
|
|
591
|
+
end
|
|
592
|
+
end
|
|
593
|
+
end
|
|
594
|
+
end
|
|
595
|
+
|