Sponsored Link

ここにはツール解説のページに関連したトピックや詳細などを載せています。
お 題
#01 単純分割の結合
#02 テキスト変換の一例
#03 偽装鶴には何故エロゲネタが多い?
#04 ちょっと変わったあやや
#05 書庫ファイルも偽装の仲間?
#06 暗号技術は戦略兵器?
#07 マックバイナリってどうよ?
#08 ビットローテーション ・XORってなんじゃ?
#09 サイズを変えないフルカラーbmpへの埋め込み
#10 音楽の数値化
#11 フォトショの怪( ;゚Д゚)
#12 指令:kage.zipを解凍せよ!
#13 Base64って何さ?
#14 JPEGのコメントにデータを埋め込んでみる

サイトトップに戻る


#01 単純分割の結合

単純分割とは乱暴にいうと、ファイルをそのまま複数にぶった切りした感じの分割形式です。
結構この形式を採用しているツールも多いです。
先頭のファイルを見ると、元ファイルのヘッダが当然ながらそのまま残っていますので、
割と判断しやすいかもしれません。

対応ツールは「脳天唐竹割り」や「DF8」など他にも沢山あります。
自分の場合は「極窓」を使ってます。理由としては普段からよく使う機会のあるツールだし、
拡張子判別に長けたツールなので、結合後の拡張子も自動判別し割り振ってくれます。
純粋な単純分割の結合だけだったら、これが一番楽です(笑

単純分割の結合で重要なのは次の3点だと思います。

1)全ての分割ファイルが揃っている。
2)結合するファイルの順番が間違っていない。
3)個々の分割ファイルに掛けられている偽装を解除しておく。

1)は、まあ読んで字の如くです(笑。
元ファイルの形式によっては、一部欠けていてもなんとかなるものもあるかもしれませんが、
全て揃っていた方が当然いいし、殆どの形式では用をなさなくなると思います。

2)は、分割時のファイル名の付け方によっては、結合が困難になる場合があります。
分割001.jpgとかのように連番で付けられていればいいのですが、
ランダムな文字列で割り振られていると、どれが最初でどれが最後なのか判断がつきません。
全て試せはいつかは正解するでしょうが、分割数が多い程困難さが増します。

3)は、具体的に例を挙げると、「璃樹無」の「でんこ偽装」などのことです。
璃樹無は単純分割形式なので、必ずしもrezファイルがなくとも結合出来ますが、
砂嵐状の画像が目印の、通称でんこ偽装というのを掛けることが出来ます。
本家璃樹無を使う場合であっても、結合前にはでんこ偽装を解除しておく必要があります。
(「タマ。」では自動的に解除してくれますので楽です。)

コマンドプロンプトからファイル結合をすることも可能です。
バッチを組んで汎用的に自動化させたい場合は便利かもしれません。

Windowsではこの書式です。
copy /b (分割ファイル1)+(分割ファイル2)+[以下順番に同様] (生成ファイル名)
/bスイッチは、バイナリファイルとして扱うことを示します。
これを忘れると途中に制御コードなど出現すると、
そこで結合が終了してしまいますので注意して下さい。

Unixの場合はこの書式です。(情報提供はハーピーさんです。感謝!)
cat (分割ファイル1)(分割ファイル2) ・・・ > (生成ファイル名)

但し、出所不明のバッチファイルにはご注意下さい。
exeだけでなくbatも実行形式ファイルです。(記述したコマンドを連続実行させます。)
以前自分が踏んだものには、(悪用防止のため詳細は割愛しますが)
PC有害なものもありましたのでご注意下さい。
(テキストエディタで丹念に中を見れば予測は出来ます。)

お題に戻る

#02 テキスト変換の一例

ある日、あなたは妙なファイルを入手しました。
やたらと大きいテキストファイルで、
中身は改行もなく2種類の文字が延々と羅列されています。
「なんだ意味ねーじゃん。捨てよっと。」

ちょっと待った!ひょっとするとそれは偽装かもしれませんよ。
内容を2文字に変換しているのかもしれません。

簡単に原理を説明します。
まず、1バイト文字(半角文字)はバイナリエディタで見るとこんな感じです。



「ア」という1バイト文字は「B1」という16進数2桁で表されています。
00からFFまでの16×16の256通りで1バイト文字は表現されているのです。
(但し、実際に文字が割当られている数はもっと少ないです。)

さて、この16進数を2進数で表現してみるとどうなるでしょう。
256は2の8乗です。00000000から11111111の8桁の数字となります。
このパターンでいくと「ア」は10110001になります。

勘のいい方は話しが見えてきたと思いますが、
この8桁の0と1を別の文字に置き換えてしまうのです。
仮に0をY、1をZで表現すると、先の「ア」は「ZYZZYYYZ」という文字列になります。
ただし、この表現するための文字に2バイト文字(全角文字)を使うと、
上のバイナリエディタの画像でも分るように2倍の文字数を必要とします。

2進数に直すと、1バイト文字だと元の8倍、
2バイト文字を使うと倍の16倍になるのです。
この手のテキスト変換系に、「変換後はファイルサイズが元の16倍になります」
というのが多いのはこういう理由なのです。

とはいえ、そのツールによっては2文字でなくて任意の文字数に出来たり、
別の進数だったり、独自のヘッダやフッタを付加したりするものなどがあったりして、
必ずしもこの手順で100%復号できる訳でもありません。
ただベースとなる考え方としては、上記の理屈なのだと思います。

お題に戻る

#03 偽装鶴には何故エロゲネタが多い?

以前mixiの偽装解除コミュでも話しが出たのですが、
偽装ツールのタイトルやインターフェイスなどには、
何故かエロゲキャラに関係したものが多いようです。

自分はエロゲはやらないので(そこのあなた、信じなさいってば!^^)、
なんというゲームのなんというキャラなのかは見てもわかりませんが、
インターフェイスに表示される虹絵をみるだけでも、
確かに萌え系だなと判断出来るものが多いてす、これが。

何故か?と言われれば、作者様達に聞くしかないのですが、
私論を述べると、Information内のこのサイトをまとめた動機の欄にも関係しますが、
偽装という行為には「洒落」という要素が多分に含まれていると思います。
色々思考を凝らせて、ファイルを別の物に変換しちゃおうというその発想。
そこには解除する人との駆け引きまでもを想定して、
辛いながらも楽しんでプログラムしている作者様の姿が見えるのです。

決めつけになってしまうかもしれませんが、多分偽装ツールの作者様というのは、
他の所謂実用的なアプリだけしか創らないプログラマの人に比べて、
洒落を楽しむことが出来る人が多いような気がします。
(勿論これは勝手な自分の想像であり、特定の人を揶揄・誹謗する意図はないです。)

そんな洒落っ気のある人達だから、ツール名やインターフェイスにも
人を楽しませよう、そして自分も楽しもうという姿勢が見えるのではないかな?
と思ったりします。
(でも、エロゲである必然性が↑では説明されていませんね、うーむ^^;)
実際のところ、よくわかりませんです(爆。

お題に戻る

#04 ちょっと変わったあやや

「ちょっと変わった」といっても、別にあややが変な格好で街中を歩いているとか
そーゆーことではありません。(当然だが)
以前、某所でちょっと変わったBDBZMの使い方を見たので再現してみます。

[サンプルファイル]

zipを解凍すると、あややで偽装したpdfがあります。

bbmは埋め込まれていますので、あやややタマ。に反応します。
が、パスワード設定がされているため、パスが解らないとそれ以上は進めません。

しかしこれは、ヘッダ偽装なしの分割形式が単純分割で分割数が1ですので、
バイナリエディタで覗くと、ヘッダが元ファイルのjpgファイルの状態そのままで残っています。

これを手動でjpgにリネームするか極窓にかけるかするとちゃんと見れます。
埋め込まれたbbmファイルの部分がオリジナルよりサイズ増加しますが、特に再生に影響は出ません。

ので、本来解除するハズのあやややタマ。だとダメで、それ以外の方法で解除できるという、
「偽装を偽装した偽装ファイル」といった感じになっています(笑

お題に戻る

#05 書庫ファイルも偽装の仲間?

ふと思ったのですが、書庫ファイルというのがありますよね。
そう、zipとかlzhとかcabとかの拡張子のついている奴。
思うに、これもある意味偽装の仲間なのでは?と
マイナーな形式であれば、これだけで充分偽装かもしれない(^^;
(実際問題として、イリーガルなファイルの流通のために開発終了したレアなアーカイバ、
またはシェアウェアのアーカイバを使って、利用者をふるいにかけるという傾向も一部にあるようです。)

書庫ファイルは生成される時に、一般にサイズが小さくなります。
アルゴリズムや元データの内容によって開きがありますが、
一般的には60〜80%台程度にサイズが圧縮され、
元が無圧縮の形式であれば、ファイル内容によっては10%台程度になったりもします。
(但しJpegやmp3等、既に圧縮がなされている形式だと、殆ど圧縮効果は期待出来ませんが・・・)

簡単に原理の一つを説明すると、連続して出現する部分を短縮します。
仮に複数続く文字列を『[文字][繰返回数]』と表現することにします。
『はははもももすき』(母は桃も好き)という文章は、
『は3も3すき』となります。これだけでもちょっと短くなりましたね。
これはラン・レングス法と呼ばれている手法です。
連続して同じ内容が出現する傾向があるデータだと、かなりの圧縮が期待出来ます。

他にハフマン法だと、『出現頻度が高いデータ程、表現するためのコードに短いものを割り当てる』、
といった感じになります。
自分はそんなに詳しい訳でもないので、興味のある方はご自分で調べてみて下さい。

こういった圧縮の考え方・手法と、テキスト変換や暗号化の考え方・手法とが
なんとなく偽装の仲間みたいだな、と思った理由なのでした。
でも本サイトでアーカイバまで取り上げると、かなりの量になってしまいます(汗。
ので、ここでは本コラムのみの記述でご容赦下さいm(_ _)m

ちなみに書庫ファイルの種類って全部でどれぐらいあるのでしょう?
自分の環境で、アーカイバに関連付けされている拡張子をざっと調べてみました。
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
777、7Z、A、ACE、ARC、ARJ、B64、BEL、BFL、BH、BZ、BZ2、BZA、CAB、CBD、CBI、CBT、
CPIO、CXF、DEB、DGC、DGCR、DGD、DGDR、DGR、DLC、DZ、EAR、ENC、GCA、GZ、GZA、
HKI、HOG、ICE、ICEOWSDOCICE、ICEOWSDOCZIP、IMP、IZE、JAK、JAR、KPAC、
LHA、LIB、LZ、LZA、LZH、LZS、LZZ、MBF、MIM、MKG、NOA、OAR、PAK、PAR、PKK、PQA、
QZE、R00〜連番、RAR、REV、RK、RS、SAR、SEA、SFV、SIT、SQX、TAR、TAZ、TBZ、TGZ、
TZ、TZE、TZS、UFA、UHA、UUE、WAD、WAR、XXE、YZ1、YZ2、YZ2A6、Z、ZIP、ZOO、ZZ
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
・・・これだけでもざっと90種類近くありました(;^_^A
世の中に流通しているもの全部というと・・・相当な数なんでしょうねぇ。

お題に戻る

#06 暗号技術は戦略兵器?

自分が最初に暗号化ツールをインスコしたのは、確かKremlinだったと記憶しています。
その当時、Ver2.21もInternational(海外)バージョンとDomestic(国内)バージョンに別れており、
サイトの英文の内容も「この技術は戦略兵器に該当するため、次に挙げる国家への輸出を禁じます」
といった感じの意味の文章になっており、ここでは具体的な国名は伏せますが、

東アジアのあの国とか中東のその国とかアフリカ大陸のこの国とか中米のどの国とか、
某国が名指しで非難している国々の名前が記載されていた記憶があります。
その時の自分の気持ちは、多分・・・こんな感じ

ビクッ. ∧∧ ∧∧   / ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
   Σ(゚Д゚;≡;゚д゚) < うお!なんかすごいところに迷い込んじまったぞゴルァ!
     ./ つ つ   \______________________
  〜(_⌒ヽ ドキドキ
     )ノ `J
お題に戻る

#07 マックバイナリってどうよ?

正確にいうと偽装ではありませんけれど・・・

マッキントッシュで作成されたファイルは、
ヘッダ部分とデータフォーク部分とリソースフォーク部分の3部門で構成されています。
このうち、リソース部分を含むのは主にプログラムなどの実行形式ファイルとの事であり、
ウィンドウズユーザーは最初から手を出さないと思うので特に問題ないと思いますが、
画像データなどの全OSユーザーが利用すると思われるファイルは、
残りのヘッダ部分と実際に利用されるデータフォーク部分の構成となります。

実はこの128バイトのヘッダ部分が曲者で、
他OSでデーダ利用する際に読み込みの邪魔するのです。
このヘッダ部分がマックバイナリと呼ばれているものです。
(正確にはマックバイナリヘッダですが、一般にヘッダ部分を直接そう呼んでいます。)

マックユーザー以外にとっては、ある意味偽装と呼んでも差し支えないものかもしれません。



上がマックバイナリ付きで(反転部分)、下が先頭の128バイト除去後です。
サンプルはsit形式の書庫です。
(本当は直接画像データとかにマックバイナリが付加されたものがあるとよかったのですが・・・)
でも最近マックバイナリもあまり見かけなくなった気しますね・・・

お題に戻る

#08 ビットローテーション・XORってなんじゃ?

えーと、実は自分自身がよくわかっていません(^(家)^;)ゞウヒャ
そこで、ツールをいぢくって体感的に把握している事を書いてみます。
(↑いいのか?それで>俺)


ビットローテーションとはこういう感じです。
例えば、半角英数の「F」は、文字コードの16進数表記だと「46」です。
この「46」を更に2進数にすると「0100 0110」になります。
(見やすいように4桁ずつ区切って表記します。)
これを右に回してずらしてみます。

回して溢れた右端の値「0」がぐるっと反対側に移動して左端の位置に入りました。
まるで一本の繋がったヒモの様にローテートします。

その結果、「0100 0110」は「0010 0011」となりました。
これを16進数にすると「23」、
文字コード表に当てはめると「#」という文字になりました。

同様に、左にシフトすると、「1000 1100」となり、
16進数の「8C」になります。


XOR(排他的論理和)は大雑把に言うとこんな感じです。

先程の半角英数「F」(2進で0100 0110)を
10進数254(16進でFE、2進で1111 1110)でXORしてみます。

同じビット位置の値が同じなら「0」、違う場合は反転して「1」となります。 

   0100 0110
 XOR 1111 1110
 ───────
     1011 1000

上下で1と1、0と0というように合致しているところは、結果が「0」になっています。
上下で0と1というように違っているところは、結果が「1」になっています。
結果の「1011 1000」は16進数で「B8」、半角カタカナの「ク」になります。


この二つは逆算が比較的容易に上、システムへの負荷の軽いこともあり、
古くから色々な暗号化に好まれて使用されているとの事です。


・・・「なんかあんまり数学的に説明になっていないぞ!」というご指摘もありましょうが、
あくまでこれは、「偽装解除するための実践的手段としてのとっかかり」として
捉えて頂けたら幸いです。
方法論より解いてナンボの世界ですから・・・(笑


尚、この項の記載に際し、猫△ワル男 ◆oKLssLV2YMさん、ハーピーさん
他皆様のご協力を頂きました。
ありがとうございます。m(_ _)m

お題に戻る

#09 サイズを変えないフルカラーbmpへの埋め込み

埋め込みの中にはBremen等のように、その前後でファイルサイズが全く変わらず、
バイナリエディタで覗いても、埋め込み前と殆ど変わらないように見えるものがあります。
これは一体どういうことなのでしょう?
その手のツールに共通しているのは、「フルカラー・24(32)ビットのbmp」という事です。
どうやらここに鍵がありそうです。

まずは改めて、この「フルカラー・24(32)ビットのbmp」の持つ意味を確認してみましょう。
今回は24ビットを例にしてみます。

先にビットの方ですか、これはPC上で扱われる最小単位、つまり電気信号のオン・オフによって
0と1の2通りを表現します。1ビットにつき2種類の数を扱える訳です。

次に「24」の方ですが、何が24あるのでしょう?
これは、色の三原色であるRGB、つまり赤・緑・青の3色が8ビットずつ組み合わせ出来るのです。

1ビット
2ビット
3ビット
4ビット
5ビット
6ビット
7ビット
8ビット
←こんなイメージでしょうか。
1ピクセル当たり8ビット×3色で24ビットとなります。

表現出来る色数としては、1ビットで0と1の2通り、
それが8ビット分あるので、2^8で256通り、
更に3色分あるので、256^3で16,777,216色分用意されている訳です。

ちなみにbmpフォーマットでは、1、4、8、16、24、32の各ビット数
がサポートされています。
1ビットだと2^1で白黒の2色、8ビットだと2^8で256色、
32ビットだと2^32で、実に4,294,967,296色が使用できる事になります。 
こんなにあっても使い切れませんね(^(家)^;)

さて、上のイメージの横の列、RGB3ビット分をビットプレーンと呼びます。
ビットプレーンが8層重なっている感じです。

ここで重要なのは、「描画に際して人間の視覚上、あまり重要でないビットプレーンがある」という事です。
下の方のビットプレーンは画像上、主要な形状を形成しているのに対し、
上の方のビットプレーンは、他とのわずかな色の違いを表現するのに使用されているのが
イメージで判ると思います。
主要でないビットプレーンの画像のみを取り出してみると、
殆ど霧のようにもやっとした画像で、なんだかわからない状態だそうです。

上の方で「こんなにあっても使い切れませんね」と書きましたが、
この視覚上あまり重要でないビットプレーン部分を使って埋め込みしているのです。
元画像はあまり画質の劣化もなく、余った部分を使っているのでサイズも変わらない訳です。
(勿論、限定されたスペースなので、埋め込みサイズの制限はありますが)

ちなみにjpegフォーマットなども、視覚上重要でない部分を使って高圧縮を行っています。
ファイルサイズ圧縮に使うのがjpegで、他のデータのために使うのが埋め込み
といった感じでしょうか。

お題に戻る

#10 音楽の数値化

【お断り】
この項は私事が多く、余り偽装に関係ない上、やたら長いです^^;

それでも見てやるぞ!という方のみこちらをクリック下さい。

・・・開いちゃいましたね。。。でわ、覚悟を決めて見て頂きましょう(笑

いきなり私事で恐縮ですが、うちの子供達は浜松に本社がある
某三連音叉印の音楽教室に通っています。
それを踏まえた上で、この間の風呂の中での会話です。

子(息子): (風呂桶を叩きながら)ココココ「8分音符っ!」(倍テンポで)ココココ「16分音符っ!」
父(おいら): 「その次は?」
子: 「うーん?」
父: 「16×2は?・・・16+16でもいいけど。」
子: 「・・・32分音符っ!」
父: 「その次は?」
子: 「えーっ?あるの?そんなの。」
父: 「あるよ。同じようにやってみ。」
子: 「・・・64分音符っ!」

・・・そうして、このお調子者の親子は延々と2048分音符辺りまでやったのでした^^;
で、途中で父はハタと気が付いたのでした。(途中で気付けよ>父)
「そういえばこの音符の分割数って、よくPCに出てくる数だよなぁ。」
いや、実際問題として譜面で見るのは32分音符、せいぜいヒゲ四つの64分音符位までです。
まあ、あくまで理論上の音符ということで。
(そんなに細かくするんなら、テンポを倍にして一つ長い音符で記譜した方が楽だしw)
8、16、32、64、128、256、512、1024なんてのはPC扱う上でよく見かける数字ですよね。
多分、ここを見ている人の中には、1000より1024の方がスッキリした数字だと思う人も居るハズ。
(そこの貴方ですよw m9(・∀・)ビシッ!!)

さて再び私事です。(年寄りの話しはやたら長いので注意w)
自分は昔バンドやってて、ベースやらギターやら弾いていました。
でバンドとは別に、ミニキーボートとKORG製の弁当箱位の大きさのシーケンサーを使って
いわゆる「打ち込み」というもので遊んでいました。
そんな事をしているのを知っていた職場の人が、「こんな本もあるよ。」と教えてくれたのが、
コンピュータ・ミュージック専門誌でした。創刊間もないCMM誌です。
それには毎月MS−DOS上で動くシーケンスソフトの体験版が付いていました。
それが自分とパソコンとの出会いです。(オフコンは除く)
世はローランドの「ミュージ郎」などのパッケージDTMセットが発売され出し、
MS−DOSも3.3Cで、PCスペックも日電の16ビットPCといったご時世でした。
いまとなってはアレなスペックですが、こうして自分はPCを使い出したのです。

さて、タイトルに戻って「音楽の数値化」ですが、忘れてならないシーケンスソフトがあります。
カモンミュージック社の「レコンポーザ」シリーズです。
PC88の頃より存在する数値入力に特化したmidiシーケンスソフトです。
DOSからウィンドウズの切り替わりの時に、従来の操作感を維持出来ずに(←あくまで私見ですが)
今では幻のソフト(販売は現在も行われているようです)となってしまった感がありますが、
製作現場では、そのスピーディな入力方法により未だにDOS版使用者も結構いらっしゃるようです。
自分もメインで使っていましたが、音符入力型のシーケンスソフトよりも判りやすく、
編集も楽なソフトでした。非常にデータの見通しがよかったのです。
拡張子midが標準的midiデータになる前は
拡張子rcpが事実上の標準的midiデータだったのです。
他のシーケンスソフトの数値入力は、このソフトがベースとなっています。

レコンポーザの入力はこんな感じでした。
確かVer2.5F辺りからタイムベースが48から480に引き上げられましたが、ここでは48で表記します。
(※タイムベース=分解能、通常四分音符を表現するために要する値)

NOTE K# ST GT VEL 左からノートaiKeyaj、ステップタイム、ゲートタイム、ベロシティです。

ノートbヘ、ト音記号の五線譜の下側に加線したところのドを
C4とした音程を表します。Cはド、Dはレという風になっています。
(ドレミの英表記ですね。)

K#はC4を60として、半音上がると+1の61といった
感じで音程を表します。
(ノートbニKeybヘ連動していますので、
一方を直すともう一方も変化します。)
C4 60 48 45 120
D4 62 24 22 0
E4 64 24 22 107
F4 65 0 45 87
A4 69 48 44 97
C5 72 48 24 127
--------192-------

ステップタイムは音符の長さを表します。
(厳密にいうと「次のコマンドまでの長さ」なのですが、ここでは便宜上こう記述します。)
一般に48は四分音符で24は八分音符です。(別に自由に設定してもよいです。)
0というのがありますが、これは次の音符まで0、つまり次の音符との和音を表します。

ゲートタイムは、実際に発音している時間です。
STが48でGTが24位だと半分の値なので楽譜的にはスタッカートの長さとなりますね。
これがST<GTだと、音程によりタイだったりスラーになったりします。

ベロシティは音の強さ(楽器を弾く強さ)です。0〜127までの128段階です。
絶対的な音量のコマンドは別にありますので、ここではピアノの鍵盤を強く叩いたとか、
バイオリンの弓を強く弾いたという、弾き方による楽器の音質の違い的なものです。
(弱々しく弾いたピアノをスピーカーで大音量にしたものと、
力強く鍵盤を叩いたピアノをスピーカーで小音量で再生したものとでは、
音質は全然違う筈です。その違いです。)
このベロシティか前述のGTを0にすると発音なし、つまり休符ということです。

最後の-------192-------は小節線に当たるもので、数字はSTの和が計算されます。
通常、4/4拍子は192になる事が多いです。
これはTB48×4という事のですが、48という数字は2の倍数の音符と3連符系の3の倍数、
どちらも割り切れて表現するのに都合の良い数字なのです。
(勿論4/4拍子の合計を192と決めつける必要はありません。自由に設定出来ます。)

基本的な入力はこんな感じで、他にテンポやプログラムチェンジ(楽器の変更)等々、
midi規格を制御するコマンドを入力していきます。

この操作体系を受け継いだフリーソフトとして、X68から移植されたSTed2があります。
(Windows版もダウンロード可。原作者様のご冥福を祈りつつ・・・(-人-))
他に、操作感はやや異なりますがmidiomというソフトもあります。
(製品版に比べて若干制限がありますが、フリーウェア版もあります。)


というように、音楽って結構数値化しやすい要素があります。
(勿論、数字だけで音楽は語れるものではありませんけどね♪)
自分はプログラムのプの字も分らないので出来ませんけど、
・・・どなたか実際に演奏可能な偽装midiツール、作ってみます?(^^;
↑と思ったら既にありました(^^;
おジャ魔などれみです。

お題に戻る

#11 フォトショの怪( ;゚Д゚)

・・・まるで週刊誌か「ムー」(←まだあるのかな?)の見出しのようなタイトルにしてしまいました。(汗
(ごめんなさいm(_ _)m>Adobe社関係の皆様、Photoshopファンの皆様)
いや、「怪(あやかし)」という程の話ではないのですが、
Adobe社のPhotoshopで作成したjpgについての話です。

ちょっとその前に、偽装判定の目安というか自分なりのポイントについて書かせて頂きます。
自分の場合だと、バイナリエディタで覗いた時に大体こんな点を見ています。

○ヘッダ・フッタの状態
○既存形式のヘッダが再度出現していないか
○ファイル名・拡張子名・偽装ツール名らしき文字列などがないか
○2のべき乗桁(主に4桁とか8桁程度)の英数字(0〜9、A〜F)の文字列がないか
○0x00や0xFFなどの同一値が暫く連続するか、または類するブロックが反復的に出現していないか

ざっとこんな感じです。

さて本題ですが、Adobe社のPhotoshop(以下フォトショ)でjpgを作成した場合、
特徴的な点が出現する事があるようです。
(自分はフォトショを持ってないので、直接検証が出来ません。曖昧な書き方で申し訳ないです。)

それは、(1)jpgヘッダが2回出現する。(2)「Ducky」という文字列がある。
という点です。

(1)についてですが、調べてみるとフォトショは
サムネイル画像のデータなどもアプリケーションセグメントというエリアに埋め込むとの事です。
これはExif規格とも絡みがあるようです。
どうやら、そのために「.リ....JFIF」というjpg特有のヘッダが2回出現するようです。
(このサムネイルデータ部分はかなりデカいみたいです。)

(2)についてですが、古いフォトショにはこの機能はないらしいですが、
上記のサムネイル等のデータを付加しない保存方法(「Web用に保存」)をした場合、
「Ducky」という文字列が付くみたいです。



さて先程の判別ポイントの中で、
○既存形式のヘッダが再度出現していないか
○ファイル名・拡張子名・偽装ツール名らしき文字列などがないか
という2点で、このフォトショ作成のjpgファイルがちょっと混乱する要因となるかもしれません。
フォトショjpgに怪かされないように皆様ご注意下さい。

え、そんなのはお前だけだって?・・・ごもっともです、ハイm(_ _)m

お題に戻る

#12 指令:kage.zipを解凍せよ!

影武者に標準添付されているダミーファイルに「kage.zip」というのがあるのですが、
これが書庫の見本市ともいうべきもので、色々な形式の書庫が多重圧縮されています。
有名なものからちょっとマイナーなものまで各種見ることが出来ますので、
もし機会がありましたら、一度御覧になってみてはいかがでしょう。
自力でコンプしたい方は、ネタバレに付きこの先閲覧をなさらない方がよろしいかもしれません。

続きを閲覧される方はこちらをクリック下さい。

解凍手順を一覧にするとこんな感じになります。
階 層
(圧縮回数)
ファイル名 サイズ
(byte)
備     考
18 kage.zip 1,621 解凍の始まり(圧縮の最終地点)
17 list.gz 1,483
16 list 3,072 拡張子なしのtar書庫(1回目)
15 list.gca 1,276
14 list.gza 1,276 1回目のgza
13 list.yz1 1,551
12 list.lzh 995
11 list.777 925
10 list.ufa 855
09 list.gza 787 2回目のgza
08 list.cab 754
07 list.zz 646 当環境(zzip.exe)では「Zzip error : unsupported compression method」
対策として、3バイト目の30hを31hにバイナリエディタで書換してから解凍
(画像)
06 list.bza 563
05 list.uha 527 当環境(UHARC.EXE)では2バイト文字のパス・ファイル名不可
対策として、パスに2バイト文字の入らないフォルダで作業
04 LIST.BZ2 437
03 LIST 2,048 拡張子なしのtar書庫(2回目)
02 list.lzz 425 当環境(LZA32.EXE)では、解凍したいファイルを明示的に指定する事と
/Uスイッチを使用する事で解凍(/Xでは不可)。
例)LZA32 list.lzz list.rk /U
(生成されるファイル名はバイナリエディタで覗いて推測)
01 list.rk 172
00 list.txt 78 解凍のおしまいヽ(^(家)^)ノ

で、list.txtの中身は↓です^^;
偽装・圧縮解除、ご苦労様でした。
これを見れた方は、かなり詳しい人ですねぇ〜。

解凍後半戦になるとGUIベースでなく、ほぼCUIベースのツールで解凍する事となりました。
(-(家)-)y-~~DOS窓ナツカシカッタヨw
この作業の為に、新たにツールを2個程探してきたのは秘密ですw

お題に戻る

#13 Base64って何さ?

Base64というのはテキスト変換の一種で、規定されたASCIIに符号化するアルゴリズムの一つです。
規定された変換後の文字列は、「A」〜「Z」、「a」〜「z」、「0」〜「9」、「+」と「/」の64種類です。
(文字数によっては、「=」も端数調整のために使われる場合があります。)
また、MIMEにより76文字毎に改行コードが挿入される規定になっています。
(ちなみに、Win/DOS系がCR+LF(0D 0A)、Mac系がCRのみ、Unix系(含Mac OS X)がLFのみです。)

利点としては、US ASCIIのみの構成のため、バイナリデータが扱えない環境でも利用出来る点で、
電子メール添付のバイナリデータは、制約より7ビット文字列以外で送受信する事が出来ないため、
Base64で符号化して添付される事が標準的に利用されています。

また、テキストのみで構成されているので、掲示板に直接エンコード後の文字列を投稿して、
その文字列を保存してデコード、という手法でバイナリデータをやりとりする事も可能です。
(但し、モノによっては、かなり長い文字列になるとは思いますが・・・^^;)

また、文字種がバイナリデータは00h〜FFhの256種に対し、64〜65種の文字列に集約されるので
書庫にした時の圧縮率(だけならば)はかなり良好な傾向にあります。
1MBの適当なダミーを作ってテストした所、未エンコードのものをzipで圧縮した場合は98%に対し、
エンコードしたものを同様に圧縮した場合は76%のサイズとなり、約20%の差がありました。
(但しエンコードそのものによって、元サイズがかなり違ってきます。詳しくは後述。)

反対に難点としては、アルゴリズムとしては比較的単純なものであるため、
暗号化・セキュリティという観点だとやはり若干弱い点は否めません。
とはいえ、見る人が見れば解るという感じだと思うので、一般的利用ではさほど問題はないと思います。

また、詳しくは後述しますが、通常1バイトは8ビット(1オクテット)単位で構成されているのに対し、
Base64は6ビット単位、更には4バイト単位で変換をしますので、
どうしても変換後はファイルサイズが大きくなりがちです。
(とはいえ、上記#2の16倍増量タイプに比べるとかわいいものではありますが・・・^^;)
前述の1MBのタ゜ミーだと、エンコード後のサイズは約1.37倍に膨らみました。
(単純計算で8/6倍(1.33倍)+改行分ですね。)
そのエンコード後1.37倍となったファイルをzipで圧縮しても、
結局は元の1MBよりも若干大きいサイズとなってしまいました。

では、実際に変換を見てみましょう。
サンプルは「技総研よ」という8バイトの文字列です。
16進表記だと「8B 5A 91 8D 8C A4 82 E6」になります。
さらに2進数のビット表示だと
8B → 1000 1011
5A → 0101 1010
91 → 1001 0001
8D → 1000 1101
8C → 1000 1100
A4 → 1010 0100
82 → 1000 0010
E6 → 1110 0110
となります。

先程6ビット単位で変換と述べました。
これを6ビット単位で区切ってみましょう。
1000 10
11 0101
1010 10
01 0001
1000 11
01 1000
1100 10
1001 00
1000 00
10 1110
0110
となります。
最後の分は4ビットしかないので、足りない2ビット分を「0」で埋めて「0110 00」にしてしまいます。

続いてルックアップテーブルです。こんな↓感じです。
000000 A 010000 Q 100000 g 110000 w
000001 B 010001 R 100001 h 110001 x
000010 C 010010 S 100010 i 110010 y
000011 D 010011 T 100011 j 110011 z
000100 E 010100 U 100100 k 110100 0
000101 F 010101 V 100101 l 110101 1
000110 G 010110 W 100110 m 110110 2
000111 H 010111 X 100111 n 110111 3
001000 I 011000 Y 101000 o 111000 4
001001 J 011001 Z 101001 p 111001 5
001010 K 011010 a 101010 q 111010 6
001011 L 011011 b 101011 r 111011 7
001100 M 011100 c 101100 s 111100 8
001101 N 011101 d 101101 t 111101 9
001110 O 011110 e 101110 u 111110 +
001111 P 011111 f 101111 v 111111 /

000000 が「A」で1ビットずつ増加していき、
  (中略)
011001 が「Z」、
011010 が「a」、
  (中略)
110011 が「z」、
110100 が「0」、
  (中略)
111101 が「9」、
111110 が「+」
111111 が「/」に割り当てられています。

この例に当てはめていくと、
100010 →i
110101 →1
101010 →q
010001 →R
100011 →j
011000 →Y
110010 →y
100100 →k
100000 →g
101110 →u
011000 →Y
となります。

変換後は「i1qRjYykguY」という11バイトの文字列となりました。
但し、このアルゴリズムは4バイト毎に変換される事になっています。
4バイト単位で区切ってみると「i1qR jYyk guY」となり、
最後の「guY」は3バイトだから1バイト足りない事になります。
そのような4バイトに満たない部分は、「=」で埋める事になっていますので、
エンコード後の文字列は「i1qRjYykguY=」になります。
変換後のバイト数は、必ず4の倍数になる事になります。
(8ビットで3バイトのものが丁度6ビットで4文字と端数を出さずに換算出来ます。)
1000 1011 1000 10
0101 1010 11 0101
1001 0001 1010 10
01 0001

他に似たような形式に下記のようなものがありますので参照下さい。

UUencode
Base64の基礎となったとの事で、Unixでは昔から存在している形式のようです。
こちらも6ビット単位で変換で、割り当てられる文字が下記の64種類です。
『`!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_』
6ビットの値に20hを加算(もし加算後20hならば60hとする)します。
つまり000000は20hで60hに読み替えられ、000001は21h、111111は5Fhとなります。
これは文字コード表の順番に対応します。(但し60hの「`」が最後でなく最初になります。)
3オクテット(8ビット×3)単位で変換しますので不足分は00hを補填します。
「begin」で始まり「end」で終わり、拡張子も.uueや.uuというパターンが多いです。

Base64url
Base64に使用されている「+」と「/」はURLやファイル名やパス名において特殊な存在です。
エンコード後の文字列が誤動作を引き起こさないよう「-」と「_」に差し替えられたものです。

Q-Encoding(Quoted Printable)
元から殆どがUS ASCIIで構成されているファイルの場合だと、
逆に局所的に存在する他の部分を変換した方が効率的である場合があります。
基本的にUS ASCII部分は無変換で、それ以外の部分は「=AA」のように=の後に16進表記します。
これにより「=」は変換部分として扱われるため、文字としての「=」は「=3D」として表記されます。
空白や制御文字や一部文字も「=○○」の形で変換します。

basE91
Eは大文字で表記するのが正しいそうです。
こちらは記号部分が追加されて全部で91種類の文字が割り当てられています。
『ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
0123456789!#$%&()*+,./:;<=>?@[]^_`{|}~"』
Base64より変換効率は良好です。


(2008/03/28 追記)

最近、"base91 デコード"でぐぐってここに辿り着く方も多いようですので、
もうちょっと詳しい記事を追加します。

basE91の変換後の文字列は、印字可能な94種類のASCII(0x21から0x7E)のうち、
「'」(0x27)、「-」(0x2D)、「\」(0x5C)の3つをを除いた91種類で構成されています。
変換表はこんな感じです。
0 A 0x41 13 N 0x4E 26 a 0x61 39 n 0x6E 52 0 0x30 65 % 0x25 78 > 0x3E
1 B 0x42 14 O 0x4F 27 b 0x62 40 o 0x6F 53 1 0x31 66 & 0x26 79 ? 0x3F
2 C 0x43 15 P 0x50 28 c 0x63 41 p 0x70 54 2 0x32 67 ( 0x28 80 @ 0x40
3 D 0x44 16 Q 0x51 29 d 0x64 42 q 0x71 55 3 0x33 68 ) 0x29 81 [ 0x5B
4 E 0x45 17 R 0x52 30 e 0x65 43 r 0x72 56 4 0x34 69 * 0x2A 82 ] 0x5D
5 F 0x46 18 S 0x53 31 f 0x66 44 s 0x73 57 5 0x35 70 + 0x2B 83 ^ 0x5E
6 G 0x47 19 T 0x54 32 g 0x67 45 t 0x74 58 6 0x36 71 , 0x2C 84 _ 0x5F
7 H 0x48 20 U 0x55 33 h 0x68 46 u 0x75 59 7 0x37 72 . 0x2E 85 ` 0x60
8 I 0x49 21 V 0x56 34 I 0x69 47 v 0x76 60 8 0x38 73 / 0x2F 86 { 0x7B
9 J 0x4A 22 W 0x57 35 j 0x6A 48 w 0x77 61 9 0x39 74 : 0x3A 87 | 0x7C
10 K 0x4B 23 X 0x58 36 k 0x6B 49 x 0x78 62 ! 0x21 75 ; 0x3B 88 } 0x7D
11 L 0x4C 24 Y 0x59 37 l 0x6C 50 y 0x79 63 # 0x23 76 < 0x3C 89 ~ 0x7E
12 M 0x4D 25 Z 0x5A 38 m 0x6D 51 z 0x7A 64 $ 0x24 77 = 0x3D 90 " 0x22

変換の仕方の概要は、変換対象部分を91で割って得た整数の商と剰余の値を、
上の表に当てはめてASCIIにそれぞれ変換します。
変換後は、商の部分と剰余で合せて2つのASCIIが得られる事になります。
例えば変換対象部分の値が1347だとしたら、
1347÷91=14と余りが73なので、まずは14と73という値が得られます。
これを上の表で変換してみると、14は「O」(0x4F)と73は「/」(0x2F)になります。

さて、変換対象範囲はどのように区切られているのでしょうか?
Base64の場合だと、データを6ビットずつ区切っていました。
6ビットは000000から111111までの丁度64通りです。
また、3オクテットの内容が丁度4バイトに変換されるので解りやすいです。
しかし、basE91は91通りに変換します。
0から90までの91通りというと、90はビット換算すると1011010となり、
Base64に比べるとなんだか中途半端な感じがしますね。

ここで、先程出てきた割り算が登場します。
結論から先に書くと、basE91は基本的に13ビットずつ区切って変換します。
13ビット全てが1なら 1 1111 1111 1111 で、10進だと8191になります
これを91で割ると90となり、商も変換表にきっちり当てはめる事が出来ます。
(剰余の方は91で割るのだから、90を超える事はありません。)

ただ、剰余の方は1になる(8191-90×91=1)ので、まだ89も余裕があります。
14ビット目もちょっと変換範囲の区切りの中に入れてもいいかもしれません。
8191+89(または90×91+90)=8280で、これが1サイクルで換算出来る最大値です。
ビット換算すると10 0000 0101 1000になり、これを超えてはいけません。
という事は、14ビット目に0が来るか1が来るかはやってみないと判らないので、
仮に14ビット目に1がきても8280を超えないように、
13ビット目までの値に注目して制限を設けた方がよさそうです。

先程の最大値は14ビット目が0ならば00 0000 0101 1000となり、88になります。
という事は逆に言うと、13ビット目までで88を超えなければ、
無条件に14ビット目も変換範囲対象に入れても問題ないようです。
14ビット目に1がきても8280を超えないし、0がきてもそのまま使えばいいのです。
このようにして、13ビット目までで88を超える場合は13ビットを対象範囲とし、
88を超えないようなら14ビットまでを対象範囲として区切って変換します。

また、上の方で「Base64より変換効率は良好です。」と書きました。
Base64が変換後は約1.33倍の増加でしたが、basE91はどうでしょう?
13ないし14ビットの変換対象が2バイト、つまり16ビットに変換されます。
仮に変換対象が全て13ビットで変換されれは16÷13で約1.23倍、
全て14ビットで変換だと16÷14で約1.14倍になります。
元データが1MBのものをBase64とbasE91で変換して増加量を比較してみます。
仮にbasE91での変換が全て14ビット単位で出来たと仮定したら、
理論上、1MB×(0.33-0.14)で0.19MB、詳しく書くと199,230バイト程差が出ます。
アルゴリズムをBase64からbasE91に変えるだけで、これだけ差が出るのです。

では、実際に変換例を見てみましょう。
尚、ここでは複数バイトの並びは、電卓の進行方向が←に向かいますので、
… 3バイト目 2バイト目 1バイト目 のように接続した形で表記します。
サンプルはjpegヘッダ風味な感じの11バイトのバイナリで、
内容は FF D8 FF E0 00 10 4A 46 49 46 2B です。
jpegっぽい感じのバイナリですね

1バイト目のFFはビットだと 1111 1111 、2バイト目のD8は 1101 1000 です。
これを接続すると、1101 1000 1111 1111 となります。
まずはこれから13ビット区切ります。右端から←方向に13ビット取ると、
1101 1000 1111 1111 で 1 1000 1111 1111 となります。左側の110は次の変換に回します。
この 1 1000 1111 1111 を10進にすると6399になります。
これは88を超えているので、ここの部分の変換対象範囲は13ビットになります。
そして、6399を91で割ると、商は70で剰余は29です。
これを上の換算表に当てはめると、70は「+」(0x2B)、29は「d」(0x64)となります。
さて商と剰余、どっちを先に並べるかというと、剰余の方が先に来ます。
ですので、変換後の奇数バイトは剰余の値、偶数バイトは商の値に対応します。
つまり、変換後の1バイト目が「d」(0x64)、2バイト目は「+」(0x2B)となります。
ここまでが基本的な変換手順の1サイクルです。

次に、先程使われずに残った14〜16ビット目の 110 、
そして次の3バイト目のFF(1111 1111)、4バイト目のE0(1110 0000)を並べます。
1110 0000 1111 1111 110 から13ビット取り出して 0 0111 1111 1110 です。
10進だと2046ですので、これも13ビットのまま変換します。
2046÷91=22と余り44ですので、22は「W」(0x57)、44は「s」(0x73)、
変換後の3バイト目が「s」(0x73)、4バイト目が「W」(0x57)です。

どんどん続けましょう。
残った 1110 00 、5バイト目の 00(0000 0000)、
並べると 0000 0000 1110 00 から13ビット取り出して 0 0000 0011 1000 です。
これを10進にすると56です。
ここで初めて88を超えない値が出て来ました。
ですので、ここは改めて14ビットを取り出して対象範囲を区切り直します。
先程使わなかった14ビット目の 0 を追加して 00 0000 0011 1000 にします。
…まあ、この場合の値そのものは88で変わらないのですが、
わずか1ビット分ですが変換効率が上昇した事、
なによりも、それ以降の区切り位置のズレに大きく影響しますので、
これは大きい変化と言えると思います。
56だと商が0、剰余が56となりますので、0が「A」(0x41)、56が「4」(0x34)、
変換後の5バイト目が「4」(0x34)、6バイト目が「A」(0x41)です。

さて、パターンも分かってきたと思うので、残りは一気にやってみましょう。
本来であれば、上のように1つ1つ確認して、サイクルとして行うべき行程ですが、
長くなるので、複数サイクルをまとめて記述したものである事をご理解下さい。
0x10 0x4A 0x46 0x49 0x46 0x2B
0001 0000 0100 1010 0100 0110 0100 1001 0100 0110 0010 1011

複数バイトの並びを逆にして、13ビットずつ区切ります。
0x2B 0x46 0x49 0x46 0x4A 0x10
0010 1011 0100 0110 0100 1001 0100 0110 0100 1010 0001 0000

10進にします。
0 0101 0110 1 0001 1001 0010 0 1010 0011 0010 0 1010 0001 0000
86 4498 2610 2576

今回88を超えなかったのは、丁度末尾に当たる部分の86だけでした。
しかし、これ以上変換する対象はもうないので、ここはこのまま変換します。
(尚、basE91にはBase64のパティング「=」のような概念はありません。

商と剰余を算出します。
86 4498 2610 2576
商0,剰余86 商49,剰余39 商28,剰余62 商28,剰余28

換算表に当てはめます。
0 86 49 39 28 62 28 28
A(0x41) {(0x7B) x(0x78) n(0x6E) c(0x63) !(0x21) c(0x63) c(0x63)

分りやすいように並び替えてみます。
7バイト目 8バイト目 9バイト目 10バイト目 11バイト目 12バイト目 13バイト目 14バイト目
c(0x63) c(0x63) !(0x21) c(0x63) n(0x6E) x(0x78) {(0x7B) A(0x41)

これで一通りの変換が完了しました。
結果を順番に並べていくと、
d+sW4Acc!cnx{A (64 2B 73 57 34 41 63 63 21 63 6E 78 7B 41)
という14バイトのASCIIが得られました。

さて、本当にこの計算で合っているのでしょうか?
そこで実際にデコーダを使って変換して確認をしてみましょう。
実は手計算で1度間違いますたw(^(家)^;)ゞ

最後に 0x0D 0x0A の改行が付加されていますが、
変換そのものは無事ちゃんと合致しているようですね。
めでたし、めでたし♪

(追記ここまで)


Base32
5オクテット単位で5ビットずつ変換します。割り当てられる文字は下記の32種類です。
『ABCDEFGHIJKLMNOPQRSTUVWXYZ234567』
パディング(補充される文字)としてBase64同様「=」が使用されます。
英大文字と数字のみで、英小文字は出現しません。

Base32hex
Base32と同様ですが、割当が下記のようになっています。
『0123456789ABCDEFGHIJKLMNOPQRSTUV』
文字コード表の順番に並んでいます。ソート後の順番に配慮されたものらしいです。

Base16
0〜Fの16種類で、そのまま16進表記したものです。
バイナリエディタで表示されたものをそのまま並べたイメージですね。

ish
パソコン通信時代にLHAとセットでバイナリデータの受け渡しに活躍した形式です。
non-kana、Shift-JIS、7ビットJIS、8ビットJISなどの複数の変換テーブルを持ちます。
この形式(ツール)はファイル名、サイズ、CRC、OS名等々の数多くの情報も格納し、
ヘッダ部分は通信エラーによる破損に備えて3回記述するなどの対策をしています。
そのため、まだ不具合の多かった通信環境の当時、強力なエラー訂正能力を誇っていたそうです。
拡張子は.ishになります。

実際にエンコードしたものを何種類かサンプルで挙げておきます。
尚、拡張子は一律.txtに変更してありますのでご了承下さい。
オリジナルの内容は、当サイトのURLを記述した30バイトのテキストです。
オリジナル Base64 basE91 uuencode ish

お題に戻る

#14 JPEGのコメントにデータを埋め込んでみる

データに於いてコメントは、人間が識別しやすいように付けるメモと言えます。
が、機械にとってコメントは、逆に動作上は冗長な部分でしかありません。
しかしながら、コメントにデータを埋め込むという発想自体は、
その形式上で規定されている仕様の範囲内であれば、
整合性が取れていて無理なくアプリで開けるため、有効な隠蔽手段と言えます。
よく知られているパターンとしては、htmlのコメント行があります。
<!-- 隠蔽データ -->のような形でデータを埋め込むものであり、
多分htmlに埋め込むタイプの大半がこの形態だと思います。

自分の所持しているフリーウェアのグラフィックツールなどでも、
JPEGのコメントを操作する機能を実装しているというものは殆どなく、
(いや自分がそういうのしか持ってないだけなのかもしれませんが^^;)
あまりご存じない方もいらっしゃるかもしれませんが、
JPEGにもコメントに関する規定があり、そこを今回利用してみたいと思います。

まずはJPEGデータについて、軽くかいつまんでみましょう。
JPEGでは、色々な情報が内容毎にブロックとなった「セグメント」があります。
各セグメントの先頭には「マーカ」と呼ばれる目印があり、
このマーカ値の先頭1バイトは常に0xFFです。
続く1バイトがその種別を表します。
例えば、ファイル先頭に付くSOI(Start of Image)がD8で、
ファイル終端につくEOI(End of Image)がD9となっています。
よって、JPEGファイルをバイナリエディタで覗くと、FFD8で始まりFFD9で終わります。
この2バイトがマーカで、「SOI」などの略称を「マーカ名」、
「FFD8」などの値を「マーカ値」と言います。
SOIやEOIなどはマーカだけで動作する特殊な存在であり、
大半の他のマーカは、その後にデータ長や値などが続きます。
ここまででひとまとめになったものがセグメントになる訳です。
構造的にはJPEGファイルは、
[SOI][セグメント][セグメント]・・・[イメージデータ][EOI]
という順列を成しています。
ちなみに、マーカでなくデータとしてのFFを表現したい場合は、
FF00が用いられます。

余談となりますが、他ファイルに埋め込まれた平文のJPEGデータを探す場合は、
FFD8やFFD9を検索すると探しやすいと思います。
また、JPEGフォーマットに於いてEOI以降は無視される仕様のようですので、
単純結合で直接他のファイルを後に連結して隠蔽する方法もアリかもしれません。

大部前置きが長くなりましたが、早速JPEGにコメントを付けてみましょう。
まずは挿入する位置ですが、SOIとEOIの間であれはどこでもよいようです。
とはいえ、セグメントのド真ん中に割って入れるのもアレですので(^^;、
セグメント間の切れ目に入れた方が後で自分も判りやすいと思います。

さて、コメントのマーカ名は「COM」で、マーカ値は「FFFE」となります。
FFFEの次には2バイトのデータが続き、コメントの長さを表します。
2バイトですので最大値はFFFF、つまり65535バイトとなりますが、
ここで重要なのは、この長さを表現する2バイト自身もこの長さに含まれる点です。
よって、実際にコメントとして挿入できるのは65533バイトまでとなります。
じゃあ、それ以上あるデータは埋め込めないの?という事になりますが、
確かにこれだけでは埋め込みは出来ませんが、複数コメントに埋め込む、
つまり隠蔽データを分割して必要な分コメントを設定する事で対応出来ます。

では実際に例を見てみましょう。
埋め込んだJPEGは、989バイトで「梅」と書かれた小さなJPEGです。
今回はSOIの直後に埋め込んであります。
[埋め込み後のサンプルファイル]


3バイト目にFFFEのマーカがあります。その直後の2バイトの03DFがデータ長です。
この配置はビッグエンディアンですので、そのまま0x3DFで991バイト、
これからデータ長自身の2バイトを差し引いて989バイトの埋め込みとなる訳です。
このデータ長の2バイトを間違って計算して埋め込むと、
必要なセクメントもコメントとして扱われたり、
逆にコメントの末端がセグメントとして扱われたりして
壊れたJPEGとして扱われる恐れもありますので、きっちり計算をしましょう。
埋め込んだ終端部分は↓こんな感じです。
埋め込まれるデータの本来3バイト目にあったFFE0が次に見えます。


JPEGコメントを操作するツールというものも色々公開されているようです。
データ長の計算を気にせずに手軽に扱えるのは有り難いのですが、
根本的に扱う内容が「コメント(文字列)」を対象にしていますので、
バイナリも埋め込み可というのは、自分は未だお目にかかっていません。
(まあ、こんな天の邪鬼な使い方は普通しませんからねぇ・・・w)
ここで発想を変えて、最初から隠蔽データを文字列形式にしてしまえば
手軽にJPEGコメント操作ツールでも扱えるかもしれません。

今回は同じ隠蔽データをbasE91でエンコードしてみました。
エンコード後の隠蔽文字列ファイルのサイズは1244(0x4DC)バイトです。
[埋め込み後のサンプルファイル]


バイナリエディタで覗くと、アドレス14hにCOMマーカのFFFEがあります。
その次が04DEになっています。4DE-2=4DCとなり、ちゃんとサイズも合致します。

文字列への変換が一手間増えて結構面倒かもしれませんが、
埋め込んだデータが平文状態でなくなり隠蔽データのヘッダ等も隠れるため、
逆にセキュリティ的にはいい傾向なのかもしれません。
こういう使い方をしようとした時、JPEGコメント操作ツールを探す場合は、
(1)埋め込もうとするコメントがファイルから読み込める
(2)その際、長いコメントは分割して処理してくれる
という点に留意してみるといいと思います。

お題に戻る

サイトトップに戻る