De unde știi că a funcționat?
Cu orice alt instrument de acest fel, nu știi. Aplicația pornește, afișează o dată oarecare și presupui. Dar ea poate citi ceasul pe o cale pe care nimic nu a interceptat-o - și atunci „testul a trecut” nu înseamnă absolut nimic.
Eșecul care nu are niciun simptom
Un instrument de mutare a timpului care ratează un canal nu se blochează și nu avertizează. Aplicația citește pur și simplu data reală prin singura funcție pe care nimeni nu a interceptat-o și se comportă exact cum s-ar fi comportat în orice după-amiază obișnuită. Testul devine verde. Bug-ul ajunge în producție.
RunAsDate este onest în privința asta în propria documentație - spune că „nu va afecta aplicațiile care iau data/ora curentă dintr-o altă sursă” - și apoi te lasă să afli singur dacă a ta este una dintre ele. Acest instrument tratează aceeași propoziție ca pe ceva de măsurat.
Ce raportează de fapt o sesiune
Ieșire reală, din rularea instrumentului pe una dintre sondele de test ale acestui proiect - una care deschide în mod deliberat o conexiune de rețea:
$ 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)
Ultimele două blocuri sunt miezul. Nimic nu a eșuat aici - verdictul este funcționează - iar raportul spune totuși, nesolicitat, că această aplicație a comunicat cu rețeaua înainte să termine, deci un hook local poate să nu fie toată povestea. Acea propoziție este diferența dintre un test în care poți avea încredere și unul în care nu poți.
Patru verdicte și un cod de ieșire pentru fiecare
Verdictul se stabilește din interiorul procesului aflat în execuție, înainte să începi să lucrezi, și este chiar codul de ieșire al instrumentului, ca un pipeline să poată ramifica după el.
| Verdict | Ieșire | Semnificație |
|---|---|---|
| funcționează | 0 | fiecare proces care a citit ora a văzut ceasul sesiunii |
| funcționează parțial | 10 | unele canale acoperite, altele nu - cele neacoperite sunt enumerate |
| nu funcționează | 11 | înlocuirea nu a ajuns la canalele cheie |
| nedeterminat | 4 | acoperirea nu a putut fi stabilită - un „nu știu” onest |
Când verdictul este „nu funcționează”, procesul este oprit imediat, înainte să poți interacționa cu el. Verdictul nu poate precede lansarea, pentru că singura sursă de adevăr este o citire făcută din interiorul procesului aflat în execuție. Ce este garantat este că afli adevărul înainte să începi să lucrezi - nu că o lansare condamnată nu are loc niciodată. Poți forța și continua, iar sesiunea este apoi marcată ca nesigură peste tot unde apare, inclusiv în orice dovezi exportezi.
Alte coduri spun că a eșuat rularea însăși, nu substituția - o eroare de utilizare, o țintă care nu a putut porni, o rulare întreruptă, o altă sesiune deja pornită - și niciunul nu este un verdict. Tabelul complet este în referința liniei de comandă.
Acoperite, observate, neacoperite
Canalele se împart în trei categorii, iar cea din mijloc este cea interesantă.
- Acoperite - interceptate și înlocuite. Aplicația a întrebat și a primit ceasul sesiunii. Numărul de apeluri spune de câte ori.
- Observate - interceptate, numărate și lăsate intenționat să spună adevărul. Aici sunt așteptările pe obiecte, pentru că scurtarea limitei de timp ar putea simula o expirare pe un handle real, și timerul multimedia, pentru că scalarea lui ar deplasa sincronizarea audio și MIDI - ambele urmărite când sesiunea scalează axa timpului scurs. Conexiunile de rețea și o cale de creare a proceselor sunt aici în fiecare sesiune, pentru că sunt dovezi, nu ceasuri. Contorul de înaltă rezoluție nu este în acest grup: rămâne neatins până când îl ceri cu
--scale-qpc, iar atunci este acoperit. - Neacoperite - un canal pe care aplicația l-a citit și la care înlocuirea nu a ajuns. Asta transformă un verdict în funcționează parțial, iar canalul este enumerat pe nume, nu rezumat până dispare.
Un număr de zero este tot informație: canalul a fost interceptat, iar aplicația nu a întrebat niciodată. De aceea raportul le enumeră, în loc să le ascundă.
Ce nu poate vedea auditul
Raportul este onest în privința acoperirii, ceea ce înseamnă să fie onest și în privința propriilor margini. Acestea sunt citite fără niciun apel de funcție de interceptat sau în afara procesului cu totul:
- citiri directe ale paginii de date partajate din user-mode - valoarea stă în memorie, deci nu există nimic de interceptat. Rar în aplicațiile obișnuite, frecvent în codul de licențiere și anti-tamper
- apeluri sistem directe care ocolesc exporturile standard - același tipar
- ora obținută în afara procesului, prin WMI, un server COM din afara procesului sau RPC
- ora din rețea - un antet HTTP
Date, NTP, un răspuns de API sau ceasul propriu al unui server de baze de date - ora din drivere de kernel
Cazul rețelei este cel pe care auditul îl poate cel puțin observa, de aceea există avertismentul din raportul de mai sus. Pentru restul, un verdict funcționează înseamnă că au fost acoperite canalele pe care instrumentul le poate vedea - nu că nu există nicio altă cale.
Într-un pipeline
--json emite aceleași fapte în formă pentru mașini, --report scrie
versiunea pentru oameni într-un fișier, iar o sesiune al cărei verdict este altul decât
funcționează începe acel fișier cu un banner de dovezi nesigure, în loc să-l îngroape la
sfârșit.
chrono run "C:\apps\test.exe" --at 2027-12-31T23:59:59 --json --report evidence.txt