miketracy-wwmd 0.2.11
Sign up to get free protection for your applications and to get access to all the features.
- 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
|