#!/usr/bin/env ruby
# -*- coding: binary -*-

require 'rex/text'

module Rex
module Encoder

class NonAlpha

	def NonAlpha.gen_decoder()
		decoder =
			"\x66\xB9\xFF\xFF" +
			"\xEB\x19"  +               # Jmp to table
			"\x5E"      +               # pop esi
			"\x8B\xFE"  +               # mov edi, esi      - Get table addr
			"\x83\xC7"  + "A" +         # add edi, tablelen - Get shellcode addr
			"\x8B\xD7"  +               # mov edx, edi      - Hold end of table ptr
			"\x3B\xF2"  +               # cmp esi, edx
			"\x7D\x0B"  +               # jle to end
			"\xB0\x7B"  +               # mov eax, 0x7B     - Set up eax with magic
			"\xF2\xAE"  +               # repne scasb       - Find magic!
			"\xFF\xCF"  +               # dec edi           - scasb purs us one ahead
			"\xAC"      +               # lodsb
			"\x28\x07"  +               # subb [edi], al
			"\xEB\xF1"  +               # jmp BACK!
			"\xEB"      + "B" +         # jmp [shellcode]
			"\xE8\xE2\xFF\xFF\xFF"
	end

	def NonAlpha.encode_byte(block, table, tablelen)
		if (tablelen > 255) or (block == 0x7B)
			raise RuntimeError, "BadChar"
		end

		if (block >= 0x41 and block <= 0x5A) or (block >= 0x61 and block <= 0x7A)
			# gen offset, return magic
			offset = 0x7b - block;
			table += offset.chr
			tablelen = tablelen + 1
			block = 0x7B
		end

		return [block.chr, table, tablelen]
	end

	def NonAlpha.encode(buf)
		table = ""
		tablelen = 0
		nonascii = ""
		encoded = gen_decoder()
		buf.each_byte { |block|
			newchar, table, tablelen = encode_byte(block.unpack('C')[0], table, tablelen)
			nonascii += newchar
		}
		encoded.gsub!(/A/, tablelen)
		encoded.gsub!(/B/, tablelen+5)
		encoded += table
		encoded += nonascii
	end

end end end
