Last active
August 29, 2015 14:04
-
-
Save glabra/e71e1feab0000a914f22 to your computer and use it in GitHub Desktop.
Twitter.CTFのお供にでもどうぞ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
=begin | |
/***** | |
decrypt.rb | |
*****/ | |
Synopsis: | |
難読化されたツイートをデコードするプラグインです。 | |
Avaliable formats: | |
Base64, gzip, rot13, rot47 | |
既知の不具合: | |
デコード結果がnilだった場合、[ERROR] stack level too deep が発生する。 | |
解凍結果が非常に膨大になった場合、rubyごと落ちる。 | |
Usage: | |
⚡ :decrypt [FORMAT] $xx | |
$xxをFORMATの順に従ってdecryptする。制御文字は~に置換される。 | |
FORMATの指定方法: | |
","区切りで指定、左から順に解読される。 | |
なお、指定するフォーマット名は下記の通りである。 | |
auto(base64, gzip): auto | |
base64: b64 | |
gzip: gz | |
rot13: r13 | |
rot47(rot13の変種): r47 | |
上記以外のフォーマット名は無視される。 | |
Options: | |
Earthquake.config[:decrypt] = { | |
:auto => Boolean # trueで自動デコードを有効にします。 | |
:auto_format => Boolean # 自動デコード時に使用するフォーマット | |
を指定します。 | |
:auto_paranoia => Boolean # 自動デコード結果に制御文字が含まれ | |
ていた場合もデコードします | |
:strip_text => int # デコード結果が指定数字以上のツイートを指定メッセージに置き換えます。 | |
無効にするには0以下の数値を入力してください。 | |
:strip_text_message => String # strip_textにおける指定メッセー | |
ジを指定します。 | |
:format_default => String # FORMATのデフォルト値を指定します。 | |
} | |
=end | |
# lzmaサポートは、ライブラリが不安定すぎるので消しました | |
require 'base64' | |
require 'zlib' | |
require 'stringio' | |
#require 'lzma' | |
Earthquake.init do | |
# 初期化 | |
config[:decrypt] ||= {} | |
config[:decrypt][:auto] ||= true | |
config[:decrypt][:auto_format] ||= ["auto"] | |
config[:decrypt][:auto_paranoia] ||= false | |
config[:decrypt][:strip_text] ||= 1024 | |
config[:decrypt][:strip_text_message] ||= "[decrypt.rb] It's Too Long." | |
config[:decrypt][:format_default] ||= ["auto"] | |
# 本体 | |
if config[:decrypt][:auto] | |
output_filter do |item| | |
next unless item["text"] | |
# 数字4桁だけのツイートが何故かデコードされるので一応の対策として | |
next if item["text"].match(/^[0-9]+$/) | |
if decrypted_text = decrypter(config[:decrypt][:auto_format], item["text"]) | |
if config[:decrypt][:auto_paranoia] | |
item["text"] = decrypted_text.gsub(/[[:cntrl:]]/, "~") + " [d]".c(:notice) | |
elsif !decrypted_text.match(/[[:cntrl:]]/) | |
item["text"] = decrypted_text + " [d]".c(:notice) | |
end | |
end | |
end | |
end | |
command :decrypt do |m| | |
data = m[1].split(" ") | |
tweet = twitter.status(data.shift) | |
if data[0].match(/^(\$[a-z]{2}|[0-9]+)$/) | |
format = config[:decrypt][:format_default] | |
else | |
format = data.shift.split(",") | |
end | |
if decrypted_text = decrypter(format, tweet["text"]) | |
decrypted_text = "'#{tweet["user"]["screen_name"]}: #{decrypted_text.gsub(/[[:cntrl:]]/, "~")}'" | |
else | |
decrypted_text = "'#{tweet["user"]["screen_name"]}: #{tweet["text"]}'" | |
end | |
puts(decrypted_text.c(:info)) | |
end | |
help :decrypt, "Decode obfuscationized tweet.", <<-HELP | |
⚡ :decrypt [FORMAT] $xx | |
If FORMAT is not provided, assume FORMAT as #{config[:decrypt][:format_default]}. | |
FORMAT: | |
auto(base64, gzip): auto | |
Base64: b64 | |
gzip: gz | |
rot13: r13 | |
rot47: r47 | |
HELP | |
# TODO: 何故か”デコード”後のものが降ってくる | |
# command :undecrypt do |m| | |
# tweet = twitter.status(m[1].split(" ").shift) | |
# puts("'#{tweet["user"]["screen_name"]}: #{tweet["text"]}'".c(:info)) | |
# end | |
# | |
# help :undecrypt, "unDecode auto decrypted tweet.", <<-HELP | |
#⚡ :undecrypt $xx | |
# | |
#Undecrypt auto decrypted tweet. | |
#HELP | |
end | |
# local 関数群 | |
# XXX: defの順番によって動かなくなったり動かなくなったりします。多分。あと汚くなってきた。 | |
def decrypter(format, data_raw) | |
if data_raw.match(/^(@([A-Za-z0-9]|_)+\s+)+/) | |
reply_target = $& | |
text_raw = $' | |
processing = $' | |
else | |
reply_target = "" | |
text_raw = data_raw | |
processing = data_raw | |
end | |
for fmt in format | |
case fmt | |
when "auto" | |
processing = decrypter_auto(processing) | |
when "b64" | |
processing = decrypter_decode_base64(processing) | |
when "gz" | |
processing = decrypter_inflate_gzip(processing) | |
# when "lz" | |
# processing = decrypter_inflate_lzma(processing) | |
when "rot13" | |
processing = decrypter_decode_rot13(processing) | |
when "rot47" | |
processing = decrypter_decode_rot47(processing) | |
end | |
end | |
if config[:decrypt][:strip_text] > 0 && processing.length >= config[:decrypt][:strip_text] | |
retval = config[:decrypt][:strip_text_message] | |
elsif text_raw.gsub("\n", "") != processing | |
retval = reply_target + processing | |
else | |
retval = nil | |
end | |
return retval | |
end | |
def decrypter_decode_base64(data_raw) | |
data_raw.gsub!(/(\r\n|\r|\n)/, "") | |
begin | |
data_decrypted = Base64.strict_decode64(data_raw) | |
rescue | |
data_decrypted = nil | |
end | |
return data_decrypted | |
end | |
def decrypter_inflate_gzip(data_raw) | |
begin | |
Zlib::GzipReader.wrap(StringIO.open(data_raw)) do |c_zlib| | |
return c_zlib.read | |
end | |
rescue | |
return nil | |
end | |
end | |
#def decrypter_inflate_lzma(data_raw) | |
# begin | |
# data_decrypted = LZMA.decompress(data_raw) | |
# rescue | |
# data_decrypted = nil | |
# end | |
# return data_decrypted | |
#end | |
def decrypter_decode_rot13(data_raw) | |
return data_raw.tr("A-Za-z", "N-ZA-Mn-za-m") | |
end | |
def decrypter_decode_rot47(data_raw) | |
return data_raw.tr("!-~", "P-~!-O") | |
end | |
def decrypter_auto(data_raw) | |
retval = nil | |
retval ||= decrypter_inflate_gzip(data_raw) | |
# retval ||= decrypter_inflate_lzma(data_raw) | |
retval ||= decrypter_decode_base64(data_raw) | |
if retval | |
retval = decrypter_auto(retval) | |
else | |
retval = data_raw | |
end | |
return retval | |
end |
大改造劇的ビフォーアフター
動くようになりました
Base64.strict_decode64 は改行を許さなかったので改行を殺したという気持ち
Replyの自動デコードに対応した
あのさぁ…@がついてるからってさぁ…
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
制御文字は~に置換され、てなかったので修正