¿Cómo sabes que funcionó?
Con cualquier otra herramienta de este tipo, no lo sabes. La aplicación arranca, muestra una fecha y tú das por hecho que está bien. Pero puede leer el reloj por una vía que nada interceptó - y entonces «la prueba pasó» no significa nada.
El fallo que no tiene síntoma
Una herramienta de desplazamiento del tiempo que se deja un canal no se cuelga ni avisa. La aplicación simplemente lee la fecha real por la única función que nadie interceptó, y se comporta exactamente como lo habría hecho en cualquier tarde normal. La prueba se pone en verde. El error se publica.
RunAsDate es honesto sobre esto en su propia documentación - dice que «no afectará a las aplicaciones que toman la fecha y hora actuales de otra fuente» - y luego te deja averiguar si la tuya es una de ellas. Esta herramienta trata esa misma frase como algo que medir.
Lo que una sesión informa en realidad
Salida real, de ejecutar la herramienta contra una de las sondas de prueba de este proyecto - una que abre deliberadamente una conexión de red:
$ chrono run "...\pnet-x64.exe" --at 2038-01-19T03:14:07 --report session.txt Chrono Mock - session report target: C:\ChronoMock\tools\probes\bin\pnet-x64.exe verdict: WORKS - time substitution took effect (processes: 1) every process that read time saw the session clock session: fake clock reached 2038-01-19T03:14:10 real elapsed 3.4s, fake elapsed 3.4s exited: the target closed itself with code 0 covered channels (substituted, with call counts, 4 calls in all): - pid 9152: GetSystemTimeAsFileTime (1 call) - pid 9152: NtQuerySystemTime (3 calls) ... every other channel, including the ones never called observed channels (hooked but left real): - pid 9152: NtCreateUserProcess (0 calls) - pid 9152: connect (1 call) warnings: - the target opened a network connection - it may read time from a server, which no local hook can cover (source.network_at_start) requested: 2038-01-19T03:14:07 (zone +02:00 (host default), mode flow)
Los dos últimos bloques son lo importante. Aquí nada falló - el veredicto es funciona - y el informe dice aun así, sin que se lo pidan, que esta aplicación habló con la red antes de terminar, de modo que un hook local puede no ser toda la historia. Esa frase es la diferencia entre una prueba en la que puedes confiar y una en la que no.
Cuatro veredictos, y un código de salida para cada uno
El veredicto se alcanza desde dentro del proceso en ejecución, antes de que empieces a trabajar, y es el propio código de salida de la herramienta, de modo que un pipeline puede bifurcar según él.
| Veredicto | Salida | Significado |
|---|---|---|
| funciona | 0 | todo proceso que leyó la hora vio el reloj de la sesión |
| funciona parcialmente | 10 | algunos canales cubiertos, otros no - los no cubiertos se enumeran |
| no funciona | 11 | la sustitución no llegó a los canales clave |
| indeterminado | 4 | no se pudo establecer la cobertura - un «no lo sé» honesto |
Cuando el veredicto es «no funciona», el proceso se detiene de inmediato, antes de que puedas interactuar con él. El veredicto no puede preceder al lanzamiento, porque la única fuente de verdad es una lectura tomada desde dentro del proceso en ejecución. Lo que se garantiza es que conoces la verdad antes de empezar a trabajar - no que un lanzamiento condenado nunca ocurra. Puedes forzar y seguir adelante, y la sesión queda entonces marcada como no fiable en todos los sitios donde aparece, incluida cualquier evidencia que exportes.
Otros códigos dicen que falló la propia ejecución y no la sustitución - un error de uso, un objetivo que no se pudo iniciar, una ejecución cortada, otra sesión ya en marcha - y ninguno es un veredicto. La tabla completa está en la referencia de la línea de comandos.
Cubiertos, observados, sin cubrir
Los canales se dividen en tres grupos, y el del medio es el interesante.
- Cubiertos - interceptados y sustituidos. La aplicación preguntó y recibió el reloj de la sesión. El recuento de llamadas dice cuántas veces.
- Observados - interceptados, contados y dejados a propósito diciendo la verdad. Aquí están las esperas sobre objetos, porque acortar su tiempo límite podría simular un tiempo agotado en un handle real, y el temporizador multimedia, porque escalarlo desplazaría el audio y el MIDI - ambos vigilados cuando la sesión escala el eje del tiempo transcurrido. Las conexiones de red y una vía de creación de procesos están aquí en cada sesión, porque son pruebas, no relojes. El contador de alta resolución no está en este grupo: se deja intacto salvo que lo pidas con
--scale-qpc, y entonces queda cubierto. - Sin cubrir - un canal que la aplicación leyó y al que la sustitución no llegó. Es lo que convierte un veredicto en funciona parcialmente, y se enumera por su nombre en lugar de resumirse.
Un recuento de cero también es información: el canal estaba interceptado y la aplicación nunca preguntó. Por eso el informe los enumera en lugar de ocultarlos.
Lo que la auditoría no puede ver
El informe es honesto sobre la cobertura, lo que implica ser honesto sobre sus propios límites. Esto se lee sin ninguna llamada de función que interceptar, o por completo fuera del proceso:
- lecturas directas de la página de datos compartida en modo usuario - el valor está en memoria, así que no hay nada que interceptar. Raro en aplicaciones corrientes, común en el código de licencias y antimanipulación
- llamadas directas al sistema que se saltan las exportaciones estándar - el mismo patrón
- hora obtenida fuera del proceso, mediante WMI, un servidor COM fuera de proceso o RPC
- hora de la red - una cabecera HTTP
Date, NTP, una respuesta de API o el propio reloj de un servidor de base de datos - hora procedente de controladores del kernel
El caso de la red es el que la auditoría al menos puede notar, que es por lo que existe el aviso del informe de arriba. Para el resto, un veredicto funciona significa que se cubrieron los canales que esta herramienta puede ver - no que no exista ninguna otra vía.
En un pipeline
--json emite los mismos hechos en formato para máquinas, --report escribe
la versión para personas en un archivo, y una sesión cuyo veredicto sea cualquier cosa menos
funciona abre ese archivo con un aviso de evidencia poco fiable en lugar de enterrarlo
al final.
chrono run "C:\apps\test.exe" --at 2027-12-31T23:59:59 --json --report evidence.txt