#!/usr/bin/env ruby # frozen_string_literal: true # Ruby internal require 'pp' require 'shellwords' # for shellescape cmd # Project internal require 'ctf_party' require 'ctf_party/version' # External require 'docopt' cmd_whitelist = { # ctf-party commands alternatecase: 'Change one characte on two upcase and the other downcase', bin2hex: 'Encode an binary string to a hexadecimal string', bin2str: 'Alias for from_bin', dec2hex: 'Encode an decimal string to a hexadecimal string', dec2str: 'Alias for from_dec', from_b64: 'Decode the string from base64', from_bin: 'Decode a binary string', from_dec: 'Decode a decimal string (decimal to hexadecimal then hexadecimal to string)', from_hex: 'Decode a hexadecimal string', from_hexip: 'Decode a hexadecimal IP string into a dotted decimal one', hex2bin: 'Encode an hexadecimal string to a binary string', hex2dec: 'Encode an hexadecimal string to a decimal string', hex2str: 'Alias for from_hex', htmlescape: 'HTML escape the string', htmlunescape: 'HTML unescape the string', istrip: 'Remove leading and trailing whitespace but also all inner whitespace', leet: 'Transform into leet speak (l337 5p34k)', md5: 'Calculate the md5 hash of the string', randomcase: 'Change the case of characters randomly', rmd160: 'Calculate the RIPEMD-160 hash of the string', rot13: 'Encrypt / Decrypt the string with Caesar cipher with a shift of 13', sha1: 'Calculate the sha1 hash of the string', sha2: 'Calculate the sha2 hash of the string', sha2_256: 'Alias for sha2 with bitlen of 256', sha2_384: 'Alias for sha2 with bitlen of 384', sha2_512: 'Alias for sha2 with bitlen of 512', str2bin: 'Alias for to_bin', str2dec: 'Alias for to_dec', str2hex: 'Alias for to_hex', to_b64: 'Encode the string into base64', to_bin: 'Encode a string into binary', to_dec: 'Encode a string into decimal (string to hexadecimal then hexadecimal to decimal)', to_hex: 'Encode a string into hexadecimal', to_hexip: 'Encode a dotted decimal IP into a hexadecimal one', urldecode: 'URL-decode the string', urldecode_component: 'URL-decode the URL component string', urlencode: 'URL-encode the string', urlencode_component: 'URL-encode the URL component string', # native string commands bytesize: 'https://rubyapi.org/3.1/o/string#method-i-bytesize', capitalize: 'https://rubyapi.org/3.1/o/string#method-i-capitalize', chomp: 'https://rubyapi.org/3.1/o/string#method-i-chomp', chop: 'https://rubyapi.org/3.1/o/string#method-i-chop', downcase: 'https://rubyapi.org/3.1/o/string#method-i-downcase', dump: 'https://rubyapi.org/3.1/o/string#method-i-dump', hex: 'https://rubyapi.org/3.1/o/string#method-i-hex', inspect: 'https://rubyapi.org/3.1/o/string#method-i-inspect', length: 'https://rubyapi.org/3.1/o/string#method-i-length', lstrip: 'https://rubyapi.org/3.1/o/string#method-i-lstrip', reverse: 'https://rubyapi.org/3.1/o/string#method-i-reverse', rstrip: 'https://rubyapi.org/3.1/o/string#method-i-rstrip', scrub: 'https://rubyapi.org/3.1/o/string#method-i-scrub', shellescape: 'https://rubyapi.org/3.1/o/string#method-i-shellescape', size: 'https://rubyapi.org/3.1/o/string#method-i-size', squeeze: 'https://rubyapi.org/3.1/o/string#method-i-squeeze', strip: 'https://rubyapi.org/3.1/o/string#method-i-strip', succ: 'https://rubyapi.org/3.1/o/string#method-i-succ', swapcase: 'https://rubyapi.org/3.1/o/string#method-i-swapcase', undump: 'https://rubyapi.org/3.1/o/string#method-i-undump', unicode_normalize: 'https://rubyapi.org/3.1/o/string#method-i-unicode_normalize', upcase: 'https://rubyapi.org/3.1/o/string#method-i-upcase' } doc = <<~DOCOPT ctf-party v#{Version::VERSION} by noraj Usage: ctf-party ... [--row --file] [--debug] ctf-party --list-commands [--debug] ctf-party -h | --help ctf-party --version Parameters: The string to manipulate, read from STDIN if equal to "-" Command to apply to the string, cf. --list-commands Options: -l, --list-commands List available commands (see https://noraj.github.io/ctf-party/yard/String.html) -r, --row Apply the transformation to each row -f, --file Interpret the string as a filename, if file doesn't exist it will still be treated as a string --debug Display arguments -h, --help Show this screen --version Show version Examples: ctf-party 'security' to_hex ctf-party 'NzQ2Zjc0NmY=' from_b64 hex2bin curl -s https://example.org | ctf-party - htmlescape seq 1 10 | ctf-party - dec2hex hex2bin --row cut -d : -f 1 /etc/passwd | ctf-party - randomcase --row ctf-party /etc/passwd str2hex --row --file DOCOPT begin args = Docopt.docopt(doc, version: Version::VERSION) # use case 1, using the tool pp args if args['--debug'] if args[''] args[''] = $stdin.read.chomp if args[''] == '-' args[''] = File.read(args['']) if args['--file'] && File.exist?(args['']) wrong_cmd = args[''] - cmd_whitelist.keys.map(&:to_s) if wrong_cmd.empty? if args['--row'] output = '' args[''].each_line(chomp: true) do |line| output_line = line args[''].each do |cmd| output_line = output_line.public_send(cmd) end output += "#{output_line}\n" end else output = args[''] args[''].each do |cmd| output = output.public_send(cmd) end end puts output else abort "Those commands don't exist: #{wrong_cmd}" end elsif args['--list-commands'] cmd_whitelist.each do |k, v| puts "#{k.to_s.ljust(25)}#{v}" end end # use case 2, help: already handled by docopt # use case 3, version: already handled by docopt rescue Docopt::Exit => e puts e.message end