Comprobador de aplicaciones: preguntas más frecuentes (P+F)
Preguntas generales
A continuación se muestra una lista de preguntas recibidas en torno al uso general del Comprobador de aplicaciones.
¿Qué es el Comprobador de aplicaciones?
Application Verifier es una herramienta de comprobación en tiempo de ejecución que se usa para buscar errores en aplicaciones de Microsoft Windows. Dado que es una herramienta en tiempo de ejecución, el código de la aplicación debe ejercerse para comprobarlo. Por lo tanto, una buena cobertura de pruebas es esencial.
El escenario de uso típico del Comprobador de aplicaciones es habilitarlo para las aplicaciones de interés (consulte las preguntas siguientes sobre cómo hacerlo) y, a continuación, ejecutar todas las pruebas que ha escrito para la aplicación. Recibirá una notificación de cualquier error que se encuentre en forma de interrupción del depurador o una entrada de registro del comprobador.
Cómo desinstalar Application Verifier?
Para desinstalar el Comprobador de aplicaciones, acceda al panel de control haciendo clic en Inicio, seleccione Agregar o quitar programas y, a continuación, quitar un programa, haga clic en Comprobador de aplicaciones y, a continuación, haga clic en Quitar.
Cómo iniciar comprobador de aplicaciones?
Después de instalar Application Verifier, puede iniciarlo accediendo a él en la lista de programas O escribiendo Appverif.exe en una línea de comandos. Para ello, vaya a un símbolo del sistema o al cuadro Ejecutar del menú Inicio. Escriba appverif.exe y presione Entrar. Se iniciará el Comprobador de aplicaciones.
El Appverifer.exe binario se instala en el directorio del sistema y se usa para establecer la configuración de la herramienta.
¿Dónde se almacenan los registros?
Los registros se almacenan en %USERPROFILE%\AppVerifierLogs.
¿Qué debo hacer si tengo problemas al usar el Comprobador de aplicaciones?
Asegúrese de que ejecuta la versión más reciente. Considere la posibilidad de probar la misma aplicación en un equipo diferente o incluso en una versión de Windows.
¿Comprueba application Comprobador el código administrado?
AppVerifier se preocupa por las interfaces entre el sistema operativo y la aplicación. Como resultado, a menos que el código administrado realice la interoperabilidad con las API nativas que tienen que ver con montones, identificadores, sección crítica, etc. los casos de prueba no le proporcionarán ninguna interacción con las interfaces que se comprueban.
Se recomienda aprovechar los Asistentes de depuración administrada para comprobar el código administrado. Obtenga más información sobre ellos en Depuración de código administrado mediante el depurador de Windows.
¿Se admite ARM64EC?
Application Comprobador no admite ARM64EC.
Preguntas del depurador
A continuación se muestra la lista de preguntas recibidas con respecto al depurador.
¿Por qué he recibido un error que me indica que necesito un depurador?
La capa de comprobación Aspectos básicos del Comprobador de aplicaciones requiere que ejecute la aplicación en un depurador. Si no tiene un depurador asociado a la aplicación antes de seleccionar la prueba, recibirá un cuadro de diálogo que le recordará que deberá ejecutar la aplicación en un depurador para obtener la información registrada.
Cómo ejecutar mi aplicación en un depurador?
Consulte los temas de instalación y configuración del depurador: Introducción a la depuración de Windows
Cómo expansión de pila de prueba sin ninguna otra instrumentación?
En general, la expansión de la pila debe probarse realmente de forma aislada de otras capas de comprobación, incluido el montón. La razón es la siguiente: cada capa de comprobación "thunks" una API o un punto exportado con alguna rutina.
Por ejemplo, una llamada a CreateFileA será una llamada a appvocre. NS_SecurityChecks::CreateFileA, que podría llamar a appvcore! NS_FillePaths::CreateFileA que podría llamar a kernel32. CreateFileA, que podría llamar al comprobador. AVrfpNtCreateFile, que llamará a ntdll! NtCreateFile. Puede ver que la instrumentación ha agregado tres llamadas de función "apiladas", cada una de ellas puede y consumirá más pila.
En el caso siguiente, la LH-verifier.dll es "thunking" cada dllMain y la ruta de acceso de código del montón "instrumentada" agregará más uso de pila. Dado que el subproceso insertado del depurador no usa los valores predeterminados de IMAGE_NT_HEADERS, la pila confirmada inicialmente no será suficiente para completar el estado de APC de un subproceso (un subproceso en el estado de APC ejecutó el código de inicialización).
Si desea usar Stack-Ckecs, probablemente la única capa de verificación que debe usar si FirstChanceAccessViolation.
Al usar la extensión !avrf, obtengo 'El comprobador de aplicaciones no está habilitado para este proceso...'
Error completo recibido: Application verifier is not enabled for this process. Use appverif.exe tool to enable it.
Es probable que solo tenga habilitadas las capas de comprobación de correcciones de compatibilidad (shim) o el montón en modo "puro". Estas son algunas de las posibles causas.
Preguntas sobre escenarios de prueba
A continuación se muestra una lista de preguntas recibidas en torno a diferentes escenarios de prueba.
¿Cómo puedo habilitar el Comprobador de aplicaciones en mi servicio, pero no en otros?
Realice una copia de svchost.exe en el directorio System32 y llame a la copia "Mysvchost.exe".
Con regedit, abra HKLM\System\CurrentControlSet\Services\MyService.
Edite el valor "ImagePath", que será similar a "%SystemRoot%\system32\svchost.exe -k myservice" y cambie svchost.exe a "Mysvchost.exe".
Agregue "Mysvchost.exe" a la lista AppVerifier y compruebe las pruebas deseadas.
Reinicie el equipo.
Cómo ejecutar Application Verifier en una aplicación de 64 bits que se inicia desde una aplicación de 32 bits que se ejecuta en WOW64?
Versión simple: la regla de oro para habilitar la configuración del comprobador en una aplicación determinada es coincidir con el bit de la herramienta y el proceso de destino. Es decir, use el appverif.exe de 32 bits para una aplicación de 32 bits (ambas que se ejecutan en WoW64) y use el AppVerif.exe de 64 bits para el destino nativo de 64 bits nativo.
Versión larga: la configuración del comprobador de aplicaciones es la unión adecuada de la configuración de "núcleo" y la configuración de "correcciones de compatibilidad".
Configuración básica: la configuración principal se almacena en Opciones de ejecución de archivos de imagen.
El valor "Debugger" se lee de la aplicación de inicio. Por lo tanto, si desea tener devenv.exe de 32 bits iniciando my.exe de 64 bits y ejecutarlo en el depurador, debe usar la clave del Registro de 32 bits en WoW6432Node. Los demás valores, para un proceso de 32 bits, se leen desde ambos lugares, tanto el IFEO nativo como el WoW6432Node.
El razonamiento es el siguiente: un proceso de 32 bits que se ejecuta en WoW es un proceso de 64 bits que ejecuta el bucle de emulación Wow64. Por lo tanto, cada proceso de 32 bits es primero un proceso de 64 bits y, después, un proceso de 32 bits. El IFEO de 64 bits habilitará el comprobador en el código de Wow64cpu.dll, mientras que el IFEO de 32 bits habilitará el comprobador en el código de 32 bits.
Desde el punto de vista del usuario final, verifier.dll se carga dos veces (una vez en el mundo de 64 bits, una vez en el mundo de 32 bits). Dado que a la mayoría de las personas no le importa comprobar wow64cpu.dll, el comportamiento más aceptado para los procesos de 32 bits es comprobar solo la parte de 32 bits. Es por eso que la regla de oro de "siempre coincide con el bit-ness" se aplica.
Cómo depurar mi servicio que se ejecuta en una estación de ventana no interactiva
Para depurar un servicio que se ejecute en una estación de ventana no interactiva, haga lo siguiente (solo se aplica si usa ntsd/windbg):
Agregue una clave al Registro en HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options. El nombre de esta clave debe ser el nombre del proceso (service.exe).
Cree un valor de REG_SZ denominado Debugger y establezca este valor en la ruta de acceso donde reside el depurador. Debe contener la ruta de acceso completa, no solo el nombre del depurador. El comando debe incluir la opción –server y un puerto o intervalo de puertos específicos en los que el depurador debe escuchar. Un ejemplo es c:\debuggers\ntsd.exe –server tcp:port=5500:5600 –g –G.
Conéctese al servidor del depurador ejecutando el depurador con una opción –remote. Un ejemplo es: windbg.exe –remote tcp:=localhost,port=55xx donde "xx" es un número comprendido entre 00 y 99 si usó un intervalo en el servidor.
¿AppVerifier detecta fugas? En Windows 7 y versiones posteriores, hay una opción de comprobación fugas que detectará cuándo un proceso pierde memoria. En sistemas operativos anteriores, AppVerifier no prueba la aplicación para la detección de fugas, pero busca otros problemas de memoria.
¿Qué pruebas se recomiendan para los problemas de seguridad?
- Montones
- Asas
- Bloqueos
- Pilas (solo para servicios y procesos importantes que pueden reducir la máquina)
Tenga en cuenta que ObsoleteAPICalls simplemente escupirá una advertencia para cada llamada que ve a una API que aparece como obsoleta o en desuso en MSDN. Debe decidir por caso si es importante que la aplicación cambie a las nuevas API. Algunas de las API son peligrosas y algunas simplemente se han reemplazado por una API más reciente con más opciones. Eche un vistazo a la sección "API peligrosas" de Escritura de código seguro, segunda adición para más.
Para las aplicaciones que necesitan ser muy confiables, como servicios y programas de servidor, también debe habilitar la comprobación Stacks. Esto comprueba si el tamaño de confirmación de la pila es adecuado al deshabilitar el crecimiento de la pila. Si la aplicación se cierra inmediatamente con un desbordamiento de pila, significa que la aplicación debe volver a compilarse con un tamaño de confirmación de pila mayor. Si es evaluador y encuentra un problema con una aplicación mientras usa la comprobación Stacks, registre un error, asígnelo al desarrollador y siga probando.
Preguntas específicas de prueba
A continuación se muestra una lista de preguntas sobre las pruebas. Haga clic en la pregunta para ver la respuesta:
¿Son importantes las fugas de secciones críticas?
Cada vez que se pierde una sección crítica, se pierde lo siguiente: un identificador de eventos, una pequeña cantidad de grupo de kernel y una asignación de montón pequeña. Se limpiarán si se cierra el proceso.
Si su proceso se supone que permanece vivo mucho tiempo, estas fugas pueden morderte. Dado que las correcciones son muy fáciles en el 99 % de los casos (el desarrollador acaba de olvidar llamar a RtlDeleteCriticalSection) debe abordarlos.
¿Podemos tratar mediante programación con desbordamientos de pila?
No se garantiza el establecimiento de un controlador de excepciones en la función de subproceso inicial para detectar los posibles desbordamientos de pila que se pueden generar. Esto se debe a que el código que envía excepciones también necesita un poco de pila para ejecutarse encima del registro de activación actual. Dado que acabamos de producir un error en la extensión de pila, es muy probable que se supere el final de la pila confirmada y se genere una segunda excepción al intentar enviar la primera. Una excepción de error doble finalizará el proceso incondicionalmente.
La prueba loaderLock da un error al llamar a DestroyWindow. ¿Por qué no puedo llamar a DestroyWindow en DllMain? No controla qué subproceso se va a desasociar. Si no es el mismo subproceso que creó la ventana, no podrá destruir la ventana. Por lo tanto, se pierde la ventana y la próxima vez que la ventana recibe un mensaje, se bloquea porque el Wndproc se ha descargado.
Debe destruir la ventana antes de obtener el proceso de desasociación. El peligro no es que se descargará user32. El peligro es que se esté descargando. Por lo tanto, el siguiente mensaje que recibe la ventana bloqueará el proceso porque user32 entregará el mensaje al Wndproc que ya no existe.
El sistema operativo Microsoft Windows tiene afinidad de subproceso. La desasociación del proceso no. El bloqueo del cargador no es realmente el gran problema; el problema es Dllmain. El proceso de desasociación es la última vez que el archivo DLL obtiene para ejecutar código. Debes deshacerte de todo antes de regresar. Pero dado que Windows tiene afinidad de subproceso, no puede limpiar la ventana si está en el subproceso incorrecto.
El bloqueo del cargador entra en la imagen si alguien tiene instalado un enlace global (por ejemplo, spy++ está en ejecución). En este caso, escribirá un posible escenario de interbloqueo. De nuevo, la solución consiste en destruir la ventana antes de obtener el proceso de desasociación.
¿Es costoso aumentar las confirmaciones de pila iniciales para evitar desbordamientos?
Al confirmar la pila, simplemente está reservando espacio de archivos de página. No hay ningún impacto en el rendimiento. En realidad no se usa ninguna memoria física. El único costo adicional se produce si realmente toca el espacio de pila que ha confirmado. Pero esto ocurrirá de todos modos incluso si no confirma la pila por adelantado.
Veamos cuál sería el costo de hacer que todos los servicios que se ejecuten en svchost.exe a prueba de balas. En una máquina de prueba, obtengo 9 svchost.exe procesos que tienen un total de 139 subprocesos. Si establecemos la pila predeterminada para cada subproceso en 32K, necesitaremos aproximadamente 32 00 x 200 ~ 6,4 Mb de espacio de archivo de página para confirmar todas las pilas por adelantado.
Este es un precio bastante pequeño para pagar la confiabilidad.
¿Qué ocurre con el tamaño de pila reservada?
Hay elementos interesantes, como el envío de excepciones en IA64/AMD64 que requiere una pila adicional "inesperada". Puede haber algún procesamiento que se produzca en subprocesos de trabajo rpc cuyos requisitos de pila son intentos razonables de medirlos.
En primer lugar, debería hacerse una idea de todos los grupos de subprocesos que viven en el proceso. Nt-Thread-Pool, con los subprocesos alertable-wait-threads a veces es especial, porque, por ejemplo, si usa un componente de base de datos de SQL, usará suspensión de alertas sobre un subproceso que es un destino de user-APC. Esto puede causar problemas con llamadas anidadas.
Una vez que conozca todos los grupos de subprocesos, obtenga una idea de cómo controlar sus requisitos de pila. Por ejemplo, RPC lee una clave del Registro para la confirmación de la pila. Los subprocesos de bomba WDM obtienen eso de la imagen. Para otros grupos de subprocesos, el kilometraje puede variar.
Cuando todos los subprocesos están claros, puede realizar alguna acción. No tener un espacio reservado enorme ayuda a abordar la fragmentación del espacio solo si los subprocesos vienen y van muy a menudo. Si tiene un grupo de subprocesos estable que se encuentra en el control, es posible que también tenga una ventaja para reducir el espacio reservado. Realmente le ayudará a ahorrar espacio de direcciones para los montones y el espacio de direcciones para los usuarios.
¿Hay recomendaciones sobre cómo elegir el tamaño adecuado para LINKER_STACKCOMMITSIZE=?
El valor debe ser divisible por el tamaño de página (4k/8k dependiendo de la CPU). Estas son algunas instrucciones para determinar el tamaño que necesita hacer:
Convierta las funciones recursivas con una profundidad potencial sin enlazar (o al menos la profundidad alta inducible del usuario) a iterativa.
Reduzca el uso de alloca. Use montón o safealloca.
Ejecute Prefast con comprobación de tamaño de pila reducida (por ejemplo, 8k). Corrija esas funciones marcadas como el uso de demasiada pila.
Establezca la confirmación de pila en 16 000.
Ejecute en un montón de pruebas del depurador con la comprobación "Pilas" del comprobador de aplicaciones.
Cuando vea desbordamiento de pila, determine los peores delincuentes y los corrija. (Consulte el paso 5).
Cuando no se puede reducir el uso de la pila más de 8k. Si tiene > un error de 64 k, vuelva a disminuir a 64 k y vea el paso 6. De lo contrario, vaya al paso 5.
¿Cuáles son los requisitos de memoria para la prueba del montón?
Para las pruebas completas del montón, necesitará 256 MB de RAM y al menos un archivo de página de 1 GB. Para las pruebas de montón normales, necesitará al menos 128 MB de RAM. No hay requisitos específicos de procesador o disco.
¿Por qué recibo una parada de ALL_ACCESS?
Cualquier aplicación que use _ALL_ACCESS represente el objeto al que está accediendo de forma no auditable porque el registro de auditoría no reflejará lo que realmente ha hecho con el objeto, solo lo que se le pide que haga con el objeto .
Esta condición crea una camuflaje para un ataque más desviado. Un administrador que examina una actividad de ataque en curso no verá nada incorrecto con la persona que solicita ALL_ACCESS en la clave X, ya que una aplicación determinada siempre lo hace. El administrador pensará que "la persona probablemente está ejecutando Word". El administrador no puede decir que un hacker ha penetrado mi cuenta y ahora está sondeando el sistema para determinar qué acceso tengo, que puede aprovechar para sus fines nefariosos. Las posibilidades son infinitas.
El problema de ACL con ALL_ACCESS es que siempre debe concederlo. Si queríamos denegar algún día el acceso DELETE a una determinada clave, no podríamos hacerlo. Aunque realmente no estaba eliminando la clave, se interrumpiría la aplicación porque solicitaría el acceso de eliminación.
¿Por qué no obtengo ningún registro del montón y las pruebas de bloqueo?
Esas pruebas son capas de verificación integradas en el sistema operativo (y no en el paquete) y notifican errores en un depurador. Si ejecuta una aplicación con esas pruebas habilitadas y no tiene bloqueos, no notifica ningún problema.
Si se produce un bloqueo, será necesario ejecutarse en un depurador o pasar la aplicación a un desarrollador para probar más detenidamente.
¿Por qué la inyección de errores no funciona?
La probabilidad de inyección de errores se cambió a partes por millón en compilaciones de AppVerifier publicadas después de febrero de 2007 en función de los comentarios de los clientes. Por lo tanto, una probabilidad de 0n20000 es del 2 %, 0n500000 es del 50 % y así sucesivamente.
!avrf –flt debugger extensión se puede usar para cambiar la probabilidad sobre la marcha en el depurador. Sin embargo, la comprobación de simulación de recursos bajos para el proceso debe estar activada para que funcione.
La extensión del depurador !avrf forma parte exts.dll que se incluye con el paquete del depurador. Los cambios en !avrf que admiten el cambio de probabilidad se encuentran en el paquete del depurador más reciente. Si tiene problemas con la inyección de errores, actualice los depuradores y el paquete AppVerifier.
¿Por qué el comprobador de fugas no notifica ciertas pérdidas de recursos?
El comprobador de fugas no notifica pérdidas de recursos mientras se carga un módulo DLL o EXE. Cuando se descarga un módulo, el comprobador de fuga emite una detención si no se ha liberado alguno de los recursos asignados por el módulo.
Para inspeccionar los recursos asignados por un archivo DLL cargado o EXE, use la extensión !avrf -leak debugger.
Consulte también
Comprobador de aplicaciones - Información general
Comprobador de aplicaciones - Características
Comprobador de aplicaciones - Pruebas de aplicaciones
Comprobador de aplicaciones - Pruebas dentro del comprobador de aplicaciones
Comprobador de aplicaciones - Códigos de detención y definiciones
Comprobador de aplicaciones - Depuración de las detenciones del comprobador de aplicaciones