dstruct 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.
- checksums.yaml +15 -0
- data/README.markdown +23 -0
- data/examples/smb_example.rb +35 -0
- data/lib/rex.rb +108 -0
- data/lib/rex/LICENSE +29 -0
- data/lib/rex/arch.rb +104 -0
- data/lib/rex/arch/sparc.rb +75 -0
- data/lib/rex/arch/x86.rb +524 -0
- data/lib/rex/assembly/nasm.rb +104 -0
- data/lib/rex/codepage.map +104 -0
- data/lib/rex/compat.rb +389 -0
- data/lib/rex/constants.rb +124 -0
- data/lib/rex/elfparsey.rb +9 -0
- data/lib/rex/elfparsey/elf.rb +121 -0
- data/lib/rex/elfparsey/elfbase.rb +256 -0
- data/lib/rex/elfparsey/exceptions.rb +25 -0
- data/lib/rex/elfscan.rb +10 -0
- data/lib/rex/elfscan/scanner.rb +226 -0
- data/lib/rex/elfscan/search.rb +44 -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 +90 -0
- data/lib/rex/encoder/alpha2/unicode_mixed.rb +116 -0
- data/lib/rex/encoder/alpha2/unicode_upper.rb +123 -0
- data/lib/rex/encoder/bloxor/bloxor.rb +327 -0
- data/lib/rex/encoder/ndr.rb +90 -0
- data/lib/rex/encoder/nonalpha.rb +61 -0
- data/lib/rex/encoder/nonupper.rb +64 -0
- data/lib/rex/encoder/xdr.rb +107 -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/encoding/xor.rb +20 -0
- data/lib/rex/encoding/xor/byte.rb +15 -0
- data/lib/rex/encoding/xor/dword.rb +21 -0
- data/lib/rex/encoding/xor/dword_additive.rb +92 -0
- data/lib/rex/encoding/xor/exceptions.rb +17 -0
- data/lib/rex/encoding/xor/generic.rb +146 -0
- data/lib/rex/encoding/xor/qword.rb +15 -0
- data/lib/rex/encoding/xor/word.rb +21 -0
- data/lib/rex/exceptions.rb +275 -0
- data/lib/rex/exploitation/cmdstager.rb +10 -0
- data/lib/rex/exploitation/cmdstager/base.rb +190 -0
- data/lib/rex/exploitation/cmdstager/bourne.rb +105 -0
- data/lib/rex/exploitation/cmdstager/debug_asm.rb +140 -0
- data/lib/rex/exploitation/cmdstager/debug_write.rb +134 -0
- data/lib/rex/exploitation/cmdstager/echo.rb +164 -0
- data/lib/rex/exploitation/cmdstager/printf.rb +122 -0
- data/lib/rex/exploitation/cmdstager/tftp.rb +71 -0
- data/lib/rex/exploitation/cmdstager/vbs.rb +126 -0
- data/lib/rex/exploitation/egghunter.rb +425 -0
- data/lib/rex/exploitation/encryptjs.rb +78 -0
- data/lib/rex/exploitation/heaplib.js.b64 +331 -0
- data/lib/rex/exploitation/heaplib.rb +107 -0
- data/lib/rex/exploitation/js.rb +6 -0
- data/lib/rex/exploitation/js/detect.rb +69 -0
- data/lib/rex/exploitation/js/memory.rb +81 -0
- data/lib/rex/exploitation/js/network.rb +84 -0
- data/lib/rex/exploitation/js/utils.rb +33 -0
- data/lib/rex/exploitation/jsobfu.rb +513 -0
- data/lib/rex/exploitation/obfuscatejs.rb +336 -0
- data/lib/rex/exploitation/omelet.rb +321 -0
- data/lib/rex/exploitation/opcodedb.rb +819 -0
- data/lib/rex/exploitation/powershell.rb +62 -0
- data/lib/rex/exploitation/powershell/function.rb +63 -0
- data/lib/rex/exploitation/powershell/obfu.rb +98 -0
- data/lib/rex/exploitation/powershell/output.rb +151 -0
- data/lib/rex/exploitation/powershell/param.rb +23 -0
- data/lib/rex/exploitation/powershell/parser.rb +183 -0
- data/lib/rex/exploitation/powershell/psh_methods.rb +70 -0
- data/lib/rex/exploitation/powershell/script.rb +99 -0
- data/lib/rex/exploitation/ropdb.rb +190 -0
- data/lib/rex/exploitation/seh.rb +93 -0
- data/lib/rex/file.rb +160 -0
- data/lib/rex/image_source.rb +10 -0
- data/lib/rex/image_source/disk.rb +58 -0
- data/lib/rex/image_source/image_source.rb +44 -0
- data/lib/rex/image_source/memory.rb +35 -0
- data/lib/rex/io/bidirectional_pipe.rb +161 -0
- data/lib/rex/io/datagram_abstraction.rb +35 -0
- data/lib/rex/io/ring_buffer.rb +369 -0
- data/lib/rex/io/stream.rb +312 -0
- data/lib/rex/io/stream_abstraction.rb +209 -0
- data/lib/rex/io/stream_server.rb +221 -0
- data/lib/rex/job_container.rb +200 -0
- data/lib/rex/logging.rb +4 -0
- data/lib/rex/logging/log_dispatcher.rb +180 -0
- data/lib/rex/logging/log_sink.rb +43 -0
- data/lib/rex/logging/sinks/flatfile.rb +56 -0
- data/lib/rex/logging/sinks/stderr.rb +44 -0
- data/lib/rex/mac_oui.rb +16581 -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 +10 -0
- data/lib/rex/mime/encoding.rb +17 -0
- data/lib/rex/mime/header.rb +78 -0
- data/lib/rex/mime/message.rb +150 -0
- data/lib/rex/mime/part.rb +50 -0
- data/lib/rex/nop/opty2.rb +109 -0
- data/lib/rex/nop/opty2_tables.rb +301 -0
- data/lib/rex/ole.rb +202 -0
- data/lib/rex/ole/clsid.rb +44 -0
- data/lib/rex/ole/difat.rb +138 -0
- data/lib/rex/ole/directory.rb +228 -0
- data/lib/rex/ole/direntry.rb +237 -0
- data/lib/rex/ole/docs/dependencies.txt +8 -0
- data/lib/rex/ole/docs/references.txt +1 -0
- data/lib/rex/ole/fat.rb +96 -0
- data/lib/rex/ole/header.rb +201 -0
- data/lib/rex/ole/minifat.rb +74 -0
- data/lib/rex/ole/propset.rb +141 -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 +392 -0
- data/lib/rex/ole/stream.rb +50 -0
- data/lib/rex/ole/substorage.rb +46 -0
- data/lib/rex/ole/util.rb +154 -0
- data/lib/rex/parser/acunetix_nokogiri.rb +406 -0
- data/lib/rex/parser/apple_backup_manifestdb.rb +132 -0
- data/lib/rex/parser/appscan_nokogiri.rb +367 -0
- data/lib/rex/parser/arguments.rb +108 -0
- data/lib/rex/parser/burp_session_nokogiri.rb +291 -0
- data/lib/rex/parser/ci_nokogiri.rb +193 -0
- data/lib/rex/parser/foundstone_nokogiri.rb +342 -0
- data/lib/rex/parser/fusionvm_nokogiri.rb +109 -0
- data/lib/rex/parser/group_policy_preferences.rb +185 -0
- data/lib/rex/parser/ini.rb +186 -0
- data/lib/rex/parser/ip360_aspl_xml.rb +103 -0
- data/lib/rex/parser/ip360_xml.rb +98 -0
- data/lib/rex/parser/mbsa_nokogiri.rb +256 -0
- data/lib/rex/parser/nessus_xml.rb +121 -0
- data/lib/rex/parser/netsparker_xml.rb +109 -0
- data/lib/rex/parser/nexpose_raw_nokogiri.rb +686 -0
- data/lib/rex/parser/nexpose_simple_nokogiri.rb +330 -0
- data/lib/rex/parser/nexpose_xml.rb +172 -0
- data/lib/rex/parser/nmap_nokogiri.rb +394 -0
- data/lib/rex/parser/nmap_xml.rb +166 -0
- data/lib/rex/parser/nokogiri_doc_mixin.rb +233 -0
- data/lib/rex/parser/openvas_nokogiri.rb +172 -0
- data/lib/rex/parser/outpost24_nokogiri.rb +240 -0
- data/lib/rex/parser/retina_xml.rb +110 -0
- data/lib/rex/parser/unattend.rb +171 -0
- data/lib/rex/parser/wapiti_nokogiri.rb +105 -0
- data/lib/rex/payloads.rb +2 -0
- data/lib/rex/payloads/win32.rb +3 -0
- data/lib/rex/payloads/win32/common.rb +27 -0
- data/lib/rex/payloads/win32/kernel.rb +54 -0
- data/lib/rex/payloads/win32/kernel/common.rb +55 -0
- data/lib/rex/payloads/win32/kernel/migration.rb +13 -0
- data/lib/rex/payloads/win32/kernel/recovery.rb +51 -0
- data/lib/rex/payloads/win32/kernel/stager.rb +195 -0
- data/lib/rex/peparsey.rb +10 -0
- data/lib/rex/peparsey/exceptions.rb +30 -0
- data/lib/rex/peparsey/pe.rb +210 -0
- data/lib/rex/peparsey/pe_memdump.rb +61 -0
- data/lib/rex/peparsey/pebase.rb +1662 -0
- data/lib/rex/peparsey/section.rb +128 -0
- data/lib/rex/pescan.rb +11 -0
- data/lib/rex/pescan/analyze.rb +366 -0
- data/lib/rex/pescan/scanner.rb +230 -0
- data/lib/rex/pescan/search.rb +68 -0
- data/lib/rex/platforms.rb +2 -0
- data/lib/rex/platforms/windows.rb +52 -0
- data/lib/rex/poly.rb +134 -0
- data/lib/rex/poly/block.rb +480 -0
- data/lib/rex/poly/machine.rb +13 -0
- data/lib/rex/poly/machine/machine.rb +830 -0
- data/lib/rex/poly/machine/x86.rb +509 -0
- data/lib/rex/poly/register.rb +101 -0
- data/lib/rex/poly/register/x86.rb +41 -0
- data/lib/rex/post.rb +7 -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 +5 -0
- data/lib/rex/post/meterpreter/channel.rb +446 -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 +483 -0
- data/lib/rex/post/meterpreter/client_core.rb +352 -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/android/android.rb +128 -0
- data/lib/rex/post/meterpreter/extensions/android/tlv.rb +40 -0
- data/lib/rex/post/meterpreter/extensions/espia/espia.rb +58 -0
- data/lib/rex/post/meterpreter/extensions/espia/tlv.rb +17 -0
- data/lib/rex/post/meterpreter/extensions/extapi/adsi/adsi.rb +71 -0
- data/lib/rex/post/meterpreter/extensions/extapi/clipboard/clipboard.rb +169 -0
- data/lib/rex/post/meterpreter/extensions/extapi/extapi.rb +45 -0
- data/lib/rex/post/meterpreter/extensions/extapi/service/service.rb +104 -0
- data/lib/rex/post/meterpreter/extensions/extapi/tlv.rb +77 -0
- data/lib/rex/post/meterpreter/extensions/extapi/window/window.rb +56 -0
- data/lib/rex/post/meterpreter/extensions/extapi/wmi/wmi.rb +75 -0
- data/lib/rex/post/meterpreter/extensions/incognito/incognito.rb +94 -0
- data/lib/rex/post/meterpreter/extensions/incognito/tlv.rb +22 -0
- data/lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb +361 -0
- data/lib/rex/post/meterpreter/extensions/kiwi/tlv.rb +76 -0
- data/lib/rex/post/meterpreter/extensions/lanattacks/dhcp/dhcp.rb +78 -0
- data/lib/rex/post/meterpreter/extensions/lanattacks/lanattacks.rb +43 -0
- data/lib/rex/post/meterpreter/extensions/lanattacks/tftp/tftp.rb +49 -0
- data/lib/rex/post/meterpreter/extensions/lanattacks/tlv.rb +17 -0
- data/lib/rex/post/meterpreter/extensions/mimikatz/mimikatz.rb +128 -0
- data/lib/rex/post/meterpreter/extensions/mimikatz/tlv.rb +16 -0
- data/lib/rex/post/meterpreter/extensions/networkpug/networkpug.rb +57 -0
- data/lib/rex/post/meterpreter/extensions/networkpug/tlv.rb +16 -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 +109 -0
- data/lib/rex/post/meterpreter/extensions/priv/tlv.rb +29 -0
- data/lib/rex/post/meterpreter/extensions/sniffer/sniffer.rb +117 -0
- data/lib/rex/post/meterpreter/extensions/sniffer/tlv.rb +27 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/constants.rb +396 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +284 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +399 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/file_stat.rb +104 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/io.rb +48 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/net/arp.rb +59 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/net/config.rb +256 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/net/interface.rb +129 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/net/netstat.rb +97 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/net/resolve.rb +106 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/net/route.rb +67 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/net/socket.rb +139 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_client_channel.rb +180 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_server_channel.rb +168 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb +209 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/api_constants.rb +38146 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/buffer_item.rb +48 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_advapi32.rb +2102 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_crypt32.rb +32 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_iphlpapi.rb +97 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_kernel32.rb +3852 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_netapi32.rb +100 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_ntdll.rb +168 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_psapi.rb +32 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_shell32.rb +32 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_user32.rb +3170 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_version.rb +41 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_wlanapi.rb +87 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_wldap32.rb +128 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_ws2_32.rb +613 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb +388 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_function.rb +111 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_helper.rb +149 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_wrapper.rb +27 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/mock_magic.rb +515 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/multicall.rb +319 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/platform_util.rb +23 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb +301 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/tlv.rb +56 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/type/pointer_util.rb +106 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/util.rb +676 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/win_const_manager.rb +96 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb +151 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb +128 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log.rb +192 -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 +60 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb +408 -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 +328 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb +193 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_value.rb +102 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/remote_registry_key.rb +188 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/thread.rb +180 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +236 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/ui.rb +259 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb +201 -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 +709 -0
- data/lib/rex/post/meterpreter/packet_dispatcher.rb +543 -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 +142 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher.rb +86 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/android.rb +383 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +939 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/espia.rb +109 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi.rb +65 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/adsi.rb +198 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/clipboard.rb +444 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/service.rb +199 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/window.rb +118 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/wmi.rb +108 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/incognito.rb +242 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb +509 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks.rb +60 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks/dhcp.rb +254 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks/tftp.rb +159 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/mimikatz.rb +182 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/networkpug.rb +232 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv.rb +62 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb +97 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/passwd.rb +52 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/timestomp.rb +133 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/sniffer.rb +204 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi.rb +66 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +527 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb +448 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +906 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb +318 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/webcam.rb +343 -0
- data/lib/rex/post/meterpreter/ui/console/interactive_channel.rb +99 -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 +15 -0
- data/lib/rex/proto/addp.rb +218 -0
- data/lib/rex/proto/dcerpc.rb +7 -0
- data/lib/rex/proto/dcerpc/client.rb +362 -0
- data/lib/rex/proto/dcerpc/exceptions.rb +151 -0
- data/lib/rex/proto/dcerpc/handle.rb +48 -0
- data/lib/rex/proto/dcerpc/ndr.rb +73 -0
- data/lib/rex/proto/dcerpc/packet.rb +264 -0
- data/lib/rex/proto/dcerpc/response.rb +188 -0
- data/lib/rex/proto/dcerpc/uuid.rb +85 -0
- data/lib/rex/proto/dcerpc/wdscp.rb +3 -0
- data/lib/rex/proto/dcerpc/wdscp/constants.rb +89 -0
- data/lib/rex/proto/dcerpc/wdscp/packet.rb +94 -0
- data/lib/rex/proto/dhcp.rb +7 -0
- data/lib/rex/proto/dhcp/constants.rb +34 -0
- data/lib/rex/proto/dhcp/server.rb +334 -0
- data/lib/rex/proto/drda.rb +6 -0
- data/lib/rex/proto/drda/constants.rb +50 -0
- data/lib/rex/proto/drda/packet.rb +253 -0
- data/lib/rex/proto/drda/utils.rb +124 -0
- data/lib/rex/proto/http.rb +7 -0
- data/lib/rex/proto/http/client.rb +722 -0
- data/lib/rex/proto/http/client_request.rb +472 -0
- data/lib/rex/proto/http/handler.rb +47 -0
- data/lib/rex/proto/http/handler/erb.rb +129 -0
- data/lib/rex/proto/http/handler/proc.rb +61 -0
- data/lib/rex/proto/http/header.rb +173 -0
- data/lib/rex/proto/http/packet.rb +414 -0
- data/lib/rex/proto/http/request.rb +354 -0
- data/lib/rex/proto/http/response.rb +151 -0
- data/lib/rex/proto/http/server.rb +385 -0
- data/lib/rex/proto/iax2.rb +2 -0
- data/lib/rex/proto/iax2/call.rb +326 -0
- data/lib/rex/proto/iax2/client.rb +218 -0
- data/lib/rex/proto/iax2/codecs.rb +5 -0
- data/lib/rex/proto/iax2/codecs/alaw.rb +16 -0
- data/lib/rex/proto/iax2/codecs/g711.rb +2176 -0
- data/lib/rex/proto/iax2/codecs/mulaw.rb +17 -0
- data/lib/rex/proto/iax2/constants.rb +262 -0
- data/lib/rex/proto/ipmi.rb +57 -0
- data/lib/rex/proto/ipmi/channel_auth_reply.rb +89 -0
- data/lib/rex/proto/ipmi/open_session_reply.rb +36 -0
- data/lib/rex/proto/ipmi/rakp2.rb +36 -0
- data/lib/rex/proto/ipmi/utils.rb +125 -0
- data/lib/rex/proto/natpmp.rb +7 -0
- data/lib/rex/proto/natpmp/constants.rb +19 -0
- data/lib/rex/proto/natpmp/packet.rb +45 -0
- data/lib/rex/proto/ntlm.rb +8 -0
- data/lib/rex/proto/ntlm/base.rb +327 -0
- data/lib/rex/proto/ntlm/constants.rb +75 -0
- data/lib/rex/proto/ntlm/crypt.rb +412 -0
- data/lib/rex/proto/ntlm/exceptions.rb +17 -0
- data/lib/rex/proto/ntlm/message.rb +534 -0
- data/lib/rex/proto/ntlm/utils.rb +765 -0
- data/lib/rex/proto/ntp.rb +3 -0
- data/lib/rex/proto/ntp/constants.rb +12 -0
- data/lib/rex/proto/ntp/modes.rb +130 -0
- data/lib/rex/proto/pjl.rb +31 -0
- data/lib/rex/proto/pjl/client.rb +163 -0
- data/lib/rex/proto/proxy/socks4a.rb +441 -0
- data/lib/rex/proto/rfb.rb +13 -0
- data/lib/rex/proto/rfb/cipher.rb +82 -0
- data/lib/rex/proto/rfb/client.rb +205 -0
- data/lib/rex/proto/rfb/constants.rb +50 -0
- data/lib/rex/proto/sip.rb +4 -0
- data/lib/rex/proto/sip/response.rb +61 -0
- data/lib/rex/proto/smb.rb +8 -0
- data/lib/rex/proto/smb/client.rb +2064 -0
- data/lib/rex/proto/smb/constants.rb +1064 -0
- data/lib/rex/proto/smb/crypt.rb +37 -0
- data/lib/rex/proto/smb/evasions.rb +67 -0
- data/lib/rex/proto/smb/exceptions.rb +867 -0
- data/lib/rex/proto/smb/simpleclient.rb +173 -0
- data/lib/rex/proto/smb/simpleclient/open_file.rb +106 -0
- data/lib/rex/proto/smb/simpleclient/open_pipe.rb +57 -0
- data/lib/rex/proto/smb/utils.rb +104 -0
- data/lib/rex/proto/sunrpc.rb +2 -0
- data/lib/rex/proto/sunrpc/client.rb +196 -0
- data/lib/rex/proto/tftp.rb +13 -0
- data/lib/rex/proto/tftp/client.rb +344 -0
- data/lib/rex/proto/tftp/constants.rb +39 -0
- data/lib/rex/proto/tftp/server.rb +497 -0
- data/lib/rex/random_identifier_generator.rb +177 -0
- data/lib/rex/registry.rb +14 -0
- data/lib/rex/registry/hive.rb +132 -0
- data/lib/rex/registry/lfkey.rb +51 -0
- data/lib/rex/registry/nodekey.rb +54 -0
- data/lib/rex/registry/regf.rb +25 -0
- data/lib/rex/registry/valuekey.rb +67 -0
- data/lib/rex/registry/valuelist.rb +29 -0
- data/lib/rex/ropbuilder.rb +8 -0
- data/lib/rex/ropbuilder/rop.rb +271 -0
- data/lib/rex/script.rb +42 -0
- data/lib/rex/script/base.rb +61 -0
- data/lib/rex/script/meterpreter.rb +16 -0
- data/lib/rex/script/shell.rb +10 -0
- data/lib/rex/service.rb +49 -0
- data/lib/rex/service_manager.rb +154 -0
- data/lib/rex/services/local_relay.rb +424 -0
- data/lib/rex/socket.rb +788 -0
- data/lib/rex/socket/comm.rb +120 -0
- data/lib/rex/socket/comm/local.rb +526 -0
- data/lib/rex/socket/ip.rb +132 -0
- data/lib/rex/socket/parameters.rb +363 -0
- data/lib/rex/socket/range_walker.rb +470 -0
- data/lib/rex/socket/ssl_tcp.rb +345 -0
- data/lib/rex/socket/ssl_tcp_server.rb +188 -0
- data/lib/rex/socket/subnet_walker.rb +76 -0
- data/lib/rex/socket/switch_board.rb +289 -0
- data/lib/rex/socket/tcp.rb +79 -0
- data/lib/rex/socket/tcp_server.rb +67 -0
- data/lib/rex/socket/udp.rb +165 -0
- data/lib/rex/sslscan/result.rb +201 -0
- data/lib/rex/sslscan/scanner.rb +206 -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 +85 -0
- data/lib/rex/sync/read_write_lock.rb +177 -0
- data/lib/rex/sync/ref.rb +58 -0
- data/lib/rex/sync/thread_safe.rb +83 -0
- data/lib/rex/text.rb +1813 -0
- data/lib/rex/thread_factory.rb +43 -0
- data/lib/rex/time.rb +66 -0
- data/lib/rex/transformer.rb +116 -0
- data/lib/rex/ui.rb +22 -0
- data/lib/rex/ui/interactive.rb +304 -0
- data/lib/rex/ui/output.rb +85 -0
- data/lib/rex/ui/output/none.rb +19 -0
- data/lib/rex/ui/progress_tracker.rb +97 -0
- data/lib/rex/ui/subscriber.rb +160 -0
- data/lib/rex/ui/text/color.rb +98 -0
- data/lib/rex/ui/text/dispatcher_shell.rb +538 -0
- data/lib/rex/ui/text/input.rb +119 -0
- data/lib/rex/ui/text/input/buffer.rb +79 -0
- data/lib/rex/ui/text/input/readline.rb +129 -0
- data/lib/rex/ui/text/input/socket.rb +96 -0
- data/lib/rex/ui/text/input/stdio.rb +46 -0
- data/lib/rex/ui/text/irb_shell.rb +62 -0
- data/lib/rex/ui/text/output.rb +86 -0
- data/lib/rex/ui/text/output/buffer.rb +62 -0
- data/lib/rex/ui/text/output/buffer/stdout.rb +26 -0
- data/lib/rex/ui/text/output/file.rb +44 -0
- data/lib/rex/ui/text/output/socket.rb +44 -0
- data/lib/rex/ui/text/output/stdio.rb +53 -0
- data/lib/rex/ui/text/output/tee.rb +56 -0
- data/lib/rex/ui/text/progress_tracker.rb +57 -0
- data/lib/rex/ui/text/shell.rb +403 -0
- data/lib/rex/ui/text/table.rb +346 -0
- data/lib/rex/zip.rb +96 -0
- data/lib/rex/zip/archive.rb +130 -0
- data/lib/rex/zip/blocks.rb +184 -0
- data/lib/rex/zip/entry.rb +122 -0
- data/lib/rex/zip/jar.rb +283 -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 +536 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# -*- coding: binary -*-
|
|
2
|
+
require 'rex/proto/drda'
|
|
3
|
+
|
|
4
|
+
module Rex
|
|
5
|
+
module Proto
|
|
6
|
+
module DRDA
|
|
7
|
+
class Constants
|
|
8
|
+
|
|
9
|
+
require 'rex/text'
|
|
10
|
+
|
|
11
|
+
# DRDA Code Points
|
|
12
|
+
|
|
13
|
+
EXCSAT = 0x1041 # Exchange Server Attributes
|
|
14
|
+
EXTNAM = 0x115e # External Name
|
|
15
|
+
MGRLVLLS = 0x1404 # Manager-Level List
|
|
16
|
+
SRVCLSNM = 0x1147 # Server Class Name
|
|
17
|
+
SRVNAM = 0x116d # Server Name
|
|
18
|
+
SRVRLSLV = 0x115a # Server Product Release Level
|
|
19
|
+
ACCSEC = 0x106d # Access Security
|
|
20
|
+
SECMEC = 0x11a2 # Security Mechanism
|
|
21
|
+
RDBNAM = 0x2110 # Relational Database Name
|
|
22
|
+
SECTKN = 0x11dc # Security Token
|
|
23
|
+
EXCSATRD = 0x1443 # Server Attributes Reply Data
|
|
24
|
+
ACCSECRD = 0x14ac # Access Security Reply Data
|
|
25
|
+
SRVDGN = 0x1153 # Server Diagnostic Information
|
|
26
|
+
RDBNFNRM = 0x2211 # Relational Database Not Found
|
|
27
|
+
SECCHK = 0x106e # Security Check
|
|
28
|
+
USERID = 0x11a0 # Remote User ID
|
|
29
|
+
PASSWORD = 0x11a1 # Remote Password
|
|
30
|
+
RDBACCCL = 0x210f # RDB Access Manager Class
|
|
31
|
+
PRDID = 0x112e # Product-Specific Identifier
|
|
32
|
+
PRDDTA = 0x2104 # Product-Specific Data
|
|
33
|
+
TYPEDEFNAM = 0x002f # Data Type Definition Name
|
|
34
|
+
TTPEDEFOVR = 0x0035 # TYPEDEF Overrides
|
|
35
|
+
CRRTKN = 0x2135 # Correlation Token
|
|
36
|
+
TRGDFTRT = 0x213b # Target Default Value Return
|
|
37
|
+
SQLCARD = 0x2408 # SQL Communications Area Reply Data
|
|
38
|
+
SECCHKRM = 0x1219 # Security Check Response Message
|
|
39
|
+
SRVCOD = 0x1149 # Severity Code
|
|
40
|
+
SECCHKCD = 0x11a4 # Security Check Code
|
|
41
|
+
ACCRDBRM = 0x2201 # Access to RDB Completed
|
|
42
|
+
|
|
43
|
+
def self.const_values
|
|
44
|
+
self.constants.map {|x| self.const_get x}
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# -*- coding: binary -*-
|
|
2
|
+
require 'rex/proto/drda'
|
|
3
|
+
|
|
4
|
+
module Rex
|
|
5
|
+
module Proto
|
|
6
|
+
module DRDA
|
|
7
|
+
|
|
8
|
+
class Error < StandardError; end
|
|
9
|
+
class RespError < Error; end
|
|
10
|
+
|
|
11
|
+
# See:
|
|
12
|
+
# http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=/com.ibm.db29.doc.drda/db2z_excsat.htm
|
|
13
|
+
class MGRLVLLS_PARAM < Struct.new(:length, :codepoint, :payload)
|
|
14
|
+
def initialize(args={})
|
|
15
|
+
self[:codepoint] = Constants::MGRLVLLS
|
|
16
|
+
self[:payload] = "\x14\x03\x00\x0a\x24\x07\x00\x0a" +
|
|
17
|
+
"\x14\x74\x00\x05\x24\x0f\x00\x08" +
|
|
18
|
+
"\x14\x40\x00\x09\x1c\x08\x04\xb8"
|
|
19
|
+
self[:length] = self[:payload].to_s.size+4
|
|
20
|
+
end
|
|
21
|
+
def to_s
|
|
22
|
+
self.to_a.pack("nna*")
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Currently, only takes a MGRLVLLS param. Extend the struct
|
|
27
|
+
# when more parameters are defined.
|
|
28
|
+
class EXCSAT_DDM < Struct.new(:length, :magic, :format, :correlid, :length2,
|
|
29
|
+
:codepoint, :mgrlvlls)
|
|
30
|
+
|
|
31
|
+
def initialize(args={})
|
|
32
|
+
self[:magic] = 0xd0
|
|
33
|
+
self[:format] = 0x41
|
|
34
|
+
self[:correlid] = 1
|
|
35
|
+
self[:codepoint] = Constants::EXCSAT
|
|
36
|
+
self[:mgrlvlls] = args[:mgrlvlls] || MGRLVLLS_PARAM.new.to_s
|
|
37
|
+
self[:length] = (10 + self[:mgrlvlls].to_s.size)
|
|
38
|
+
self[:length2] = self[:length]-6
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def to_s
|
|
42
|
+
packstr = "nCCnnn"
|
|
43
|
+
packstr += "a*" # Pack smarter as more params are added.
|
|
44
|
+
self.to_a.pack(packstr)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# See http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=/com.ibm.db29.doc.drda/db2z_accsec.htm
|
|
49
|
+
# for all sorts of info about SECMEC.
|
|
50
|
+
class SECMEC_PARAM < Struct.new(:length, :codepoint, :payload)
|
|
51
|
+
def initialize(args={})
|
|
52
|
+
self[:length] = 6
|
|
53
|
+
self[:codepoint] = Constants::SECMEC
|
|
54
|
+
self[:payload] = 3 # Plaintext username and password.
|
|
55
|
+
end
|
|
56
|
+
def to_s
|
|
57
|
+
self.to_a.pack("nnn")
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Relational Database name parameter.
|
|
62
|
+
class RDBNAM_PARAM < Struct.new(:length, :codepoint, :payload)
|
|
63
|
+
def initialize(args={})
|
|
64
|
+
self[:length] = 22 # Since the database name is padded out.
|
|
65
|
+
self[:codepoint] = Constants::RDBNAM
|
|
66
|
+
self[:payload] = encode(args[:payload].to_s)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def encode(str)
|
|
70
|
+
Rex::Text.to_ebcdic([str].pack("A18"))
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def payload=(str)
|
|
74
|
+
self[:payload] = encode(str.to_s)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def to_s
|
|
78
|
+
self.to_a.pack("nna18")
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# The ACCSEC DDM is responsible for picking the security mechanism (SECMEC)
|
|
84
|
+
# which, in our case, will always be plain text username and password. It
|
|
85
|
+
# also sets the relational database name (RDBNAM), if specified. You need
|
|
86
|
+
# one to login, but not to probe.
|
|
87
|
+
class ACCSEC_DDM < Struct.new(:length, :magic, :format, :correlid, :length2,
|
|
88
|
+
:codepoint, :secmec, :rdbnam)
|
|
89
|
+
def initialize(args={})
|
|
90
|
+
self[:magic] = 0xd0
|
|
91
|
+
self[:format] = args[:format] || 0x01
|
|
92
|
+
self[:correlid] = 2
|
|
93
|
+
self[:codepoint] = Constants::ACCSEC
|
|
94
|
+
self[:secmec] = SECMEC_PARAM.new.to_s
|
|
95
|
+
if args[:dbname] # Include a database name if we're given one.
|
|
96
|
+
self[:rdbnam] = RDBNAM_PARAM.new(:payload => args[:dbname]).to_s
|
|
97
|
+
end
|
|
98
|
+
self[:length] = 10 + self[:secmec].to_s.size + self[:rdbnam].to_s.size
|
|
99
|
+
self[:length2] = self[:length]-6
|
|
100
|
+
end
|
|
101
|
+
def dbname=(str)
|
|
102
|
+
self[:rdbnam] = RDBNAM_PARAM.new(:payload => args[:dbname]).to_s
|
|
103
|
+
end
|
|
104
|
+
def to_s
|
|
105
|
+
packstr = "nCCnnna6"
|
|
106
|
+
packstr += "a22" if self[:rdbnam]
|
|
107
|
+
self.to_a.pack(packstr)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
class DDM_PARAM < Struct.new(:length, :codepoint, :payload)
|
|
112
|
+
|
|
113
|
+
def read(str="")
|
|
114
|
+
raise DRDA::Error, "Input isn't a String." if !str.kind_of? String
|
|
115
|
+
raise DRDA::RespError, "DDM_PARAM is too short" if str.size < 4
|
|
116
|
+
(self[:length], self[:codepoint]) =
|
|
117
|
+
str.unpack("nn")
|
|
118
|
+
raise DRDA::RespError, "DDM_PARAM Length is too short" if self[:length] < 4
|
|
119
|
+
rest = str[4,self[:length]-4] # If it's negative or whatever, it'll end up as "".
|
|
120
|
+
self[:payload] = rest.to_s[0,self[:length]-4]
|
|
121
|
+
return self
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def to_s
|
|
125
|
+
self.to_a.pack("nna*")
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
class BASIC_DDM < Struct.new(:length, :magic, :format, :correlid,
|
|
131
|
+
:length2, :codepoint, :payload)
|
|
132
|
+
def initialize
|
|
133
|
+
self[:payload] = []
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def read(str="")
|
|
137
|
+
self[:payload].clear
|
|
138
|
+
raise DRDA::Error, "Input isn't a String." if !str.kind_of? String
|
|
139
|
+
raise DRDA::RespError, "Response is too short." if str.size < 10
|
|
140
|
+
(self[:length],self[:magic],self[:format],
|
|
141
|
+
self[:correlid],self[:length2],self[:codepoint]) =
|
|
142
|
+
str.unpack("nCCnnn")
|
|
143
|
+
sanity_check
|
|
144
|
+
rest = str[10,self[:length2]-4]
|
|
145
|
+
i = 0
|
|
146
|
+
while (i < rest.size)
|
|
147
|
+
if self[:codepoint] == Constants::SQLCARD # These aren't DDM's.
|
|
148
|
+
this_param = rest[i,self[:length]-10]
|
|
149
|
+
else
|
|
150
|
+
this_param = DDM_PARAM.new.read(rest[i,rest.size])
|
|
151
|
+
end
|
|
152
|
+
self[:payload] << this_param
|
|
153
|
+
i += this_param.to_s.size
|
|
154
|
+
end
|
|
155
|
+
return self
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
# Just a quick test.
|
|
159
|
+
def sanity_check
|
|
160
|
+
if self[:length] < 10
|
|
161
|
+
raise DRDA::RespError, "DDM Length is too short."
|
|
162
|
+
elsif self[:length2] < 4
|
|
163
|
+
raise DRDA::RespError, "DDM Length2 is too short."
|
|
164
|
+
elsif self[:length]-6 != self[:length2]
|
|
165
|
+
raise DRDA::RespError, "Codepoint: 0x#{self[:codepoint].to_s(16)} DDM Length2 (0x#{self[:length2].to_s(16)}) isn't six less than Length (0x#{self[:length].to_s(16)})"
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def to_s
|
|
170
|
+
self.to_a.pack("nCCnnn") + self[:payload].map {|x| x.to_s}.join
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
class SERVER_PACKET < Array
|
|
176
|
+
|
|
177
|
+
def read(str="")
|
|
178
|
+
raise DRDA::Error, "Input isn't a String." if !str.kind_of? String
|
|
179
|
+
self.clear
|
|
180
|
+
i = 0
|
|
181
|
+
while(i < str.size)
|
|
182
|
+
this_ddm = BASIC_DDM.new.read(str[i,str.size])
|
|
183
|
+
self << this_ddm
|
|
184
|
+
i += this_ddm.to_s.size
|
|
185
|
+
end
|
|
186
|
+
return self
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def to_s; self.join; end
|
|
190
|
+
def sz; self.to_s.size; end
|
|
191
|
+
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
class PASSWORD_PARAM < Struct.new(:length, :codepoint, :payload)
|
|
195
|
+
def initialize(args={})
|
|
196
|
+
self[:codepoint] = Constants::PASSWORD
|
|
197
|
+
self[:payload] = Rex::Text.to_ebcdic(args[:payload].to_s)
|
|
198
|
+
self[:length] = self[:payload].size + 4
|
|
199
|
+
end
|
|
200
|
+
def encode(str)
|
|
201
|
+
Rex::Text.to_ebcdic(str)
|
|
202
|
+
end
|
|
203
|
+
def to_s
|
|
204
|
+
self.to_a.pack("nna*")
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
class USERID_PARAM < Struct.new(:length, :codepoint, :payload)
|
|
209
|
+
def initialize(args={})
|
|
210
|
+
self[:codepoint] = Constants::USERID
|
|
211
|
+
self[:payload] = Rex::Text.to_ebcdic(args[:payload].to_s)
|
|
212
|
+
self[:length] = self[:payload].size + 4
|
|
213
|
+
end
|
|
214
|
+
def encode(str)
|
|
215
|
+
Rex::Text.to_ebcdic(str)
|
|
216
|
+
end
|
|
217
|
+
def to_s
|
|
218
|
+
self.to_a.pack("nna*")
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
class SECCHK_DDM < Struct.new(:length, :magic, :format, :correlid, :length2,
|
|
223
|
+
:codepoint, :secmec, :rdbnam, :password, :userid)
|
|
224
|
+
def initialize(args={}) # Takes :dbname, :dbpass, :dbuser
|
|
225
|
+
self[:magic] = 0xd0
|
|
226
|
+
self[:format] = 0x01
|
|
227
|
+
self[:correlid] = 2
|
|
228
|
+
self[:codepoint] = Constants::SECCHK
|
|
229
|
+
self[:secmec] = SECMEC_PARAM.new.to_s
|
|
230
|
+
if args[:dbname] # Include a database name if we're given one.
|
|
231
|
+
self[:rdbnam] = RDBNAM_PARAM.new(:payload => args[:dbname]).to_s
|
|
232
|
+
end
|
|
233
|
+
self[:password] = PASSWORD_PARAM.new(:payload => args[:dbpass]).to_s
|
|
234
|
+
self[:userid] = USERID_PARAM.new(:payload => args[:dbuser]).to_s
|
|
235
|
+
self[:length] = ( 10 + self[:secmec].to_s.size + self[:rdbnam].to_s.size +
|
|
236
|
+
self[:password].to_s.size + self[:userid].to_s.size )
|
|
237
|
+
self[:length2] = self[:length]-6
|
|
238
|
+
end
|
|
239
|
+
def dbname=(str)
|
|
240
|
+
self[:rdbnam] = RDBNAM_PARAM.new(:payload => args[:dbname]).to_s
|
|
241
|
+
end
|
|
242
|
+
def to_s
|
|
243
|
+
packstr = "nCCnnna6"
|
|
244
|
+
packstr += "a22" if self[:rdbnam]
|
|
245
|
+
packstr += "a*a*" # username and password
|
|
246
|
+
self.to_a.pack(packstr)
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# -*- coding: binary -*-
|
|
2
|
+
require 'rex/proto/drda'
|
|
3
|
+
|
|
4
|
+
module Rex
|
|
5
|
+
module Proto
|
|
6
|
+
module DRDA
|
|
7
|
+
class Utils
|
|
8
|
+
|
|
9
|
+
# Creates a packet with EXCSAT_DDM and an ACCSEC_DDM. This will elicit
|
|
10
|
+
# a reponse from the target server.
|
|
11
|
+
def self.client_probe(dbname=nil)
|
|
12
|
+
pkt = [
|
|
13
|
+
EXCSAT_DDM.new,
|
|
14
|
+
ACCSEC_DDM.new(:dbname => dbname)
|
|
15
|
+
]
|
|
16
|
+
pkt.map {|x| x.to_s}.join
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Creates a packet with EXCSAT_DDM and an SECCHK_DDM.
|
|
20
|
+
# In order to ever succeed, you do need a successful probe first.
|
|
21
|
+
def self.client_auth(args={})
|
|
22
|
+
dbname = args[:dbname]
|
|
23
|
+
dbuser = args[:dbuser]
|
|
24
|
+
dbpass = args[:dbpass]
|
|
25
|
+
pkt = [
|
|
26
|
+
ACCSEC_DDM.new(:format => 0x41),
|
|
27
|
+
SECCHK_DDM.new(:dbname => dbname, :dbuser => dbuser, :dbpass => dbpass)
|
|
28
|
+
]
|
|
29
|
+
pkt.map {|x| x.to_s}.join
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.server_packet_info(obj)
|
|
33
|
+
info_hash = {}
|
|
34
|
+
return info_hash unless obj.kind_of? Rex::Proto::DRDA::SERVER_PACKET
|
|
35
|
+
obj.each do |ddm|
|
|
36
|
+
case ddm.codepoint
|
|
37
|
+
when Constants::EXCSATRD
|
|
38
|
+
info_hash.merge!(_info_excsatrd(ddm))
|
|
39
|
+
when Constants::ACCSECRD
|
|
40
|
+
info_hash.merge!(_info_accsecrd(ddm))
|
|
41
|
+
when Constants::RDBNFNRM
|
|
42
|
+
info_hash.merge!(_info_rdbnfnrm(ddm))
|
|
43
|
+
when Constants::SECCHKRM
|
|
44
|
+
info_hash.merge!(_info_secchkrm(ddm))
|
|
45
|
+
else
|
|
46
|
+
next
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
return info_hash
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def self._info_excsatrd(ddm)
|
|
53
|
+
info_hash = {:excsatrd => true}
|
|
54
|
+
ddm.payload.each do |param|
|
|
55
|
+
case param.codepoint
|
|
56
|
+
when Constants::SRVNAM
|
|
57
|
+
info_hash[:instance_name] = Rex::Text.from_ebcdic(param.payload)
|
|
58
|
+
when Constants::SRVCLSNM
|
|
59
|
+
info_hash[:platform] = Rex::Text.from_ebcdic(param.payload)
|
|
60
|
+
when Constants::SRVRLSLV
|
|
61
|
+
info_hash[:version] = Rex::Text.from_ebcdic(param.payload)
|
|
62
|
+
else
|
|
63
|
+
next
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
return info_hash
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def self._info_accsecrd(ddm)
|
|
70
|
+
info_hash = {:accsecrd => true}
|
|
71
|
+
ddm.payload.each do |param|
|
|
72
|
+
case param.codepoint
|
|
73
|
+
when Constants::SECMEC
|
|
74
|
+
info_hash[:plaintext_auth] = true if param.payload =~ /\x00\x03/n
|
|
75
|
+
when Constants::SECCHKCD
|
|
76
|
+
info_hash[:security_check_code] = param.payload.unpack("C").first
|
|
77
|
+
# A little spurious? This is always nonzero when there's no SECCHKRM DDM.
|
|
78
|
+
info_hash[:db_login_success] = false unless info_hash[:security_check_code].zero?
|
|
79
|
+
else
|
|
80
|
+
next
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
return info_hash
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def self._info_rdbnfnrm(ddm)
|
|
87
|
+
info_hash = {:rdbnfnrm => true}
|
|
88
|
+
info_hash[:database_found] = false
|
|
89
|
+
ddm.payload.each do |param|
|
|
90
|
+
case param.codepoint
|
|
91
|
+
when Constants::RDBNAM
|
|
92
|
+
info_hash[:db_name] = Rex::Text.from_ebcdic(param.payload).unpack("A*").first
|
|
93
|
+
when Constants::SRVDGN
|
|
94
|
+
info_hash[:error_message] = Rex::Text.from_ebcdic(param.payload)
|
|
95
|
+
else
|
|
96
|
+
next
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
return info_hash
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def self._info_secchkrm(ddm)
|
|
103
|
+
info_hash = {:secchkrm => true}
|
|
104
|
+
ddm.payload.each do |param|
|
|
105
|
+
case param.codepoint
|
|
106
|
+
when Constants::SRVCOD
|
|
107
|
+
info_hash[:severity_code] = param.payload.unpack("n").first
|
|
108
|
+
when Constants::SECCHKCD
|
|
109
|
+
info_hash[:security_check_code] = param.payload.unpack("C").first
|
|
110
|
+
else
|
|
111
|
+
next
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
if info_hash[:serverity].to_i.zero? and info_hash[:security_check_code].to_i.zero?
|
|
115
|
+
info_hash[:db_login_success] = true
|
|
116
|
+
end
|
|
117
|
+
return info_hash
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
@@ -0,0 +1,722 @@
|
|
|
1
|
+
# -*- coding: binary -*-
|
|
2
|
+
require 'rex/socket'
|
|
3
|
+
require 'rex/proto/http'
|
|
4
|
+
require 'rex/text'
|
|
5
|
+
require 'digest'
|
|
6
|
+
require 'rex/proto/ntlm/crypt'
|
|
7
|
+
require 'rex/proto/ntlm/constants'
|
|
8
|
+
require 'rex/proto/ntlm/utils'
|
|
9
|
+
require 'rex/proto/ntlm/exceptions'
|
|
10
|
+
|
|
11
|
+
require 'rex/proto/http/client_request'
|
|
12
|
+
|
|
13
|
+
module Rex
|
|
14
|
+
module Proto
|
|
15
|
+
module Http
|
|
16
|
+
|
|
17
|
+
###
|
|
18
|
+
#
|
|
19
|
+
# Acts as a client to an HTTP server, sending requests and receiving responses.
|
|
20
|
+
#
|
|
21
|
+
# See the RFC: http://www.w3.org/Protocols/rfc2616/rfc2616.html
|
|
22
|
+
#
|
|
23
|
+
###
|
|
24
|
+
class Client
|
|
25
|
+
|
|
26
|
+
DefaultUserAgent = ClientRequest::DefaultUserAgent
|
|
27
|
+
|
|
28
|
+
#
|
|
29
|
+
# Creates a new client instance
|
|
30
|
+
#
|
|
31
|
+
def initialize(host, port = 80, context = {}, ssl = nil, ssl_version = nil, proxies = nil, username = '', password = '')
|
|
32
|
+
self.hostname = host
|
|
33
|
+
self.port = port.to_i
|
|
34
|
+
self.context = context
|
|
35
|
+
self.ssl = ssl
|
|
36
|
+
self.ssl_version = ssl_version
|
|
37
|
+
self.proxies = proxies
|
|
38
|
+
self.username = username
|
|
39
|
+
self.password = password
|
|
40
|
+
|
|
41
|
+
# Take ClientRequest's defaults, but override with our own
|
|
42
|
+
self.config = Http::ClientRequest::DefaultConfig.merge({
|
|
43
|
+
'read_max_data' => (1024*1024*1),
|
|
44
|
+
'vhost' => self.hostname,
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
# XXX: This info should all be controlled by ClientRequest
|
|
48
|
+
self.config_types = {
|
|
49
|
+
'uri_encode_mode' => ['hex-normal', 'hex-all', 'hex-random', 'u-normal', 'u-random', 'u-all'],
|
|
50
|
+
'uri_encode_count' => 'integer',
|
|
51
|
+
'uri_full_url' => 'bool',
|
|
52
|
+
'pad_method_uri_count' => 'integer',
|
|
53
|
+
'pad_uri_version_count' => 'integer',
|
|
54
|
+
'pad_method_uri_type' => ['space', 'tab', 'apache'],
|
|
55
|
+
'pad_uri_version_type' => ['space', 'tab', 'apache'],
|
|
56
|
+
'method_random_valid' => 'bool',
|
|
57
|
+
'method_random_invalid' => 'bool',
|
|
58
|
+
'method_random_case' => 'bool',
|
|
59
|
+
'version_random_valid' => 'bool',
|
|
60
|
+
'version_random_invalid' => 'bool',
|
|
61
|
+
'version_random_case' => 'bool',
|
|
62
|
+
'uri_dir_self_reference' => 'bool',
|
|
63
|
+
'uri_dir_fake_relative' => 'bool',
|
|
64
|
+
'uri_use_backslashes' => 'bool',
|
|
65
|
+
'pad_fake_headers' => 'bool',
|
|
66
|
+
'pad_fake_headers_count' => 'integer',
|
|
67
|
+
'pad_get_params' => 'bool',
|
|
68
|
+
'pad_get_params_count' => 'integer',
|
|
69
|
+
'pad_post_params' => 'bool',
|
|
70
|
+
'pad_post_params_count' => 'integer',
|
|
71
|
+
'uri_fake_end' => 'bool',
|
|
72
|
+
'uri_fake_params_start' => 'bool',
|
|
73
|
+
'header_folding' => 'bool',
|
|
74
|
+
'chunked_size' => 'integer'
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
#
|
|
81
|
+
# Set configuration options
|
|
82
|
+
#
|
|
83
|
+
def set_config(opts = {})
|
|
84
|
+
opts.each_pair do |var,val|
|
|
85
|
+
# Default type is string
|
|
86
|
+
typ = self.config_types[var] || 'string'
|
|
87
|
+
|
|
88
|
+
# These are enum types
|
|
89
|
+
if(typ.class.to_s == 'Array')
|
|
90
|
+
if not typ.include?(val)
|
|
91
|
+
raise RuntimeError, "The specified value for #{var} is not one of the valid choices"
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# The caller should have converted these to proper ruby types, but
|
|
96
|
+
# take care of the case where they didn't before setting the
|
|
97
|
+
# config.
|
|
98
|
+
|
|
99
|
+
if(typ == 'bool')
|
|
100
|
+
val = (val =~ /^(t|y|1)$/i ? true : false || val === true)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
if(typ == 'integer')
|
|
104
|
+
val = val.to_i
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
self.config[var]=val
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
#
|
|
112
|
+
# Create an arbitrary HTTP request
|
|
113
|
+
#
|
|
114
|
+
# @param opts [Hash]
|
|
115
|
+
# @option opts 'agent' [String] User-Agent header value
|
|
116
|
+
# @option opts 'connection' [String] Connection header value
|
|
117
|
+
# @option opts 'cookie' [String] Cookie header value
|
|
118
|
+
# @option opts 'data' [String] HTTP data (only useful with some methods, see rfc2616)
|
|
119
|
+
# @option opts 'encode' [Bool] URI encode the supplied URI, default: false
|
|
120
|
+
# @option opts 'headers' [Hash] HTTP headers, e.g. <code>{ "X-MyHeader" => "value" }</code>
|
|
121
|
+
# @option opts 'method' [String] HTTP method to use in the request, not limited to standard methods defined by rfc2616, default: GET
|
|
122
|
+
# @option opts 'proto' [String] protocol, default: HTTP
|
|
123
|
+
# @option opts 'query' [String] raw query string
|
|
124
|
+
# @option opts 'raw_headers' [Hash] HTTP headers
|
|
125
|
+
# @option opts 'uri' [String] the URI to request
|
|
126
|
+
# @option opts 'version' [String] version of the protocol, default: 1.1
|
|
127
|
+
# @option opts 'vhost' [String] Host header value
|
|
128
|
+
#
|
|
129
|
+
# @return [ClientRequest]
|
|
130
|
+
def request_raw(opts={})
|
|
131
|
+
opts = self.config.merge(opts)
|
|
132
|
+
|
|
133
|
+
opts['ssl'] = self.ssl
|
|
134
|
+
opts['cgi'] = false
|
|
135
|
+
opts['port'] = self.port
|
|
136
|
+
|
|
137
|
+
req = ClientRequest.new(opts)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
#
|
|
142
|
+
# Create a CGI compatible request
|
|
143
|
+
#
|
|
144
|
+
# @param (see #request_raw)
|
|
145
|
+
# @option opts (see #request_raw)
|
|
146
|
+
# @option opts 'ctype' [String] Content-Type header value, default: +application/x-www-form-urlencoded+
|
|
147
|
+
# @option opts 'encode_params' [Bool] URI encode the GET or POST variables (names and values), default: true
|
|
148
|
+
# @option opts 'vars_get' [Hash] GET variables as a hash to be translated into a query string
|
|
149
|
+
# @option opts 'vars_post' [Hash] POST variables as a hash to be translated into POST data
|
|
150
|
+
#
|
|
151
|
+
# @return [ClientRequest]
|
|
152
|
+
def request_cgi(opts={})
|
|
153
|
+
opts = self.config.merge(opts)
|
|
154
|
+
|
|
155
|
+
opts['ctype'] ||= 'application/x-www-form-urlencoded'
|
|
156
|
+
opts['ssl'] = self.ssl
|
|
157
|
+
opts['cgi'] = true
|
|
158
|
+
opts['port'] = self.port
|
|
159
|
+
|
|
160
|
+
req = ClientRequest.new(opts)
|
|
161
|
+
req
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
#
|
|
165
|
+
# Connects to the remote server if possible.
|
|
166
|
+
#
|
|
167
|
+
# @param t [Fixnum] Timeout
|
|
168
|
+
# @see Rex::Socket::Tcp.create
|
|
169
|
+
# @return [Rex::Socket::Tcp]
|
|
170
|
+
def connect(t = -1)
|
|
171
|
+
# If we already have a connection and we aren't pipelining, close it.
|
|
172
|
+
if (self.conn)
|
|
173
|
+
if !pipelining?
|
|
174
|
+
close
|
|
175
|
+
else
|
|
176
|
+
return self.conn
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
timeout = (t.nil? or t == -1) ? 0 : t
|
|
181
|
+
|
|
182
|
+
self.conn = Rex::Socket::Tcp.create(
|
|
183
|
+
'PeerHost' => self.hostname,
|
|
184
|
+
'PeerPort' => self.port.to_i,
|
|
185
|
+
'LocalHost' => self.local_host,
|
|
186
|
+
'LocalPort' => self.local_port,
|
|
187
|
+
'Context' => self.context,
|
|
188
|
+
'SSL' => self.ssl,
|
|
189
|
+
'SSLVersion' => self.ssl_version,
|
|
190
|
+
'Proxies' => self.proxies,
|
|
191
|
+
'Timeout' => timeout
|
|
192
|
+
)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
#
|
|
196
|
+
# Closes the connection to the remote server.
|
|
197
|
+
#
|
|
198
|
+
def close
|
|
199
|
+
if (self.conn)
|
|
200
|
+
self.conn.shutdown
|
|
201
|
+
self.conn.close unless self.conn.closed?
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
self.conn = nil
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
#
|
|
208
|
+
# Sends a request and gets a response back
|
|
209
|
+
#
|
|
210
|
+
# If the request is a 401, and we have creds, it will attempt to complete
|
|
211
|
+
# authentication and return the final response
|
|
212
|
+
#
|
|
213
|
+
# @return (see #_send_recv)
|
|
214
|
+
def send_recv(req, t = -1, persist=false)
|
|
215
|
+
res = _send_recv(req,t,persist)
|
|
216
|
+
if res and res.code == 401 and res.headers['WWW-Authenticate']
|
|
217
|
+
res = send_auth(res, req.opts, t, persist)
|
|
218
|
+
end
|
|
219
|
+
res
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
#
|
|
223
|
+
# Transmit an HTTP request and receive the response
|
|
224
|
+
#
|
|
225
|
+
# If persist is set, then the request will attempt to reuse an existing
|
|
226
|
+
# connection.
|
|
227
|
+
#
|
|
228
|
+
# Call this directly instead of {#send_recv} if you don't want automatic
|
|
229
|
+
# authentication handling.
|
|
230
|
+
#
|
|
231
|
+
# @return (see #read_response)
|
|
232
|
+
def _send_recv(req, t = -1, persist=false)
|
|
233
|
+
@pipeline = persist
|
|
234
|
+
send_request(req, t)
|
|
235
|
+
res = read_response(t)
|
|
236
|
+
res.request = req.to_s if res
|
|
237
|
+
res
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
#
|
|
241
|
+
# Send an HTTP request to the server
|
|
242
|
+
#
|
|
243
|
+
# @param req [Request,ClientRequest,#to_s] The request to send
|
|
244
|
+
# @param t (see #connect)
|
|
245
|
+
#
|
|
246
|
+
# @return [void]
|
|
247
|
+
def send_request(req, t = -1)
|
|
248
|
+
connect(t)
|
|
249
|
+
conn.put(req.to_s)
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
# Resends an HTTP Request with the propper authentcation headers
|
|
253
|
+
# set. If we do not support the authentication type the server requires
|
|
254
|
+
# we return the original response object
|
|
255
|
+
#
|
|
256
|
+
# @param res [Response] the HTTP Response object
|
|
257
|
+
# @param opts [Hash] the options used to generate the original HTTP request
|
|
258
|
+
# @param t [Fixnum] the timeout for the request in seconds
|
|
259
|
+
# @param persist [Boolean] whether or not to persist the TCP connection (pipelining)
|
|
260
|
+
#
|
|
261
|
+
# @return [Response] the last valid HTTP response object we received
|
|
262
|
+
def send_auth(res, opts, t, persist)
|
|
263
|
+
if opts['username'].nil? or opts['username'] == ''
|
|
264
|
+
if self.username and not (self.username == '')
|
|
265
|
+
opts['username'] = self.username
|
|
266
|
+
opts['password'] = self.password
|
|
267
|
+
else
|
|
268
|
+
opts['username'] = nil
|
|
269
|
+
opts['password'] = nil
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
return res if opts['username'].nil? or opts['username'] == ''
|
|
274
|
+
supported_auths = res.headers['WWW-Authenticate']
|
|
275
|
+
if supported_auths.include? 'Basic'
|
|
276
|
+
opts['headers'] ||= {}
|
|
277
|
+
opts['headers']['Authorization'] = basic_auth_header(opts['username'],opts['password'] )
|
|
278
|
+
req = request_cgi(opts)
|
|
279
|
+
res = _send_recv(req,t,persist)
|
|
280
|
+
return res
|
|
281
|
+
elsif supported_auths.include? "Digest"
|
|
282
|
+
temp_response = digest_auth(opts)
|
|
283
|
+
if temp_response.kind_of? Rex::Proto::Http::Response
|
|
284
|
+
res = temp_response
|
|
285
|
+
end
|
|
286
|
+
return res
|
|
287
|
+
elsif supported_auths.include? "NTLM"
|
|
288
|
+
opts['provider'] = 'NTLM'
|
|
289
|
+
temp_response = negotiate_auth(opts)
|
|
290
|
+
if temp_response.kind_of? Rex::Proto::Http::Response
|
|
291
|
+
res = temp_response
|
|
292
|
+
end
|
|
293
|
+
return res
|
|
294
|
+
elsif supported_auths.include? "Negotiate"
|
|
295
|
+
opts['provider'] = 'Negotiate'
|
|
296
|
+
temp_response = negotiate_auth(opts)
|
|
297
|
+
if temp_response.kind_of? Rex::Proto::Http::Response
|
|
298
|
+
res = temp_response
|
|
299
|
+
end
|
|
300
|
+
return res
|
|
301
|
+
end
|
|
302
|
+
return res
|
|
303
|
+
end
|
|
304
|
+
|
|
305
|
+
# Converts username and password into the HTTP Basic authorization
|
|
306
|
+
# string.
|
|
307
|
+
#
|
|
308
|
+
# @return [String] A value suitable for use as an Authorization header
|
|
309
|
+
def basic_auth_header(username,password)
|
|
310
|
+
auth_str = username.to_s + ":" + password.to_s
|
|
311
|
+
auth_str = "Basic " + Rex::Text.encode_base64(auth_str)
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
# Send a series of requests to complete Digest Authentication
|
|
315
|
+
#
|
|
316
|
+
# @param opts [Hash] the options used to build an HTTP request
|
|
317
|
+
#
|
|
318
|
+
# @return [Response] the last valid HTTP response we received
|
|
319
|
+
def digest_auth(opts={})
|
|
320
|
+
@nonce_count = 0
|
|
321
|
+
|
|
322
|
+
to = opts['timeout'] || 20
|
|
323
|
+
|
|
324
|
+
digest_user = opts['username'] || ""
|
|
325
|
+
digest_password = opts['password'] || ""
|
|
326
|
+
|
|
327
|
+
method = opts['method']
|
|
328
|
+
path = opts['uri']
|
|
329
|
+
iis = true
|
|
330
|
+
if (opts['DigestAuthIIS'] == false or self.config['DigestAuthIIS'] == false)
|
|
331
|
+
iis = false
|
|
332
|
+
end
|
|
333
|
+
|
|
334
|
+
begin
|
|
335
|
+
@nonce_count += 1
|
|
336
|
+
|
|
337
|
+
resp = opts['response']
|
|
338
|
+
|
|
339
|
+
if not resp
|
|
340
|
+
# Get authentication-challenge from server, and read out parameters required
|
|
341
|
+
r = request_cgi(opts.merge({
|
|
342
|
+
'uri' => path,
|
|
343
|
+
'method' => method }))
|
|
344
|
+
resp = _send_recv(r, to)
|
|
345
|
+
unless resp.kind_of? Rex::Proto::Http::Response
|
|
346
|
+
return nil
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
if resp.code != 401
|
|
350
|
+
return resp
|
|
351
|
+
end
|
|
352
|
+
return resp unless resp.headers['WWW-Authenticate']
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
# Don't anchor this regex to the beginning of string because header
|
|
356
|
+
# folding makes it appear later when the server presents multiple
|
|
357
|
+
# WWW-Authentication options (such as is the case with IIS configured
|
|
358
|
+
# for Digest or NTLM).
|
|
359
|
+
resp['www-authenticate'] =~ /Digest (.*)/
|
|
360
|
+
|
|
361
|
+
parameters = {}
|
|
362
|
+
$1.split(/,[[:space:]]*/).each do |p|
|
|
363
|
+
k, v = p.split("=", 2)
|
|
364
|
+
parameters[k] = v.gsub('"', '')
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
qop = parameters['qop']
|
|
368
|
+
|
|
369
|
+
if parameters['algorithm'] =~ /(.*?)(-sess)?$/
|
|
370
|
+
algorithm = case $1
|
|
371
|
+
when 'MD5' then Digest::MD5
|
|
372
|
+
when 'SHA1' then Digest::SHA1
|
|
373
|
+
when 'SHA2' then Digest::SHA2
|
|
374
|
+
when 'SHA256' then Digest::SHA256
|
|
375
|
+
when 'SHA384' then Digest::SHA384
|
|
376
|
+
when 'SHA512' then Digest::SHA512
|
|
377
|
+
when 'RMD160' then Digest::RMD160
|
|
378
|
+
else raise Error, "unknown algorithm \"#{$1}\""
|
|
379
|
+
end
|
|
380
|
+
algstr = parameters["algorithm"]
|
|
381
|
+
sess = $2
|
|
382
|
+
else
|
|
383
|
+
algorithm = Digest::MD5
|
|
384
|
+
algstr = "MD5"
|
|
385
|
+
sess = false
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
a1 = if sess then
|
|
389
|
+
[
|
|
390
|
+
algorithm.hexdigest("#{digest_user}:#{parameters['realm']}:#{digest_password}"),
|
|
391
|
+
parameters['nonce'],
|
|
392
|
+
@cnonce
|
|
393
|
+
].join ':'
|
|
394
|
+
else
|
|
395
|
+
"#{digest_user}:#{parameters['realm']}:#{digest_password}"
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
ha1 = algorithm.hexdigest(a1)
|
|
399
|
+
ha2 = algorithm.hexdigest("#{method}:#{path}")
|
|
400
|
+
|
|
401
|
+
request_digest = [ha1, parameters['nonce']]
|
|
402
|
+
request_digest.push(('%08x' % @nonce_count), @cnonce, qop) if qop
|
|
403
|
+
request_digest << ha2
|
|
404
|
+
request_digest = request_digest.join ':'
|
|
405
|
+
|
|
406
|
+
# Same order as IE7
|
|
407
|
+
auth = [
|
|
408
|
+
"Digest username=\"#{digest_user}\"",
|
|
409
|
+
"realm=\"#{parameters['realm']}\"",
|
|
410
|
+
"nonce=\"#{parameters['nonce']}\"",
|
|
411
|
+
"uri=\"#{path}\"",
|
|
412
|
+
"cnonce=\"#{@cnonce}\"",
|
|
413
|
+
"nc=#{'%08x' % @nonce_count}",
|
|
414
|
+
"algorithm=#{algstr}",
|
|
415
|
+
"response=\"#{algorithm.hexdigest(request_digest)[0, 32]}\"",
|
|
416
|
+
# The spec says the qop value shouldn't be enclosed in quotes, but
|
|
417
|
+
# some versions of IIS require it and Apache accepts it. Chrome
|
|
418
|
+
# and Firefox both send it without quotes but IE does it this way.
|
|
419
|
+
# Use the non-compliant-but-everybody-does-it to be as compatible
|
|
420
|
+
# as possible by default. The user can override if they don't like
|
|
421
|
+
# it.
|
|
422
|
+
if qop.nil? then
|
|
423
|
+
elsif iis then
|
|
424
|
+
"qop=\"#{qop}\""
|
|
425
|
+
else
|
|
426
|
+
"qop=#{qop}"
|
|
427
|
+
end,
|
|
428
|
+
if parameters.key? 'opaque' then
|
|
429
|
+
"opaque=\"#{parameters['opaque']}\""
|
|
430
|
+
end
|
|
431
|
+
].compact
|
|
432
|
+
|
|
433
|
+
headers ={ 'Authorization' => auth.join(', ') }
|
|
434
|
+
headers.merge!(opts['headers']) if opts['headers']
|
|
435
|
+
|
|
436
|
+
# Send main request with authentication
|
|
437
|
+
r = request_cgi(opts.merge({
|
|
438
|
+
'uri' => path,
|
|
439
|
+
'method' => method,
|
|
440
|
+
'headers' => headers }))
|
|
441
|
+
resp = _send_recv(r, to, true)
|
|
442
|
+
unless resp.kind_of? Rex::Proto::Http::Response
|
|
443
|
+
return nil
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
return resp
|
|
447
|
+
|
|
448
|
+
rescue ::Errno::EPIPE, ::Timeout::Error
|
|
449
|
+
end
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
#
|
|
453
|
+
# Builds a series of requests to complete Negotiate Auth. Works essentially
|
|
454
|
+
# the same way as Digest auth. Same pipelining concerns exist.
|
|
455
|
+
#
|
|
456
|
+
# @option opts (see #send_request_cgi)
|
|
457
|
+
# @option opts provider ["Negotiate","NTLM"] What Negotiate provider to use
|
|
458
|
+
#
|
|
459
|
+
# @return [Response] the last valid HTTP response we received
|
|
460
|
+
def negotiate_auth(opts={})
|
|
461
|
+
ntlm_options = {
|
|
462
|
+
:signing => false,
|
|
463
|
+
:usentlm2_session => self.config['usentlm2_session'],
|
|
464
|
+
:use_ntlmv2 => self.config['use_ntlmv2'],
|
|
465
|
+
:send_lm => self.config['send_lm'],
|
|
466
|
+
:send_ntlm => self.config['send_ntlm']
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
to = opts['timeout'] || 20
|
|
470
|
+
opts['username'] ||= ''
|
|
471
|
+
opts['password'] ||= ''
|
|
472
|
+
|
|
473
|
+
if opts['provider'] and opts['provider'].include? 'Negotiate'
|
|
474
|
+
provider = "Negotiate "
|
|
475
|
+
else
|
|
476
|
+
provider = 'NTLM '
|
|
477
|
+
end
|
|
478
|
+
|
|
479
|
+
opts['method']||= 'GET'
|
|
480
|
+
opts['headers']||= {}
|
|
481
|
+
|
|
482
|
+
ntlmssp_flags = ::Rex::Proto::NTLM::Utils.make_ntlm_flags(ntlm_options)
|
|
483
|
+
workstation_name = Rex::Text.rand_text_alpha(rand(8)+6)
|
|
484
|
+
domain_name = self.config['domain']
|
|
485
|
+
|
|
486
|
+
b64_blob = Rex::Text::encode_base64(
|
|
487
|
+
::Rex::Proto::NTLM::Utils::make_ntlmssp_blob_init(
|
|
488
|
+
domain_name,
|
|
489
|
+
workstation_name,
|
|
490
|
+
ntlmssp_flags
|
|
491
|
+
))
|
|
492
|
+
|
|
493
|
+
ntlm_message_1 = provider + b64_blob
|
|
494
|
+
|
|
495
|
+
begin
|
|
496
|
+
# First request to get the challenge
|
|
497
|
+
opts['headers']['Authorization'] = ntlm_message_1
|
|
498
|
+
r = request_cgi(opts)
|
|
499
|
+
resp = _send_recv(r, to)
|
|
500
|
+
unless resp.kind_of? Rex::Proto::Http::Response
|
|
501
|
+
return nil
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
return resp unless resp.code == 401 && resp.headers['WWW-Authenticate']
|
|
505
|
+
|
|
506
|
+
# Get the challenge and craft the response
|
|
507
|
+
ntlm_challenge = resp.headers['WWW-Authenticate'].scan(/#{provider}([A-Z0-9\x2b\x2f=]+)/ni).flatten[0]
|
|
508
|
+
return resp unless ntlm_challenge
|
|
509
|
+
|
|
510
|
+
ntlm_message_2 = Rex::Text::decode_base64(ntlm_challenge)
|
|
511
|
+
blob_data = ::Rex::Proto::NTLM::Utils.parse_ntlm_type_2_blob(ntlm_message_2)
|
|
512
|
+
|
|
513
|
+
challenge_key = blob_data[:challenge_key]
|
|
514
|
+
server_ntlmssp_flags = blob_data[:server_ntlmssp_flags] #else should raise an error
|
|
515
|
+
default_name = blob_data[:default_name] || '' #netbios name
|
|
516
|
+
default_domain = blob_data[:default_domain] || '' #netbios domain
|
|
517
|
+
dns_host_name = blob_data[:dns_host_name] || '' #dns name
|
|
518
|
+
dns_domain_name = blob_data[:dns_domain_name] || '' #dns domain
|
|
519
|
+
chall_MsvAvTimestamp = blob_data[:chall_MsvAvTimestamp] || '' #Client time
|
|
520
|
+
|
|
521
|
+
spnopt = {:use_spn => self.config['SendSPN'], :name => self.hostname}
|
|
522
|
+
|
|
523
|
+
resp_lm, resp_ntlm, client_challenge, ntlm_cli_challenge = ::Rex::Proto::NTLM::Utils.create_lm_ntlm_responses(
|
|
524
|
+
opts['username'],
|
|
525
|
+
opts['password'],
|
|
526
|
+
challenge_key,
|
|
527
|
+
domain_name,
|
|
528
|
+
default_name,
|
|
529
|
+
default_domain,
|
|
530
|
+
dns_host_name,
|
|
531
|
+
dns_domain_name,
|
|
532
|
+
chall_MsvAvTimestamp,
|
|
533
|
+
spnopt,
|
|
534
|
+
ntlm_options
|
|
535
|
+
)
|
|
536
|
+
|
|
537
|
+
ntlm_message_3 = ::Rex::Proto::NTLM::Utils.make_ntlmssp_blob_auth(
|
|
538
|
+
domain_name,
|
|
539
|
+
workstation_name,
|
|
540
|
+
opts['username'],
|
|
541
|
+
resp_lm,
|
|
542
|
+
resp_ntlm,
|
|
543
|
+
'',
|
|
544
|
+
ntlmssp_flags
|
|
545
|
+
)
|
|
546
|
+
|
|
547
|
+
ntlm_message_3 = Rex::Text::encode_base64(ntlm_message_3)
|
|
548
|
+
|
|
549
|
+
# Send the response
|
|
550
|
+
opts['headers']['Authorization'] = "#{provider}#{ntlm_message_3}"
|
|
551
|
+
r = request_cgi(opts)
|
|
552
|
+
resp = _send_recv(r, to, true)
|
|
553
|
+
unless resp.kind_of? Rex::Proto::Http::Response
|
|
554
|
+
return nil
|
|
555
|
+
end
|
|
556
|
+
return resp
|
|
557
|
+
|
|
558
|
+
rescue ::Errno::EPIPE, ::Timeout::Error
|
|
559
|
+
return nil
|
|
560
|
+
end
|
|
561
|
+
end
|
|
562
|
+
#
|
|
563
|
+
# Read a response from the server
|
|
564
|
+
#
|
|
565
|
+
# @return [Response]
|
|
566
|
+
def read_response(t = -1, opts = {})
|
|
567
|
+
|
|
568
|
+
resp = Response.new
|
|
569
|
+
resp.max_data = config['read_max_data']
|
|
570
|
+
|
|
571
|
+
# Wait at most t seconds for the full response to be read in. We only
|
|
572
|
+
# do this if t was specified as a negative value indicating an infinite
|
|
573
|
+
# wait cycle. If t were specified as nil it would indicate that no
|
|
574
|
+
# response parsing is required.
|
|
575
|
+
|
|
576
|
+
return resp if not t
|
|
577
|
+
|
|
578
|
+
Timeout.timeout((t < 0) ? nil : t) do
|
|
579
|
+
|
|
580
|
+
rv = nil
|
|
581
|
+
while (
|
|
582
|
+
rv != Packet::ParseCode::Completed and
|
|
583
|
+
rv != Packet::ParseCode::Error
|
|
584
|
+
)
|
|
585
|
+
|
|
586
|
+
begin
|
|
587
|
+
|
|
588
|
+
buff = conn.get_once(-1, 1)
|
|
589
|
+
rv = resp.parse( buff || '' )
|
|
590
|
+
|
|
591
|
+
# Handle unexpected disconnects
|
|
592
|
+
rescue ::Errno::EPIPE, ::EOFError, ::IOError
|
|
593
|
+
case resp.state
|
|
594
|
+
when Packet::ParseState::ProcessingHeader
|
|
595
|
+
resp = nil
|
|
596
|
+
when Packet::ParseState::ProcessingBody
|
|
597
|
+
# truncated request, good enough
|
|
598
|
+
resp.error = :truncated
|
|
599
|
+
end
|
|
600
|
+
break
|
|
601
|
+
end
|
|
602
|
+
|
|
603
|
+
# This is a dirty hack for broken HTTP servers
|
|
604
|
+
if rv == Packet::ParseCode::Completed
|
|
605
|
+
rbody = resp.body
|
|
606
|
+
rbufq = resp.bufq
|
|
607
|
+
|
|
608
|
+
rblob = rbody.to_s + rbufq.to_s
|
|
609
|
+
tries = 0
|
|
610
|
+
begin
|
|
611
|
+
# XXX: This doesn't deal with chunked encoding or "Content-type: text/html; charset=..."
|
|
612
|
+
while tries < 1000 and resp.headers["Content-Type"]== "text/html" and rblob !~ /<\/html>/i
|
|
613
|
+
buff = conn.get_once(-1, 0.05)
|
|
614
|
+
break if not buff
|
|
615
|
+
rblob += buff
|
|
616
|
+
tries += 1
|
|
617
|
+
end
|
|
618
|
+
rescue ::Errno::EPIPE, ::EOFError, ::IOError
|
|
619
|
+
end
|
|
620
|
+
|
|
621
|
+
resp.bufq = ""
|
|
622
|
+
resp.body = rblob
|
|
623
|
+
end
|
|
624
|
+
end
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
return resp if not resp
|
|
628
|
+
|
|
629
|
+
# As a last minute hack, we check to see if we're dealing with a 100 Continue here.
|
|
630
|
+
# Most of the time this is handled by the parser via check_100()
|
|
631
|
+
if resp.proto == '1.1' and resp.code == 100 and not opts[:skip_100]
|
|
632
|
+
# Read the real response from the body if we found one
|
|
633
|
+
# If so, our real response became the body, so we re-parse it.
|
|
634
|
+
if resp.body.to_s =~ /^HTTP/
|
|
635
|
+
body = resp.body
|
|
636
|
+
resp = Response.new
|
|
637
|
+
resp.max_data = config['read_max_data']
|
|
638
|
+
rv = resp.parse(body)
|
|
639
|
+
# We found a 100 Continue but didn't read the real reply yet
|
|
640
|
+
# Otherwise reread the reply, but don't try this hack again
|
|
641
|
+
else
|
|
642
|
+
resp = read_response(t, :skip_100 => true)
|
|
643
|
+
end
|
|
644
|
+
end
|
|
645
|
+
|
|
646
|
+
resp
|
|
647
|
+
end
|
|
648
|
+
|
|
649
|
+
#
|
|
650
|
+
# Cleans up any outstanding connections and other resources.
|
|
651
|
+
#
|
|
652
|
+
def stop
|
|
653
|
+
close
|
|
654
|
+
end
|
|
655
|
+
|
|
656
|
+
#
|
|
657
|
+
# Returns whether or not the conn is valid.
|
|
658
|
+
#
|
|
659
|
+
def conn?
|
|
660
|
+
conn != nil
|
|
661
|
+
end
|
|
662
|
+
|
|
663
|
+
#
|
|
664
|
+
# Whether or not connections should be pipelined.
|
|
665
|
+
#
|
|
666
|
+
def pipelining?
|
|
667
|
+
pipeline
|
|
668
|
+
end
|
|
669
|
+
|
|
670
|
+
#
|
|
671
|
+
# The client request configuration
|
|
672
|
+
#
|
|
673
|
+
attr_accessor :config
|
|
674
|
+
#
|
|
675
|
+
# The client request configuration classes
|
|
676
|
+
#
|
|
677
|
+
attr_accessor :config_types
|
|
678
|
+
#
|
|
679
|
+
# Whether or not pipelining is in use.
|
|
680
|
+
#
|
|
681
|
+
attr_accessor :pipeline
|
|
682
|
+
#
|
|
683
|
+
# The local host of the client.
|
|
684
|
+
#
|
|
685
|
+
attr_accessor :local_host
|
|
686
|
+
#
|
|
687
|
+
# The local port of the client.
|
|
688
|
+
#
|
|
689
|
+
attr_accessor :local_port
|
|
690
|
+
#
|
|
691
|
+
# The underlying connection.
|
|
692
|
+
#
|
|
693
|
+
attr_accessor :conn
|
|
694
|
+
#
|
|
695
|
+
# The calling context to pass to the socket
|
|
696
|
+
#
|
|
697
|
+
attr_accessor :context
|
|
698
|
+
#
|
|
699
|
+
# The proxy list
|
|
700
|
+
#
|
|
701
|
+
attr_accessor :proxies
|
|
702
|
+
|
|
703
|
+
# Auth
|
|
704
|
+
attr_accessor :username, :password
|
|
705
|
+
|
|
706
|
+
# When parsing the request, thunk off the first response from the server, since junk
|
|
707
|
+
attr_accessor :junk_pipeline
|
|
708
|
+
|
|
709
|
+
protected
|
|
710
|
+
|
|
711
|
+
# https
|
|
712
|
+
attr_accessor :ssl, :ssl_version # :nodoc:
|
|
713
|
+
|
|
714
|
+
attr_accessor :hostname, :port # :nodoc:
|
|
715
|
+
|
|
716
|
+
|
|
717
|
+
end
|
|
718
|
+
|
|
719
|
+
end
|
|
720
|
+
end
|
|
721
|
+
end
|
|
722
|
+
|