Skip to content

fix: report the rate of the current run on a resumed session - #1120

Open
qianeric-backup wants to merge 1 commit into
vanhauser-thc:masterfrom
qianeric-backup:fix/restore-eta
Open

qianeric-backup wants to merge 1 commit into
vanhauser-thc:masterfrom
qianeric-backup:fix/restore-eta

Conversation

@qianeric-backup

Copy link
Copy Markdown

What this fixes

hydra_brains.sent is cumulative and is loaded straight from the restore file, so a resumed
session starts with the try count of the previous run already in it. The status line then divides
that total by the elapsed time of the current run:

(1.0 * hydra_brains.sent) / (((elapsed_status - starttime) * 1.0) / 60)

Resuming a session that had done ~9000 tries and had been running for a minute reports
10166.00 tries/min and an ETA of 01:38h, instead of the actual ~634 tries/min and ~26:17h.
The reported rate only converges once the old tries are diluted by enough new ones, which is why
the issue describes it as "with time due to averaging it does converge".

Fixes #824.

The change

Record the value read from the restore file in restore_sent_base, and derive the rate from the
tries completed since starttime:

tries_session = hydra_brains.sent > restore_sent_base ? hydra_brains.sent - restore_sent_base : 0;
tries_per_sec = (double)tries_session / (double)elapsed_secs;

The cumulative count is still what the tries in field prints, so the running total and the
to do count are unchanged. Only tries/min and the ETA are affected. When no restore file is
used, restore_sent_base stays 0 and the arithmetic is identical to before.

The ETA expression is also no longer a division by zero when no pair has completed yet. The old
code divided by sent / elapsed, which is 0 at that point, and converting the resulting
infinity to uint64_t is undefined behaviour.

The reworked block also replaces the two duplicated ETA sub-expressions with eta_secs, so the
hours and minutes fields can no longer drift apart.

Verification

The -R code path currently crashes on main (Received signal 11 right after
[VERBOSE] resolving done), and an unmodified build crashes the same way on the same restore
file, so this was verified by driving the two builds into the same state the restore path
produces rather than through a real -R:

  • Both builds run a normal attack against a local server that answers 401 to every request,
    with hydra_brains.sent pre-set to 5000 (what a restored session looks like after a
    previous run of 5000 tries) and a 200000-entry password list.
  • Before: [STATUS] 103700.00 tries/min, 5185 tries in 00:00h, 194815 to do in 00:02h
  • After: [STATUS] 3240.00 tries/min, 5162 tries in 00:00h, 194838 to do in 01:01h

3240/min is the actual rate the run achieved (162 tries in 3 seconds); 103700/min is the 5000
inherited tries divided by those same 3 seconds. The tries and to do fields stay consistent
between the two builds, as intended.

For the no-restore case both builds produce the same output (second status line identical in both:
4593.33 tries/min, 689 tries in 00:00h, 199311 to do in 00:44h).

Built and run on Linux x86_64, gcc 13.3.0, openssl 3, against a local test server only.

Note on the crash

I did not touch it here, since it is a separate defect, but hydra -R segfaults on current main
after reading any restore file produced by this build. Happy to look at it in a follow-up if that
is useful — it is what made an end-to-end test of this change impossible.

hydra_brains.sent is cumulative: hydra_restore_read() loads it straight from
the restore file, so a resumed session starts with the try count of the
previous run already in it. The status line then divides that total by the
elapsed time of the current run, which reports a rate far above the real
one. Resuming a session that had done 9000 tries and had been running for a
minute reports ~10166 tries/min instead of the actual ~634.

Record the value read from the restore file in restore_sent_base and derive
the rate from the tries completed since starttime. The cumulative count is
still what is printed in the "tries in" field, so the total is unchanged;
only tries/min and the ETA are affected. When no restore file is used the
base stays 0 and the output is bit-for-bit what it was before.

The ETA now also avoids a division by zero when no pair has been completed
yet, which previously produced an undefined conversion from inf to uint64_t.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The zero-throughput guard reports a misleading one-minute ETA for resumed runs with substantial work remaining instead of showing the ETA as unavailable until throughput is measurable.

1 open issue
What changed in this PR

Updates Hydra’s progress reporting to use the current run’s attempt count when calculating throughput and ETA after a restore, addressing issue #824.

Changes:

  • Records the restored attempt count as a baseline for session-rate calculations.
  • Preserves cumulative attempt and remaining-work counts.
  • Consolidates ETA calculation and guards against division by zero.
File Description
hydra.c Tracks the restore baseline and updates status-line rate and ETA calculations.

Review effort: Balanced

Comment thread hydra.c
if (hydra_heads[j]->active >= HEAD_UNUSED)
k++;
todo_left = (hydra_brains.todo_all + total_redo_count) - hydra_brains.sent;
eta_secs = tries_per_sec > 0 ? (double)todo_left / tries_per_sec : 0;
@vanhauser-thc

Copy link
Copy Markdown
Owner

@qianeric-backup please have a look at the issues copilot found

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] When resuming a session, finished tries count towards new session tries - messing up ETA

3 participants