たいちょーの雑記

ぼくが3日に一度くらい雑記をかくところ

超・記号オンリー難読化シェル芸の材料について

時代と共にUsageも変わる・・・!

そんなお話

シェル芸botくんにmtコマンドが入った

LANG=Cにもしていただいたみたいなので超・記号オンリー難読化ができる

www.slideshare.net

とっても嬉しい。ありがとうございます。

試してみる

喜び勇んで試しにmtコマンドのUsageを見ようと思ったのでやってみたんですが

思ってた出力と違います。ちなみに期待していたのは以下

$ LANG=C mt --usage
Usage: mt [-?V] [-f DEVICE] [--file=DEVICE] [--rsh-command=COMMAND] [--help]
            [--usage] [--version] operation [count]

なんだこれーと思ったのでとりあえずmtコマンドのバージョンを見てみると

$ mt --version
mt (GNU cpio) 2.12
...

え〜〜〜全然違うなるほど〜。どうやらaptでインストールできるmtは少し古いみたいですね

$ apt search mt-st 
ソート中... 完了
全文検索... 完了  
mt-st/bionic 1.3-1 amd64
  Linux SCSI tape driver aware magnetic tape control (aka mt)

やっぱりバージョンによってmtのUsageが違うんですねー。時代を感じる

GNU CPIOのサイトで公開されているChangeLogを眺めてみると、何回かmtのUsageを変更したゼみたいなことが書いてあります(英語わからん)

GNU CPIO

具体的にどのリリースからUsageが違うのか、配布されてるソースをビルドしてみたりしたんですがわからなかったです(もうちょっと調査するかも)

マナ の色が違う

しかしこのマナではスライドそのままでは 世界樹 を作ることができません。こうした色の違いを 属性 ということにしました

属性 が違うなら混ぜるか変換すればいいので 命の泉マナ から作れる別のコマンドを探し、世界樹 へつなげます

今回選んだのは tset コマンドです。適当に/usr/bin/bin以下から探して目についたのと、響きがなんか可愛かったので選びました。

tset

tsetは変なオプションをつけるとUsageを出力して終了します

$ tset -@
tset: invalid option -- '@'
Usage: tset [options] [terminal]

Options:
  -c          set control characters
  -e ch       erase character
  -I          no initialization strings
  -i ch       interrupt character
  -k ch       kill character
  -m mapping  map identifier to type
  -Q          do not output control key settings
  -q          display term only, do no changes
  -r          display term on stderr
  -s          output TERM set command
  -V          print curses-version
  -w          set window-size

If neither -c/-w are given, both are assumed.

割とたくさん文字が出ますね。mt始動をやめてtset始動に切り替えても行けるかもしれません

ともかく、tsetmtマナ世界樹 が作れそうです

やったね

一応難読化の解説も書いておきます

# mtのUsage
___=$(mt 2>&1)
# tset
____=$(${___:8:1}${___:1:1}${___:4:1}${___:8:1} -@ 2>&1)

# ls --help
echo ${____:10:1}${____:1:1} -${___:28:2}${____:2:1}${____:10:1}${____:15:1}

なんの解説なの?これ

LANG=C問題

この難読化では文字を変数に格納して展開することを繰り返して難読化します。なのでマナや世界樹を作るmt,ls --helpと言ったコマンドの出力は重要です。

今回のバージョンの違いというのもありますが、特に影響するのは言語設定です。翻訳の程度では全く難読化が成り立たなくなることもあります。

じゃあLANG=Cを必須にして難読化の先頭につければいいじゃん?という御仁もいらっしゃることかと思いますが、頑張ってアルファベットを消したのに復活させるのは悔しいのでダメです

なのでこれらの出力の中でもLANGの値に依存しない部分を切り取ったりすることが肝要です。これは実は発案のkanataさんが 命の泉 を作るときにもやっています。僕はコレをやっていなかったので実は超・記号オンリー難読化はできてないと言えます。

現に日本語設定だとmtのUsageは日本語訳され、以下のように出力されます

$ mt
使用法: mt [OPTION...] 操作 []
Try 'mt --help' or 'mt --usage' for more information.

かなり違うのが解ると思います。使える文字種も減っています。

解決していく

しかし、よく見てみれば 世界樹 を得るだけであれば Try...の行さえあれば大丈夫であることがわかります。

なのでkanataさんのやったようにいらない部分を削っていきます。

$ __=$(mt 2>&1)
$ echo $__
使用法: mt [OPTION...] 操作 []
Try 'mt --help' or 'mt --usage' for more information.
$ echo ${__##*]} 

Try 'mt --help' or 'mt --usage' for more information.

いい感じですね。空行が気になりますが、必要な部分だけ記号のみで取り出せそうです。

同様にls --helpの出力も必要な部分だけ取り出すようにしていきます。

$ LANG=C /bin/ls --help|grep -o .|sort -u|grep "[A-Za-z]"|xargs
A B C D E F G H I K L M N O P Q R S T U W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z
$ /bin/ls --help|grep -o .|sort -u|grep "[A-Za-z]"|xargs
A B C D E F G H I K L M N O P Q R S T U W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z

ん?あれ?一緒なの?日本語にしても得られる文字種は一緒に見えます。これならLANG=Cしなくても良さそうです。少なくとも日本語環境では

しかしホンマかいなと思って発表時に得られなかった文字を探してみました。そしたらjだけが新たに現れていました。しかも両方

なんかおかしいな〜とおもって確認したら

$ type ls
ls is an alias for exa

あ〜〜〜exaに変えてたんだった

github.com

実際jが増えたからと言ってどうせJ,Vが足りないのでブレース展開をするので何でも良いんじゃないかと考える方もいるかと思いますが、世界樹内での文字の位置が変わるため、割と死活問題です・・・

まとめ

今回はmtが作るマナについて少し調査しました。その結果

  • 古いmtと最近のmtじゃUsageが違う(この違いを属性の違いとした)
  • aptで探すと出てくるのは古いほう。
  • 古いUsageだとそのままじゃ世界樹にならない
  • tsetのマナから足りない部品を集める。ただしmtは既に使わなくてもいいレベルで文字が豊富

さらにLANG=Cが必須かもしれない問題についても少し取り組みました

  • やはり環境に依存しない部分だけで難読化するのがよさそう
  • mtの場合は必要な部分だけ切り取ってやればOK
  • つまりLANG=Cはなくても良い
  • ただしツールは合わせること(/bin/ls を指定するとか)

難読化シェル芸。とっても楽しいですね。色んな所で話題になっているようで、これで興味を持ってもらえていたら難読化シェル芸クラスタとしてはとっても嬉しいです。ありがとうございます。

これからもヤベー難読化が見つかることを楽しみにしています。