2019.04.12
難読化シェル芸の世界 Bashとすてきな難読化②
『難読化シェル芸の世界 Bashとすてきな難読化』。ディープでユーモアあふれる難読化シェル芸の世界に触れてみてください。
『難読化シェル芸の世界』PDF書籍をマイナビブックス・Manateeにて販売中です。
書籍の内容を一部公開! ぜひニッチでディープな世界に触れてみてください。
記号だけで作る難読化:基本原理
PowerShellやJavaScriptは、どのようにして記号だけでプログラミングしているのでしょうか。PowerShellやJavaScript難読化の原理を確認してみます。重要なポイントは記号だけで文字を作り出し(記号の)変数に突っ込むという点です。そうして作った文字でプログラミングし、最後にその変数をeval(相当の命令)で実行しています。
bashに置き換えると…
• 記号だけで文字を作り出し
できるか・・・な・・・?
•( 記号の)変数に突っ込んで
コレはダメそうです。bashで変数に使えるのは英字と数字だけ…ですよね? (実は無理じゃなかったというのが後でわかります)
結果として、1,2,A,zだけ使わざるを得えませんでした。
• evalする
evalしなくても変数の内容がそのままコマンドとして認識されるためevalは必要なさそうです。
ではbashで、できるだけ英数字を使わずに難読化していきます。 基本的な原理としては、以下のように変数展開を使います。 ${変数名:offset:length} これはoffset文字+1からlength分出力する仕様です。
それでは、実際に順を追ってやってみましょう。
記号と1,2だけでアルファベットを得る
記号だけでアルファベット得るには、以下のエラーメッセージを使います。 エラーメッセージは、標準エラー出力に出力されるので標準出力に向けるよう1と2を使ってリダイレクトします。( この後1と2は使いません) 編集結果は変数に入れます。Aとzしか使えない縛りなので、ここではAを使います。 このエラーメッセージは、Linuxディストリビューションや言語環境の違いで内容が異なりますが、英語の部分(filename [arguments])は変化しません。そのため、変数展開で変化のない箇所だけ取り出します。 アルファベットaefgilmnrstu(filename [arguments] の文字列から取れるアルファベット)を得ることができました。 このアルファベットを格納した変数を利用してコマンドを実行するには、bashの 変数展開を使います。 変数展開を利用すると、この文字列を切り出すsubstringのような機能を実現できます。この配列からlsの実行は、以下でできます。 さて、このままだと使えるアルファベットが限定されています。dateもできませんし、echo,grep...よく使うコマンドも大半が利用できません。なんとか使えるアルファベットを増やす必要があります。ブレース展開でアルファベット全部を得る
使えるアルファベットを増やすには、ブレース展開を使うのがよさそうです。Aとzだけでアルファベットを全て得られます。 これを変数に入れればいいですね。ただ直接入れられません。echoなどで出力した結果を変数に入れる必要があります。 あ... echoが使えませんね。使えるアルファベット(aefgilmnrstu)からechoの代替を探しましょう。正解は・・・! これ さっきの変数展開を駆使して、setを実行します。実行結果は、なんと位置パラメータ 1) に入る仕様です。 やったね! これでdateも実行できるはずです。試してみます。 できましたね! でもまだ終わりじゃないです。
数字使っているところをなんとかする
まだ数字が入っているところがありますね。 これを何とかしましょう。もう1つの文字zをここで変数として使います。算術式展開を使います。数字を一切使わずに目的の数値を計算して出力します。一度計算に利用した変数z は、0に戻ることもなく、そのまま次の処理に引き継がれるため、現在の変数zの値を意識しながらプログラミングしなければなりません(辛い)。以下のように計算していますが、前提として変数zの初期値が1であったり、0であったりする必要があります。 全部載せるのが大変なので、dateを実行するために使う数値だけに絞っています。