2006-11-09 19:54:40 +00:00
require 'digest/md5'
2006-01-02 07:49:52 +00:00
require 'stringio'
2005-09-30 06:48:52 +00:00
2006-01-03 04:07:20 +00:00
begin
2007-02-16 18:49:07 +00:00
require 'iconv'
2006-01-03 04:07:20 +00:00
require 'zlib'
rescue LoadError
end
2005-07-10 07:15:20 +00:00
module Rex
###
#
# This class formats text in various fashions and also provides
# a mechanism for wrapping text at a given column.
#
###
module Text
2009-03-09 05:18:33 +00:00
@@codepage_map_cache = nil
2010-02-12 05:08:16 +00:00
2005-09-30 06:40:35 +00:00
##
#
# Constants
#
##
2006-02-22 23:29:34 +00:00
2006-04-21 03:59:07 +00:00
States = [ " AK " , " AL " , " AR " , " AZ " , " CA " , " CO " , " CT " , " DE " , " FL " , " GA " , " HI " ,
" IA " , " ID " , " IL " , " IN " , " KS " , " KY " , " LA " , " MA " , " MD " , " ME " , " MI " , " MN " ,
" MO " , " MS " , " MT " , " NC " , " ND " , " NE " , " NH " , " NJ " , " NM " , " NV " , " NY " , " OH " ,
" OK " , " OR " , " PA " , " RI " , " SC " , " SD " , " TN " , " TX " , " UT " , " VA " , " VT " , " WA " ,
" WI " , " WV " , " WY " ]
2005-09-30 06:40:35 +00:00
UpperAlpha = " ABCDEFGHIJKLMNOPQRSTUVWXYZ "
LowerAlpha = " abcdefghijklmnopqrstuvwxyz "
Numerals = " 0123456789 "
Alpha = UpperAlpha + LowerAlpha
AlphaNumeric = Alpha + Numerals
2009-06-02 23:36:58 +00:00
HighAscii = [ * ( 0x80 .. 0xff ) ] . pack ( " C* " )
2011-07-17 17:32:52 +00:00
LowAscii = [ * ( 0x00 .. 0x1f ) ] . pack ( " C* " )
2005-09-30 06:40:35 +00:00
DefaultWrap = 60
2009-10-20 17:24:33 +00:00
AllChars = [ * ( 0x00 .. 0xff ) ] . pack ( " C* " )
2011-10-16 09:42:04 +00:00
Punctuation = ( [ * ( 0x21 .. 0x2f ) ] + [ * ( 0x3a .. 0x3F ) ] + [ * ( 0x5b .. 0x60 ) ] + [ * ( 0x7b .. 0x7e ) ] ) . flatten . pack ( " C* " )
2005-07-10 07:15:20 +00:00
2005-12-09 00:03:52 +00:00
DefaultPatternSets = [ Rex :: Text :: UpperAlpha , Rex :: Text :: LowerAlpha , Rex :: Text :: Numerals ]
2010-07-05 13:38:39 +00:00
2010-06-03 17:35:58 +00:00
# In case Iconv isn't loaded
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 ]
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 ]
2010-02-12 05:08:16 +00:00
2005-09-30 06:40:35 +00:00
##
#
# Serialization
#
##
2005-07-10 19:21:40 +00:00
2005-07-10 07:15:20 +00:00
#
# Converts a raw string into a ruby buffer
#
2008-12-20 07:40:27 +00:00
def self . to_ruby ( str , wrap = DefaultWrap , name = " buf " )
return hexify ( str , wrap , '"' , '" +' , " #{ name } = \n " , '"' )
2005-07-10 07:15:20 +00:00
end
2005-07-10 19:21:40 +00:00
#
# Creates a ruby-style comment
#
def self . to_ruby_comment ( str , wrap = DefaultWrap )
return wordwrap ( str , 0 , wrap , '' , '# ' )
end
2005-07-10 07:15:20 +00:00
#
# Converts a raw string into a C buffer
#
2005-07-10 19:21:40 +00:00
def self . to_c ( str , wrap = DefaultWrap , name = " buf " )
return hexify ( str , wrap , '"' , '"' , " unsigned char #{ name } [] = \n " , '";' )
end
#
# Creates a c-style comment
#
def self . to_c_comment ( str , wrap = DefaultWrap )
return " /* \n " + wordwrap ( str , 0 , wrap , '' , ' * ' ) + " */ \n "
2005-07-10 07:15:20 +00:00
end
2010-02-12 05:08:16 +00:00
2006-07-31 04:05:20 +00:00
#
# Creates a javascript-style comment
#
def self . to_js_comment ( str , wrap = DefaultWrap )
return wordwrap ( str , 0 , wrap , '' , '// ' )
end
2010-02-12 05:08:16 +00:00
2005-07-10 07:15:20 +00:00
#
# Converts a raw string into a perl buffer
#
2008-12-20 07:40:27 +00:00
def self . to_perl ( str , wrap = DefaultWrap , name = " buf " )
return hexify ( str , wrap , '"' , '" .' , " my $ #{ name } = \n " , '";' )
2005-07-10 07:15:20 +00:00
end
2011-11-11 08:13:17 +00:00
#
# Converts a raw string into a Bash buffer
#
def self . to_bash ( str , wrap = DefaultWrap , name = " buf " )
return hexify ( str , wrap , '$\'' , '\'\\' , " export #{ name } = \\ \n " , '\'' )
end
2007-05-07 04:42:11 +00:00
#
# Converts a raw string into a java byte array
#
2008-12-20 07:40:27 +00:00
def self . to_java ( str , name = " shell " )
buff = " byte #{ name } [] = new byte[] \n { \n "
2007-05-07 04:42:11 +00:00
cnt = 0
max = 0
str . unpack ( 'C*' ) . each do | c |
buff << " , " if max > 0
buff << " \t " if max == 0
buff << sprintf ( '(byte) 0x%.2x' , c )
max += 1
2010-02-12 05:08:16 +00:00
cnt += 1
if ( max > 7 )
buff << " , \n " if cnt != str . length
2007-05-07 04:42:11 +00:00
max = 0
end
end
buff << " \n }; \n "
2010-02-12 05:08:16 +00:00
return buff
2007-05-07 04:42:11 +00:00
end
2010-02-12 05:08:16 +00:00
2005-07-10 19:21:40 +00:00
#
# Creates a perl-style comment
#
def self . to_perl_comment ( str , wrap = DefaultWrap )
return wordwrap ( str , 0 , wrap , '' , '# ' )
end
2011-11-11 08:13:17 +00:00
#
# Creates a Bash-style comment
#
def self . to_bash_comment ( str , wrap = DefaultWrap )
return wordwrap ( str , 0 , wrap , '' , '# ' )
end
2005-07-10 07:15:20 +00:00
#
# Returns the raw string
#
def self . to_raw ( str )
return str
end
2007-02-11 09:22:06 +00:00
#
# Converts ISO-8859-1 to UTF-8
#
def self . to_utf8 ( str )
2007-02-16 18:49:07 +00:00
begin
Iconv . iconv ( " utf-8 " , " iso-8859-1 " , str ) . join ( " " )
rescue
raise :: RuntimeError , " Your installation does not support iconv (needed for utf8 conversion) "
end
2007-02-11 09:22:06 +00:00
end
2010-01-25 15:58:24 +00:00
#
# Converts ASCII to EBCDIC
#
2010-06-03 17:28:45 +00:00
class IllegalSequence < ArgumentError ; end
# A native implementation of the ASCII->EBCDIC table, used to fall back from using
# Iconv
def self . to_ebcdic_rex ( str )
new_str = [ ]
2010-07-05 13:38:39 +00:00
str . each_byte do | x |
2010-06-03 17:35:58 +00:00
if Iconv_ASCII . index ( x . chr )
new_str << Iconv_EBCDIC [ Iconv_ASCII . index ( x . chr ) ]
2010-06-03 17:28:45 +00:00
else
raise Rex :: Text :: IllegalSequence , ( " \\ x%x " % x )
end
end
new_str . join
end
# A native implementation of the EBCDIC->ASCII table, used to fall back from using
# Iconv
def self . from_ebcdic_rex ( str )
new_str = [ ]
2010-07-05 13:38:39 +00:00
str . each_byte do | x |
2010-06-03 17:35:58 +00:00
if Iconv_EBCDIC . index ( x . chr )
new_str << Iconv_ASCII [ Iconv_EBCDIC . index ( x . chr ) ]
2010-06-03 17:28:45 +00:00
else
raise Rex :: Text :: IllegalSequence , ( " \\ x%x " % x )
end
end
new_str . join
end
2010-01-25 15:58:24 +00:00
def self . to_ebcdic ( str )
begin
Iconv . iconv ( " EBCDIC-US " , " ASCII " , str ) . first
rescue :: Iconv :: IllegalSequence = > e
raise e
rescue
2010-06-03 17:28:45 +00:00
self . to_ebcdic_rex ( str )
2010-01-25 15:58:24 +00:00
end
end
2010-02-12 05:08:16 +00:00
#
2010-01-25 15:58:24 +00:00
# Converts EBCIDC to ASCII
#
def self . from_ebcdic ( str )
begin
Iconv . iconv ( " ASCII " , " EBCDIC-US " , str ) . first
rescue :: Iconv :: IllegalSequence = > e
raise e
rescue
2010-06-03 17:28:45 +00:00
self . from_ebcdic_rex ( str )
2010-01-25 15:58:24 +00:00
end
end
2010-02-12 05:08:16 +00:00
2006-07-31 02:50:41 +00:00
#
# Returns a unicode escaped string for Javascript
#
def self . to_unescape ( data , endian = ENDIAN_LITTLE )
data << " \x41 " if ( data . length % 2 != 0 )
dptr = 0
buff = ''
while ( dptr < data . length )
2009-06-20 14:26:22 +00:00
c1 = data [ dptr , 1 ] . unpack ( " C* " ) [ 0 ]
2006-07-31 02:50:41 +00:00
dptr += 1
2009-06-20 14:26:22 +00:00
c2 = data [ dptr , 1 ] . unpack ( " C* " ) [ 0 ]
2006-07-31 02:50:41 +00:00
dptr += 1
2010-02-12 05:08:16 +00:00
2006-07-31 02:50:41 +00:00
if ( endian == ENDIAN_LITTLE )
buff << sprintf ( '%%u%.2x%.2x' , c2 , c1 )
else
buff << sprintf ( '%%u%.2x%.2x' , c1 , c2 )
end
end
2010-02-12 05:08:16 +00:00
return buff
2006-07-31 02:50:41 +00:00
end
2005-07-10 07:15:20 +00:00
#
# Returns the hex version of the supplied string
#
2006-02-27 19:51:17 +00:00
def self . to_hex ( str , prefix = " \\ x " , count = 1 )
2006-10-29 17:41:19 +00:00
raise :: RuntimeError , " unable to chunk into #{ count } byte chunks " if ( ( str . length % count ) > 0 )
2006-02-27 19:51:17 +00:00
# XXX: Regexp.new is used here since using /.{#{count}}/o would compile
# the regex the first time it is used and never check again. Since we
# want to know how many to capture on every instance, we do it this
# way.
2009-11-02 17:09:13 +00:00
return str . unpack ( 'H*' ) [ 0 ] . gsub ( Regexp . new ( " .{ #{ count * 2 } } " , nil , 'n' ) ) { | s | prefix + s }
2005-07-10 07:15:20 +00:00
end
2010-07-13 18:52:27 +00:00
#
# Returns the string with nonprintable hex characters sanitized to ascii. Similiar to to_hex,
# but regular ASCII is not translated if count is 1.
#
2010-09-01 22:40:07 +00:00
def self . to_hex_ascii ( str , prefix = " \\ x " , count = 1 , suffix = nil )
2010-07-13 18:52:27 +00:00
raise :: RuntimeError , " unable to chunk into #{ count } byte chunks " if ( ( str . length % count ) > 0 )
2011-01-25 19:59:56 +00:00
return str . unpack ( 'H*' ) [ 0 ] . gsub ( Regexp . new ( " .{ #{ count * 2 } } " , nil , 'n' ) ) { | s |
2010-09-02 16:22:48 +00:00
( 0x20 .. 0x7e ) === s . to_i ( 16 ) ? s . to_i ( 16 ) . chr : prefix + s + suffix . to_s
2010-07-13 18:52:27 +00:00
}
end
2005-07-13 23:01:34 +00:00
#
2010-02-12 05:08:16 +00:00
# Converts standard ASCII text to a unicode string.
2006-02-13 22:52:01 +00:00
#
# Supported unicode types include: utf-16le, utf16-be, utf32-le, utf32-be, utf-7, and utf-8
2010-02-12 05:08:16 +00:00
#
2006-02-13 22:52:01 +00:00
# Providing 'mode' provides hints to the actual encoder as to how it should encode the string. Only UTF-7 and UTF-8 use "mode".
2010-02-12 05:08:16 +00:00
#
2006-02-13 22:52:01 +00:00
# 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.
# to_unicode(str, 'utf-7', 'all')
2010-02-12 05:08:16 +00:00
#
2006-02-13 22:52:01 +00:00
# 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'.
# to_unicode(str, 'utf-8', 'overlong', 2)
#
# 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.
# to_unicode(str, 'utf-8', 'invalid', 2)
#
# utf-7 defaults to 'normal' utf-7 encoding
# utf-8 defaults to 2 byte 'normal' encoding
2010-02-12 05:08:16 +00:00
#
2006-02-22 23:29:34 +00:00
def self . to_unicode ( str = '' , type = 'utf-16le' , mode = '' , size = '' )
2007-09-09 22:10:38 +00:00
return '' if not str
2010-02-12 05:08:16 +00:00
case type
2006-02-13 22:52:01 +00:00
when 'utf-16le'
return str . unpack ( 'C*' ) . pack ( 'v*' )
when 'utf-16be'
return str . unpack ( 'C*' ) . pack ( 'n*' )
when 'utf-32le'
return str . unpack ( 'C*' ) . pack ( 'V*' )
when 'utf-32be'
return str . unpack ( 'C*' ) . pack ( 'N*' )
when 'utf-7'
case mode
when 'all'
return str . gsub ( / . / ) { | a |
2006-02-10 17:30:41 +00:00
out = ''
2006-02-13 22:52:01 +00:00
if 'a' != '+'
2006-02-10 17:30:41 +00:00
out = encode_base64 ( to_unicode ( a , 'utf-16be' ) ) . gsub ( / [= \ r \ n] / , '' )
end
'+' + out + '-'
}
2006-02-13 22:52:01 +00:00
else
2010-02-12 05:08:16 +00:00
return str . gsub ( / [^ \ n \ r \ t \ A-Za-z0-9 \ ' \ ( \ ),-. \/ \ : \ ?] / ) { | a |
2006-02-10 17:30:41 +00:00
out = ''
2006-02-13 22:52:01 +00:00
if a != '+'
2006-02-10 17:30:41 +00:00
out = encode_base64 ( to_unicode ( a , 'utf-16be' ) ) . gsub ( / [= \ r \ n] / , '' )
end
'+' + out + '-'
}
2006-02-13 22:52:01 +00:00
end
when 'utf-8'
2006-02-22 23:29:34 +00:00
if size == ''
size = 2
end
2006-02-13 22:52:01 +00:00
if size > = 2 and size < = 7
string = ''
str . each_byte { | a |
2006-02-14 01:04:06 +00:00
if ( a < 21 || a > 0x7f ) || mode != ''
2006-02-13 22:52:01 +00:00
# ugh. turn a single byte into the binary representation of it, in array form
bin = [ a ] . pack ( 'C' ) . unpack ( 'B8' ) [ 0 ] . split ( / / )
# even more ugh.
2009-10-25 17:18:23 +00:00
bin . collect! { | a_ | a_ . to_i }
2006-02-13 22:52:01 +00:00
out = Array . new ( 8 * size , 0 )
0 . upto ( size - 1 ) { | i |
out [ i ] = 1
out [ i * 8 ] = 1
}
i = 0
byte = 0
bin . reverse . each { | bit |
if i < 6
mod = ( ( ( size * 8 ) - 1 ) - byte * 8 ) - i
out [ mod ] = bit
2010-02-12 05:08:16 +00:00
else
2006-02-13 22:52:01 +00:00
byte = byte + 1
i = 0
redo
end
i = i + 1
}
if mode != ''
case mode
when 'overlong'
# do nothing, since we already handle this as above...
when 'invalid'
done = 0
while done == 0
2006-02-14 01:04:06 +00:00
# the ghetto...
2006-02-13 22:52:01 +00:00
bits = [ 7 , 8 , 15 , 16 , 23 , 24 , 31 , 32 , 41 ]
bits . each { | bit |
bit = ( size * 8 ) - bit
if bit > 1
set = rand ( 2 )
if out [ bit ] != set
out [ bit ] = set
done = 1
end
end
}
end
else
raise TypeError , 'Invalid mode. Only "overlong" and "invalid" are acceptable modes for utf-8'
end
end
2009-03-08 07:55:47 +00:00
string << [ out . join ( '' ) ] . pack ( 'B*' )
2006-02-13 22:52:01 +00:00
else
2009-03-08 07:55:47 +00:00
string << [ a ] . pack ( 'C' )
2006-02-13 22:52:01 +00:00
end
}
return string
2010-02-12 05:08:16 +00:00
else
2006-02-13 22:52:01 +00:00
raise TypeError , 'invalid utf-8 size'
2006-02-10 17:30:41 +00:00
end
2006-02-22 23:29:34 +00:00
when 'uhwtfms' # suggested name from HD :P
load_codepage ( )
string = ''
# overloading mode as codepage
if mode == ''
mode = 1252 # ANSI - Latan 1, default for US installs of MS products
else
mode = mode . to_i
end
2007-09-29 06:47:16 +00:00
if @@codepage_map_cache [ mode ] . nil?
2006-02-22 23:29:34 +00:00
raise TypeError , " Invalid codepage #{ mode } "
end
str . each_byte { | byte |
char = [ byte ] . pack ( 'C*' )
2007-09-29 06:47:16 +00:00
possible = @@codepage_map_cache [ mode ] [ 'data' ] [ char ]
2006-02-22 23:29:34 +00:00
if possible . nil?
raise TypeError , " codepage #{ mode } does not provide an encoding for 0x #{ char . unpack ( 'H*' ) [ 0 ] } "
end
2009-03-08 07:55:47 +00:00
string << possible [ rand ( possible . length ) ]
2006-02-22 23:29:34 +00:00
}
return string
2007-05-14 20:49:35 +00:00
when 'uhwtfms-half' # suggested name from HD :P
load_codepage ( )
string = ''
# overloading mode as codepage
if mode == ''
mode = 1252 # ANSI - Latan 1, default for US installs of MS products
else
2009-07-14 00:01:04 +00:00
mode = mode . to_i
end
if mode != 1252
2009-10-20 17:24:33 +00:00
raise TypeError , " Invalid codepage #{ mode } , only 1252 supported for uhwtfms_half "
2007-05-14 20:49:35 +00:00
end
str . each_byte { | byte |
2009-10-16 18:27:18 +00:00
if ( ( byte > = 33 && byte < = 63 ) || ( byte > = 96 && byte < = 126 ) )
string << " \xFF " + [ byte ^ 32 ] . pack ( 'C' )
elsif ( byte > = 64 && byte < = 95 )
string << " \xFF " + [ byte ^ 96 ] . pack ( 'C' )
else
char = [ byte ] . pack ( 'C' )
2007-09-29 06:47:16 +00:00
possible = @@codepage_map_cache [ mode ] [ 'data' ] [ char ]
2007-05-14 20:49:35 +00:00
if possible . nil?
raise TypeError , " codepage #{ mode } does not provide an encoding for 0x #{ char . unpack ( 'H*' ) [ 0 ] } "
end
2009-03-08 07:55:47 +00:00
string << possible [ rand ( possible . length ) ]
2009-10-16 18:27:18 +00:00
end
2007-05-14 20:49:35 +00:00
}
return string
2010-02-12 05:08:16 +00:00
else
2006-02-13 22:52:01 +00:00
raise TypeError , 'invalid utf type'
end
2005-11-26 02:34:39 +00:00
end
2006-02-27 19:51:17 +00:00
2011-03-07 19:57:53 +00:00
#
# Converts a unicode string to standard ASCII text.
#
def self . to_ascii ( str = '' , type = 'utf-16le' , mode = '' , size = '' )
return '' if not str
case type
when 'utf-16le'
return str . unpack ( 'v*' ) . pack ( 'C*' )
when 'utf-16be'
return str . unpack ( 'n*' ) . pack ( 'C*' )
when 'utf-32le'
return str . unpack ( 'V*' ) . pack ( 'C*' )
when 'utf-32be'
return str . unpack ( 'N*' ) . pack ( 'C*' )
when 'utf-7'
raise TypeError , 'invalid utf type, not yet implemented'
when 'utf-8'
raise TypeError , 'invalid utf type, not yet implemented'
when 'uhwtfms' # suggested name from HD :P
raise TypeError , 'invalid utf type, not yet implemented'
when 'uhwtfms-half' # suggested name from HD :P
raise TypeError , 'invalid utf type, not yet implemented'
else
raise TypeError , 'invalid utf type'
end
end
2010-02-12 05:08:16 +00:00
#
# Encode a string in a manor useful for HTTP URIs and URI Parameters.
2006-02-27 19:51:17 +00:00
#
def self . uri_encode ( str , mode = 'hex-normal' )
2010-02-12 05:08:16 +00:00
return " " if str == nil
2007-03-08 14:08:41 +00:00
2006-02-27 19:51:17 +00:00
return str if mode == 'none' # fast track no encoding
all = / [^ \/ \\ ]+ /
2009-10-16 18:27:18 +00:00
normal = / [^a-zA-Z0-9 \/ \\ \ . \ -]+ /
2007-03-08 14:08:41 +00:00
normal_na = / [a-zA-Z0-9 \/ \\ \ . \ -] /
2010-02-12 05:08:16 +00:00
2009-10-16 18:27:18 +00:00
case mode
when 'hex-normal'
return str . gsub ( normal ) { | s | Rex :: Text . to_hex ( s , '%' ) }
when 'hex-all'
return str . gsub ( all ) { | s | Rex :: Text . to_hex ( s , '%' ) }
when 'hex-random'
res = ''
str . each_byte do | c |
b = c . chr
2010-02-12 05:08:16 +00:00
res << ( ( rand ( 2 ) == 0 ) ?
2009-10-16 18:27:18 +00:00
b . gsub ( all ) { | s | Rex :: Text . to_hex ( s , '%' ) } :
b . gsub ( normal ) { | s | Rex :: Text . to_hex ( s , '%' ) } )
end
return res
when 'u-normal'
return str . gsub ( normal ) { | s | Rex :: Text . to_hex ( Rex :: Text . to_unicode ( s , 'uhwtfms' ) , '%u' , 2 ) }
when 'u-all'
return str . gsub ( all ) { | s | Rex :: Text . to_hex ( Rex :: Text . to_unicode ( s , 'uhwtfms' ) , '%u' , 2 ) }
when 'u-random'
res = ''
str . each_byte do | c |
b = c . chr
2010-02-12 05:08:16 +00:00
res << ( ( rand ( 2 ) == 0 ) ?
2009-10-16 18:27:18 +00:00
b . gsub ( all ) { | s | Rex :: Text . to_hex ( Rex :: Text . to_unicode ( s , 'uhwtfms' ) , '%u' , 2 ) } :
b . gsub ( normal ) { | s | Rex :: Text . to_hex ( Rex :: Text . to_unicode ( s , 'uhwtfms' ) , '%u' , 2 ) } )
end
2010-02-12 05:08:16 +00:00
return res
2009-10-16 18:27:18 +00:00
when 'u-half'
return str . gsub ( all ) { | s | Rex :: Text . to_hex ( Rex :: Text . to_unicode ( s , 'uhwtfms-half' ) , '%u' , 2 ) }
else
raise TypeError , 'invalid mode'
end
2006-02-27 19:51:17 +00:00
end
2010-02-12 05:08:16 +00:00
#
2010-03-17 17:47:08 +00:00
# Encode a string in a manner useful for HTTP URIs and URI Parameters.
2010-02-12 05:08:16 +00:00
#
2006-07-24 19:25:59 +00:00
def self . html_encode ( str , mode = 'hex' )
case mode
when 'hex'
2010-02-12 05:08:16 +00:00
return str . unpack ( 'C*' ) . collect { | i | " & # x " + ( " %.2x " % i ) + " ; " } . join
2006-07-24 19:25:59 +00:00
when 'int'
2010-02-12 05:08:16 +00:00
return str . unpack ( 'C*' ) . collect { | i | " & # " + i . to_s + " ; " } . join
2006-07-24 19:25:59 +00:00
when 'int-wide'
2010-02-12 05:08:16 +00:00
return str . unpack ( 'C*' ) . collect { | i | " & # " + ( " 0 " * ( 7 - i . to_s . length ) ) + i . to_s + " ; " } . join
else
2006-07-24 19:25:59 +00:00
raise TypeError , 'invalid mode'
end
end
2008-04-22 18:48:21 +00:00
2010-09-01 22:40:07 +00:00
#
# Encode an ASCII string so it's safe for XML. It's a wrapper for to_hex_ascii.
#
def self . xml_char_encode ( str )
2010-09-01 23:26:35 +00:00
self . to_hex_ascii ( str , " & # x " , 1 , " ; " )
2010-09-01 22:40:07 +00:00
end
2010-02-12 05:08:16 +00:00
#
2008-04-22 18:48:21 +00:00
# Decode a URI encoded string
#
def self . uri_decode ( str )
str . gsub ( / (%[a-z0-9]{2}) /i ) { | c | [ c [ 1 , 2 ] ] . pack ( " H* " ) }
end
2010-02-12 05:08:16 +00:00
2007-02-18 22:35:07 +00:00
#
# Converts a string to random case
#
def self . to_rand_case ( str )
buf = str . dup
0 . upto ( str . length ) do | i |
buf [ i , 1 ] = rand ( 2 ) == 0 ? str [ i , 1 ] . upcase : str [ i , 1 ] . downcase
end
return buf
end
2006-07-24 19:25:59 +00:00
2010-03-17 17:47:08 +00:00
#
# Takes a string, and returns an array of all mixed case versions.
#
# Example:
#
# >> Rex::Text.to_mixed_case_array "abc1"
# => ["abc1", "abC1", "aBc1", "aBC1", "Abc1", "AbC1", "ABc1", "ABC1"]
#
def self . to_mixed_case_array ( str )
letters = [ ]
str . scan ( / . / ) . each { | l | letters << [ l . downcase , l . upcase ] }
coords = [ ]
( 1 << str . size ) . times { | i | coords << ( " %0 #{ str . size } b " % i ) }
mixed = [ ]
2010-05-09 02:58:55 +00:00
coords . each do | coord |
2010-03-17 17:47:08 +00:00
c = coord . scan ( / . / ) . map { | x | x . to_i }
this_str = " "
c . each_with_index { | d , i | this_str << letters [ i ] [ d ] }
mixed << this_str
end
return mixed . uniq
end
2007-04-11 22:23:32 +00:00
#
# Converts a string a nicely formatted hex dump
#
def self . to_hex_dump ( str , width = 16 )
buf = ''
idx = 0
cnt = 0
snl = false
lst = 0
2010-02-12 05:08:16 +00:00
2007-04-11 22:23:32 +00:00
while ( idx < str . length )
2010-02-12 05:08:16 +00:00
2007-04-11 22:23:32 +00:00
chunk = str [ idx , width ]
line = chunk . unpack ( " H* " ) [ 0 ] . scan ( / .. / ) . join ( " " )
2010-02-12 05:08:16 +00:00
buf << line
2007-04-11 22:23:32 +00:00
if ( lst == 0 )
lst = line . length
buf << " " * 4
else
buf << " " * ( ( lst - line . length ) + 4 ) . abs
end
2010-02-12 05:08:16 +00:00
2007-04-11 22:23:32 +00:00
chunk . unpack ( " C* " ) . each do | c |
2009-12-18 20:40:08 +00:00
if ( c > 0x1f and c < 0x7f )
2007-04-11 22:23:32 +00:00
buf << c . chr
else
buf << " . "
end
end
2010-02-12 05:08:16 +00:00
2007-04-11 22:23:32 +00:00
buf << " \n "
2010-02-12 05:08:16 +00:00
2007-04-11 22:23:32 +00:00
idx += width
end
2010-02-12 05:08:16 +00:00
2007-04-11 22:23:32 +00:00
buf << " \n "
end
2010-02-12 05:08:16 +00:00
2005-11-26 02:34:39 +00:00
#
2005-07-13 23:01:34 +00:00
# Converts a hex string to a raw string
#
def self . hex_to_raw ( str )
2005-07-18 14:39:00 +00:00
[ str . downcase . gsub ( / ' / , '' ) . gsub ( / \\ ?x([a-f0-9][a-f0-9]) / , '\1' ) ] . pack ( " H* " )
2005-07-13 23:01:34 +00:00
end
2011-04-07 21:59:32 +00:00
#
# Turn non-printable chars into hex representations, leaving others alone
#
# If +whitespace+ is true, converts whitespace (0x20, 0x09, etc) to hex as
# well.
#
def self . ascii_safe_hex ( str , whitespace = false )
if whitespace
str . gsub ( / ([ \ x00- \ x20 \ x80- \ xFF]) / ) { | x | " \\ x%.2x " % x . unpack ( " C* " ) [ 0 ] }
else
str . gsub ( / ([ \ x00- \ x08 \ x0b \ x0c \ x0e- \ x1f \ x80- \ xFF]) /n ) { | x | " \\ x%.2x " % x . unpack ( " C* " ) [ 0 ] }
end
end
2005-07-10 07:15:20 +00:00
#
# Wraps text at a given column using a supplied indention
#
2005-07-10 19:21:40 +00:00
def self . wordwrap ( str , indent = 0 , col = DefaultWrap , append = '' , prepend = '' )
2005-07-10 07:15:20 +00:00
return str . gsub ( / .{1, #{ col - indent } }(?: \ s| \ Z) / ) {
( ( " " * indent ) + prepend + $& + append + 5 . chr ) . gsub ( / \ n \ 005 / , " \n " ) . gsub ( / \ 005 / , " \n " ) }
end
#
# Converts a string to a hex version with wrapping support
#
2005-07-10 19:21:40 +00:00
def self . hexify ( str , col = DefaultWrap , line_start = '' , line_end = '' , buf_start = '' , buf_end = '' )
2005-07-10 07:15:20 +00:00
output = buf_start
cur = 0
count = 0
new_line = true
# Go through each byte in the string
str . each_byte { | byte |
count += 1
append = ''
# If this is a new line, prepend with the
# line start text
if ( new_line == true )
2009-03-08 07:55:47 +00:00
append << line_start
2005-07-10 07:15:20 +00:00
new_line = false
end
# Append the hexified version of the byte
2009-03-08 07:55:47 +00:00
append << sprintf ( " \\ x%.2x " , byte )
2005-07-10 07:15:20 +00:00
cur += append . length
# If we're about to hit the column or have gone past it,
# time to finish up this line
2010-01-14 18:15:15 +00:00
if ( ( cur + line_end . length > = col ) or ( cur + buf_end . length > = col ) )
2005-07-10 07:15:20 +00:00
new_line = true
cur = 0
# If this is the last byte, use the buf_end instead of
# line_end
if ( count == str . length )
2009-03-08 07:55:47 +00:00
append << buf_end + " \n "
2005-07-10 07:15:20 +00:00
else
2009-03-08 07:55:47 +00:00
append << line_end + " \n "
2005-07-10 07:15:20 +00:00
end
end
2009-03-08 07:55:47 +00:00
output << append
2005-07-10 07:15:20 +00:00
}
# If we were in the middle of a line, finish the buffer at this point
if ( new_line == false )
2009-03-08 07:55:47 +00:00
output << buf_end + " \n "
2010-02-12 05:08:16 +00:00
end
2005-07-10 07:15:20 +00:00
return output
end
2005-09-30 06:40:35 +00:00
2005-09-30 06:48:52 +00:00
##
#
# Transforms
#
##
#
# Base64 encoder
#
2007-04-02 06:23:14 +00:00
def self . encode_base64 ( str , delim = '' )
2011-10-05 01:42:14 +00:00
[ str . to_s ] . pack ( " m " ) . gsub ( / \ s+ / , delim )
2005-09-30 06:48:52 +00:00
end
#
# Base64 decoder
#
def self . decode_base64 ( str )
2011-10-05 01:42:14 +00:00
str . to_s . unpack ( " m " ) [ 0 ]
2005-09-30 06:48:52 +00:00
end
#
# Raw MD5 digest of the supplied string
#
def self . md5_raw ( str )
2010-02-12 05:08:16 +00:00
Digest :: MD5 . digest ( str )
2005-09-30 06:48:52 +00:00
end
#
# Hexidecimal MD5 digest of the supplied string
#
def self . md5 ( str )
2006-11-09 19:54:40 +00:00
Digest :: MD5 . hexdigest ( str )
2005-09-30 06:48:52 +00:00
end
2011-06-30 06:52:52 +00:00
#
# Convert hex-encoded characters to literals.
# Example: "AA\\x42CC" becomes "AABCC"
#
def self . dehex ( str )
return str unless str . respond_to? :match
return str unless str . respond_to? :gsub
regex = / \ x5cx[0-9a-f]{2} /mi
if str . match ( regex )
str . gsub ( regex ) { | x | x [ 2 , 2 ] . to_i ( 16 ) . chr }
else
str
end
end
#
# Convert and replace hex-encoded characters to literals.
#
def self . dehex! ( str )
return str unless str . respond_to? :match
return str unless str . respond_to? :gsub
regex = / \ x5cx[0-9a-f]{2} /mi
str . gsub! ( regex ) { | x | x [ 2 , 2 ] . to_i ( 16 ) . chr }
end
2007-09-25 01:50:05 +00:00
2005-09-30 06:40:35 +00:00
##
#
# Generators
#
##
2006-08-14 08:55:37 +00:00
2007-02-18 22:35:07 +00:00
2006-08-14 08:55:37 +00:00
# Generates a random character.
def self . rand_char ( bad , chars = AllChars )
2010-02-12 05:08:16 +00:00
rand_text ( 1 , bad , chars )
2006-08-14 08:55:37 +00:00
end
2010-02-12 05:08:16 +00:00
2005-07-18 01:47:18 +00:00
# Base text generator method
def self . rand_base ( len , bad , * foo )
2010-05-09 02:58:55 +00:00
cset = ( foo . join . unpack ( " C* " ) - bad . to_s . unpack ( " C* " ) ) . uniq
2010-07-05 13:38:39 +00:00
return " " if cset . length == 0
2010-05-09 02:58:55 +00:00
outp = [ ]
len . times { outp << cset [ rand ( cset . length ) ] }
outp . pack ( " C* " )
2005-07-17 10:30:11 +00:00
end
2005-07-18 01:47:18 +00:00
# Generate random bytes of data
2006-01-31 22:25:55 +00:00
def self . rand_text ( len , bad = '' , chars = AllChars )
foo = chars . split ( '' )
2005-07-18 01:47:18 +00:00
rand_base ( len , bad , * foo )
end
# Generate random bytes of alpha data
def self . rand_text_alpha ( len , bad = '' )
foo = [ ]
foo += ( 'A' .. 'Z' ) . to_a
foo += ( 'a' .. 'z' ) . to_a
rand_base ( len , bad , * foo )
end
# Generate random bytes of lowercase alpha data
def self . rand_text_alpha_lower ( len , bad = '' )
rand_base ( len , bad , * ( 'a' .. 'z' ) . to_a )
end
# Generate random bytes of uppercase alpha data
def self . rand_text_alpha_upper ( len , bad = '' )
rand_base ( len , bad , * ( 'A' .. 'Z' ) . to_a )
end
# Generate random bytes of alphanumeric data
def self . rand_text_alphanumeric ( len , bad = '' )
foo = [ ]
foo += ( 'A' .. 'Z' ) . to_a
foo += ( 'a' .. 'z' ) . to_a
foo += ( '0' .. '9' ) . to_a
rand_base ( len , bad , * foo )
end
2005-09-30 06:40:35 +00:00
2010-01-26 02:35:13 +00:00
# Generate random bytes of alphanumeric hex.
def self . rand_text_hex ( len , bad = '' )
foo = [ ]
foo += ( '0' .. '9' ) . to_a
foo += ( 'a' .. 'f' ) . to_a
rand_base ( len , bad , * foo )
end
2007-09-05 13:39:45 +00:00
# Generate random bytes of numeric data
def self . rand_text_numeric ( len , bad = '' )
foo = ( '0' .. '9' ) . to_a
rand_base ( len , bad , * foo )
end
2010-02-12 05:08:16 +00:00
2005-11-24 03:16:10 +00:00
# Generate random bytes of english-like data
def self . rand_text_english ( len , bad = '' )
foo = [ ]
foo += ( 0x21 .. 0x7e ) . map { | c | c . chr }
rand_base ( len , bad , * foo )
end
2010-02-12 05:08:16 +00:00
2009-04-16 03:02:41 +00:00
# Generate random bytes of high ascii data
def self . rand_text_highascii ( len , bad = '' )
foo = [ ]
2009-10-16 18:27:18 +00:00
foo += ( 0x80 .. 0xff ) . map { | c | c . chr }
rand_base ( len , bad , * foo )
end
2005-09-30 06:40:35 +00:00
#
# Creates a pattern that can be used for offset calculation purposes. This
# routine is capable of generating patterns using a supplied set and a
2005-12-09 00:03:52 +00:00
# supplied number of identifiable characters (slots). The supplied sets
# should not contain any duplicate characters or the logic will fail.
2005-09-30 06:40:35 +00:00
#
2010-09-04 00:08:12 +00:00
def self . pattern_create ( length , sets = nil )
2005-12-09 00:03:52 +00:00
buf = ''
idx = 0
offsets = [ ]
2010-09-04 00:08:12 +00:00
2010-09-03 23:48:46 +00:00
# Make sure there's something in sets even if we were given an explicit nil
sets || = [ UpperAlpha , LowerAlpha , Numerals ]
2005-09-30 06:40:35 +00:00
2010-10-15 19:40:33 +00:00
# Return stupid uses
return " " if length . to_i < 1
2011-11-11 08:13:17 +00:00
return sets [ 0 ] [ 0 ] . chr * length if sets . size == 1 and sets [ 0 ] . size == 1
2010-10-15 19:40:33 +00:00
2005-12-09 00:03:52 +00:00
sets . length . times { offsets << 0 }
2005-09-30 06:40:35 +00:00
2005-12-09 00:03:52 +00:00
until buf . length > = length
begin
2009-03-08 07:55:47 +00:00
buf << converge_sets ( sets , 0 , offsets , length )
2005-09-30 06:40:35 +00:00
end
end
2010-02-12 05:08:16 +00:00
2007-09-13 16:11:33 +00:00
# Maximum permutations reached, but we need more data
if ( buf . length < length )
buf = buf * ( length / buf . length . to_f ) . ceil
end
2007-10-18 16:55:23 +00:00
2007-04-03 02:42:30 +00:00
buf [ 0 , length ]
2005-09-30 06:40:35 +00:00
end
2010-10-15 19:40:33 +00:00
# Step through an arbitrary number of sets of bytes to build up a findable pattern.
# This is mostly useful for experimentially determining offset lengths into memory
# structures. Note that the supplied sets should never contain duplicate bytes, or
# else it can become impossible to measure the offset accurately.
def self . patt2 ( len , sets = nil )
buf = " "
counter = [ ]
sets || = [ UpperAlpha , LowerAlpha , Numerals ]
len || = len . to_i
return " " if len . zero?
sets = sets . map { | a | a . split ( / / ) }
sets . size . times { counter << 0 }
0 . upto ( len - 1 ) do | i |
setnum = i % sets . size
2011-01-25 19:59:56 +00:00
2011-09-11 02:42:39 +00:00
#puts counter.inspect
2010-10-15 19:40:33 +00:00
end
return buf
end
2005-09-30 06:40:35 +00:00
#
# Calculate the offset to a pattern
#
2009-11-09 17:50:53 +00:00
def self . pattern_offset ( pattern , value , start = 0 )
2005-09-30 06:40:35 +00:00
if ( value . kind_of? ( String ) )
2009-11-09 17:50:53 +00:00
pattern . index ( value , start )
2005-12-09 00:03:52 +00:00
elsif ( value . kind_of? ( Fixnum ) or value . kind_of? ( Bignum ) )
2009-11-09 17:50:53 +00:00
pattern . index ( [ value ] . pack ( 'V' ) , start )
2005-09-30 06:40:35 +00:00
else
2006-10-29 17:41:19 +00:00
raise :: ArgumentError , " Invalid class for value: #{ value . class } "
2005-09-30 06:40:35 +00:00
end
end
2005-10-01 06:15:39 +00:00
#
# Compresses a string, eliminating all superfluous whitespace before and
# after lines and eliminating all lines.
#
def self . compress ( str )
str . gsub ( / \ n /m , ' ' ) . gsub ( / \ s+ / , ' ' ) . gsub ( / ^ \ s+ / , '' ) . gsub ( / \ s+$ / , '' )
end
2006-01-02 07:49:52 +00:00
2008-04-23 06:54:00 +00:00
#
# Randomize the whitespace in a string
#
def self . randomize_space ( str )
str . gsub ( / \ s+ / ) { | s |
len = rand ( 50 ) + 2
set = " \x09 \x20 \x0d \x0a "
buf = ''
while ( buf . length < len )
2009-10-01 16:01:53 +00:00
buf << set [ rand ( set . length ) , 1 ]
2008-04-23 06:54:00 +00:00
end
2010-02-12 05:08:16 +00:00
2008-04-23 06:54:00 +00:00
buf
}
end
2006-01-19 15:12:22 +00:00
# Returns true if zlib can be used.
def self . zlib_present?
2006-01-03 04:07:20 +00:00
begin
2006-07-18 17:30:43 +00:00
temp = Zlib
2006-01-03 04:07:20 +00:00
return true
rescue
return false
end
end
2010-02-12 05:08:16 +00:00
2006-01-27 05:33:08 +00:00
# backwards compat for just a bit...
def self . gzip_present?
self . zlib_present?
end
2006-01-19 15:12:22 +00:00
2006-01-27 05:33:08 +00:00
#
# Compresses a string using zlib
#
2010-01-21 19:31:17 +00:00
def self . zlib_deflate ( str , level = Zlib :: BEST_COMPRESSION )
2010-01-14 18:15:15 +00:00
if self . zlib_present?
z = Zlib :: Deflate . new ( level )
dst = z . deflate ( str , Zlib :: FINISH )
z . close
return dst
2010-02-12 05:08:16 +00:00
else
2010-01-14 18:15:15 +00:00
raise RuntimeError , " Gzip support is not present. "
end
2006-01-27 05:33:08 +00:00
end
2006-01-19 15:12:22 +00:00
2006-01-27 05:33:08 +00:00
#
# Uncompresses a string using zlib
#
def self . zlib_inflate ( str )
2010-01-14 18:15:15 +00:00
if ( self . zlib_present? )
zstream = Zlib :: Inflate . new
buf = zstream . inflate ( str )
zstream . finish
zstream . close
return buf
else
raise RuntimeError , " Gzip support is not present. "
end
2006-01-27 05:33:08 +00:00
end
2006-01-03 04:07:20 +00:00
2006-01-02 07:49:52 +00:00
#
# Compresses a string using gzip
#
2006-01-05 22:20:28 +00:00
def self . gzip ( str , level = 9 )
2006-01-19 15:12:22 +00:00
raise RuntimeError , " Gzip support is not present. " if ( ! zlib_present? )
2006-01-24 03:59:44 +00:00
raise RuntimeError , " Invalid gzip compression level " if ( level < 1 or level > 9 )
2006-01-03 04:07:20 +00:00
2006-01-27 05:33:08 +00:00
s = " "
2011-01-25 20:03:33 +00:00
s . force_encoding ( 'ASCII-8BIT' ) if s . respond_to? ( :encoding )
2011-01-25 19:59:56 +00:00
gz = Zlib :: GzipWriter . new ( StringIO . new ( s , 'wb' ) , level )
2006-01-27 05:33:08 +00:00
gz << str
gz . close
return s
2006-01-05 22:20:28 +00:00
end
2010-02-12 05:08:16 +00:00
2006-01-27 05:33:08 +00:00
#
2006-01-05 22:20:28 +00:00
# Uncompresses a string using gzip
#
def self . ungzip ( str )
2006-01-19 15:12:22 +00:00
raise RuntimeError , " Gzip support is not present. " if ( ! zlib_present? )
2006-01-05 22:20:28 +00:00
2006-01-27 05:33:08 +00:00
s = " "
2011-01-25 20:03:33 +00:00
s . force_encoding ( 'ASCII-8BIT' ) if s . respond_to? ( :encoding )
2011-01-25 19:59:56 +00:00
gz = Zlib :: GzipReader . new ( StringIO . new ( str , 'rb' ) )
2006-01-27 05:33:08 +00:00
s << gz . read
gz . close
return s
2006-01-02 07:49:52 +00:00
end
2010-02-12 05:08:16 +00:00
2005-11-09 04:18:08 +00:00
#
# Return the index of the first badchar in data, otherwise return
# nil if there wasn't any badchar occurences.
#
2005-11-26 11:16:36 +00:00
def self . badchar_index ( data , badchars = '' )
2010-01-26 02:39:43 +00:00
badchars . unpack ( " C* " ) . each { | badchar |
2009-06-02 23:36:58 +00:00
pos = data . index ( badchar . chr )
2005-11-09 04:18:08 +00:00
return pos if pos
}
return nil
end
#
# This method removes bad characters from a string.
#
2005-11-26 11:16:36 +00:00
def self . remove_badchars ( data , badchars = '' )
2005-11-09 04:18:08 +00:00
data . delete ( badchars )
end
2005-11-27 18:42:44 +00:00
#
# This method returns all chars but the supplied set
#
2005-12-02 00:49:46 +00:00
def self . charset_exclude ( keepers )
2005-11-27 18:42:44 +00:00
[ * ( 0 .. 255 ) ] . pack ( 'C*' ) . delete ( keepers )
end
2006-01-17 04:09:40 +00:00
#
# Shuffles a byte stream
#
def self . shuffle_s ( str )
shuffle_a ( str . unpack ( " C* " ) ) . pack ( " C* " )
end
#
# Performs a Fisher-Yates shuffle on an array
#
def self . shuffle_a ( arr )
len = arr . length
max = len - 1
cyc = [ * ( 0 .. max ) ]
for d in cyc
e = rand ( d + 1 )
next if e == d
f = arr [ d ] ;
g = arr [ e ] ;
arr [ d ] = g ;
arr [ e ] = f ;
end
return arr
end
2008-10-22 22:43:13 +00:00
# Permute the case of a word
def self . permute_case ( word , idx = 0 )
res = [ ]
if ( ( UpperAlpha + LowerAlpha ) . index ( word [ idx , 1 ] ) )
word_ucase = word . dup
word_ucase [ idx , 1 ] = word [ idx , 1 ] . upcase
2010-02-12 05:08:16 +00:00
2008-10-22 22:43:13 +00:00
word_lcase = word . dup
word_lcase [ idx , 1 ] = word [ idx , 1 ] . downcase
2010-02-12 05:08:16 +00:00
2008-10-22 22:43:13 +00:00
if ( idx == word . length )
return [ word ]
else
res << permute_case ( word_ucase , idx + 1 )
res << permute_case ( word_lcase , idx + 1 )
end
else
res << permute_case ( word , idx + 1 )
end
2010-02-12 05:08:16 +00:00
2008-10-22 22:43:13 +00:00
res . flatten
end
2006-04-21 03:59:07 +00:00
# Generate a random hostname
def self . rand_hostname
host = [ ]
( rand ( 5 ) + 1 ) . times {
host . push ( Rex :: Text . rand_text_alphanumeric ( rand ( 10 ) + 1 ) )
}
d = [ 'com' , 'net' , 'org' , 'gov' ]
host . push ( d [ rand ( d . size ) ] )
host . join ( '.' ) . downcase
end
# Generate a state
def self . rand_state ( )
States [ rand ( States . size ) ]
end
2008-08-13 01:44:37 +00:00
#
# Calculate the ROR13 hash of a given string
#
def self . ror13_hash ( name )
hash = 0
name . unpack ( " C* " ) . each { | c | hash = ror ( hash , 13 ) ; hash += c }
hash
end
#
# Rotate a 32-bit value to the right by cnt bits
#
def self . ror ( val , cnt )
bits = [ val ] . pack ( " N " ) . unpack ( " B32 " ) [ 0 ] . split ( / / )
1 . upto ( cnt ) do | c |
bits . unshift ( bits . pop )
end
[ bits . join ] . pack ( " B32 " ) . unpack ( " N " ) [ 0 ]
end
2010-02-12 05:08:16 +00:00
2008-08-13 01:44:37 +00:00
#
# Rotate a 32-bit value to the left by cnt bits
#
def self . rol ( val , cnt )
bits = [ val ] . pack ( " N " ) . unpack ( " B32 " ) [ 0 ] . split ( / / )
1 . upto ( cnt ) do | c |
bits . push ( bits . shift )
end
[ bits . join ] . pack ( " B32 " ) . unpack ( " N " ) [ 0 ]
end
2011-03-07 19:57:53 +00:00
#
# Split a string by n charachter into an array
#
def self . split_to_a ( str , n )
if n > 0
s = str . dup
until s . empty?
( ret || = [ ] ) . push s . slice! ( 0 , n )
end
else
ret = str
end
ret
end
#
#Pack a value as 64 bit litle endian; does not exist for Array.pack
#
def self . pack_int64le ( val )
[ val & 0x00000000ffffffff , val >> 32 ] . pack ( " V2 " )
end
2011-07-17 17:32:52 +00:00
#
# A custom unicode filter for dealing with multi-byte strings on a 8-bit console
# Punycode would have been more "standard", but it requires valid Unicode chars
#
def self . unicode_filter_encode ( str )
2011-10-18 19:16:48 +00:00
if ( str . to_s . unpack ( " C* " ) & ( LowAscii + HighAscii + " \x7f " ) . unpack ( " C* " ) ) . length > 0
2011-07-17 17:32:52 +00:00
str = " $U$ " + str . unpack ( " C* " ) . select { | c | c < 0x7f and c > 0x1f and c != 0x2d } . pack ( " C* " ) + " -0x " + str . unpack ( " H* " ) [ 0 ]
else
str
end
end
def self . unicode_filter_decode ( str )
2011-10-18 19:16:48 +00:00
str . to_s . gsub ( / \ $U \ $([ \ x20- \ x2c \ x2e- \ x7E]*) \ -0x([A-Fa-f0-9]+) / ) { | m | [ $2 ] . pack ( " H* " ) }
2011-07-17 17:32:52 +00:00
end
2008-08-13 01:44:37 +00:00
2005-12-09 00:03:52 +00:00
protected
def self . converge_sets ( sets , idx , offsets , length ) # :nodoc:
buf = sets [ idx ] [ offsets [ idx ] ] . chr
# If there are more sets after use, converage with them.
if ( sets [ idx + 1 ] )
2009-03-08 07:55:47 +00:00
buf << converge_sets ( sets , idx + 1 , offsets , length )
2005-12-09 00:03:52 +00:00
else
# Increment the current set offset as well as previous ones if we
# wrap back to zero.
while ( idx > = 0 and ( ( offsets [ idx ] = ( offsets [ idx ] + 1 ) % sets [ idx ] . length ) ) == 0 )
idx -= 1
end
# If we reached the point where the idx fell below zero, then that
# means we've reached the maximum threshold for permutations.
if ( idx < 0 )
2010-10-15 19:40:33 +00:00
return buf
2005-12-09 00:03:52 +00:00
end
2010-10-15 19:40:33 +00:00
2005-12-09 00:03:52 +00:00
end
buf
end
2010-02-12 05:08:16 +00:00
2006-02-22 23:29:34 +00:00
def self . load_codepage ( )
2007-09-29 06:47:16 +00:00
return if ( ! @@codepage_map_cache . nil? )
2006-02-22 23:29:34 +00:00
file = File . join ( File . dirname ( __FILE__ ) , 'codepage.map' )
page = ''
name = ''
map = { }
File . open ( file ) . each { | line |
next if line =~ / ^ # /
next if line =~ / ^ \ s*$ /
data = line . split
if data [ 1 ] =~ / ^ \ ( /
page = data . shift . to_i
name = data . join ( ' ' ) . sub ( / ^ \ ( / , '' ) . sub ( / \ )$ / , '' )
map [ page ] = { }
map [ page ] [ 'name' ] = name
map [ page ] [ 'data' ] = { }
else
data . each { | entry |
wide , char = entry . split ( ':' )
char = [ char ] . pack ( 'H*' )
wide = [ wide ] . pack ( 'H*' )
if map [ page ] [ 'data' ] [ char ] . nil?
map [ page ] [ 'data' ] [ char ] = [ wide ]
else
map [ page ] [ 'data' ] [ char ] . push ( wide )
end
}
end
}
2007-09-29 06:47:16 +00:00
@@codepage_map_cache = map
2006-02-22 23:29:34 +00:00
end
2005-12-09 00:03:52 +00:00
2005-07-10 07:15:20 +00:00
end
2008-10-22 22:43:13 +00:00
end
2010-02-12 05:08:16 +00:00