ctf-party 1.3.5 → 2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f09406956f91fdbe561c73f343efc68e28ad20c774370053e88472ebb1bb5098
4
- data.tar.gz: 8bf8dfddfdbb4780578216b022d4815778f6f79d489506a2dba9fa0355bc8f90
3
+ metadata.gz: 4d60cac63a1449a4ddc3bf3b34ab1ff58db23b62adb3f5710b7bfe4822827088
4
+ data.tar.gz: 9fdc5fdaced3468d7003865e2e334ee756f6162a7204b64d99665c6e378a7bf8
5
5
  SHA512:
6
- metadata.gz: 40adf3307a9e8b99ccda9af3d1ab063413433998455cf92c292eb9b6e8d3deb754280673e796d7d980e22c87c222b7eb07c1fd7a6434d4597c186857ea973937
7
- data.tar.gz: e3d1bbf14cf1dd05112833a7fa8096acaf0ee6065a266990fa56a71c30415f504a83255c8ae835188dfbd25593e37b983d06b7c137ed5e3d0598ebd3dcc83edd
6
+ metadata.gz: 4212f6d4908cf82c3921b581424109c05d3bdd06d26bb8531c61cd903754260de7732bd019ee04dbf8d500dd1d947773701fb41a29ddf8142dd3f0388d59f778
7
+ data.tar.gz: ab4919f51fe339643dd6f6a4da0086e42451245f68438049c66f81ebf9f9ad14aadfe6ef2f04c28f4b26b473d0440283e9324be331e6643519e7b462a798de55
data/bin/ctf-party ADDED
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Ruby internal
5
+ require 'pp'
6
+ # Project internal
7
+ require 'ctf_party'
8
+ require 'ctf_party/version'
9
+ # External
10
+ require 'docopt'
11
+
12
+ cmd_whitelist = {
13
+ alternatecase: 'Change one characte on two upcase and the other downcase',
14
+ bin2hex: 'Encode an binary string to a hexadecimal string',
15
+ bin2str: 'Alias for from_bin',
16
+ dec2hex: 'Encode an decimal string to a hexadecimal string',
17
+ dec2str: 'Alias for from_dec',
18
+ from_b64: 'Decode the string from base64',
19
+ from_bin: 'Decode a binary string',
20
+ from_dec: 'Decode a decimal string (decimal to hexadecimal then hexadecimal to string)',
21
+ from_hex: 'Decode a hexadecimal string',
22
+ from_hexip: 'Decode a hexadecimal IP string into a dotted decimal one',
23
+ hex2bin: 'Encode an hexadecimal string to a binary string',
24
+ hex2dec: 'Encode an hexadecimal string to a decimal string',
25
+ hex2str: 'Alias for from_hex',
26
+ htmlescape: 'HTML escape the string',
27
+ htmlunescape: 'HTML unescape the string',
28
+ istrip: 'Remove leading and trailing whitespace but also all inner whitespace',
29
+ leet: 'Transform into leet speak (l337 5p34k)',
30
+ md5: 'Calculate the md5 hash of the string',
31
+ randomcase: 'Change the case of characters randomly',
32
+ rmd160: 'Calculate the RIPEMD-160 hash of the string',
33
+ rot13: 'Encrypt / Decrypt the string with Caesar cipher with a shift of 13',
34
+ sha1: 'Calculate the sha1 hash of the string',
35
+ sha2: 'Calculate the sha2 hash of the string',
36
+ sha2_256: 'Alias for sha2 with bitlen of 256',
37
+ sha2_384: 'Alias for sha2 with bitlen of 384',
38
+ sha2_512: 'Alias for sha2 with bitlen of 512',
39
+ str2bin: 'Alias for to_bin',
40
+ str2dec: 'Alias for to_dec',
41
+ str2hex: 'Alias for to_hex',
42
+ to_b64: 'Encode the string into base64',
43
+ to_bin: 'Encode a string into binary',
44
+ to_dec: 'Encode a string into decimal (string to hexadecimal then hexadecimal to decimal)',
45
+ to_hex: 'Encode a string into hexadecimal',
46
+ to_hexip: 'Encode a dotted decimal IP into a hexadecimal one',
47
+ urldecode: 'URL-decode the string',
48
+ urlencode: 'URL-encode the string'
49
+ }
50
+
51
+ doc = <<~DOCOPT
52
+ ctf-party by noraj
53
+
54
+ Usage:
55
+ ctf-party <string> <cmd>... [--debug]
56
+ ctf-party --list-commands [--debug]
57
+ ctf-party -h | --help
58
+ ctf-party --version
59
+
60
+ Options:
61
+ -l, --list-commands List available commands (see https://noraj.github.io/ctf-party/yard/String.html)
62
+ --debug Display arguments
63
+ -h, --help Show this screen
64
+ --version Show version
65
+
66
+ Examples:
67
+ ctf-party 'security' to_hex
68
+ ctf-party 'NzQ2Zjc0NmY=' from_b64 hex2str str2bin
69
+ DOCOPT
70
+
71
+ begin
72
+ args = Docopt.docopt(doc, version: Version::VERSION)
73
+ # use case 1, using the tool
74
+ pp args if args['--debug']
75
+ if args['<string>']
76
+ wrong_cmd = args['<cmd>'] - cmd_whitelist.keys.map(&:to_s)
77
+ if wrong_cmd.empty?
78
+ output = args['<string>']
79
+ args['<cmd>'].each do |cmd|
80
+ output = output.public_send(cmd)
81
+ end
82
+ puts output
83
+ else
84
+ abort "Those commands don't exist: #{wrong_cmd}"
85
+ end
86
+ elsif args['--list-commands']
87
+ cmd_whitelist.each do |k, v|
88
+ puts "#{k.to_s.ljust(15)}#{v}"
89
+ end
90
+ end
91
+ # use case 2, help: already handled by docopt
92
+ # use case 3, version: already handled by docopt
93
+ rescue Docopt::Exit => e
94
+ puts e.message
95
+ end
File without changes
@@ -6,8 +6,8 @@ require 'base64'
6
6
  class String
7
7
  # Encode the string into base64
8
8
  # @param opts [Hash] optional parameters
9
- # @option opts [Symbol] :mode Default value: +:strict+.
10
- # Other values are +:strict+ (+:rfc4648+) or +:urlsafe+.
9
+ # @option opts [Symbol] :mode Default value: `:strict`.
10
+ # Other values are `:strict` (`:rfc4648`) or `:urlsafe`.
11
11
  # @see https://ruby-doc.org/stdlib-2.6.5/libdoc/base64/rdoc/Base64.html
12
12
  # @return [String] the Base64 encoded string
13
13
  # @example
@@ -32,8 +32,8 @@ class String
32
32
 
33
33
  # Decode the string from base64
34
34
  # @param opts [Hash] optional parameters
35
- # @option opts [Symbol] :mode Default value: +:strict+.
36
- # Other values are +:strict+ (+:rfc4648+) or +:urlsafe+.
35
+ # @option opts [Symbol] :mode Default value: `:strict`.
36
+ # Other values are `:strict` (`:rfc4648`) or `:urlsafe`.
37
37
  # @see https://ruby-doc.org/stdlib-2.6.5/libdoc/base64/rdoc/Base64.html
38
38
  # @return [String] the Base64 decoded string
39
39
  # @example
@@ -58,10 +58,10 @@ class String
58
58
 
59
59
  # Is the string encoded in base64?
60
60
  # @param opts [Hash] optional parameters
61
- # @option opts [Symbol] :mode Default value: +:strict+.
62
- # Other values are +:strict+ (+:rfc4648+) or +:urlsafe+.
61
+ # @option opts [Symbol] :mode Default value: `:strict`.
62
+ # Other values are `:strict` (`:rfc4648`) or `:urlsafe`.
63
63
  # @see https://ruby-doc.org/stdlib-2.6.5/libdoc/base64/rdoc/Base64.html
64
- # @return [Boolean] +true+ if the string is a valid base64 string, +false+
64
+ # @return [Boolean] `true` if the string is a valid base64 string, `false`
65
65
  # else.
66
66
  # @example
67
67
  # 'SGVsbG8gd29ybGQh'.b64? # => true
@@ -4,7 +4,7 @@ class String
4
4
  # Encode a string into binary
5
5
  # @param opts [Hash] optional parameters
6
6
  # @option opts [Symbol] :bitnumbering Display output with most significant bit
7
- # first (+:MSB+ default) or least significant bit first (+:LSB+).
7
+ # first (`:MSB` default) or least significant bit first (`:LSB`).
8
8
  # @return [String] the binary encoded string
9
9
  # @example
10
10
  # 'binary'.to_bin # => "011000100110100101101110011000010111001001111001"
@@ -41,7 +41,7 @@ class String
41
41
  # Decode a binary string
42
42
  # @param opts [Hash] optional parameters
43
43
  # @option opts [Symbol] :bitnumbering Display input with most significant bit
44
- # first (+:MSB+ default) or least significant bit first (+:LSB+).
44
+ # first (`:MSB` default) or least significant bit first (`:LSB`).
45
45
  # @return [String] the binary decoded string
46
46
  # @example
47
47
  # '011000100110100101101110011000010111001001111001'.from_bin # => "binary"
@@ -74,4 +74,4 @@ class String
74
74
  def bin2str!(opts = {})
75
75
  from_bin!(opts)
76
76
  end
77
- end
77
+ end
data/lib/ctf_party/cgi.rb CHANGED
@@ -4,12 +4,13 @@
4
4
  require 'cgi'
5
5
 
6
6
  class String
7
- # URL-encode the string
7
+ # URL-encode the URL string (RFC2396)
8
8
  # @return [String] the URL-encoded string
9
9
  # @example
10
- # "'Stop!' said Fred".urlencode # => "%27Stop%21%27+said+Fred"
10
+ # 'http://vulnerable.site/search.aspx?txt="><script>alert(/Rubyfu/.source)</script>'.urlencode # => "http://vulnerable.site/search.aspx?txt=%22%3E%3Cscript%3Ealert(/Rubyfu/.source)%3C/script%3E"
11
+ # "'Stop!' said Fred" # => "'Stop!'%20said%20Fred"
11
12
  def urlencode
12
- CGI.escape self
13
+ URI::Parser.new.escape self
13
14
  end
14
15
 
15
16
  # URL-encode the string in place as described for {String#urlencode}.
@@ -17,12 +18,29 @@ class String
17
18
  replace(urlencode)
18
19
  end
19
20
 
20
- # URL-decode the string
21
+ # URL-encode the URL component string
22
+ # @return [String] the URL-encoded string
23
+ # @example
24
+ # "'Stop!' said Fred".urlencode_component # => "%27Stop%21%27+said+Fred"
25
+ # 'http://vulnerable.site/search.aspx?txt="><script>alert(/Rubyfu/.source)</script>'.urlencode_component # => "http%3A%2F%2Fvulnerable.site%2Fsearch.aspx%3Ftxt%3D%22%3E%3Cscript%3Ealert%28%2FRubyfu%2F.source%29%3C%2Fscript%3E"
26
+ def urlencode_component
27
+ CGI.escape self
28
+ end
29
+
30
+ # URL-encode the string in place as described for {String#urlencode_component}.
31
+ def urlencode_component!
32
+ replace(urlencode_component)
33
+ end
34
+
35
+ # URL-decode the URL string (RFC2396)
21
36
  # @return [String] the URL-decoded string
22
37
  # @example
23
- # "%27Stop%21%27+said+Fred".urldecode # => "'Stop!' said Fred"
38
+ # 'http://vulnerable.site/search.aspx?txt=%22%3E%3Cscript%3Ealert(/Rubyfu/.source)%3C/script%3E'.urldecode # => "http://vulnerable.site/search.aspx?txt=\"><script>alert(/Rubyfu/.source)</script>"
39
+ # 'http%3A%2F%2Fvulnerable.site%2Fsearch.aspx%3Ftxt%3D%22%3E%3Cscript%3Ealert%28%2FRubyfu%2F.source%29%3C%2Fscript%3E'.urldecode # => "http://vulnerable.site/search.aspx?txt=\"><script>alert(/Rubyfu/.source)</script>"
40
+ # "'Stop!'%20said%20Fred".urldecode # => "'Stop!' said Fred"
41
+ # '%27Stop%21%27+said+Fred'.urldecode # => "'Stop!'+said+Fred"
24
42
  def urldecode
25
- CGI.unescape self
43
+ URI::Parser.new.unescape self
26
44
  end
27
45
 
28
46
  # URL-decode the string in place as described for {String#urldecode}.
@@ -30,6 +48,22 @@ class String
30
48
  replace(urldecode)
31
49
  end
32
50
 
51
+ # URL-decode the URL component string
52
+ # @return [String] the URL-decoded string
53
+ # @example
54
+ # 'http://vulnerable.site/search.aspx?txt=%22%3E%3Cscript%3Ealert(/Rubyfu/.source)%3C/script%3E'.urldecode_component # => "http://vulnerable.site/search.aspx?txt=\"><script>alert(/Rubyfu/.source)</script>"
55
+ # 'http%3A%2F%2Fvulnerable.site%2Fsearch.aspx%3Ftxt%3D%22%3E%3Cscript%3Ealert%28%2FRubyfu%2F.source%29%3C%2Fscript%3E'.urldecode_component # => "http://vulnerable.site/search.aspx?txt=\"><script>alert(/Rubyfu/.source)</script>"
56
+ # "'Stop!'%20said%20Fred".urldecode_component => "'Stop!' said Fred"
57
+ # '%27Stop%21%27+said+Fred'.urldecode_component # => "'Stop!' said Fred"
58
+ def urldecode_component
59
+ CGI.unescape self
60
+ end
61
+
62
+ # URL-decode the string in place as described for {String#urldecode_component}.
63
+ def urldecode_component!
64
+ replace(urldecode_component)
65
+ end
66
+
33
67
  # HTML escape the string
34
68
  # @return [String] the HTML escaped string
35
69
  # @example
@@ -66,32 +66,32 @@ class String
66
66
  replace(sha2(opts))
67
67
  end
68
68
 
69
- # Alias for {String#sha2} with default value ( +sha2(bitlen: 256)+ ).
69
+ # Alias for {String#sha2} with default value ( `sha2(bitlen: 256)` ).
70
70
  def sha2_256
71
71
  sha2
72
72
  end
73
73
 
74
- # Alias for {String#sha2!} with default value ( +sha2!(bitlen: 256)+ ).
74
+ # Alias for {String#sha2!} with default value ( `sha2!(bitlen: 256)` ).
75
75
  def sha2_256!
76
76
  replace(sha2)
77
77
  end
78
78
 
79
- # Alias for {String#sha2} with default value ( +sha2(bitlen: 384)+ ).
79
+ # Alias for {String#sha2} with default value ( `sha2(bitlen: 384)` ).
80
80
  def sha2_384
81
81
  sha2(bitlen: 384)
82
82
  end
83
83
 
84
- # Alias for {String#sha2!} with default value ( +sha2!(bitlen: 384)+ ).
84
+ # Alias for {String#sha2!} with default value ( `sha2!(bitlen: 384)` ).
85
85
  def sha2_384!
86
86
  replace(sha2(bitlen: 384))
87
87
  end
88
88
 
89
- # Alias for {String#sha2} with default value ( +sha2(bitlen: 512)+ ).
89
+ # Alias for {String#sha2} with default value ( `sha2(bitlen: 512)` ).
90
90
  def sha2_512
91
91
  sha2(bitlen: 512)
92
92
  end
93
93
 
94
- # Alias for {String#sha2!} with default value ( +sha2!(bitlen: 512)+ ).
94
+ # Alias for {String#sha2!} with default value ( `sha2!(bitlen: 512)` ).
95
95
  def sha2_512!
96
96
  replace(sha2(bitlen: 512))
97
97
  end
@@ -21,7 +21,7 @@ class String
21
21
  # @option hash [String] :prefix prefix of the flag. Default: none.
22
22
  # @option hash [String] :suffix suffix of the flag. Default: none.
23
23
  # @option hash [Array<String>] :enclosing the characters used to surround
24
- # the flag. Default are curly braces: +{+, +}+. The array must contain
24
+ # the flag. Default are curly braces: `{`, `}`. The array must contain
25
25
  # exactly 2 elements.
26
26
  # @option hash [String] :digest the hash algorithm to apply on the flag.
27
27
  # Default: none. Allowed values: md5, sha1, sha2_256, sha2_384, sha2_512,
data/lib/ctf_party/hex.rb CHANGED
@@ -4,15 +4,17 @@ class String
4
4
  # Encode an hexadecimal string to a decimal string
5
5
  # @param opts [Hash] optional parameters
6
6
  # @option opts [String] :prefix Prefix of the input. Default value is a void
7
- # string. Example of values: +0x+, +\x+.
7
+ # string. Example of values: `0x`, `\x`, `\\x`.
8
8
  # @return [String] the decimal encoded string
9
9
  # @example
10
10
  # 'ff'.hex2dec # => "255"
11
11
  # '\xf3'.hex2dec(prefix: '\x') # => "243"
12
+ # '6e6f72616a'.hex2dec # => "474316169578"
13
+ # '\\x6e\\x6f\\x72\\x61\\x6a'.hex2dec(prefix: '\\x') # => "474316169578"
12
14
  def hex2dec(opts = {})
13
15
  opts[:prefix] ||= ''
14
16
  # remove prefix
15
- out = sub(opts[:prefix], '')
17
+ out = gsub(opts[:prefix], '')
16
18
  # convert
17
19
  return out.hex.to_s
18
20
  end
@@ -30,26 +32,35 @@ class String
30
32
  # Encode an decimal string to a hexadecimal string
31
33
  # @param opts [Hash] optional parameters
32
34
  # @option opts [String] :prefix Prefix of the output. Default value is a void
33
- # string. Example of values: +0x+, +\x+.
34
- # @option opts [Symbol] :case Char case of the ouput. Default value +:lower+.
35
- # Other valid value +:upper+.
35
+ # string. Example of values: `0x`, `\x`.
36
+ # @option opts [String] :prefixall Prefix each byte. Default value is a void
37
+ # string. Example of value: `\\x`.
38
+ # @option opts [Symbol] :case Char case of the output. Default value `:lower`.
39
+ # Other valid value `:upper`.
36
40
  # @option opts [Symbol] :padding Minimum size of the hexadecimal display
37
- # (number of characters). Eg. 10 -> 0xA or 0x0A
41
+ # (number of characters). Must be even.
38
42
  # @return [String] the hexadecimal encoded string
39
43
  # @example
40
44
  # '255'.dec2hex # => "ff"
41
45
  # '255'.dec2hex({prefix: '0x', case: :upper}) # => "0xFF"
46
+ # '10'.dec2hex(padding: 2) # => "0a"
47
+ # '10'.dec2hex(padding: 8) # => "0000000a"
48
+ # '474316169578'.dec2hex(prefixall: '\\x') # => "\\x6e\\x6f\\x72\\x61\\x6a"
42
49
  def dec2hex(opts = {})
43
50
  opts[:prefix] ||= ''
51
+ opts[:prefixall] ||= ''
44
52
  opts[:case] ||= :lower
45
- opts[:padding] ||= 1
53
+ opts[:padding] ||= 2
54
+ raise(ArgumentError, 'Padding must be even') if opts[:padding].odd?
55
+
46
56
  # convert
47
57
  out = to_i.to_s(16)
48
58
  # padding
49
- out = ('0' * (opts[:padding] - 1)) + out if out.size < opts[:padding]
59
+ out = ('0' * (opts[:padding] - out.size)) + out if out.size < opts[:padding]
50
60
  # char case management
51
61
  out = out.upcase if opts[:case] == :upper
52
62
  # adding prefix must be done after case change
63
+ out = out.scan(/.{2}/).map { |x| opts[:prefixall] + x }.join
53
64
  return opts[:prefix] + out
54
65
  end
55
66
 
@@ -66,19 +77,23 @@ class String
66
77
  # Encode a string into hexadecimal
67
78
  # @param opts [Hash] optional parameters
68
79
  # @option opts [String] :prefix Prefix of the output. Default value is a void
69
- # string. Example of values: +0x+, +\x+.
70
- # @option opts [Symbol] :case Char case of the ouput. Default value +:lower+.
71
- # Other valid value +:upper+.
80
+ # string. Example of values: `0x`, `\x`.
81
+ # @option opts [String] :prefixall Prefix each byte. Default value is a void
82
+ # string. Example of value: `\\x`.
83
+ # @option opts [Symbol] :case Char case of the output. Default value `:lower`.
84
+ # Other valid value `:upper`.
72
85
  # @option opts [Symbol] :nibble Display output with high nibble first
73
- # (+:high+ default) or low nibble first (+:low+).
86
+ # (`:high` default) or low nibble first (`:low`).
74
87
  # @return [String] the hexadecimal encoded string
75
88
  # @example
76
89
  # 'noraj'.to_hex # => "6e6f72616a"
77
90
  # 'noraj'.to_hex(prefix: '0x') # => "0x6e6f72616a"
78
91
  # 'noraj'.to_hex(case: :upper) # => "6E6F72616A"
79
92
  # 'noraj'.to_hex(nibble: :low) # => "e6f62716a6"
93
+ # 'noraj'.to_hex(prefixall: '\\x') # => "\\x6e\\x6f\\x72\\x61\\x6a"
80
94
  def to_hex(opts = {})
81
95
  opts[:prefix] ||= ''
96
+ opts[:prefixall] ||= ''
82
97
  opts[:case] ||= :lower
83
98
  opts[:nibble] ||= :high
84
99
  # convert
@@ -92,6 +107,7 @@ class String
92
107
  # char case management
93
108
  out = out.upcase if opts[:case] == :upper
94
109
  # adding prefix must be done after case change
110
+ out = out.scan(/.{2}/).map { |x| opts[:prefixall] + x }.join
95
111
  return opts[:prefix] + out
96
112
  end
97
113
 
@@ -118,19 +134,20 @@ class String
118
134
  # Decode a hexadecimal string
119
135
  # @param opts [Hash] optional parameters
120
136
  # @option opts [String] :prefix Prefix of the input. Default value is a void
121
- # string. Example of values: +0x+, +\x+.
137
+ # string. Example of values: `0x`, `\x`, `\\x`.
122
138
  # @option opts [Symbol] :nibble Display input with high nibble first
123
- # (+:high+ default) or low nibble first (+:low+).
139
+ # (`:high` default) or low nibble first (`:low`).
124
140
  # @return [String] the hexadecimal decoded string
125
141
  # @example
126
142
  # "6e6f72616a".from_hex # => "noraj"
127
143
  # "0x6e6f72616a".from_hex(prefix: '0x') # => "noraj"
128
144
  # "e6f62716a6".from_hex(nibble: :low) # => "noraj"
145
+ # '\\x6e\\x6f\\x72\\x61\\x6a'.from_hex(prefix: '\\x') # => "noraj"
129
146
  def from_hex(opts = {})
130
147
  opts[:prefix] ||= ''
131
148
  opts[:nibble] ||= :high
132
149
  # remove prefix
133
- out = sub(opts[:prefix], '')
150
+ out = gsub(opts[:prefix], '')
134
151
  # convert
135
152
  return Array(out).pack('H*') if opts[:nibble] == :high
136
153
  return Array(out).pack('h*') if opts[:nibble] == :low
@@ -161,15 +178,16 @@ class String
161
178
  # Encode an hexadecimal string to a binary string
162
179
  # @param opts [Hash] optional parameters
163
180
  # @option opts [String] :prefix Prefix of the input. Default value is a void
164
- # string. Example of values: +0x+, +\x+.
181
+ # string. Example of values: `0x`, `\x`, `\\x`.
165
182
  # @return [String] the binary encoded string
166
183
  # @example
167
184
  # 'ab'.hex2bin # => "10101011"
168
185
  # '\xf3'.hex2bin(prefix: '\x') # => "11110011"
186
+ # '\\x6e\\x6f\\x72\\x61\\x6a'.hex2bin(prefix: '\\x') # => "110111001101111011100100110000101101010"
169
187
  def hex2bin(opts = {})
170
188
  opts[:prefix] ||= ''
171
189
  # remove prefix
172
- out = sub(opts[:prefix], '')
190
+ out = gsub(opts[:prefix], '')
173
191
  # convert
174
192
  return out.to_i(16).to_s(2)
175
193
  end
@@ -187,21 +205,26 @@ class String
187
205
  # Encode an binary string to a hexadecimal string
188
206
  # @param opts [Hash] optional parameters
189
207
  # @option opts [String] :prefix Prefix of the output. Default value is a void
190
- # string. Example of values: +0x+, +\x+.
191
- # @option opts [Symbol] :case Char case of the ouput. Default value +:lower+.
192
- # Other valid value +:upper+.
208
+ # string. Example of values: `0x`, `\x`.
209
+ # @option opts [String] :prefixall Prefix each byte. Default value is a void
210
+ # string. Example of value: `\\x`.
211
+ # @option opts [Symbol] :case Char case of the output. Default value `:lower`.
212
+ # Other valid value `:upper`.
193
213
  # @return [String] the hexadecimal encoded string
194
214
  # @example
195
215
  # '11110011'.bin2hex # => "f3"
196
216
  # '11110011'.bin2hex({prefix: '0x', case: :upper}) # => "0xF3"
217
+ # '0110111001101111011100100110000101101010'.bin2hex(prefixall: '\\x') # => "\\x6e\\x6f\\x72\\x61\\x6a"
197
218
  def bin2hex(opts = {})
198
219
  opts[:prefix] ||= ''
220
+ opts[:prefixall] ||= ''
199
221
  opts[:case] ||= :lower
200
222
  # convert
201
223
  out = to_i(2).to_s(16)
202
224
  # char case management
203
225
  out = out.upcase if opts[:case] == :upper
204
226
  # adding prefix must be done after case change
227
+ out = out.scan(/.{2}/).map { |x| opts[:prefixall] + x }.join
205
228
  return opts[:prefix] + out
206
229
  end
207
230
 
@@ -218,18 +241,19 @@ class String
218
241
  # Decode a hexadecimal IP string into a dotted decimal one
219
242
  # @param opts [Hash] optional parameters
220
243
  # @option opts [String] :prefix Prefix of the input. Default value is a void
221
- # string. Example of values: +0x+, +\x+.
244
+ # string. Example of values: `0x`, `\x`, '\\x'.
222
245
  # @option opts [Symbol] :nibble Display input with high nibble first
223
- # (+:high+ default) or low nibble first (+:low+, used on Unix +/proc/net/tcp+).
246
+ # (`:high` default) or low nibble first (`:low`, used on Unix `/proc/net/tcp`).
224
247
  # @return [String] the dotted decimal IP
225
248
  # @example
226
249
  # '0100007F'.from_hexip(nibble: :low) # => "127.0.0.1"
227
250
  # '0x7f000001'.from_hexip(prefix: '0x') # => "127.0.0.1"
251
+ # '\\x7f\\x00\\x00\\x01'.from_hexip(prefix: '\\x') # => "127.0.0.1"
228
252
  def from_hexip(opts = {})
229
253
  opts[:prefix] ||= ''
230
254
  opts[:nibble] ||= :high
231
255
  # remove prefix
232
- out = sub(opts[:prefix], '')
256
+ out = gsub(opts[:prefix], '')
233
257
  # convert
234
258
  out = out.scan(/.{2}/).map(&:hex2dec)
235
259
  out = out.reverse if opts[:nibble] == :low
@@ -245,17 +269,21 @@ class String
245
269
  # Encode a dotted decimal IP into a hexadecimal one
246
270
  # @param opts [Hash] optional parameters
247
271
  # @option opts [String] :prefix Prefix of the output. Default value is a void
248
- # string. Example of values: +0x+, +\x+.
249
- # @option opts [Symbol] :case Char case of the ouput. Default value +:lower+.
250
- # Other valid value +:upper+.
272
+ # string. Example of values: `0x`, `\x`.
273
+ # @option opts [String] :prefixall Prefix each byte. Default value is a void
274
+ # string. Example of value: `\\x`.
275
+ # @option opts [Symbol] :case Char case of the output. Default value `:lower`.
276
+ # Other valid value `:upper`.
251
277
  # @option opts [Symbol] :nibble Display output with high nibble first
252
- # (+:high+ default) or low nibble first (+:low+, used on Unix +/proc/net/tcp+).
278
+ # (`:high` default) or low nibble first (`:low`, used on Unix `/proc/net/tcp`).
253
279
  # @return [String] the hexadecimal encoded IP
254
280
  # @example
255
281
  # '127.0.0.1'.to_hexip # => "7f000001"
256
282
  # '127.0.0.1'.to_hexip(nibble: :low) # => "0100007f"
283
+ # '127.0.0.1'.to_hexip(prefixall: '\\x') # => "\\x7f\\x00\\x00\\x01"
257
284
  def to_hexip(opts = {})
258
285
  opts[:prefix] ||= ''
286
+ opts[:prefixall] ||= ''
259
287
  opts[:case] ||= :lower
260
288
  opts[:nibble] ||= :high
261
289
  # convert
@@ -265,6 +293,7 @@ class String
265
293
  # char case management
266
294
  out = out.upcase if opts[:case] == :upper
267
295
  # adding prefix must be done after case change
296
+ out = out.scan(/.{2}/).map { |x| opts[:prefixall] + x }.join
268
297
  return opts[:prefix] + out
269
298
  end
270
299
 
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ class String
4
+ # Remove leading and trailing whitespace (like {String#strip}) but also all
5
+ # inner whitespace.
6
+ # @return [String] the whitespace-free string
7
+ # @example
8
+ # "\t\n\v\f\r Hello \t\n\v\f\r World !\t\n\v\f\r ".istrip # => "HelloWorld!"
9
+ # '73 74 72 69 70'.istrip # => "7374726970"
10
+ def istrip
11
+ strip.gsub(/\s/, '')
12
+ end
13
+
14
+ # Remove all whitespace in place as described for {String#istrip}.
15
+ def istrip!
16
+ replace(innerstrip)
17
+ end
18
+ end
data/lib/ctf_party/rot.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  class String
4
4
  # "Encrypt / Decrypt" the string with Caesar cipher. This will shift the
5
- # alphabet letters by +n+, where +n+ is the integer key. The same function
5
+ # alphabet letters by `n`, where `n` is the integer key. The same function
6
6
  # is used for encryption / decryption.
7
7
  # @param opts [Hash] optional parameters
8
8
  # @option opts [Integer] :shift The shift key. Default value: 13.
@@ -16,9 +16,9 @@ class String
16
16
  def rot(opts = {})
17
17
  opts[:shift] ||= 13
18
18
  alphabet = Array('a'..'z')
19
- lowercase = Hash[alphabet.zip(alphabet.rotate(opts[:shift]))]
19
+ lowercase = alphabet.zip(alphabet.rotate(opts[:shift])).to_h
20
20
  alphabet = Array('A'..'Z')
21
- uppercasecase = Hash[alphabet.zip(alphabet.rotate(opts[:shift]))]
21
+ uppercasecase = alphabet.zip(alphabet.rotate(opts[:shift])).to_h
22
22
  encrypter = lowercase.merge(uppercasecase)
23
23
  chars.map { |c| encrypter.fetch(c, c) }.join
24
24
  end
@@ -35,13 +35,22 @@ class String
35
35
  replace(rot(opts))
36
36
  end
37
37
 
38
- # Alias for {String#rot} with default value ( +rot(shift: 13)+ ).
38
+ # Alias for {String#rot} with default value ( `rot(shift: 13)` ).
39
39
  def rot13
40
40
  rot
41
41
  end
42
42
 
43
- # Alias for {String#rot!} with default value ( +rot!(shift: 13)+ ).
43
+ # Alias for {String#rot!} with default value ( `rot!(shift: 13)` ).
44
44
  def rot13!
45
45
  rot!
46
46
  end
47
+
48
+ # Compute all possibilities with {String#rot}
49
+ # @return [Hash] All possibilities with the shift index as key and the
50
+ # (de)ciphered text as value
51
+ # @example
52
+ # 'noraj'.rot_all # => {1=>"opsbk", 2=>"pqtcl", 3=>"qrudm", ... }
53
+ def rot_all
54
+ (1..26).each_with_object({}) { |i, h| h[i] = rot(shift: i) }
55
+ end
47
56
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Version
4
- VERSION = '1.3.5'
4
+ VERSION = '2.0.0'
5
5
  end
@@ -0,0 +1,93 @@
1
+ # frozen_string_literal: true
2
+
3
+ class String
4
+ # UTF-8 XOR with key, padding left the shortest element
5
+ # @param key [String] the element to xor the string with
6
+ # @return [String] the xored string (UTF-8)
7
+ # @example
8
+ # 'hello'.ulxor('key') # => "he\a\t\u0016"
9
+ # 'key'.ulxor('hello') # => "he\a\t\u0016"
10
+ def ulxor(key)
11
+ b1 = unpack('U*')
12
+ b2 = key.unpack('U*')
13
+ longest = [b1.length, b2.length].max
14
+ b1 = ([0] * (longest - b1.length)) + b1
15
+ b2 = ([0] * (longest - b2.length)) + b2
16
+ b1.zip(b2).map { |a, b| a ^ b }.pack('U*')
17
+ end
18
+
19
+ # UTF-8 XOR with key (padding left) in place as described for {String#ulxor}.
20
+ def ulxor!(key)
21
+ replace(ulxor(key))
22
+ end
23
+
24
+ # ASCII XOR with key, padding left the shortest element
25
+ # @param key [String] the element to xor the string with
26
+ # @return [String] the xored string (ASCII)
27
+ # @example
28
+ # 'hello'.alxor('key') # => "he\a\t\x16"
29
+ # 'key'.alxor('hello') # => "he\a\t\x16"
30
+ def alxor(key)
31
+ b1 = force_encoding('UTF-8')
32
+ b2 = key.force_encoding('UTF-8')
33
+ raise 'The string is not ASCII' unless b1.ascii_only?
34
+ raise 'The key is not ASCII' unless b2.ascii_only?
35
+
36
+ b1 = b1.chars.map(&:ord)
37
+ b2 = b2.chars.map(&:ord)
38
+ longest = [b1.length, b2.length].max
39
+ b1 = ([0] * (longest - b1.length)) + b1
40
+ b2 = ([0] * (longest - b2.length)) + b2
41
+ b1.zip(b2).map { |a, b| (a ^ b).chr }.join
42
+ end
43
+
44
+ # ASCII XOR with key (padding left) in place as described for {String#alxor}.
45
+ def alxor!(key)
46
+ replace(alxor(key))
47
+ end
48
+
49
+ # UTF-8 XOR with key, padding right the shortest element
50
+ # @param key [String] the element to xor the string with
51
+ # @return [String] the xored string (UTF-8)
52
+ # @example
53
+ # 'hello'.urxor('key') # => "\u0003\u0000\u0015lo"
54
+ # 'key'.urxor('hello') # => "\u0003\u0000\u0015lo"
55
+ def urxor(key)
56
+ b1 = unpack('U*')
57
+ b2 = key.unpack('U*')
58
+ longest = [b1.length, b2.length].max
59
+ b1 += [0] * (longest - b1.length)
60
+ b2 += [0] * (longest - b2.length)
61
+ b1.zip(b2).map { |a, b| a ^ b }.pack('U*')
62
+ end
63
+
64
+ # UTF-8 XOR with key (padding right) in place as described for {String#urxor}.
65
+ def urxor!(key)
66
+ replace(urxor(key))
67
+ end
68
+
69
+ # ASCII XOR with key, padding right the shortest element
70
+ # @param key [String] the element to xor the string with
71
+ # @return [String] the xored string (ASCII)
72
+ # @example
73
+ # 'hello'.arxor('key') # => "\x03\x00\x15lo"
74
+ # 'key'.arxor('hello') # => "\x03\x00\x15lo"
75
+ def arxor(key)
76
+ b1 = force_encoding('UTF-8')
77
+ b2 = key.force_encoding('UTF-8')
78
+ raise 'The string is not ASCII' unless b1.ascii_only?
79
+ raise 'The key is not ASCII' unless b2.ascii_only?
80
+
81
+ b1 = b1.chars.map(&:ord)
82
+ b2 = b2.chars.map(&:ord)
83
+ longest = [b1.length, b2.length].max
84
+ b1 += [0] * (longest - b1.length)
85
+ b2 += [0] * (longest - b2.length)
86
+ b1.zip(b2).map { |a, b| (a ^ b).chr }.join
87
+ end
88
+
89
+ # ASCII XOR with key (padding right) in place as described for {String#arxor}.
90
+ def arxor!(key)
91
+ replace(arxor(key))
92
+ end
93
+ end
data/lib/ctf_party.rb CHANGED
@@ -11,3 +11,5 @@ require 'ctf_party/cgi'
11
11
  require 'ctf_party/binary'
12
12
  require 'ctf_party/leet'
13
13
  require 'ctf_party/dec'
14
+ require 'ctf_party/misc'
15
+ require 'ctf_party/xor'
metadata CHANGED
@@ -1,152 +1,45 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ctf-party
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.5
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexandre ZANNI
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-04-02 00:00:00.000000000 Z
11
+ date: 2022-01-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: bundler
14
+ name: docopt
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.1'
20
- type: :development
19
+ version: '0.6'
20
+ type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.1'
27
- - !ruby/object:Gem::Dependency
28
- name: commonmarker
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '0.20'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '0.20'
41
- - !ruby/object:Gem::Dependency
42
- name: github-markup
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '4.0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '4.0'
55
- - !ruby/object:Gem::Dependency
56
- name: minitest
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '5'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '5'
69
- - !ruby/object:Gem::Dependency
70
- name: minitest-skip
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '0.0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '0.0'
83
- - !ruby/object:Gem::Dependency
84
- name: rake
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: '13.0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: '13.0'
97
- - !ruby/object:Gem::Dependency
98
- name: redcarpet
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: '3.5'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: '3.5'
111
- - !ruby/object:Gem::Dependency
112
- name: rubocop
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - "~>"
116
- - !ruby/object:Gem::Version
117
- version: '1.8'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - "~>"
123
- - !ruby/object:Gem::Version
124
- version: '1.8'
125
- - !ruby/object:Gem::Dependency
126
- name: yard
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - "~>"
130
- - !ruby/object:Gem::Version
131
- version: '0.9'
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - "~>"
137
- - !ruby/object:Gem::Version
138
- version: '0.9'
139
- description: A library to enhance and speed up script/exploit writingfor CTF players
140
- (or security researchers, bug bountyhunters, pentesters but mostly focused on CTF)
141
- bypatching the String class to add a short syntax of usual code patterns.
26
+ version: '0.6'
27
+ description: A CLI tool & library to enhance and speed up script/exploit writing for
28
+ CTF players (or security researchers, bug bounty hunters, pentesters but mostly
29
+ focused on CTF) by patching the String class to add a short syntax of usual code
30
+ patterns. Methods for base64, digest (hash), flag, rot (Caesar), hexadecimal, case,
31
+ cgi (URL encoding/decoding, HTML escaping/unescaping), binary, leet (1337), decimal,
32
+ XOR, whitespace strip.
142
33
  email: alexandre.zanni@engineer.com
143
34
  executables:
144
- - ctf_party_console
35
+ - ctf-party
36
+ - ctf-party_console
145
37
  extensions: []
146
38
  extra_rdoc_files: []
147
39
  files:
148
40
  - LICENSE.txt
149
- - bin/ctf_party_console
41
+ - bin/ctf-party
42
+ - bin/ctf-party_console
150
43
  - lib/ctf_party.rb
151
44
  - lib/ctf_party/base64.rb
152
45
  - lib/ctf_party/binary.rb
@@ -157,8 +50,10 @@ files:
157
50
  - lib/ctf_party/flag.rb
158
51
  - lib/ctf_party/hex.rb
159
52
  - lib/ctf_party/leet.rb
53
+ - lib/ctf_party/misc.rb
160
54
  - lib/ctf_party/rot.rb
161
55
  - lib/ctf_party/version.rb
56
+ - lib/ctf_party/xor.rb
162
57
  homepage: https://noraj.github.io/ctf-party/
163
58
  licenses:
164
59
  - MIT
@@ -169,23 +64,28 @@ metadata:
169
64
  documentation_uri: https://noraj.github.io/ctf-party/
170
65
  homepage_uri: https://noraj.github.io/ctf-party/
171
66
  source_code_uri: https://github.com/noraj/ctf-party/
67
+ rubygems_mfa_required: 'true'
172
68
  post_install_message:
173
69
  rdoc_options: []
174
70
  require_paths:
175
71
  - lib
176
72
  required_ruby_version: !ruby/object:Gem::Requirement
177
73
  requirements:
178
- - - "~>"
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: 2.7.0
77
+ - - "<"
179
78
  - !ruby/object:Gem::Version
180
- version: '2.7'
79
+ version: '3.1'
181
80
  required_rubygems_version: !ruby/object:Gem::Requirement
182
81
  requirements:
183
82
  - - ">="
184
83
  - !ruby/object:Gem::Version
185
84
  version: '0'
186
85
  requirements: []
187
- rubygems_version: 3.1.4
86
+ rubygems_version: 3.2.15
188
87
  signing_key:
189
88
  specification_version: 4
190
- summary: A library to enhance and speed up script/exploit writing for CTF players
89
+ summary: A CLI tool & library to enhance and speed up script/exploit writing with
90
+ string conversion/manipulation
191
91
  test_files: []