記号難読化シェル芸のやべーやつを解読してみた
_(){ __=$@;};_ /*/$$/../?????-*;_ ${__##*-};$(${__%?????} '!-:' ^-~<<<"'\$${#__}(")
2019年2月は、記号で作る難読化シェル芸がメガシンカした歴史的な月でした。
一度にたくさんの素敵な情報が集まって、私の思考回路はショート寸前です。
記号と英字2文字だけでbash
https://www.ryotosaito.com/blog/?p=178
記号だけでシェルは操れた
https://www.ryotosaito.com/blog/?p=194
34C3 CTF minbashmaxfun - writeup
https://hack.more.systems/writeup/2017/12/30/34c3ctf-minbashmaxfun/
そんな中やべーやつが開発されます。yamayaさんという方が作成した記号だけのdateです。
$ _(){ __=$@;};_ /*/$$/../?????-*;_ ${__##*-};$(${__%?????} '!-:' ^-~<<<"'\$${#__}(") 2019年 2月 28日 木曜日 12:37:56 JST
こんなに短いのに全て記号で、そしてちゃんとdateとして動作します。美しい…そして恐ろしい…
人の褌で相撲を取るようで大変恐縮なのですが、これが埋もれてしまうのは人類の損失のような気がしたので、解読してみました。
大きく、4パートに分かれます。
$ _(){ __=$@;};_ /*/$$/../?????-*;_ ${__##*-};$(${__%?????} '!-:' ^-~<<<"'\$${#__}(") ^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ① ② ③ ④
①関数_の定義¶
_(){ __=$@;}
関数_を定義しています。$@が特殊なシェル変数になります。動作は「変数__に関数の全引数の内容を設定する」という動作になっています。
②一意なディレクトリパスの取得¶
_ /*/$$/../?????-*
さっそく関数_が実行されています。引数に渡されている /*/$$/../?????-* は、ワイルドカード(glob)てすね。
/*/$$/../?????-* に一致するディレクトリは1つだけになりました。
/proc/[PID]/../sysrq-trigger というファイルが該当します。これはマジックSysRqキーと呼ばれるカーネル機能を制御するためのインタフェースになりますね。この機能を利用するわけではなく、triggerという文字列を取得するのが目的になっています。
※マジックSysRqキーは、カーネルのデバッグなどに使用されるやつです。昔、クラスタの動作確認するために、これを使って意図的にカーネルパニックさせた記憶があります。
③"trigger"の取得¶
_ ${__##*-}
ここから変数展開を使って-以降だけを切り取って、再び変数__に設定しています。
"trigger"で7文字になるのですが、この7という数字も最後に使われます。
④trでdateコマンドを生成する¶
ここは更に細かく分けました。
$( ${__%?????} '!-:' ^-~ <<<"'\$${#__}(" ) ^^^^ ^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^ ④-1 ④-2 ④-3 ④-4 ④-1
④-1¶
$( )
コマンド置換ですね。最終的にこのカッコの中がdateになれば、dateが実行されます。
④-2¶
${__%?????}
変数展開の機能を巧みに使って先頭ニ文字を切り出しています。triggerの頭ニ文字、trが取得されます。
④-3¶
'!-:' ^-~
trの範囲指定を巧みに使っています。!-: と ^-~ どいういう範囲でしょうか。
Asciiコードから確認してみます。
0x20 | 0x21 | 0x22 | 0x23 | 0x24 | 0x25 | 0x26 | 0x27 | 0x28 | 0x29 | 0x2A | 0x2B | 0x2C | 0x2D | 0x2E | 0x2F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
space | ! | " | # | $ | % | & | ' | ( | ) | * | + | , | - | . | / |
0x30 | 0x31 | 0x32 | 0x33 | 0x34 | 0x35 | 0x36 | 0x37 | 0x38 | 0x39 | 0x3A | 0x3B | 0x3C | 0x3D | 0x3E | 0x3F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | : | ; | < | = | > | ? |
0x40 | 0x41 | 0x42 | 0x43 | 0x44 | 0x45 | 0x46 | 0x47 | 0x48 | 0x49 | 0x4A | 0x4B | 0x4C | 0x4D | 0x4E | 0x4F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@ | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O |
0x50 | 0x51 | 0x52 | 0x53 | 0x54 | 0x55 | 0x56 | 0x57 | 0x58 | 0x59 | 0x5A | 0x5B | 0x5C | 0x5D | 0x5E | 0x5F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
P | Q | R | S | T | U | V | W | X | Y | Z | [ | \ | ] | ^ | _ |
0x60 | 0x61 | 0x62 | 0x63 | 0x64 | 0x65 | 0x66 | 0x67 | 0x68 | 0x69 | 0x6A | 0x6B | 0x6C | 0x6D | 0x6E | 0x6F |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
` | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o |
0x70 | 0x71 | 0x72 | 0x73 | 0x74 | 0x75 | 0x76 | 0x77 | 0x78 | 0x79 | 0x7A | 0x7B | 0x7C | 0x7D | 0x7E |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
p | q | r | s | t | u | v | w | x | y | z | { | | | } | ~ |
ここから考えると !-: は、0x21から0x3Aの範囲、^-~ は、0x5Eから0x7Eの範囲になります。
trで変換される変換表を作ってみます。
! | " | # | $ | % | & | ' | ( | ) | * | + | , | - | . | / | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | : |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
^ | _ | ` | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | w |
dateの変換前の文字は '$7( ですね。
④-4¶
<<< "'\$${#__}("
<<<は、ヒアストリングという機能になります。通常、変換したい文字はパイプ経由でtrに渡しますが、これでも渡すことができます。
渡している文字は"'\$${#__}("です。この中の ${#__} は"trigger"の文字数を返す変数展開です。7ですね!
ゴールが見えてきました。
①〜④まとめ¶
まとめると、以下になります。
$ _(){ __=$@;} # ①関数_の定義 $ _ /*/$$/../?????-* # ②一意なディレクトリパスの取得 $ echo $__ /proc/16120/../sysrq-trigger $ _ ${__##*-} # ③"trigger"の取得 $ echo $__ trigger $ echo ${__%?????} # ④-2 "trigger"からtrを取り出す tr $ echo ${__%?????} '!-:' ^-~ # 結果としてtrが実行できる tr !-: ^-~ $ echo ${#__} # ④-3 "trigger"の文字数から7を生み出す 7 $ cat <<<"'\$${#__}(" # ④-4 ヒアストリングでtrの入力にする '$7( $ $(${__%?????} '!-:' ^-~<<<"'\$${#__}(") # ④-1 $(tr '!-:' ^-~ <<< "'\$7(" ) を実行 2019年 2月 28日 木曜日 12:54:22 JST
おわかりいただけたでしょうか…
ここまでくるともはや芸術品...!
出典は、ココのコメントにあります。
記号だけで Hello world したやべーやつもありますねw
2019.3.7 yamayaさん新作が以下になります¶
$ : /*/$$/../?????-*;: ${_##*-};$(${_%?????} '!-:' ^-~<<<"'\$${#_}(") 2019年 3月 7日 木曜日 22:51:09 JST
より短い!なぜこれでdateが実行できるか解読してみよう!
Comments