戴兜

戴兜

Coding the world.
github
bilibili
twitter

base64データのステガノグラフィー実装原理の分析

image

この記事を始める前に、まずは base64 エンコードされた文字列のグループを見てみましょう。

ZG==
YY==
aW==
ZF==
cm==
aM==
b2==
dc==
c2==
Zf==

デコードされた内容は daidrhouse で、問題はなさそうです。しかし、よく見ると、1 行目と 4 行目のデコード結果はどちらも d ですが、内容が異なるようです。

通常の base64 エンコードでは、daidrhouse は以下の結果になります。

ZA==
YQ==
aQ==
ZA==
cg==
aA==
bw==
dQ==
cw==
ZQ==

明らかに、前者と比較して、各 base64 の 2 番目の文字が変更されていますが、デコード後の内容は変わりません。これは、base64 エンコードの原理について話す必要があります。

base64 とは#

その名前が示すように、base64 エンコードは、バイナリコンテンツをエンコードするために 64 個の ASCII 文字を基にするエンコーディング方法です。おそらく皆さんは、ウェブページで base64 エンコードされた埋め込み画像を見たことがあるでしょうし、QQ 音楽が歌詞ファイルを転送する際にも base64 エンコードを使用しているかもしれません。バイナリを ASCII 文字にエンコードすることで、データが特定のシナリオで読みやすく、転送しやすくなります。もちろん、すべてのバイナリをたった 64 文字で「凝縮」して表現することは、容量の面で妥協する必要があります。文字はエンコード後に 1/3 倍に増加しますが、その理由については後で説明します。

インデックステーブル#

base64 には、64 個の ASCII 文字を並べ替えてインデックスを割り当てた標準のエンコードテーブルがあります。

インデックス文字インデックス文字インデックス文字インデックス文字
0A16Q32g48w
1B17R33h49x
2C18S34i50y
3D19T35j51z
4E20U36k520
5F21V37l531
6G22W38m542
7H23X39n553
8I24Y40o564
9J25Z41p575
10K26a42q586
11L27b43r597
12M28c44s608
13N29d45t619
14O30e46u62+
15P31f47v63/

混乱を避けるために(リンクなど)、+ / の代わりに . _ を使用することもあります。

エンコード方法#

base64 は、3 バイト(24 ビット)を 1 グループとして処理します。3 バイトに満たない場合は、0 でパディングし、末尾に = を使用してパディングされたバイト数を示します。そして、6 ビットごとに 1 グループとし、24 ビットを 4 つの 6 ビットのバイナリにエンコードします。この時、6 ビットのバイナリは合計で 26=642^6=6426=64 の組み合わせがあり、ちょうど 64 個の文字で表現できます。(これがエンコード後のサイズが 1/3 増加する理由でもあります)

例を挙げる#

image

image

ステガノグラフィの原理#

base64 のデコード時には、文字列の末尾の = の数に応じて、対応するバイト数を削除します。おそらく気づいているかもしれませんが、1 バイトまたは 2 バイトの場合、4 ビットまたは 2 ビットのバイナリがデコード時に無視されることがあります。以下の図の赤いマークです。

image

image

赤いマークのバイナリはエンコードできますが、デコード時には無視されます。これらの位置の内容を変更しても、元のデータには影響しません。

問題を解決する#

さて、記事の冒頭の問題を解決してみましょう。その base64 エンコードされた文字列には何が隠されているのでしょうか?

image

image

image

image

image

image

image

image

image

image

赤いマークのバイナリビットをすべて結合すると、最終的な結果である hello が得られます。

image

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。