pedump 0.6.10 → 0.7.1
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.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/Gemfile.lock +85 -34
- data/README.md +89 -72
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/bin/pedump +1 -1
- data/data/jc-userdb.txt +0 -8
- data/data/signatures.txt +1 -2
- data/data/userdb.txt +0 -8
- data/lib/pedump/cli.rb +305 -48
- data/lib/pedump/clr/readytorun.rb +115 -0
- data/lib/pedump/clr/signature.rb +318 -0
- data/lib/pedump/clr.rb +709 -0
- data/lib/pedump/logger.rb +1 -1
- data/lib/pedump.rb +41 -5
- data/pedump.gemspec +8 -5
- metadata +8 -8
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
#coding: binary
|
|
2
|
+
|
|
3
|
+
class PEdump
|
|
4
|
+
module CLR
|
|
5
|
+
class Signature
|
|
6
|
+
FIELD = 6
|
|
7
|
+
PROPERTY = 8
|
|
8
|
+
|
|
9
|
+
DEFAULT = 0
|
|
10
|
+
VARARG = 5
|
|
11
|
+
GENERIC = 0x10
|
|
12
|
+
HASTHIS = 0x20
|
|
13
|
+
EXPLICITTHIS = 0x40
|
|
14
|
+
|
|
15
|
+
SENTINEL = 0x41
|
|
16
|
+
|
|
17
|
+
# https://github.com/stakx/ecma-335/blob/master/docs/ii.23.1.16-element-types-used-in-signatures.md
|
|
18
|
+
ELEMENT_TYPE_END = 0
|
|
19
|
+
ELEMENT_TYPE_VOID = 1
|
|
20
|
+
ELEMENT_TYPE_BOOLEAN = 2
|
|
21
|
+
ELEMENT_TYPE_CHAR = 3
|
|
22
|
+
ELEMENT_TYPE_I1 = 4
|
|
23
|
+
ELEMENT_TYPE_U1 = 5
|
|
24
|
+
ELEMENT_TYPE_I2 = 6
|
|
25
|
+
ELEMENT_TYPE_U2 = 7
|
|
26
|
+
ELEMENT_TYPE_I4 = 8
|
|
27
|
+
ELEMENT_TYPE_U4 = 9
|
|
28
|
+
ELEMENT_TYPE_I8 = 0x0a
|
|
29
|
+
ELEMENT_TYPE_U8 = 0x0b
|
|
30
|
+
ELEMENT_TYPE_R4 = 0x0c
|
|
31
|
+
ELEMENT_TYPE_R8 = 0x0d
|
|
32
|
+
ELEMENT_TYPE_STRING = 0x0e
|
|
33
|
+
ELEMENT_TYPE_PTR = 0x0f # Followed by type
|
|
34
|
+
ELEMENT_TYPE_BYREF = 0x10 # Followed by type
|
|
35
|
+
ELEMENT_TYPE_VALUETYPE = 0x11 # Followed by TypeDef or TypeRef token
|
|
36
|
+
ELEMENT_TYPE_CLASS = 0x12 # Followed by TypeDef or TypeRef token
|
|
37
|
+
ELEMENT_TYPE_VAR = 0x13 # Generic parameter in a generic type definition, represented as number (compressed unsigned integer)
|
|
38
|
+
ELEMENT_TYPE_ARRAY = 0x14 # type rank boundsCount bound1 … loCount lo1 …
|
|
39
|
+
ELEMENT_TYPE_GENERICINST = 0x15 # Generic type instantiation. Followed by type type-arg-count type-1 … type-n
|
|
40
|
+
ELEMENT_TYPE_TYPEDBYREF = 0x16
|
|
41
|
+
ELEMENT_TYPE_I = 0x18 # System.IntPtr
|
|
42
|
+
ELEMENT_TYPE_U = 0x19 # System.UIntPtr
|
|
43
|
+
ELEMENT_TYPE_FNPTR = 0x1b # Followed by full method signature
|
|
44
|
+
ELEMENT_TYPE_OBJECT = 0x1c # System.Object
|
|
45
|
+
ELEMENT_TYPE_SZARRAY = 0x1d # Single-dim array with 0 lower bound
|
|
46
|
+
ELEMENT_TYPE_MVAR = 0x1e # Generic parameter in a generic method definition, represented as number (compressed unsigned integer)
|
|
47
|
+
ELEMENT_TYPE_CMOD_REQD = 0x1f # Required modifier: followed by a TypeDef or TypeRef token
|
|
48
|
+
ELEMENT_TYPE_CMOD_OPT = 0x20 # Optional modifier: followed by a TypeDef or TypeRef token
|
|
49
|
+
ELEMENT_TYPE_INTERNAL = 0x21 # Implemented within the CLI
|
|
50
|
+
# TODO: 0x40+
|
|
51
|
+
|
|
52
|
+
# https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2.10-param.md
|
|
53
|
+
# https://github.com/stakx/ecma-335/blob/master/docs/ii.15.3-calling-convention.md
|
|
54
|
+
def to_s
|
|
55
|
+
a = []
|
|
56
|
+
a << 'instance' if @type & 0x20 != 0
|
|
57
|
+
a << 'explicit' if @type & 0x40 != 0
|
|
58
|
+
a << case @type & 0x0f
|
|
59
|
+
when DEFAULT
|
|
60
|
+
nil # default calling convention
|
|
61
|
+
when 1
|
|
62
|
+
'cdecl'
|
|
63
|
+
when 2
|
|
64
|
+
'stdcall'
|
|
65
|
+
when 3
|
|
66
|
+
'thiscall'
|
|
67
|
+
when 4
|
|
68
|
+
'fastcall'
|
|
69
|
+
when VARARG
|
|
70
|
+
'vararg'
|
|
71
|
+
else
|
|
72
|
+
"0x%02x" % (@type)
|
|
73
|
+
end
|
|
74
|
+
a << @RetType
|
|
75
|
+
a.compact.join(' ')
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def self.read(io, key)
|
|
79
|
+
klass =
|
|
80
|
+
case key
|
|
81
|
+
when :Field
|
|
82
|
+
FieldSig
|
|
83
|
+
when :Property
|
|
84
|
+
PropertySig
|
|
85
|
+
when :MethodDef
|
|
86
|
+
MethodDefSig
|
|
87
|
+
when :MemberRef
|
|
88
|
+
type = io.getbyte
|
|
89
|
+
io.ungetbyte(type)
|
|
90
|
+
if type == FIELD
|
|
91
|
+
FieldSig
|
|
92
|
+
else
|
|
93
|
+
MethodRefSig
|
|
94
|
+
end
|
|
95
|
+
when :StandAloneSig
|
|
96
|
+
StandAloneMethodSig
|
|
97
|
+
when :TypeSpec
|
|
98
|
+
TypeSpecBlob
|
|
99
|
+
else
|
|
100
|
+
raise "unknown key: #{key.inspect}"
|
|
101
|
+
end
|
|
102
|
+
klass.new(io)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2.10-param.md
|
|
106
|
+
def _read_Param io
|
|
107
|
+
_read_CustomMod(io)
|
|
108
|
+
case (b = io.getbyte)
|
|
109
|
+
when ELEMENT_TYPE_BYREF
|
|
110
|
+
# TODO "add byref"
|
|
111
|
+
_read_Type(io)
|
|
112
|
+
when ELEMENT_TYPE_TYPEDBYREF
|
|
113
|
+
"TYPEDBYREF"
|
|
114
|
+
else
|
|
115
|
+
io.ungetbyte(b)
|
|
116
|
+
_read_Type(io)
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def _read_Type io
|
|
121
|
+
case b = io.getbyte
|
|
122
|
+
when ELEMENT_TYPE_BOOLEAN then "bool"
|
|
123
|
+
when ELEMENT_TYPE_CHAR then "char"
|
|
124
|
+
when ELEMENT_TYPE_CLASS
|
|
125
|
+
a = ['CLASS']
|
|
126
|
+
a << _read_TypeDefOrRefOrSpecEncoded(io).to_s(16)
|
|
127
|
+
a.join(' ')
|
|
128
|
+
|
|
129
|
+
when ELEMENT_TYPE_VALUETYPE
|
|
130
|
+
a = ['VALUE']
|
|
131
|
+
a << _read_TypeDefOrRefOrSpecEncoded(io).to_s(16)
|
|
132
|
+
a.join(' ')
|
|
133
|
+
|
|
134
|
+
when ELEMENT_TYPE_GENERICINST
|
|
135
|
+
# https://github.com/stakx/ecma-335/blob/f181e4696eebcbbc7c2b1e5d0a2ee289f2884d2d/docs/vi.b.4.3-metadata.md
|
|
136
|
+
a = []
|
|
137
|
+
a << _read_Type(io)
|
|
138
|
+
genArgCount = _read_compressed_uint(io)
|
|
139
|
+
nested_types = genArgCount.times.map{ _read_Type(io).to_s }
|
|
140
|
+
a << '<' + nested_types.join(', ') + '>'
|
|
141
|
+
a.join(' ')
|
|
142
|
+
|
|
143
|
+
when ELEMENT_TYPE_I then "nint"
|
|
144
|
+
when ELEMENT_TYPE_I1 then "sbyte"
|
|
145
|
+
when ELEMENT_TYPE_I2 then "short"
|
|
146
|
+
when ELEMENT_TYPE_I4 then "int"
|
|
147
|
+
when ELEMENT_TYPE_I8 then "long"
|
|
148
|
+
|
|
149
|
+
when ELEMENT_TYPE_R4 then "float"
|
|
150
|
+
when ELEMENT_TYPE_R8 then "double"
|
|
151
|
+
|
|
152
|
+
when ELEMENT_TYPE_U then "nuint"
|
|
153
|
+
when ELEMENT_TYPE_U1 then "byte"
|
|
154
|
+
when ELEMENT_TYPE_U2 then "ushort"
|
|
155
|
+
when ELEMENT_TYPE_U4 then "uint"
|
|
156
|
+
when ELEMENT_TYPE_U8 then "ulong"
|
|
157
|
+
when ELEMENT_TYPE_OBJECT then "object"
|
|
158
|
+
when ELEMENT_TYPE_STRING then "string"
|
|
159
|
+
when ELEMENT_TYPE_SZARRAY then "#{_read_Type(io)}[]"
|
|
160
|
+
when ELEMENT_TYPE_VALUETYPE then _read_TypeDefOrRefOrSpecEncoded(io)
|
|
161
|
+
when ELEMENT_TYPE_VAR, ELEMENT_TYPE_MVAR
|
|
162
|
+
_read_compressed_uint(io).to_s
|
|
163
|
+
when ELEMENT_TYPE_VOID then "void"
|
|
164
|
+
when ELEMENT_TYPE_END then "END"
|
|
165
|
+
else
|
|
166
|
+
"0x%02x" % b
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
# https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2.11-rettype.md
|
|
171
|
+
def _read_RetType io
|
|
172
|
+
_read_CustomMod(io)
|
|
173
|
+
case (b = io.getbyte)
|
|
174
|
+
when ELEMENT_TYPE_BYREF
|
|
175
|
+
# TODO "add byref"
|
|
176
|
+
_read_Type(io)
|
|
177
|
+
when ELEMENT_TYPE_TYPEDBYREF
|
|
178
|
+
"TYPEDBYREF"
|
|
179
|
+
when ELEMENT_TYPE_VOID
|
|
180
|
+
"void"
|
|
181
|
+
else
|
|
182
|
+
io.ungetbyte(b)
|
|
183
|
+
_read_Type(io)
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2.7-custommod.md
|
|
188
|
+
def _read_CustomMod io
|
|
189
|
+
b = io.getbyte
|
|
190
|
+
if b == ELEMENT_TYPE_CMOD_REQD || b == ELEMENT_TYPE_CMOD_OPT
|
|
191
|
+
@cmod = b
|
|
192
|
+
@cmod_type = _read_TypeDefOrRefOrSpecEncoded(io)
|
|
193
|
+
else
|
|
194
|
+
io.ungetbyte(b)
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2.8-typedeforreforspecencoded.md
|
|
199
|
+
def _read_TypeDefOrRefOrSpecEncoded io
|
|
200
|
+
v = _read_compressed_uint(io)
|
|
201
|
+
table_id = (v & 3)
|
|
202
|
+
idx_in_table = (v >> 2)
|
|
203
|
+
table_id_hi =
|
|
204
|
+
case table_id
|
|
205
|
+
when 0
|
|
206
|
+
# TypeDef
|
|
207
|
+
0x02_000000
|
|
208
|
+
when 1
|
|
209
|
+
# TypeRef
|
|
210
|
+
0x01_000000
|
|
211
|
+
when 2
|
|
212
|
+
# TypeSpec
|
|
213
|
+
0x1b_000000
|
|
214
|
+
else
|
|
215
|
+
# invalid
|
|
216
|
+
0
|
|
217
|
+
end
|
|
218
|
+
table_id_hi | idx_in_table
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2-blobs-and-signatures.md
|
|
222
|
+
def _read_compressed_uint io
|
|
223
|
+
v = io.read(1).unpack1('C')
|
|
224
|
+
if v & 0x80 == 0
|
|
225
|
+
# 1 byte
|
|
226
|
+
v
|
|
227
|
+
elsif v & 0xC0 == 0x80
|
|
228
|
+
# 2 bytes
|
|
229
|
+
((v & 0x3F) << 8) | io.read(1).unpack1('C')
|
|
230
|
+
elsif v & 0xE0 == 0xC0
|
|
231
|
+
# 4 bytes
|
|
232
|
+
((v & 0x1F) << 24) | (io.read(3).unpack1('C') << 16) | (io.read(2).unpack1('C') << 8) | io.read(1).unpack1('C')
|
|
233
|
+
else
|
|
234
|
+
nil
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
end # class Signature
|
|
238
|
+
|
|
239
|
+
# https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2.4-fieldsig.md
|
|
240
|
+
class FieldSig < Signature
|
|
241
|
+
attr_accessor :type
|
|
242
|
+
|
|
243
|
+
def initialize(io)
|
|
244
|
+
sig_type = io.getbyte
|
|
245
|
+
raise "unexpected sig_type #{sig_type}" if sig_type != FIELD
|
|
246
|
+
|
|
247
|
+
_read_CustomMod(io)
|
|
248
|
+
@type = _read_Type(io)
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
# https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2.5-propertysig.md
|
|
253
|
+
class PropertySig < Signature
|
|
254
|
+
attr_accessor :type, :params
|
|
255
|
+
|
|
256
|
+
def initialize(io)
|
|
257
|
+
sig_type = io.getbyte
|
|
258
|
+
raise "unexpected sig_type #{sig_type}" if sig_type != PROPERTY && sig_type != PROPERTY|HASTHIS
|
|
259
|
+
|
|
260
|
+
@ParamCount = _read_compressed_uint(io)
|
|
261
|
+
_read_CustomMod(io) # FIXME
|
|
262
|
+
@type = _read_Type(io)
|
|
263
|
+
if @ParamCount < 255 # protect from malformed EXEs
|
|
264
|
+
@params = @ParamCount.times.map{ _read_Param(io) }
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2.2-methodrefsig.md
|
|
270
|
+
class MethodRefSig < Signature
|
|
271
|
+
attr_accessor :ret_type, :params
|
|
272
|
+
|
|
273
|
+
def initialize io
|
|
274
|
+
# "The first byte of the Signature holds bits for HASTHIS, EXPLICITTHIS, and the calling convention VARARG. These are ORed together."
|
|
275
|
+
@type = io.read(1).unpack1('C')
|
|
276
|
+
@ParamCount = _read_compressed_uint(io)
|
|
277
|
+
@ret_type = _read_RetType(io)
|
|
278
|
+
|
|
279
|
+
if @ParamCount < 255 # protect from malformed EXEs
|
|
280
|
+
@params = @ParamCount.times.map{ _read_Param(io) }
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
# https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2.1-methoddefsig.md
|
|
286
|
+
class MethodDefSig < Signature
|
|
287
|
+
attr_accessor :ret_type, :params
|
|
288
|
+
|
|
289
|
+
def initialize io
|
|
290
|
+
# "The first byte of the Signature holds bits for HASTHIS, EXPLICITTHIS, and the calling convention VARARG. These are ORed together."
|
|
291
|
+
@type = io.read(1).unpack1('C')
|
|
292
|
+
|
|
293
|
+
if @type & GENERIC == GENERIC
|
|
294
|
+
@GenParamCount = _read_compressed_uint(io)
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
@ParamCount = _read_compressed_uint(io)
|
|
298
|
+
@ret_type = _read_RetType(io)
|
|
299
|
+
|
|
300
|
+
if @ParamCount < 255 # protect from malformed EXEs
|
|
301
|
+
@params = @ParamCount.times.map{ _read_Param(io) }
|
|
302
|
+
end
|
|
303
|
+
end
|
|
304
|
+
end
|
|
305
|
+
|
|
306
|
+
# https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2.3-standalonemethodsig.md
|
|
307
|
+
class StandAloneMethodSig < MethodRefSig
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# https://github.com/stakx/ecma-335/blob/master/docs/ii.23.2.14-typespec.md
|
|
311
|
+
class TypeSpecBlob < Signature
|
|
312
|
+
def initialize io
|
|
313
|
+
@type = _read_Type(io)
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
end
|
|
318
|
+
end
|