Files
metasploit-gs/lib/rex/encoding/xor/generic.rb
T

147 lines
3.0 KiB
Ruby
Raw Normal View History

2005-12-17 06:46:23 +00:00
#!/usr/bin/env ruby
2005-05-23 00:34:16 +00:00
2005-07-09 21:18:49 +00:00
require 'rex/encoding/xor/exceptions'
2005-11-09 04:18:08 +00:00
require 'rex/text'
2005-06-08 21:39:12 +00:00
2005-05-23 00:34:16 +00:00
module Rex
module Encoding
module Xor
class Generic
def Generic.keysize
# special case:
# 0 means we encode based on the length of the key
# we don't enforce any perticular key length
return 0
end
#
# Now for some internal check methods
#
# hook stylies!
# return index of offending byte or nil
def Generic._check(data, key, badchars)
return _check_key(key, badchars) || _check_encode(data, key, badchars)
end
def Generic._check_key(key, badchars)
2005-11-09 04:18:08 +00:00
return Rex::Text.badchar_index(key, badchars)
end
def Generic._check_encode(data, key, badchars)
2005-11-09 04:18:08 +00:00
return Rex::Text.badchar_index(encode(data, key), badchars)
end
2005-05-24 06:50:46 +00:00
def Generic.find_key(data, badchars)
return _find_good_key(data, _find_bad_keys(data, badchars), badchars)
2005-05-24 06:50:46 +00:00
end
# !!! xxx MAKE THESE BITCHE PRIVATE
#
# Find a list of bytes that can't be valid xor keys, from the data and badchars.
# This returns a Array of hashes, length keysize
#
def Generic._find_bad_keys(data, badchars)
ksize = keysize
# array of hashes for the bad characters based
# on their position in the data
badkeys = [ ]
ksize.times { badkeys << { } }
badchars.each_byte { |badchar|
pos = 0
data.each_byte { |char|
badkeys[pos % ksize][char ^ badchar] = true
pos += 1
}
}
return badkeys
end
#
# (Hopefully) find a good key, from badkeys and badchars
#
def Generic._find_good_key(data, badkeys, badchars)
2005-05-24 06:50:46 +00:00
ksize = keysize
strip = 0
key = ""
while strip < keysize
kbyte = rand(256)
catch(:found_kbyte) do
256.times {
if !badkeys[strip][kbyte] && !badchars[kbyte.chr]
throw :found_kbyte
end
kbyte = (kbyte + 1) & 0xff
}
2005-06-08 21:39:12 +00:00
raise KeySearchError, "Exhausted byte space for strip #{strip}!", caller
2005-05-24 06:50:46 +00:00
end
key << kbyte
strip += 1
end
# ok, we should have a good key now, lets double check...
2005-06-09 04:25:40 +00:00
if _check(data, key, badchars)
2005-06-08 21:39:12 +00:00
raise KeySearchError, "Key found, but bad character check failed!", caller
end
2005-05-24 06:50:46 +00:00
return key
2005-05-24 03:58:47 +00:00
end
2005-05-23 00:34:16 +00:00
def Generic.encode(buf, key)
if !key.kind_of?(String)
2005-06-08 21:39:12 +00:00
raise ::ArgumentError, "Key must be a string!", caller
2005-05-23 00:34:16 +00:00
end
2005-05-24 03:58:47 +00:00
len = key.length
if len == 0
2005-06-08 21:39:12 +00:00
raise ::ArgumentError, "Zero key length!", caller
2005-05-24 03:58:47 +00:00
end
2005-05-23 00:34:16 +00:00
if keysize != 0 && keysize != len
2005-06-08 21:39:12 +00:00
raise ::ArgumentError, "Key length #{len}, expected #{keysize}", caller
2005-05-23 00:34:16 +00:00
end
encoded = ""
pos = 0
while pos < buf.length
encoded += (buf[pos,1].unpack("C*")[0] ^ key[pos % len, 1].unpack("C*")[0]).chr
2005-06-09 20:20:08 +00:00
key = _encode_mutate_key(buf, key, pos, len)
2005-05-24 03:58:47 +00:00
pos += 1
2005-05-23 00:34:16 +00:00
end
2005-06-09 18:08:06 +00:00
return [ encoded, key ]
2005-05-23 00:34:16 +00:00
end
# kind of ghetto, but very convenient for mutating keys
# by default, do no key mutations
def Generic._encode_mutate_key(buf, key, pos, len)
return key
end
2005-05-24 03:58:47 +00:00
# maybe a bit a smaller of method name?
2005-06-09 04:25:40 +00:00
def Generic.find_key_and_encode(data, badchars)
2005-06-09 18:08:06 +00:00
key = find_key(data, badchars)
enc, fkey = encode(data, key)
return [ enc, key, fkey ]
2005-05-24 03:58:47 +00:00
end
2005-05-23 00:34:16 +00:00
end end end end # Generic/Xor/Encoding/Rex