pwntools 0.1.0 → 1.0.0
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/README.md +88 -11
- data/Rakefile +5 -1
- data/lib/pwn.rb +9 -7
- data/lib/pwnlib/abi.rb +60 -0
- data/lib/pwnlib/asm.rb +146 -0
- data/lib/pwnlib/constants/constant.rb +16 -2
- data/lib/pwnlib/constants/constants.rb +35 -19
- data/lib/pwnlib/constants/linux/amd64.rb +30 -1
- data/lib/pwnlib/context.rb +25 -17
- data/lib/pwnlib/dynelf.rb +117 -54
- data/lib/pwnlib/elf/elf.rb +267 -0
- data/lib/pwnlib/ext/helper.rb +4 -4
- data/lib/pwnlib/logger.rb +87 -0
- data/lib/pwnlib/memleak.rb +58 -29
- data/lib/pwnlib/pwn.rb +19 -8
- data/lib/pwnlib/reg_sort.rb +102 -108
- data/lib/pwnlib/shellcraft/generators/amd64/common/common.rb +14 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/infloop.rb +17 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/memcpy.rb +31 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/mov.rb +127 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/nop.rb +16 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/popad.rb +27 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/pushstr.rb +64 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/pushstr_array.rb +19 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/ret.rb +32 -0
- data/lib/pwnlib/shellcraft/generators/amd64/common/setregs.rb +19 -0
- data/lib/pwnlib/shellcraft/generators/amd64/linux/execve.rb +21 -0
- data/lib/pwnlib/shellcraft/generators/amd64/linux/linux.rb +14 -0
- data/lib/pwnlib/shellcraft/generators/amd64/linux/ls.rb +19 -0
- data/lib/pwnlib/shellcraft/generators/amd64/linux/sh.rb +19 -0
- data/lib/pwnlib/shellcraft/generators/amd64/linux/syscall.rb +21 -0
- data/lib/pwnlib/shellcraft/generators/helper.rb +106 -0
- data/lib/pwnlib/shellcraft/generators/i386/common/common.rb +14 -0
- data/lib/pwnlib/shellcraft/generators/i386/common/infloop.rb +17 -0
- data/lib/pwnlib/shellcraft/generators/i386/common/mov.rb +90 -0
- data/lib/pwnlib/shellcraft/generators/i386/common/nop.rb +16 -0
- data/lib/pwnlib/shellcraft/generators/i386/common/pushstr.rb +39 -0
- data/lib/pwnlib/shellcraft/generators/i386/common/pushstr_array.rb +19 -0
- data/lib/pwnlib/shellcraft/generators/i386/common/setregs.rb +19 -0
- data/lib/pwnlib/shellcraft/generators/i386/linux/execve.rb +19 -0
- data/lib/pwnlib/shellcraft/generators/i386/linux/linux.rb +14 -0
- data/lib/pwnlib/shellcraft/generators/i386/linux/ls.rb +19 -0
- data/lib/pwnlib/shellcraft/generators/i386/linux/sh.rb +19 -0
- data/lib/pwnlib/shellcraft/generators/i386/linux/syscall.rb +19 -0
- data/lib/pwnlib/shellcraft/generators/x86/common/common.rb +26 -0
- data/lib/pwnlib/shellcraft/generators/x86/common/infloop.rb +22 -0
- data/lib/pwnlib/shellcraft/generators/x86/common/mov.rb +15 -0
- data/lib/pwnlib/shellcraft/generators/x86/common/pushstr.rb +15 -0
- data/lib/pwnlib/shellcraft/generators/x86/common/pushstr_array.rb +85 -0
- data/lib/pwnlib/shellcraft/generators/x86/common/setregs.rb +82 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/execve.rb +69 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/linux.rb +14 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/ls.rb +66 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/sh.rb +52 -0
- data/lib/pwnlib/shellcraft/generators/x86/linux/syscall.rb +52 -0
- data/lib/pwnlib/shellcraft/registers.rb +145 -0
- data/lib/pwnlib/shellcraft/shellcraft.rb +67 -0
- data/lib/pwnlib/timer.rb +60 -0
- data/lib/pwnlib/tubes/buffer.rb +96 -0
- data/lib/pwnlib/tubes/sock.rb +95 -0
- data/lib/pwnlib/tubes/tube.rb +270 -0
- data/lib/pwnlib/util/cyclic.rb +95 -94
- data/lib/pwnlib/util/fiddling.rb +256 -220
- data/lib/pwnlib/util/getdents.rb +83 -0
- data/lib/pwnlib/util/hexdump.rb +109 -108
- data/lib/pwnlib/util/lists.rb +55 -0
- data/lib/pwnlib/util/packing.rb +226 -228
- data/lib/pwnlib/util/ruby.rb +18 -0
- data/lib/pwnlib/version.rb +2 -1
- data/test/abi_test.rb +21 -0
- data/test/asm_test.rb +104 -0
- data/test/constants/constant_test.rb +1 -0
- data/test/constants/constants_test.rb +4 -2
- data/test/context_test.rb +1 -0
- data/test/data/echo.rb +20 -0
- data/test/data/elfs/Makefile +22 -0
- data/test/data/elfs/amd64.frelro.elf +0 -0
- data/test/data/elfs/amd64.frelro.pie.elf +0 -0
- data/test/data/elfs/amd64.nrelro.elf +0 -0
- data/test/data/elfs/amd64.prelro.elf +0 -0
- data/test/data/elfs/i386.frelro.pie.elf +0 -0
- data/test/data/elfs/i386.prelro.elf +0 -0
- data/test/data/elfs/source.cpp +19 -0
- data/test/data/flag +1 -0
- data/test/data/lib32/ld.so.2 +0 -0
- data/test/data/lib32/libc.so.6 +0 -0
- data/test/data/lib64/ld.so.2 +0 -0
- data/test/data/lib64/libc.so.6 +0 -0
- data/test/dynelf_test.rb +59 -24
- data/test/elf/elf_test.rb +120 -0
- data/test/ext_test.rb +3 -2
- data/test/files/use_pwnlib.rb +1 -1
- data/test/logger_test.rb +61 -0
- data/test/memleak_test.rb +4 -33
- data/test/reg_sort_test.rb +3 -1
- data/test/shellcraft/infloop_test.rb +26 -0
- data/test/shellcraft/linux/ls_test.rb +108 -0
- data/test/shellcraft/linux/sh_test.rb +119 -0
- data/test/shellcraft/linux/syscalls/execve_test.rb +136 -0
- data/test/shellcraft/linux/syscalls/syscall_test.rb +83 -0
- data/test/shellcraft/memcpy_test.rb +35 -0
- data/test/shellcraft/mov_test.rb +98 -0
- data/test/shellcraft/nop_test.rb +26 -0
- data/test/shellcraft/popad_test.rb +29 -0
- data/test/shellcraft/pushstr_array_test.rb +91 -0
- data/test/shellcraft/pushstr_test.rb +108 -0
- data/test/shellcraft/registers_test.rb +32 -0
- data/test/shellcraft/ret_test.rb +30 -0
- data/test/shellcraft/setregs_test.rb +62 -0
- data/test/shellcraft/shellcraft_test.rb +28 -0
- data/test/test_helper.rb +12 -1
- data/test/timer_test.rb +23 -0
- data/test/tubes/buffer_test.rb +45 -0
- data/test/tubes/sock_test.rb +68 -0
- data/test/tubes/tube_test.rb +241 -0
- data/test/util/cyclic_test.rb +2 -1
- data/test/util/fiddling_test.rb +2 -1
- data/test/util/getdents_test.rb +32 -0
- data/test/util/hexdump_test.rb +7 -9
- data/test/util/lists_test.rb +21 -0
- data/test/util/packing_test.rb +4 -3
- metadata +215 -25
data/lib/pwnlib/util/fiddling.rb
CHANGED
@@ -5,7 +5,7 @@ require 'pwnlib/context'
|
|
5
5
|
module Pwnlib
|
6
6
|
module Util
|
7
7
|
# Some fiddling methods.
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# @example Call by specifying full module path.
|
10
10
|
# require 'pwnlib/util/fiddling'
|
11
11
|
# Pwnlib::Util::Fiddling.enhex('217') #=> '323137'
|
@@ -13,250 +13,286 @@ module Pwnlib
|
|
13
13
|
# require 'pwn'
|
14
14
|
# enhex('217') #=> '323137'
|
15
15
|
module Fiddling
|
16
|
-
|
17
|
-
module ClassMethods
|
18
|
-
# Hex-encodes a string.
|
19
|
-
#
|
20
|
-
# @param [String] s
|
21
|
-
# String to be encoded.
|
22
|
-
# @return [String]
|
23
|
-
# Hex-encoded string.
|
24
|
-
#
|
25
|
-
# @example
|
26
|
-
# enhex('217') #=> '323137'
|
27
|
-
def enhex(s)
|
28
|
-
s.unpack('H*')[0]
|
29
|
-
end
|
16
|
+
module_function
|
30
17
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
18
|
+
# Hex-encodes a string.
|
19
|
+
#
|
20
|
+
# @param [String] s
|
21
|
+
# String to be encoded.
|
22
|
+
#
|
23
|
+
# @return [String]
|
24
|
+
# Hex-encoded string.
|
25
|
+
#
|
26
|
+
# @example
|
27
|
+
# enhex('217') #=> '323137'
|
28
|
+
def enhex(s)
|
29
|
+
s.unpack('H*')[0]
|
30
|
+
end
|
43
31
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
(n < 0 ? '-' : '') + format('0x%x', n.abs)
|
58
|
-
end
|
32
|
+
# Hex-decodes a string.
|
33
|
+
#
|
34
|
+
# @param [String] s
|
35
|
+
# String to be decoded.
|
36
|
+
#
|
37
|
+
# @return [String]
|
38
|
+
# Hex-decoded string.
|
39
|
+
#
|
40
|
+
# @example
|
41
|
+
# unhex('353134') #=> '514'
|
42
|
+
def unhex(s)
|
43
|
+
[s].pack('H*')
|
44
|
+
end
|
59
45
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
46
|
+
# Present number in hex format, same as python hex() do.
|
47
|
+
#
|
48
|
+
# @param [Integer] n
|
49
|
+
# The number.
|
50
|
+
#
|
51
|
+
# @return [String]
|
52
|
+
# The hex format string.
|
53
|
+
#
|
54
|
+
# @example
|
55
|
+
# hex(0) #=> '0x0'
|
56
|
+
# hex(-10) #=> '-0xa'
|
57
|
+
# hex(0xfaceb00cdeadbeef) #=> '0xfaceb00cdeadbeef'
|
58
|
+
def hex(n)
|
59
|
+
(n < 0 ? '-' : '') + format('0x%x', n.abs)
|
60
|
+
end
|
72
61
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
62
|
+
# URL-encodes a string.
|
63
|
+
#
|
64
|
+
# @param [String] s
|
65
|
+
# String to be encoded.
|
66
|
+
#
|
67
|
+
# @return [String]
|
68
|
+
# URL-encoded string.
|
69
|
+
#
|
70
|
+
# @example
|
71
|
+
# urlencode('shikway') #=> '%73%68%69%6b%77%61%79'
|
72
|
+
def urlencode(s)
|
73
|
+
s.bytes.map { |b| format('%%%02x', b) }.join
|
74
|
+
end
|
75
|
+
|
76
|
+
# URL-decodes a string.
|
77
|
+
#
|
78
|
+
# @param [String] s
|
79
|
+
# String to be decoded.
|
80
|
+
# @param [Boolean] ignore_invalid
|
81
|
+
# Whether invalid encoding should be ignore.
|
82
|
+
# If set to +true+, invalid encoding in input are left intact to output.
|
83
|
+
#
|
84
|
+
# @return [String]
|
85
|
+
# URL-decoded string.
|
86
|
+
#
|
87
|
+
# @raise [ArgumentError]
|
88
|
+
# If +ignore_invalid+ is +false+, and there are invalid encoding in input.
|
89
|
+
#
|
90
|
+
# @example
|
91
|
+
# urldecode('test%20url') #=> 'test url'
|
92
|
+
# urldecode('%qw%er%ty') #=> raise ArgumentError
|
93
|
+
# urldecode('%qw%er%ty', true) #=> '%qw%er%ty'
|
94
|
+
def urldecode(s, ignore_invalid = false)
|
95
|
+
res = ''
|
96
|
+
n = 0
|
97
|
+
while n < s.size
|
98
|
+
if s[n] != '%'
|
99
|
+
res << s[n]
|
100
|
+
n += 1
|
101
|
+
else
|
102
|
+
cur = s[n + 1, 2]
|
103
|
+
if cur =~ /[0-9a-fA-F]{2}/
|
104
|
+
res << cur.to_i(16).chr
|
105
|
+
n += 3
|
106
|
+
elsif ignore_invalid
|
107
|
+
res << '%'
|
97
108
|
n += 1
|
98
109
|
else
|
99
|
-
|
100
|
-
if cur =~ /[0-9a-fA-F]{2}/
|
101
|
-
res << cur.to_i(16).chr
|
102
|
-
n += 3
|
103
|
-
elsif ignore_invalid
|
104
|
-
res << '%'
|
105
|
-
n += 1
|
106
|
-
else
|
107
|
-
raise ArgumentError, 'Invalid input to urldecode'
|
108
|
-
end
|
110
|
+
raise ArgumentError, 'Invalid input to urldecode'
|
109
111
|
end
|
110
112
|
end
|
111
|
-
res
|
112
113
|
end
|
114
|
+
res
|
115
|
+
end
|
113
116
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
end
|
117
|
+
# Converts the argument to an array of bits.
|
118
|
+
#
|
119
|
+
# @param [String, Integer] s
|
120
|
+
# Input to be converted into bits.
|
121
|
+
# If input is integer, output would be padded to byte aligned.
|
122
|
+
# @param [String] endian
|
123
|
+
# Endian for conversion.
|
124
|
+
# Can be any value accepted by context (See {Context::ContextType}).
|
125
|
+
# @param zero
|
126
|
+
# Object representing a 0-bit.
|
127
|
+
# @param one
|
128
|
+
# Object representing a 1-bit.
|
129
|
+
#
|
130
|
+
# @return [Array]
|
131
|
+
# An array consisting of +zero+ and +one+.
|
132
|
+
#
|
133
|
+
# @example
|
134
|
+
# bits(314) #=> [0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0]
|
135
|
+
# bits('orz', zero: '-', one: '+').join #=> '-++-++++-+++--+--++++-+-'
|
136
|
+
# bits(128, endian: 'little') #=> [0, 0, 0, 0, 0, 0, 0, 1]
|
137
|
+
def bits(s, endian: 'big', zero: 0, one: 1)
|
138
|
+
context.local(endian: endian) do
|
139
|
+
is_little = context.endian == 'little'
|
140
|
+
case s
|
141
|
+
when String
|
142
|
+
v = 'B*'
|
143
|
+
v.downcase! if is_little
|
144
|
+
s.unpack(v)[0].chars.map { |ch| ch == '1' ? one : zero }
|
145
|
+
when Integer
|
146
|
+
# TODO(Darkpi): What should we do to negative number?
|
147
|
+
raise ArgumentError, 's must be non-negative' unless s >= 0
|
148
|
+
r = s.to_s(2).chars.map { |ch| ch == '1' ? one : zero }
|
149
|
+
r.unshift(zero) until (r.size % 8).zero?
|
150
|
+
is_little ? r.reverse : r
|
151
|
+
else
|
152
|
+
raise ArgumentError, 's must be either String or Integer'
|
151
153
|
end
|
152
154
|
end
|
155
|
+
end
|
153
156
|
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
157
|
+
# Simple wrapper around {.bits}, which converts output to string.
|
158
|
+
#
|
159
|
+
# @param (see .bits)
|
160
|
+
#
|
161
|
+
# @return [String]
|
162
|
+
# The output of {.bits} joined.
|
163
|
+
#
|
164
|
+
# @example
|
165
|
+
# bits_str('GG') #=> '0100011101000111'
|
166
|
+
def bits_str(s, endian: 'big', zero: 0, one: 1)
|
167
|
+
bits(s, endian: endian, zero: zero, one: one).join
|
168
|
+
end
|
164
169
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
170
|
+
# Reverse of {.bits} and {.bits_str}, convert an array of bits back to string.
|
171
|
+
#
|
172
|
+
# @param [String, Array<String, Integer, Boolean>] s
|
173
|
+
# String or array of bits to be convert back to string.
|
174
|
+
# <tt>[0, '0', false]</tt> represents 0-bit, and <tt>[1, '1', true]</tt> represents 1-bit.
|
175
|
+
# @param [String] endian
|
176
|
+
# Endian for conversion.
|
177
|
+
# Can be any value accepted by context (See {Context::ContextType}).
|
178
|
+
#
|
179
|
+
# @return [String]
|
180
|
+
# A string with bits from +s+.
|
181
|
+
#
|
182
|
+
# @raise [ArgumentError]
|
183
|
+
# If input contains value not in <tt>[0, 1, '0', '1', true, false]</tt>.
|
184
|
+
#
|
185
|
+
# @example
|
186
|
+
# unbits('0100011101000111') #=> 'GG'
|
187
|
+
# unbits([0, 1, 0, 1, 0, 1, 0, 0]) #=> 'T'
|
188
|
+
# unbits('0100011101000111', endian: 'little') #=> "\xE2\xE2"
|
189
|
+
def unbits(s, endian: 'big')
|
190
|
+
s = s.chars if s.is_a?(String)
|
191
|
+
context.local(endian: endian) do
|
192
|
+
is_little = context.endian == 'little'
|
193
|
+
bytes = s.map do |c|
|
194
|
+
case c
|
195
|
+
when '1', 1, true then '1'
|
196
|
+
when '0', 0, false then '0'
|
197
|
+
else raise ArgumentError, "cannot decode value #{c.inspect} into a bit"
|
191
198
|
end
|
192
|
-
[bytes.join].pack(is_little ? 'b*' : 'B*')
|
193
199
|
end
|
200
|
+
[bytes.join].pack(is_little ? 'b*' : 'B*')
|
194
201
|
end
|
202
|
+
end
|
195
203
|
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
204
|
+
# Reverse the bits of each byte in input string.
|
205
|
+
#
|
206
|
+
# @param [String] s
|
207
|
+
# Input string.
|
208
|
+
#
|
209
|
+
# @return [String]
|
210
|
+
# The string with bits of each byte reversed.
|
211
|
+
#
|
212
|
+
# @example
|
213
|
+
# bitswap('rb') #=> 'NF'
|
214
|
+
def bitswap(s)
|
215
|
+
unbits(bits(s, endian: 'big'), endian: 'little')
|
216
|
+
end
|
208
217
|
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
218
|
+
# Reverse the bits of a number, and returns the result as number.
|
219
|
+
#
|
220
|
+
# @param [Integer] n
|
221
|
+
# @param [Integer] bits
|
222
|
+
# The bit length of +n+,
|
223
|
+
# only the lower +bits+ bits of +n+ would be used.
|
224
|
+
# Default to +context.bits+.
|
225
|
+
#
|
226
|
+
# @return [Integer]
|
227
|
+
# The number with bits reversed.
|
228
|
+
#
|
229
|
+
# @example
|
230
|
+
# bitswap_int(217, bits: 8) #=> 155
|
231
|
+
def bitswap_int(n, bits: nil)
|
232
|
+
context.local(bits: bits) do
|
233
|
+
bits = context.bits
|
234
|
+
n &= (1 << bits) - 1
|
235
|
+
bits_str(n, endian: 'little').ljust(bits, '0').to_i(2)
|
227
236
|
end
|
237
|
+
end
|
228
238
|
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
239
|
+
# Base64-encodes a string.
|
240
|
+
# Do NOT contains those stupid newline (with RFC 4648).
|
241
|
+
#
|
242
|
+
# @param [String] s
|
243
|
+
# String to be encoded.
|
244
|
+
#
|
245
|
+
# @return [String]
|
246
|
+
# Base64-encoded string.
|
247
|
+
#
|
248
|
+
# @example
|
249
|
+
# b64e('desu') #=> 'ZGVzdQ=='
|
250
|
+
def b64e(s)
|
251
|
+
[s].pack('m0')
|
252
|
+
end
|
242
253
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
254
|
+
# Base64-decodes a string.
|
255
|
+
#
|
256
|
+
# @param [String] s
|
257
|
+
# String to be decoded.
|
258
|
+
#
|
259
|
+
# @return [String]
|
260
|
+
# Base64-decoded string.
|
261
|
+
#
|
262
|
+
# @example
|
263
|
+
# b64d('ZGVzdQ==') #=> 'desu'
|
264
|
+
def b64d(s)
|
265
|
+
s.unpack('m0')[0]
|
266
|
+
end
|
255
267
|
|
256
|
-
|
268
|
+
# Find two strings that will xor into a given string, while only using a given alphabet.
|
269
|
+
#
|
270
|
+
# @param [String, Integer] data
|
271
|
+
# The desired string.
|
272
|
+
# @param [String] avoid
|
273
|
+
# The list of disallowed characters. Defaults to nulls and newlines.
|
274
|
+
#
|
275
|
+
# @return [(String, String)?]
|
276
|
+
# Two strings which will xor to the given string. If no such two strings exist, then nil is returned.
|
277
|
+
#
|
278
|
+
# @example
|
279
|
+
# xor_pair("test") #=> ["\x01\x01\x01\x01", 'udru']
|
280
|
+
def xor_pair(data, avoid: "\x00\n")
|
281
|
+
data = pack(data) if data.is_a?(Integer)
|
282
|
+
alphabet = 256.times.reject { |c| avoid.include?(c.chr) }
|
283
|
+
res1 = ''
|
284
|
+
res2 = ''
|
285
|
+
data.bytes.each do |c1|
|
286
|
+
# alphabet.shuffle! if context.randomize
|
287
|
+
c2 = alphabet.find { |c| alphabet.include?(c1 ^ c) }
|
288
|
+
return nil if c2.nil?
|
289
|
+
res1 << c2.chr
|
290
|
+
res2 << (c1 ^ c2).chr
|
291
|
+
end
|
292
|
+
[res1, res2]
|
257
293
|
end
|
258
294
|
|
259
|
-
|
295
|
+
include ::Pwnlib::Context
|
260
296
|
end
|
261
297
|
end
|
262
298
|
end
|