librex 0.0.20 → 0.0.21
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/Rakefile +1 -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 +104 -0
- data/lib/rex/assembly/nasm.rb.ut.rb +22 -0
- data/lib/rex/codepage.map +104 -0
- data/lib/rex/compat.rb +311 -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 +258 -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 +114 -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 +9 -0
- data/lib/rex/exploitation/cmdstager/base.rb +175 -0
- data/lib/rex/exploitation/cmdstager/debug_asm.rb +142 -0
- data/lib/rex/exploitation/cmdstager/debug_write.rb +136 -0
- data/lib/rex/exploitation/cmdstager/tftp.rb +63 -0
- data/lib/rex/exploitation/cmdstager/vbs.rb +128 -0
- data/lib/rex/exploitation/egghunter.rb +277 -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 +897 -0
- data/lib/rex/exploitation/obfuscatejs.rb +335 -0
- data/lib/rex/exploitation/omelet.rb +320 -0
- data/lib/rex/exploitation/omelet.rb.ut.rb +13 -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 +112 -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/ring_buffer.rb +364 -0
- data/lib/rex/io/stream.rb +319 -0
- data/lib/rex/io/stream_abstraction.rb +197 -0
- data/lib/rex/io/stream_server.rb +211 -0
- data/lib/rex/job_container.rb +187 -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 +77 -0
- data/lib/rex/mime/message.rb +144 -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 +205 -0
- data/lib/rex/ole/clsid.rb +47 -0
- data/lib/rex/ole/difat.rb +141 -0
- data/lib/rex/ole/directory.rb +231 -0
- data/lib/rex/ole/direntry.rb +240 -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 +99 -0
- data/lib/rex/ole/header.rb +204 -0
- data/lib/rex/ole/minifat.rb +77 -0
- data/lib/rex/ole/propset.rb +144 -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/ip360_aspl_xml.rb +102 -0
- data/lib/rex/parser/ip360_xml.rb +97 -0
- data/lib/rex/parser/nessus_xml.rb +118 -0
- data/lib/rex/parser/netsparker_xml.rb +94 -0
- data/lib/rex/parser/nexpose_xml.rb +136 -0
- data/lib/rex/parser/nmap_xml.rb +137 -0
- data/lib/rex/parser/retina_xml.rb +109 -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 +194 -0
- data/lib/rex/peparsey.rb +12 -0
- data/lib/rex/peparsey/exceptions.rb +32 -0
- data/lib/rex/peparsey/pe.rb +212 -0
- data/lib/rex/peparsey/pe_memdump.rb +63 -0
- data/lib/rex/peparsey/pebase.rb +1680 -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 +477 -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 +445 -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 +364 -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/networkpug/networkpug.rb +57 -0
- data/lib/rex/post/meterpreter/extensions/networkpug/tlv.rb +15 -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 +111 -0
- data/lib/rex/post/meterpreter/extensions/priv/tlv.rb +28 -0
- data/lib/rex/post/meterpreter/extensions/sniffer/sniffer.rb +101 -0
- data/lib/rex/post/meterpreter/extensions/sniffer/tlv.rb +26 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/constants.rb +333 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +282 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +266 -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 +180 -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 +208 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun.rb.ts.rb +6 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/api_constants.rb +38106 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/api_constants.rb.ut.rb +31 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/buffer_item.rb +47 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/buffer_item.rb.ut.rb +36 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_advapi32.rb +1818 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_iphlpapi.rb +96 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_kernel32.rb +3848 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_netapi32.rb +26 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_ntdll.rb +153 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_shell32.rb +21 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_user32.rb +3169 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_ws2_32.rb +599 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb +318 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_function.rb +100 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_function.rb.ut.rb +42 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_helper.rb +148 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_helper.rb.ut.rb +127 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/multicall.rb +309 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb +204 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/tlv.rb +51 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/util.rb +630 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/win_const_manager.rb +75 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/railgun/win_const_manager.rb.ut.rb +103 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb +149 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb +97 -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 +61 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb +370 -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 +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/thread.rb +180 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +211 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/ui.rb +227 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb +63 -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 +688 -0
- data/lib/rex/post/meterpreter/packet_dispatcher.rb +431 -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 +137 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher.rb +62 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +730 -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/networkpug.rb +231 -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 +65 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +442 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb +298 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +486 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb +315 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/webcam.rb +157 -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 +13 -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 +361 -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 +187 -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/dhcp.rb +7 -0
- data/lib/rex/proto/dhcp/constants.rb +33 -0
- data/lib/rex/proto/dhcp/server.rb +292 -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 +821 -0
- data/lib/rex/proto/http/client.rb.ut.rb +95 -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 +60 -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 +407 -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 +90 -0
- data/lib/rex/proto/http/response.rb.ut.rb +149 -0
- data/lib/rex/proto/http/server.rb +369 -0
- data/lib/rex/proto/http/server.rb.ut.rb +79 -0
- data/lib/rex/proto/ntlm.rb +7 -0
- data/lib/rex/proto/ntlm.rb.ut.rb +177 -0
- data/lib/rex/proto/ntlm/base.rb +326 -0
- data/lib/rex/proto/ntlm/constants.rb +74 -0
- data/lib/rex/proto/ntlm/crypt.rb +415 -0
- data/lib/rex/proto/ntlm/exceptions.rb +16 -0
- data/lib/rex/proto/ntlm/message.rb +536 -0
- data/lib/rex/proto/ntlm/utils.rb +764 -0
- data/lib/rex/proto/proxy/socks4a.rb +440 -0
- data/lib/rex/proto/rfb.rb +19 -0
- data/lib/rex/proto/rfb.rb.ut.rb +37 -0
- data/lib/rex/proto/rfb/cipher.rb +84 -0
- data/lib/rex/proto/rfb/client.rb +207 -0
- data/lib/rex/proto/rfb/constants.rb +52 -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 +1952 -0
- data/lib/rex/proto/smb/client.rb.ut.rb +223 -0
- data/lib/rex/proto/smb/constants.rb +1047 -0
- data/lib/rex/proto/smb/constants.rb.ut.rb +18 -0
- data/lib/rex/proto/smb/crypt.rb +36 -0
- data/lib/rex/proto/smb/evasions.rb +66 -0
- data/lib/rex/proto/smb/exceptions.rb +858 -0
- data/lib/rex/proto/smb/simpleclient.rb +306 -0
- data/lib/rex/proto/smb/simpleclient.rb.ut.rb +128 -0
- data/lib/rex/proto/smb/utils.rb +103 -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/proto/tftp.rb +12 -0
- data/lib/rex/proto/tftp/constants.rb +39 -0
- data/lib/rex/proto/tftp/server.rb +497 -0
- data/lib/rex/proto/tftp/server.rb.ut.rb +28 -0
- data/lib/rex/script.rb +42 -0
- data/lib/rex/script/base.rb +59 -0
- data/lib/rex/script/meterpreter.rb +15 -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 +684 -0
- data/lib/rex/socket.rb.ut.rb +107 -0
- data/lib/rex/socket/comm.rb +119 -0
- data/lib/rex/socket/comm/local.rb +412 -0
- data/lib/rex/socket/comm/local.rb.ut.rb +75 -0
- data/lib/rex/socket/ip.rb +130 -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 +346 -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 +61 -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 +278 -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 +66 -0
- data/lib/rex/socket/tcp_server.rb.ut.rb +44 -0
- data/lib/rex/socket/udp.rb +164 -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 +1163 -0
- data/lib/rex/text.rb.ut.rb +190 -0
- data/lib/rex/thread_factory.rb +42 -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 +298 -0
- data/lib/rex/ui/output.rb +78 -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 +467 -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 +57 -0
- data/lib/rex/ui/text/output.rb +80 -0
- data/lib/rex/ui/text/output/buffer.rb +61 -0
- data/lib/rex/ui/text/output/file.rb +43 -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 +328 -0
- data/lib/rex/ui/text/table.rb +279 -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 +184 -0
- data/lib/rex/zip/blocks.rb +182 -0
- data/lib/rex/zip/entry.rb +104 -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 +434 -1
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
require 'thread'
|
|
2
|
+
|
|
3
|
+
module Rex
|
|
4
|
+
|
|
5
|
+
###
|
|
6
|
+
#
|
|
7
|
+
# This class implements a read/write lock synchronization
|
|
8
|
+
# primitive. It is meant to allow for more efficient access to
|
|
9
|
+
# resources that are more often read from than written to and many
|
|
10
|
+
# times can have concurrent reader threads. By allowing the reader
|
|
11
|
+
# threads to lock the resource concurrently rather than serially,
|
|
12
|
+
# a large performance boost can be seen. Acquiring a write lock
|
|
13
|
+
# results in exclusive access to the resource and thereby prevents
|
|
14
|
+
# any read operations during the time that a write lock is acquired.
|
|
15
|
+
# Only one write lock may be acquired at a time.
|
|
16
|
+
#
|
|
17
|
+
###
|
|
18
|
+
class ReadWriteLock
|
|
19
|
+
|
|
20
|
+
#
|
|
21
|
+
# Initializes a reader/writer lock instance.
|
|
22
|
+
#
|
|
23
|
+
def initialize
|
|
24
|
+
@read_sync_mutex = Mutex.new
|
|
25
|
+
@write_sync_mutex = Mutex.new
|
|
26
|
+
@exclusive_mutex = Mutex.new
|
|
27
|
+
@readers = 0
|
|
28
|
+
@writer = false
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
#
|
|
32
|
+
# Acquires the read lock for the calling thread.
|
|
33
|
+
#
|
|
34
|
+
def lock_read
|
|
35
|
+
read_sync_mutex.lock
|
|
36
|
+
|
|
37
|
+
begin
|
|
38
|
+
# If there are a non-zero number of readers and a
|
|
39
|
+
# writer is waiting to acquire the exclusive lock,
|
|
40
|
+
# free up the sync mutex temporarily and lock/unlock
|
|
41
|
+
# the exclusive lock. This is to give the writer
|
|
42
|
+
# thread a chance to acquire the lock and prevents
|
|
43
|
+
# it from being constantly starved.
|
|
44
|
+
if ((@readers > 0) and
|
|
45
|
+
(@writer))
|
|
46
|
+
read_sync_mutex.unlock
|
|
47
|
+
exclusive_mutex.lock
|
|
48
|
+
exclusive_mutex.unlock
|
|
49
|
+
read_sync_mutex.lock
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Increment the active reader count
|
|
53
|
+
@readers += 1
|
|
54
|
+
|
|
55
|
+
# If we now have just one reader, acquire the exclusive
|
|
56
|
+
# lock. Track the thread owner so that we release the
|
|
57
|
+
# lock from within the same thread context later on.
|
|
58
|
+
if (@readers == 1)
|
|
59
|
+
exclusive_mutex.lock
|
|
60
|
+
|
|
61
|
+
@owner = Thread.current
|
|
62
|
+
end
|
|
63
|
+
ensure
|
|
64
|
+
read_sync_mutex.unlock
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
#
|
|
69
|
+
# Releases the read lock for the calling thread.
|
|
70
|
+
#
|
|
71
|
+
def unlock_read
|
|
72
|
+
read_sync_mutex.lock
|
|
73
|
+
|
|
74
|
+
begin
|
|
75
|
+
unlocked = false
|
|
76
|
+
|
|
77
|
+
# Keep looping until we've lost this thread's reader
|
|
78
|
+
# lock
|
|
79
|
+
while (!unlocked)
|
|
80
|
+
# If there are no more readers left after this one
|
|
81
|
+
if (@readers - 1 == 0)
|
|
82
|
+
# If the calling thread is the owner of the exclusive
|
|
83
|
+
# reader lock, then let's release it
|
|
84
|
+
if (Thread.current == @owner)
|
|
85
|
+
@owner = nil
|
|
86
|
+
|
|
87
|
+
exclusive_mutex.unlock
|
|
88
|
+
end
|
|
89
|
+
# If there is more than one reader left and this thread is
|
|
90
|
+
# the owner of the exclusive lock, then keep looping so that
|
|
91
|
+
# we can eventually unlock the exclusive mutex in this thread's
|
|
92
|
+
# context
|
|
93
|
+
elsif (Thread.current == @owner)
|
|
94
|
+
read_sync_mutex.unlock
|
|
95
|
+
|
|
96
|
+
next
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# Unlocked!
|
|
100
|
+
unlocked = true
|
|
101
|
+
|
|
102
|
+
# Decrement the active reader count
|
|
103
|
+
@readers -= 1
|
|
104
|
+
end
|
|
105
|
+
ensure
|
|
106
|
+
read_sync_mutex.unlock
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
#
|
|
111
|
+
# Acquire the exclusive write lock.
|
|
112
|
+
#
|
|
113
|
+
def lock_write
|
|
114
|
+
write_sync_mutex.lock
|
|
115
|
+
|
|
116
|
+
begin
|
|
117
|
+
@writer = true
|
|
118
|
+
|
|
119
|
+
exclusive_mutex.lock
|
|
120
|
+
|
|
121
|
+
@owner = Thread.current
|
|
122
|
+
ensure
|
|
123
|
+
write_sync_mutex.unlock
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
#
|
|
128
|
+
# Release the exclusive write lock.
|
|
129
|
+
#
|
|
130
|
+
def unlock_write
|
|
131
|
+
# If the caller is not the owner of the write lock, then someone is
|
|
132
|
+
# doing something broken, let's let them know.
|
|
133
|
+
if (Thread.current != @owner)
|
|
134
|
+
raise RuntimeError, "Non-owner calling thread attempted to release write lock", caller
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
# Otherwise, release the exclusive write lock
|
|
138
|
+
@writer = false
|
|
139
|
+
|
|
140
|
+
exclusive_mutex.unlock
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
#
|
|
144
|
+
# Synchronize a block for read access.
|
|
145
|
+
#
|
|
146
|
+
def synchronize_read
|
|
147
|
+
lock_read
|
|
148
|
+
begin
|
|
149
|
+
yield
|
|
150
|
+
ensure
|
|
151
|
+
unlock_read
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
#
|
|
156
|
+
# Synchronize a block for write access.
|
|
157
|
+
#
|
|
158
|
+
def synchronize_write
|
|
159
|
+
lock_write
|
|
160
|
+
begin
|
|
161
|
+
yield
|
|
162
|
+
ensure
|
|
163
|
+
unlock_write
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
protected
|
|
168
|
+
|
|
169
|
+
attr_accessor :read_sync_mutex # :nodoc:
|
|
170
|
+
attr_accessor :write_sync_mutex # :nodoc:
|
|
171
|
+
attr_accessor :exclusive_mutex # :nodoc:
|
|
172
|
+
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
end
|
|
176
|
+
|
data/lib/rex/sync/ref.rb
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require 'thread'
|
|
2
|
+
|
|
3
|
+
module Rex
|
|
4
|
+
|
|
5
|
+
###
|
|
6
|
+
#
|
|
7
|
+
# This module provides a uniform reference counted interface for classes to
|
|
8
|
+
# use.
|
|
9
|
+
#
|
|
10
|
+
###
|
|
11
|
+
module Ref
|
|
12
|
+
|
|
13
|
+
#
|
|
14
|
+
# Initializes the reference count to one.
|
|
15
|
+
#
|
|
16
|
+
def refinit
|
|
17
|
+
@_references = 1
|
|
18
|
+
@_references_mutex = Mutex.new
|
|
19
|
+
|
|
20
|
+
self
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
#
|
|
24
|
+
# Increments the total number of references.
|
|
25
|
+
#
|
|
26
|
+
def ref
|
|
27
|
+
@_references_mutex.synchronize {
|
|
28
|
+
@_references += 1
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
self
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
#
|
|
35
|
+
# Decrements the total number of references. If the reference count
|
|
36
|
+
# reaches zero, true is returned. Otherwise, false is returned.
|
|
37
|
+
#
|
|
38
|
+
def deref
|
|
39
|
+
@_references_mutex.synchronize {
|
|
40
|
+
if ((@_references -= 1) == 0)
|
|
41
|
+
cleanup
|
|
42
|
+
|
|
43
|
+
true
|
|
44
|
+
else
|
|
45
|
+
false
|
|
46
|
+
end
|
|
47
|
+
}
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
#
|
|
51
|
+
# Called to clean up resources once the ref count drops to zero.
|
|
52
|
+
#
|
|
53
|
+
def cleanup
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
require 'timeout'
|
|
2
|
+
|
|
3
|
+
module Rex
|
|
4
|
+
|
|
5
|
+
###
|
|
6
|
+
#
|
|
7
|
+
# This module provides a set of methods for performing various blocking
|
|
8
|
+
# operations in a manner that is compatible with ruby style threads.
|
|
9
|
+
#
|
|
10
|
+
###
|
|
11
|
+
module ThreadSafe
|
|
12
|
+
|
|
13
|
+
DefaultCycle = 0.2
|
|
14
|
+
|
|
15
|
+
#
|
|
16
|
+
# Wraps calls to select with a lower timeout period and does the
|
|
17
|
+
# calculations to walk down to zero timeout. This has a little room for
|
|
18
|
+
# improvement in that it should probably check how much time actually
|
|
19
|
+
# elapsed during the select call considering ruby threading wont be exactly
|
|
20
|
+
# accurate perhaps.
|
|
21
|
+
#
|
|
22
|
+
def self.select(rfd = nil, wfd = nil, efd = nil, t = nil)
|
|
23
|
+
left = t
|
|
24
|
+
|
|
25
|
+
# Immediately raise a StreamClosedError if the socket was closed. This
|
|
26
|
+
# prevents a bad fd from being passed downstream and solves an issue
|
|
27
|
+
# with Ruby on Windows.
|
|
28
|
+
rfd.each { |fd| raise StreamClosedError.new(fd) if (fd.closed?) } if rfd
|
|
29
|
+
|
|
30
|
+
begin
|
|
31
|
+
orig_size = rfd.length if (rfd)
|
|
32
|
+
|
|
33
|
+
# Poll the set supplied to us at least once.
|
|
34
|
+
begin
|
|
35
|
+
rv = ::IO.select(rfd, wfd, efd, DefaultCycle)
|
|
36
|
+
rescue ::IOError, ::Errno::EBADF, ::Errno::ENOTSOCK
|
|
37
|
+
# If a stream was detected as being closed, re-raise the error as
|
|
38
|
+
# a StreamClosedError with the specific file descriptor that was
|
|
39
|
+
# detected as being closed. This is to better handle the case of
|
|
40
|
+
# a closed socket being detected so that it can be cleaned up and
|
|
41
|
+
# removed.
|
|
42
|
+
rfd.each { |fd| raise StreamClosedError.new(fd) if (fd.closed?) } if rfd
|
|
43
|
+
|
|
44
|
+
# If the original rfd length is not the same as the current
|
|
45
|
+
# length, then the list may have been altered and as such may not
|
|
46
|
+
# contain the socket that caused the IOError. This is a bad way
|
|
47
|
+
# to do this since it's possible that the array length could be
|
|
48
|
+
# back to the size that it was originally and yet have had the
|
|
49
|
+
# socket that caused the IOError to be removed.
|
|
50
|
+
return nil if (rfd and rfd.length != orig_size)
|
|
51
|
+
|
|
52
|
+
# Re-raise the exception since we didn't handle it here.
|
|
53
|
+
raise $!
|
|
54
|
+
# rescue ::Exception => e
|
|
55
|
+
# $stderr.puts "SELECT(#{t}) #{[rfd,wfd,efd].inspect} #{e.class} #{e} #{e.backtrace}"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
return rv if (rv)
|
|
59
|
+
|
|
60
|
+
# Decrement the amount of time left by the polling cycle
|
|
61
|
+
left -= DefaultCycle if (left)
|
|
62
|
+
|
|
63
|
+
# Keep chugging until we run out of time, if time was supplied.
|
|
64
|
+
end while ((left == nil) or (left > 0))
|
|
65
|
+
|
|
66
|
+
# Nothin.
|
|
67
|
+
nil
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
#
|
|
71
|
+
# Simulates a sleep operation by selecting on nil until a timeout period
|
|
72
|
+
# expires.
|
|
73
|
+
#
|
|
74
|
+
def self.sleep(seconds)
|
|
75
|
+
self.select(nil, nil, nil, seconds)
|
|
76
|
+
|
|
77
|
+
seconds
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
end
|
data/lib/rex/test.rb
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require 'test/unit'
|
|
2
|
+
|
|
3
|
+
# DEFAULTS
|
|
4
|
+
module Rex
|
|
5
|
+
class Test
|
|
6
|
+
|
|
7
|
+
$_REX_TEST_NO_MOCK = nil
|
|
8
|
+
$_REX_TEST_TIMEOUT = 30
|
|
9
|
+
$_REX_TEST_SMB_HOST = '10.4.10.58'
|
|
10
|
+
$_REX_TEXT_SMB_USER = 'SMBTest'
|
|
11
|
+
$_REX_TEXT_SMB_PASS = 'SMBTest'
|
|
12
|
+
|
|
13
|
+
# overwrite test defaults with rex/test-config.rb
|
|
14
|
+
def self.load()
|
|
15
|
+
file = File.join( ENV.fetch('HOME'), '.msf3', 'test')
|
|
16
|
+
begin
|
|
17
|
+
if File.stat(file + '.rb')
|
|
18
|
+
require file
|
|
19
|
+
end
|
|
20
|
+
rescue
|
|
21
|
+
# just ignore the errors
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def self.cantmock()
|
|
27
|
+
if (!$_REX_TEST_NO_MOCK)
|
|
28
|
+
raise RuntimeError, "*** $_REX_TEST_NO_MOCK must not be set for this test ***", caller
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
Rex::Test.load()
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
end
|
data/lib/rex/text.rb
ADDED
|
@@ -0,0 +1,1163 @@
|
|
|
1
|
+
require 'digest/md5'
|
|
2
|
+
require 'stringio'
|
|
3
|
+
|
|
4
|
+
begin
|
|
5
|
+
require 'iconv'
|
|
6
|
+
require 'zlib'
|
|
7
|
+
rescue LoadError
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
module Rex
|
|
11
|
+
|
|
12
|
+
###
|
|
13
|
+
#
|
|
14
|
+
# This class formats text in various fashions and also provides
|
|
15
|
+
# a mechanism for wrapping text at a given column.
|
|
16
|
+
#
|
|
17
|
+
###
|
|
18
|
+
module Text
|
|
19
|
+
@@codepage_map_cache = nil
|
|
20
|
+
|
|
21
|
+
##
|
|
22
|
+
#
|
|
23
|
+
# Constants
|
|
24
|
+
#
|
|
25
|
+
##
|
|
26
|
+
|
|
27
|
+
States = ["AK", "AL", "AR", "AZ", "CA", "CO", "CT", "DE", "FL", "GA", "HI",
|
|
28
|
+
"IA", "ID", "IL", "IN", "KS", "KY", "LA", "MA", "MD", "ME", "MI", "MN",
|
|
29
|
+
"MO", "MS", "MT", "NC", "ND", "NE", "NH", "NJ", "NM", "NV", "NY", "OH",
|
|
30
|
+
"OK", "OR", "PA", "RI", "SC", "SD", "TN", "TX", "UT", "VA", "VT", "WA",
|
|
31
|
+
"WI", "WV", "WY"]
|
|
32
|
+
UpperAlpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
33
|
+
LowerAlpha = "abcdefghijklmnopqrstuvwxyz"
|
|
34
|
+
Numerals = "0123456789"
|
|
35
|
+
Alpha = UpperAlpha + LowerAlpha
|
|
36
|
+
AlphaNumeric = Alpha + Numerals
|
|
37
|
+
HighAscii = [*(0x80 .. 0xff)].pack("C*")
|
|
38
|
+
DefaultWrap = 60
|
|
39
|
+
AllChars = [*(0x00 .. 0xff)].pack("C*")
|
|
40
|
+
|
|
41
|
+
DefaultPatternSets = [ Rex::Text::UpperAlpha, Rex::Text::LowerAlpha, Rex::Text::Numerals ]
|
|
42
|
+
|
|
43
|
+
# In case Iconv isn't loaded
|
|
44
|
+
Iconv_EBCDIC = ["\x00", "\x01", "\x02", "\x03", "7", "-", ".", "/", "\x16", "\x05", "%", "\v", "\f", "\r", "\x0E", "\x0F", "\x10", "\x11", "\x12", "\x13", "<", "=", "2", "&", "\x18", "\x19", "?", "'", "\x1C", "\x1D", "\x1E", "\x1F", "@", "Z", "\x7F", "{", "[", "l", "P", "}", "M", "]", "\\", "N", "k", "`", "K", "a", "\xF0", "\xF1", "\xF2", "\xF3", "\xF4", "\xF5", "\xF6", "\xF7", "\xF8", "\xF9", "z", "^", "L", "~", "n", "o", "|", "\xC1", "\xC2", "\xC3", "\xC4", "\xC5", "\xC6", "\xC7", "\xC8", "\xC9", "\xD1", "\xD2", "\xD3", "\xD4", "\xD5", "\xD6", "\xD7", "\xD8", "\xD9", "\xE2", "\xE3", "\xE4", "\xE5", "\xE6", "\xE7", "\xE8", "\xE9", nil, "\xE0", nil, nil, "m", "y", "\x81", "\x82", "\x83", "\x84", "\x85", "\x86", "\x87", "\x88", "\x89", "\x91", "\x92", "\x93", "\x94", "\x95", "\x96", "\x97", "\x98", "\x99", "\xA2", "\xA3", "\xA4", "\xA5", "\xA6", "\xA7", "\xA8", "\xA9", "\xC0", "O", "\xD0", "\xA1", "\a", nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil]
|
|
45
|
+
Iconv_ASCII = ["\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\a", "\b", "\t", "\n", "\v", "\f", "\r", "\x0E", "\x0F", "\x10", "\x11", "\x12", "\x13", "\x14", "\x15", "\x16", "\x17", "\x18", "\x19", "\x1A", "\e", "\x1C", "\x1D", "\x1E", "\x1F", " ", "!", "\"", "#", "$", "%", "&", "'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", nil, "\\", nil, nil, "_", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "{", "|", "}", "~", "\x7F", nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil]
|
|
46
|
+
|
|
47
|
+
##
|
|
48
|
+
#
|
|
49
|
+
# Serialization
|
|
50
|
+
#
|
|
51
|
+
##
|
|
52
|
+
|
|
53
|
+
#
|
|
54
|
+
# Converts a raw string into a ruby buffer
|
|
55
|
+
#
|
|
56
|
+
def self.to_ruby(str, wrap = DefaultWrap, name = "buf")
|
|
57
|
+
return hexify(str, wrap, '"', '" +', "#{name} = \n", '"')
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
#
|
|
61
|
+
# Creates a ruby-style comment
|
|
62
|
+
#
|
|
63
|
+
def self.to_ruby_comment(str, wrap = DefaultWrap)
|
|
64
|
+
return wordwrap(str, 0, wrap, '', '# ')
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
#
|
|
68
|
+
# Converts a raw string into a C buffer
|
|
69
|
+
#
|
|
70
|
+
def self.to_c(str, wrap = DefaultWrap, name = "buf")
|
|
71
|
+
return hexify(str, wrap, '"', '"', "unsigned char #{name}[] = \n", '";')
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
#
|
|
75
|
+
# Creates a c-style comment
|
|
76
|
+
#
|
|
77
|
+
def self.to_c_comment(str, wrap = DefaultWrap)
|
|
78
|
+
return "/*\n" + wordwrap(str, 0, wrap, '', ' * ') + " */\n"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
#
|
|
82
|
+
# Creates a javascript-style comment
|
|
83
|
+
#
|
|
84
|
+
def self.to_js_comment(str, wrap = DefaultWrap)
|
|
85
|
+
return wordwrap(str, 0, wrap, '', '// ')
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
#
|
|
89
|
+
# Converts a raw string into a perl buffer
|
|
90
|
+
#
|
|
91
|
+
def self.to_perl(str, wrap = DefaultWrap, name = "buf")
|
|
92
|
+
return hexify(str, wrap, '"', '" .', "my $#{name} = \n", '";')
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
#
|
|
96
|
+
# Converts a raw string into a java byte array
|
|
97
|
+
#
|
|
98
|
+
def self.to_java(str, name = "shell")
|
|
99
|
+
buff = "byte #{name}[] = new byte[]\n{\n"
|
|
100
|
+
cnt = 0
|
|
101
|
+
max = 0
|
|
102
|
+
str.unpack('C*').each do |c|
|
|
103
|
+
buff << ", " if max > 0
|
|
104
|
+
buff << "\t" if max == 0
|
|
105
|
+
buff << sprintf('(byte) 0x%.2x', c)
|
|
106
|
+
max +=1
|
|
107
|
+
cnt +=1
|
|
108
|
+
|
|
109
|
+
if (max > 7)
|
|
110
|
+
buff << ",\n" if cnt != str.length
|
|
111
|
+
max = 0
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
buff << "\n};\n"
|
|
115
|
+
return buff
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
#
|
|
119
|
+
# Creates a perl-style comment
|
|
120
|
+
#
|
|
121
|
+
def self.to_perl_comment(str, wrap = DefaultWrap)
|
|
122
|
+
return wordwrap(str, 0, wrap, '', '# ')
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
#
|
|
126
|
+
# Returns the raw string
|
|
127
|
+
#
|
|
128
|
+
def self.to_raw(str)
|
|
129
|
+
return str
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
#
|
|
133
|
+
# Converts ISO-8859-1 to UTF-8
|
|
134
|
+
#
|
|
135
|
+
def self.to_utf8(str)
|
|
136
|
+
begin
|
|
137
|
+
Iconv.iconv("utf-8","iso-8859-1", str).join(" ")
|
|
138
|
+
rescue
|
|
139
|
+
raise ::RuntimeError, "Your installation does not support iconv (needed for utf8 conversion)"
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
#
|
|
144
|
+
# Converts ASCII to EBCDIC
|
|
145
|
+
#
|
|
146
|
+
class IllegalSequence < ArgumentError; end
|
|
147
|
+
|
|
148
|
+
# A native implementation of the ASCII->EBCDIC table, used to fall back from using
|
|
149
|
+
# Iconv
|
|
150
|
+
def self.to_ebcdic_rex(str)
|
|
151
|
+
new_str = []
|
|
152
|
+
str.each_byte do |x|
|
|
153
|
+
if Iconv_ASCII.index(x.chr)
|
|
154
|
+
new_str << Iconv_EBCDIC[Iconv_ASCII.index(x.chr)]
|
|
155
|
+
else
|
|
156
|
+
raise Rex::Text::IllegalSequence, ("\\x%x" % x)
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
new_str.join
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
# A native implementation of the EBCDIC->ASCII table, used to fall back from using
|
|
163
|
+
# Iconv
|
|
164
|
+
def self.from_ebcdic_rex(str)
|
|
165
|
+
new_str = []
|
|
166
|
+
str.each_byte do |x|
|
|
167
|
+
if Iconv_EBCDIC.index(x.chr)
|
|
168
|
+
new_str << Iconv_ASCII[Iconv_EBCDIC.index(x.chr)]
|
|
169
|
+
else
|
|
170
|
+
raise Rex::Text::IllegalSequence, ("\\x%x" % x)
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
new_str.join
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def self.to_ebcdic(str)
|
|
177
|
+
begin
|
|
178
|
+
Iconv.iconv("EBCDIC-US", "ASCII", str).first
|
|
179
|
+
rescue ::Iconv::IllegalSequence => e
|
|
180
|
+
raise e
|
|
181
|
+
rescue
|
|
182
|
+
self.to_ebcdic_rex(str)
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
#
|
|
187
|
+
# Converts EBCIDC to ASCII
|
|
188
|
+
#
|
|
189
|
+
def self.from_ebcdic(str)
|
|
190
|
+
begin
|
|
191
|
+
Iconv.iconv("ASCII", "EBCDIC-US", str).first
|
|
192
|
+
rescue ::Iconv::IllegalSequence => e
|
|
193
|
+
raise e
|
|
194
|
+
rescue
|
|
195
|
+
self.from_ebcdic_rex(str)
|
|
196
|
+
end
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
#
|
|
200
|
+
# Returns a unicode escaped string for Javascript
|
|
201
|
+
#
|
|
202
|
+
def self.to_unescape(data, endian=ENDIAN_LITTLE)
|
|
203
|
+
data << "\x41" if (data.length % 2 != 0)
|
|
204
|
+
dptr = 0
|
|
205
|
+
buff = ''
|
|
206
|
+
while (dptr < data.length)
|
|
207
|
+
c1 = data[dptr,1].unpack("C*")[0]
|
|
208
|
+
dptr += 1
|
|
209
|
+
c2 = data[dptr,1].unpack("C*")[0]
|
|
210
|
+
dptr += 1
|
|
211
|
+
|
|
212
|
+
if (endian == ENDIAN_LITTLE)
|
|
213
|
+
buff << sprintf('%%u%.2x%.2x', c2, c1)
|
|
214
|
+
else
|
|
215
|
+
buff << sprintf('%%u%.2x%.2x', c1, c2)
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
return buff
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
#
|
|
222
|
+
# Returns the hex version of the supplied string
|
|
223
|
+
#
|
|
224
|
+
def self.to_hex(str, prefix = "\\x", count = 1)
|
|
225
|
+
raise ::RuntimeError, "unable to chunk into #{count} byte chunks" if ((str.length % count) > 0)
|
|
226
|
+
|
|
227
|
+
# XXX: Regexp.new is used here since using /.{#{count}}/o would compile
|
|
228
|
+
# the regex the first time it is used and never check again. Since we
|
|
229
|
+
# want to know how many to capture on every instance, we do it this
|
|
230
|
+
# way.
|
|
231
|
+
return str.unpack('H*')[0].gsub(Regexp.new(".{#{count * 2}}", nil, 'n')) { |s| prefix + s }
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
#
|
|
235
|
+
# Returns the string with nonprintable hex characters sanitized to ascii. Similiar to to_hex,
|
|
236
|
+
# but regular ASCII is not translated if count is 1.
|
|
237
|
+
#
|
|
238
|
+
def self.to_hex_ascii(str, prefix = "\\x", count = 1, suffix=nil)
|
|
239
|
+
raise ::RuntimeError, "unable to chunk into #{count} byte chunks" if ((str.length % count) > 0)
|
|
240
|
+
return str.unpack('H*')[0].gsub(Regexp.new(".{#{count * 2}}", nil, 'n')) { |s|
|
|
241
|
+
(0x20..0x7e) === s.to_i(16) ? s.to_i(16).chr : prefix + s + suffix.to_s
|
|
242
|
+
}
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
#
|
|
246
|
+
# Converts standard ASCII text to a unicode string.
|
|
247
|
+
#
|
|
248
|
+
# Supported unicode types include: utf-16le, utf16-be, utf32-le, utf32-be, utf-7, and utf-8
|
|
249
|
+
#
|
|
250
|
+
# Providing 'mode' provides hints to the actual encoder as to how it should encode the string. Only UTF-7 and UTF-8 use "mode".
|
|
251
|
+
#
|
|
252
|
+
# utf-7 by default does not encode alphanumeric and a few other characters. By specifying the mode of "all", then all of the characters are encoded, not just the non-alphanumeric set.
|
|
253
|
+
# to_unicode(str, 'utf-7', 'all')
|
|
254
|
+
#
|
|
255
|
+
# utf-8 specifies that alphanumeric characters are used directly, eg "a" is just "a". However, there exist 6 different overlong encodings of "a" that are technically not valid, but parse just fine in most utf-8 parsers. (0xC1A1, 0xE081A1, 0xF08081A1, 0xF8808081A1, 0xFC80808081A1, 0xFE8080808081A1). How many bytes to use for the overlong enocding is specified providing 'size'.
|
|
256
|
+
# to_unicode(str, 'utf-8', 'overlong', 2)
|
|
257
|
+
#
|
|
258
|
+
# Many utf-8 parsers also allow invalid overlong encodings, where bits that are unused when encoding a single byte are modified. Many parsers will ignore these bits, rendering simple string matching to be ineffective for dealing with UTF-8 strings. There are many more invalid overlong encodings possible for "a". For example, three encodings are available for an invalid 2 byte encoding of "a". (0xC1E1 0xC161 0xC121). By specifying "invalid", a random invalid encoding is chosen for the given byte size.
|
|
259
|
+
# to_unicode(str, 'utf-8', 'invalid', 2)
|
|
260
|
+
#
|
|
261
|
+
# utf-7 defaults to 'normal' utf-7 encoding
|
|
262
|
+
# utf-8 defaults to 2 byte 'normal' encoding
|
|
263
|
+
#
|
|
264
|
+
def self.to_unicode(str='', type = 'utf-16le', mode = '', size = '')
|
|
265
|
+
return '' if not str
|
|
266
|
+
case type
|
|
267
|
+
when 'utf-16le'
|
|
268
|
+
return str.unpack('C*').pack('v*')
|
|
269
|
+
when 'utf-16be'
|
|
270
|
+
return str.unpack('C*').pack('n*')
|
|
271
|
+
when 'utf-32le'
|
|
272
|
+
return str.unpack('C*').pack('V*')
|
|
273
|
+
when 'utf-32be'
|
|
274
|
+
return str.unpack('C*').pack('N*')
|
|
275
|
+
when 'utf-7'
|
|
276
|
+
case mode
|
|
277
|
+
when 'all'
|
|
278
|
+
return str.gsub(/./){ |a|
|
|
279
|
+
out = ''
|
|
280
|
+
if 'a' != '+'
|
|
281
|
+
out = encode_base64(to_unicode(a, 'utf-16be')).gsub(/[=\r\n]/, '')
|
|
282
|
+
end
|
|
283
|
+
'+' + out + '-'
|
|
284
|
+
}
|
|
285
|
+
else
|
|
286
|
+
return str.gsub(/[^\n\r\t\ A-Za-z0-9\'\(\),-.\/\:\?]/){ |a|
|
|
287
|
+
out = ''
|
|
288
|
+
if a != '+'
|
|
289
|
+
out = encode_base64(to_unicode(a, 'utf-16be')).gsub(/[=\r\n]/, '')
|
|
290
|
+
end
|
|
291
|
+
'+' + out + '-'
|
|
292
|
+
}
|
|
293
|
+
end
|
|
294
|
+
when 'utf-8'
|
|
295
|
+
if size == ''
|
|
296
|
+
size = 2
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
if size >= 2 and size <= 7
|
|
300
|
+
string = ''
|
|
301
|
+
str.each_byte { |a|
|
|
302
|
+
if (a < 21 || a > 0x7f) || mode != ''
|
|
303
|
+
# ugh. turn a single byte into the binary representation of it, in array form
|
|
304
|
+
bin = [a].pack('C').unpack('B8')[0].split(//)
|
|
305
|
+
|
|
306
|
+
# even more ugh.
|
|
307
|
+
bin.collect!{|a_| a_.to_i}
|
|
308
|
+
|
|
309
|
+
out = Array.new(8 * size, 0)
|
|
310
|
+
|
|
311
|
+
0.upto(size - 1) { |i|
|
|
312
|
+
out[i] = 1
|
|
313
|
+
out[i * 8] = 1
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
i = 0
|
|
317
|
+
byte = 0
|
|
318
|
+
bin.reverse.each { |bit|
|
|
319
|
+
if i < 6
|
|
320
|
+
mod = (((size * 8) - 1) - byte * 8) - i
|
|
321
|
+
out[mod] = bit
|
|
322
|
+
else
|
|
323
|
+
byte = byte + 1
|
|
324
|
+
i = 0
|
|
325
|
+
redo
|
|
326
|
+
end
|
|
327
|
+
i = i + 1
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
if mode != ''
|
|
331
|
+
case mode
|
|
332
|
+
when 'overlong'
|
|
333
|
+
# do nothing, since we already handle this as above...
|
|
334
|
+
when 'invalid'
|
|
335
|
+
done = 0
|
|
336
|
+
while done == 0
|
|
337
|
+
# the ghetto...
|
|
338
|
+
bits = [7, 8, 15, 16, 23, 24, 31, 32, 41]
|
|
339
|
+
bits.each { |bit|
|
|
340
|
+
bit = (size * 8) - bit
|
|
341
|
+
if bit > 1
|
|
342
|
+
set = rand(2)
|
|
343
|
+
if out[bit] != set
|
|
344
|
+
out[bit] = set
|
|
345
|
+
done = 1
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
}
|
|
349
|
+
end
|
|
350
|
+
else
|
|
351
|
+
raise TypeError, 'Invalid mode. Only "overlong" and "invalid" are acceptable modes for utf-8'
|
|
352
|
+
end
|
|
353
|
+
end
|
|
354
|
+
string << [out.join('')].pack('B*')
|
|
355
|
+
else
|
|
356
|
+
string << [a].pack('C')
|
|
357
|
+
end
|
|
358
|
+
}
|
|
359
|
+
return string
|
|
360
|
+
else
|
|
361
|
+
raise TypeError, 'invalid utf-8 size'
|
|
362
|
+
end
|
|
363
|
+
when 'uhwtfms' # suggested name from HD :P
|
|
364
|
+
load_codepage()
|
|
365
|
+
|
|
366
|
+
string = ''
|
|
367
|
+
# overloading mode as codepage
|
|
368
|
+
if mode == ''
|
|
369
|
+
mode = 1252 # ANSI - Latan 1, default for US installs of MS products
|
|
370
|
+
else
|
|
371
|
+
mode = mode.to_i
|
|
372
|
+
end
|
|
373
|
+
if @@codepage_map_cache[mode].nil?
|
|
374
|
+
raise TypeError, "Invalid codepage #{mode}"
|
|
375
|
+
end
|
|
376
|
+
str.each_byte {|byte|
|
|
377
|
+
char = [byte].pack('C*')
|
|
378
|
+
possible = @@codepage_map_cache[mode]['data'][char]
|
|
379
|
+
if possible.nil?
|
|
380
|
+
raise TypeError, "codepage #{mode} does not provide an encoding for 0x#{char.unpack('H*')[0]}"
|
|
381
|
+
end
|
|
382
|
+
string << possible[ rand(possible.length) ]
|
|
383
|
+
}
|
|
384
|
+
return string
|
|
385
|
+
when 'uhwtfms-half' # suggested name from HD :P
|
|
386
|
+
load_codepage()
|
|
387
|
+
string = ''
|
|
388
|
+
# overloading mode as codepage
|
|
389
|
+
if mode == ''
|
|
390
|
+
mode = 1252 # ANSI - Latan 1, default for US installs of MS products
|
|
391
|
+
else
|
|
392
|
+
mode = mode.to_i
|
|
393
|
+
end
|
|
394
|
+
if mode != 1252
|
|
395
|
+
raise TypeError, "Invalid codepage #{mode}, only 1252 supported for uhwtfms_half"
|
|
396
|
+
end
|
|
397
|
+
str.each_byte {|byte|
|
|
398
|
+
if ((byte >= 33 && byte <= 63) || (byte >= 96 && byte <= 126))
|
|
399
|
+
string << "\xFF" + [byte ^ 32].pack('C')
|
|
400
|
+
elsif (byte >= 64 && byte <= 95)
|
|
401
|
+
string << "\xFF" + [byte ^ 96].pack('C')
|
|
402
|
+
else
|
|
403
|
+
char = [byte].pack('C')
|
|
404
|
+
possible = @@codepage_map_cache[mode]['data'][char]
|
|
405
|
+
if possible.nil?
|
|
406
|
+
raise TypeError, "codepage #{mode} does not provide an encoding for 0x#{char.unpack('H*')[0]}"
|
|
407
|
+
end
|
|
408
|
+
string << possible[ rand(possible.length) ]
|
|
409
|
+
end
|
|
410
|
+
}
|
|
411
|
+
return string
|
|
412
|
+
else
|
|
413
|
+
raise TypeError, 'invalid utf type'
|
|
414
|
+
end
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
#
|
|
418
|
+
# Converts a unicode string to standard ASCII text.
|
|
419
|
+
#
|
|
420
|
+
def self.to_ascii(str='', type = 'utf-16le', mode = '', size = '')
|
|
421
|
+
return '' if not str
|
|
422
|
+
case type
|
|
423
|
+
when 'utf-16le'
|
|
424
|
+
return str.unpack('v*').pack('C*')
|
|
425
|
+
when 'utf-16be'
|
|
426
|
+
return str.unpack('n*').pack('C*')
|
|
427
|
+
when 'utf-32le'
|
|
428
|
+
return str.unpack('V*').pack('C*')
|
|
429
|
+
when 'utf-32be'
|
|
430
|
+
return str.unpack('N*').pack('C*')
|
|
431
|
+
when 'utf-7'
|
|
432
|
+
raise TypeError, 'invalid utf type, not yet implemented'
|
|
433
|
+
when 'utf-8'
|
|
434
|
+
raise TypeError, 'invalid utf type, not yet implemented'
|
|
435
|
+
when 'uhwtfms' # suggested name from HD :P
|
|
436
|
+
raise TypeError, 'invalid utf type, not yet implemented'
|
|
437
|
+
when 'uhwtfms-half' # suggested name from HD :P
|
|
438
|
+
raise TypeError, 'invalid utf type, not yet implemented'
|
|
439
|
+
else
|
|
440
|
+
raise TypeError, 'invalid utf type'
|
|
441
|
+
end
|
|
442
|
+
end
|
|
443
|
+
|
|
444
|
+
#
|
|
445
|
+
# Encode a string in a manor useful for HTTP URIs and URI Parameters.
|
|
446
|
+
#
|
|
447
|
+
def self.uri_encode(str, mode = 'hex-normal')
|
|
448
|
+
return "" if str == nil
|
|
449
|
+
|
|
450
|
+
return str if mode == 'none' # fast track no encoding
|
|
451
|
+
|
|
452
|
+
all = /[^\/\\]+/
|
|
453
|
+
normal = /[^a-zA-Z0-9\/\\\.\-]+/
|
|
454
|
+
normal_na = /[a-zA-Z0-9\/\\\.\-]/
|
|
455
|
+
|
|
456
|
+
case mode
|
|
457
|
+
when 'hex-normal'
|
|
458
|
+
return str.gsub(normal) { |s| Rex::Text.to_hex(s, '%') }
|
|
459
|
+
when 'hex-all'
|
|
460
|
+
return str.gsub(all) { |s| Rex::Text.to_hex(s, '%') }
|
|
461
|
+
when 'hex-random'
|
|
462
|
+
res = ''
|
|
463
|
+
str.each_byte do |c|
|
|
464
|
+
b = c.chr
|
|
465
|
+
res << ((rand(2) == 0) ?
|
|
466
|
+
b.gsub(all) { |s| Rex::Text.to_hex(s, '%') } :
|
|
467
|
+
b.gsub(normal){ |s| Rex::Text.to_hex(s, '%') } )
|
|
468
|
+
end
|
|
469
|
+
return res
|
|
470
|
+
when 'u-normal'
|
|
471
|
+
return str.gsub(normal) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) }
|
|
472
|
+
when 'u-all'
|
|
473
|
+
return str.gsub(all) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) }
|
|
474
|
+
when 'u-random'
|
|
475
|
+
res = ''
|
|
476
|
+
str.each_byte do |c|
|
|
477
|
+
b = c.chr
|
|
478
|
+
res << ((rand(2) == 0) ?
|
|
479
|
+
b.gsub(all) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) } :
|
|
480
|
+
b.gsub(normal){ |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) } )
|
|
481
|
+
end
|
|
482
|
+
return res
|
|
483
|
+
when 'u-half'
|
|
484
|
+
return str.gsub(all) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms-half'), '%u', 2) }
|
|
485
|
+
else
|
|
486
|
+
raise TypeError, 'invalid mode'
|
|
487
|
+
end
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
#
|
|
491
|
+
# Encode a string in a manner useful for HTTP URIs and URI Parameters.
|
|
492
|
+
#
|
|
493
|
+
def self.html_encode(str, mode = 'hex')
|
|
494
|
+
case mode
|
|
495
|
+
when 'hex'
|
|
496
|
+
return str.unpack('C*').collect{ |i| "&#x" + ("%.2x" % i) + ";"}.join
|
|
497
|
+
when 'int'
|
|
498
|
+
return str.unpack('C*').collect{ |i| "&#" + i.to_s + ";"}.join
|
|
499
|
+
when 'int-wide'
|
|
500
|
+
return str.unpack('C*').collect{ |i| "&#" + ("0" * (7 - i.to_s.length)) + i.to_s + ";" }.join
|
|
501
|
+
else
|
|
502
|
+
raise TypeError, 'invalid mode'
|
|
503
|
+
end
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
#
|
|
507
|
+
# Encode an ASCII string so it's safe for XML. It's a wrapper for to_hex_ascii.
|
|
508
|
+
#
|
|
509
|
+
def self.xml_char_encode(str)
|
|
510
|
+
self.to_hex_ascii(str, "&#x", 1, ";")
|
|
511
|
+
end
|
|
512
|
+
|
|
513
|
+
#
|
|
514
|
+
# Decode a URI encoded string
|
|
515
|
+
#
|
|
516
|
+
def self.uri_decode(str)
|
|
517
|
+
str.gsub(/(%[a-z0-9]{2})/i){ |c| [c[1,2]].pack("H*") }
|
|
518
|
+
end
|
|
519
|
+
|
|
520
|
+
#
|
|
521
|
+
# Converts a string to random case
|
|
522
|
+
#
|
|
523
|
+
def self.to_rand_case(str)
|
|
524
|
+
buf = str.dup
|
|
525
|
+
0.upto(str.length) do |i|
|
|
526
|
+
buf[i,1] = rand(2) == 0 ? str[i,1].upcase : str[i,1].downcase
|
|
527
|
+
end
|
|
528
|
+
return buf
|
|
529
|
+
end
|
|
530
|
+
|
|
531
|
+
#
|
|
532
|
+
# Takes a string, and returns an array of all mixed case versions.
|
|
533
|
+
#
|
|
534
|
+
# Example:
|
|
535
|
+
#
|
|
536
|
+
# >> Rex::Text.to_mixed_case_array "abc1"
|
|
537
|
+
# => ["abc1", "abC1", "aBc1", "aBC1", "Abc1", "AbC1", "ABc1", "ABC1"]
|
|
538
|
+
#
|
|
539
|
+
def self.to_mixed_case_array(str)
|
|
540
|
+
letters = []
|
|
541
|
+
str.scan(/./).each { |l| letters << [l.downcase, l.upcase] }
|
|
542
|
+
coords = []
|
|
543
|
+
(1 << str.size).times { |i| coords << ("%0#{str.size}b" % i) }
|
|
544
|
+
mixed = []
|
|
545
|
+
coords.each do |coord|
|
|
546
|
+
c = coord.scan(/./).map {|x| x.to_i}
|
|
547
|
+
this_str = ""
|
|
548
|
+
c.each_with_index { |d,i| this_str << letters[i][d] }
|
|
549
|
+
mixed << this_str
|
|
550
|
+
end
|
|
551
|
+
return mixed.uniq
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
#
|
|
555
|
+
# Converts a string a nicely formatted hex dump
|
|
556
|
+
#
|
|
557
|
+
def self.to_hex_dump(str, width=16)
|
|
558
|
+
buf = ''
|
|
559
|
+
idx = 0
|
|
560
|
+
cnt = 0
|
|
561
|
+
snl = false
|
|
562
|
+
lst = 0
|
|
563
|
+
|
|
564
|
+
while (idx < str.length)
|
|
565
|
+
|
|
566
|
+
chunk = str[idx, width]
|
|
567
|
+
line = chunk.unpack("H*")[0].scan(/../).join(" ")
|
|
568
|
+
buf << line
|
|
569
|
+
|
|
570
|
+
if (lst == 0)
|
|
571
|
+
lst = line.length
|
|
572
|
+
buf << " " * 4
|
|
573
|
+
else
|
|
574
|
+
buf << " " * ((lst - line.length) + 4).abs
|
|
575
|
+
end
|
|
576
|
+
|
|
577
|
+
chunk.unpack("C*").each do |c|
|
|
578
|
+
if (c > 0x1f and c < 0x7f)
|
|
579
|
+
buf << c.chr
|
|
580
|
+
else
|
|
581
|
+
buf << "."
|
|
582
|
+
end
|
|
583
|
+
end
|
|
584
|
+
|
|
585
|
+
buf << "\n"
|
|
586
|
+
|
|
587
|
+
idx += width
|
|
588
|
+
end
|
|
589
|
+
|
|
590
|
+
buf << "\n"
|
|
591
|
+
end
|
|
592
|
+
|
|
593
|
+
#
|
|
594
|
+
# Converts a hex string to a raw string
|
|
595
|
+
#
|
|
596
|
+
def self.hex_to_raw(str)
|
|
597
|
+
[ str.downcase.gsub(/'/,'').gsub(/\\?x([a-f0-9][a-f0-9])/, '\1') ].pack("H*")
|
|
598
|
+
end
|
|
599
|
+
|
|
600
|
+
#
|
|
601
|
+
# Turn non-printable chars into hex representations, leaving others alone
|
|
602
|
+
#
|
|
603
|
+
# If +whitespace+ is true, converts whitespace (0x20, 0x09, etc) to hex as
|
|
604
|
+
# well.
|
|
605
|
+
#
|
|
606
|
+
def self.ascii_safe_hex(str, whitespace=false)
|
|
607
|
+
if whitespace
|
|
608
|
+
str.gsub(/([\x00-\x20\x80-\xFF])/){ |x| "\\x%.2x" % x.unpack("C*")[0] }
|
|
609
|
+
else
|
|
610
|
+
str.gsub(/([\x00-\x08\x0b\x0c\x0e-\x1f\x80-\xFF])/n){ |x| "\\x%.2x" % x.unpack("C*")[0]}
|
|
611
|
+
end
|
|
612
|
+
end
|
|
613
|
+
|
|
614
|
+
#
|
|
615
|
+
# Wraps text at a given column using a supplied indention
|
|
616
|
+
#
|
|
617
|
+
def self.wordwrap(str, indent = 0, col = DefaultWrap, append = '', prepend = '')
|
|
618
|
+
return str.gsub(/.{1,#{col - indent}}(?:\s|\Z)/){
|
|
619
|
+
( (" " * indent) + prepend + $& + append + 5.chr).gsub(/\n\005/,"\n").gsub(/\005/,"\n")}
|
|
620
|
+
end
|
|
621
|
+
|
|
622
|
+
#
|
|
623
|
+
# Converts a string to a hex version with wrapping support
|
|
624
|
+
#
|
|
625
|
+
def self.hexify(str, col = DefaultWrap, line_start = '', line_end = '', buf_start = '', buf_end = '')
|
|
626
|
+
output = buf_start
|
|
627
|
+
cur = 0
|
|
628
|
+
count = 0
|
|
629
|
+
new_line = true
|
|
630
|
+
|
|
631
|
+
# Go through each byte in the string
|
|
632
|
+
str.each_byte { |byte|
|
|
633
|
+
count += 1
|
|
634
|
+
append = ''
|
|
635
|
+
|
|
636
|
+
# If this is a new line, prepend with the
|
|
637
|
+
# line start text
|
|
638
|
+
if (new_line == true)
|
|
639
|
+
append << line_start
|
|
640
|
+
new_line = false
|
|
641
|
+
end
|
|
642
|
+
|
|
643
|
+
# Append the hexified version of the byte
|
|
644
|
+
append << sprintf("\\x%.2x", byte)
|
|
645
|
+
cur += append.length
|
|
646
|
+
|
|
647
|
+
# If we're about to hit the column or have gone past it,
|
|
648
|
+
# time to finish up this line
|
|
649
|
+
if ((cur + line_end.length >= col) or (cur + buf_end.length >= col))
|
|
650
|
+
new_line = true
|
|
651
|
+
cur = 0
|
|
652
|
+
|
|
653
|
+
# If this is the last byte, use the buf_end instead of
|
|
654
|
+
# line_end
|
|
655
|
+
if (count == str.length)
|
|
656
|
+
append << buf_end + "\n"
|
|
657
|
+
else
|
|
658
|
+
append << line_end + "\n"
|
|
659
|
+
end
|
|
660
|
+
end
|
|
661
|
+
|
|
662
|
+
output << append
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
# If we were in the middle of a line, finish the buffer at this point
|
|
666
|
+
if (new_line == false)
|
|
667
|
+
output << buf_end + "\n"
|
|
668
|
+
end
|
|
669
|
+
|
|
670
|
+
return output
|
|
671
|
+
end
|
|
672
|
+
|
|
673
|
+
##
|
|
674
|
+
#
|
|
675
|
+
# Transforms
|
|
676
|
+
#
|
|
677
|
+
##
|
|
678
|
+
|
|
679
|
+
#
|
|
680
|
+
# Base64 encoder
|
|
681
|
+
#
|
|
682
|
+
def self.encode_base64(str, delim='')
|
|
683
|
+
[str].pack("m").gsub(/\s+/, delim)
|
|
684
|
+
end
|
|
685
|
+
|
|
686
|
+
#
|
|
687
|
+
# Base64 decoder
|
|
688
|
+
#
|
|
689
|
+
def self.decode_base64(str)
|
|
690
|
+
str.unpack("m")[0]
|
|
691
|
+
end
|
|
692
|
+
|
|
693
|
+
#
|
|
694
|
+
# Raw MD5 digest of the supplied string
|
|
695
|
+
#
|
|
696
|
+
def self.md5_raw(str)
|
|
697
|
+
Digest::MD5.digest(str)
|
|
698
|
+
end
|
|
699
|
+
|
|
700
|
+
#
|
|
701
|
+
# Hexidecimal MD5 digest of the supplied string
|
|
702
|
+
#
|
|
703
|
+
def self.md5(str)
|
|
704
|
+
Digest::MD5.hexdigest(str)
|
|
705
|
+
end
|
|
706
|
+
|
|
707
|
+
|
|
708
|
+
##
|
|
709
|
+
#
|
|
710
|
+
# Generators
|
|
711
|
+
#
|
|
712
|
+
##
|
|
713
|
+
|
|
714
|
+
|
|
715
|
+
# Generates a random character.
|
|
716
|
+
def self.rand_char(bad, chars = AllChars)
|
|
717
|
+
rand_text(1, bad, chars)
|
|
718
|
+
end
|
|
719
|
+
|
|
720
|
+
# Base text generator method
|
|
721
|
+
def self.rand_base(len, bad, *foo)
|
|
722
|
+
cset = (foo.join.unpack("C*") - bad.to_s.unpack("C*")).uniq
|
|
723
|
+
return "" if cset.length == 0
|
|
724
|
+
outp = []
|
|
725
|
+
len.times { outp << cset[rand(cset.length)] }
|
|
726
|
+
outp.pack("C*")
|
|
727
|
+
end
|
|
728
|
+
|
|
729
|
+
# Generate random bytes of data
|
|
730
|
+
def self.rand_text(len, bad='', chars = AllChars)
|
|
731
|
+
foo = chars.split('')
|
|
732
|
+
rand_base(len, bad, *foo)
|
|
733
|
+
end
|
|
734
|
+
|
|
735
|
+
# Generate random bytes of alpha data
|
|
736
|
+
def self.rand_text_alpha(len, bad='')
|
|
737
|
+
foo = []
|
|
738
|
+
foo += ('A' .. 'Z').to_a
|
|
739
|
+
foo += ('a' .. 'z').to_a
|
|
740
|
+
rand_base(len, bad, *foo )
|
|
741
|
+
end
|
|
742
|
+
|
|
743
|
+
# Generate random bytes of lowercase alpha data
|
|
744
|
+
def self.rand_text_alpha_lower(len, bad='')
|
|
745
|
+
rand_base(len, bad, *('a' .. 'z').to_a)
|
|
746
|
+
end
|
|
747
|
+
|
|
748
|
+
# Generate random bytes of uppercase alpha data
|
|
749
|
+
def self.rand_text_alpha_upper(len, bad='')
|
|
750
|
+
rand_base(len, bad, *('A' .. 'Z').to_a)
|
|
751
|
+
end
|
|
752
|
+
|
|
753
|
+
# Generate random bytes of alphanumeric data
|
|
754
|
+
def self.rand_text_alphanumeric(len, bad='')
|
|
755
|
+
foo = []
|
|
756
|
+
foo += ('A' .. 'Z').to_a
|
|
757
|
+
foo += ('a' .. 'z').to_a
|
|
758
|
+
foo += ('0' .. '9').to_a
|
|
759
|
+
rand_base(len, bad, *foo )
|
|
760
|
+
end
|
|
761
|
+
|
|
762
|
+
# Generate random bytes of alphanumeric hex.
|
|
763
|
+
def self.rand_text_hex(len, bad='')
|
|
764
|
+
foo = []
|
|
765
|
+
foo += ('0' .. '9').to_a
|
|
766
|
+
foo += ('a' .. 'f').to_a
|
|
767
|
+
rand_base(len, bad, *foo)
|
|
768
|
+
end
|
|
769
|
+
|
|
770
|
+
# Generate random bytes of numeric data
|
|
771
|
+
def self.rand_text_numeric(len, bad='')
|
|
772
|
+
foo = ('0' .. '9').to_a
|
|
773
|
+
rand_base(len, bad, *foo )
|
|
774
|
+
end
|
|
775
|
+
|
|
776
|
+
# Generate random bytes of english-like data
|
|
777
|
+
def self.rand_text_english(len, bad='')
|
|
778
|
+
foo = []
|
|
779
|
+
foo += (0x21 .. 0x7e).map{ |c| c.chr }
|
|
780
|
+
rand_base(len, bad, *foo )
|
|
781
|
+
end
|
|
782
|
+
|
|
783
|
+
# Generate random bytes of high ascii data
|
|
784
|
+
def self.rand_text_highascii(len, bad='')
|
|
785
|
+
foo = []
|
|
786
|
+
foo += (0x80 .. 0xff).map{ |c| c.chr }
|
|
787
|
+
rand_base(len, bad, *foo )
|
|
788
|
+
end
|
|
789
|
+
|
|
790
|
+
#
|
|
791
|
+
# Creates a pattern that can be used for offset calculation purposes. This
|
|
792
|
+
# routine is capable of generating patterns using a supplied set and a
|
|
793
|
+
# supplied number of identifiable characters (slots). The supplied sets
|
|
794
|
+
# should not contain any duplicate characters or the logic will fail.
|
|
795
|
+
#
|
|
796
|
+
def self.pattern_create(length, sets = nil)
|
|
797
|
+
buf = ''
|
|
798
|
+
idx = 0
|
|
799
|
+
offsets = []
|
|
800
|
+
|
|
801
|
+
# Make sure there's something in sets even if we were given an explicit nil
|
|
802
|
+
sets ||= [ UpperAlpha, LowerAlpha, Numerals ]
|
|
803
|
+
|
|
804
|
+
# Return stupid uses
|
|
805
|
+
return "" if length.to_i < 1
|
|
806
|
+
return sets[0][0] * length if sets.size == 1 and sets[0].size == 1
|
|
807
|
+
|
|
808
|
+
sets.length.times { offsets << 0 }
|
|
809
|
+
|
|
810
|
+
until buf.length >= length
|
|
811
|
+
begin
|
|
812
|
+
buf << converge_sets(sets, 0, offsets, length)
|
|
813
|
+
end
|
|
814
|
+
end
|
|
815
|
+
|
|
816
|
+
# Maximum permutations reached, but we need more data
|
|
817
|
+
if (buf.length < length)
|
|
818
|
+
buf = buf * (length / buf.length.to_f).ceil
|
|
819
|
+
end
|
|
820
|
+
|
|
821
|
+
buf[0,length]
|
|
822
|
+
end
|
|
823
|
+
|
|
824
|
+
# Step through an arbitrary number of sets of bytes to build up a findable pattern.
|
|
825
|
+
# This is mostly useful for experimentially determining offset lengths into memory
|
|
826
|
+
# structures. Note that the supplied sets should never contain duplicate bytes, or
|
|
827
|
+
# else it can become impossible to measure the offset accurately.
|
|
828
|
+
def self.patt2(len, sets = nil)
|
|
829
|
+
buf = ""
|
|
830
|
+
counter = []
|
|
831
|
+
sets ||= [ UpperAlpha, LowerAlpha, Numerals ]
|
|
832
|
+
len ||= len.to_i
|
|
833
|
+
return "" if len.zero?
|
|
834
|
+
|
|
835
|
+
sets = sets.map {|a| a.split(//)}
|
|
836
|
+
sets.size.times { counter << 0}
|
|
837
|
+
0.upto(len-1) do |i|
|
|
838
|
+
setnum = i % sets.size
|
|
839
|
+
|
|
840
|
+
puts counter.inspect
|
|
841
|
+
end
|
|
842
|
+
|
|
843
|
+
return buf
|
|
844
|
+
end
|
|
845
|
+
|
|
846
|
+
#
|
|
847
|
+
# Calculate the offset to a pattern
|
|
848
|
+
#
|
|
849
|
+
def self.pattern_offset(pattern, value, start=0)
|
|
850
|
+
if (value.kind_of?(String))
|
|
851
|
+
pattern.index(value, start)
|
|
852
|
+
elsif (value.kind_of?(Fixnum) or value.kind_of?(Bignum))
|
|
853
|
+
pattern.index([ value ].pack('V'), start)
|
|
854
|
+
else
|
|
855
|
+
raise ::ArgumentError, "Invalid class for value: #{value.class}"
|
|
856
|
+
end
|
|
857
|
+
end
|
|
858
|
+
|
|
859
|
+
#
|
|
860
|
+
# Compresses a string, eliminating all superfluous whitespace before and
|
|
861
|
+
# after lines and eliminating all lines.
|
|
862
|
+
#
|
|
863
|
+
def self.compress(str)
|
|
864
|
+
str.gsub(/\n/m, ' ').gsub(/\s+/, ' ').gsub(/^\s+/, '').gsub(/\s+$/, '')
|
|
865
|
+
end
|
|
866
|
+
|
|
867
|
+
#
|
|
868
|
+
# Randomize the whitespace in a string
|
|
869
|
+
#
|
|
870
|
+
def self.randomize_space(str)
|
|
871
|
+
str.gsub(/\s+/) { |s|
|
|
872
|
+
len = rand(50)+2
|
|
873
|
+
set = "\x09\x20\x0d\x0a"
|
|
874
|
+
buf = ''
|
|
875
|
+
while (buf.length < len)
|
|
876
|
+
buf << set[rand(set.length),1]
|
|
877
|
+
end
|
|
878
|
+
|
|
879
|
+
buf
|
|
880
|
+
}
|
|
881
|
+
end
|
|
882
|
+
|
|
883
|
+
# Returns true if zlib can be used.
|
|
884
|
+
def self.zlib_present?
|
|
885
|
+
begin
|
|
886
|
+
temp = Zlib
|
|
887
|
+
return true
|
|
888
|
+
rescue
|
|
889
|
+
return false
|
|
890
|
+
end
|
|
891
|
+
end
|
|
892
|
+
|
|
893
|
+
# backwards compat for just a bit...
|
|
894
|
+
def self.gzip_present?
|
|
895
|
+
self.zlib_present?
|
|
896
|
+
end
|
|
897
|
+
|
|
898
|
+
#
|
|
899
|
+
# Compresses a string using zlib
|
|
900
|
+
#
|
|
901
|
+
def self.zlib_deflate(str, level = Zlib::BEST_COMPRESSION)
|
|
902
|
+
if self.zlib_present?
|
|
903
|
+
z = Zlib::Deflate.new(level)
|
|
904
|
+
dst = z.deflate(str, Zlib::FINISH)
|
|
905
|
+
z.close
|
|
906
|
+
return dst
|
|
907
|
+
else
|
|
908
|
+
raise RuntimeError, "Gzip support is not present."
|
|
909
|
+
end
|
|
910
|
+
end
|
|
911
|
+
|
|
912
|
+
#
|
|
913
|
+
# Uncompresses a string using zlib
|
|
914
|
+
#
|
|
915
|
+
def self.zlib_inflate(str)
|
|
916
|
+
if(self.zlib_present?)
|
|
917
|
+
zstream = Zlib::Inflate.new
|
|
918
|
+
buf = zstream.inflate(str)
|
|
919
|
+
zstream.finish
|
|
920
|
+
zstream.close
|
|
921
|
+
return buf
|
|
922
|
+
else
|
|
923
|
+
raise RuntimeError, "Gzip support is not present."
|
|
924
|
+
end
|
|
925
|
+
end
|
|
926
|
+
|
|
927
|
+
#
|
|
928
|
+
# Compresses a string using gzip
|
|
929
|
+
#
|
|
930
|
+
def self.gzip(str, level = 9)
|
|
931
|
+
raise RuntimeError, "Gzip support is not present." if (!zlib_present?)
|
|
932
|
+
raise RuntimeError, "Invalid gzip compression level" if (level < 1 or level > 9)
|
|
933
|
+
|
|
934
|
+
s = ""
|
|
935
|
+
s.force_encoding('ASCII-8BIT') if s.respond_to?(:encoding)
|
|
936
|
+
gz = Zlib::GzipWriter.new(StringIO.new(s, 'wb'), level)
|
|
937
|
+
gz << str
|
|
938
|
+
gz.close
|
|
939
|
+
return s
|
|
940
|
+
end
|
|
941
|
+
|
|
942
|
+
#
|
|
943
|
+
# Uncompresses a string using gzip
|
|
944
|
+
#
|
|
945
|
+
def self.ungzip(str)
|
|
946
|
+
raise RuntimeError, "Gzip support is not present." if (!zlib_present?)
|
|
947
|
+
|
|
948
|
+
s = ""
|
|
949
|
+
s.force_encoding('ASCII-8BIT') if s.respond_to?(:encoding)
|
|
950
|
+
gz = Zlib::GzipReader.new(StringIO.new(str, 'rb'))
|
|
951
|
+
s << gz.read
|
|
952
|
+
gz.close
|
|
953
|
+
return s
|
|
954
|
+
end
|
|
955
|
+
|
|
956
|
+
#
|
|
957
|
+
# Return the index of the first badchar in data, otherwise return
|
|
958
|
+
# nil if there wasn't any badchar occurences.
|
|
959
|
+
#
|
|
960
|
+
def self.badchar_index(data, badchars = '')
|
|
961
|
+
badchars.unpack("C*").each { |badchar|
|
|
962
|
+
pos = data.index(badchar.chr)
|
|
963
|
+
return pos if pos
|
|
964
|
+
}
|
|
965
|
+
return nil
|
|
966
|
+
end
|
|
967
|
+
|
|
968
|
+
#
|
|
969
|
+
# This method removes bad characters from a string.
|
|
970
|
+
#
|
|
971
|
+
def self.remove_badchars(data, badchars = '')
|
|
972
|
+
data.delete(badchars)
|
|
973
|
+
end
|
|
974
|
+
|
|
975
|
+
#
|
|
976
|
+
# This method returns all chars but the supplied set
|
|
977
|
+
#
|
|
978
|
+
def self.charset_exclude(keepers)
|
|
979
|
+
[*(0..255)].pack('C*').delete(keepers)
|
|
980
|
+
end
|
|
981
|
+
|
|
982
|
+
#
|
|
983
|
+
# Shuffles a byte stream
|
|
984
|
+
#
|
|
985
|
+
def self.shuffle_s(str)
|
|
986
|
+
shuffle_a(str.unpack("C*")).pack("C*")
|
|
987
|
+
end
|
|
988
|
+
|
|
989
|
+
#
|
|
990
|
+
# Performs a Fisher-Yates shuffle on an array
|
|
991
|
+
#
|
|
992
|
+
def self.shuffle_a(arr)
|
|
993
|
+
len = arr.length
|
|
994
|
+
max = len - 1
|
|
995
|
+
cyc = [* (0..max) ]
|
|
996
|
+
for d in cyc
|
|
997
|
+
e = rand(d+1)
|
|
998
|
+
next if e == d
|
|
999
|
+
f = arr[d];
|
|
1000
|
+
g = arr[e];
|
|
1001
|
+
arr[d] = g;
|
|
1002
|
+
arr[e] = f;
|
|
1003
|
+
end
|
|
1004
|
+
return arr
|
|
1005
|
+
end
|
|
1006
|
+
|
|
1007
|
+
# Permute the case of a word
|
|
1008
|
+
def self.permute_case(word, idx=0)
|
|
1009
|
+
res = []
|
|
1010
|
+
|
|
1011
|
+
if( (UpperAlpha+LowerAlpha).index(word[idx,1]))
|
|
1012
|
+
|
|
1013
|
+
word_ucase = word.dup
|
|
1014
|
+
word_ucase[idx, 1] = word[idx, 1].upcase
|
|
1015
|
+
|
|
1016
|
+
word_lcase = word.dup
|
|
1017
|
+
word_lcase[idx, 1] = word[idx, 1].downcase
|
|
1018
|
+
|
|
1019
|
+
if (idx == word.length)
|
|
1020
|
+
return [word]
|
|
1021
|
+
else
|
|
1022
|
+
res << permute_case(word_ucase, idx+1)
|
|
1023
|
+
res << permute_case(word_lcase, idx+1)
|
|
1024
|
+
end
|
|
1025
|
+
else
|
|
1026
|
+
res << permute_case(word, idx+1)
|
|
1027
|
+
end
|
|
1028
|
+
|
|
1029
|
+
res.flatten
|
|
1030
|
+
end
|
|
1031
|
+
|
|
1032
|
+
# Generate a random hostname
|
|
1033
|
+
def self.rand_hostname
|
|
1034
|
+
host = []
|
|
1035
|
+
(rand(5) + 1).times {
|
|
1036
|
+
host.push(Rex::Text.rand_text_alphanumeric(rand(10) + 1))
|
|
1037
|
+
}
|
|
1038
|
+
d = ['com', 'net', 'org', 'gov']
|
|
1039
|
+
host.push(d[rand(d.size)])
|
|
1040
|
+
host.join('.').downcase
|
|
1041
|
+
end
|
|
1042
|
+
|
|
1043
|
+
# Generate a state
|
|
1044
|
+
def self.rand_state()
|
|
1045
|
+
States[rand(States.size)]
|
|
1046
|
+
end
|
|
1047
|
+
|
|
1048
|
+
|
|
1049
|
+
#
|
|
1050
|
+
# Calculate the ROR13 hash of a given string
|
|
1051
|
+
#
|
|
1052
|
+
def self.ror13_hash(name)
|
|
1053
|
+
hash = 0
|
|
1054
|
+
name.unpack("C*").each {|c| hash = ror(hash, 13); hash += c }
|
|
1055
|
+
hash
|
|
1056
|
+
end
|
|
1057
|
+
|
|
1058
|
+
#
|
|
1059
|
+
# Rotate a 32-bit value to the right by cnt bits
|
|
1060
|
+
#
|
|
1061
|
+
def self.ror(val, cnt)
|
|
1062
|
+
bits = [val].pack("N").unpack("B32")[0].split(//)
|
|
1063
|
+
1.upto(cnt) do |c|
|
|
1064
|
+
bits.unshift( bits.pop )
|
|
1065
|
+
end
|
|
1066
|
+
[bits.join].pack("B32").unpack("N")[0]
|
|
1067
|
+
end
|
|
1068
|
+
|
|
1069
|
+
#
|
|
1070
|
+
# Rotate a 32-bit value to the left by cnt bits
|
|
1071
|
+
#
|
|
1072
|
+
def self.rol(val, cnt)
|
|
1073
|
+
bits = [val].pack("N").unpack("B32")[0].split(//)
|
|
1074
|
+
1.upto(cnt) do |c|
|
|
1075
|
+
bits.push( bits.shift )
|
|
1076
|
+
end
|
|
1077
|
+
[bits.join].pack("B32").unpack("N")[0]
|
|
1078
|
+
end
|
|
1079
|
+
|
|
1080
|
+
#
|
|
1081
|
+
# Split a string by n charachter into an array
|
|
1082
|
+
#
|
|
1083
|
+
def self.split_to_a(str, n)
|
|
1084
|
+
if n > 0
|
|
1085
|
+
s = str.dup
|
|
1086
|
+
until s.empty?
|
|
1087
|
+
(ret ||= []).push s.slice!(0, n)
|
|
1088
|
+
end
|
|
1089
|
+
else
|
|
1090
|
+
ret = str
|
|
1091
|
+
end
|
|
1092
|
+
ret
|
|
1093
|
+
end
|
|
1094
|
+
|
|
1095
|
+
#
|
|
1096
|
+
#Pack a value as 64 bit litle endian; does not exist for Array.pack
|
|
1097
|
+
#
|
|
1098
|
+
def self.pack_int64le(val)
|
|
1099
|
+
[val & 0x00000000ffffffff, val >> 32].pack("V2")
|
|
1100
|
+
end
|
|
1101
|
+
|
|
1102
|
+
|
|
1103
|
+
protected
|
|
1104
|
+
|
|
1105
|
+
def self.converge_sets(sets, idx, offsets, length) # :nodoc:
|
|
1106
|
+
buf = sets[idx][offsets[idx]].chr
|
|
1107
|
+
|
|
1108
|
+
# If there are more sets after use, converage with them.
|
|
1109
|
+
if (sets[idx + 1])
|
|
1110
|
+
buf << converge_sets(sets, idx + 1, offsets, length)
|
|
1111
|
+
else
|
|
1112
|
+
# Increment the current set offset as well as previous ones if we
|
|
1113
|
+
# wrap back to zero.
|
|
1114
|
+
while (idx >= 0 and ((offsets[idx] = (offsets[idx] + 1) % sets[idx].length)) == 0)
|
|
1115
|
+
idx -= 1
|
|
1116
|
+
end
|
|
1117
|
+
|
|
1118
|
+
# If we reached the point where the idx fell below zero, then that
|
|
1119
|
+
# means we've reached the maximum threshold for permutations.
|
|
1120
|
+
if (idx < 0)
|
|
1121
|
+
return buf
|
|
1122
|
+
end
|
|
1123
|
+
|
|
1124
|
+
end
|
|
1125
|
+
|
|
1126
|
+
buf
|
|
1127
|
+
end
|
|
1128
|
+
|
|
1129
|
+
def self.load_codepage()
|
|
1130
|
+
return if (!@@codepage_map_cache.nil?)
|
|
1131
|
+
file = File.join(File.dirname(__FILE__),'codepage.map')
|
|
1132
|
+
page = ''
|
|
1133
|
+
name = ''
|
|
1134
|
+
map = {}
|
|
1135
|
+
File.open(file).each { |line|
|
|
1136
|
+
next if line =~ /^#/
|
|
1137
|
+
next if line =~ /^\s*$/
|
|
1138
|
+
data = line.split
|
|
1139
|
+
if data[1] =~ /^\(/
|
|
1140
|
+
page = data.shift.to_i
|
|
1141
|
+
name = data.join(' ').sub(/^\(/,'').sub(/\)$/,'')
|
|
1142
|
+
map[page] = {}
|
|
1143
|
+
map[page]['name'] = name
|
|
1144
|
+
map[page]['data'] = {}
|
|
1145
|
+
else
|
|
1146
|
+
data.each { |entry|
|
|
1147
|
+
wide, char = entry.split(':')
|
|
1148
|
+
char = [char].pack('H*')
|
|
1149
|
+
wide = [wide].pack('H*')
|
|
1150
|
+
if map[page]['data'][char].nil?
|
|
1151
|
+
map[page]['data'][char] = [wide]
|
|
1152
|
+
else
|
|
1153
|
+
map[page]['data'][char].push(wide)
|
|
1154
|
+
end
|
|
1155
|
+
}
|
|
1156
|
+
end
|
|
1157
|
+
}
|
|
1158
|
+
@@codepage_map_cache = map
|
|
1159
|
+
end
|
|
1160
|
+
|
|
1161
|
+
end
|
|
1162
|
+
end
|
|
1163
|
+
|