Shellcodeの解析_ROR13
Posted on
今回はシェルコードの解析を進めていきます。
この記事の手法を使うとROR13で難読化されたインポート関数を特定することができるようになります。
解析するバイナリは前の記事「Process Injectionを解析する」でiexplore.exeにInjectionされたコードです。そちらもぜひ読んでみてください。
iexplore.exeにInjectionされたシェルコードの動作
1. Kernel32.dllのベースアドレス取得
まず、シェルコードの\x00
から始まるアドレスを6つpush
する動きをします。これは目的の値を6つ分スタックに配置するための処理です。
※ loop
は、ecx
が0になるまでjmp
を繰り返す。
シェルコード上でWin32APIを呼び出すための前処理を行います。
loc_50B007D
ではfs:30h
のProcess Environment Block (PEB)からkernell32.dllのベースイメージ (先頭アドレス)をebx
に取得する動作を行っています。
call
の引数はさきほどの6つのアドレスになっています。
2. LoadLibraryA()のスタートアドレス取得
先ほどのcallでスタックに積んだReturn-eipをすぐさまpop esi
で取り出します。つまりesi
には050B0095の直後のアドレスが入ります。
kernel32.dllのベースアドレスが入ったebxと、Return-eipの入ったesi
の指す値を引数に関数を呼び出します。ここではその関数をaa_ror13
と名付けているのでaa_ror13(ebx, [esi])
という状態で、引数[esi]
には4B1E5ADBh
が入っています。これはROR13ハッシュです。
aa_ror13(ebx, [esi])
は始めにlstrcmpiA()のスタートアドレスを戻り値eaxに返します。このようにROR13ハッシュ[esi]を+4ずつ進めaa_ror13(ebx, [esi])
を繰り返し呼び出すことよって、[esi]が0になるまでROR13ハッシュに対応するkernel32.dll内の関数のスタートアドレスeaxをpushしてスタックに積むことを繰り返します。
以下は、インポート関数を積まれたスタックの様子です。最後に取得したインポート関数のスタートアドレスはLoadLibraryA();
のものです。
ここで、aa_ror13();
の引数[esi]
はReturn-eipだったことを思い出してください。call
の直後のアドレスであるReturn-eipには以下の様にfistp dword ptr [edx+1Eh]
などが続いていました。しかし、
call
の後ろからドラッグして右クリックでUndefinedし、dキーで4バイトのdd表示にすると、実は、Return-eip以降+4ごとにROR13ハッシュが隠されていました。
ちなみに、C言語でROR13ハッシュの計算を行う処理を載せておくので理解の足しにどうぞ。
#include <stdio.h>
typedef unsigned int DWORD;
int ror13_hash(const char *string)
{
DWORD hash = 0;
while (*string) {
DWORD val = (DWORD) *string++;
hash = (hash >> 13)|(hash << 19);
hash += val;
}
return hash;
}
int main(void)
{
printf("%x", ror13_hash("LoadLibraryA"));
return 0;
}
3. LoadLibraryA()で関数をインポート
2. LoadLibraryA()のスタートアドレス取得で050B00D4にあるcall
を実行するところに話を戻します。同じ画像を再掲しておきます。
call near ptr loc_50B00E1+1
となっていた箇所が実行に伴いcall loc_50B00E2
に変わっています。単純に足し算しただけですが、+1で1バイト分呼び出し先をずらすことでデバッガに間違ってアセンブラを表示させることができる難読化テクニックです。
呼び出し先を見ていくと、call eax
つまり、aa_ror13()の最後の戻り値であるLoadLibraryA();
を呼び出しています。
LoadLibraryA();
の引数は、直前のcall loc_50B00E2
でスタックに積まれたReturn-eipなので、そのアドレスの表示を文字列へ変換すると、advapi32であることが分かります。
ここからはadvapi32.dll内からROR13ハッシュでインポート関数のスタートアドレスを取得し、スタックに積んでいきます。マルウェアがレジストリを操作しようとしているということが分かってきますね。
画像一番下のcall dword ptr [ebp-20h]
は実際にROR13で取得した関数を呼び出しているところです。
最後に
呼び出す関数名をROR13によって隠しているシェルコードの解析手順を紹介しました。 今回登場したROR13と関数名の対応表を以下に記載しておきます。
ROR13ハッシュ
今回の記事に登場したROR13ハッシュと関数名の対応表です。
ROR13 | 関数 |
---|---|
4B1E5ADB | lstrcmpiA |
4DC9D5A0 | FreeLibrary |
7C0DFCAA | GetProcAddress |
73E2D87E | ExitProcess |
99EC895E | CopyFileA |
C2FFB025 | DeleteFileA |
56F7396A | SetFileAttributesA |
DD434738 | lstrlen |
EC0E4E8E | LoadLibraryA |
2D1C9ADD | RegSetValueExA |
A84AEB81 | RegOpenKeyExA |
2D1C9ADD | RegSetValueExA |
B4CEEAB6 | RegDeleteValueA |
2D1C9ADD | RegCloseKey |