rex-encoder 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +1 -0
  3. data.tar.gz.sig +0 -0
  4. data/.gitignore +9 -0
  5. data/.rspec +2 -0
  6. data/.travis.yml +5 -0
  7. data/CODE_OF_CONDUCT.md +49 -0
  8. data/Gemfile +4 -0
  9. data/README.md +32 -0
  10. data/Rakefile +6 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/lib/rex/encoder.rb +15 -0
  14. data/lib/rex/encoder/alpha2.rb +31 -0
  15. data/lib/rex/encoder/alpha2/alpha_mixed.rb +129 -0
  16. data/lib/rex/encoder/alpha2/alpha_upper.rb +138 -0
  17. data/lib/rex/encoder/alpha2/generic.rb +90 -0
  18. data/lib/rex/encoder/alpha2/unicode_mixed.rb +116 -0
  19. data/lib/rex/encoder/alpha2/unicode_upper.rb +123 -0
  20. data/lib/rex/encoder/bloxor/bloxor.rb +327 -0
  21. data/lib/rex/encoder/ndr.rb +90 -0
  22. data/lib/rex/encoder/nonalpha.rb +61 -0
  23. data/lib/rex/encoder/nonupper.rb +64 -0
  24. data/lib/rex/encoder/version.rb +5 -0
  25. data/lib/rex/encoder/xdr.rb +108 -0
  26. data/lib/rex/encoder/xor.rb +69 -0
  27. data/lib/rex/encoder/xor/dword.rb +13 -0
  28. data/lib/rex/encoder/xor/dword_additive.rb +13 -0
  29. data/lib/rex/encoding/xor.rb +20 -0
  30. data/lib/rex/encoding/xor/byte.rb +15 -0
  31. data/lib/rex/encoding/xor/dword.rb +21 -0
  32. data/lib/rex/encoding/xor/dword_additive.rb +92 -0
  33. data/lib/rex/encoding/xor/exceptions.rb +17 -0
  34. data/lib/rex/encoding/xor/generic.rb +146 -0
  35. data/lib/rex/encoding/xor/qword.rb +15 -0
  36. data/lib/rex/encoding/xor/word.rb +21 -0
  37. data/lib/rex/poly.rb +134 -0
  38. data/lib/rex/poly/block.rb +480 -0
  39. data/lib/rex/poly/machine.rb +13 -0
  40. data/lib/rex/poly/machine/machine.rb +830 -0
  41. data/lib/rex/poly/machine/x86.rb +509 -0
  42. data/lib/rex/poly/register.rb +101 -0
  43. data/lib/rex/poly/register/x86.rb +41 -0
  44. data/rex-encoder.gemspec +31 -0
  45. metadata +248 -0
  46. metadata.gz.sig +0 -0
@@ -0,0 +1,90 @@
1
+ # -*- coding: binary -*-
2
+ require "rex/text"
3
+
4
+ module Rex
5
+ module Encoder
6
+ module NDR
7
+
8
+ # Provide padding to align the string to the 32bit boundary
9
+ def NDR.align(string)
10
+ return "\x00" * ((4 - (string.length & 3)) & 3)
11
+ end
12
+
13
+ # Encode a 4 byte long
14
+ # use to encode:
15
+ # long element_1;
16
+ def NDR.long(string)
17
+ return [string].pack('V')
18
+ end
19
+
20
+ # Encode a 2 byte short
21
+ # use to encode:
22
+ # short element_1;
23
+ def NDR.short(string)
24
+ return [string].pack('v')
25
+ end
26
+
27
+ # Encode a single byte
28
+ # use to encode:
29
+ # byte element_1;
30
+ def NDR.byte(string)
31
+ return [string].pack('C')
32
+ end
33
+
34
+ # Encode a byte array
35
+ # use to encode:
36
+ # char element_1
37
+ def NDR.UniConformantArray(string)
38
+ return long(string.length) + string + align(string)
39
+ end
40
+
41
+ # Encode a string
42
+ # use to encode:
43
+ # char *element_1;
44
+ def NDR.string(string)
45
+ string << "\x00" # null pad
46
+ return long(string.length) + long(0) + long(string.length) + string + align(string)
47
+ end
48
+
49
+ # Encode a string
50
+ # use to encode:
51
+ # w_char *element_1;
52
+ def NDR.wstring(string)
53
+ string = string + "\x00" # null pad
54
+ return long(string.length) + long(0) + long(string.length) + Rex::Text.to_unicode(string) + align(Rex::Text.to_unicode(string))
55
+ end
56
+
57
+ # Encode a string and make it unique
58
+ # use to encode:
59
+ # [unique] w_char *element_1;
60
+ def NDR.uwstring(string)
61
+ string = string + "\x00" # null pad
62
+ return long(rand(0xffffffff))+long(string.length) + long(0) + long(string.length) + Rex::Text.to_unicode(string) + align(Rex::Text.to_unicode(string))
63
+ end
64
+
65
+ # Encode a string that is already unicode encoded
66
+ # use to encode:
67
+ # w_char *element_1;
68
+ def NDR.wstring_prebuilt(string)
69
+ # if the string len is odd, thats bad!
70
+ if string.length % 2 > 0
71
+ string = string + "\x00"
72
+ end
73
+ len = string.length / 2;
74
+ return long(len) + long(0) + long(len) + string + align(string)
75
+ end
76
+
77
+ # alias to wstring, going away soon
78
+ def NDR.UnicodeConformantVaryingString(string)
79
+ NDR.wstring(string)
80
+ end
81
+
82
+ # alias to wstring_prebuilt, going away soon
83
+ def NDR.UnicodeConformantVaryingStringPreBuilt(string)
84
+ NDR.wstring_prebuilt(string)
85
+ end
86
+
87
+ end
88
+ end
89
+ end
90
+
@@ -0,0 +1,61 @@
1
+ # -*- coding: binary -*-
2
+
3
+ require 'rex/text'
4
+
5
+ module Rex
6
+ module Encoder
7
+
8
+ class NonAlpha
9
+
10
+ def NonAlpha.gen_decoder
11
+ decoder =
12
+ "\x66\xB9\xFF\xFF" +
13
+ "\xEB\x19" + # Jmp to table
14
+ "\x5E" + # pop esi
15
+ "\x8B\xFE" + # mov edi, esi - Get table addr
16
+ "\x83\xC7" + "A" + # add edi, tablelen - Get shellcode addr
17
+ "\x8B\xD7" + # mov edx, edi - Hold end of table ptr
18
+ "\x3B\xF2" + # cmp esi, edx
19
+ "\x7D\x0B" + # jle to end
20
+ "\xB0\x7B" + # mov eax, 0x7B - Set up eax with magic
21
+ "\xF2\xAE" + # repne scasb - Find magic!
22
+ "\xFF\xCF" + # dec edi - scasb purs us one ahead
23
+ "\xAC" + # lodsb
24
+ "\x28\x07" + # subb [edi], al
25
+ "\xEB\xF1" + # jmp BACK!
26
+ "\xEB" + "B" + # jmp [shellcode]
27
+ "\xE8\xE2\xFF\xFF\xFF"
28
+ end
29
+
30
+ def NonAlpha.encode_byte(block, table, tablelen)
31
+ if tablelen > 255 || block == 0x7B
32
+ raise RuntimeError, "BadChar"
33
+ end
34
+
35
+ if (block >= 0x41 && block <= 0x5A) || (block >= 0x61 && block <= 0x7A)
36
+ # gen offset, return magic
37
+ offset = 0x7b - block
38
+ table += offset.chr
39
+ tablelen = tablelen + 1
40
+ block = 0x7B
41
+ end
42
+
43
+ return [block.chr, table, tablelen]
44
+ end
45
+
46
+ def NonAlpha.encode(buf)
47
+ table = ""
48
+ tablelen = 0
49
+ nonascii = ""
50
+ encoded = gen_decoder()
51
+ buf.each_byte { |block|
52
+ newchar, table, tablelen = encode_byte(block.unpack('C')[0], table, tablelen)
53
+ nonascii += newchar
54
+ }
55
+ encoded.gsub!(/A/, tablelen)
56
+ encoded.gsub!(/B/, tablelen+5)
57
+ encoded += table
58
+ encoded += nonascii
59
+ end
60
+
61
+ end end end
@@ -0,0 +1,64 @@
1
+ # -*- coding: binary -*-
2
+
3
+ require 'rex/text'
4
+
5
+ module Rex
6
+ module Encoder
7
+
8
+ class NonUpper
9
+
10
+
11
+ def NonUpper.gen_decoder()
12
+ decoder =
13
+ "\x66\xB9\xFF\xFF" +
14
+ "\xEB\x19" + # Jmp to table
15
+ "\x5E" + # pop esi
16
+ "\x8B\xFE" + # mov edi, esi - Get table addr
17
+ "\x83\xC7" + "A" + # add edi, tablelen - Get shellcode addr
18
+ "\x8B\xD7" + # mov edx, edi - Hold end of table ptr
19
+ "\x3B\xF2" + # cmp esi, edx
20
+ "\x7D\x0B" + # jle to end
21
+ "\xB0\x7B" + # mov eax, 0x7B - Set up eax with magic
22
+ "\xF2\xAE" + # repne scasb - Find magic!
23
+ "\xFF\xCF" + # dec edi - scasb purs us one ahead
24
+ "\xAC" + # lodsb
25
+ "\x28\x07" + # subb [edi], al
26
+ "\xEB\xF1" + # jmp BACK!
27
+ "\xEB" + "B" + # jmp [shellcode]
28
+ "\xE8\xE2\xFF\xFF\xFF"
29
+ end
30
+
31
+ def NonUpper.encode_byte(badchars, block, table, tablelen)
32
+ if (tablelen > 255) or (block == 0x40)
33
+ raise RuntimeError, "BadChar"
34
+ end
35
+
36
+ if (block >= 0x41 and block <= 0x40) or (badchars =~ block)
37
+ # gen offset, return magic
38
+ offset = 0x40 - block;
39
+ table += offset.chr
40
+ tablelen = tablelen + 1
41
+ block = 0x40
42
+ end
43
+
44
+ return [block.chr, table, tablelen]
45
+ end
46
+
47
+ def NonUpper.encode(buf)
48
+ table = ""
49
+ tablelen = 0
50
+ nonascii = ""
51
+ encoded = gen_decoder()
52
+ buf.each_byte {
53
+ |block|
54
+
55
+ newchar, table, tablelen = encode_byte(block.unpack('C')[0], table, tablelen)
56
+ nonascii += newchar
57
+ }
58
+ encoded.gsub!(/A/, tablelen)
59
+ encoded.gsub!(/B/, tablelen+5)
60
+ encoded += table
61
+ encoded += nonascii
62
+ end
63
+
64
+ end end end
@@ -0,0 +1,5 @@
1
+ module Rex
2
+ module Encoder
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,108 @@
1
+ # -*- coding: binary -*-
2
+ module Rex
3
+ module Encoder
4
+
5
+ ###
6
+ #
7
+ # This class implements basic XDR encoding.
8
+ #
9
+ ###
10
+ module XDR
11
+ MAX_ARG = 0xffffffff
12
+
13
+ # Also: unsigned int, bool, enum
14
+ def XDR.encode_int(int)
15
+ return [int].pack('N')
16
+ end
17
+
18
+ def XDR.decode_int!(data)
19
+ raise ArgumentError, 'XDR: No Integer data to decode' unless data
20
+ raise ArgumentError, "XDR: Too little data to decode (#{data.size})" if data.size < 4
21
+ return data.slice!(0..3).unpack('N')[0]
22
+ end
23
+
24
+ def XDR.encode_lchar(char)
25
+ char |= 0xffffff00 if char & 0x80 != 0
26
+ return encode_int(char)
27
+ end
28
+
29
+ def XDR.decode_lchar!(data)
30
+ return (decode_int!(data) & 0xff).chr
31
+ end
32
+
33
+ # Also: Variable length opaque
34
+ def XDR.encode_string(str, max=MAX_ARG)
35
+ raise ArgumentError, 'XDR: String too long' if str.length > max
36
+ len = str.length
37
+ str << "\x00" * ((4 - (len & 3)) & 3)
38
+ return encode_int(len) + str
39
+ end
40
+
41
+ def XDR.decode_string!(data)
42
+ real_len = decode_int!(data)
43
+ return "" if real_len == 0
44
+ align_len = (real_len + 3) & ~3
45
+ return data.slice!(0..align_len-1).slice(0..real_len-1)
46
+ end
47
+
48
+ def XDR.encode_varray(arr, max=MAX_ARG, &block)
49
+ raise ArgumentError, 'XDR: Too many array elements' if arr.length > max
50
+ return encode_int(arr.length) + arr.collect(&block).join(nil)
51
+ end
52
+
53
+ def XDR.decode_varray!(data)
54
+ buf = []
55
+ 1.upto(decode_int!(data)) { buf.push(yield(data)) }
56
+ return buf
57
+ end
58
+
59
+ # encode(0, [0, 1], "foo", ["bar", 4]) does:
60
+ # encode_int(0) +
61
+ # encode_varray([0, 1]) { |i| XDR.encode_int(i) } +
62
+ # encode_string("foo") +
63
+ # encode_string("bar", 4)
64
+ def XDR.encode(*data)
65
+ data.collect do |var|
66
+ if var.kind_of?(String)
67
+ encode_string(var)
68
+ elsif var.kind_of?(Integer)
69
+ encode_int(var)
70
+ elsif var.kind_of?(Array) && var[0].kind_of?(String)
71
+ raise ArgumentError, 'XDR: Incorrect string array arguments' if var.length != 2
72
+ encode_string(var[0], var[1])
73
+ elsif var.kind_of?(Array) && var[0].kind_of?(Integer)
74
+ encode_varray(var) { |i| XDR.encode_int(i) }
75
+ # 0 means an empty array index in the case of Integer and an empty string in
76
+ # the case of String so we get the best of both worlds
77
+ elsif var.kind_of?(Array) && var[0].nil?
78
+ encode_int(0)
79
+ else
80
+ type = var.class
81
+ type = var[0].class if var.kind_of?(Array)
82
+ raise TypeError, "XDR: encode does not support #{type}"
83
+ end
84
+ end.join(nil)
85
+ end
86
+
87
+ # decode(buf, Integer, String, [Integer], [String]) does:
88
+ # [decode_int!(buf), decode_string!(buf),
89
+ # decode_varray!(buf) { |i| XDR.decode_int!(i) },
90
+ # decode_varray!(buf) { |s| XDR.decode_string(s) }]
91
+ def XDR.decode!(buf, *data)
92
+ return *data.collect do |var|
93
+ if data.length == 0
94
+ elsif var.kind_of?(Array) && var[0] == String
95
+ decode_varray!(buf) { |s| XDR.decode_string!(s) }
96
+ elsif var.kind_of?(Array) && var[0] == Integer
97
+ decode_varray!(buf) { |i| XDR.decode_int!(i) }
98
+ elsif var == String
99
+ decode_string!(buf)
100
+ elsif var == Integer
101
+ decode_int!(buf)
102
+ end
103
+ end
104
+ end
105
+ end
106
+
107
+ end
108
+ end
@@ -0,0 +1,69 @@
1
+ # -*- coding: binary -*-
2
+
3
+ module Rex
4
+ module Encoder
5
+
6
+ ###
7
+ #
8
+ # This class performs basic XOR encoding.
9
+ #
10
+ ###
11
+ class Xor
12
+
13
+ attr_accessor :raw, :encoded, :badchars, :opts, :key, :fkey # :nodoc:
14
+
15
+ #
16
+ # wrap that in a wanna be static class
17
+ #
18
+ def self.encode(*args)
19
+ self.new.encode(*args)
20
+ end
21
+
22
+ #
23
+ # Return the class associated with this encoder.
24
+ #
25
+ def encoder()
26
+ self.class::EncoderKlass
27
+ end
28
+
29
+ #
30
+ # This method encodes the supplied data, taking into account the badchar
31
+ # list, and returns the encoded buffer.
32
+ #
33
+ def encode(data, badchars = '', opts = { })
34
+ self.raw = data
35
+ self.badchars = badchars
36
+ self.opts = opts
37
+
38
+ # apply any transforms to the plaintext data
39
+ data = _unencoded_transform(data)
40
+
41
+ self.encoded, self.key, self.fkey = encoder().find_key_and_encode(data, badchars)
42
+
43
+ # apply any transforms to the encoded data
44
+ self.encoded = _encoded_transform(encoded)
45
+
46
+ return _prepend() + encoded + _append()
47
+ end
48
+
49
+ protected
50
+ def _unencoded_transform(data) # :nodoc:
51
+ data
52
+ end
53
+
54
+ def _encoded_transform(data) # :nodoc:
55
+ data
56
+ end
57
+
58
+ def _prepend() # :nodoc:
59
+ ""
60
+ end
61
+
62
+ def _append() # :nodoc:
63
+ ""
64
+ end
65
+
66
+ end
67
+
68
+ end end
69
+
@@ -0,0 +1,13 @@
1
+ # -*- coding: binary -*-
2
+
3
+ require 'rex/encoder/xor'
4
+ require 'rex/encoding/xor/dword'
5
+
6
+ ###
7
+ #
8
+ # This class wraps the Dword XOR encoder.
9
+ #
10
+ ###
11
+ class Rex::Encoder::Xor::Dword < Rex::Encoder::Xor
12
+ EncoderKlass = Rex::Encoding::Xor::Dword
13
+ end
@@ -0,0 +1,13 @@
1
+ # -*- coding: binary -*-
2
+
3
+ require 'rex/encoder/xor'
4
+ require 'rex/encoding/xor/dword_additive'
5
+
6
+ ###
7
+ #
8
+ # This class wraps the Dword XOR Additive feedback encoder.
9
+ #
10
+ ###
11
+ class Rex::Encoder::Xor::DwordAdditive < Rex::Encoder::Xor
12
+ EncoderKlass = Rex::Encoding::Xor::DwordAdditive
13
+ end
@@ -0,0 +1,20 @@
1
+ # -*- coding: binary -*-
2
+
3
+ #
4
+ # make sure the namespace is created
5
+ #
6
+
7
+ module Rex
8
+ module Encoding
9
+ module Xor
10
+ end end end
11
+
12
+ #
13
+ # include the Xor encodings
14
+ #
15
+
16
+ require 'rex/encoding/xor/generic'
17
+ require 'rex/encoding/xor/byte'
18
+ require 'rex/encoding/xor/word'
19
+ require 'rex/encoding/xor/dword'
20
+ require 'rex/encoding/xor/qword'