miketracy-wwmd 0.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +3 -0
- data/README +62 -0
- data/README.txt +62 -0
- data/Rakefile +34 -0
- data/examples/config_example.yaml +24 -0
- data/examples/wwmd_example.rb +73 -0
- data/lib/wwmd.rb +78 -0
- data/lib/wwmd/encoding.rb +40 -0
- data/lib/wwmd/form.rb +110 -0
- data/lib/wwmd/form_array.rb +273 -0
- data/lib/wwmd/guid.rb +155 -0
- data/lib/wwmd/hpricot_html2text.rb +76 -0
- data/lib/wwmd/mixins.rb +318 -0
- data/lib/wwmd/mixins_extends.rb +188 -0
- data/lib/wwmd/mixins_external.rb +18 -0
- data/lib/wwmd/nokogiri_html2text.rb +41 -0
- data/lib/wwmd/page.rb +414 -0
- data/lib/wwmd/page/auth.rb +183 -0
- data/lib/wwmd/page/config.rb +44 -0
- data/lib/wwmd/page/constants.rb +60 -0
- data/lib/wwmd/page/headers.rb +107 -0
- data/lib/wwmd/page/inputs.rb +47 -0
- data/lib/wwmd/page/irb_helpers.rb +90 -0
- data/lib/wwmd/page/scrape.rb +202 -0
- data/lib/wwmd/page/spider.rb +127 -0
- data/lib/wwmd/page/urlparse.rb +79 -0
- data/lib/wwmd/page/utils.rb +30 -0
- data/lib/wwmd/viewstate.rb +118 -0
- data/lib/wwmd/viewstate/viewstate_class_helpers.rb +35 -0
- data/lib/wwmd/viewstate/viewstate_deserializer_methods.rb +213 -0
- data/lib/wwmd/viewstate/viewstate_from_xml.rb +126 -0
- data/lib/wwmd/viewstate/viewstate_types.rb +51 -0
- data/lib/wwmd/viewstate/viewstate_utils.rb +157 -0
- data/lib/wwmd/viewstate/viewstate_yaml.rb +25 -0
- data/lib/wwmd/viewstate/vs_array.rb +36 -0
- data/lib/wwmd/viewstate/vs_binary_serialized.rb +28 -0
- data/lib/wwmd/viewstate/vs_hashtable.rb +40 -0
- data/lib/wwmd/viewstate/vs_hybrid_dict.rb +40 -0
- data/lib/wwmd/viewstate/vs_indexed_string.rb +6 -0
- data/lib/wwmd/viewstate/vs_indexed_string_ref.rb +22 -0
- data/lib/wwmd/viewstate/vs_int_enum.rb +25 -0
- data/lib/wwmd/viewstate/vs_list.rb +32 -0
- data/lib/wwmd/viewstate/vs_pair.rb +27 -0
- data/lib/wwmd/viewstate/vs_read_types.rb +11 -0
- data/lib/wwmd/viewstate/vs_read_value.rb +33 -0
- data/lib/wwmd/viewstate/vs_sparse_array.rb +56 -0
- data/lib/wwmd/viewstate/vs_string.rb +29 -0
- data/lib/wwmd/viewstate/vs_string_array.rb +37 -0
- data/lib/wwmd/viewstate/vs_string_formatted.rb +30 -0
- data/lib/wwmd/viewstate/vs_triplet.rb +29 -0
- data/lib/wwmd/viewstate/vs_type.rb +21 -0
- data/lib/wwmd/viewstate/vs_unit.rb +28 -0
- data/lib/wwmd/viewstate/vs_value.rb +33 -0
- data/spec/README +3 -0
- data/spec/form_array.spec +49 -0
- data/spec/spider_csrf_test.spec +28 -0
- data/spec/urlparse_test.spec +89 -0
- data/tasks/ann.rake +80 -0
- data/tasks/bones.rake +20 -0
- data/tasks/gem.rake +201 -0
- data/tasks/git.rake +40 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +34 -0
- data/tasks/rdoc.rake +51 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +292 -0
- data/tasks/spec.rake +54 -0
- data/tasks/test.rake +40 -0
- data/tasks/zentest.rake +36 -0
- metadata +164 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
module WWMD
|
2
|
+
class VSClassHelpers < ViewStateUtils
|
3
|
+
def to_sym
|
4
|
+
self.class.to_s.split(":").last.gsub(/[A-Z]+/,'\1_\0').downcase[1..-1].gsub(/\Avs/,"").to_sym
|
5
|
+
end
|
6
|
+
|
7
|
+
def opcode
|
8
|
+
return VIEWSTATE_TYPES.index(self.to_sym)
|
9
|
+
end
|
10
|
+
|
11
|
+
def size
|
12
|
+
return @value.size
|
13
|
+
end
|
14
|
+
|
15
|
+
def serialize
|
16
|
+
stack = ""
|
17
|
+
stack << self.write_byte(self.opcode)
|
18
|
+
if self.respond_to?(:typeref)
|
19
|
+
stack << self.serialize_type(self.typeref,self.typeval)
|
20
|
+
end
|
21
|
+
return stack
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_xml
|
25
|
+
xml = REXML::Element.new(self.class.to_s.split(":").last)
|
26
|
+
if self.respond_to?(:typeref)
|
27
|
+
xml.add_attribute("typeref",self.typeref)
|
28
|
+
xml.add_attribute("typeval",self.typeval)
|
29
|
+
end
|
30
|
+
# xml.add_attribute("size",self.size)
|
31
|
+
xml
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,213 @@
|
|
1
|
+
module WWMD
|
2
|
+
class ViewState
|
3
|
+
# complex types
|
4
|
+
def pair(t=nil)
|
5
|
+
dlog t,"next = #{next_type}"
|
6
|
+
VSPair.new(self.deserialize_value,self.deserialize_value)
|
7
|
+
end
|
8
|
+
|
9
|
+
def triplet(t=nil)
|
10
|
+
dlog t,"next = #{next_type}"
|
11
|
+
VSTriplet.new(self.deserialize_value,self.deserialize_value,self.deserialize_value)
|
12
|
+
end
|
13
|
+
|
14
|
+
def type(t=nil)
|
15
|
+
typeref,typeval = self.deserialize_type
|
16
|
+
dlog(t,"typeref = #{typeref} typeval = #{typeval}")
|
17
|
+
VSType.new(typeref,typeval)
|
18
|
+
end
|
19
|
+
|
20
|
+
def string_formatted(t=nil)
|
21
|
+
typeref,typeval = self.deserialize_type
|
22
|
+
str = self.read_string
|
23
|
+
dlog(t,"typeref = #{typeref} typeval = #{typeval} string = #{str}")
|
24
|
+
VSStringFormatted.new(typeref,typeval,str)
|
25
|
+
end
|
26
|
+
|
27
|
+
def int_enum(t=nil)
|
28
|
+
typeref,typeval = self.deserialize_type
|
29
|
+
index = self.read_7bit_encoded_int
|
30
|
+
dlog(t,"typeref = #{typeref} typeval = #{typeval} index = #{index}")
|
31
|
+
VSIntEnum.new(typeref,typeval,index)
|
32
|
+
end
|
33
|
+
|
34
|
+
def binary_serialized(t=nil)
|
35
|
+
count = self.read_7bit_encoded_int
|
36
|
+
dlog(t,count)
|
37
|
+
bin = self.read(count)
|
38
|
+
me = VSBinarySerialized.new()
|
39
|
+
me.set(bin)
|
40
|
+
return me
|
41
|
+
end
|
42
|
+
|
43
|
+
def sparse_array(t=nil)
|
44
|
+
typeref,typeval = self.deserialize_type
|
45
|
+
size = read_7bit_encoded_int
|
46
|
+
elems = read_7bit_encoded_int
|
47
|
+
dlog(t,"typeref = #{typeref} typeval = #{typeval} size = #{size} elems = #{elems}")
|
48
|
+
me = VSSparseArray.new(typeref,typeval,size,elems)
|
49
|
+
if elems > size
|
50
|
+
raise "Invalid sparse_array"
|
51
|
+
end
|
52
|
+
(1..elems).each do |i|
|
53
|
+
idx = read_7bit_encoded_int
|
54
|
+
me.add(idx,self.deserialize_value)
|
55
|
+
end
|
56
|
+
return me
|
57
|
+
end
|
58
|
+
|
59
|
+
def hashtable(t=nil)
|
60
|
+
len = read_7bit_encoded_int
|
61
|
+
dlog(t,"len = #{len}")
|
62
|
+
me = VSHashtable.new()
|
63
|
+
(1..len).each do |i|
|
64
|
+
me.add(self.deserialize_value,self.deserialize_value)
|
65
|
+
end
|
66
|
+
return me
|
67
|
+
end
|
68
|
+
|
69
|
+
def hybrid_dict(t=nil)
|
70
|
+
len = read_7bit_encoded_int
|
71
|
+
dlog(t,"len = #{len}")
|
72
|
+
me = VSHybridDict.new()
|
73
|
+
(1..len).each do |i|
|
74
|
+
me.add(self.deserialize_value,self.deserialize_value)
|
75
|
+
end
|
76
|
+
return me
|
77
|
+
end
|
78
|
+
|
79
|
+
def array(t=nil)
|
80
|
+
typeref,typeval = self.deserialize_type
|
81
|
+
len = read_7bit_encoded_int
|
82
|
+
dlog(t,"typeref = #{typeref} typeval = #{typeval} len = #{len}")
|
83
|
+
me = VSArray.new(typeref,typeval)
|
84
|
+
(1..len).each do |i|
|
85
|
+
me.add(self.deserialize_value)
|
86
|
+
end
|
87
|
+
return me
|
88
|
+
end
|
89
|
+
|
90
|
+
def string_array(t=nil)
|
91
|
+
len = read_7bit_encoded_int
|
92
|
+
dlog(t,"len = #{len}")
|
93
|
+
me = VSStringArray.new()
|
94
|
+
(1..len).each do |i|
|
95
|
+
str = self.read_string
|
96
|
+
me.add(str)
|
97
|
+
dlog(t,"string_array_elem: #{str}")
|
98
|
+
end
|
99
|
+
return me
|
100
|
+
end
|
101
|
+
|
102
|
+
def list(t=nil)
|
103
|
+
len = read_7bit_encoded_int
|
104
|
+
dlog(t,"len = #{len}")
|
105
|
+
me = VSList.new()
|
106
|
+
(1..len).each do |i|
|
107
|
+
me.add(self.deserialize_value)
|
108
|
+
end
|
109
|
+
return me
|
110
|
+
end
|
111
|
+
|
112
|
+
def unit(t=nil)
|
113
|
+
s1 = read_double
|
114
|
+
s2 = read_int32
|
115
|
+
dlog(t,"#{s1.to_s(16).rjust(16,"0")},#{s2.to_s(16).rjust(8,"0")}")
|
116
|
+
VSUnit.new(s1,s2)
|
117
|
+
end
|
118
|
+
|
119
|
+
def indexed_string(t=nil)
|
120
|
+
str = self.read_string
|
121
|
+
@indexed_strings << str
|
122
|
+
dlog(t,"idx = #{@indexed_strings.size - 1} val = #{str}")
|
123
|
+
VSIndexedString.new(str)
|
124
|
+
end
|
125
|
+
|
126
|
+
def indexed_string_ref(t=nil)
|
127
|
+
ref = self.read_int
|
128
|
+
dlog(t,"ref = #{ref} val = #{@indexed_strings[ref]}")
|
129
|
+
VSIndexedStringRef.new(ref)
|
130
|
+
end
|
131
|
+
|
132
|
+
def string(t=nil)
|
133
|
+
str = self.read_string
|
134
|
+
dlog(t,str)
|
135
|
+
VSString.new(str)
|
136
|
+
end
|
137
|
+
|
138
|
+
# VSReadValue types
|
139
|
+
def color(t=nil)
|
140
|
+
val = self.read_int32
|
141
|
+
dlog(t,val.to_s(16))
|
142
|
+
VSColor.new(val)
|
143
|
+
end
|
144
|
+
|
145
|
+
def known_color(t=nil)
|
146
|
+
index = self.read_7bit_encoded_int
|
147
|
+
dlog(t,"index = #{index.to_s(16)}")
|
148
|
+
VSKnownColor.new(index)
|
149
|
+
end
|
150
|
+
|
151
|
+
def int16(t=nil)
|
152
|
+
val = read_short
|
153
|
+
dlog(t,val)
|
154
|
+
VSInt16.new(val)
|
155
|
+
end
|
156
|
+
|
157
|
+
def int32(t=nil)
|
158
|
+
val = self.read_7bit_encoded_int
|
159
|
+
dlog(t,val)
|
160
|
+
VSInt32.new(val)
|
161
|
+
end
|
162
|
+
|
163
|
+
def byte(t=nil)
|
164
|
+
val = self.read_byte
|
165
|
+
dlog(t,val)
|
166
|
+
VSByte.new(val)
|
167
|
+
end
|
168
|
+
|
169
|
+
def char(t=nil)
|
170
|
+
val = self.read_byte
|
171
|
+
dlog(t,val)
|
172
|
+
VSChar.new(val)
|
173
|
+
end
|
174
|
+
|
175
|
+
def date_time(t=nil)
|
176
|
+
val = self.read_double
|
177
|
+
dlog(t,val)
|
178
|
+
VSDateTime.new(val)
|
179
|
+
end
|
180
|
+
|
181
|
+
def double(t=nil)
|
182
|
+
val = self.read_double
|
183
|
+
dlog(t,val)
|
184
|
+
VSDouble.new(val)
|
185
|
+
end
|
186
|
+
|
187
|
+
def single(t=nil)
|
188
|
+
val = self.read_single
|
189
|
+
dlog(t,val)
|
190
|
+
VSSingle.new(val)
|
191
|
+
end
|
192
|
+
|
193
|
+
# VSValue types
|
194
|
+
def null(t=nil); dlog(t,nil); return VSValue.new(t); end
|
195
|
+
def empty_byte(t=nil); dlog(t,nil); return VSValue.new(t); end
|
196
|
+
def zeroint32(t=nil); dlog(t,nil); return VSValue.new(t); end
|
197
|
+
def bool_true(t=nil); dlog(t,nil); return VSValue.new(t); end
|
198
|
+
def bool_false(t=nil); dlog(t,nil); return VSValue.new(t); end
|
199
|
+
def empty_color(t=nil); dlog(t,nil); return VSValue.new(t); end
|
200
|
+
def empty_unit(t=nil); dlog(t,nil); return VSValue.new(t); end
|
201
|
+
|
202
|
+
# deserialize_value
|
203
|
+
def deserialize_value
|
204
|
+
@last_offset = self.offset
|
205
|
+
token = self.read_byte # self.read_raw_byte
|
206
|
+
raise "Invalid Type #{token.hexify} at #{last_offset}" if not (tsym = VIEWSTATE_TYPES[token])
|
207
|
+
nobj = self.send(tsym,token)
|
208
|
+
raise "Invalid Class Returned #{nobj.class}" if not VIEWSTATE_TYPES.include?(nobj.opcode)
|
209
|
+
return nobj
|
210
|
+
end
|
211
|
+
|
212
|
+
end
|
213
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module WWMD
|
2
|
+
class ViewState
|
3
|
+
# directly serialize into stack from received xml (the easy way)
|
4
|
+
# this is pretty silly but it didn't take me very long so...
|
5
|
+
|
6
|
+
attr_reader :xmlstack
|
7
|
+
|
8
|
+
def get_sym(str)
|
9
|
+
str.split(":").last.gsub(/[A-Z]+/,'\1_\0').downcase[1..-1].gsub(/\Avs/,"").to_sym
|
10
|
+
end
|
11
|
+
|
12
|
+
def opcode(name,val)
|
13
|
+
sym = get_sym(name)
|
14
|
+
if sym == :value
|
15
|
+
ret = VIEWSTATE_TYPES.index(val.to_sym)
|
16
|
+
else
|
17
|
+
ret = VIEWSTATE_TYPES.index(sym)
|
18
|
+
end
|
19
|
+
ret
|
20
|
+
end
|
21
|
+
|
22
|
+
def serialize_hashtable(node)
|
23
|
+
tstack = ""
|
24
|
+
tstack << self.write_7bit_encoded_int(node['size'].to_i)
|
25
|
+
node.children.each do |c|
|
26
|
+
next if c.text?
|
27
|
+
raise "Invalid Hashtable: got #{c.name}" if not c.name == "Pair"
|
28
|
+
end
|
29
|
+
tstack
|
30
|
+
end
|
31
|
+
|
32
|
+
def decode_text(node)
|
33
|
+
case node['encoding']
|
34
|
+
when "quoted-printable"
|
35
|
+
node.inner_text.from_qp
|
36
|
+
when "base64"
|
37
|
+
node.inner_text.b64d
|
38
|
+
when "hexify"
|
39
|
+
node.inner_text.dehexify
|
40
|
+
else
|
41
|
+
node.inner_text
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def write_node(node)
|
46
|
+
return false if node.text?
|
47
|
+
tstack = ""
|
48
|
+
# this is a hack to get sparse_array to work
|
49
|
+
return false if ["Pair","Key","Value"].include?(node.name) # skip and fall through
|
50
|
+
if ["Index","Size","Elements"].include?(node.name)
|
51
|
+
@xmlstack << self.write_7bit_encoded_int(node.inner_text.to_i)
|
52
|
+
return false
|
53
|
+
end
|
54
|
+
if node.name == "Mac"
|
55
|
+
@xmlstack << decode_text(node)
|
56
|
+
return false
|
57
|
+
end
|
58
|
+
# end hack
|
59
|
+
flag = true # begin; sillyness; rescue => me; end
|
60
|
+
case get_sym(node.name)
|
61
|
+
when :pair, :triplet, :value, :sparse_array, :type, :string_formatted
|
62
|
+
when :int_enum, :known_color, :int32
|
63
|
+
tstack << self.write_7bit_encoded_int(node.inner_text.to_i)
|
64
|
+
when :int16
|
65
|
+
tstack << self.write_short(node.inner_text.to_i)
|
66
|
+
when :byte, :char, :indexed_string_ref
|
67
|
+
tstack << self.write_byte(node.inner_text.to_i)
|
68
|
+
when :color, :single
|
69
|
+
tstack << self.write_int32(node.inner_text.to_i)
|
70
|
+
when :double, :date_time
|
71
|
+
tstack << self.write_double(node.inner_text.to_i)
|
72
|
+
when :unit
|
73
|
+
tstack << self.write_double(node['dword'].to_i)
|
74
|
+
tstack << self.write_single(node['word'].to_i)
|
75
|
+
when :list, :string_array, :array
|
76
|
+
tstack << self.write_7bit_encoded_int(node['size'].to_i)
|
77
|
+
when :string, :indexed_string, :binary_serialized
|
78
|
+
flag = false if ([:string_array,:string_formatted].include?(get_sym(node.parent.name)))
|
79
|
+
# get encoding
|
80
|
+
str = decode_text(node)
|
81
|
+
tstack << self.write_7bit_encoded_int(str.size)
|
82
|
+
tstack << str
|
83
|
+
when :hashtable, :hybrid_dict
|
84
|
+
tstack << serialize_hashtable(node)
|
85
|
+
else
|
86
|
+
raise "Invalid Node:\n#{node.name}"
|
87
|
+
end
|
88
|
+
|
89
|
+
# [flag] is a hack to get around string_array and string_formatted emitting opcodes
|
90
|
+
@xmlstack << self.write_byte(opcode(node.name,node.inner_text)) if flag
|
91
|
+
if node.has_attribute?("typeref")
|
92
|
+
if node['typeref'].to_i == 0x2b
|
93
|
+
@xmlstack << self.serialize_type(node['typeref'].to_i,node['typeval'].to_i)
|
94
|
+
else
|
95
|
+
@xmlstack << self.serialize_type(node['typeref'].to_i,node['typeval'])
|
96
|
+
end
|
97
|
+
end
|
98
|
+
@xmlstack << tstack
|
99
|
+
end
|
100
|
+
|
101
|
+
def serialize_xml(node)
|
102
|
+
begin
|
103
|
+
write_node(node)
|
104
|
+
rescue => e
|
105
|
+
STDERR.puts "ERROR parsing node:\n#{node.to_s}"
|
106
|
+
raise e
|
107
|
+
end
|
108
|
+
node.children.each do |c|
|
109
|
+
serialize_xml(c)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def from_xml(xml)
|
114
|
+
@xmlstack = ""
|
115
|
+
doc = Nokogiri::XML.parse(xml)
|
116
|
+
root = doc.root
|
117
|
+
raise "Invalid ViewState Version" if not root.has_attribute?("version")
|
118
|
+
@xmlstack << root['version'].b64d
|
119
|
+
root.children.each do |c|
|
120
|
+
serialize_xml(c)
|
121
|
+
end
|
122
|
+
self.deserialize(@xmlstack.b64e)
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module WWMD
|
2
|
+
# private const byte Marker_Format = 0xff;
|
3
|
+
# private const byte Marker_Version_1 = 1;
|
4
|
+
# private const int StringTableSize = 0xff;
|
5
|
+
|
6
|
+
VIEWSTATE_MAGIC = ["\xff\x01"] unless defined?(VIEWSTATE_MAGIC)
|
7
|
+
|
8
|
+
VIEWSTATE_TYPES = {
|
9
|
+
# System.Web.UI.LosFormatter
|
10
|
+
# System.Web.UI.ObjectStateFormatter
|
11
|
+
# .DeserializeValue
|
12
|
+
|
13
|
+
0x00 => :debug, ##X debugging
|
14
|
+
0x01 => :int16, #RX private const byte Token_Int16 = 1;
|
15
|
+
0x02 => :int32, #RX private const byte Token_Int32 = 2;
|
16
|
+
0x03 => :byte, #RX private const byte Token_Byte = 3;
|
17
|
+
0x04 => :char, #RX private const byte Token_Char = 4;
|
18
|
+
0x05 => :string, ##X private const byte Token_String = 5;
|
19
|
+
0x06 => :date_time, #RX private const byte Token_DateTime = 6;
|
20
|
+
0x07 => :double, #RX private const byte Token_Double = 7;
|
21
|
+
0x08 => :single, #RX private const byte Token_Single = 8;
|
22
|
+
0x09 => :color, ##X private const byte Token_Color = 9;
|
23
|
+
0x0a => :known_color, ##X private const byte Token_KnownColor = 10;
|
24
|
+
0x0b => :int_enum, ##X private const byte Token_IntEnum = 11;
|
25
|
+
0x0c => :empty_color, #VX private const byte Token_EmptyColor = 12;
|
26
|
+
0x0f => :pair, ##X private const byte Token_Pair = 15;
|
27
|
+
0x10 => :triplet, ##X private const byte Token_Triplet = 0x10;
|
28
|
+
0x14 => :array, ##X private const byte Token_Array = 20;
|
29
|
+
0x15 => :string_array, ##X private const byte Token_StringArray = 0x15;
|
30
|
+
0x16 => :list, ##X private const byte Token_ArrayList = 0x16;
|
31
|
+
0x17 => :hashtable, ##X private const byte Token_Hashtable = 0x17
|
32
|
+
0x18 => :hybrid_dict, ##X private const byte Token_HybridDictionary = 0x18;
|
33
|
+
0x19 => :type, ##X private const byte Token_Type = 0x19;
|
34
|
+
0x1b => :unit, ##X private const byte Token_Unit = 0x1b;
|
35
|
+
0x1c => :empty_unit, #VX private const byte Token_EmptyUnit = 0x1c;
|
36
|
+
0x1e => :indexed_string, ##X private const byte Token_IndexedStringAdd = 30;
|
37
|
+
0x1f => :indexed_string_ref, ##X private const byte Token_IndexedString = 0x1f;
|
38
|
+
0x28 => :string_formatted, ##X private const byte Token_StringFormatted = 40;
|
39
|
+
0x29 => :typeref_add, ##X private const byte Token_TypeRefAdd = 0x29;
|
40
|
+
0x2a => :typeref_add_local, ##X private const byte Token_TypeRefAddLocal = 0x2a;
|
41
|
+
0x2b => :typeref, ##X private const byte Token_TypeRef = 0x2b;
|
42
|
+
0x32 => :binary_serialized, ##X private const byte Token_BinarySerialized = 50;
|
43
|
+
0x3c => :sparse_array, ##X private const byte Token_SparseArray = 60;
|
44
|
+
0x64 => :null, #VX private const byte Token_Null = 100;
|
45
|
+
0x65 => :empty_byte, #VX private const byte Token_EmptyString = 0x65;
|
46
|
+
0x66 => :zeroint32, #VX private const byte Token_ZeroInt32 = 0x66;
|
47
|
+
0x67 => :bool_true, #VX private const byte Token_True = 0x67;
|
48
|
+
0x68 => :bool_false, #VX private const byte Token_False = 0x68;
|
49
|
+
} unless defined?(VIEWSTATE_TYPES)
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
module WWMD
|
2
|
+
class ViewStateUtils
|
3
|
+
|
4
|
+
def putd(msg)
|
5
|
+
puts(msg) if self.debug
|
6
|
+
end
|
7
|
+
|
8
|
+
def slog(obj,msg=nil)
|
9
|
+
raise "No @value" if not obj.respond_to?(:value)
|
10
|
+
raise "No @size" if not obj.respond_to?(:size)
|
11
|
+
putd "#{@stack.size.to_s(16).rjust(8,"0")} [0x#{obj.opcode.to_s(16)}] #{obj.class}: #{msg}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def dlog(t,msg)
|
15
|
+
raise "null token passed to dlog()" if t.nil?
|
16
|
+
putd "#{self.last_offset} [0x#{t.to_s(16).rjust(2,"0")}] #{VIEWSTATE_TYPES[t]}: #{msg}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def write_7bit_encoded_int(val)
|
20
|
+
s = ""
|
21
|
+
while (val >= 0x80) do
|
22
|
+
s << [val | 0x80].pack("C")
|
23
|
+
val = val >> 7
|
24
|
+
end
|
25
|
+
s << [val].pack("C")
|
26
|
+
return s
|
27
|
+
end
|
28
|
+
|
29
|
+
# why oh why did I have to go find this?
|
30
|
+
# System.IO.BinaryReader.Read7BitEncodedInt
|
31
|
+
def read_7bit_encoded_int(buf=nil)
|
32
|
+
l = 0 # length
|
33
|
+
s = 0 # shift
|
34
|
+
b = "" # byte
|
35
|
+
buf = buf.scan(/./m) if buf
|
36
|
+
begin
|
37
|
+
if not buf
|
38
|
+
b = self.read_int
|
39
|
+
else
|
40
|
+
b = buf.shift.unpack("C").first
|
41
|
+
end
|
42
|
+
l |= (b & 0x7f) << s
|
43
|
+
s += 7
|
44
|
+
end while ((b & 0x80) != 0)
|
45
|
+
return l
|
46
|
+
end
|
47
|
+
|
48
|
+
def read_string
|
49
|
+
len = read_7bit_encoded_int
|
50
|
+
starr = []
|
51
|
+
(1..len).each { |i| starr << @bufarr.shift }
|
52
|
+
return starr.to_s
|
53
|
+
# @bufarr.slice!(0..(len - 1)).join("")
|
54
|
+
end
|
55
|
+
|
56
|
+
def read(count)
|
57
|
+
@bufarr.slice!(0..(count - 1)).join("")
|
58
|
+
end
|
59
|
+
|
60
|
+
def read_int
|
61
|
+
@bufarr.shift.unpack("C").first
|
62
|
+
end
|
63
|
+
alias_method :read_byte, :read_int
|
64
|
+
|
65
|
+
def write_int(val)
|
66
|
+
[val].pack("C")
|
67
|
+
end
|
68
|
+
alias_method :write_byte, :write_int
|
69
|
+
|
70
|
+
def read_short
|
71
|
+
self.read(2).unpack("S").first
|
72
|
+
end
|
73
|
+
|
74
|
+
def write_short(val)
|
75
|
+
[val].pack("n")
|
76
|
+
end
|
77
|
+
|
78
|
+
def read_int32
|
79
|
+
@bufarr.slice!(0..3).join("").unpack("L").first
|
80
|
+
end
|
81
|
+
alias_method :read_single, :read_int32
|
82
|
+
|
83
|
+
def write_int32(val)
|
84
|
+
[val].pack("I")
|
85
|
+
end
|
86
|
+
alias_method :write_single, :write_int32
|
87
|
+
|
88
|
+
def read_double
|
89
|
+
@bufarr.slice!(0..7).join("").unpack("Q").first
|
90
|
+
end
|
91
|
+
|
92
|
+
def write_double(val)
|
93
|
+
[val].pack("Q")
|
94
|
+
end
|
95
|
+
|
96
|
+
def magic?
|
97
|
+
@magic = [@bufarr.shift,@bufarr.shift].join("")
|
98
|
+
VIEWSTATE_MAGIC.include?(@magic)
|
99
|
+
end
|
100
|
+
|
101
|
+
def read_raw_byte
|
102
|
+
@bufarr.shift
|
103
|
+
end
|
104
|
+
|
105
|
+
def serialize_type(op,ref)
|
106
|
+
op_str = [op].pack("C")
|
107
|
+
s = op_str
|
108
|
+
case op
|
109
|
+
when VIEWSTATE_TYPES.index(:typeref)
|
110
|
+
s << write_7bit_encoded_int(ref)
|
111
|
+
when VIEWSTATE_TYPES.index(:typeref_add_local)
|
112
|
+
s << write_7bit_encoded_int(ref.size)
|
113
|
+
s << ref
|
114
|
+
when VIEWSTATE_TYPES.index(:typeref_add)
|
115
|
+
s << write_7bit_encoded_int(ref.size)
|
116
|
+
s << ref
|
117
|
+
else
|
118
|
+
raise "Invalid Type Error #{op.to_s(16)}"
|
119
|
+
end
|
120
|
+
return s
|
121
|
+
end
|
122
|
+
|
123
|
+
def deserialize_type(t=nil)
|
124
|
+
op = self.read_byte
|
125
|
+
case op
|
126
|
+
when VIEWSTATE_TYPES.index(:typeref)
|
127
|
+
type = read_7bit_encoded_int
|
128
|
+
return [op,type]
|
129
|
+
when VIEWSTATE_TYPES.index(:typeref_add_local)
|
130
|
+
name = read_string
|
131
|
+
return [op,name]
|
132
|
+
when VIEWSTATE_TYPES.index(:typeref_add)
|
133
|
+
name = read_string
|
134
|
+
return [op,name]
|
135
|
+
else
|
136
|
+
raise "Invalid Type Error 0x#{op.to_s(16)}"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def offset(cur=nil)
|
141
|
+
(self.size - @bufarr.size).to_s(16).rjust(8,"0")
|
142
|
+
end
|
143
|
+
|
144
|
+
def throw(t=nil)
|
145
|
+
STDERR.puts "==== Error at Type 0x#{t.to_s(16).rjust(2,"0")}"
|
146
|
+
STDERR.puts "offset: #{self.offset}"
|
147
|
+
STDERR.puts "left: #{@bufarr.size}"
|
148
|
+
STDERR.puts @bufarr[0..31].join("").hexdump
|
149
|
+
end
|
150
|
+
|
151
|
+
def next_type
|
152
|
+
t = @bufarr.first.unpack("C").first
|
153
|
+
throw(t) if not VIEWSTATE_TYPES.include?(t)
|
154
|
+
VIEWSTATE_TYPES[t]
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|