解析手法的な

0は偉大です、そりゃあもう0なしでは生きていけないぐらい偉大です。
ありとあらゆる法則で0だけ例外なんて日常茶飯事、むしろ例外じゃない事柄の方が少ないぐらいなんじゃないですかね。
というわけで、フル0による暗号化もしくは圧縮の解析手法について。

前提:ファイル読み書きアプリがあり、ファイルフォーマットが不明で、圧縮か暗号が施されているが、、かけているだろう場所が大雑把にでも判明している。
ぶっちゃけここまで着てたら丸1日も頭捻れば大抵のフォーマットなら展開方法が出てきますが、まぁ少しでも楽するための手法です。

まず全Byteが0x00で埋まったファイルを用意します。
このファイルを読み込ませ、ちょうど圧縮なり暗号なりを終えたところでブレイクし、メモリー上に展開されている変換後のデータを覗き見ます。

ここでありえるのは大抵以下のパターン
・0xC7とか、特定の数値が延々とファイルサイズ分並んでる。
・ランダムっぽいバイト列が出ている
・ただ0x00で埋まってる
・メモリー確保した直後のままで、0xCCとか不定っぽい値が並んでる
・数バイトだけ何か出ているが後は手付かず
・それ以前にクラッシュした

特定の数値が並んでいるだけならすぐわかるとは思いますが、単なるxorもしくは加算か減算暗号です。
全byteにその数値でxorか、最上位bitか最下位bitがローテーションする加算や減算を試してみましょう、たぶん復元できます。

ランダムっぽいバイト列が出た場合は乱数xor法(私的命名)か、X次xor法(私的命名)です。
乱数xor法は種から生成できる乱数(有名どころはメルセンヌツイスター)をひたすらxorしている暗号化で、一度だけ見た事があります。
単に一つの数値でxorしないだけマシですが、該当するコードの逆アセンブリから種とアルゴリズムを洗えばすぐ解けると思います。
X次xor法は意外とよく見る手法で(なので、何か正式名前あるかも)


for(int i = 0; i < size; i++){
  data[i] ^= a;
  a += b;
  b += c;
  c += d;
  i++;
}

大体こんな感じのコードによる暗号化です。
簡単に言えばサイズ1byteの乱数を作り出す簡易アルゴリズムによる乱数xor法で、+=している変数(上記の例ではabcdの四つ)が増えれば増えるだけ判別が難しくなります。
が、所詮は簡易アルゴリズムなので、出てきたデータから逆算するか適当に逆アセンブリした物から生の値を拾ってくれば解けます。
実装が容易でxor暗号なので暗号化と展開で別に実装する必要が無く実行速度も速く、変数の数と初期値を弄ることで容易に生成数値を変更できる事が利点です。
この辺が好まれて良く使われている理由なんですかね? 正直mtによる乱数xorの方が楽で強度も高いと思うのですが。

0x00もしくは不定値で埋まっている。
(不定な値の判別が付かなければ、メモリーの確保を捕まえてそこから内容が変わっていないかを見ます)
これはフォーマットの足がかりとなるべき部分がファイル先頭に埋まっていることを意味します。
たとえばファイルサイズといった情報がファイル内に保持されており、それらの情報を元に展開を行う予定だったが読み取れなかったために展開作業を行えずに終了した、という事になります。
これにに明確な対応方法はありません。
ただ、明らかに暗号化ではなく圧縮の傾向があります。 少なくとも素の暗号データではなく暗号化データを含むコンテナファイルでしょう。
バイナリを眺める作業に戻る、逆アセンブリコードから初期の処理だけでも読み取るなど、何かしらの手は打たないといけません。
自分だったらとりあえず0x0F、0xF0、0x7F、0x80、0x01、0xFFなどで埋めたデータを読み込ませてみてその挙動を見てから考えます。

数バイトだけ何かが出ているが手付かず。
これは大分絞り込めます。
おそらくは圧縮で、なおかつ位置情報か長さ情報を含むタイプのデータが連続するタイプです。
たとえばLZSSが実装によってはこういう挙動を示します。
先頭1byteだけ弄って再読み込みなどしてみると大まかな挙動は掴める筈。
その時点でたとえ思い当たるアルゴリズムは無くともなんとなく概要はつかめているはずなので、後は適当に細部を詰めていけば理解可能です。

クラッシュした場合は多少傾向は変わりますが、0x00不定値数バイトのどれかです。
ただ先頭付近に埋まっているだろうデータが位置でも距離でもサイズでもなく、何かしらの通し番号である可能性が高いです。
(たとえば使用する圧縮アルゴリズムのIDなど)
そこが仕様上使えるようには残してあるが完全に想定外な数値である為、どのようにも扱う事が出来ず、なおかつエラーチェックが不足しているためクラッシュ。
これがよくあるパターンです。
ぶっちゃけこれに遭遇したらちまちま逆アセンブリを追う位しか手がありません、何か暴走してデータ壊れても困りますしね。

それと、上記には述べませんでしたが。
0x01,0x02,0x03,0x04と連番を仕込んだデータを読ませたり、途中まで元データと同じであとは0x00のデータなど読ませても特徴的な挙動を見つけられる事が多いのでお勧めです。
どちらにしろ、データを読ませてその結果を見れる状況になれれば後はトライアンドエラーでサクサク進みます。
逆に言えば、解析を阻止したいならここが最終ラインです。
createfileとreadfileのAPIさえ押えればここまでたどり着けますので、論文にでも載りそうな高度な物を使わない限り
呼び出しAPIリストがばれる=ファイルフォーマットまではばれると覚悟しておくべきでしょう。
問題は、そこまでして隠す必要があるのか、ということですが。

コメントをどうぞ