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
Tod Beardsley 2011-12-02 12:51:47 -08:00
commit 6b06df0d7d
3 changed files with 40 additions and 76 deletions

View File

@ -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)
@ -38,57 +31,40 @@ 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 # No, not nipple.
# an accepted char or we'll certainly fail at this point. This could nibble_chars = Array.new(0x10) {[]}
# be fixed later maybe with some recalculation of the encoder stubs... accepted_chars.each {|c| nibble_chars[c.unpack('C')[0] & 0x0F].push(c) }
# - Puss
(badchars || '').unpack('C*').map { |c| accepted_chars.delete([c].pack('C')) }
first = 0 poss_encodings = []
second = 1
randbase = 0
found = nil
block_low_nibble = block & 0x0F
block_high_nibble = block >> 4
gen_base_set(block).each do |randbase_| # Get list of chars suitable for expressing lower part of byte
second = gen_second(block, randbase_) first_chars = nibble_chars[block_low_nibble]
next if second < 0
if accepted_chars.include?([second].pack('C')) # Build a list of possible encodings
found = second first_chars.each do |first_char|
randbase = randbase_ first_high_nibble = first_char.unpack('C')[0] >> 4
break
end # In the decoding process, the low nibble of the second char gets combined
# (either ADDed or XORed depending on the encoder) with the high nibble of the first char,
# 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

View File

@ -8,20 +8,14 @@ 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
(block - base) (block - base)
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 :(

View File

@ -9,20 +9,14 @@ 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
(block - base) (block - base)
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 :(