Merge pull request #38 from XeroHawk/alpha2_fix
Ported over the Issue 3190 SVN changes for unicode_mixed, an old bug that was hiding out in Redmine.unstable
commit
6b06df0d7d
|
@ -8,6 +8,7 @@ module Alpha2
|
||||||
|
|
||||||
class Generic
|
class Generic
|
||||||
|
|
||||||
|
# Note: 'A' is presumed to be accepted, but excluded from the accepted characters, because it serves as the terminator
|
||||||
def Generic.default_accepted_chars ; ('a' .. 'z').to_a + ('B' .. 'Z').to_a + ('0' .. '9').to_a ; end
|
def Generic.default_accepted_chars ; ('a' .. 'z').to_a + ('B' .. 'Z').to_a + ('0' .. '9').to_a ; end
|
||||||
|
|
||||||
def Generic.gen_decoder_prefix(reg, offset)
|
def Generic.gen_decoder_prefix(reg, offset)
|
||||||
|
@ -22,14 +23,6 @@ class Generic
|
||||||
return ''
|
return ''
|
||||||
end
|
end
|
||||||
|
|
||||||
def Generic.gen_base_set(ignored_max=0x0f)
|
|
||||||
# 0xf is max for XOR encodings - non-unicode
|
|
||||||
max = 0x0f
|
|
||||||
Rex::Text.shuffle_a(
|
|
||||||
[* ( (0..(max)).map { |i| i *= 0x10 } ) ]
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def Generic.gen_second(block, base)
|
def Generic.gen_second(block, base)
|
||||||
# XOR encoder for ascii - unicode uses additive
|
# XOR encoder for ascii - unicode uses additive
|
||||||
(block^base)
|
(block^base)
|
||||||
|
@ -37,58 +30,41 @@ class Generic
|
||||||
|
|
||||||
def Generic.encode_byte(block, badchars)
|
def Generic.encode_byte(block, badchars)
|
||||||
accepted_chars = default_accepted_chars.dup
|
accepted_chars = default_accepted_chars.dup
|
||||||
|
|
||||||
|
badchars.each_char {|c| accepted_chars.delete(c) } if badchars
|
||||||
# Remove bad chars from the accepted_chars list. Sadly 'A' must be
|
|
||||||
# an accepted char or we'll certainly fail at this point. This could
|
# No, not nipple.
|
||||||
# be fixed later maybe with some recalculation of the encoder stubs...
|
nibble_chars = Array.new(0x10) {[]}
|
||||||
# - Puss
|
accepted_chars.each {|c| nibble_chars[c.unpack('C')[0] & 0x0F].push(c) }
|
||||||
(badchars || '').unpack('C*').map { |c| accepted_chars.delete([c].pack('C')) }
|
|
||||||
|
poss_encodings = []
|
||||||
first = 0
|
|
||||||
second = 1
|
block_low_nibble = block & 0x0F
|
||||||
randbase = 0
|
block_high_nibble = block >> 4
|
||||||
found = nil
|
|
||||||
|
# Get list of chars suitable for expressing lower part of byte
|
||||||
|
first_chars = nibble_chars[block_low_nibble]
|
||||||
gen_base_set(block).each do |randbase_|
|
|
||||||
second = gen_second(block, randbase_)
|
# Build a list of possible encodings
|
||||||
next if second < 0
|
first_chars.each do |first_char|
|
||||||
if accepted_chars.include?([second].pack('C'))
|
first_high_nibble = first_char.unpack('C')[0] >> 4
|
||||||
found = second
|
|
||||||
randbase = randbase_
|
# In the decoding process, the low nibble of the second char gets combined
|
||||||
break
|
# (either ADDed or XORed depending on the encoder) with the high nibble of the first char,
|
||||||
end
|
# and we want the high nibble of our input byte to result
|
||||||
|
second_low_nibble = gen_second(block_high_nibble, first_high_nibble) & 0x0F
|
||||||
|
|
||||||
|
# Find valid second chars for this first char and add each combination to our possible encodings
|
||||||
|
second_chars = nibble_chars[second_low_nibble]
|
||||||
|
second_chars.each {|second_char| poss_encodings.push(second_char + first_char) }
|
||||||
end
|
end
|
||||||
|
|
||||||
if not found
|
if poss_encodings.empty?
|
||||||
msg = "No valid base found for #{"0x%.2x" % block}"
|
raise RuntimeError, "No encoding of #{"0x%.2X" % block} possible with limited character set"
|
||||||
if not accepted_chars.include?([second].pack('C'))
|
|
||||||
msg << ": BadChar to #{second}"
|
|
||||||
elsif second < 1
|
|
||||||
msg << ": Negative"
|
|
||||||
end
|
|
||||||
raise RuntimeError, msg
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if (randbase > 0xa0)
|
# Return a random encoding
|
||||||
# first num must be 4
|
poss_encodings[rand(poss_encodings.length)]
|
||||||
first = (randbase/0x10) + 0x40
|
|
||||||
elsif (randbase == 0x00) || (randbase == 0x10)
|
|
||||||
# first num must be 5
|
|
||||||
first = (randbase/0x10) + 0x50
|
|
||||||
else
|
|
||||||
# pick one at "random"
|
|
||||||
first = (randbase/0x10)
|
|
||||||
if (first % 2) > 0
|
|
||||||
first += 0x40
|
|
||||||
else
|
|
||||||
first += 0x50
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# now add our new bytes :)
|
|
||||||
[first.to_i, second].pack('CC')
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def Generic.encode(buf, reg, offset, badchars = '')
|
def Generic.encode(buf, reg, offset, badchars = '')
|
||||||
|
@ -97,10 +73,10 @@ class Generic
|
||||||
buf.each_byte {
|
buf.each_byte {
|
||||||
|block|
|
|block|
|
||||||
|
|
||||||
encoded += encode_byte(block, badchars)
|
encoded << encode_byte(block, badchars)
|
||||||
}
|
}
|
||||||
|
|
||||||
encoded += add_terminator()
|
encoded << add_terminator()
|
||||||
|
|
||||||
return encoded
|
return encoded
|
||||||
end
|
end
|
||||||
|
|
|
@ -7,12 +7,6 @@ module Encoder
|
||||||
module Alpha2
|
module Alpha2
|
||||||
|
|
||||||
class UnicodeMixed < Generic
|
class UnicodeMixed < Generic
|
||||||
|
|
||||||
def self.gen_base_set(max)
|
|
||||||
Rex::Text.shuffle_a(
|
|
||||||
[* ( (0..(max-1)).map { |i| i *= 0x10 } ) ]
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.gen_second(block, base)
|
def self.gen_second(block, base)
|
||||||
# unicode uses additive encoding
|
# unicode uses additive encoding
|
||||||
|
@ -20,8 +14,8 @@ class UnicodeMixed < Generic
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.gen_decoder_prefix(reg, offset)
|
def self.gen_decoder_prefix(reg, offset)
|
||||||
if (offset > 28)
|
if (offset > 21)
|
||||||
raise "Critical: Offset is greater than 28"
|
raise "Critical: Offset is greater than 21"
|
||||||
end
|
end
|
||||||
|
|
||||||
# offset untested for unicode :(
|
# offset untested for unicode :(
|
||||||
|
|
|
@ -8,12 +8,6 @@ module Alpha2
|
||||||
|
|
||||||
class UnicodeUpper < Generic
|
class UnicodeUpper < Generic
|
||||||
def self.default_accepted_chars ; ('B' .. 'Z').to_a + ('0' .. '9').to_a ; end
|
def self.default_accepted_chars ; ('B' .. 'Z').to_a + ('0' .. '9').to_a ; end
|
||||||
|
|
||||||
def self.gen_base_set(max)
|
|
||||||
Rex::Text.shuffle_a(
|
|
||||||
[* ( (0..(max-1)).map { |i| i *= 0x10 } ) ]
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.gen_second(block, base)
|
def self.gen_second(block, base)
|
||||||
# unicode uses additive encoding
|
# unicode uses additive encoding
|
||||||
|
@ -21,8 +15,8 @@ class UnicodeUpper < Generic
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.gen_decoder_prefix(reg, offset)
|
def self.gen_decoder_prefix(reg, offset)
|
||||||
if (offset > 8)
|
if (offset > 6)
|
||||||
raise "Critical: Offset is greater than 8"
|
raise "Critical: Offset is greater than 6"
|
||||||
end
|
end
|
||||||
|
|
||||||
# offset untested for unicode :(
|
# offset untested for unicode :(
|
||||||
|
|
Loading…
Reference in New Issue