pwntools 0.1.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|