This repository holds scripts relating to the paper "Time and Time Again: Leveraging TCP Timestamps to Improve Remote Timing Attacks" which was presented at NDSS 2026 in San Diego. This work has also been presented at Black Hat 2026 in Las Vegas as a briefing named "Time for ACKrobatics: Abusing TCP Timestamps to Improve Remote Timing Attacks".
If you use these tools in academic work, please cite the paper:
@inproceedings{timeandtimeagain2026,
title = {Time and Time Again: Leveraging TCP Timestamps to Improve Remote Timing Attacks},
author = {Vanderlinden, Vik and Van Goethem, Tom and Vanhoef, Mathy},
booktitle = {Network and Distributed System Security Symposium (NDSS)},
year = {2026},
}The scripts in this repo actively probe live hosts: they send hand-crafted TCP segments, sniff traffic, and open connections to the targets you supply. The authors provide these tools for research purposes only. It is your own responsibility to use these script responsibly, please do so.
The scripts were written using Python 3.12. Create a virtual environment and install the dependencies:
python -m venv venv
. ./venv/bin/activate
pip install -r requirements.txtThis installs scapy, tranco, requests, and pymongo.
- Root privileges.
tcpts.py,immack.py, andcollect_ts.pyuse raw sockets and/or packet capture and must be run as root (e.g. withsudo).
persistence.pyuses ordinary HTTP requests and does not require elevated privileges. tcpdumprequired for collection.
collect_ts.pyshells out totcpdumpto capture the target's response segments into a temporary pcap, so thetcpdumpbinary must be installed and on yourPATH.- Firewall modification.
tcpts.pybuilds its TCP conversation by hand, so it installs a temporaryiptablesrule on theOUTPUTchain that drops outgoingRSTsegments for its source port (otherwise the kernel resets connections it doesn't know about immediately). The script attempts to make sure this rule is removed automatically on exit, but there is no guarantee that this will always work in a watertight way.
Running it therefore modifies your local firewall for the duration of the scan. Check your firewall after testing to revert potential lingering changes. - IPv4 only.
All scripts are IPv4-only by design: targets are resolved to an IPv4 address, the raw-socket tools useAF_INETsockets, andtcpts.py's RST-drop rule relies on IPv4iptables.
In order to scan a site or IP address/range for preconditions of the attack, the scripts in ./susceptibility are provided.
tcpts.py- whether the target supports TCP timestamps, includes graceful shutdown of the connection usingFINsegmentsimmack.py- whether the target sends back an immediate acknowledgment after receiving the request rather than waiting until the response is sentpersistence.py- whether the target supports a persistent connection (responding withoutConnection: closeon HTTP/1.1, or with an explicitConnection: keep-aliveon HTTP/1.0)
The ./collection/collect_ts.py script is provided to gather timestamp values from the target.
It opens an ordinary TCP connection and pipelines a burst of requests to elicit many timestamped response segments.
A tcpdump capture is started first and the captured TCP timestamp options are written to the output file.
The susceptibility scripts emit one JSON record per target, with the following fields:
| Field | Description |
|---|---|
host |
The target host (domain or IP). |
port |
The probed port. |
result |
The result: a boolean for a definitive answer, or an "error: …" string when the probe failed. |
error |
true when result is an error string, false otherwise. |
time |
UNIX timestamp of when the record was produced. |
Results can be written either to a JSON file (-o/--output) as a single array of result records, or to a MongoDB collection (--db <connection-string> --collection <collection-name>), in which case each record is inserted as its own document.
The two outputs contain exactly the same data; If a database write fails, the records are written to <collection-name>.json as a fallback.
This project is licensed under the GNU General Public License v3.0. See the LICENSE file for details.