reverse-eg-mal-memoのブログ -30ページ目

reverse-eg-mal-memoのブログ

サイバーセキュリティに関して、あれこれとメモするという、チラシの裏的存在。
medium(英語):https://sachiel-archangel.medium.com/

ファイルの暗号化の解析

まずは、被害ファイルの暗号化の方法から見ていきます。

ファイルの暗号化処理は、当該検体のアドレス0x004035C7の関数で実行されます。

 

ファイルの暗号化は「バーナム暗号に似た、XORを使った暗号化」を使用しています。

つまり、ファイル全体を、対になる値でXORすることで暗号化している、ということです。

 

これが、「バーナム暗号」ではなく、「バーナム暗号に似た」と表現したのには理由があります。

 

ファイル全体をXORを使って暗号化したこと自体は、バーナム暗号の仕組みと同じです。

問題は、暗号化に使われる「」です。

バーナム暗号で使われる「」は、乱数である必要があります。

しかし、このファイルの暗号化で用いられる「」は、そのファイルの暗号化のために用意された「「シードとなる64バイトのデータ」から計算される値」なのです。

確かに、人の見た目には数値の並びに法則性は見えず、文字コードに当てはめることで文字として表示して読めるものではありません。

 

しかし、コンピュータの世界では、そもそも「計算できる値」、しかも「シードとなる64バイトのデータ」があれば再現できる値は、「乱数」とは呼ばないのです。

 

このため、あえて「バーナム暗号に似た、XORを使った暗号化」という表現にしました。

 

うんちく
コンピュータでプログラムを作る人は、「乱数」というと「ランダム関数」を思い浮かべるでしょう。
私も、かつてはそのように思っていました。
しかし、それは実際は「乱数」ではなく、「疑似乱数」と呼ばれるものです。
実際の「乱数」は、基本的には「自然乱数(真の乱数)」を指します。
(特に、私が話したことがある暗号関係を研究されている方々は、この差は念頭におかれていつも話をされていました。)

自然乱数」とは、本質的に確率的な自然現象・物理現象によって作られるものを指します。
一方、コンピュータのいわゆる「ランダム関数」は、コンピュータで生成する関係上、どうあっても「疑似乱数」となってしまいます。
それは、良く用いられる「時刻」というソルトを用いていても、根本的には「疑似乱数」となります。
もしコンピュータで本物の「乱数」を得たいならば、少なくとも自然現象・物理現象を計測してそれを乱数とする機能が必要でしょう。
現実的には、コンピュータでは「十分乱数として認められる」程度に再現性が低い方法が用いられます。

 

 

「ファイルの暗号化」のロジックの解説

このファイルの暗号化について、実際のコードを確認します。

これは、実は自分はTwitterでつぶやいていました。

 

0x004035C7の関数の関数内で、「0x00407EAD」をコールしています。

 

 

この関数では、「シードとなる64バイトのデータ」を用いて「乱数に見える」値を算出します。

第2引数に「シードとなる64バイトのデータ」を指定することで、第1引数の領域に計算された64バイトのデータが出力される、という仕組みです。

また、0x00407DB3で、「シードとなる64バイトのデータ」の一部をしれっと+1加算しています。

これにより、ループでまたこの関数で「乱数に見える」値を算出する際、結果が変わるようにしている、というわけです。

 

 

「乱数に見える」値を得た後は、この値を用いてファイルデータを暗号化します。

ファイルは、この関数開始前までに既にメモリに読み込まれています。

 

 

0x00407DC9~のループでは、64バイト固定で暗号化する場合のルーチンで、暗号化対象が64バイト以上ある場合にこのルートを通ります。

また、0x00407E04~のループも非常ににていますが、こちらは64バイト未満のファイルの残りの領域を暗号化する場合にこのルートを通ります。

こちらのルートを通ると、あとは関数の終了に進む流れです。

 

それぞれ黄色でハイライトされた「xor」が、暗号化のための排他的論理和の計算というわけです。

そして、その結果はその下の「mov」でファイルの元のデータ領域に格納されている、というわけです。

 

 

「ファイルの暗号化」のロジックの動作検証

では、実際に動作させた結果を見てみましょう。

百聞は一見にしかず!

・・・というと聞こえはいいけど、実際は動かして検証しないと不安だったりして。

私はハッカーさんじゃないからねw

 

まず、「0x00407EAD」関数の開始前です。

第2引数に「0x40ECF5B0」が指定されています。

これが、「シードとなる64バイトのデータ」の初期値となります。

 

 

 

ここから「Step over」でワンステップ進めて、結果を確認してみます。

 

 

結果は、第1引数で指定されていた「0x0505FEF4」に出力されました。

確かに、これを前提の知識無しでみたら、「乱数」に見えるかもしれません。

しかし、これ(=乱数と誤認させること)が攻撃者の意図であるとも言えます。

 

そして、このパラメータを用いて実際のXORを行う処理を確認してみます。

 

 

画像では、[ebx + ecx] のアドレスのデータを al (EAXの下位1バイト)に格納しています。

分かりにくいかもですが、ebx (0xFFE6F708) + ecx (0x0505FEF4) = 0x04ECF5FC となります。

(32ビット演算なので、桁あふれしますが桁あふれした1は電子の塵となって消えます。いや、正確にはキャリーフラグには残るだろうけどさ?)

 

つまり、0x00407DD0の命令の実行で、ファイルのデータの先頭(0x04ECF5FC)のアスキー文字の「A」がalに格納されます。

そして、次の行の0x00407DD3の命令の実行で、さきほどの「0x00407EAD」関数の結果で得た値である「0x0505FEF4」のデータ(この場合0xB0)とXORを取ります。

その結果を0x00407DD6でメモリに出力していますが、その出力先は元のファイルデータと同じアドレスのため、ファイルデータは暗号化されたデータで上書きされる、ということが分かります。

 

以上のことから、「「ファイルの暗号化」のロジックの解説」に書かれた分析結果の動作が、そのとおりに実際に行われることが確認できました。

 

 

判明した暗号化の方法から考えられる復号化方法

暗号化方法が判明したので、その復号化方法を考えてみましょう。

これは単純な「xor」を用いた暗号化です。

 

つまり、復号化は、「暗号化に用いたのとまったく同じ鍵でもう一度XORすれば、復号化できる」ということになります。

 

では、「暗号化に用いたのとまったく同じ鍵」は、どのようなものなのでしょうか?

解析の通り、暗号化では「シードとなる64バイトのデータ」を用いて「0x00407EAD」をコールして鍵となる値を得ていました。

(そして、計算の度に「シードとなる64バイトのデータ」の特定の領域を加算していました。)

 

そうなると、以下を得られれば暗号化されたファイルは復号できる、ということになります。

 

  • シードとなる64バイトのデータ
  • 0x00407EADと同じ結果になる計算式

 

この記事を執筆している時点では、実は関数「0x00407EAD」の計算式をしっかり解読してはいません。

しかしながら、これはある程度時間をかければ解読可能です。

 

っていうか、ぶっちゃけ復号化ツールをつくる「だけ」であれば、この計算ロジックをアセンブラのままパクッて移植しちゃえば解決だしね?

(ニチャァ・・・という外道の微笑み)

 

こう言うと、このマルウェアの作者に「ヒ・・・ヒデェ・・・、てめぇには血も涙も無いのか!?お前の血の色は何色だ!!」とか言われそうですが。

もちろんいつも通り、私は「もちろん、体内にはヘドロが流れているぜぇ?人並みに紅い血が流れているとでも思ったか?ゲヘ、ゲヘ、ゲヘ」と答えますからね?

(これを読んだよい子のみんな!こんな変態おっさんに絡まれると、人生メンドクサイので、マルウェア作成者にはなっちゃダメだよ?)

 

言っておくが・・・私は今までに、自分が「正義の味方」だと言ったことは無いし、思ったこともないからね?w

ランサムウェアを作った人の、更に外道の所業での解決も厭わないので、そこんとこヨロシクw

(このマルウェアの作成者も、こういうタイプの変態に絡まれてたりして大変だなぁ。)

 

 

冗談はさておき。

計算式は解決の目途があるのでファイルの復号化のための問題は「シードとなる64バイトのデータ」が復元できるか否か、となってきます。

 

 

次回は、この「シードとなる64バイトのデータ」がそもそもどういうデータなのか、ということを解析した結果を出したいと思います。