librex 0.0.68 → 0.0.70

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.
Files changed (528) hide show
  1. checksums.yaml +15 -0
  2. data/README.markdown +1 -1
  3. data/Rakefile +18 -16
  4. data/lib/rex.rb +14 -10
  5. data/lib/rex/LICENSE +2 -2
  6. data/lib/rex/arch.rb +76 -76
  7. data/lib/rex/arch/sparc.rb +57 -58
  8. data/lib/rex/arch/x86.rb +506 -496
  9. data/lib/rex/assembly/nasm.rb +83 -84
  10. data/lib/rex/compat.rb +228 -173
  11. data/lib/rex/constants.rb +47 -37
  12. data/lib/rex/elfparsey.rb +0 -3
  13. data/lib/rex/elfparsey/elf.rb +107 -110
  14. data/lib/rex/elfparsey/elfbase.rb +244 -247
  15. data/lib/rex/elfparsey/exceptions.rb +0 -3
  16. data/lib/rex/elfscan.rb +0 -3
  17. data/lib/rex/elfscan/scanner.rb +184 -166
  18. data/lib/rex/elfscan/search.rb +35 -38
  19. data/lib/rex/encoder/alpha2.rb +1 -2
  20. data/lib/rex/encoder/alpha2/alpha_mixed.rb +52 -53
  21. data/lib/rex/encoder/alpha2/alpha_upper.rb +62 -63
  22. data/lib/rex/encoder/alpha2/generic.rb +77 -78
  23. data/lib/rex/encoder/alpha2/unicode_mixed.rb +101 -97
  24. data/lib/rex/encoder/alpha2/unicode_upper.rb +106 -107
  25. data/lib/rex/encoder/bloxor/bloxor.rb +326 -0
  26. data/lib/rex/encoder/ndr.rb +68 -68
  27. data/lib/rex/encoder/nonalpha.rb +50 -51
  28. data/lib/rex/encoder/nonupper.rb +50 -51
  29. data/lib/rex/encoder/xdr.rb +78 -78
  30. data/lib/rex/encoder/xor.rb +52 -53
  31. data/lib/rex/encoder/xor/dword.rb +1 -2
  32. data/lib/rex/encoder/xor/dword_additive.rb +1 -2
  33. data/lib/rex/encoders/xor_dword.rb +17 -18
  34. data/lib/rex/encoders/xor_dword_additive.rb +35 -36
  35. data/lib/rex/encoding/xor.rb +0 -1
  36. data/lib/rex/encoding/xor/byte.rb +3 -4
  37. data/lib/rex/encoding/xor/dword.rb +3 -4
  38. data/lib/rex/encoding/xor/dword_additive.rb +72 -73
  39. data/lib/rex/encoding/xor/exceptions.rb +2 -3
  40. data/lib/rex/encoding/xor/generic.rb +129 -130
  41. data/lib/rex/encoding/xor/qword.rb +3 -4
  42. data/lib/rex/encoding/xor/word.rb +3 -4
  43. data/lib/rex/exceptions.rb +100 -101
  44. data/lib/rex/exploitation/cmdstager.rb +3 -3
  45. data/lib/rex/exploitation/cmdstager/base.rb +170 -156
  46. data/lib/rex/exploitation/cmdstager/bourne.rb +105 -0
  47. data/lib/rex/exploitation/cmdstager/debug_asm.rb +110 -113
  48. data/lib/rex/exploitation/cmdstager/debug_write.rb +106 -109
  49. data/lib/rex/exploitation/cmdstager/echo.rb +164 -0
  50. data/lib/rex/exploitation/cmdstager/printf.rb +122 -0
  51. data/lib/rex/exploitation/cmdstager/tftp.rb +34 -27
  52. data/lib/rex/exploitation/cmdstager/vbs.rb +95 -98
  53. data/lib/rex/exploitation/egghunter.rb +359 -346
  54. data/lib/rex/exploitation/encryptjs.rb +60 -60
  55. data/lib/rex/exploitation/heaplib.rb +76 -76
  56. data/lib/rex/exploitation/js.rb +6 -0
  57. data/lib/rex/exploitation/js/detect.rb +69 -0
  58. data/lib/rex/exploitation/js/memory.rb +81 -0
  59. data/lib/rex/exploitation/js/network.rb +84 -0
  60. data/lib/rex/exploitation/js/utils.rb +33 -0
  61. data/lib/rex/exploitation/jsobfu.rb +448 -424
  62. data/lib/rex/exploitation/obfuscatejs.rb +301 -301
  63. data/lib/rex/exploitation/omelet.rb +257 -257
  64. data/lib/rex/exploitation/opcodedb.rb +699 -699
  65. data/lib/rex/exploitation/ropdb.rb +189 -0
  66. data/lib/rex/exploitation/seh.rb +68 -68
  67. data/lib/rex/file.rb +96 -49
  68. data/lib/rex/image_source.rb +0 -3
  69. data/lib/rex/image_source/disk.rb +45 -48
  70. data/lib/rex/image_source/image_source.rb +33 -36
  71. data/lib/rex/image_source/memory.rb +17 -20
  72. data/lib/rex/io/bidirectional_pipe.rb +118 -115
  73. data/lib/rex/io/datagram_abstraction.rb +13 -14
  74. data/lib/rex/io/ring_buffer.rb +273 -273
  75. data/lib/rex/io/stream.rb +284 -284
  76. data/lib/rex/io/stream_abstraction.rb +183 -181
  77. data/lib/rex/io/stream_server.rb +193 -193
  78. data/lib/rex/job_container.rb +167 -167
  79. data/lib/rex/logging.rb +0 -1
  80. data/lib/rex/logging/log_dispatcher.rb +113 -113
  81. data/lib/rex/logging/log_sink.rb +17 -17
  82. data/lib/rex/logging/sinks/flatfile.rb +36 -36
  83. data/lib/rex/logging/sinks/stderr.rb +27 -27
  84. data/lib/rex/mac_oui.rb +16572 -16571
  85. data/lib/rex/machparsey.rb +0 -1
  86. data/lib/rex/machparsey/exceptions.rb +0 -1
  87. data/lib/rex/machparsey/mach.rb +160 -161
  88. data/lib/rex/machparsey/machbase.rb +367 -368
  89. data/lib/rex/machscan.rb +0 -1
  90. data/lib/rex/machscan/scanner.rb +175 -176
  91. data/lib/rex/mime/encoding.rb +17 -0
  92. data/lib/rex/mime/header.rb +58 -58
  93. data/lib/rex/mime/message.rb +140 -137
  94. data/lib/rex/mime/part.rb +41 -12
  95. data/lib/rex/nop/opty2.rb +90 -90
  96. data/lib/rex/nop/opty2_tables.rb +273 -273
  97. data/lib/rex/ole.rb +0 -4
  98. data/lib/rex/ole/clsid.rb +26 -30
  99. data/lib/rex/ole/difat.rb +121 -125
  100. data/lib/rex/ole/directory.rb +205 -209
  101. data/lib/rex/ole/direntry.rb +217 -221
  102. data/lib/rex/ole/fat.rb +79 -83
  103. data/lib/rex/ole/header.rb +178 -182
  104. data/lib/rex/ole/minifat.rb +49 -53
  105. data/lib/rex/ole/propset.rb +113 -117
  106. data/lib/rex/ole/samples/create_ole.rb +8 -9
  107. data/lib/rex/ole/samples/dir.rb +10 -11
  108. data/lib/rex/ole/samples/dump_stream.rb +14 -15
  109. data/lib/rex/ole/samples/ole_info.rb +5 -6
  110. data/lib/rex/ole/storage.rb +372 -376
  111. data/lib/rex/ole/stream.rb +33 -37
  112. data/lib/rex/ole/substorage.rb +20 -24
  113. data/lib/rex/ole/util.rb +137 -141
  114. data/lib/rex/parser/acunetix_nokogiri.rb +398 -398
  115. data/lib/rex/parser/apple_backup_manifestdb.rb +116 -116
  116. data/lib/rex/parser/appscan_nokogiri.rb +359 -359
  117. data/lib/rex/parser/arguments.rb +88 -88
  118. data/lib/rex/parser/burp_session_nokogiri.rb +258 -258
  119. data/lib/rex/parser/ci_nokogiri.rb +184 -184
  120. data/lib/rex/parser/foundstone_nokogiri.rb +334 -333
  121. data/lib/rex/parser/fusionvm_nokogiri.rb +94 -94
  122. data/lib/rex/parser/ini.rb +167 -167
  123. data/lib/rex/parser/ip360_aspl_xml.rb +84 -84
  124. data/lib/rex/parser/ip360_xml.rb +77 -77
  125. data/lib/rex/parser/mbsa_nokogiri.rb +224 -224
  126. data/lib/rex/parser/nessus_xml.rb +100 -100
  127. data/lib/rex/parser/netsparker_xml.rb +89 -75
  128. data/lib/rex/parser/nexpose_raw_nokogiri.rb +677 -677
  129. data/lib/rex/parser/nexpose_simple_nokogiri.rb +322 -322
  130. data/lib/rex/parser/nexpose_xml.rb +105 -105
  131. data/lib/rex/parser/nmap_nokogiri.rb +386 -386
  132. data/lib/rex/parser/nmap_xml.rb +116 -116
  133. data/lib/rex/parser/nokogiri_doc_mixin.rb +223 -221
  134. data/lib/rex/parser/openvas_nokogiri.rb +162 -162
  135. data/lib/rex/parser/outpost24_nokogiri.rb +239 -0
  136. data/lib/rex/parser/retina_xml.rb +90 -90
  137. data/lib/rex/parser/unattend.rb +171 -0
  138. data/lib/rex/parser/wapiti_nokogiri.rb +89 -89
  139. data/lib/rex/payloads/win32/common.rb +14 -14
  140. data/lib/rex/payloads/win32/kernel.rb +36 -36
  141. data/lib/rex/payloads/win32/kernel/common.rb +32 -32
  142. data/lib/rex/payloads/win32/kernel/recovery.rb +27 -27
  143. data/lib/rex/payloads/win32/kernel/stager.rb +170 -170
  144. data/lib/rex/peparsey.rb +0 -3
  145. data/lib/rex/peparsey/exceptions.rb +0 -3
  146. data/lib/rex/peparsey/pe.rb +196 -199
  147. data/lib/rex/peparsey/pe_memdump.rb +35 -38
  148. data/lib/rex/peparsey/pebase.rb +1633 -1652
  149. data/lib/rex/peparsey/section.rb +115 -124
  150. data/lib/rex/pescan.rb +0 -3
  151. data/lib/rex/pescan/analyze.rb +351 -351
  152. data/lib/rex/pescan/scanner.rb +182 -182
  153. data/lib/rex/pescan/search.rb +59 -59
  154. data/lib/rex/platforms/windows.rb +37 -37
  155. data/lib/rex/poly.rb +111 -110
  156. data/lib/rex/poly/block.rb +419 -417
  157. data/lib/rex/poly/machine.rb +12 -0
  158. data/lib/rex/poly/machine/machine.rb +829 -0
  159. data/lib/rex/poly/machine/x86.rb +508 -0
  160. data/lib/rex/poly/register.rb +70 -70
  161. data/lib/rex/poly/register/x86.rb +22 -22
  162. data/lib/rex/post.rb +0 -1
  163. data/lib/rex/post/dir.rb +35 -36
  164. data/lib/rex/post/file.rb +140 -141
  165. data/lib/rex/post/file_stat.rb +198 -199
  166. data/lib/rex/post/io.rb +167 -168
  167. data/lib/rex/post/meterpreter.rb +1 -1
  168. data/lib/rex/post/meterpreter/channel.rb +389 -390
  169. data/lib/rex/post/meterpreter/channel_container.rb +33 -34
  170. data/lib/rex/post/meterpreter/channels/pool.rb +129 -130
  171. data/lib/rex/post/meterpreter/channels/pools/file.rb +35 -36
  172. data/lib/rex/post/meterpreter/channels/pools/stream_pool.rb +72 -73
  173. data/lib/rex/post/meterpreter/channels/stream.rb +62 -63
  174. data/lib/rex/post/meterpreter/client.rb +442 -436
  175. data/lib/rex/post/meterpreter/client_core.rb +326 -310
  176. data/lib/rex/post/meterpreter/dependencies.rb +0 -1
  177. data/lib/rex/post/meterpreter/extension.rb +12 -13
  178. data/lib/rex/post/meterpreter/extensions/espia/espia.rb +35 -36
  179. data/lib/rex/post/meterpreter/extensions/extapi/adsi/adsi.rb +71 -0
  180. data/lib/rex/post/meterpreter/extensions/extapi/clipboard/clipboard.rb +169 -0
  181. data/lib/rex/post/meterpreter/extensions/extapi/extapi.rb +45 -0
  182. data/lib/rex/post/meterpreter/extensions/extapi/service/service.rb +104 -0
  183. data/lib/rex/post/meterpreter/extensions/extapi/tlv.rb +77 -0
  184. data/lib/rex/post/meterpreter/extensions/extapi/window/window.rb +56 -0
  185. data/lib/rex/post/meterpreter/extensions/extapi/wmi/wmi.rb +75 -0
  186. data/lib/rex/post/meterpreter/extensions/incognito/incognito.rb +70 -71
  187. data/lib/rex/post/meterpreter/extensions/kiwi/kiwi.rb +361 -0
  188. data/lib/rex/post/meterpreter/extensions/kiwi/tlv.rb +76 -0
  189. data/lib/rex/post/meterpreter/extensions/lanattacks/dhcp/dhcp.rb +78 -0
  190. data/lib/rex/post/meterpreter/extensions/lanattacks/lanattacks.rb +22 -78
  191. data/lib/rex/post/meterpreter/extensions/lanattacks/tftp/tftp.rb +49 -0
  192. data/lib/rex/post/meterpreter/extensions/lanattacks/tlv.rb +4 -4
  193. data/lib/rex/post/meterpreter/extensions/mimikatz/mimikatz.rb +128 -0
  194. data/lib/rex/post/meterpreter/extensions/mimikatz/tlv.rb +16 -0
  195. data/lib/rex/post/meterpreter/extensions/networkpug/networkpug.rb +38 -39
  196. data/lib/rex/post/meterpreter/extensions/networkpug/tlv.rb +1 -1
  197. data/lib/rex/post/meterpreter/extensions/priv/fs.rb +95 -96
  198. data/lib/rex/post/meterpreter/extensions/priv/passwd.rb +39 -40
  199. data/lib/rex/post/meterpreter/extensions/priv/priv.rb +80 -85
  200. data/lib/rex/post/meterpreter/extensions/sniffer/sniffer.rb +94 -95
  201. data/lib/rex/post/meterpreter/extensions/stdapi/constants.rb +207 -147
  202. data/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +258 -259
  203. data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +366 -301
  204. data/lib/rex/post/meterpreter/extensions/stdapi/fs/file_stat.rb +72 -73
  205. data/lib/rex/post/meterpreter/extensions/stdapi/fs/io.rb +24 -25
  206. data/lib/rex/post/meterpreter/extensions/stdapi/net/arp.rb +59 -0
  207. data/lib/rex/post/meterpreter/extensions/stdapi/net/config.rb +227 -149
  208. data/lib/rex/post/meterpreter/extensions/stdapi/net/interface.rb +107 -108
  209. data/lib/rex/post/meterpreter/extensions/stdapi/net/netstat.rb +97 -0
  210. data/lib/rex/post/meterpreter/extensions/stdapi/net/resolve.rb +106 -0
  211. data/lib/rex/post/meterpreter/extensions/stdapi/net/route.rb +41 -42
  212. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket.rb +102 -101
  213. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_client_channel.rb +151 -152
  214. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_server_channel.rb +142 -142
  215. data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb +185 -185
  216. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/api_constants.rb +38118 -38117
  217. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/buffer_item.rb +7 -7
  218. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_advapi32.rb +2086 -2084
  219. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_crypt32.rb +15 -15
  220. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_iphlpapi.rb +80 -80
  221. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_kernel32.rb +3835 -3833
  222. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_netapi32.rb +84 -28
  223. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_ntdll.rb +151 -137
  224. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_shell32.rb +15 -6
  225. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_user32.rb +3155 -3155
  226. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_version.rb +41 -0
  227. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_wlanapi.rb +70 -70
  228. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_wldap32.rb +128 -0
  229. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/def/def_ws2_32.rb +596 -596
  230. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb +310 -301
  231. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_function.rb +71 -61
  232. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_helper.rb +100 -100
  233. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_wrapper.rb +14 -14
  234. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/mock_magic.rb +488 -488
  235. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/multicall.rb +273 -264
  236. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/platform_util.rb +5 -5
  237. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb +240 -238
  238. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/tlv.rb +17 -15
  239. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/type/pointer_util.rb +61 -61
  240. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/util.rb +654 -635
  241. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/win_const_manager.rb +49 -49
  242. data/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb +103 -102
  243. data/lib/rex/post/meterpreter/extensions/stdapi/sys/config.rb +98 -68
  244. data/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log.rb +165 -166
  245. data/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log_subsystem/event_record.rb +16 -17
  246. data/lib/rex/post/meterpreter/extensions/stdapi/sys/power.rb +34 -36
  247. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb +363 -364
  248. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/image.rb +102 -103
  249. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/io.rb +28 -29
  250. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/memory.rb +303 -304
  251. data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/thread.rb +113 -114
  252. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry.rb +260 -261
  253. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb +165 -166
  254. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_value.rb +69 -70
  255. data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/remote_registry_key.rb +160 -161
  256. data/lib/rex/post/meterpreter/extensions/stdapi/sys/thread.rb +143 -144
  257. data/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +29 -12
  258. data/lib/rex/post/meterpreter/extensions/stdapi/ui.rb +230 -231
  259. data/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb +181 -44
  260. data/lib/rex/post/meterpreter/inbound_packet_handler.rb +12 -13
  261. data/lib/rex/post/meterpreter/object_aliases.rb +56 -57
  262. data/lib/rex/post/meterpreter/packet.rb +591 -592
  263. data/lib/rex/post/meterpreter/packet_dispatcher.rb +506 -496
  264. data/lib/rex/post/meterpreter/packet_parser.rb +72 -73
  265. data/lib/rex/post/meterpreter/packet_response_waiter.rb +56 -57
  266. data/lib/rex/post/meterpreter/ui/console.rb +112 -112
  267. data/lib/rex/post/meterpreter/ui/console/command_dispatcher.rb +53 -53
  268. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +911 -854
  269. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/espia.rb +86 -86
  270. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi.rb +65 -0
  271. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/adsi.rb +198 -0
  272. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/clipboard.rb +444 -0
  273. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/service.rb +199 -0
  274. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/window.rb +118 -0
  275. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/extapi/wmi.rb +108 -0
  276. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/incognito.rb +220 -220
  277. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/kiwi.rb +509 -0
  278. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks.rb +60 -0
  279. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks/dhcp.rb +254 -0
  280. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/lanattacks/tftp.rb +159 -0
  281. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/mimikatz.rb +182 -0
  282. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/networkpug.rb +173 -173
  283. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv.rb +40 -40
  284. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/elevate.rb +75 -77
  285. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/passwd.rb +30 -30
  286. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/priv/timestomp.rb +105 -105
  287. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/sniffer.rb +182 -182
  288. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi.rb +37 -37
  289. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +504 -482
  290. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/net.rb +401 -330
  291. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +883 -581
  292. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/ui.rb +296 -299
  293. data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/webcam.rb +320 -153
  294. data/lib/rex/post/meterpreter/ui/console/interactive_channel.rb +78 -78
  295. data/lib/rex/post/permission.rb +0 -1
  296. data/lib/rex/post/process.rb +39 -40
  297. data/lib/rex/post/thread.rb +41 -42
  298. data/lib/rex/post/ui.rb +35 -36
  299. data/lib/rex/proto/addp.rb +218 -0
  300. data/lib/rex/proto/dcerpc/client.rb +344 -344
  301. data/lib/rex/proto/dcerpc/exceptions.rb +128 -128
  302. data/lib/rex/proto/dcerpc/handle.rb +32 -32
  303. data/lib/rex/proto/dcerpc/ndr.rb +56 -56
  304. data/lib/rex/proto/dcerpc/packet.rb +249 -245
  305. data/lib/rex/proto/dcerpc/response.rb +170 -170
  306. data/lib/rex/proto/dcerpc/uuid.rb +65 -65
  307. data/lib/rex/proto/dcerpc/wdscp.rb +3 -0
  308. data/lib/rex/proto/dcerpc/wdscp/constants.rb +89 -0
  309. data/lib/rex/proto/dcerpc/wdscp/packet.rb +94 -0
  310. data/lib/rex/proto/dhcp.rb +0 -1
  311. data/lib/rex/proto/dhcp/constants.rb +0 -1
  312. data/lib/rex/proto/dhcp/server.rb +303 -304
  313. data/lib/rex/proto/drda/constants.rb +1 -1
  314. data/lib/rex/proto/drda/packet.rb +186 -186
  315. data/lib/rex/proto/drda/utils.rb +104 -104
  316. data/lib/rex/proto/http.rb +1 -0
  317. data/lib/rex/proto/http/client.rb +692 -820
  318. data/lib/rex/proto/http/client_request.rb +472 -0
  319. data/lib/rex/proto/http/handler.rb +25 -25
  320. data/lib/rex/proto/http/handler/erb.rb +104 -104
  321. data/lib/rex/proto/http/handler/proc.rb +37 -37
  322. data/lib/rex/proto/http/header.rb +149 -149
  323. data/lib/rex/proto/http/packet.rb +388 -382
  324. data/lib/rex/proto/http/request.rb +332 -335
  325. data/lib/rex/proto/http/response.rb +132 -72
  326. data/lib/rex/proto/http/server.rb +348 -338
  327. data/lib/rex/proto/iax2/call.rb +310 -310
  328. data/lib/rex/proto/iax2/client.rb +197 -197
  329. data/lib/rex/proto/iax2/codecs/alaw.rb +4 -4
  330. data/lib/rex/proto/iax2/codecs/mulaw.rb +4 -4
  331. data/lib/rex/proto/ipmi.rb +57 -0
  332. data/lib/rex/proto/ipmi/channel_auth_reply.rb +88 -0
  333. data/lib/rex/proto/ipmi/open_session_reply.rb +35 -0
  334. data/lib/rex/proto/ipmi/rakp2.rb +35 -0
  335. data/lib/rex/proto/ipmi/utils.rb +125 -0
  336. data/lib/rex/proto/natpmp.rb +1 -5
  337. data/lib/rex/proto/natpmp/constants.rb +4 -4
  338. data/lib/rex/proto/natpmp/packet.rb +25 -25
  339. data/lib/rex/proto/ntlm/base.rb +271 -271
  340. data/lib/rex/proto/ntlm/constants.rb +61 -61
  341. data/lib/rex/proto/ntlm/crypt.rb +348 -352
  342. data/lib/rex/proto/ntlm/exceptions.rb +3 -3
  343. data/lib/rex/proto/ntlm/message.rb +468 -471
  344. data/lib/rex/proto/ntlm/utils.rb +746 -746
  345. data/lib/rex/proto/pjl.rb +30 -0
  346. data/lib/rex/proto/pjl/client.rb +162 -0
  347. data/lib/rex/proto/proxy/socks4a.rb +440 -440
  348. data/lib/rex/proto/rfb.rb +1 -8
  349. data/lib/rex/proto/rfb/cipher.rb +46 -49
  350. data/lib/rex/proto/rfb/client.rb +179 -182
  351. data/lib/rex/proto/rfb/constants.rb +18 -21
  352. data/lib/rex/proto/smb/client.rb +1954 -1843
  353. data/lib/rex/proto/smb/constants.rb +533 -516
  354. data/lib/rex/proto/smb/crypt.rb +21 -21
  355. data/lib/rex/proto/smb/evasions.rb +43 -43
  356. data/lib/rex/proto/smb/exceptions.rb +791 -791
  357. data/lib/rex/proto/smb/simpleclient.rb +142 -286
  358. data/lib/rex/proto/smb/simpleclient/open_file.rb +106 -0
  359. data/lib/rex/proto/smb/simpleclient/open_pipe.rb +57 -0
  360. data/lib/rex/proto/smb/utils.rb +81 -81
  361. data/lib/rex/proto/sunrpc/client.rb +158 -158
  362. data/lib/rex/proto/tftp.rb +0 -1
  363. data/lib/rex/proto/tftp/client.rb +289 -289
  364. data/lib/rex/proto/tftp/constants.rb +9 -10
  365. data/lib/rex/proto/tftp/server.rb +466 -467
  366. data/lib/rex/random_identifier_generator.rb +176 -0
  367. data/lib/rex/registry.rb +1 -1
  368. data/lib/rex/registry/hive.rb +88 -88
  369. data/lib/rex/registry/lfkey.rb +25 -25
  370. data/lib/rex/registry/nodekey.rb +30 -30
  371. data/lib/rex/registry/regf.rb +10 -10
  372. data/lib/rex/registry/valuekey.rb +43 -43
  373. data/lib/rex/registry/valuelist.rb +13 -13
  374. data/lib/rex/ropbuilder/rop.rb +254 -253
  375. data/lib/rex/script.rb +21 -22
  376. data/lib/rex/script/base.rb +51 -50
  377. data/lib/rex/script/meterpreter.rb +2 -2
  378. data/lib/rex/service.rb +24 -24
  379. data/lib/rex/service_manager.rb +132 -132
  380. data/lib/rex/services/local_relay.rb +398 -398
  381. data/lib/rex/socket.rb +758 -763
  382. data/lib/rex/socket/comm.rb +95 -95
  383. data/lib/rex/socket/comm/local.rb +507 -440
  384. data/lib/rex/socket/ip.rb +118 -118
  385. data/lib/rex/socket/parameters.rb +351 -350
  386. data/lib/rex/socket/range_walker.rb +445 -368
  387. data/lib/rex/socket/ssl_tcp.rb +323 -317
  388. data/lib/rex/socket/ssl_tcp_server.rb +173 -158
  389. data/lib/rex/socket/subnet_walker.rb +48 -48
  390. data/lib/rex/socket/switch_board.rb +259 -259
  391. data/lib/rex/socket/tcp.rb +58 -56
  392. data/lib/rex/socket/tcp_server.rb +42 -42
  393. data/lib/rex/socket/udp.rb +152 -152
  394. data/lib/rex/sslscan/result.rb +200 -0
  395. data/lib/rex/sslscan/scanner.rb +205 -0
  396. data/lib/rex/struct2.rb +0 -1
  397. data/lib/rex/struct2/c_struct.rb +162 -163
  398. data/lib/rex/struct2/c_struct_template.rb +21 -22
  399. data/lib/rex/struct2/constant.rb +6 -7
  400. data/lib/rex/struct2/element.rb +30 -31
  401. data/lib/rex/struct2/generic.rb +60 -61
  402. data/lib/rex/struct2/restraint.rb +40 -41
  403. data/lib/rex/struct2/s_string.rb +60 -61
  404. data/lib/rex/struct2/s_struct.rb +97 -98
  405. data/lib/rex/sync.rb +0 -1
  406. data/lib/rex/sync/event.rb +62 -72
  407. data/lib/rex/sync/read_write_lock.rb +149 -149
  408. data/lib/rex/sync/ref.rb +42 -42
  409. data/lib/rex/sync/thread_safe.rb +59 -59
  410. data/lib/rex/text.rb +1803 -1315
  411. data/lib/rex/thread_factory.rb +25 -25
  412. data/lib/rex/time.rb +44 -44
  413. data/lib/rex/transformer.rb +91 -91
  414. data/lib/rex/ui/interactive.rb +265 -265
  415. data/lib/rex/ui/output.rb +66 -60
  416. data/lib/rex/ui/progress_tracker.rb +79 -79
  417. data/lib/rex/ui/subscriber.rb +144 -134
  418. data/lib/rex/ui/text/color.rb +76 -76
  419. data/lib/rex/ui/text/dispatcher_shell.rb +512 -505
  420. data/lib/rex/ui/text/input.rb +96 -96
  421. data/lib/rex/ui/text/input/buffer.rb +58 -58
  422. data/lib/rex/ui/text/input/readline.rb +114 -114
  423. data/lib/rex/ui/text/input/socket.rb +77 -77
  424. data/lib/rex/ui/text/input/stdio.rb +24 -24
  425. data/lib/rex/ui/text/irb_shell.rb +45 -41
  426. data/lib/rex/ui/text/output.rb +64 -60
  427. data/lib/rex/ui/text/output/buffer.rb +42 -42
  428. data/lib/rex/ui/text/output/buffer/stdout.rb +25 -0
  429. data/lib/rex/ui/text/output/file.rb +24 -24
  430. data/lib/rex/ui/text/output/socket.rb +24 -24
  431. data/lib/rex/ui/text/output/stdio.rb +29 -29
  432. data/lib/rex/ui/text/output/tee.rb +36 -36
  433. data/lib/rex/ui/text/progress_tracker.rb +37 -37
  434. data/lib/rex/ui/text/shell.rb +371 -361
  435. data/lib/rex/ui/text/table.rb +320 -284
  436. data/lib/rex/zip.rb +0 -1
  437. data/lib/rex/zip/archive.rb +115 -94
  438. data/lib/rex/zip/blocks.rb +101 -100
  439. data/lib/rex/zip/entry.rb +108 -99
  440. data/lib/rex/zip/jar.rb +261 -206
  441. data/lib/rex/zip/samples/comment.rb +1 -2
  442. data/lib/rex/zip/samples/mkwar.rb +12 -13
  443. data/lib/rex/zip/samples/mkzip.rb +1 -2
  444. data/lib/rex/zip/samples/recursive.rb +29 -30
  445. metadata +424 -446
  446. data/lib/rex/arch/sparc.rb.ut.rb +0 -19
  447. data/lib/rex/arch/x86.rb.ut.rb +0 -94
  448. data/lib/rex/assembly/nasm.rb.ut.rb +0 -23
  449. data/lib/rex/encoder/ndr.rb.ut.rb +0 -45
  450. data/lib/rex/encoder/xdr.rb.ut.rb +0 -30
  451. data/lib/rex/encoders/xor_dword_additive.rb.ut.rb +0 -13
  452. data/lib/rex/encoding/xor.rb.ts.rb +0 -15
  453. data/lib/rex/encoding/xor/byte.rb.ut.rb +0 -22
  454. data/lib/rex/encoding/xor/dword.rb.ut.rb +0 -16
  455. data/lib/rex/encoding/xor/dword_additive.rb.ut.rb +0 -16
  456. data/lib/rex/encoding/xor/generic.rb.ut.rb +0 -121
  457. data/lib/rex/encoding/xor/word.rb.ut.rb +0 -14
  458. data/lib/rex/exceptions.rb.ut.rb +0 -45
  459. data/lib/rex/exploitation/egghunter.rb.ut.rb +0 -28
  460. data/lib/rex/exploitation/javascriptosdetect.js +0 -1014
  461. data/lib/rex/exploitation/javascriptosdetect.rb +0 -43
  462. data/lib/rex/exploitation/omelet.rb.ut.rb +0 -27
  463. data/lib/rex/exploitation/opcodedb.rb.ut.rb +0 -280
  464. data/lib/rex/exploitation/seh.rb.ut.rb +0 -20
  465. data/lib/rex/file.rb.ut.rb +0 -17
  466. data/lib/rex/io/ring_buffer.rb.ut.rb +0 -135
  467. data/lib/rex/nop/opty2.rb.ut.rb +0 -24
  468. data/lib/rex/parser/arguments.rb.ut.rb +0 -68
  469. data/lib/rex/parser/ini.rb.ut.rb +0 -30
  470. data/lib/rex/post/meterpreter/extensions/stdapi/railgun.rb.ts.rb +0 -18
  471. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/api_constants.rb.ut.rb +0 -39
  472. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/buffer_item.rb.ut.rb +0 -37
  473. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll.rb.ut.rb +0 -52
  474. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_function.rb.ut.rb +0 -43
  475. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_helper.rb.ut.rb +0 -128
  476. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/dll_wrapper.rb.ut.rb +0 -64
  477. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/platform_util.rb.ut.rb +0 -29
  478. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/railgun.rb.ut.rb +0 -155
  479. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/type/pointer_util.rb.ut.rb +0 -128
  480. data/lib/rex/post/meterpreter/extensions/stdapi/railgun/win_const_manager.rb.ut.rb +0 -124
  481. data/lib/rex/proto.rb.ts.rb +0 -9
  482. data/lib/rex/proto/dcerpc.rb.ts.rb +0 -10
  483. data/lib/rex/proto/dcerpc/client.rb.ut.rb +0 -492
  484. data/lib/rex/proto/dcerpc/handle.rb.ut.rb +0 -86
  485. data/lib/rex/proto/dcerpc/ndr.rb.ut.rb +0 -42
  486. data/lib/rex/proto/dcerpc/packet.rb.ut.rb +0 -57
  487. data/lib/rex/proto/dcerpc/response.rb.ut.rb +0 -16
  488. data/lib/rex/proto/dcerpc/uuid.rb.ut.rb +0 -47
  489. data/lib/rex/proto/drda.rb.ts.rb +0 -18
  490. data/lib/rex/proto/drda/constants.rb.ut.rb +0 -24
  491. data/lib/rex/proto/drda/packet.rb.ut.rb +0 -110
  492. data/lib/rex/proto/drda/utils.rb.ut.rb +0 -85
  493. data/lib/rex/proto/http.rb.ts.rb +0 -13
  494. data/lib/rex/proto/http/client.rb.ut.rb +0 -96
  495. data/lib/rex/proto/http/handler/erb.rb.ut.rb +0 -22
  496. data/lib/rex/proto/http/handler/erb.rb.ut.rb.rhtml +0 -1
  497. data/lib/rex/proto/http/handler/proc.rb.ut.rb +0 -25
  498. data/lib/rex/proto/http/header.rb.ut.rb +0 -47
  499. data/lib/rex/proto/http/packet.rb.ut.rb +0 -166
  500. data/lib/rex/proto/http/request.rb.ut.rb +0 -215
  501. data/lib/rex/proto/http/response.rb.ut.rb +0 -150
  502. data/lib/rex/proto/http/server.rb.ut.rb +0 -80
  503. data/lib/rex/proto/ntlm.rb.ut.rb +0 -181
  504. data/lib/rex/proto/rfb.rb.ut.rb +0 -40
  505. data/lib/rex/proto/smb.rb.ts.rb +0 -9
  506. data/lib/rex/proto/smb/client.rb.ut.rb +0 -224
  507. data/lib/rex/proto/smb/constants.rb.ut.rb +0 -19
  508. data/lib/rex/proto/smb/simpleclient.rb.ut.rb +0 -129
  509. data/lib/rex/proto/smb/utils.rb.ut.rb +0 -21
  510. data/lib/rex/proto/tftp/server.rb.ut.rb +0 -29
  511. data/lib/rex/service_manager.rb.ut.rb +0 -33
  512. data/lib/rex/socket.rb.ut.rb +0 -108
  513. data/lib/rex/socket/comm/local.rb.ut.rb +0 -76
  514. data/lib/rex/socket/parameters.rb.ut.rb +0 -52
  515. data/lib/rex/socket/range_walker.rb.ut.rb +0 -56
  516. data/lib/rex/socket/ssl_tcp.rb.ut.rb +0 -40
  517. data/lib/rex/socket/ssl_tcp_server.rb.ut.rb +0 -62
  518. data/lib/rex/socket/subnet_walker.rb.ut.rb +0 -29
  519. data/lib/rex/socket/switch_board.rb.ut.rb +0 -53
  520. data/lib/rex/socket/tcp.rb.ut.rb +0 -65
  521. data/lib/rex/socket/tcp_server.rb.ut.rb +0 -45
  522. data/lib/rex/socket/udp.rb.ut.rb +0 -45
  523. data/lib/rex/test.rb +0 -36
  524. data/lib/rex/text.rb.ut.rb +0 -193
  525. data/lib/rex/transformer.rb.ut.rb +0 -39
  526. data/lib/rex/ui/text/color.rb.ut.rb +0 -19
  527. data/lib/rex/ui/text/progress_tracker.rb.ut.rb +0 -35
  528. data/lib/rex/ui/text/table.rb.ut.rb +0 -56
@@ -11,48 +11,48 @@ module Rex
11
11
  ###
12
12
  module Ref
13
13
 
14
- #
15
- # Initializes the reference count to one.
16
- #
17
- def refinit
18
- @_references = 1
19
- @_references_mutex = Mutex.new
20
-
21
- self
22
- end
23
-
24
- #
25
- # Increments the total number of references.
26
- #
27
- def ref
28
- @_references_mutex.synchronize {
29
- @_references += 1
30
- }
31
-
32
- self
33
- end
34
-
35
- #
36
- # Decrements the total number of references. If the reference count
37
- # reaches zero, true is returned. Otherwise, false is returned.
38
- #
39
- def deref
40
- @_references_mutex.synchronize {
41
- if ((@_references -= 1) == 0)
42
- cleanup
43
-
44
- true
45
- else
46
- false
47
- end
48
- }
49
- end
50
-
51
- #
52
- # Called to clean up resources once the ref count drops to zero.
53
- #
54
- def cleanup
55
- end
14
+ #
15
+ # Initializes the reference count to one.
16
+ #
17
+ def refinit
18
+ @_references = 1
19
+ @_references_mutex = Mutex.new
20
+
21
+ self
22
+ end
23
+
24
+ #
25
+ # Increments the total number of references.
26
+ #
27
+ def ref
28
+ @_references_mutex.synchronize {
29
+ @_references += 1
30
+ }
31
+
32
+ self
33
+ end
34
+
35
+ #
36
+ # Decrements the total number of references. If the reference count
37
+ # reaches zero, true is returned. Otherwise, false is returned.
38
+ #
39
+ def deref
40
+ @_references_mutex.synchronize {
41
+ if ((@_references -= 1) == 0)
42
+ cleanup
43
+
44
+ true
45
+ else
46
+ false
47
+ end
48
+ }
49
+ end
50
+
51
+ #
52
+ # Called to clean up resources once the ref count drops to zero.
53
+ #
54
+ def cleanup
55
+ end
56
56
 
57
57
  end
58
58
  end
@@ -4,79 +4,79 @@ require 'timeout'
4
4
  module Rex
5
5
 
6
6
  ###
7
- #
7
+ #
8
8
  # This module provides a set of methods for performing various blocking
9
9
  # operations in a manner that is compatible with ruby style threads.
10
10
  #
11
11
  ###
12
12
  module ThreadSafe
13
13
 
14
- DefaultCycle = 0.2
15
-
16
- #
17
- # Wraps calls to select with a lower timeout period and does the
18
- # calculations to walk down to zero timeout. This has a little room for
19
- # improvement in that it should probably check how much time actually
20
- # elapsed during the select call considering ruby threading wont be exactly
21
- # accurate perhaps.
22
- #
23
- def self.select(rfd = nil, wfd = nil, efd = nil, t = nil)
24
- left = t
25
-
26
- # Immediately raise a StreamClosedError if the socket was closed. This
27
- # prevents a bad fd from being passed downstream and solves an issue
28
- # with Ruby on Windows.
29
- rfd.each { |fd| raise StreamClosedError.new(fd) if (fd.closed?) } if rfd
30
-
31
- begin
32
- orig_size = rfd.length if (rfd)
33
-
34
- # Poll the set supplied to us at least once.
35
- begin
36
- rv = ::IO.select(rfd, wfd, efd, DefaultCycle)
37
- rescue ::IOError, ::Errno::EBADF, ::Errno::ENOTSOCK
38
- # If a stream was detected as being closed, re-raise the error as
39
- # a StreamClosedError with the specific file descriptor that was
40
- # detected as being closed. This is to better handle the case of
41
- # a closed socket being detected so that it can be cleaned up and
42
- # removed.
43
- rfd.each { |fd| raise StreamClosedError.new(fd) if (fd.closed?) } if rfd
44
-
45
- # If the original rfd length is not the same as the current
46
- # length, then the list may have been altered and as such may not
47
- # contain the socket that caused the IOError. This is a bad way
48
- # to do this since it's possible that the array length could be
49
- # back to the size that it was originally and yet have had the
50
- # socket that caused the IOError to be removed.
51
- return nil if (rfd and rfd.length != orig_size)
52
-
53
- # Re-raise the exception since we didn't handle it here.
54
- raise $!
14
+ DefaultCycle = 0.2
15
+
16
+ #
17
+ # Wraps calls to select with a lower timeout period and does the
18
+ # calculations to walk down to zero timeout. This has a little room for
19
+ # improvement in that it should probably check how much time actually
20
+ # elapsed during the select call considering ruby threading wont be exactly
21
+ # accurate perhaps.
22
+ #
23
+ def self.select(rfd = nil, wfd = nil, efd = nil, t = nil)
24
+ left = t
25
+
26
+ # Immediately raise a StreamClosedError if the socket was closed. This
27
+ # prevents a bad fd from being passed downstream and solves an issue
28
+ # with Ruby on Windows.
29
+ rfd.each { |fd| raise StreamClosedError.new(fd) if (fd.closed?) } if rfd
30
+
31
+ begin
32
+ orig_size = rfd.length if (rfd)
33
+
34
+ # Poll the set supplied to us at least once.
35
+ begin
36
+ rv = ::IO.select(rfd, wfd, efd, DefaultCycle)
37
+ rescue ::IOError, ::Errno::EBADF, ::Errno::ENOTSOCK
38
+ # If a stream was detected as being closed, re-raise the error as
39
+ # a StreamClosedError with the specific file descriptor that was
40
+ # detected as being closed. This is to better handle the case of
41
+ # a closed socket being detected so that it can be cleaned up and
42
+ # removed.
43
+ rfd.each { |fd| raise StreamClosedError.new(fd) if (fd.closed?) } if rfd
44
+
45
+ # If the original rfd length is not the same as the current
46
+ # length, then the list may have been altered and as such may not
47
+ # contain the socket that caused the IOError. This is a bad way
48
+ # to do this since it's possible that the array length could be
49
+ # back to the size that it was originally and yet have had the
50
+ # socket that caused the IOError to be removed.
51
+ return nil if (rfd and rfd.length != orig_size)
52
+
53
+ # Re-raise the exception since we didn't handle it here.
54
+ raise $!
55
55
  # rescue ::Exception => e
56
56
  # $stderr.puts "SELECT(#{t}) #{[rfd,wfd,efd].inspect} #{e.class} #{e} #{e.backtrace}"
57
- end
57
+ end
58
58
 
59
- return rv if (rv)
59
+ return rv if (rv)
60
60
 
61
- # Decrement the amount of time left by the polling cycle
62
- left -= DefaultCycle if (left)
61
+ # Decrement the amount of time left by the polling cycle
62
+ left -= DefaultCycle if (left)
63
63
 
64
- # Keep chugging until we run out of time, if time was supplied.
65
- end while ((left == nil) or (left > 0))
64
+ # Keep chugging until we run out of time, if time was supplied.
65
+ end while ((left == nil) or (left > 0))
66
66
 
67
- # Nothin.
68
- nil
69
- end
67
+ # Nothin.
68
+ nil
69
+ end
70
70
 
71
- #
72
- # Simulates a sleep operation by selecting on nil until a timeout period
73
- # expires.
74
- #
75
- def self.sleep(seconds)
76
- self.select(nil, nil, nil, seconds)
71
+ #
72
+ # Simulates a sleep operation by selecting on nil until a timeout period
73
+ # expires.
74
+ #
75
+ def self.sleep(seconds=nil)
76
+ self.select(nil, nil, nil, seconds)
77
77
 
78
- seconds
79
- end
78
+ seconds
79
+ end
80
80
 
81
81
  end
82
82
 
@@ -1,15 +1,18 @@
1
1
  # -*- coding: binary -*-
2
2
  require 'digest/md5'
3
+ require 'digest/sha1'
3
4
  require 'stringio'
4
-
5
- begin
6
- old_verbose = $VERBOSE
7
- $VERBOSE = nil
8
- require 'iconv'
9
- require 'zlib'
10
- rescue ::LoadError
11
- ensure
12
- $VERBOSE = old_verbose
5
+ require 'cgi'
6
+
7
+ %W{ iconv zlib }.each do |libname|
8
+ begin
9
+ old_verbose = $VERBOSE
10
+ $VERBOSE = nil
11
+ require libname
12
+ rescue ::LoadError
13
+ ensure
14
+ $VERBOSE = old_verbose
15
+ end
13
16
  end
14
17
 
15
18
  module Rex
@@ -21,1315 +24,1800 @@ module Rex
21
24
  #
22
25
  ###
23
26
  module Text
24
- @@codepage_map_cache = nil
25
-
26
- ##
27
- #
28
- # Constants
29
- #
30
- ##
31
-
32
- States = ["AK", "AL", "AR", "AZ", "CA", "CO", "CT", "DE", "FL", "GA", "HI",
33
- "IA", "ID", "IL", "IN", "KS", "KY", "LA", "MA", "MD", "ME", "MI", "MN",
34
- "MO", "MS", "MT", "NC", "ND", "NE", "NH", "NJ", "NM", "NV", "NY", "OH",
35
- "OK", "OR", "PA", "RI", "SC", "SD", "TN", "TX", "UT", "VA", "VT", "WA",
36
- "WI", "WV", "WY"]
37
- UpperAlpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
38
- LowerAlpha = "abcdefghijklmnopqrstuvwxyz"
39
- Numerals = "0123456789"
40
- Base32 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
41
- Alpha = UpperAlpha + LowerAlpha
42
- AlphaNumeric = Alpha + Numerals
43
- HighAscii = [*(0x80 .. 0xff)].pack("C*")
44
- LowAscii = [*(0x00 .. 0x1f)].pack("C*")
45
- DefaultWrap = 60
46
- AllChars = [*(0x00 .. 0xff)].pack("C*")
47
- Punctuation = ( [*(0x21 .. 0x2f)] + [*(0x3a .. 0x3F)] + [*(0x5b .. 0x60)] + [*(0x7b .. 0x7e)] ).flatten.pack("C*")
48
-
49
- DefaultPatternSets = [ Rex::Text::UpperAlpha, Rex::Text::LowerAlpha, Rex::Text::Numerals ]
50
-
51
- # In case Iconv isn't loaded
52
- 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]
53
- 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]
54
-
55
- ##
56
- #
57
- # Serialization
58
- #
59
- ##
60
-
61
- #
62
- # Converts a raw string into a ruby buffer
63
- #
64
- def self.to_ruby(str, wrap = DefaultWrap, name = "buf")
65
- return hexify(str, wrap, '"', '" +', "#{name} = \n", '"')
66
- end
67
-
68
- #
69
- # Creates a ruby-style comment
70
- #
71
- def self.to_ruby_comment(str, wrap = DefaultWrap)
72
- return wordwrap(str, 0, wrap, '', '# ')
73
- end
74
-
75
- #
76
- # Converts a raw string into a C buffer
77
- #
78
- def self.to_c(str, wrap = DefaultWrap, name = "buf")
79
- return hexify(str, wrap, '"', '"', "unsigned char #{name}[] = \n", '";')
80
- end
81
-
82
- #
83
- # Creates a c-style comment
84
- #
85
- def self.to_c_comment(str, wrap = DefaultWrap)
86
- return "/*\n" + wordwrap(str, 0, wrap, '', ' * ') + " */\n"
87
- end
88
-
89
- #
90
- # Creates a javascript-style comment
91
- #
92
- def self.to_js_comment(str, wrap = DefaultWrap)
93
- return wordwrap(str, 0, wrap, '', '// ')
94
- end
95
-
96
- #
97
- # Converts a raw string into a perl buffer
98
- #
99
- def self.to_perl(str, wrap = DefaultWrap, name = "buf")
100
- return hexify(str, wrap, '"', '" .', "my $#{name} = \n", '";')
101
- end
102
-
103
- #
104
- # Converts a raw string into a Bash buffer
105
- #
106
- def self.to_bash(str, wrap = DefaultWrap, name = "buf")
107
- return hexify(str, wrap, '$\'', '\'\\', "export #{name}=\\\n", '\'')
108
- end
109
-
110
- #
111
- # Converts a raw string into a java byte array
112
- #
113
- def self.to_java(str, name = "shell")
114
- buff = "byte #{name}[] = new byte[]\n{\n"
115
- cnt = 0
116
- max = 0
117
- str.unpack('C*').each do |c|
118
- buff << ", " if max > 0
119
- buff << "\t" if max == 0
120
- buff << sprintf('(byte) 0x%.2x', c)
121
- max +=1
122
- cnt +=1
123
-
124
- if (max > 7)
125
- buff << ",\n" if cnt != str.length
126
- max = 0
127
- end
128
- end
129
- buff << "\n};\n"
130
- return buff
131
- end
132
-
133
- #
134
- # Creates a perl-style comment
135
- #
136
- def self.to_perl_comment(str, wrap = DefaultWrap)
137
- return wordwrap(str, 0, wrap, '', '# ')
138
- end
139
-
140
- #
141
- # Creates a Bash-style comment
142
- #
143
- def self.to_bash_comment(str, wrap = DefaultWrap)
144
- return wordwrap(str, 0, wrap, '', '# ')
145
- end
146
-
147
- #
148
- # Returns the raw string
149
- #
150
- def self.to_raw(str)
151
- return str
152
- end
153
-
154
- #
155
- # Converts ISO-8859-1 to UTF-8
156
- #
157
- def self.to_utf8(str)
158
- begin
159
- Iconv.iconv("utf-8","iso-8859-1", str).join(" ")
160
- rescue
161
- raise ::RuntimeError, "Your installation does not support iconv (needed for utf8 conversion)"
162
- end
163
- end
164
-
165
- #
166
- # Converts ASCII to EBCDIC
167
- #
168
- class IllegalSequence < ArgumentError; end
169
-
170
- # A native implementation of the ASCII->EBCDIC table, used to fall back from using
171
- # Iconv
172
- def self.to_ebcdic_rex(str)
173
- new_str = []
174
- str.each_byte do |x|
175
- if Iconv_ASCII.index(x.chr)
176
- new_str << Iconv_EBCDIC[Iconv_ASCII.index(x.chr)]
177
- else
178
- raise Rex::Text::IllegalSequence, ("\\x%x" % x)
179
- end
180
- end
181
- new_str.join
182
- end
183
-
184
- # A native implementation of the EBCDIC->ASCII table, used to fall back from using
185
- # Iconv
186
- def self.from_ebcdic_rex(str)
187
- new_str = []
188
- str.each_byte do |x|
189
- if Iconv_EBCDIC.index(x.chr)
190
- new_str << Iconv_ASCII[Iconv_EBCDIC.index(x.chr)]
191
- else
192
- raise Rex::Text::IllegalSequence, ("\\x%x" % x)
193
- end
194
- end
195
- new_str.join
196
- end
197
-
198
- def self.to_ebcdic(str)
199
- begin
200
- Iconv.iconv("EBCDIC-US", "ASCII", str).first
201
- rescue ::Iconv::IllegalSequence => e
202
- raise e
203
- rescue
204
- self.to_ebcdic_rex(str)
205
- end
206
- end
207
-
208
- #
209
- # Converts EBCIDC to ASCII
210
- #
211
- def self.from_ebcdic(str)
212
- begin
213
- Iconv.iconv("ASCII", "EBCDIC-US", str).first
214
- rescue ::Iconv::IllegalSequence => e
215
- raise e
216
- rescue
217
- self.from_ebcdic_rex(str)
218
- end
219
- end
220
-
221
- #
222
- # Returns a unicode escaped string for Javascript
223
- #
224
- def self.to_unescape(data, endian=ENDIAN_LITTLE)
225
- data << "\x41" if (data.length % 2 != 0)
226
- dptr = 0
227
- buff = ''
228
- while (dptr < data.length)
229
- c1 = data[dptr,1].unpack("C*")[0]
230
- dptr += 1
231
- c2 = data[dptr,1].unpack("C*")[0]
232
- dptr += 1
233
-
234
- if (endian == ENDIAN_LITTLE)
235
- buff << sprintf('%%u%.2x%.2x', c2, c1)
236
- else
237
- buff << sprintf('%%u%.2x%.2x', c1, c2)
238
- end
239
- end
240
- return buff
241
- end
242
-
243
- def self.to_octal(str, prefix = "\\")
244
- octal = ""
245
- str.each_byte { |b|
246
- octal << "#{prefix}#{b.to_s 8}"
247
- }
248
-
249
- return octal
250
- end
251
-
252
- #
253
- # Returns the hex version of the supplied string
254
- #
255
- def self.to_hex(str, prefix = "\\x", count = 1)
256
- raise ::RuntimeError, "unable to chunk into #{count} byte chunks" if ((str.length % count) > 0)
257
-
258
- # XXX: Regexp.new is used here since using /.{#{count}}/o would compile
259
- # the regex the first time it is used and never check again. Since we
260
- # want to know how many to capture on every instance, we do it this
261
- # way.
262
- return str.unpack('H*')[0].gsub(Regexp.new(".{#{count * 2}}", nil, 'n')) { |s| prefix + s }
263
- end
264
-
265
- #
266
- # Returns the string with nonprintable hex characters sanitized to ascii. Similiar to to_hex,
267
- # but regular ASCII is not translated if count is 1.
268
- #
269
- def self.to_hex_ascii(str, prefix = "\\x", count = 1, suffix=nil)
270
- raise ::RuntimeError, "unable to chunk into #{count} byte chunks" if ((str.length % count) > 0)
271
- return str.unpack('H*')[0].gsub(Regexp.new(".{#{count * 2}}", nil, 'n')) { |s|
272
- (0x20..0x7e) === s.to_i(16) ? s.to_i(16).chr : prefix + s + suffix.to_s
273
- }
274
- end
275
-
276
- #
277
- # Converts standard ASCII text to a unicode string.
278
- #
279
- # Supported unicode types include: utf-16le, utf16-be, utf32-le, utf32-be, utf-7, and utf-8
280
- #
281
- # Providing 'mode' provides hints to the actual encoder as to how it should encode the string. Only UTF-7 and UTF-8 use "mode".
282
- #
283
- # 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.
284
- # to_unicode(str, 'utf-7', 'all')
285
- #
286
- # 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'.
287
- # to_unicode(str, 'utf-8', 'overlong', 2)
288
- #
289
- # 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.
290
- # to_unicode(str, 'utf-8', 'invalid', 2)
291
- #
292
- # utf-7 defaults to 'normal' utf-7 encoding
293
- # utf-8 defaults to 2 byte 'normal' encoding
294
- #
295
- def self.to_unicode(str='', type = 'utf-16le', mode = '', size = '')
296
- return '' if not str
297
- case type
298
- when 'utf-16le'
299
- return str.unpack('C*').pack('v*')
300
- when 'utf-16be'
301
- return str.unpack('C*').pack('n*')
302
- when 'utf-32le'
303
- return str.unpack('C*').pack('V*')
304
- when 'utf-32be'
305
- return str.unpack('C*').pack('N*')
306
- when 'utf-7'
307
- case mode
308
- when 'all'
309
- return str.gsub(/./){ |a|
310
- out = ''
311
- if 'a' != '+'
312
- out = encode_base64(to_unicode(a, 'utf-16be')).gsub(/[=\r\n]/, '')
313
- end
314
- '+' + out + '-'
315
- }
316
- else
317
- return str.gsub(/[^\n\r\t\ A-Za-z0-9\'\(\),-.\/\:\?]/){ |a|
318
- out = ''
319
- if a != '+'
320
- out = encode_base64(to_unicode(a, 'utf-16be')).gsub(/[=\r\n]/, '')
321
- end
322
- '+' + out + '-'
323
- }
324
- end
325
- when 'utf-8'
326
- if size == ''
327
- size = 2
328
- end
329
-
330
- if size >= 2 and size <= 7
331
- string = ''
332
- str.each_byte { |a|
333
- if (a < 21 || a > 0x7f) || mode != ''
334
- # ugh. turn a single byte into the binary representation of it, in array form
335
- bin = [a].pack('C').unpack('B8')[0].split(//)
336
-
337
- # even more ugh.
338
- bin.collect!{|a_| a_.to_i}
339
-
340
- out = Array.new(8 * size, 0)
341
-
342
- 0.upto(size - 1) { |i|
343
- out[i] = 1
344
- out[i * 8] = 1
345
- }
346
-
347
- i = 0
348
- byte = 0
349
- bin.reverse.each { |bit|
350
- if i < 6
351
- mod = (((size * 8) - 1) - byte * 8) - i
352
- out[mod] = bit
353
- else
354
- byte = byte + 1
355
- i = 0
356
- redo
357
- end
358
- i = i + 1
359
- }
360
-
361
- if mode != ''
362
- case mode
363
- when 'overlong'
364
- # do nothing, since we already handle this as above...
365
- when 'invalid'
366
- done = 0
367
- while done == 0
368
- # the ghetto...
369
- bits = [7, 8, 15, 16, 23, 24, 31, 32, 41]
370
- bits.each { |bit|
371
- bit = (size * 8) - bit
372
- if bit > 1
373
- set = rand(2)
374
- if out[bit] != set
375
- out[bit] = set
376
- done = 1
377
- end
378
- end
379
- }
380
- end
381
- else
382
- raise TypeError, 'Invalid mode. Only "overlong" and "invalid" are acceptable modes for utf-8'
383
- end
384
- end
385
- string << [out.join('')].pack('B*')
386
- else
387
- string << [a].pack('C')
388
- end
389
- }
390
- return string
391
- else
392
- raise TypeError, 'invalid utf-8 size'
393
- end
394
- when 'uhwtfms' # suggested name from HD :P
395
- load_codepage()
396
-
397
- string = ''
398
- # overloading mode as codepage
399
- if mode == ''
400
- mode = 1252 # ANSI - Latan 1, default for US installs of MS products
401
- else
402
- mode = mode.to_i
403
- end
404
- if @@codepage_map_cache[mode].nil?
405
- raise TypeError, "Invalid codepage #{mode}"
406
- end
407
- str.each_byte {|byte|
408
- char = [byte].pack('C*')
409
- possible = @@codepage_map_cache[mode]['data'][char]
410
- if possible.nil?
411
- raise TypeError, "codepage #{mode} does not provide an encoding for 0x#{char.unpack('H*')[0]}"
412
- end
413
- string << possible[ rand(possible.length) ]
414
- }
415
- return string
416
- when 'uhwtfms-half' # suggested name from HD :P
417
- load_codepage()
418
- string = ''
419
- # overloading mode as codepage
420
- if mode == ''
421
- mode = 1252 # ANSI - Latan 1, default for US installs of MS products
422
- else
423
- mode = mode.to_i
424
- end
425
- if mode != 1252
426
- raise TypeError, "Invalid codepage #{mode}, only 1252 supported for uhwtfms_half"
427
- end
428
- str.each_byte {|byte|
429
- if ((byte >= 33 && byte <= 63) || (byte >= 96 && byte <= 126))
430
- string << "\xFF" + [byte ^ 32].pack('C')
431
- elsif (byte >= 64 && byte <= 95)
432
- string << "\xFF" + [byte ^ 96].pack('C')
433
- else
434
- char = [byte].pack('C')
435
- possible = @@codepage_map_cache[mode]['data'][char]
436
- if possible.nil?
437
- raise TypeError, "codepage #{mode} does not provide an encoding for 0x#{char.unpack('H*')[0]}"
438
- end
439
- string << possible[ rand(possible.length) ]
440
- end
441
- }
442
- return string
443
- else
444
- raise TypeError, 'invalid utf type'
445
- end
446
- end
447
-
448
- #
449
- # Converts a unicode string to standard ASCII text.
450
- #
451
- def self.to_ascii(str='', type = 'utf-16le', mode = '', size = '')
452
- return '' if not str
453
- case type
454
- when 'utf-16le'
455
- return str.unpack('v*').pack('C*')
456
- when 'utf-16be'
457
- return str.unpack('n*').pack('C*')
458
- when 'utf-32le'
459
- return str.unpack('V*').pack('C*')
460
- when 'utf-32be'
461
- return str.unpack('N*').pack('C*')
462
- when 'utf-7'
463
- raise TypeError, 'invalid utf type, not yet implemented'
464
- when 'utf-8'
465
- raise TypeError, 'invalid utf type, not yet implemented'
466
- when 'uhwtfms' # suggested name from HD :P
467
- raise TypeError, 'invalid utf type, not yet implemented'
468
- when 'uhwtfms-half' # suggested name from HD :P
469
- raise TypeError, 'invalid utf type, not yet implemented'
470
- else
471
- raise TypeError, 'invalid utf type'
472
- end
473
- end
474
-
475
- #
476
- # Encode a string in a manor useful for HTTP URIs and URI Parameters.
477
- #
478
- def self.uri_encode(str, mode = 'hex-normal')
479
- return "" if str == nil
480
-
481
- return str if mode == 'none' # fast track no encoding
482
-
483
- all = /[^\/\\]+/
484
- normal = /[^a-zA-Z0-9\/\\\.\-]+/
485
- normal_na = /[a-zA-Z0-9\/\\\.\-]/
486
-
487
- case mode
488
- when 'hex-normal'
489
- return str.gsub(normal) { |s| Rex::Text.to_hex(s, '%') }
490
- when 'hex-all'
491
- return str.gsub(all) { |s| Rex::Text.to_hex(s, '%') }
492
- when 'hex-random'
493
- res = ''
494
- str.each_byte do |c|
495
- b = c.chr
496
- res << ((rand(2) == 0) ?
497
- b.gsub(all) { |s| Rex::Text.to_hex(s, '%') } :
498
- b.gsub(normal){ |s| Rex::Text.to_hex(s, '%') } )
499
- end
500
- return res
501
- when 'u-normal'
502
- return str.gsub(normal) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) }
503
- when 'u-all'
504
- return str.gsub(all) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) }
505
- when 'u-random'
506
- res = ''
507
- str.each_byte do |c|
508
- b = c.chr
509
- res << ((rand(2) == 0) ?
510
- b.gsub(all) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) } :
511
- b.gsub(normal){ |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) } )
512
- end
513
- return res
514
- when 'u-half'
515
- return str.gsub(all) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms-half'), '%u', 2) }
516
- else
517
- raise TypeError, 'invalid mode'
518
- end
519
- end
520
-
521
- #
522
- # Encode a string in a manner useful for HTTP URIs and URI Parameters.
523
- #
524
- def self.html_encode(str, mode = 'hex')
525
- case mode
526
- when 'hex'
527
- return str.unpack('C*').collect{ |i| "&#x" + ("%.2x" % i) + ";"}.join
528
- when 'int'
529
- return str.unpack('C*').collect{ |i| "&#" + i.to_s + ";"}.join
530
- when 'int-wide'
531
- return str.unpack('C*').collect{ |i| "&#" + ("0" * (7 - i.to_s.length)) + i.to_s + ";" }.join
532
- else
533
- raise TypeError, 'invalid mode'
534
- end
535
- end
536
-
537
- #
538
- # Encode an ASCII string so it's safe for XML. It's a wrapper for to_hex_ascii.
539
- #
540
- def self.xml_char_encode(str)
541
- self.to_hex_ascii(str, "&#x", 1, ";")
542
- end
543
-
544
- #
545
- # Decode a URI encoded string
546
- #
547
- def self.uri_decode(str)
548
- str.gsub(/(%[a-z0-9]{2})/i){ |c| [c[1,2]].pack("H*") }
549
- end
550
-
551
- #
552
- # Converts a string to random case
553
- #
554
- def self.to_rand_case(str)
555
- buf = str.dup
556
- 0.upto(str.length) do |i|
557
- buf[i,1] = rand(2) == 0 ? str[i,1].upcase : str[i,1].downcase
558
- end
559
- return buf
560
- end
561
-
562
- #
563
- # Takes a string, and returns an array of all mixed case versions.
564
- #
565
- # Example:
566
- #
567
- # >> Rex::Text.to_mixed_case_array "abc1"
568
- # => ["abc1", "abC1", "aBc1", "aBC1", "Abc1", "AbC1", "ABc1", "ABC1"]
569
- #
570
- def self.to_mixed_case_array(str)
571
- letters = []
572
- str.scan(/./).each { |l| letters << [l.downcase, l.upcase] }
573
- coords = []
574
- (1 << str.size).times { |i| coords << ("%0#{str.size}b" % i) }
575
- mixed = []
576
- coords.each do |coord|
577
- c = coord.scan(/./).map {|x| x.to_i}
578
- this_str = ""
579
- c.each_with_index { |d,i| this_str << letters[i][d] }
580
- mixed << this_str
581
- end
582
- return mixed.uniq
583
- end
584
-
585
- #
586
- # Converts a string a nicely formatted hex dump
587
- #
588
- def self.to_hex_dump(str, width=16)
589
- buf = ''
590
- idx = 0
591
- cnt = 0
592
- snl = false
593
- lst = 0
594
-
595
- while (idx < str.length)
596
-
597
- chunk = str[idx, width]
598
- line = chunk.unpack("H*")[0].scan(/../).join(" ")
599
- buf << line
600
-
601
- if (lst == 0)
602
- lst = line.length
603
- buf << " " * 4
604
- else
605
- buf << " " * ((lst - line.length) + 4).abs
606
- end
607
-
608
- chunk.unpack("C*").each do |c|
609
- if (c > 0x1f and c < 0x7f)
610
- buf << c.chr
611
- else
612
- buf << "."
613
- end
614
- end
615
-
616
- buf << "\n"
617
-
618
- idx += width
619
- end
620
-
621
- buf << "\n"
622
- end
623
-
624
- #
625
- # Converts a hex string to a raw string
626
- #
627
- def self.hex_to_raw(str)
628
- [ str.downcase.gsub(/'/,'').gsub(/\\?x([a-f0-9][a-f0-9])/, '\1') ].pack("H*")
629
- end
630
-
631
- #
632
- # Turn non-printable chars into hex representations, leaving others alone
633
- #
634
- # If +whitespace+ is true, converts whitespace (0x20, 0x09, etc) to hex as
635
- # well.
636
- #
637
- def self.ascii_safe_hex(str, whitespace=false)
638
- if whitespace
639
- str.gsub(/([\x00-\x20\x80-\xFF])/){ |x| "\\x%.2x" % x.unpack("C*")[0] }
640
- else
641
- str.gsub(/([\x00-\x08\x0b\x0c\x0e-\x1f\x80-\xFF])/n){ |x| "\\x%.2x" % x.unpack("C*")[0]}
642
- end
643
- end
644
-
645
- #
646
- # Wraps text at a given column using a supplied indention
647
- #
648
- def self.wordwrap(str, indent = 0, col = DefaultWrap, append = '', prepend = '')
649
- return str.gsub(/.{1,#{col - indent}}(?:\s|\Z)/){
650
- ( (" " * indent) + prepend + $& + append + 5.chr).gsub(/\n\005/,"\n").gsub(/\005/,"\n")}
651
- end
652
-
653
- #
654
- # Converts a string to a hex version with wrapping support
655
- #
656
- def self.hexify(str, col = DefaultWrap, line_start = '', line_end = '', buf_start = '', buf_end = '')
657
- output = buf_start
658
- cur = 0
659
- count = 0
660
- new_line = true
661
-
662
- # Go through each byte in the string
663
- str.each_byte { |byte|
664
- count += 1
665
- append = ''
666
-
667
- # If this is a new line, prepend with the
668
- # line start text
669
- if (new_line == true)
670
- append << line_start
671
- new_line = false
672
- end
673
-
674
- # Append the hexified version of the byte
675
- append << sprintf("\\x%.2x", byte)
676
- cur += append.length
677
-
678
- # If we're about to hit the column or have gone past it,
679
- # time to finish up this line
680
- if ((cur + line_end.length >= col) or (cur + buf_end.length >= col))
681
- new_line = true
682
- cur = 0
683
-
684
- # If this is the last byte, use the buf_end instead of
685
- # line_end
686
- if (count == str.length)
687
- append << buf_end + "\n"
688
- else
689
- append << line_end + "\n"
690
- end
691
- end
692
-
693
- output << append
694
- }
695
-
696
- # If we were in the middle of a line, finish the buffer at this point
697
- if (new_line == false)
698
- output << buf_end + "\n"
699
- end
700
-
701
- return output
702
- end
703
-
704
- ##
705
- #
706
- # Transforms
707
- #
708
- ##
709
-
710
- #
711
- # Base32 code
712
- #
713
-
714
- # Based on --> https://github.com/stesla/base32
715
-
716
- # Copyright (c) 2007-2011 Samuel Tesla
717
-
718
- # Permission is hereby granted, free of charge, to any person obtaining a copy
719
- # of this software and associated documentation files (the "Software"), to deal
720
- # in the Software without restriction, including without limitation the rights
721
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
722
- # copies of the Software, and to permit persons to whom the Software is
723
- # furnished to do so, subject to the following conditions:
724
-
725
- # The above copyright notice and this permission notice shall be included in
726
- # all copies or substantial portions of the Software.
727
-
728
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
729
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
730
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
731
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
732
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
733
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
734
- # THE SOFTWARE.
735
-
736
-
737
- #
738
- # Base32 encoder
739
- #
740
- def self.b32encode(bytes_in)
741
- n = (bytes_in.length * 8.0 / 5.0).ceil
742
- p = n < 8 ? 5 - (bytes_in.length * 8) % 5 : 0
743
- c = bytes_in.inject(0) {|m,o| (m << 8) + o} << p
744
- [(0..n-1).to_a.reverse.collect {|i| Base32[(c >> i * 5) & 0x1f].chr},
745
- ("=" * (8-n))]
746
- end
747
-
748
- def self.encode_base32(str)
749
- bytes = str.bytes
750
- result = ''
751
- size= 5
752
- while bytes.any? do
753
- bytes.each_slice(size) do |a|
754
- bytes_out = b32encode(a).flatten.join
755
- result << bytes_out
756
- bytes = bytes.drop(size)
757
- end
758
- end
759
- return result
760
- end
761
-
762
- #
763
- # Base32 decoder
764
- #
765
- def self.b32decode(bytes_in)
766
- bytes = bytes_in.take_while {|c| c != 61} # strip padding
767
- n = (bytes.length * 5.0 / 8.0).floor
768
- p = bytes.length < 8 ? 5 - (n * 8) % 5 : 0
769
- c = bytes.inject(0) {|m,o| (m << 5) + Base32.index(o.chr)} >> p
770
- (0..n-1).to_a.reverse.collect {|i| ((c >> i * 8) & 0xff).chr}
771
- end
772
-
773
- def self.decode_base32(str)
774
- bytes = str.bytes
775
- result = ''
776
- size= 8
777
- while bytes.any? do
778
- bytes.each_slice(size) do |a|
779
- bytes_out = b32decode(a).flatten.join
780
- result << bytes_out
781
- bytes = bytes.drop(size)
782
- end
783
- end
784
- return result
785
- end
786
-
787
- #
788
- # Base64 encoder
789
- #
790
- def self.encode_base64(str, delim='')
791
- [str.to_s].pack("m").gsub(/\s+/, delim)
792
- end
793
-
794
- #
795
- # Base64 decoder
796
- #
797
- def self.decode_base64(str)
798
- str.to_s.unpack("m")[0]
799
- end
800
-
801
- #
802
- # Raw MD5 digest of the supplied string
803
- #
804
- def self.md5_raw(str)
805
- Digest::MD5.digest(str)
806
- end
807
-
808
- #
809
- # Hexidecimal MD5 digest of the supplied string
810
- #
811
- def self.md5(str)
812
- Digest::MD5.hexdigest(str)
813
- end
814
-
815
- #
816
- # Convert hex-encoded characters to literals.
817
- # Example: "AA\\x42CC" becomes "AABCC"
818
- #
819
- def self.dehex(str)
820
- return str unless str.respond_to? :match
821
- return str unless str.respond_to? :gsub
822
- regex = /\x5cx[0-9a-f]{2}/mi
823
- if str.match(regex)
824
- str.gsub(regex) { |x| x[2,2].to_i(16).chr }
825
- else
826
- str
827
- end
828
- end
829
-
830
- #
831
- # Convert and replace hex-encoded characters to literals.
832
- #
833
- def self.dehex!(str)
834
- return str unless str.respond_to? :match
835
- return str unless str.respond_to? :gsub
836
- regex = /\x5cx[0-9a-f]{2}/mi
837
- str.gsub!(regex) { |x| x[2,2].to_i(16).chr }
838
- end
839
-
840
- ##
841
- #
842
- # Generators
843
- #
844
- ##
845
-
846
-
847
- # Generates a random character.
848
- def self.rand_char(bad, chars = AllChars)
849
- rand_text(1, bad, chars)
850
- end
851
-
852
- # Base text generator method
853
- def self.rand_base(len, bad, *foo)
854
- cset = (foo.join.unpack("C*") - bad.to_s.unpack("C*")).uniq
855
- return "" if cset.length == 0
856
- outp = []
857
- len.times { outp << cset[rand(cset.length)] }
858
- outp.pack("C*")
859
- end
860
-
861
- # Generate random bytes of data
862
- def self.rand_text(len, bad='', chars = AllChars)
863
- foo = chars.split('')
864
- rand_base(len, bad, *foo)
865
- end
866
-
867
- # Generate random bytes of alpha data
868
- def self.rand_text_alpha(len, bad='')
869
- foo = []
870
- foo += ('A' .. 'Z').to_a
871
- foo += ('a' .. 'z').to_a
872
- rand_base(len, bad, *foo )
873
- end
874
-
875
- # Generate random bytes of lowercase alpha data
876
- def self.rand_text_alpha_lower(len, bad='')
877
- rand_base(len, bad, *('a' .. 'z').to_a)
878
- end
879
-
880
- # Generate random bytes of uppercase alpha data
881
- def self.rand_text_alpha_upper(len, bad='')
882
- rand_base(len, bad, *('A' .. 'Z').to_a)
883
- end
884
-
885
- # Generate random bytes of alphanumeric data
886
- def self.rand_text_alphanumeric(len, bad='')
887
- foo = []
888
- foo += ('A' .. 'Z').to_a
889
- foo += ('a' .. 'z').to_a
890
- foo += ('0' .. '9').to_a
891
- rand_base(len, bad, *foo )
892
- end
893
-
894
- # Generate random bytes of alphanumeric hex.
895
- def self.rand_text_hex(len, bad='')
896
- foo = []
897
- foo += ('0' .. '9').to_a
898
- foo += ('a' .. 'f').to_a
899
- rand_base(len, bad, *foo)
900
- end
901
-
902
- # Generate random bytes of numeric data
903
- def self.rand_text_numeric(len, bad='')
904
- foo = ('0' .. '9').to_a
905
- rand_base(len, bad, *foo )
906
- end
907
-
908
- # Generate random bytes of english-like data
909
- def self.rand_text_english(len, bad='')
910
- foo = []
911
- foo += (0x21 .. 0x7e).map{ |c| c.chr }
912
- rand_base(len, bad, *foo )
913
- end
914
-
915
- # Generate random bytes of high ascii data
916
- def self.rand_text_highascii(len, bad='')
917
- foo = []
918
- foo += (0x80 .. 0xff).map{ |c| c.chr }
919
- rand_base(len, bad, *foo )
920
- end
921
-
922
- # Generate a random GUID, of the form {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
923
- def self.rand_guid
924
- "{#{[8,4,4,4,12].map {|a| rand_text_hex(a) }.join("-")}}"
925
- end
926
-
927
- #
928
- # Creates a pattern that can be used for offset calculation purposes. This
929
- # routine is capable of generating patterns using a supplied set and a
930
- # supplied number of identifiable characters (slots). The supplied sets
931
- # should not contain any duplicate characters or the logic will fail.
932
- #
933
- def self.pattern_create(length, sets = nil)
934
- buf = ''
935
- idx = 0
936
- offsets = []
937
-
938
- # Make sure there's something in sets even if we were given an explicit nil
939
- sets ||= [ UpperAlpha, LowerAlpha, Numerals ]
940
-
941
- # Return stupid uses
942
- return "" if length.to_i < 1
943
- return sets[0][0].chr * length if sets.size == 1 and sets[0].size == 1
944
-
945
- sets.length.times { offsets << 0 }
946
-
947
- until buf.length >= length
948
- begin
949
- buf << converge_sets(sets, 0, offsets, length)
950
- end
951
- end
952
-
953
- # Maximum permutations reached, but we need more data
954
- if (buf.length < length)
955
- buf = buf * (length / buf.length.to_f).ceil
956
- end
957
-
958
- buf[0,length]
959
- end
960
-
961
- # Step through an arbitrary number of sets of bytes to build up a findable pattern.
962
- # This is mostly useful for experimentially determining offset lengths into memory
963
- # structures. Note that the supplied sets should never contain duplicate bytes, or
964
- # else it can become impossible to measure the offset accurately.
965
- def self.patt2(len, sets = nil)
966
- buf = ""
967
- counter = []
968
- sets ||= [ UpperAlpha, LowerAlpha, Numerals ]
969
- len ||= len.to_i
970
- return "" if len.zero?
971
-
972
- sets = sets.map {|a| a.split(//)}
973
- sets.size.times { counter << 0}
974
- 0.upto(len-1) do |i|
975
- setnum = i % sets.size
976
-
977
- #puts counter.inspect
978
- end
979
-
980
- return buf
981
- end
982
-
983
- #
984
- # Calculate the offset to a pattern
985
- #
986
- def self.pattern_offset(pattern, value, start=0)
987
- if (value.kind_of?(String))
988
- pattern.index(value, start)
989
- elsif (value.kind_of?(Fixnum) or value.kind_of?(Bignum))
990
- pattern.index([ value ].pack('V'), start)
991
- else
992
- raise ::ArgumentError, "Invalid class for value: #{value.class}"
993
- end
994
- end
995
-
996
- #
997
- # Compresses a string, eliminating all superfluous whitespace before and
998
- # after lines and eliminating all lines.
999
- #
1000
- def self.compress(str)
1001
- str.gsub(/\n/m, ' ').gsub(/\s+/, ' ').gsub(/^\s+/, '').gsub(/\s+$/, '')
1002
- end
1003
-
1004
- #
1005
- # Randomize the whitespace in a string
1006
- #
1007
- def self.randomize_space(str)
1008
- str.gsub(/\s+/) { |s|
1009
- len = rand(50)+2
1010
- set = "\x09\x20\x0d\x0a"
1011
- buf = ''
1012
- while (buf.length < len)
1013
- buf << set[rand(set.length),1]
1014
- end
1015
-
1016
- buf
1017
- }
1018
- end
1019
-
1020
- # Returns true if zlib can be used.
1021
- def self.zlib_present?
1022
- begin
1023
- temp = Zlib
1024
- return true
1025
- rescue
1026
- return false
1027
- end
1028
- end
1029
-
1030
- # backwards compat for just a bit...
1031
- def self.gzip_present?
1032
- self.zlib_present?
1033
- end
1034
-
1035
- #
1036
- # Compresses a string using zlib
1037
- #
1038
- def self.zlib_deflate(str, level = Zlib::BEST_COMPRESSION)
1039
- if self.zlib_present?
1040
- z = Zlib::Deflate.new(level)
1041
- dst = z.deflate(str, Zlib::FINISH)
1042
- z.close
1043
- return dst
1044
- else
1045
- raise RuntimeError, "Gzip support is not present."
1046
- end
1047
- end
1048
-
1049
- #
1050
- # Uncompresses a string using zlib
1051
- #
1052
- def self.zlib_inflate(str)
1053
- if(self.zlib_present?)
1054
- zstream = Zlib::Inflate.new
1055
- buf = zstream.inflate(str)
1056
- zstream.finish
1057
- zstream.close
1058
- return buf
1059
- else
1060
- raise RuntimeError, "Gzip support is not present."
1061
- end
1062
- end
1063
-
1064
- #
1065
- # Compresses a string using gzip
1066
- #
1067
- def self.gzip(str, level = 9)
1068
- raise RuntimeError, "Gzip support is not present." if (!zlib_present?)
1069
- raise RuntimeError, "Invalid gzip compression level" if (level < 1 or level > 9)
1070
-
1071
- s = ""
1072
- s.force_encoding('ASCII-8BIT') if s.respond_to?(:encoding)
1073
- gz = Zlib::GzipWriter.new(StringIO.new(s, 'wb'), level)
1074
- gz << str
1075
- gz.close
1076
- return s
1077
- end
1078
-
1079
- #
1080
- # Uncompresses a string using gzip
1081
- #
1082
- def self.ungzip(str)
1083
- raise RuntimeError, "Gzip support is not present." if (!zlib_present?)
1084
-
1085
- s = ""
1086
- s.force_encoding('ASCII-8BIT') if s.respond_to?(:encoding)
1087
- gz = Zlib::GzipReader.new(StringIO.new(str, 'rb'))
1088
- s << gz.read
1089
- gz.close
1090
- return s
1091
- end
1092
-
1093
- #
1094
- # Return the index of the first badchar in data, otherwise return
1095
- # nil if there wasn't any badchar occurences.
1096
- #
1097
- def self.badchar_index(data, badchars = '')
1098
- badchars.unpack("C*").each { |badchar|
1099
- pos = data.index(badchar.chr)
1100
- return pos if pos
1101
- }
1102
- return nil
1103
- end
1104
-
1105
- #
1106
- # This method removes bad characters from a string.
1107
- #
1108
- def self.remove_badchars(data, badchars = '')
1109
- data.delete(badchars)
1110
- end
1111
-
1112
- #
1113
- # This method returns all chars but the supplied set
1114
- #
1115
- def self.charset_exclude(keepers)
1116
- [*(0..255)].pack('C*').delete(keepers)
1117
- end
1118
-
1119
- #
1120
- # Shuffles a byte stream
1121
- #
1122
- def self.shuffle_s(str)
1123
- shuffle_a(str.unpack("C*")).pack("C*")
1124
- end
1125
-
1126
- #
1127
- # Performs a Fisher-Yates shuffle on an array
1128
- #
1129
- def self.shuffle_a(arr)
1130
- len = arr.length
1131
- max = len - 1
1132
- cyc = [* (0..max) ]
1133
- for d in cyc
1134
- e = rand(d+1)
1135
- next if e == d
1136
- f = arr[d];
1137
- g = arr[e];
1138
- arr[d] = g;
1139
- arr[e] = f;
1140
- end
1141
- return arr
1142
- end
1143
-
1144
- # Permute the case of a word
1145
- def self.permute_case(word, idx=0)
1146
- res = []
1147
-
1148
- if( (UpperAlpha+LowerAlpha).index(word[idx,1]))
1149
-
1150
- word_ucase = word.dup
1151
- word_ucase[idx, 1] = word[idx, 1].upcase
1152
-
1153
- word_lcase = word.dup
1154
- word_lcase[idx, 1] = word[idx, 1].downcase
1155
-
1156
- if (idx == word.length)
1157
- return [word]
1158
- else
1159
- res << permute_case(word_ucase, idx+1)
1160
- res << permute_case(word_lcase, idx+1)
1161
- end
1162
- else
1163
- res << permute_case(word, idx+1)
1164
- end
1165
-
1166
- res.flatten
1167
- end
1168
-
1169
- # Generate a random hostname
1170
- def self.rand_hostname
1171
- host = []
1172
- (rand(5) + 1).times {
1173
- host.push(Rex::Text.rand_text_alphanumeric(rand(10) + 1))
1174
- }
1175
- d = ['com', 'net', 'org', 'gov']
1176
- host.push(d[rand(d.size)])
1177
- host.join('.').downcase
1178
- end
1179
-
1180
- # Generate a state
1181
- def self.rand_state()
1182
- States[rand(States.size)]
1183
- end
1184
-
1185
-
1186
- #
1187
- # Calculate the ROR13 hash of a given string
1188
- #
1189
- def self.ror13_hash(name)
1190
- hash = 0
1191
- name.unpack("C*").each {|c| hash = ror(hash, 13); hash += c }
1192
- hash
1193
- end
1194
-
1195
- #
1196
- # Rotate a 32-bit value to the right by cnt bits
1197
- #
1198
- def self.ror(val, cnt)
1199
- bits = [val].pack("N").unpack("B32")[0].split(//)
1200
- 1.upto(cnt) do |c|
1201
- bits.unshift( bits.pop )
1202
- end
1203
- [bits.join].pack("B32").unpack("N")[0]
1204
- end
1205
-
1206
- #
1207
- # Rotate a 32-bit value to the left by cnt bits
1208
- #
1209
- def self.rol(val, cnt)
1210
- bits = [val].pack("N").unpack("B32")[0].split(//)
1211
- 1.upto(cnt) do |c|
1212
- bits.push( bits.shift )
1213
- end
1214
- [bits.join].pack("B32").unpack("N")[0]
1215
- end
1216
-
1217
- #
1218
- # Split a string by n charachter into an array
1219
- #
1220
- def self.split_to_a(str, n)
1221
- if n > 0
1222
- s = str.dup
1223
- until s.empty?
1224
- (ret ||= []).push s.slice!(0, n)
1225
- end
1226
- else
1227
- ret = str
1228
- end
1229
- ret
1230
- end
1231
-
1232
- #
1233
- #Pack a value as 64 bit litle endian; does not exist for Array.pack
1234
- #
1235
- def self.pack_int64le(val)
1236
- [val & 0x00000000ffffffff, val >> 32].pack("V2")
1237
- end
1238
-
1239
-
1240
- #
1241
- # A custom unicode filter for dealing with multi-byte strings on a 8-bit console
1242
- # Punycode would have been more "standard", but it requires valid Unicode chars
1243
- #
1244
- def self.unicode_filter_encode(str)
1245
- if (str.to_s.unpack("C*") & ( LowAscii + HighAscii + "\x7f" ).unpack("C*")).length > 0
1246
- str = "$U$" + str.unpack("C*").select{|c| c < 0x7f and c > 0x1f and c != 0x2d}.pack("C*") + "-0x" + str.unpack("H*")[0]
1247
- else
1248
- str
1249
- end
1250
- end
1251
-
1252
- def self.unicode_filter_decode(str)
1253
- str.to_s.gsub( /\$U\$([\x20-\x2c\x2e-\x7E]*)\-0x([A-Fa-f0-9]+)/ ){|m| [$2].pack("H*") }
1254
- end
27
+ @@codepage_map_cache = nil
28
+
29
+ ##
30
+ #
31
+ # Constants
32
+ #
33
+ ##
34
+
35
+ TLDs = ['com', 'net', 'org', 'gov', 'biz', 'edu']
36
+ States = ["AK", "AL", "AR", "AZ", "CA", "CO", "CT", "DE", "FL", "GA", "HI",
37
+ "IA", "ID", "IL", "IN", "KS", "KY", "LA", "MA", "MD", "ME", "MI", "MN",
38
+ "MO", "MS", "MT", "NC", "ND", "NE", "NH", "NJ", "NM", "NV", "NY", "OH",
39
+ "OK", "OR", "PA", "RI", "SC", "SD", "TN", "TX", "UT", "VA", "VT", "WA",
40
+ "WI", "WV", "WY"]
41
+ UpperAlpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
42
+ LowerAlpha = "abcdefghijklmnopqrstuvwxyz"
43
+ Numerals = "0123456789"
44
+ Base32 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
45
+ Alpha = UpperAlpha + LowerAlpha
46
+ AlphaNumeric = Alpha + Numerals
47
+ HighAscii = [*(0x80 .. 0xff)].pack("C*")
48
+ LowAscii = [*(0x00 .. 0x1f)].pack("C*")
49
+ DefaultWrap = 60
50
+ AllChars = [*(0x00 .. 0xff)].pack("C*")
51
+ Punctuation = ( [*(0x21 .. 0x2f)] + [*(0x3a .. 0x3F)] + [*(0x5b .. 0x60)] + [*(0x7b .. 0x7e)] ).flatten.pack("C*")
52
+
53
+ DefaultPatternSets = [ Rex::Text::UpperAlpha, Rex::Text::LowerAlpha, Rex::Text::Numerals ]
54
+
55
+ # In case Iconv isn't loaded
56
+ Iconv_EBCDIC = [
57
+ "\x00", "\x01", "\x02", "\x03", "7", "-", ".", "/", "\x16", "\x05",
58
+ "%", "\v", "\f", "\r", "\x0E", "\x0F", "\x10", "\x11", "\x12", "\x13",
59
+ "<", "=", "2", "&", "\x18", "\x19", "?", "'", "\x1C", "\x1D", "\x1E",
60
+ "\x1F", "@", "Z", "\x7F", "{", "[", "l", "P", "}", "M", "]", "\\",
61
+ "N", "k", "`", "K", "a", "\xF0", "\xF1", "\xF2", "\xF3", "\xF4",
62
+ "\xF5", "\xF6", "\xF7", "\xF8", "\xF9", "z", "^", "L", "~", "n", "o",
63
+ "|", "\xC1", "\xC2", "\xC3", "\xC4", "\xC5", "\xC6", "\xC7", "\xC8",
64
+ "\xC9", "\xD1", "\xD2", "\xD3", "\xD4", "\xD5", "\xD6", "\xD7",
65
+ "\xD8", "\xD9", "\xE2", "\xE3", "\xE4", "\xE5", "\xE6", "\xE7",
66
+ "\xE8", "\xE9", nil, "\xE0", nil, nil, "m", "y", "\x81", "\x82",
67
+ "\x83", "\x84", "\x85", "\x86", "\x87", "\x88", "\x89", "\x91",
68
+ "\x92", "\x93", "\x94", "\x95", "\x96", "\x97", "\x98", "\x99",
69
+ "\xA2", "\xA3", "\xA4", "\xA5", "\xA6", "\xA7", "\xA8", "\xA9",
70
+ "\xC0", "O", "\xD0", "\xA1", "\a", nil, nil, nil, nil, nil, nil,
71
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
72
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
73
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
74
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
75
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
76
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
77
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
78
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
79
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
80
+ nil, nil, nil, nil, nil
81
+ ]
82
+
83
+ Iconv_ASCII = [
84
+ "\x00", "\x01", "\x02", "\x03", "\x04", "\x05", "\x06", "\a", "\b",
85
+ "\t", "\n", "\v", "\f", "\r", "\x0E", "\x0F", "\x10", "\x11", "\x12",
86
+ "\x13", "\x14", "\x15", "\x16", "\x17", "\x18", "\x19", "\x1A", "\e",
87
+ "\x1C", "\x1D", "\x1E", "\x1F", " ", "!", "\"", "#", "$", "%", "&",
88
+ "'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "1", "2", "3", "4",
89
+ "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@", "A", "B",
90
+ "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P",
91
+ "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", nil, "\\", nil,
92
+ nil, "_", "`", "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k",
93
+ "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y",
94
+ "z", "{", "|", "}", "~", "\x7F", nil, nil, nil, nil, nil, nil, nil,
95
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
96
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
97
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
98
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
99
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
100
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
101
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
102
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil,
103
+ nil, nil, nil, nil, nil, nil, nil, nil, nil
104
+ ]
105
+
106
+ #
107
+ # Most 100 common surnames, male/female names in the U.S. (http://names.mongabay.com/)
108
+ #
109
+
110
+ Surnames = [
111
+ "adams", "alexander", "allen", "anderson", "bailey", "baker", "barnes",
112
+ "bell", "bennett", "brooks", "brown", "bryant", "butler", "campbell",
113
+ "carter", "clark", "coleman", "collins", "cook", "cooper", "cox",
114
+ "davis", "diaz", "edwards", "evans", "flores", "foster", "garcia",
115
+ "gonzales", "gonzalez", "gray", "green", "griffin", "hall", "harris",
116
+ "hayes", "henderson", "hernandez", "hill", "howard", "hughes", "jackson",
117
+ "james", "jenkins", "johnson", "jones", "kelly", "king", "lee", "lewis",
118
+ "long", "lopez", "martin", "martinez", "miller", "mitchell", "moore",
119
+ "morgan", "morris", "murphy", "nelson", "parker", "patterson", "perez",
120
+ "perry", "peterson", "phillips", "powell", "price", "ramirez", "reed",
121
+ "richardson", "rivera", "roberts", "robinson", "rodriguez", "rogers",
122
+ "ross", "russell", "sanchez", "sanders", "scott", "simmons", "smith",
123
+ "stewart", "taylor", "thomas", "thompson", "torres", "turner", "walker",
124
+ "ward", "washington", "watson", "white", "williams", "wilson", "wood",
125
+ "wright", "young"
126
+ ]
127
+
128
+ Names_Male = [
129
+ "aaron", "adam", "alan", "albert", "andrew", "anthony", "antonio",
130
+ "arthur", "benjamin", "billy", "bobby", "brandon", "brian", "bruce",
131
+ "carl", "carlos", "charles", "chris", "christopher", "clarence", "craig",
132
+ "daniel", "david", "dennis", "donald", "douglas", "earl", "edward",
133
+ "eric", "ernest", "eugene", "frank", "fred", "gary", "george", "gerald",
134
+ "gregory", "harold", "harry", "henry", "howard", "jack", "james", "jason",
135
+ "jeffrey", "jeremy", "jerry", "jesse", "jimmy", "joe", "john", "johnny",
136
+ "jonathan", "jose", "joseph", "joshua", "juan", "justin", "keith",
137
+ "kenneth", "kevin", "larry", "lawrence", "louis", "mark", "martin",
138
+ "matthew", "michael", "nicholas", "patrick", "paul", "peter", "philip",
139
+ "phillip", "ralph", "randy", "raymond", "richard", "robert", "roger",
140
+ "ronald", "roy", "russell", "ryan", "samuel", "scott", "sean", "shawn",
141
+ "stephen", "steve", "steven", "terry", "thomas", "timothy", "todd",
142
+ "victor", "walter", "wayne", "william", "willie"
143
+ ]
144
+
145
+ Names_Female = [
146
+ "alice", "amanda", "amy", "andrea", "angela", "ann", "anna", "anne",
147
+ "annie", "ashley", "barbara", "betty", "beverly", "bonnie", "brenda",
148
+ "carol", "carolyn", "catherine", "cheryl", "christina", "christine",
149
+ "cynthia", "deborah", "debra", "denise", "diana", "diane", "donna",
150
+ "doris", "dorothy", "elizabeth", "emily", "evelyn", "frances", "gloria",
151
+ "heather", "helen", "irene", "jacqueline", "jane", "janet", "janice",
152
+ "jean", "jennifer", "jessica", "joan", "joyce", "judith", "judy", "julia",
153
+ "julie", "karen", "katherine", "kathleen", "kathryn", "kathy", "kelly",
154
+ "kimberly", "laura", "lillian", "linda", "lisa", "lois", "lori", "louise",
155
+ "margaret", "maria", "marie", "marilyn", "martha", "mary", "melissa",
156
+ "michelle", "mildred", "nancy", "nicole", "norma", "pamela", "patricia",
157
+ "paula", "phyllis", "rachel", "rebecca", "robin", "rose", "ruby", "ruth",
158
+ "sandra", "sara", "sarah", "sharon", "shirley", "stephanie", "susan",
159
+ "tammy", "teresa", "theresa", "tina", "virginia", "wanda"
160
+ ]
161
+
162
+ ##
163
+ #
164
+ # Serialization
165
+ #
166
+ ##
167
+
168
+ #
169
+ # Converts a raw string into a ruby buffer
170
+ #
171
+ def self.to_ruby(str, wrap = DefaultWrap, name = "buf")
172
+ return hexify(str, wrap, '"', '" +', "#{name} = \n", '"')
173
+ end
174
+
175
+ #
176
+ # Creates a comma separated list of numbers
177
+ #
178
+ def self.to_num(str, wrap = DefaultWrap)
179
+ code = str.unpack('C*')
180
+ buff = ""
181
+ 0.upto(code.length-1) do |byte|
182
+ if(byte % 15 == 0) and (buff.length > 0)
183
+ buff << "\r\n"
184
+ end
185
+ buff << sprintf('0x%.2x, ', code[byte])
186
+ end
187
+ # strip , at the end
188
+ buff = buff.chomp(', ')
189
+ buff << "\r\n"
190
+ return buff
191
+ end
192
+
193
+ #
194
+ # Creates a comma separated list of dwords
195
+ #
196
+ def self.to_dword(str, wrap = DefaultWrap)
197
+ code = str
198
+ alignnr = str.length % 4
199
+ if (alignnr > 0)
200
+ code << "\x00" * (4 - alignnr)
201
+ end
202
+ codevalues = Array.new
203
+ code.split("").each_slice(4) do |chars4|
204
+ chars4 = chars4.join("")
205
+ dwordvalue = chars4.unpack('*V')
206
+ codevalues.push(dwordvalue[0])
207
+ end
208
+ buff = ""
209
+ 0.upto(codevalues.length-1) do |byte|
210
+ if(byte % 8 == 0) and (buff.length > 0)
211
+ buff << "\r\n"
212
+ end
213
+ buff << sprintf('0x%.8x, ', codevalues[byte])
214
+ end
215
+ # strip , at the end
216
+ buff = buff.chomp(', ')
217
+ buff << "\r\n"
218
+ return buff
219
+ end
220
+
221
+ #
222
+ # Creates a ruby-style comment
223
+ #
224
+ def self.to_ruby_comment(str, wrap = DefaultWrap)
225
+ return wordwrap(str, 0, wrap, '', '# ')
226
+ end
227
+
228
+ #
229
+ # Converts a raw string into a C buffer
230
+ #
231
+ def self.to_c(str, wrap = DefaultWrap, name = "buf")
232
+ return hexify(str, wrap, '"', '"', "unsigned char #{name}[] = \n", '";')
233
+ end
234
+
235
+ def self.to_csharp(str, wrap = DefaultWrap, name = "buf")
236
+ ret = "byte[] #{name} = new byte[#{str.length}] {"
237
+ i = -1;
238
+ while (i += 1) < str.length
239
+ ret << "\n" if i%(wrap/4) == 0
240
+ ret << "0x" << str[i].unpack("H*")[0] << ","
241
+ end
242
+ ret = ret[0..ret.length-2] #cut off last comma
243
+ ret << " };\n"
244
+ end
245
+
246
+ #
247
+ # Creates a c-style comment
248
+ #
249
+ def self.to_c_comment(str, wrap = DefaultWrap)
250
+ return "/*\n" + wordwrap(str, 0, wrap, '', ' * ') + " */\n"
251
+ end
252
+
253
+ #
254
+ # Creates a javascript-style comment
255
+ #
256
+ def self.to_js_comment(str, wrap = DefaultWrap)
257
+ return wordwrap(str, 0, wrap, '', '// ')
258
+ end
259
+
260
+ #
261
+ # Converts a raw string into a perl buffer
262
+ #
263
+ def self.to_perl(str, wrap = DefaultWrap, name = "buf")
264
+ return hexify(str, wrap, '"', '" .', "my $#{name} = \n", '";')
265
+ end
266
+
267
+ #
268
+ # Converts a raw string into a python buffer
269
+ #
270
+ def self.to_python(str, wrap = DefaultWrap, name = "buf")
271
+ return hexify(str, wrap, "#{name} += \"", '"', "#{name} = \"\"\n", '"')
272
+ end
273
+
274
+ #
275
+ # Converts a raw string into a Bash buffer
276
+ #
277
+ def self.to_bash(str, wrap = DefaultWrap, name = "buf")
278
+ return hexify(str, wrap, '$\'', '\'\\', "export #{name}=\\\n", '\'')
279
+ end
280
+
281
+ #
282
+ # Converts a raw string into a java byte array
283
+ #
284
+ def self.to_java(str, name = "shell")
285
+ buff = "byte #{name}[] = new byte[]\n{\n"
286
+ cnt = 0
287
+ max = 0
288
+ str.unpack('C*').each do |c|
289
+ buff << ", " if max > 0
290
+ buff << "\t" if max == 0
291
+ buff << sprintf('(byte) 0x%.2x', c)
292
+ max +=1
293
+ cnt +=1
294
+
295
+ if (max > 7)
296
+ buff << ",\n" if cnt != str.length
297
+ max = 0
298
+ end
299
+ end
300
+ buff << "\n};\n"
301
+ return buff
302
+ end
303
+
304
+ #
305
+ # Converts a raw string to a powershell byte array
306
+ #
307
+ def self.to_powershell(str, name = "buf")
308
+ return "[Byte[]]$#{name} = ''" if str.nil? or str.empty?
309
+
310
+ code = str.unpack('C*')
311
+ buff = "[Byte[]]$#{name} = 0x#{code[0].to_s(16)}"
312
+ 1.upto(code.length-1) do |byte|
313
+ if(byte % 10 == 0)
314
+ buff << "\r\n$#{name} += 0x#{code[byte].to_s(16)}"
315
+ else
316
+ buff << ",0x#{code[byte].to_s(16)}"
317
+ end
318
+ end
319
+
320
+ return buff
321
+ end
322
+
323
+ #
324
+ # Converts a raw string to a vbscript byte array
325
+ #
326
+ def self.to_vbscript(str, name = "buf")
327
+ return "#{name}" if str.nil? or str.empty?
328
+
329
+ code = str.unpack('C*')
330
+ buff = "#{name}=Chr(#{code[0]})"
331
+ 1.upto(code.length-1) do |byte|
332
+ if(byte % 100 == 0)
333
+ buff << "\r\n#{name}=#{name}"
334
+ end
335
+ # exe is an Array of bytes, not a String, thanks to the unpack
336
+ # above, so the following line is not subject to the different
337
+ # treatments of String#[] between ruby 1.8 and 1.9
338
+ buff << "&Chr(#{code[byte]})"
339
+ end
340
+
341
+ return buff
342
+ end
343
+
344
+ #
345
+ # Converts a raw string into a vba buffer
346
+ #
347
+ def self.to_vbapplication(str, name = "buf")
348
+ return "#{name} = Array()" if str.nil? or str.empty?
349
+
350
+ code = str.unpack('C*')
351
+ buff = "#{name} = Array("
352
+ maxbytes = 20
353
+
354
+ 1.upto(code.length) do |idx|
355
+ buff << code[idx].to_s
356
+ buff << "," if idx < code.length - 1
357
+ buff << " _\r\n" if (idx > 1 and (idx % maxbytes) == 0)
358
+ end
359
+
360
+ buff << ")\r\n"
361
+
362
+ return buff
363
+ end
364
+
365
+ #
366
+ # Creates a perl-style comment
367
+ #
368
+ def self.to_perl_comment(str, wrap = DefaultWrap)
369
+ return wordwrap(str, 0, wrap, '', '# ')
370
+ end
371
+
372
+ #
373
+ # Creates a Bash-style comment
374
+ #
375
+ def self.to_bash_comment(str, wrap = DefaultWrap)
376
+ return wordwrap(str, 0, wrap, '', '# ')
377
+ end
378
+
379
+ #
380
+ # Returns the raw string
381
+ #
382
+ def self.to_raw(str)
383
+ return str
384
+ end
385
+
386
+ #
387
+ # Converts ISO-8859-1 to UTF-8
388
+ #
389
+ def self.to_utf8(str)
390
+
391
+ if str.respond_to?(:encode)
392
+ # Skip over any bytes that fail to convert to UTF-8
393
+ return str.encode('utf-8', { :invalid => :replace, :undef => :replace, :replace => '' })
394
+ end
395
+
396
+ begin
397
+ Iconv.iconv("utf-8","iso-8859-1", str).join(" ")
398
+ rescue
399
+ raise ::RuntimeError, "Your installation does not support iconv (needed for utf8 conversion)"
400
+ end
401
+ end
402
+
403
+ #
404
+ # Converts ASCII to EBCDIC
405
+ #
406
+ class IllegalSequence < ArgumentError; end
407
+
408
+ # A native implementation of the ASCII->EBCDIC table, used to fall back from using
409
+ # Iconv
410
+ def self.to_ebcdic_rex(str)
411
+ new_str = []
412
+ str.each_byte do |x|
413
+ if Iconv_ASCII.index(x.chr)
414
+ new_str << Iconv_EBCDIC[Iconv_ASCII.index(x.chr)]
415
+ else
416
+ raise Rex::Text::IllegalSequence, ("\\x%x" % x)
417
+ end
418
+ end
419
+ new_str.join
420
+ end
421
+
422
+ # A native implementation of the EBCDIC->ASCII table, used to fall back from using
423
+ # Iconv
424
+ def self.from_ebcdic_rex(str)
425
+ new_str = []
426
+ str.each_byte do |x|
427
+ if Iconv_EBCDIC.index(x.chr)
428
+ new_str << Iconv_ASCII[Iconv_EBCDIC.index(x.chr)]
429
+ else
430
+ raise Rex::Text::IllegalSequence, ("\\x%x" % x)
431
+ end
432
+ end
433
+ new_str.join
434
+ end
435
+
436
+ def self.to_ebcdic(str)
437
+ begin
438
+ Iconv.iconv("EBCDIC-US", "ASCII", str).first
439
+ rescue ::Iconv::IllegalSequence => e
440
+ raise e
441
+ rescue
442
+ self.to_ebcdic_rex(str)
443
+ end
444
+ end
445
+
446
+ #
447
+ # Converts EBCIDC to ASCII
448
+ #
449
+ def self.from_ebcdic(str)
450
+ begin
451
+ Iconv.iconv("ASCII", "EBCDIC-US", str).first
452
+ rescue ::Iconv::IllegalSequence => e
453
+ raise e
454
+ rescue
455
+ self.from_ebcdic_rex(str)
456
+ end
457
+ end
458
+
459
+ #
460
+ # Returns the words in +str+ as an Array.
461
+ #
462
+ # strict - include *only* words, no boundary characters (like spaces, etc.)
463
+ #
464
+ def self.to_words( str, strict = false )
465
+ splits = str.split( /\b/ )
466
+ splits.reject! { |w| !(w =~ /\w/) } if strict
467
+ splits
468
+ end
469
+
470
+ #
471
+ # Removes noise from 2 Strings and return a refined String version.
472
+ #
473
+ def self.refine( str1, str2 )
474
+ return str1 if str1 == str2
475
+
476
+ # get the words of the first str in an array
477
+ s_words = to_words( str1 )
478
+
479
+ # get the words of the second str in an array
480
+ o_words = to_words( str2 )
481
+
482
+ # get what hasn't changed (the rdiff, so to speak) as a string
483
+ (s_words - (s_words - o_words)).join
484
+ end
485
+
486
+ #
487
+ # Returns a unicode escaped string for Javascript
488
+ #
489
+ def self.to_unescape(data, endian=ENDIAN_LITTLE, prefix='%%u')
490
+ data << "\x41" if (data.length % 2 != 0)
491
+ dptr = 0
492
+ buff = ''
493
+ while (dptr < data.length)
494
+ c1 = data[dptr,1].unpack("C*")[0]
495
+ dptr += 1
496
+ c2 = data[dptr,1].unpack("C*")[0]
497
+ dptr += 1
498
+
499
+ if (endian == ENDIAN_LITTLE)
500
+ buff << sprintf("#{prefix}%.2x%.2x", c2, c1)
501
+ else
502
+ buff << sprintf("#{prefix}%.2x%.2x", c1, c2)
503
+ end
504
+ end
505
+ return buff
506
+ end
507
+
508
+ #
509
+ # Returns the escaped octal version of the supplied string
510
+ #
511
+ # @example
512
+ # Rex::Text.to_octal("asdf") # => "\\141\\163\\144\\146"
513
+ #
514
+ # @param str [String] The string to be converted
515
+ # @param prefix [String]
516
+ # @return [String] The escaped octal version of +str+
517
+ def self.to_octal(str, prefix = "\\")
518
+ octal = ""
519
+ str.each_byte { |b|
520
+ octal << "#{prefix}#{b.to_s 8}"
521
+ }
522
+
523
+ return octal
524
+ end
525
+
526
+ #
527
+ # Returns the escaped hex version of the supplied string
528
+ #
529
+ # @example
530
+ # Rex::Text.to_hex("asdf") # => "\\x61\\x73\\x64\\x66"
531
+ #
532
+ # @param str (see to_octal)
533
+ # @param prefix (see to_octal)
534
+ # @param count [Fixnum] Number of bytes to put in each escape chunk
535
+ # @return [String] The escaped hex version of +str+
536
+ def self.to_hex(str, prefix = "\\x", count = 1)
537
+ raise ::RuntimeError, "unable to chunk into #{count} byte chunks" if ((str.length % count) > 0)
538
+
539
+ # XXX: Regexp.new is used here since using /.{#{count}}/o would compile
540
+ # the regex the first time it is used and never check again. Since we
541
+ # want to know how many to capture on every instance, we do it this
542
+ # way.
543
+ return str.unpack('H*')[0].gsub(Regexp.new(".{#{count * 2}}", nil, 'n')) { |s| prefix + s }
544
+ end
545
+
546
+ #
547
+ # Returns the string with nonprintable hex characters sanitized to ascii.
548
+ # Similiar to {.to_hex}, but regular ASCII is not translated if +count+ is 1.
549
+ #
550
+ # @example
551
+ # Rex::Text.to_hex_ascii("\x7fABC\0") # => "\\x7fABC\\x00"
552
+ #
553
+ # @param str (see to_hex)
554
+ # @param prefix (see to_hex)
555
+ # @param count (see to_hex)
556
+ # @param suffix [String,nil] A string to append to the converted bytes
557
+ # @return [String] The original string with non-printables converted to
558
+ # their escaped hex representation
559
+ def self.to_hex_ascii(str, prefix = "\\x", count = 1, suffix=nil)
560
+ raise ::RuntimeError, "unable to chunk into #{count} byte chunks" if ((str.length % count) > 0)
561
+ return str.unpack('H*')[0].gsub(Regexp.new(".{#{count * 2}}", nil, 'n')) { |s|
562
+ (0x20..0x7e) === s.to_i(16) ? s.to_i(16).chr : prefix + s + suffix.to_s
563
+ }
564
+ end
565
+
566
+ #
567
+ # Converts standard ASCII text to a unicode string.
568
+ #
569
+ # Supported unicode types include: utf-16le, utf16-be, utf32-le,
570
+ # utf32-be, utf-7, and utf-8
571
+ #
572
+ # Providing 'mode' provides hints to the actual encoder as to how it
573
+ # should encode the string.
574
+ #
575
+ # Only UTF-7 and UTF-8 use "mode".
576
+ #
577
+ # utf-7 by default does not encode alphanumeric and a few other
578
+ # characters. By specifying the mode of "all", then all of the
579
+ # characters are encoded, not just the non-alphanumeric set.
580
+ # to_unicode(str, 'utf-7', 'all')
581
+ #
582
+ # utf-8 specifies that alphanumeric characters are used directly, eg
583
+ # "a" is just "a". However, there exist 6 different overlong
584
+ # encodings of "a" that are technically not valid, but parse just fine
585
+ # in most utf-8 parsers. (0xC1A1, 0xE081A1, 0xF08081A1, 0xF8808081A1,
586
+ # 0xFC80808081A1, 0xFE8080808081A1). How many bytes to use for the
587
+ # overlong enocding is specified providing 'size'. to_unicode(str,
588
+ # 'utf-8', 'overlong', 2)
589
+ #
590
+ # Many utf-8 parsers also allow invalid overlong encodings, where bits
591
+ # that are unused when encoding a single byte are modified. Many
592
+ # parsers will ignore these bits, rendering simple string matching to
593
+ # be ineffective for dealing with UTF-8 strings. There are many more
594
+ # invalid overlong encodings possible for "a". For example, three
595
+ # encodings are available for an invalid 2 byte encoding of "a".
596
+ # (0xC1E1 0xC161 0xC121).
597
+ #
598
+ # By specifying "invalid", a random invalid encoding is chosen for the
599
+ # given byte size. to_unicode(str, 'utf-8', 'invalid', 2)
600
+ #
601
+ # utf-7 defaults to 'normal' utf-7 encoding utf-8 defaults to 2 byte
602
+ # 'normal' encoding
603
+ def self.to_unicode(str='', type = 'utf-16le', mode = '', size = '')
604
+ return '' if not str
605
+ case type
606
+ when 'utf-16le'
607
+ return str.unpack('C*').pack('v*')
608
+ when 'utf-16be'
609
+ return str.unpack('C*').pack('n*')
610
+ when 'utf-32le'
611
+ return str.unpack('C*').pack('V*')
612
+ when 'utf-32be'
613
+ return str.unpack('C*').pack('N*')
614
+ when 'utf-7'
615
+ case mode
616
+ when 'all'
617
+ return str.gsub(/./){ |a|
618
+ out = ''
619
+ if 'a' != '+'
620
+ out = encode_base64(to_unicode(a, 'utf-16be')).gsub(/[=\r\n]/, '')
621
+ end
622
+ '+' + out + '-'
623
+ }
624
+ else
625
+ return str.gsub(/[^\n\r\t\ A-Za-z0-9\'\(\),-.\/\:\?]/){ |a|
626
+ out = ''
627
+ if a != '+'
628
+ out = encode_base64(to_unicode(a, 'utf-16be')).gsub(/[=\r\n]/, '')
629
+ end
630
+ '+' + out + '-'
631
+ }
632
+ end
633
+ when 'utf-8'
634
+ if size == ''
635
+ size = 2
636
+ end
637
+
638
+ if size >= 2 and size <= 7
639
+ string = ''
640
+ str.each_byte { |a|
641
+ if (a < 21 || a > 0x7f) || mode != ''
642
+ # ugh. turn a single byte into the binary representation of it, in array form
643
+ bin = [a].pack('C').unpack('B8')[0].split(//)
644
+
645
+ # even more ugh.
646
+ bin.collect!{|a_| a_.to_i}
647
+
648
+ out = Array.new(8 * size, 0)
649
+
650
+ 0.upto(size - 1) { |i|
651
+ out[i] = 1
652
+ out[i * 8] = 1
653
+ }
654
+
655
+ i = 0
656
+ byte = 0
657
+ bin.reverse.each { |bit|
658
+ if i < 6
659
+ mod = (((size * 8) - 1) - byte * 8) - i
660
+ out[mod] = bit
661
+ else
662
+ byte = byte + 1
663
+ i = 0
664
+ redo
665
+ end
666
+ i = i + 1
667
+ }
668
+
669
+ if mode != ''
670
+ case mode
671
+ when 'overlong'
672
+ # do nothing, since we already handle this as above...
673
+ when 'invalid'
674
+ done = 0
675
+ while done == 0
676
+ # the ghetto...
677
+ bits = [7, 8, 15, 16, 23, 24, 31, 32, 41]
678
+ bits.each { |bit|
679
+ bit = (size * 8) - bit
680
+ if bit > 1
681
+ set = rand(2)
682
+ if out[bit] != set
683
+ out[bit] = set
684
+ done = 1
685
+ end
686
+ end
687
+ }
688
+ end
689
+ else
690
+ raise TypeError, 'Invalid mode. Only "overlong" and "invalid" are acceptable modes for utf-8'
691
+ end
692
+ end
693
+ string << [out.join('')].pack('B*')
694
+ else
695
+ string << [a].pack('C')
696
+ end
697
+ }
698
+ return string
699
+ else
700
+ raise TypeError, 'invalid utf-8 size'
701
+ end
702
+ when 'uhwtfms' # suggested name from HD :P
703
+ load_codepage()
704
+
705
+ string = ''
706
+ # overloading mode as codepage
707
+ if mode == ''
708
+ mode = 1252 # ANSI - Latan 1, default for US installs of MS products
709
+ else
710
+ mode = mode.to_i
711
+ end
712
+ if @@codepage_map_cache[mode].nil?
713
+ raise TypeError, "Invalid codepage #{mode}"
714
+ end
715
+ str.each_byte {|byte|
716
+ char = [byte].pack('C*')
717
+ possible = @@codepage_map_cache[mode]['data'][char]
718
+ if possible.nil?
719
+ raise TypeError, "codepage #{mode} does not provide an encoding for 0x#{char.unpack('H*')[0]}"
720
+ end
721
+ string << possible[ rand(possible.length) ]
722
+ }
723
+ return string
724
+ when 'uhwtfms-half' # suggested name from HD :P
725
+ load_codepage()
726
+ string = ''
727
+ # overloading mode as codepage
728
+ if mode == ''
729
+ mode = 1252 # ANSI - Latan 1, default for US installs of MS products
730
+ else
731
+ mode = mode.to_i
732
+ end
733
+ if mode != 1252
734
+ raise TypeError, "Invalid codepage #{mode}, only 1252 supported for uhwtfms_half"
735
+ end
736
+ str.each_byte {|byte|
737
+ if ((byte >= 33 && byte <= 63) || (byte >= 96 && byte <= 126))
738
+ string << "\xFF" + [byte ^ 32].pack('C')
739
+ elsif (byte >= 64 && byte <= 95)
740
+ string << "\xFF" + [byte ^ 96].pack('C')
741
+ else
742
+ char = [byte].pack('C')
743
+ possible = @@codepage_map_cache[mode]['data'][char]
744
+ if possible.nil?
745
+ raise TypeError, "codepage #{mode} does not provide an encoding for 0x#{char.unpack('H*')[0]}"
746
+ end
747
+ string << possible[ rand(possible.length) ]
748
+ end
749
+ }
750
+ return string
751
+ else
752
+ raise TypeError, 'invalid utf type'
753
+ end
754
+ end
755
+
756
+ #
757
+ # Converts a unicode string to standard ASCII text.
758
+ #
759
+ def self.to_ascii(str='', type = 'utf-16le', mode = '', size = '')
760
+ return '' if not str
761
+ case type
762
+ when 'utf-16le'
763
+ return str.unpack('v*').pack('C*')
764
+ when 'utf-16be'
765
+ return str.unpack('n*').pack('C*')
766
+ when 'utf-32le'
767
+ return str.unpack('V*').pack('C*')
768
+ when 'utf-32be'
769
+ return str.unpack('N*').pack('C*')
770
+ when 'utf-7'
771
+ raise TypeError, 'invalid utf type, not yet implemented'
772
+ when 'utf-8'
773
+ raise TypeError, 'invalid utf type, not yet implemented'
774
+ when 'uhwtfms' # suggested name from HD :P
775
+ raise TypeError, 'invalid utf type, not yet implemented'
776
+ when 'uhwtfms-half' # suggested name from HD :P
777
+ raise TypeError, 'invalid utf type, not yet implemented'
778
+ else
779
+ raise TypeError, 'invalid utf type'
780
+ end
781
+ end
782
+
783
+ #
784
+ # Encode a string in a manor useful for HTTP URIs and URI Parameters.
785
+ #
786
+ def self.uri_encode(str, mode = 'hex-normal')
787
+ return "" if str == nil
788
+
789
+ return str if mode == 'none' # fast track no encoding
790
+
791
+ all = /./
792
+ noslashes = /[^\/\\]+/
793
+ # http://tools.ietf.org/html/rfc3986#section-2.3
794
+ normal = /[^a-zA-Z0-9\/\\\.\-_~]+/
795
+
796
+ case mode
797
+ when 'hex-all'
798
+ return str.gsub(all) { |s| Rex::Text.to_hex(s, '%') }
799
+ when 'hex-normal'
800
+ return str.gsub(normal) { |s| Rex::Text.to_hex(s, '%') }
801
+ when 'hex-noslashes'
802
+ return str.gsub(noslashes) { |s| Rex::Text.to_hex(s, '%') }
803
+ when 'hex-random'
804
+ res = ''
805
+ str.each_byte do |c|
806
+ b = c.chr
807
+ res << ((rand(2) == 0) ?
808
+ b.gsub(all) { |s| Rex::Text.to_hex(s, '%') } :
809
+ b.gsub(normal){ |s| Rex::Text.to_hex(s, '%') } )
810
+ end
811
+ return res
812
+ when 'u-all'
813
+ return str.gsub(all) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) }
814
+ when 'u-normal'
815
+ return str.gsub(normal) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) }
816
+ when 'u-noslashes'
817
+ return str.gsub(noslashes) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) }
818
+ when 'u-random'
819
+ res = ''
820
+ str.each_byte do |c|
821
+ b = c.chr
822
+ res << ((rand(2) == 0) ?
823
+ b.gsub(all) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) } :
824
+ b.gsub(normal){ |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms'), '%u', 2) } )
825
+ end
826
+ return res
827
+ when 'u-half'
828
+ return str.gsub(all) { |s| Rex::Text.to_hex(Rex::Text.to_unicode(s, 'uhwtfms-half'), '%u', 2) }
829
+ else
830
+ raise TypeError, "invalid mode #{mode.inspect}"
831
+ end
832
+ end
833
+
834
+ #
835
+ # Encode a string in a manner useful for HTTP URIs and URI Parameters.
836
+ #
837
+ # @param str [String] The string to be encoded
838
+ # @param mode ["hex","int","int-wide"]
839
+ # @return [String]
840
+ # @raise [TypeError] if +mode+ is not one of the three available modes
841
+ def self.html_encode(str, mode = 'hex')
842
+ case mode
843
+ when 'hex'
844
+ return str.unpack('C*').collect{ |i| "&#x" + ("%.2x" % i) + ";"}.join
845
+ when 'int'
846
+ return str.unpack('C*').collect{ |i| "&#" + i.to_s + ";"}.join
847
+ when 'int-wide'
848
+ return str.unpack('C*').collect{ |i| "&#" + ("0" * (7 - i.to_s.length)) + i.to_s + ";" }.join
849
+ else
850
+ raise TypeError, 'invalid mode'
851
+ end
852
+ end
853
+
854
+ #
855
+ # Decode a string that's html encoded
856
+ #
857
+ def self.html_decode(str)
858
+ decoded_str = CGI.unescapeHTML(str)
859
+ return decoded_str
860
+ end
861
+
862
+ #
863
+ # Encode an ASCII string so it's safe for XML. It's a wrapper for to_hex_ascii.
864
+ #
865
+ def self.xml_char_encode(str)
866
+ self.to_hex_ascii(str, "&#x", 1, ";")
867
+ end
868
+
869
+ #
870
+ # Decode a URI encoded string
871
+ #
872
+ def self.uri_decode(str)
873
+ str.gsub(/(%[a-z0-9]{2})/i){ |c| [c[1,2]].pack("H*") }
874
+ end
875
+
876
+ #
877
+ # Converts a string to random case
878
+ #
879
+ # @example
880
+ # Rex::Text.to_rand_case("asdf") # => "asDf"
881
+ #
882
+ # @param str [String] The string to randomize
883
+ # @return [String]
884
+ # @see permute_case
885
+ # @see to_mixed_case_array
886
+ def self.to_rand_case(str)
887
+ buf = str.dup
888
+ 0.upto(str.length) do |i|
889
+ buf[i,1] = rand(2) == 0 ? str[i,1].upcase : str[i,1].downcase
890
+ end
891
+ return buf
892
+ end
893
+
894
+ #
895
+ # Takes a string, and returns an array of all mixed case versions.
896
+ #
897
+ # @example
898
+ # >> Rex::Text.to_mixed_case_array "abc1"
899
+ # => ["abc1", "abC1", "aBc1", "aBC1", "Abc1", "AbC1", "ABc1", "ABC1"]
900
+ #
901
+ # @param str [String] The string to randomize
902
+ # @return [Array<String>]
903
+ # @see permute_case
904
+ def self.to_mixed_case_array(str)
905
+ letters = []
906
+ str.scan(/./).each { |l| letters << [l.downcase, l.upcase] }
907
+ coords = []
908
+ (1 << str.size).times { |i| coords << ("%0#{str.size}b" % i) }
909
+ mixed = []
910
+ coords.each do |coord|
911
+ c = coord.scan(/./).map {|x| x.to_i}
912
+ this_str = ""
913
+ c.each_with_index { |d,i| this_str << letters[i][d] }
914
+ mixed << this_str
915
+ end
916
+ return mixed.uniq
917
+ end
918
+
919
+ #
920
+ # Converts a string to a nicely formatted hex dump
921
+ #
922
+ # @param str [String] The string to convert
923
+ # @param width [Fixnum] Number of bytes to convert before adding a newline
924
+ # @param base [Fixnum] The base address of the dump
925
+ def self.to_hex_dump(str, width=16, base=nil)
926
+ buf = ''
927
+ idx = 0
928
+ cnt = 0
929
+ snl = false
930
+ lst = 0
931
+ lft_col_len = (base.to_i+str.length).to_s(16).length
932
+ lft_col_len = 8 if lft_col_len < 8
933
+
934
+ while (idx < str.length)
935
+ chunk = str[idx, width]
936
+ addr = base ? "%0#{lft_col_len}x " %(base.to_i + idx) : ''
937
+ line = chunk.unpack("H*")[0].scan(/../).join(" ")
938
+ buf << addr + line
939
+
940
+ if (lst == 0)
941
+ lst = line.length
942
+ buf << " " * 4
943
+ else
944
+ buf << " " * ((lst - line.length) + 4).abs
945
+ end
946
+
947
+ buf << "|"
948
+
949
+ chunk.unpack("C*").each do |c|
950
+ if (c > 0x1f and c < 0x7f)
951
+ buf << c.chr
952
+ else
953
+ buf << "."
954
+ end
955
+ end
956
+
957
+ buf << "|\n"
958
+
959
+ idx += width
960
+ end
961
+
962
+ buf << "\n"
963
+ end
964
+
965
+ #
966
+ # Converts a hex string to a raw string
967
+ #
968
+ # @example
969
+ # Rex::Text.hex_to_raw("\\x41\\x7f\\x42") # => "A\x7fB"
970
+ #
971
+ def self.hex_to_raw(str)
972
+ [ str.downcase.gsub(/'/,'').gsub(/\\?x([a-f0-9][a-f0-9])/, '\1') ].pack("H*")
973
+ end
974
+
975
+ #
976
+ # Turn non-printable chars into hex representations, leaving others alone
977
+ #
978
+ # If +whitespace+ is true, converts whitespace (0x20, 0x09, etc) to hex as
979
+ # well.
980
+ #
981
+ # @see hexify
982
+ # @see to_hex Converts all the chars
983
+ #
984
+ def self.ascii_safe_hex(str, whitespace=false)
985
+ if whitespace
986
+ str.gsub(/([\x00-\x20\x80-\xFF])/n){ |x| "\\x%.2x" % x.unpack("C*")[0] }
987
+ else
988
+ str.gsub(/([\x00-\x08\x0b\x0c\x0e-\x1f\x80-\xFF])/n){ |x| "\\x%.2x" % x.unpack("C*")[0]}
989
+ end
990
+ end
991
+
992
+ #
993
+ # Wraps text at a given column using a supplied indention
994
+ #
995
+ def self.wordwrap(str, indent = 0, col = DefaultWrap, append = '', prepend = '')
996
+ return str.gsub(/.{1,#{col - indent}}(?:\s|\Z)/){
997
+ ( (" " * indent) + prepend + $& + append + 5.chr).gsub(/\n\005/,"\n").gsub(/\005/,"\n")}
998
+ end
999
+
1000
+ #
1001
+ # Converts a string to a hex version with wrapping support
1002
+ #
1003
+ def self.hexify(str, col = DefaultWrap, line_start = '', line_end = '', buf_start = '', buf_end = '')
1004
+ output = buf_start
1005
+ cur = 0
1006
+ count = 0
1007
+ new_line = true
1008
+
1009
+ # Go through each byte in the string
1010
+ str.each_byte { |byte|
1011
+ count += 1
1012
+ append = ''
1013
+
1014
+ # If this is a new line, prepend with the
1015
+ # line start text
1016
+ if (new_line == true)
1017
+ append << line_start
1018
+ new_line = false
1019
+ end
1020
+
1021
+ # Append the hexified version of the byte
1022
+ append << sprintf("\\x%.2x", byte)
1023
+ cur += append.length
1024
+
1025
+ # If we're about to hit the column or have gone past it,
1026
+ # time to finish up this line
1027
+ if ((cur + line_end.length >= col) or (cur + buf_end.length >= col))
1028
+ new_line = true
1029
+ cur = 0
1030
+
1031
+ # If this is the last byte, use the buf_end instead of
1032
+ # line_end
1033
+ if (count == str.length)
1034
+ append << buf_end + "\n"
1035
+ else
1036
+ append << line_end + "\n"
1037
+ end
1038
+ end
1039
+
1040
+ output << append
1041
+ }
1042
+
1043
+ # If we were in the middle of a line, finish the buffer at this point
1044
+ if (new_line == false)
1045
+ output << buf_end + "\n"
1046
+ end
1047
+
1048
+ return output
1049
+ end
1050
+
1051
+ ##
1052
+ #
1053
+ # Transforms
1054
+ #
1055
+ ##
1056
+
1057
+ #
1058
+ # Base32 code
1059
+ #
1060
+
1061
+ # Based on --> https://github.com/stesla/base32
1062
+
1063
+ # Copyright (c) 2007-2011 Samuel Tesla
1064
+
1065
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
1066
+ # of this software and associated documentation files (the "Software"), to deal
1067
+ # in the Software without restriction, including without limitation the rights
1068
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
1069
+ # copies of the Software, and to permit persons to whom the Software is
1070
+ # furnished to do so, subject to the following conditions:
1071
+
1072
+ # The above copyright notice and this permission notice shall be included in
1073
+ # all copies or substantial portions of the Software.
1074
+
1075
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1076
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1077
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1078
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1079
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1080
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
1081
+ # THE SOFTWARE.
1082
+
1083
+
1084
+ #
1085
+ # Base32 encoder
1086
+ #
1087
+ def self.b32encode(bytes_in)
1088
+ n = (bytes_in.length * 8.0 / 5.0).ceil
1089
+ p = n < 8 ? 5 - (bytes_in.length * 8) % 5 : 0
1090
+ c = bytes_in.inject(0) {|m,o| (m << 8) + o} << p
1091
+ [(0..n-1).to_a.reverse.collect {|i| Base32[(c >> i * 5) & 0x1f].chr},
1092
+ ("=" * (8-n))]
1093
+ end
1094
+
1095
+ def self.encode_base32(str)
1096
+ bytes = str.bytes
1097
+ result = ''
1098
+ size= 5
1099
+ while bytes.any? do
1100
+ bytes.each_slice(size) do |a|
1101
+ bytes_out = b32encode(a).flatten.join
1102
+ result << bytes_out
1103
+ bytes = bytes.drop(size)
1104
+ end
1105
+ end
1106
+ return result
1107
+ end
1108
+
1109
+ #
1110
+ # Base32 decoder
1111
+ #
1112
+ def self.b32decode(bytes_in)
1113
+ bytes = bytes_in.take_while {|c| c != 61} # strip padding
1114
+ n = (bytes.length * 5.0 / 8.0).floor
1115
+ p = bytes.length < 8 ? 5 - (n * 8) % 5 : 0
1116
+ c = bytes.inject(0) {|m,o| (m << 5) + Base32.index(o.chr)} >> p
1117
+ (0..n-1).to_a.reverse.collect {|i| ((c >> i * 8) & 0xff).chr}
1118
+ end
1119
+
1120
+ def self.decode_base32(str)
1121
+ bytes = str.bytes
1122
+ result = ''
1123
+ size= 8
1124
+ while bytes.any? do
1125
+ bytes.each_slice(size) do |a|
1126
+ bytes_out = b32decode(a).flatten.join
1127
+ result << bytes_out
1128
+ bytes = bytes.drop(size)
1129
+ end
1130
+ end
1131
+ return result
1132
+ end
1133
+
1134
+ #
1135
+ # Base64 encoder
1136
+ #
1137
+ def self.encode_base64(str, delim='')
1138
+ [str.to_s].pack("m").gsub(/\s+/, delim)
1139
+ end
1140
+
1141
+ #
1142
+ # Base64 decoder
1143
+ #
1144
+ def self.decode_base64(str)
1145
+ str.to_s.unpack("m")[0]
1146
+ end
1147
+
1148
+ #
1149
+ # Raw MD5 digest of the supplied string
1150
+ #
1151
+ def self.md5_raw(str)
1152
+ Digest::MD5.digest(str)
1153
+ end
1154
+
1155
+ #
1156
+ # Hexidecimal MD5 digest of the supplied string
1157
+ #
1158
+ def self.md5(str)
1159
+ Digest::MD5.hexdigest(str)
1160
+ end
1161
+
1162
+ #
1163
+ # Raw SHA1 digest of the supplied string
1164
+ #
1165
+ def self.sha1_raw(str)
1166
+ Digest::SHA1.digest(str)
1167
+ end
1168
+
1169
+ #
1170
+ # Hexidecimal SHA1 digest of the supplied string
1171
+ #
1172
+ def self.sha1(str)
1173
+ Digest::SHA1.hexdigest(str)
1174
+ end
1175
+
1176
+ #
1177
+ # Convert hex-encoded characters to literals.
1178
+ #
1179
+ # @example
1180
+ # Rex::Text.dehex("AA\\x42CC") # => "AABCC"
1181
+ #
1182
+ # @see hex_to_raw
1183
+ # @param str [String]
1184
+ def self.dehex(str)
1185
+ return str unless str.respond_to? :match
1186
+ return str unless str.respond_to? :gsub
1187
+ regex = /\x5cx[0-9a-f]{2}/nmi
1188
+ if str.match(regex)
1189
+ str.gsub(regex) { |x| x[2,2].to_i(16).chr }
1190
+ else
1191
+ str
1192
+ end
1193
+ end
1194
+
1195
+ #
1196
+ # Convert and replace hex-encoded characters to literals.
1197
+ #
1198
+ # @param (see dehex)
1199
+ def self.dehex!(str)
1200
+ return str unless str.respond_to? :match
1201
+ return str unless str.respond_to? :gsub
1202
+ regex = /\x5cx[0-9a-f]{2}/nmi
1203
+ str.gsub!(regex) { |x| x[2,2].to_i(16).chr }
1204
+ end
1205
+
1206
+ ##
1207
+ #
1208
+ # Generators
1209
+ #
1210
+ ##
1211
+
1212
+
1213
+ # Generates a random character.
1214
+ def self.rand_char(bad, chars = AllChars)
1215
+ rand_text(1, bad, chars)
1216
+ end
1217
+
1218
+ # Base text generator method
1219
+ def self.rand_base(len, bad, *foo)
1220
+ cset = (foo.join.unpack("C*") - bad.to_s.unpack("C*")).uniq
1221
+ return "" if cset.length == 0
1222
+ outp = []
1223
+ len.times { outp << cset[rand(cset.length)] }
1224
+ outp.pack("C*")
1225
+ end
1226
+
1227
+ # Generate random bytes of data
1228
+ def self.rand_text(len, bad='', chars = AllChars)
1229
+ foo = chars.split('')
1230
+ rand_base(len, bad, *foo)
1231
+ end
1232
+
1233
+ # Generate random bytes of alpha data
1234
+ def self.rand_text_alpha(len, bad='')
1235
+ foo = []
1236
+ foo += ('A' .. 'Z').to_a
1237
+ foo += ('a' .. 'z').to_a
1238
+ rand_base(len, bad, *foo )
1239
+ end
1240
+
1241
+ # Generate random bytes of lowercase alpha data
1242
+ def self.rand_text_alpha_lower(len, bad='')
1243
+ rand_base(len, bad, *('a' .. 'z').to_a)
1244
+ end
1245
+
1246
+ # Generate random bytes of uppercase alpha data
1247
+ def self.rand_text_alpha_upper(len, bad='')
1248
+ rand_base(len, bad, *('A' .. 'Z').to_a)
1249
+ end
1250
+
1251
+ # Generate random bytes of alphanumeric data
1252
+ def self.rand_text_alphanumeric(len, bad='')
1253
+ foo = []
1254
+ foo += ('A' .. 'Z').to_a
1255
+ foo += ('a' .. 'z').to_a
1256
+ foo += ('0' .. '9').to_a
1257
+ rand_base(len, bad, *foo )
1258
+ end
1259
+
1260
+ # Generate random bytes of alphanumeric hex.
1261
+ def self.rand_text_hex(len, bad='')
1262
+ foo = []
1263
+ foo += ('0' .. '9').to_a
1264
+ foo += ('a' .. 'f').to_a
1265
+ rand_base(len, bad, *foo)
1266
+ end
1267
+
1268
+ # Generate random bytes of numeric data
1269
+ def self.rand_text_numeric(len, bad='')
1270
+ foo = ('0' .. '9').to_a
1271
+ rand_base(len, bad, *foo )
1272
+ end
1273
+
1274
+ # Generate random bytes of english-like data
1275
+ def self.rand_text_english(len, bad='')
1276
+ foo = []
1277
+ foo += (0x21 .. 0x7e).map{ |c| c.chr }
1278
+ rand_base(len, bad, *foo )
1279
+ end
1280
+
1281
+ # Generate random bytes of high ascii data
1282
+ def self.rand_text_highascii(len, bad='')
1283
+ foo = []
1284
+ foo += (0x80 .. 0xff).map{ |c| c.chr }
1285
+ rand_base(len, bad, *foo )
1286
+ end
1287
+
1288
+ # Generate a random GUID
1289
+ #
1290
+ # @example
1291
+ # Rex::Text.rand_guid # => "{ca776ced-4ab8-2ed6-6510-aa71e5e2508e}"
1292
+ #
1293
+ # @return [String]
1294
+ def self.rand_guid
1295
+ "{#{[8,4,4,4,12].map {|a| rand_text_hex(a) }.join("-")}}"
1296
+ end
1297
+
1298
+ #
1299
+ # Convert 16-byte string to a GUID string
1300
+ #
1301
+ # @example
1302
+ # str = "ABCDEFGHIJKLMNOP"
1303
+ # Rex::Text.to_guid(str) #=> "{44434241-4645-4847-494a-4b4c4d4e4f50}"
1304
+ #
1305
+ # @param bytes [String] 16 bytes which represent a GUID in the proper
1306
+ # order.
1307
+ #
1308
+ # @return [String]
1309
+ def self.to_guid(bytes)
1310
+ return nil unless bytes
1311
+ s = bytes.unpack('H*')[0]
1312
+ parts = [
1313
+ s[6, 2] + s[4, 2] + s[2, 2] + s[0, 2],
1314
+ s[10, 2] + s[8, 2],
1315
+ s[14, 2] + s[12, 2],
1316
+ s[16, 4],
1317
+ s[20, 12]
1318
+ ]
1319
+ "{#{parts.join('-')}}"
1320
+ end
1321
+
1322
+ #
1323
+ # Creates a pattern that can be used for offset calculation purposes. This
1324
+ # routine is capable of generating patterns using a supplied set and a
1325
+ # supplied number of identifiable characters (slots). The supplied sets
1326
+ # should not contain any duplicate characters or the logic will fail.
1327
+ #
1328
+ # @param length [Fixnum]
1329
+ # @param sets [Array<(String,String,String)>] The character sets to choose
1330
+ # from. Should have 3 elements, each of which must be a string containing
1331
+ # no characters contained in the other sets.
1332
+ # @return [String] A pattern of +length+ bytes, in which any 4-byte chunk is
1333
+ # unique
1334
+ # @see pattern_offset
1335
+ def self.pattern_create(length, sets = nil)
1336
+ buf = ''
1337
+ offsets = []
1338
+
1339
+ # Make sure there's something in sets even if we were given an explicit nil
1340
+ sets ||= [ UpperAlpha, LowerAlpha, Numerals ]
1341
+
1342
+ # Return stupid uses
1343
+ return "" if length.to_i < 1
1344
+ return sets[0][0].chr * length if sets.size == 1 and sets[0].size == 1
1345
+
1346
+ sets.length.times { offsets << 0 }
1347
+
1348
+ until buf.length >= length
1349
+ begin
1350
+ buf << converge_sets(sets, 0, offsets, length)
1351
+ end
1352
+ end
1353
+
1354
+ # Maximum permutations reached, but we need more data
1355
+ if (buf.length < length)
1356
+ buf = buf * (length / buf.length.to_f).ceil
1357
+ end
1358
+
1359
+ buf[0,length]
1360
+ end
1361
+
1362
+ # Step through an arbitrary number of sets of bytes to build up a findable pattern.
1363
+ # This is mostly useful for experimentially determining offset lengths into memory
1364
+ # structures. Note that the supplied sets should never contain duplicate bytes, or
1365
+ # else it can become impossible to measure the offset accurately.
1366
+ def self.patt2(len, sets = nil)
1367
+ buf = ""
1368
+ counter = []
1369
+ sets ||= [ UpperAlpha, LowerAlpha, Numerals ]
1370
+ len ||= len.to_i
1371
+ return "" if len.zero?
1372
+
1373
+ sets = sets.map {|a| a.split(//)}
1374
+ sets.size.times { counter << 0}
1375
+ 0.upto(len-1) do |i|
1376
+ setnum = i % sets.size
1377
+
1378
+ #puts counter.inspect
1379
+ end
1380
+
1381
+ return buf
1382
+ end
1383
+
1384
+ #
1385
+ # Calculate the offset to a pattern
1386
+ #
1387
+ # @param pattern [String] The pattern to search. Usually the return value
1388
+ # from {.pattern_create}
1389
+ # @param value [String,Fixnum,Bignum]
1390
+ # @return [Fixnum] Index of the given +value+ within +pattern+, if it exists
1391
+ # @return [nil] if +pattern+ does not contain +value+
1392
+ # @see pattern_create
1393
+ def self.pattern_offset(pattern, value, start=0)
1394
+ if (value.kind_of?(String))
1395
+ pattern.index(value, start)
1396
+ elsif (value.kind_of?(Fixnum) or value.kind_of?(Bignum))
1397
+ pattern.index([ value ].pack('V'), start)
1398
+ else
1399
+ raise ::ArgumentError, "Invalid class for value: #{value.class}"
1400
+ end
1401
+ end
1402
+
1403
+ #
1404
+ # Compresses a string, eliminating all superfluous whitespace before and
1405
+ # after lines and eliminating all lines.
1406
+ #
1407
+ # @param str [String] The string in which to crunch whitespace
1408
+ # @return [String] Just like +str+, but with repeated whitespace characters
1409
+ # trimmed down to a single space
1410
+ def self.compress(str)
1411
+ str.gsub(/\n/m, ' ').gsub(/\s+/, ' ').gsub(/^\s+/, '').gsub(/\s+$/, '')
1412
+ end
1413
+
1414
+ #
1415
+ # Randomize the whitespace in a string
1416
+ #
1417
+ def self.randomize_space(str)
1418
+ set = ["\x09", "\x20", "\x0d", "\x0a"]
1419
+ str.gsub(/\s+/) { |s|
1420
+ len = rand(50)+2
1421
+ buf = ''
1422
+ while (buf.length < len)
1423
+ buf << set.sample
1424
+ end
1425
+
1426
+ buf
1427
+ }
1428
+ end
1429
+
1430
+ # Returns true if zlib can be used.
1431
+ def self.zlib_present?
1432
+ begin
1433
+ temp = Zlib
1434
+ return true
1435
+ rescue
1436
+ return false
1437
+ end
1438
+ end
1439
+
1440
+ # backwards compat for just a bit...
1441
+ def self.gzip_present?
1442
+ self.zlib_present?
1443
+ end
1444
+
1445
+ #
1446
+ # Compresses a string using zlib
1447
+ #
1448
+ # @param str [String] The string to be compressed
1449
+ # @param level [Fixnum] One of the Zlib compression level constants
1450
+ # @return [String] The compressed version of +str+
1451
+ def self.zlib_deflate(str, level = Zlib::BEST_COMPRESSION)
1452
+ if self.zlib_present?
1453
+ z = Zlib::Deflate.new(level)
1454
+ dst = z.deflate(str, Zlib::FINISH)
1455
+ z.close
1456
+ return dst
1457
+ else
1458
+ raise RuntimeError, "Gzip support is not present."
1459
+ end
1460
+ end
1461
+
1462
+ #
1463
+ # Uncompresses a string using zlib
1464
+ #
1465
+ # @param str [String] Compressed string to inflate
1466
+ # @return [String] The uncompressed version of +str+
1467
+ def self.zlib_inflate(str)
1468
+ if(self.zlib_present?)
1469
+ zstream = Zlib::Inflate.new
1470
+ buf = zstream.inflate(str)
1471
+ zstream.finish
1472
+ zstream.close
1473
+ return buf
1474
+ else
1475
+ raise RuntimeError, "Gzip support is not present."
1476
+ end
1477
+ end
1478
+
1479
+ #
1480
+ # Compresses a string using gzip
1481
+ #
1482
+ # @param str (see zlib_deflate)
1483
+ # @param level [Fixnum] Compression level, 1 (fast) to 9 (best)
1484
+ # @return (see zlib_deflate)
1485
+ def self.gzip(str, level = 9)
1486
+ raise RuntimeError, "Gzip support is not present." if (!zlib_present?)
1487
+ raise RuntimeError, "Invalid gzip compression level" if (level < 1 or level > 9)
1488
+
1489
+ s = ""
1490
+ s.force_encoding('ASCII-8BIT') if s.respond_to?(:encoding)
1491
+ gz = Zlib::GzipWriter.new(StringIO.new(s, 'wb'), level)
1492
+ gz << str
1493
+ gz.close
1494
+ return s
1495
+ end
1496
+
1497
+ #
1498
+ # Uncompresses a string using gzip
1499
+ #
1500
+ # @param str (see zlib_inflate)
1501
+ # @return (see zlib_inflate)
1502
+ def self.ungzip(str)
1503
+ raise RuntimeError, "Gzip support is not present." if (!zlib_present?)
1504
+
1505
+ s = ""
1506
+ s.force_encoding('ASCII-8BIT') if s.respond_to?(:encoding)
1507
+ gz = Zlib::GzipReader.new(StringIO.new(str, 'rb'))
1508
+ s << gz.read
1509
+ gz.close
1510
+ return s
1511
+ end
1512
+
1513
+ #
1514
+ # Return the index of the first badchar in +data+, otherwise return
1515
+ # nil if there wasn't any badchar occurences.
1516
+ #
1517
+ # @param data [String] The string to check for bad characters
1518
+ # @param badchars [String] A list of characters considered to be bad
1519
+ # @return [Fixnum] Index of the first bad character if any exist in +data+
1520
+ # @return [nil] If +data+ contains no bad characters
1521
+ def self.badchar_index(data, badchars = '')
1522
+ badchars.unpack("C*").each { |badchar|
1523
+ pos = data.index(badchar.chr)
1524
+ return pos if pos
1525
+ }
1526
+ return nil
1527
+ end
1528
+
1529
+ #
1530
+ # Removes bad characters from a string.
1531
+ #
1532
+ # Modifies +data+ in place
1533
+ #
1534
+ # @param data [#delete]
1535
+ # @param badchars [String] A list of characters considered to be bad
1536
+ def self.remove_badchars(data, badchars = '')
1537
+ data.delete(badchars)
1538
+ end
1539
+
1540
+ #
1541
+ # Returns all chars that are not in the supplied set
1542
+ #
1543
+ # @param keepers [String]
1544
+ # @return [String] All characters not contained in +keepers+
1545
+ def self.charset_exclude(keepers)
1546
+ [*(0..255)].pack('C*').delete(keepers)
1547
+ end
1548
+
1549
+ #
1550
+ # Shuffles a byte stream
1551
+ #
1552
+ # @param str [String]
1553
+ # @return [String] The shuffled result
1554
+ # @see shuffle_a
1555
+ def self.shuffle_s(str)
1556
+ shuffle_a(str.unpack("C*")).pack("C*")
1557
+ end
1558
+
1559
+ #
1560
+ # Performs a Fisher-Yates shuffle on an array
1561
+ #
1562
+ # Modifies +arr+ in place
1563
+ #
1564
+ # @param arr [Array] The array to be shuffled
1565
+ # @return [Array]
1566
+ def self.shuffle_a(arr)
1567
+ len = arr.length
1568
+ max = len - 1
1569
+ cyc = [* (0..max) ]
1570
+ for d in cyc
1571
+ e = rand(d+1)
1572
+ next if e == d
1573
+ f = arr[d];
1574
+ g = arr[e];
1575
+ arr[d] = g;
1576
+ arr[e] = f;
1577
+ end
1578
+ return arr
1579
+ end
1580
+
1581
+ # Permute the case of a word
1582
+ def self.permute_case(word, idx=0)
1583
+ res = []
1584
+
1585
+ if( (UpperAlpha+LowerAlpha).index(word[idx,1]))
1586
+
1587
+ word_ucase = word.dup
1588
+ word_ucase[idx, 1] = word[idx, 1].upcase
1589
+
1590
+ word_lcase = word.dup
1591
+ word_lcase[idx, 1] = word[idx, 1].downcase
1592
+
1593
+ if (idx == word.length)
1594
+ return [word]
1595
+ else
1596
+ res << permute_case(word_ucase, idx+1)
1597
+ res << permute_case(word_lcase, idx+1)
1598
+ end
1599
+ else
1600
+ res << permute_case(word, idx+1)
1601
+ end
1602
+
1603
+ res.flatten
1604
+ end
1605
+
1606
+ # Generate a random hostname
1607
+ #
1608
+ # @return [String] A random string conforming to the rules of FQDNs
1609
+ def self.rand_hostname
1610
+ host = []
1611
+ (rand(5) + 1).times {
1612
+ host.push(Rex::Text.rand_text_alphanumeric(rand(10) + 1))
1613
+ }
1614
+ host.push(TLDs.sample)
1615
+ host.join('.').downcase
1616
+ end
1617
+
1618
+ # Generate a state
1619
+ def self.rand_state()
1620
+ States.sample
1621
+ end
1622
+
1623
+ # Generate a surname
1624
+ def self.rand_surname
1625
+ Surnames.sample
1626
+ end
1627
+
1628
+ # Generate a name
1629
+ def self.rand_name
1630
+ if rand(10) % 2 == 0
1631
+ Names_Male.sample
1632
+ else
1633
+ Names_Female.sample
1634
+ end
1635
+ end
1636
+
1637
+ # Generate a male name
1638
+ def self.rand_name_male
1639
+ Names_Male.sample
1640
+ end
1641
+
1642
+ # Generate a female name
1643
+ def self.rand_name_female
1644
+ Names_Female.sample
1645
+ end
1646
+
1647
+ # Generate a random mail address
1648
+ def self.rand_mail_address
1649
+ mail_address = ''
1650
+ mail_address << Rex::Text.rand_name
1651
+ mail_address << '.'
1652
+ mail_address << Rex::Text.rand_surname
1653
+ mail_address << '@'
1654
+ mail_address << Rex::Text.rand_hostname
1655
+ end
1656
+
1657
+
1658
+ #
1659
+ # Calculate the ROR13 hash of a given string
1660
+ #
1661
+ # @return [Fixnum]
1662
+ def self.ror13_hash(name)
1663
+ hash = 0
1664
+ name.unpack("C*").each {|c| hash = ror(hash, 13); hash += c }
1665
+ hash
1666
+ end
1667
+
1668
+ #
1669
+ # Rotate a 32-bit value to the right by +cnt+ bits
1670
+ #
1671
+ # @param val [Fixnum] The value to rotate
1672
+ # @param cnt [Fixnum] Number of bits to rotate by
1673
+ def self.ror(val, cnt)
1674
+ bits = [val].pack("N").unpack("B32")[0].split(//)
1675
+ 1.upto(cnt) do |c|
1676
+ bits.unshift( bits.pop )
1677
+ end
1678
+ [bits.join].pack("B32").unpack("N")[0]
1679
+ end
1680
+
1681
+ #
1682
+ # Rotate a 32-bit value to the left by +cnt+ bits
1683
+ #
1684
+ # @param val (see ror)
1685
+ # @param cnt (see ror)
1686
+ # @return (see ror)
1687
+ def self.rol(val, cnt)
1688
+ bits = [val].pack("N").unpack("B32")[0].split(//)
1689
+ 1.upto(cnt) do |c|
1690
+ bits.push( bits.shift )
1691
+ end
1692
+ [bits.join].pack("B32").unpack("N")[0]
1693
+ end
1694
+
1695
+ #
1696
+ # Split a string by n character into an array
1697
+ #
1698
+ def self.split_to_a(str, n)
1699
+ if n > 0
1700
+ s = str.dup
1701
+ until s.empty?
1702
+ (ret ||= []).push s.slice!(0, n)
1703
+ end
1704
+ else
1705
+ ret = str
1706
+ end
1707
+ ret
1708
+ end
1709
+
1710
+ #
1711
+ # Pack a value as 64 bit litle endian; does not exist for Array.pack
1712
+ #
1713
+ def self.pack_int64le(val)
1714
+ [val & 0x00000000ffffffff, val >> 32].pack("V2")
1715
+ end
1716
+
1717
+
1718
+ #
1719
+ # A custom unicode filter for dealing with multi-byte strings on a 8-bit console
1720
+ # Punycode would have been more "standard", but it requires valid Unicode chars
1721
+ #
1722
+ def self.unicode_filter_encode(str)
1723
+ if (str.to_s.unpack("C*") & ( LowAscii + HighAscii + "\x7f" ).unpack("C*")).length > 0
1724
+ str = "$U$" + str.unpack("C*").select{|c| c < 0x7f and c > 0x1f and c != 0x2d}.pack("C*") + "-0x" + str.unpack("H*")[0]
1725
+ else
1726
+ str
1727
+ end
1728
+ end
1729
+
1730
+ def self.unicode_filter_decode(str)
1731
+ str.to_s.gsub( /\$U\$([\x20-\x2c\x2e-\x7E]*)\-0x([A-Fa-f0-9]+)/n ){|m| [$2].pack("H*") }
1732
+ end
1255
1733
 
1256
1734
  protected
1257
1735
 
1258
- def self.converge_sets(sets, idx, offsets, length) # :nodoc:
1259
- buf = sets[idx][offsets[idx]].chr
1260
-
1261
- # If there are more sets after use, converage with them.
1262
- if (sets[idx + 1])
1263
- buf << converge_sets(sets, idx + 1, offsets, length)
1264
- else
1265
- # Increment the current set offset as well as previous ones if we
1266
- # wrap back to zero.
1267
- while (idx >= 0 and ((offsets[idx] = (offsets[idx] + 1) % sets[idx].length)) == 0)
1268
- idx -= 1
1269
- end
1270
-
1271
- # If we reached the point where the idx fell below zero, then that
1272
- # means we've reached the maximum threshold for permutations.
1273
- if (idx < 0)
1274
- return buf
1275
- end
1276
-
1277
- end
1278
-
1279
- buf
1280
- end
1281
-
1282
- def self.load_codepage()
1283
- return if (!@@codepage_map_cache.nil?)
1284
- file = File.join(File.dirname(__FILE__),'codepage.map')
1285
- page = ''
1286
- name = ''
1287
- map = {}
1288
- File.open(file).each { |line|
1289
- next if line =~ /^#/
1290
- next if line =~ /^\s*$/
1291
- data = line.split
1292
- if data[1] =~ /^\(/
1293
- page = data.shift.to_i
1294
- name = data.join(' ').sub(/^\(/,'').sub(/\)$/,'')
1295
- map[page] = {}
1296
- map[page]['name'] = name
1297
- map[page]['data'] = {}
1298
- else
1299
- data.each { |entry|
1300
- wide, char = entry.split(':')
1301
- char = [char].pack('H*')
1302
- wide = [wide].pack('H*')
1303
- if map[page]['data'][char].nil?
1304
- map[page]['data'][char] = [wide]
1305
- else
1306
- map[page]['data'][char].push(wide)
1307
- end
1308
- }
1309
- end
1310
- }
1311
- @@codepage_map_cache = map
1312
- end
1313
-
1314
- def self.checksum8(str)
1315
- str.unpack("C*").inject(:+) % 0x100
1316
- end
1317
-
1318
- def self.checksum16_le(str)
1319
- str.unpack("v*").inject(:+) % 0x10000
1320
- end
1321
-
1322
- def self.checksum16_be(str)
1323
- str.unpack("n*").inject(:+) % 0x10000
1324
- end
1325
-
1326
- def self.checksum32_le(str)
1327
- str.unpack("V*").inject(:+) % 0x100000000
1328
- end
1329
-
1330
- def self.checksum32_be(str)
1331
- str.unpack("N*").inject(:+) % 0x100000000
1332
- end
1736
+ def self.converge_sets(sets, idx, offsets, length) # :nodoc:
1737
+ buf = sets[idx][offsets[idx]].chr
1738
+
1739
+ # If there are more sets after use, converage with them.
1740
+ if (sets[idx + 1])
1741
+ buf << converge_sets(sets, idx + 1, offsets, length)
1742
+ else
1743
+ # Increment the current set offset as well as previous ones if we
1744
+ # wrap back to zero.
1745
+ while (idx >= 0 and ((offsets[idx] = (offsets[idx] + 1) % sets[idx].length)) == 0)
1746
+ idx -= 1
1747
+ end
1748
+
1749
+ # If we reached the point where the idx fell below zero, then that
1750
+ # means we've reached the maximum threshold for permutations.
1751
+ if (idx < 0)
1752
+ return buf
1753
+ end
1754
+
1755
+ end
1756
+
1757
+ buf
1758
+ end
1759
+
1760
+ def self.load_codepage()
1761
+ return if (!@@codepage_map_cache.nil?)
1762
+ file = File.join(File.dirname(__FILE__),'codepage.map')
1763
+ page = ''
1764
+ name = ''
1765
+ map = {}
1766
+ File.open(file).each { |line|
1767
+ next if line =~ /^#/
1768
+ next if line =~ /^\s*$/
1769
+ data = line.split
1770
+ if data[1] =~ /^\(/
1771
+ page = data.shift.to_i
1772
+ name = data.join(' ').sub(/^\(/,'').sub(/\)$/,'')
1773
+ map[page] = {}
1774
+ map[page]['name'] = name
1775
+ map[page]['data'] = {}
1776
+ else
1777
+ data.each { |entry|
1778
+ wide, char = entry.split(':')
1779
+ char = [char].pack('H*')
1780
+ wide = [wide].pack('H*')
1781
+ if map[page]['data'][char].nil?
1782
+ map[page]['data'][char] = [wide]
1783
+ else
1784
+ map[page]['data'][char].push(wide)
1785
+ end
1786
+ }
1787
+ end
1788
+ }
1789
+ @@codepage_map_cache = map
1790
+ end
1791
+
1792
+ # @param str [String] Data to checksum
1793
+ # @return [Fixnum] 8-bit checksum
1794
+ def self.checksum8(str)
1795
+ (str.unpack("C*").inject(:+) || 0) % 0x100
1796
+ end
1797
+
1798
+ # @param str [String] Little-endian data to checksum
1799
+ # @return [Fixnum] 16-bit checksum
1800
+ def self.checksum16_le(str)
1801
+ (str.unpack("v*").inject(:+) || 0) % 0x10000
1802
+ end
1803
+
1804
+ # @param str [String] Big-endian data to checksum
1805
+ # @return [Fixnum] 16-bit checksum
1806
+ def self.checksum16_be(str)
1807
+ (str.unpack("n*").inject(:+) || 0) % 0x10000
1808
+ end
1809
+
1810
+ # @param str [String] Little-endian data to checksum
1811
+ # @return [Fixnum] 32-bit checksum
1812
+ def self.checksum32_le(str)
1813
+ (str.unpack("V*").inject(:+) || 0) % 0x100000000
1814
+ end
1815
+
1816
+ # @param str [String] Big-endian data to checksum
1817
+ # @return [Fixnum] 32-bit checksum
1818
+ def self.checksum32_be(str)
1819
+ (str.unpack("N*").inject(:+) || 0) % 0x100000000
1820
+ end
1333
1821
 
1334
1822
  end
1335
1823
  end