rbkb 0.7.2 → 0.7.3
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 +5 -5
- data/.gitignore +1 -0
- data/Gemfile.lock +21 -13
- data/bin/b64 +2 -2
- data/bin/bgrep +2 -2
- data/bin/blit +2 -2
- data/bin/c +2 -2
- data/bin/crc32 +2 -2
- data/bin/d64 +2 -2
- data/bin/dedump +2 -2
- data/bin/feed +2 -2
- data/bin/hexify +2 -2
- data/bin/len +2 -2
- data/bin/plugsrv +66 -76
- data/bin/rex +1 -2
- data/bin/rstrings +2 -2
- data/bin/slice +2 -2
- data/bin/telson +2 -2
- data/bin/unhexify +2 -2
- data/bin/urldec +2 -2
- data/bin/urlenc +2 -2
- data/bin/xor +2 -2
- data/lib/rbkb/cli/b64.rb +6 -7
- data/lib/rbkb/cli/bgrep.rb +16 -17
- data/lib/rbkb/cli/blit.rb +29 -31
- data/lib/rbkb/cli/chars.rb +1 -2
- data/lib/rbkb/cli/crc32.rb +8 -10
- data/lib/rbkb/cli/d64.rb +3 -4
- data/lib/rbkb/cli/dedump.rb +15 -18
- data/lib/rbkb/cli/feed.rb +58 -64
- data/lib/rbkb/cli/hexify.rb +15 -16
- data/lib/rbkb/cli/len.rb +19 -27
- data/lib/rbkb/cli/rstrings.rb +41 -44
- data/lib/rbkb/cli/slice.rb +8 -15
- data/lib/rbkb/cli/telson.rb +33 -37
- data/lib/rbkb/cli/unhexify.rb +10 -11
- data/lib/rbkb/cli/urldec.rb +8 -9
- data/lib/rbkb/cli/urlenc.rb +8 -8
- data/lib/rbkb/cli/xor.rb +13 -14
- data/lib/rbkb/cli.rb +52 -65
- data/lib/rbkb/extends/array.rb +7 -8
- data/lib/rbkb/extends/common.rb +3 -5
- data/lib/rbkb/extends/enumerable.rb +9 -9
- data/lib/rbkb/extends/float.rb +1 -2
- data/lib/rbkb/extends/numeric.rb +29 -30
- data/lib/rbkb/extends/object.rb +1 -2
- data/lib/rbkb/extends/string.rb +172 -189
- data/lib/rbkb/extends/symbol.rb +2 -4
- data/lib/rbkb/extends.rb +0 -1
- data/lib/rbkb/plug/blit.rb +66 -69
- data/lib/rbkb/plug/cli.rb +22 -25
- data/lib/rbkb/plug/feed_import.rb +17 -21
- data/lib/rbkb/plug/peer.rb +11 -13
- data/lib/rbkb/plug/plug.rb +83 -91
- data/lib/rbkb/plug/proxy.rb +4 -8
- data/lib/rbkb/plug/unix_domain.rb +12 -14
- data/lib/rbkb/plug.rb +5 -6
- data/lib/rbkb/version.rb +1 -1
- data/lib/rbkb.rb +2 -3
- data/rbkb.gemspec +3 -3
- data/test/disabled_test_cli_blit.rb +1 -2
- data/test/disabled_test_cli_feed.rb +1 -2
- data/test/disabled_test_cli_telson.rb +1 -2
- data/test/test_cli_crc32.rb +1 -1
- data/test/test_cli_dedump.rb +83 -79
- data/test/test_cli_len.rb +25 -24
- data/test/test_cli_slice.rb +22 -22
- data/test/test_cli_xor.rb +4 -4
- metadata +18 -23
data/lib/rbkb/extends/string.rb
CHANGED
@@ -5,12 +5,12 @@ require 'cgi'
|
|
5
5
|
module Rbkb
|
6
6
|
module Extends
|
7
7
|
module String
|
8
|
-
# This is so disgusting... but str.encode('BINARY')
|
9
|
-
# fails hard whenever certain utf-8 characters
|
8
|
+
# This is so disgusting... but str.encode('BINARY')
|
9
|
+
# fails hard whenever certain utf-8 characters
|
10
10
|
# present. Try "\xca\xfe\xba\xbe".encode('BINARY')
|
11
11
|
# for kicks.
|
12
12
|
def force_to_binary
|
13
|
-
|
13
|
+
dup.force_encoding('binary')
|
14
14
|
end
|
15
15
|
|
16
16
|
def ishex?
|
@@ -21,24 +21,25 @@ module Rbkb
|
|
21
21
|
# @param [Hash] opts Optional parameters
|
22
22
|
# @option opts [optional, Boolean] :plus
|
23
23
|
# Treat + as a literal '+', instead of a space
|
24
|
-
def urlenc(opts={})
|
25
|
-
s=self
|
24
|
+
def urlenc(opts = {})
|
25
|
+
s = self
|
26
26
|
plus = opts[:plus]
|
27
|
-
unless (opts[:rx] ||= /[^A-Za-z0-9_
|
28
|
-
raise
|
27
|
+
unless (opts[:rx] ||= /[^A-Za-z0-9_.~-]/).is_a? Regexp
|
28
|
+
raise 'rx must be a regular expression for a character class'
|
29
29
|
end
|
30
|
+
|
30
31
|
hx = Rbkb::HEXCHARS
|
31
32
|
|
32
33
|
s.force_to_binary.gsub(opts[:rx]) do |c|
|
33
|
-
c=c.ord
|
34
|
-
(plus and c==32)? '+' :
|
34
|
+
c = c.ord
|
35
|
+
(plus and c == 32) ? '+' : '%' + (hx[(c >> 4)] + hx[(c & 0xf)])
|
35
36
|
end
|
36
37
|
end
|
37
38
|
|
38
39
|
# Base64 encode
|
39
|
-
def b64(len=nil)
|
40
|
-
ret = [self].pack(
|
41
|
-
if len and Numeric
|
40
|
+
def b64(len = nil)
|
41
|
+
ret = [self].pack('m').gsub("\n", '')
|
42
|
+
if len and len.is_a?(Numeric)
|
42
43
|
ret.scan(/.{1,#{len}}/).join("\n") + "\n"
|
43
44
|
else
|
44
45
|
ret
|
@@ -47,36 +48,36 @@ module Rbkb
|
|
47
48
|
|
48
49
|
# Base64 decode
|
49
50
|
def d64
|
50
|
-
|
51
|
+
unpack1('m')
|
51
52
|
end
|
52
53
|
|
53
54
|
# right-align to 'a' alignment padded with 'p'
|
54
|
-
def ralign(a, p=' ')
|
55
|
+
def ralign(a, p = ' ')
|
55
56
|
p ||= ' '
|
56
|
-
l =
|
57
|
+
l = bytesize
|
57
58
|
pad = l.pad(a)
|
58
|
-
|
59
|
+
rjust(pad + l, p)
|
59
60
|
end
|
60
61
|
|
61
62
|
# left-align to 'a' alignment padded with 'p'
|
62
|
-
def lalign(a, p=' ')
|
63
|
+
def lalign(a, p = ' ')
|
63
64
|
p ||= ' '
|
64
|
-
l =
|
65
|
+
l = bytesize
|
65
66
|
pad = l.pad(a)
|
66
|
-
|
67
|
+
ljust(pad + l, p)
|
67
68
|
end
|
68
69
|
|
69
70
|
# Undo percent-hexified url encoded string
|
70
71
|
# @param [Hash] opts Optional parameters
|
71
72
|
# @option opts [optional, Boolean] :noplus
|
72
73
|
# Treat + as a literal '+', instead of a space
|
73
|
-
def urldec(opts=nil)
|
74
|
+
def urldec(opts = nil)
|
74
75
|
if opts.nil? or opts.empty?
|
75
76
|
CGI.unescape(self)
|
76
77
|
else
|
77
|
-
s=self
|
78
|
+
s = self
|
78
79
|
s.gsub!('+', ' ') unless opts[:noplus]
|
79
|
-
s.gsub(/%([A-Fa-f0-9]{2})/) {
|
80
|
+
s.gsub(/%([A-Fa-f0-9]{2})/) { ::Regexp.last_match(1).hex.chr }
|
80
81
|
end
|
81
82
|
end
|
82
83
|
|
@@ -94,50 +95,48 @@ module Rbkb
|
|
94
95
|
# @option opts [String] :suffix
|
95
96
|
# suffix after each hex byte
|
96
97
|
#
|
97
|
-
def hexify(opts={})
|
98
|
+
def hexify(opts = {})
|
98
99
|
delim = opts[:delim]
|
99
|
-
pre =
|
100
|
-
suf =
|
100
|
+
pre = opts[:prefix] || ''
|
101
|
+
suf = opts[:suffix] || ''
|
101
102
|
|
102
|
-
if (rx=opts[:rx]) and
|
103
|
-
raise
|
103
|
+
if (rx = opts[:rx]) and !rx.is_a? Regexp
|
104
|
+
raise 'rx must be a regular expression for a character class'
|
104
105
|
end
|
105
106
|
|
106
|
-
hx=Rbkb::HEXCHARS
|
107
|
+
hx = Rbkb::HEXCHARS
|
107
108
|
|
108
|
-
out=
|
109
|
+
out = []
|
109
110
|
|
110
|
-
|
111
|
-
hc = if
|
112
|
-
c.chr
|
111
|
+
each_byte do |c|
|
112
|
+
hc = if rx and !rx.match c.chr
|
113
|
+
c.chr
|
113
114
|
else
|
114
|
-
pre + (hx[(c >> 4)] + hx[(c & 0xf
|
115
|
+
pre + (hx[(c >> 4)] + hx[(c & 0xf)]) + suf
|
115
116
|
end
|
116
|
-
out <<
|
117
|
+
out << hc
|
117
118
|
end
|
118
119
|
out.join(delim)
|
119
120
|
end
|
120
121
|
|
121
|
-
|
122
|
-
# Convert ASCII hex string to raw.
|
122
|
+
# Convert ASCII hex string to raw.
|
123
123
|
#
|
124
124
|
# @param [String] d optional 'delimiter' between hex bytes
|
125
125
|
# (zero+ spaces by default)
|
126
|
-
def unhexify(d
|
127
|
-
|
126
|
+
def unhexify(d = /\s*/)
|
127
|
+
force_to_binary.strip.gsub(/([A-Fa-f0-9]{1,2})#{d}?/) { ::Regexp.last_match(1).hex.chr }
|
128
128
|
end
|
129
129
|
|
130
130
|
# Converts a hex value to numeric.
|
131
131
|
#
|
132
132
|
# Parameters:
|
133
|
-
#
|
133
|
+
#
|
134
134
|
# order => :big or :little endian (default is :big)
|
135
135
|
#
|
136
|
-
def hex_to_num(order=Rbkb::DEFAULT_BYTE_ORDER)
|
137
|
-
|
136
|
+
def hex_to_num(order = Rbkb::DEFAULT_BYTE_ORDER)
|
137
|
+
unhexify.dat_to_num(order)
|
138
138
|
end
|
139
139
|
|
140
|
-
|
141
140
|
# A "generalized" lazy bytestring -> numeric converter.
|
142
141
|
#
|
143
142
|
# @param [Symbol] order :big or :little endian (default is :big)
|
@@ -149,15 +148,14 @@ module Rbkb
|
|
149
148
|
# >> ("\xFF"*20).dat_to_num
|
150
149
|
# => 1461501637330902918203684832716283019655932542975
|
151
150
|
#
|
152
|
-
def dat_to_num(order=Rbkb::DEFAULT_BYTE_ORDER)
|
153
|
-
b =
|
151
|
+
def dat_to_num(order = Rbkb::DEFAULT_BYTE_ORDER)
|
152
|
+
b = bytes
|
154
153
|
b = b.to_a.reverse if order == :little
|
155
154
|
r = 0
|
156
|
-
b.each {|c| r = ((r << 8) | c)}
|
155
|
+
b.each { |c| r = ((r << 8) | c) }
|
157
156
|
r
|
158
157
|
end
|
159
158
|
|
160
|
-
|
161
159
|
#### Crypto'ey stuff
|
162
160
|
|
163
161
|
# calculates entropy in string
|
@@ -167,18 +165,15 @@ module Rbkb
|
|
167
165
|
# string, in "bits of randomness per byte". This is useful, so..."
|
168
166
|
def entropy
|
169
167
|
e = 0
|
170
|
-
sz =
|
171
|
-
b =
|
168
|
+
sz = bytesize.to_f
|
169
|
+
b = bytes
|
172
170
|
0.upto(255) do |i|
|
173
|
-
x = b.count(i)/sz
|
174
|
-
if x > 0
|
175
|
-
e += - x * (Math.log(x)/Math.log(2))
|
176
|
-
end
|
171
|
+
x = b.count(i) / sz
|
172
|
+
e += - x * (Math.log(x) / Math.log(2)) if x > 0
|
177
173
|
end
|
178
174
|
e
|
179
175
|
end
|
180
176
|
|
181
|
-
|
182
177
|
# Produces a character frequency distribution histogram in descending
|
183
178
|
# order. Example:
|
184
179
|
#
|
@@ -194,66 +189,63 @@ module Rbkb
|
|
194
189
|
#
|
195
190
|
def char_frequency
|
196
191
|
hits = {}
|
197
|
-
|
198
|
-
|
192
|
+
each_byte do |c|
|
193
|
+
hits[c.chr] ||= 0
|
194
|
+
hits[c.chr] += 1
|
195
|
+
end
|
196
|
+
hits.to_a.sort { |a, b| b[1] <=> a[1] }
|
199
197
|
end
|
200
198
|
|
201
199
|
# xor against a key. key will be repeated or truncated to self.size.
|
202
200
|
def xor(k)
|
203
|
-
i=0
|
204
|
-
|
205
|
-
x = k.getbyte(i) || k.getbyte(i=0)
|
206
|
-
i+=1
|
201
|
+
i = 0
|
202
|
+
bytes.map do |b|
|
203
|
+
x = k.getbyte(i) || k.getbyte(i = 0)
|
204
|
+
i += 1
|
207
205
|
(b ^ x).chr
|
208
206
|
end.join
|
209
207
|
end
|
210
208
|
|
211
|
-
|
212
|
-
# (en|de)ciphers using a substition cipher en/decoder ring in the form of a
|
209
|
+
# (en|de)ciphers using a substition cipher en/decoder ring in the form of a
|
213
210
|
# hash with orig => substitute mappings
|
214
211
|
def substitution(keymap)
|
215
|
-
split('').map {|c| (sub=keymap[c]) ? sub : c }.join
|
212
|
+
split('').map { |c| (sub = keymap[c]) ? sub : c }.join
|
216
213
|
end
|
217
214
|
|
218
|
-
|
219
|
-
#
|
220
|
-
#
|
221
|
-
# char_frequency, this sometimes provides a shorter way to derive a single
|
215
|
+
# (en|de)crypts using a substition xor en/decoder ring in the form of
|
216
|
+
# a hash with orig => substitute mappings. Used in conjunction with
|
217
|
+
# char_frequency, this sometimes provides a shorter way to derive a single
|
222
218
|
# character xor key used in conjunction with char_frequency.
|
223
219
|
def substitution_xor(keymap)
|
224
|
-
split('').map {|c| (sub=keymap[c]) ? sub.xor(c) : c }.join
|
220
|
+
split('').map { |c| (sub = keymap[c]) ? sub.xor(c) : c }.join
|
225
221
|
end
|
226
222
|
|
227
|
-
|
228
223
|
# convert bytes to number then xor against another byte-string or number
|
229
|
-
def ^(
|
230
|
-
|
231
|
-
(
|
224
|
+
def ^(other)
|
225
|
+
other = other.dat_to_num unless other.is_a? Numeric
|
226
|
+
(dat_to_num ^ other) # .to_bytes
|
232
227
|
end
|
233
228
|
|
234
|
-
|
235
229
|
# Byte rotation as found in lame ciphers.
|
236
|
-
def rotate_bytes(k=0)
|
230
|
+
def rotate_bytes(k = 0)
|
237
231
|
k = (256 + k) if k < 0
|
238
|
-
|
232
|
+
bytes.map { |c| ((c + k) & 0xff).chr }.join
|
239
233
|
end
|
240
234
|
|
241
|
-
|
242
235
|
# String randomizer
|
243
236
|
def randomize
|
244
|
-
|
237
|
+
split('').randomize.to_s
|
245
238
|
end
|
246
239
|
|
247
|
-
|
248
240
|
# In-place string randomizer
|
249
241
|
def randomize!
|
250
|
-
|
242
|
+
replace(randomize)
|
251
243
|
end
|
252
244
|
|
253
245
|
# Does string "start with" dat?
|
254
246
|
# No clue whether/when this is faster than a regex, but it is easier to type.
|
255
247
|
def starts_with?(dat)
|
256
|
-
|
248
|
+
index(dat) == 0
|
257
249
|
end
|
258
250
|
|
259
251
|
# Returns a single null-terminated ascii string from beginning of self.
|
@@ -263,8 +255,8 @@ module Rbkb
|
|
263
255
|
#
|
264
256
|
# off = specify an optional beggining offset
|
265
257
|
#
|
266
|
-
def cstring(off=0)
|
267
|
-
self[
|
258
|
+
def cstring(off = 0)
|
259
|
+
self[off, (index("\x00") || size)]
|
268
260
|
end
|
269
261
|
|
270
262
|
# returns CRC32 checksum for the string object
|
@@ -284,7 +276,7 @@ module Rbkb
|
|
284
276
|
|
285
277
|
# @return [Digest::MD5] the MD5 digest/checksum for this string.
|
286
278
|
def md5
|
287
|
-
d=Digest::MD5.new
|
279
|
+
d = Digest::MD5.new
|
288
280
|
d.update(self)
|
289
281
|
d
|
290
282
|
end
|
@@ -292,14 +284,14 @@ module Rbkb
|
|
292
284
|
|
293
285
|
# @return [Digest::SHA1] the SHA1 digest for this string.
|
294
286
|
def sha1
|
295
|
-
d=Digest::SHA1.new
|
287
|
+
d = Digest::SHA1.new
|
296
288
|
d.update(self)
|
297
289
|
d
|
298
290
|
end
|
299
291
|
|
300
292
|
# @return [Digest::SHA2] the SHA2 digest for this string.
|
301
293
|
def sha2
|
302
|
-
d=Digest::SHA2.new
|
294
|
+
d = Digest::SHA2.new
|
303
295
|
d.update(self)
|
304
296
|
d
|
305
297
|
end
|
@@ -309,58 +301,59 @@ module Rbkb
|
|
309
301
|
# (using popen3 because IO.popen blows)
|
310
302
|
# Tried doing this with a fmagic ruby extention to libmagic, but it was
|
311
303
|
# a whole lot slower.
|
312
|
-
def pipe_magick(arg=
|
313
|
-
ret=
|
314
|
-
Open3.popen3("file #{arg} -") do |w,r,
|
315
|
-
w.write self
|
316
|
-
|
317
|
-
ret
|
304
|
+
def pipe_magick(arg = '')
|
305
|
+
ret = ''
|
306
|
+
Open3.popen3("file #{arg} -") do |w, r, _e|
|
307
|
+
w.write self
|
308
|
+
w.close
|
309
|
+
ret = r.read
|
310
|
+
r.close
|
311
|
+
ret.sub!(%r{^/dev/stdin: }, '')
|
318
312
|
end
|
319
313
|
ret
|
320
314
|
end
|
321
315
|
|
322
|
-
# Converts a '_' delimited string to CamelCase like 'foo_class' into
|
316
|
+
# Converts a '_' delimited string to CamelCase like 'foo_class' into
|
323
317
|
# 'FooClass'.
|
324
318
|
# See also: camelize_meth, decamelize
|
325
319
|
def camelize
|
326
|
-
|
320
|
+
gsub(/(^|_)([a-z])/) { ::Regexp.last_match(2).upcase }
|
327
321
|
end
|
328
322
|
|
329
323
|
# Converts a '_' delimited string to method style camelCase like 'foo_method'
|
330
324
|
# into 'fooMethod'.
|
331
325
|
# See also: camelize, decamelize
|
332
326
|
def camelize_meth
|
333
|
-
|
327
|
+
gsub(/_([a-z])/) { ::Regexp.last_match(1).upcase }
|
334
328
|
end
|
335
329
|
|
336
|
-
|
337
330
|
# Converts a CamelCase or camelCase string into '_' delimited form like
|
338
|
-
# 'FooBar' or 'fooBar' into 'foo_bar'.
|
331
|
+
# 'FooBar' or 'fooBar' into 'foo_bar'.
|
339
332
|
#
|
340
|
-
# Note: This method only handles camel humps. Strings with consecutive
|
333
|
+
# Note: This method only handles camel humps. Strings with consecutive
|
341
334
|
# uppercase chars like 'FooBAR' will be converted to 'foo_bar'
|
342
335
|
#
|
343
336
|
# See also: camelize, camelize_meth
|
344
337
|
def decamelize
|
345
|
-
|
346
|
-
(
|
338
|
+
gsub(/(^|[a-z])([A-Z])/) do
|
339
|
+
::Regexp.last_match(1).empty? ? ::Regexp.last_match(2) : "#{::Regexp.last_match(1)}_#{::Regexp.last_match(2)}"
|
347
340
|
end.downcase
|
348
341
|
end
|
349
342
|
|
350
343
|
# convert a string to its idiomatic ruby class name
|
351
344
|
def class_name
|
352
|
-
r =
|
345
|
+
r = ''
|
353
346
|
up = true
|
354
347
|
each_byte do |c|
|
355
348
|
if c == 95
|
356
349
|
if up
|
357
|
-
r <<
|
350
|
+
r << '::'
|
358
351
|
else
|
359
352
|
up = true
|
360
353
|
end
|
361
354
|
else
|
362
355
|
m = up ? :upcase : :to_s
|
363
|
-
r <<
|
356
|
+
r << c.chr.send(m)
|
364
357
|
up = false
|
365
358
|
end
|
366
359
|
end
|
@@ -369,8 +362,8 @@ module Rbkb
|
|
369
362
|
|
370
363
|
# Returns a reference to actual constant for a given name in namespace
|
371
364
|
# can be used to lookup classes from enums and such
|
372
|
-
def const_lookup(ns=Object)
|
373
|
-
if c=ns.constants.select {|n| n ==
|
365
|
+
def const_lookup(ns = Object)
|
366
|
+
if c = ns.constants.select { |n| n == class_name } and !c.empty?
|
374
367
|
ns.const_get(c.first)
|
375
368
|
end
|
376
369
|
end
|
@@ -382,11 +375,11 @@ module Rbkb
|
|
382
375
|
|
383
376
|
# Returns or prints a hexdump in the style of 'hexdump -C'
|
384
377
|
#
|
385
|
-
# :len => optionally specify a length other than 16 for a wider or thinner
|
378
|
+
# :len => optionally specify a length other than 16 for a wider or thinner
|
386
379
|
# dump. If length is an odd number, it will be rounded up.
|
387
380
|
#
|
388
381
|
# :out => optionally specify an alternate IO object for output. By default,
|
389
|
-
# hexdump will output to STDOUT. Pass a StringIO object and it will return
|
382
|
+
# hexdump will output to STDOUT. Pass a StringIO object and it will return
|
390
383
|
# it as a string.
|
391
384
|
#
|
392
385
|
# Example:
|
@@ -402,29 +395,29 @@ module Rbkb
|
|
402
395
|
# <prints hexdump on STDERR>
|
403
396
|
# -> nil # return value is nil!
|
404
397
|
#
|
405
|
-
def hexdump(opt={})
|
406
|
-
s=self
|
398
|
+
def hexdump(opt = {})
|
399
|
+
s = self
|
407
400
|
out = opt[:out] || StringIO.new
|
408
|
-
len = (opt[:len] and opt[:len] > 0)? opt[:len] + (opt[:len] % 2) : 16
|
401
|
+
len = (opt[:len] and opt[:len] > 0) ? opt[:len] + (opt[:len] % 2) : 16
|
409
402
|
|
410
403
|
off = opt[:start_addr] || 0
|
411
404
|
offlen = opt[:start_len] || 8
|
412
405
|
|
413
|
-
hlen=len/2
|
406
|
+
hlen = len / 2
|
414
407
|
|
415
408
|
s.bytes.each_slice(len) do |m|
|
416
|
-
out.write(off.to_s(16).rjust(offlen,
|
409
|
+
out.write(off.to_s(16).rjust(offlen, '0') + ' ')
|
417
410
|
|
418
|
-
i=0
|
411
|
+
i = 0
|
419
412
|
m.each do |c|
|
420
|
-
out.write
|
421
|
-
out.write(' ') if (i+=1) == hlen
|
413
|
+
out.write '%0.2x ' % c
|
414
|
+
out.write(' ') if (i += 1) == hlen
|
422
415
|
end
|
423
416
|
|
424
|
-
out.write(
|
425
|
-
out.write(
|
417
|
+
out.write(' ' * (len - i)) # pad
|
418
|
+
out.write(' ') if i < hlen
|
426
419
|
|
427
|
-
out.write(
|
420
|
+
out.write(' |')
|
428
421
|
m.each do |c|
|
429
422
|
if c > 0x19 and c < 0x7f
|
430
423
|
out.write(c.chr)
|
@@ -436,96 +429,89 @@ module Rbkb
|
|
436
429
|
off += m.length
|
437
430
|
end
|
438
431
|
|
439
|
-
out.write(off.to_s(16).rjust(offlen,'0') + "\n")
|
432
|
+
out.write(off.to_s(16).rjust(offlen, '0') + "\n")
|
440
433
|
|
441
|
-
|
442
|
-
out.string
|
443
|
-
end
|
444
|
-
end
|
434
|
+
return unless out.class == StringIO
|
445
435
|
|
436
|
+
out.string
|
437
|
+
end
|
446
438
|
|
447
439
|
# Converts a hexdump back to binary - takes the same options as hexdump().
|
448
440
|
# Fairly flexible. Should work both with 'xxd' and 'hexdump -C' style dumps.
|
449
|
-
def dehexdump(opt={})
|
450
|
-
s=self
|
441
|
+
def dehexdump(opt = {})
|
442
|
+
s = self
|
451
443
|
out = opt[:out] || StringIO.new
|
452
|
-
|
444
|
+
l = opt[:len]
|
445
|
+
len = l && l.positive? ? opt[:len] : 16
|
453
446
|
|
454
447
|
hcrx = /[A-Fa-f0-9]/
|
455
448
|
dumprx = /^(#{hcrx}+):?\s*((?:#{hcrx}{2}\s*){0,#{len}})/
|
456
|
-
|
449
|
+
off = opt[:start_addr] || 0
|
457
450
|
|
458
|
-
i=1
|
451
|
+
i = 1
|
459
452
|
# iterate each line of hexdump
|
460
453
|
s.split(/\r?\n/).each do |hl|
|
461
454
|
# match and check offset
|
462
|
-
|
463
|
-
i+=1
|
464
|
-
# take the data chunk and unhexify it
|
465
|
-
raw = $2.unhexify
|
466
|
-
off += out.write(raw)
|
467
|
-
else
|
468
|
-
raise "Hexdump parse error on line #{i} #{s}"
|
469
|
-
end
|
470
|
-
end
|
455
|
+
raise "Hexdump parse error on line #{i} #{s}" unless dumprx.match(hl) && ::Regexp.last_match(1).hex == off
|
471
456
|
|
472
|
-
|
473
|
-
|
457
|
+
i += 1
|
458
|
+
# take the data chunk and unhexify it
|
459
|
+
raw = ::Regexp.last_match(2).unhexify
|
460
|
+
off += out.write(raw)
|
474
461
|
end
|
462
|
+
|
463
|
+
return unless out.instance_of?(StringIO)
|
464
|
+
|
465
|
+
out.string.force_to_binary
|
475
466
|
end
|
476
467
|
alias dedump dehexdump
|
477
468
|
alias undump dehexdump
|
478
469
|
alias unhexdump dehexdump
|
479
470
|
|
480
|
-
|
481
471
|
# Binary grep
|
482
|
-
#
|
472
|
+
#
|
483
473
|
# Parameters:
|
484
474
|
#
|
485
475
|
# find : A Regexp or string to search for in self
|
486
476
|
# align : nil | numeric alignment (matches only made if aligned)
|
487
|
-
def bgrep(find, align=nil)
|
488
|
-
if align and (
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
end
|
507
|
-
end
|
477
|
+
def bgrep(find, align = nil)
|
478
|
+
raise 'alignment must be a integer >= 0' if align and (!align.is_a?(Integer) or align < 0)
|
479
|
+
|
480
|
+
dat = self
|
481
|
+
search = if find.is_a? Regexp
|
482
|
+
lambda do |mf, buf|
|
483
|
+
if m = mf.match(buf)
|
484
|
+
mtch = m[0]
|
485
|
+
off, endoff = m.offset(0)
|
486
|
+
[off, endoff, mtch]
|
487
|
+
end
|
488
|
+
end
|
489
|
+
else
|
490
|
+
lambda do |s, buf|
|
491
|
+
if off = buf.index(s)
|
492
|
+
[off, off + s.size, s]
|
493
|
+
end
|
494
|
+
end
|
495
|
+
end
|
508
496
|
|
509
|
-
ret=[]
|
497
|
+
ret = []
|
510
498
|
pos = 0
|
511
499
|
while (res = search.call(find, dat[pos..-1].force_to_binary))
|
512
500
|
off, endoff, match = res
|
513
|
-
if align and (
|
501
|
+
if align and (pad = (pos + off).pad(align)) != 0
|
514
502
|
pos += pad
|
515
503
|
else
|
516
|
-
hit = [pos+off, pos+endoff, match]
|
517
|
-
if
|
518
|
-
ret << hit
|
519
|
-
end
|
504
|
+
hit = [pos + off, pos + endoff, match]
|
505
|
+
ret << hit if !block_given? or yield([pos + off, pos + endoff, match])
|
520
506
|
pos += endoff
|
521
507
|
end
|
522
508
|
end
|
523
|
-
|
509
|
+
ret
|
524
510
|
end
|
525
511
|
|
526
512
|
# A 'strings' method a-la unix strings utility. Finds printable strings in
|
527
513
|
# a binary blob.
|
528
|
-
# Supports ASCII and little endian unicode (though only for ASCII printable
|
514
|
+
# Supports ASCII and little endian unicode (though only for ASCII printable
|
529
515
|
# character.)
|
530
516
|
#
|
531
517
|
# === Parameters and options:
|
@@ -542,7 +528,7 @@ module Rbkb
|
|
542
528
|
#
|
543
529
|
# * Supports an optional block, which will be passed |offset, type, string|
|
544
530
|
# for each match.
|
545
|
-
# The block's boolean return value also determines whether the match
|
531
|
+
# The block's boolean return value also determines whether the match
|
546
532
|
# passes or fails (true or false/nil) and gets returned by the function.
|
547
533
|
#
|
548
534
|
# === Return Value:
|
@@ -555,18 +541,18 @@ module Rbkb
|
|
555
541
|
# * end_offset will include the terminating null character
|
556
542
|
# * end_offset will include all null bytes in unicode strings (including
|
557
543
|
# * both terminating nulls)
|
558
|
-
#
|
544
|
+
#
|
559
545
|
# If strings are null terminated, the trailing null *IS* included
|
560
546
|
# in the end_offset. Unicode matches will also include null bytes.
|
561
547
|
#
|
562
548
|
# Todos?
|
563
549
|
# - better unicode support (i.e. not using half-assed unicode)
|
564
550
|
# - support other encodings such as all those the binutils strings does?
|
565
|
-
def strings(opts={})
|
551
|
+
def strings(opts = {})
|
566
552
|
opts[:encoding] ||= :both
|
567
|
-
min =
|
553
|
+
min = opts[:minimum] || 6
|
568
554
|
|
569
|
-
raise
|
555
|
+
raise 'Minimum must be numeric and > 0' unless min.is_a? Numeric and min > 0
|
570
556
|
|
571
557
|
acc = /[\s[:print:]]/
|
572
558
|
ucc = /(?:#{acc}\x00)/
|
@@ -575,41 +561,39 @@ module Rbkb
|
|
575
561
|
urx = /(#{ucc}{#{min}}#{ucc}*(?:\x00\x00)?)/
|
576
562
|
|
577
563
|
rx = case (opts[:encoding] || :both).to_sym
|
578
|
-
when :ascii
|
579
|
-
mtype_blk =
|
564
|
+
when :ascii
|
565
|
+
mtype_blk = ->(_x) { :ascii }
|
580
566
|
arx
|
581
|
-
when :unicode
|
582
|
-
mtype_blk =
|
567
|
+
when :unicode
|
568
|
+
mtype_blk = ->(_x) { :unicode }
|
583
569
|
urx
|
584
|
-
when :both
|
585
|
-
mtype_blk =
|
570
|
+
when :both
|
571
|
+
mtype_blk = ->(x) { x[2].nil? ? :ascii : :unicode }
|
586
572
|
|
587
|
-
Regexp.union(
|
588
|
-
else
|
589
|
-
raise
|
573
|
+
Regexp.union(arx, urx)
|
574
|
+
else
|
575
|
+
raise 'Encoding must be :unicode, :ascii, or :both'
|
590
576
|
end
|
591
577
|
|
592
578
|
ret = []
|
593
579
|
|
594
580
|
# wow ruby 1.9 string encoding is a total cluster
|
595
|
-
|
581
|
+
force_to_binary.scan(rx) do
|
596
582
|
mtch = $~
|
597
583
|
|
598
584
|
stype = mtype_blk.call(mtch)
|
599
585
|
|
600
586
|
startoff, endoff = mtch.offset(0)
|
601
|
-
mret = [startoff, endoff, stype, mtch[0]
|
587
|
+
mret = [startoff, endoff, stype, mtch[0]]
|
602
588
|
|
603
589
|
# yield to a block for additional criteria
|
604
|
-
next if block_given? and
|
590
|
+
next if block_given? and !yield(*mret)
|
605
591
|
|
606
592
|
ret << mret
|
607
593
|
end
|
608
594
|
|
609
|
-
|
595
|
+
ret
|
610
596
|
end
|
611
|
-
|
612
|
-
|
613
597
|
end
|
614
598
|
end
|
615
599
|
end
|
@@ -621,4 +605,3 @@ end
|
|
621
605
|
def RbkbString(x)
|
622
606
|
RbkbString.new(x)
|
623
607
|
end
|
624
|
-
|