origami 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING.LESSER +165 -0
- data/README +77 -0
- data/VERSION +1 -0
- data/bin/config/pdfcop.conf.yml +237 -0
- data/bin/gui/about.rb +46 -0
- data/bin/gui/config.rb +132 -0
- data/bin/gui/file.rb +385 -0
- data/bin/gui/hexdump.rb +74 -0
- data/bin/gui/hexview.rb +91 -0
- data/bin/gui/imgview.rb +72 -0
- data/bin/gui/menu.rb +392 -0
- data/bin/gui/properties.rb +132 -0
- data/bin/gui/signing.rb +635 -0
- data/bin/gui/textview.rb +107 -0
- data/bin/gui/treeview.rb +409 -0
- data/bin/gui/walker.rb +282 -0
- data/bin/gui/xrefs.rb +79 -0
- data/bin/pdf2graph +121 -0
- data/bin/pdf2ruby +353 -0
- data/bin/pdfcocoon +104 -0
- data/bin/pdfcop +455 -0
- data/bin/pdfdecompress +104 -0
- data/bin/pdfdecrypt +95 -0
- data/bin/pdfencrypt +112 -0
- data/bin/pdfextract +221 -0
- data/bin/pdfmetadata +123 -0
- data/bin/pdfsh +13 -0
- data/bin/pdfwalker +7 -0
- data/bin/shell/.irbrc +104 -0
- data/bin/shell/console.rb +136 -0
- data/bin/shell/hexdump.rb +83 -0
- data/origami.rb +36 -0
- data/origami/3d.rb +239 -0
- data/origami/acroform.rb +321 -0
- data/origami/actions.rb +299 -0
- data/origami/adobe/fdf.rb +259 -0
- data/origami/adobe/ppklite.rb +489 -0
- data/origami/annotations.rb +775 -0
- data/origami/array.rb +187 -0
- data/origami/boolean.rb +101 -0
- data/origami/catalog.rb +486 -0
- data/origami/destinations.rb +213 -0
- data/origami/dictionary.rb +188 -0
- data/origami/docmdp.rb +96 -0
- data/origami/encryption.rb +1293 -0
- data/origami/export.rb +283 -0
- data/origami/file.rb +222 -0
- data/origami/filters.rb +250 -0
- data/origami/filters/ascii.rb +189 -0
- data/origami/filters/ccitt.rb +515 -0
- data/origami/filters/crypt.rb +47 -0
- data/origami/filters/dct.rb +61 -0
- data/origami/filters/flate.rb +112 -0
- data/origami/filters/jbig2.rb +63 -0
- data/origami/filters/jpx.rb +53 -0
- data/origami/filters/lzw.rb +195 -0
- data/origami/filters/predictors.rb +276 -0
- data/origami/filters/runlength.rb +117 -0
- data/origami/font.rb +209 -0
- data/origami/functions.rb +93 -0
- data/origami/graphics.rb +33 -0
- data/origami/graphics/colors.rb +191 -0
- data/origami/graphics/instruction.rb +126 -0
- data/origami/graphics/path.rb +154 -0
- data/origami/graphics/patterns.rb +180 -0
- data/origami/graphics/state.rb +164 -0
- data/origami/graphics/text.rb +224 -0
- data/origami/graphics/xobject.rb +493 -0
- data/origami/header.rb +90 -0
- data/origami/linearization.rb +318 -0
- data/origami/metadata.rb +114 -0
- data/origami/name.rb +170 -0
- data/origami/null.rb +75 -0
- data/origami/numeric.rb +188 -0
- data/origami/obfuscation.rb +233 -0
- data/origami/object.rb +527 -0
- data/origami/outline.rb +59 -0
- data/origami/page.rb +559 -0
- data/origami/parser.rb +268 -0
- data/origami/parsers/fdf.rb +45 -0
- data/origami/parsers/pdf.rb +27 -0
- data/origami/parsers/pdf/linear.rb +113 -0
- data/origami/parsers/ppklite.rb +86 -0
- data/origami/pdf.rb +1144 -0
- data/origami/reference.rb +113 -0
- data/origami/signature.rb +474 -0
- data/origami/stream.rb +575 -0
- data/origami/string.rb +416 -0
- data/origami/trailer.rb +173 -0
- data/origami/webcapture.rb +87 -0
- data/origami/xfa.rb +3027 -0
- data/origami/xreftable.rb +447 -0
- data/templates/patterns.rb +66 -0
- data/templates/widgets.rb +173 -0
- data/templates/xdp.rb +92 -0
- data/tests/dataset/test.dummycrt +28 -0
- data/tests/dataset/test.dummykey +27 -0
- data/tests/tc_actions.rb +32 -0
- data/tests/tc_annotations.rb +85 -0
- data/tests/tc_pages.rb +37 -0
- data/tests/tc_pdfattach.rb +24 -0
- data/tests/tc_pdfencrypt.rb +110 -0
- data/tests/tc_pdfnew.rb +32 -0
- data/tests/tc_pdfparse.rb +98 -0
- data/tests/tc_pdfsig.rb +37 -0
- data/tests/tc_streams.rb +129 -0
- data/tests/ts_pdf.rb +45 -0
- metadata +193 -0
data/origami/name.rb
ADDED
@@ -0,0 +1,170 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
= File
|
4
|
+
name.rb
|
5
|
+
|
6
|
+
= Info
|
7
|
+
This file is part of Origami, PDF manipulation framework for Ruby
|
8
|
+
Copyright (C) 2010 Guillaume Delugré <guillaume@security-labs.org>
|
9
|
+
All right reserved.
|
10
|
+
|
11
|
+
Origami is free software: you can redistribute it and/or modify
|
12
|
+
it under the terms of the GNU Lesser General Public License as published by
|
13
|
+
the Free Software Foundation, either version 3 of the License, or
|
14
|
+
(at your option) any later version.
|
15
|
+
|
16
|
+
Origami is distributed in the hope that it will be useful,
|
17
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
18
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
19
|
+
GNU Lesser General Public License for more details.
|
20
|
+
|
21
|
+
You should have received a copy of the GNU Lesser General Public License
|
22
|
+
along with Origami. If not, see <http://www.gnu.org/licenses/>.
|
23
|
+
|
24
|
+
=end
|
25
|
+
|
26
|
+
if RUBY_VERSION < '1.9'
|
27
|
+
class EmptySymbol
|
28
|
+
def ==(sym)
|
29
|
+
sym.is_a?(EmptySymbol)
|
30
|
+
end
|
31
|
+
|
32
|
+
def id2name
|
33
|
+
""
|
34
|
+
end
|
35
|
+
alias to_s id2name
|
36
|
+
|
37
|
+
def to_sym
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_o
|
42
|
+
Name.new("")
|
43
|
+
end
|
44
|
+
|
45
|
+
def inspect
|
46
|
+
":"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
module Origami
|
52
|
+
|
53
|
+
REGULARCHARS = "([^ \\t\\r\\n\\0\\[\\]<>()%\\/]|#[a-fA-F0-9][a-fA-F0-9])*" #:nodoc:
|
54
|
+
|
55
|
+
class InvalidNameObjectError < InvalidObjectError #:nodoc:
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
# Class representing a Name Object.
|
60
|
+
# Name objects are strings which identify some PDF file inner structures.
|
61
|
+
#
|
62
|
+
class Name #< DelegateClass(Symbol)
|
63
|
+
|
64
|
+
include Origami::Object
|
65
|
+
|
66
|
+
TOKENS = %w{ / } #:nodoc:
|
67
|
+
|
68
|
+
@@regexp = Regexp.new(WHITESPACES + TOKENS.first + "(" + REGULARCHARS + ")" + WHITESPACES) #:nodoc
|
69
|
+
|
70
|
+
#
|
71
|
+
# Creates a new Name.
|
72
|
+
# _name_:: A symbol representing the new Name value.
|
73
|
+
#
|
74
|
+
def initialize(name = "")
|
75
|
+
unless name.is_a?(Symbol) or name.is_a?(::String)
|
76
|
+
raise TypeError, "Expected type Symbol or String, received #{name.class}."
|
77
|
+
end
|
78
|
+
|
79
|
+
@value = name.to_s
|
80
|
+
|
81
|
+
super()
|
82
|
+
end
|
83
|
+
|
84
|
+
if RUBY_VERSION < '1.9'
|
85
|
+
def value
|
86
|
+
( @value.empty? ) ? EmptySymbol.new : @value.to_sym
|
87
|
+
end
|
88
|
+
else
|
89
|
+
def value
|
90
|
+
@value.to_sym
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def ==(object) #:nodoc:
|
95
|
+
@value.to_sym == object
|
96
|
+
end
|
97
|
+
|
98
|
+
def eql?(object) #:nodoc:
|
99
|
+
object.is_a?(Name) and self.to_s == object.to_s
|
100
|
+
end
|
101
|
+
|
102
|
+
def hash #:nodoc:
|
103
|
+
@value.hash
|
104
|
+
end
|
105
|
+
|
106
|
+
def to_s #:nodoc:
|
107
|
+
super(TOKENS.first + Name.expand(@value))
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.parse(stream) #:nodoc:
|
111
|
+
|
112
|
+
offset = stream.pos
|
113
|
+
|
114
|
+
name =
|
115
|
+
if stream.scan(@@regexp).nil?
|
116
|
+
raise InvalidNameObjectError, "Bad name format"
|
117
|
+
else
|
118
|
+
value = stream[2]
|
119
|
+
|
120
|
+
Name.new(value.include?('#') ? contract(value) : value)
|
121
|
+
end
|
122
|
+
|
123
|
+
name.file_offset = offset
|
124
|
+
|
125
|
+
name
|
126
|
+
end
|
127
|
+
|
128
|
+
def self.contract(name) #:nodoc:
|
129
|
+
|
130
|
+
i = 0
|
131
|
+
while i < name.length
|
132
|
+
|
133
|
+
if name[i,1] == "#"
|
134
|
+
digits = name[i+1, 2]
|
135
|
+
|
136
|
+
unless /^[A-Za-z0-9]{2}$/ === digits
|
137
|
+
raise InvalidNameObjectError, "Irregular use of # token"
|
138
|
+
end
|
139
|
+
|
140
|
+
char = digits.hex.chr
|
141
|
+
|
142
|
+
if char == "\0"
|
143
|
+
raise InvalidNameObjectError, "Null byte forbidden inside name definition"
|
144
|
+
end
|
145
|
+
|
146
|
+
name[i, 3] = char
|
147
|
+
end
|
148
|
+
|
149
|
+
i = i + 1
|
150
|
+
end
|
151
|
+
|
152
|
+
name
|
153
|
+
end
|
154
|
+
|
155
|
+
def self.expand(name) #:nodoc:
|
156
|
+
|
157
|
+
forbiddenchars = /[ #\t\r\n\0\[\]<>()%\/]/
|
158
|
+
|
159
|
+
name.gsub!(forbiddenchars) do |c|
|
160
|
+
"#" + c[0].ord.to_s(16).rjust(2,"0")
|
161
|
+
end
|
162
|
+
|
163
|
+
name
|
164
|
+
end
|
165
|
+
|
166
|
+
def real_type ; Name end
|
167
|
+
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
data/origami/null.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
= File
|
4
|
+
null.rb
|
5
|
+
|
6
|
+
= Info
|
7
|
+
This file is part of Origami, PDF manipulation framework for Ruby
|
8
|
+
Copyright (C) 2010 Guillaume Delugr� <guillaume@security-labs.org>
|
9
|
+
All right reserved.
|
10
|
+
|
11
|
+
Origami is free software: you can redistribute it and/or modify
|
12
|
+
it under the terms of the GNU Lesser General Public License as published by
|
13
|
+
the Free Software Foundation, either version 3 of the License, or
|
14
|
+
(at your option) any later version.
|
15
|
+
|
16
|
+
Origami is distributed in the hope that it will be useful,
|
17
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
18
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
19
|
+
GNU Lesser General Public License for more details.
|
20
|
+
|
21
|
+
You should have received a copy of the GNU Lesser General Public License
|
22
|
+
along with Origami. If not, see <http://www.gnu.org/licenses/>.
|
23
|
+
|
24
|
+
=end
|
25
|
+
|
26
|
+
module Origami
|
27
|
+
|
28
|
+
class InvalidNullObjectError < InvalidObjectError #:nodoc:
|
29
|
+
end
|
30
|
+
|
31
|
+
#
|
32
|
+
# Class representing Null Object.
|
33
|
+
#
|
34
|
+
class Null
|
35
|
+
|
36
|
+
include Origami::Object
|
37
|
+
|
38
|
+
TOKENS = %w{ null } #:nodoc:
|
39
|
+
|
40
|
+
@@regexp = Regexp.new(WHITESPACES + TOKENS.first)
|
41
|
+
|
42
|
+
def initialize
|
43
|
+
super
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.parse(stream) #:nodoc:
|
47
|
+
|
48
|
+
offset = stream.pos
|
49
|
+
|
50
|
+
if stream.skip(@@regexp).nil?
|
51
|
+
raise InvalidNullObjectError
|
52
|
+
end
|
53
|
+
|
54
|
+
null = Null.new
|
55
|
+
null.file_offset = offset
|
56
|
+
|
57
|
+
null
|
58
|
+
end
|
59
|
+
|
60
|
+
#
|
61
|
+
# Returns *nil*.
|
62
|
+
#
|
63
|
+
def value
|
64
|
+
nil
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_s #:nodoc:
|
68
|
+
super(TOKENS.first)
|
69
|
+
end
|
70
|
+
|
71
|
+
def real_type ; Null end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
data/origami/numeric.rb
ADDED
@@ -0,0 +1,188 @@
|
|
1
|
+
=begin
|
2
|
+
|
3
|
+
= File
|
4
|
+
numeric.rb
|
5
|
+
|
6
|
+
= Info
|
7
|
+
Origami is free software: you can redistribute it and/or modify
|
8
|
+
it under the terms of the GNU Lesser General Public License as published by
|
9
|
+
the Free Software Foundation, either version 3 of the License, or
|
10
|
+
(at your option) any later version.
|
11
|
+
|
12
|
+
Origami is distributed in the hope that it will be useful,
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
GNU Lesser General Public License for more details.
|
16
|
+
|
17
|
+
You should have received a copy of the GNU Lesser General Public License
|
18
|
+
along with Origami. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
=end
|
21
|
+
|
22
|
+
require 'delegate'
|
23
|
+
|
24
|
+
module Origami
|
25
|
+
|
26
|
+
class InvalidIntegerObjectError < InvalidObjectError #:nodoc:
|
27
|
+
end
|
28
|
+
|
29
|
+
#
|
30
|
+
# Class representing a PDF number (Integer, or Real).
|
31
|
+
#
|
32
|
+
module Number
|
33
|
+
include Origami::Object
|
34
|
+
|
35
|
+
def ~
|
36
|
+
self.class.new(~self.to_i)
|
37
|
+
end
|
38
|
+
|
39
|
+
def |(val)
|
40
|
+
self.class.new(self.to_i | val)
|
41
|
+
end
|
42
|
+
|
43
|
+
def &(val)
|
44
|
+
self.class.new(self.to_i & val)
|
45
|
+
end
|
46
|
+
|
47
|
+
def ^(val)
|
48
|
+
self.class.new(self.to_i ^ val)
|
49
|
+
end
|
50
|
+
|
51
|
+
def <<(val)
|
52
|
+
self.class.new(self.to_i << val)
|
53
|
+
end
|
54
|
+
|
55
|
+
def >>(val)
|
56
|
+
self.class.new(self.to_i >> val)
|
57
|
+
end
|
58
|
+
|
59
|
+
def +(val)
|
60
|
+
self.class.new(self.to_i + val)
|
61
|
+
end
|
62
|
+
|
63
|
+
def -(val)
|
64
|
+
self.class.new(self.to_i - val)
|
65
|
+
end
|
66
|
+
|
67
|
+
def -@
|
68
|
+
self.class.new(-self.to_i)
|
69
|
+
end
|
70
|
+
|
71
|
+
def *(val)
|
72
|
+
self.class.new(self.to_i * val)
|
73
|
+
end
|
74
|
+
|
75
|
+
def /(val)
|
76
|
+
self.class.new(self.to_i / val)
|
77
|
+
end
|
78
|
+
|
79
|
+
def abs
|
80
|
+
self.class.new(self.to_i.abs)
|
81
|
+
end
|
82
|
+
|
83
|
+
def **(val)
|
84
|
+
self.class.new(self.to_i ** val)
|
85
|
+
end
|
86
|
+
|
87
|
+
def to_s
|
88
|
+
super(value.to_s)
|
89
|
+
end
|
90
|
+
|
91
|
+
def real_type ; Number end
|
92
|
+
end
|
93
|
+
|
94
|
+
#
|
95
|
+
# Class representing an Integer Object.
|
96
|
+
#
|
97
|
+
class Integer < DelegateClass(Bignum)
|
98
|
+
|
99
|
+
include Number
|
100
|
+
|
101
|
+
TOKENS = [ "(\\+|-)?[\\d]+[^.]?" ] #:nodoc:
|
102
|
+
|
103
|
+
REGEXP_TOKEN = Regexp.new(TOKENS.first)
|
104
|
+
|
105
|
+
@@regexp = Regexp.new(WHITESPACES + "((\\+|-)?[\\d]+)")
|
106
|
+
|
107
|
+
#
|
108
|
+
# Creates a new Integer from a Ruby Fixnum / Bignum.
|
109
|
+
# _i_:: The Integer value.
|
110
|
+
#
|
111
|
+
def initialize(i = 0)
|
112
|
+
|
113
|
+
unless i.is_a?(::Integer)
|
114
|
+
raise TypeError, "Expected type Fixnum or Bignum, received #{i.class}."
|
115
|
+
end
|
116
|
+
|
117
|
+
super(i)
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.parse(stream) #:nodoc:
|
121
|
+
|
122
|
+
offset = stream.pos
|
123
|
+
|
124
|
+
if not stream.scan(@@regexp)
|
125
|
+
raise InvalidIntegerObjectError, "Invalid integer format"
|
126
|
+
end
|
127
|
+
|
128
|
+
value = stream[2].to_i
|
129
|
+
int = Integer.new(value)
|
130
|
+
int.file_offset = offset
|
131
|
+
|
132
|
+
int
|
133
|
+
end
|
134
|
+
|
135
|
+
alias value to_i
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
class InvalidRealObjectError < InvalidObjectError #:nodoc:
|
140
|
+
end
|
141
|
+
|
142
|
+
#
|
143
|
+
# Class representing a Real number Object.
|
144
|
+
# PDF real numbers are arbitrary precision numbers, depending on architectures.
|
145
|
+
#
|
146
|
+
class Real < DelegateClass(Float)
|
147
|
+
|
148
|
+
include Number
|
149
|
+
|
150
|
+
TOKENS = [ "(\\+|-)?([\\d]*\\.[\\d]+|[\\d]+\\.[\\d]*)([eE](\\+|-)?[\\d]+)?" ] #:nodoc:
|
151
|
+
|
152
|
+
REGEXP_TOKEN = Regexp.new(TOKENS.first)
|
153
|
+
|
154
|
+
@@regexp = Regexp.new(WHITESPACES + "(" + TOKENS.first + ")")
|
155
|
+
|
156
|
+
#
|
157
|
+
# Creates a new Real from a Ruby Float.
|
158
|
+
# _f_:: The new Real value.
|
159
|
+
#
|
160
|
+
def initialize(f = 0)
|
161
|
+
|
162
|
+
unless f.is_a?(Float)
|
163
|
+
raise TypeError, "Expected type Float, received #{f.class}."
|
164
|
+
end
|
165
|
+
|
166
|
+
super(f)
|
167
|
+
end
|
168
|
+
|
169
|
+
def self.parse(stream) #:nodoc:
|
170
|
+
|
171
|
+
offset = stream.pos
|
172
|
+
|
173
|
+
if not stream.scan(@@regexp)
|
174
|
+
raise InvalidRealObjectError, "Invalid real number format"
|
175
|
+
end
|
176
|
+
|
177
|
+
value = stream[2].to_f
|
178
|
+
real = Real.new(value)
|
179
|
+
real.file_offset = offset
|
180
|
+
|
181
|
+
real
|
182
|
+
end
|
183
|
+
|
184
|
+
alias value to_f
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
@@ -0,0 +1,233 @@
|
|
1
|
+
module Origami
|
2
|
+
|
3
|
+
module Obfuscator
|
4
|
+
|
5
|
+
WHITECHARS = [ " ", "\t", "\r", "\n", "\0" ]
|
6
|
+
OBJECTS = [ Array, Boolean, Dictionary, Integer, Name, Null, Stream, String, Real, Reference ]
|
7
|
+
MAX_INT = 0xFFFFFFFF
|
8
|
+
PRINTABLE = ("!".."9").to_a + (':'..'Z').to_a + ('['..'z').to_a + ('{'..'~').to_a
|
9
|
+
FILTERS = [ :FlateDecode, :RunLengthDecode, :LZWDecode, :ASCIIHexDecode, :ASCII85Decode ]
|
10
|
+
|
11
|
+
def self.junk_spaces(max_size = 3)
|
12
|
+
length = rand(max_size) + 1
|
13
|
+
|
14
|
+
::Array.new(length) { WHITECHARS[rand(WHITECHARS.size)] }.join
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.junk_comment(max_size = 15)
|
18
|
+
length = rand(max_size) + 1
|
19
|
+
|
20
|
+
junk_comment = ::Array.new(length) {
|
21
|
+
byte = rand(256).chr until (not byte.nil? and byte != "\n" and byte != "\r"); byte
|
22
|
+
}.join
|
23
|
+
|
24
|
+
"%#{junk_comment}#{EOL}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.junk_object(type = nil)
|
28
|
+
|
29
|
+
if type.nil?
|
30
|
+
type = OBJECTS[rand(OBJECTS.size)]
|
31
|
+
end
|
32
|
+
|
33
|
+
unless type.include?(Origami::Object)
|
34
|
+
raise TypeError, "Not a valid object type"
|
35
|
+
end
|
36
|
+
|
37
|
+
Obfuscator.send("junk_#{type.to_s.split('::').last.downcase}")
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.junk_array(max_size = 5)
|
41
|
+
length = rand(max_size) + 1
|
42
|
+
|
43
|
+
::Array.new(length) {
|
44
|
+
obj = Obfuscator.junk_object until (not obj.nil? and not obj.is_a?(Stream)) ; obj
|
45
|
+
}.to_o
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.junk_boolean
|
49
|
+
Boolean.new(rand(2).zero?)
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.junk_dictionary(max_size = 5)
|
53
|
+
length = rand(max_size) + 1
|
54
|
+
|
55
|
+
hash = Hash.new
|
56
|
+
length.times do
|
57
|
+
obj = Obfuscator.junk_object
|
58
|
+
hash[Obfuscator.junk_name] = obj unless obj.is_a?(Stream)
|
59
|
+
end
|
60
|
+
|
61
|
+
hash.to_o
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.junk_integer(max = MAX_INT)
|
65
|
+
Integer.new(rand(max + 1))
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.junk_name(max_size = 8)
|
69
|
+
length = rand(max_size) + 1
|
70
|
+
|
71
|
+
Name.new(::Array.new(length) { PRINTABLE[rand(PRINTABLE.size)] }.join)
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.junk_null
|
75
|
+
Null.new
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.junk_stream(max_data_size = 200)
|
79
|
+
|
80
|
+
chainlen = rand(2) + 1
|
81
|
+
chain = ::Array.new(chainlen) { FILTERS[rand(FILTERS.size)] }
|
82
|
+
|
83
|
+
length = rand(max_data_size) + 1
|
84
|
+
junk_data = ::Array.new(length) { rand(256).chr }.join
|
85
|
+
|
86
|
+
stm = Stream.new
|
87
|
+
stm.dictionary = Obfuscator.junk_dictionary(5)
|
88
|
+
stm.setFilter(chain)
|
89
|
+
stm.data = junk_data
|
90
|
+
|
91
|
+
stm
|
92
|
+
end
|
93
|
+
|
94
|
+
def self.junk_string(max_size = 10)
|
95
|
+
length = rand(max_size) + 1
|
96
|
+
|
97
|
+
strtype = (rand(2).zero?) ? ByteString : HexaString
|
98
|
+
|
99
|
+
strtype.new(::Array.new(length) { PRINTABLE[rand(PRINTABLE.size)] }.join)
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.junk_real
|
103
|
+
Real.new(rand * rand(MAX_INT + 1))
|
104
|
+
end
|
105
|
+
|
106
|
+
def self.junk_reference(max_no = 300, max_gen = 1)
|
107
|
+
no = rand(max_no) + 1
|
108
|
+
gen = rand(max_gen)
|
109
|
+
|
110
|
+
Reference.new(no, gen)
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|
114
|
+
|
115
|
+
class Dictionary
|
116
|
+
|
117
|
+
def to_obfuscated_str
|
118
|
+
content = TOKENS.first + Obfuscator.junk_spaces
|
119
|
+
self.each_pair { |key, value|
|
120
|
+
content << Obfuscator.junk_spaces +
|
121
|
+
key.to_obfuscated_str + Obfuscator.junk_spaces +
|
122
|
+
value.to_obfuscated_str + Obfuscator.junk_spaces
|
123
|
+
}
|
124
|
+
|
125
|
+
content << TOKENS.last
|
126
|
+
super(content)
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
module Object
|
132
|
+
alias :to_obfuscated_str :to_s
|
133
|
+
end
|
134
|
+
|
135
|
+
class Array
|
136
|
+
def to_obfuscated_str
|
137
|
+
content = TOKENS.first + Obfuscator.junk_spaces
|
138
|
+
self.each { |entry|
|
139
|
+
content << entry.to_o.to_obfuscated_str + Obfuscator.junk_spaces
|
140
|
+
}
|
141
|
+
|
142
|
+
content << TOKENS.last
|
143
|
+
|
144
|
+
super(content)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
class Null
|
149
|
+
alias :to_obfuscated_str :to_s
|
150
|
+
end
|
151
|
+
|
152
|
+
class Boolean
|
153
|
+
alias :to_obfuscated_str :to_s
|
154
|
+
end
|
155
|
+
|
156
|
+
class Integer
|
157
|
+
alias :to_obfuscated_str :to_s
|
158
|
+
end
|
159
|
+
|
160
|
+
class Real
|
161
|
+
alias :to_obfuscated_str :to_s
|
162
|
+
end
|
163
|
+
|
164
|
+
class Reference
|
165
|
+
def to_obfuscated_str
|
166
|
+
refstr = refno.to_s + Obfuscator.junk_spaces + refgen.to_s + Obfuscator.junk_spaces + "R"
|
167
|
+
|
168
|
+
super(refstr)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
class ByteString
|
173
|
+
def to_obfuscated_str
|
174
|
+
to_s
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
class HexaString
|
179
|
+
def to_obfuscated_str
|
180
|
+
to_s
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
class Name
|
185
|
+
def to_obfuscated_str(prop = 2)
|
186
|
+
name = @value.dup
|
187
|
+
|
188
|
+
forbiddenchars = [ " ","#","\t","\r","\n","\0","[","]","<",">","(",")","%","/","\\" ]
|
189
|
+
|
190
|
+
name.gsub!(/./) do |c|
|
191
|
+
if rand(prop) == 0 or forbiddenchars.include?(c)
|
192
|
+
hexchar = c[0].to_s(base=16)
|
193
|
+
hexchar = "0" + hexchar if hexchar.length < 2
|
194
|
+
|
195
|
+
'#' + hexchar
|
196
|
+
else
|
197
|
+
c
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
super(TOKENS.first + name)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
class Stream
|
206
|
+
def to_obfuscated_str
|
207
|
+
content = ""
|
208
|
+
|
209
|
+
content << @dictionary.to_obfuscated_str
|
210
|
+
content << "stream" + EOL
|
211
|
+
content << self.rawdata
|
212
|
+
content << EOL << TOKENS.last
|
213
|
+
|
214
|
+
super(content)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
class Trailer
|
219
|
+
|
220
|
+
def to_obfuscated_str
|
221
|
+
content = ""
|
222
|
+
if self.has_dictionary?
|
223
|
+
content << TOKENS.first << EOL << @dictionary.to_obfuscated_str << EOL
|
224
|
+
end
|
225
|
+
|
226
|
+
content << XREF_TOKEN << EOL << @startxref.to_s << EOL << TOKENS.last << EOL
|
227
|
+
|
228
|
+
content
|
229
|
+
end
|
230
|
+
|
231
|
+
end
|
232
|
+
|
233
|
+
end
|