rlwrap, sshpass, ntpdate & faketime
Four tiny tools that aren’t the exploit but save you constant friction in AD and Linux boxes.
rlwrap — usable raw shells
Wrap a netcat listener so you get readline: arrow keys, command history, line editing in an otherwise dumb reverse shell.
# the standard listener for a Windows reverse shell
rlwrap -cAr nc -lnvp 443
# sudo when binding a low port
sudo rlwrap -cAr nc -lvnp 445
| Flag | Meaning |
|---|---|
-c | complete filenames (tab-completion) |
-A | force ANSI colour handling |
-r | put all seen words in the completion list |
[!tip]
rlwrap -cAr nc -lnvp <port>is the muscle-memory line Especially for Windowspowershell/cmdreverse shells where you can’t easily upgrade the TTY. For Linux targets you’ll usually still do thepython3 -c 'pty.spawn'+stty raw -echo; fgupgrade on top. See Foothold: shells & payloads.
sshpass — non-interactive SSH password
SSH/scp without the interactive password prompt — for scripting, loops, or when a password came from loot.
# ssh with an inline password
sshpass -p 'Passw0rd!' ssh user@10.10.10.5
# from a file (safer; keeps it out of ps/history)
sshpass -f pass.txt ssh user@10.10.10.5
# scp a tool over
sshpass -p 'Passw0rd!' scp ./GodPotato.exe user@10.10.10.5:/programdata/gp.exe
# trust a new lab host key on first connect; changed keys still fail
sshpass -p 'Passw0rd!' ssh -o StrictHostKeyChecking=accept-new user@10.10.10.5
| Flag | Meaning |
|---|---|
-p PASS | password inline (visible in ps — least safe) |
-f FILE | read password from a file |
-e | read password from $SSHPASS env var |
-d N | read from file descriptor N |
[!warning]
-pleaks intops/shell history On a shared/monitored box prefer-f fileor-e(SSHPASS=... sshpass -e ssh ...). sshpass also only works for password auth — it does not unlock a private-key passphrase or implement a general multi-factor login flow.
ntpdate / faketime — beat Kerberos clock skew
Kerberos rejects tickets when your clock differs from the DC by more than ~5 min (KRB_AP_ERR_SKEW). Fix it before any -k / ticket operation.
# sync your clock to the DC (simplest; needs root)
sudo ntpdate dc.domain.htb
sudo ntpdate 10.10.10.5
# can't/won't change system time? run just one command at the DC's time:
# Example only: use a measured offset, not a guessed timezone difference
faketime -f '+300s' getST.py 'domain.htb/user' -spn cifs/dc01.domain.htb
[!tip] When to reach for which
ntpdateis the default — one command, done. Usefaketimewhen you can’t change system time (shared VM, breaks other tooling) and only need one Kerberos command to run at the DC’s clock. Rare but handy when the DC’s time is deliberately offset.
[!warning] ntpdate side effects
ntpdateyanks your whole system clock to the DC’s — fine on a throwaway attack VM, annoying if you juggle several targets with different offsets (re-sync per box). First inspect your active time service. Enabling NTP only helps when the configured server provides the required time; it does not automatically synchronize against the target DC.
Check what each helper actually changes
# Display UTC and query the DC without changing the machine clock
date -u
ntpdate -q dc01.domain.htb
# Keep rlwrap's shell-command history out of the default persistent file
rlwrap -H /dev/null -cAr nc -lvnp 4444
# Avoid an inline SSH password; protect the password file locally
chmod 600 pass.txt
sshpass -f pass.txt ssh -o StrictHostKeyChecking=accept-new user@10.10.10.5
rlwrap provides local editing, not a remote PTY, job control or terminal resizing. A password file avoids exposing the password as a command argument, but the file remains a secret. accept-new is first-use trust; verify the fingerprint when you have an authoritative one.
Kerberos compares time instants, not displayed timezone names. Measure skew, inspect the ticket’s start/end times with klist, and check DNS/SPNs before blaming the clock. faketime changes the local process’s view of time; it neither changes the remote clock nor refreshes an expired ticket.
Success: editing works, SSH accepts the intended account, or the same Kerberos operation succeeds after a measured time correction. Record which dependency changed instead of treating a helper invocation as proof.
rlwrap completion is local, not remote
-c completes filenames on the listener machine. It does not enumerate the Windows/Linux target’s filesystem. -r remembers words seen in output for completion; it is not a remote command discovery mechanism. In this rlwrap build, -A enables ANSI-colour-aware prompt handling; it does not provide full terminal emulation.
# Avoid saving command history for this session
rlwrap -H /dev/null nc -lvnp 4444
If backspace prints escape sequences, check the remote shell and terminal handling separately. Full-screen editors, job control and Ctrl-C signal behaviour need a suitable remote PTY; adding more readline switches cannot supply one.
Feed sshpass through a descriptor
In Bash, prompt once and provide the password through a temporary descriptor:
read -r -s -p 'SSH password: ' lab_ssh_password
printf '\n'
sshpass -d 3 ssh -o StrictHostKeyChecking=yes labuser@host.example.test \
3< <(printf '%s\n' "$lab_ssh_password")
unset lab_ssh_password
This example assumes the host key is already known and verified. Process substitution is Bash syntax; use the earlier protected-file method on shells without it. A descriptor removes the password from the command argument list, while the process still handles a secret in memory.
| Exit/result | Next check |
|---|---|
| Password rejected | Correct account, authentication method and password |
| Unknown/changed host key | Verify the expected fingerprint and known-hosts entry |
| Hangs at another prompt | MFA, key passphrase or nonstandard prompt unsupported by the invocation |
| SSH works manually but automation fails | Which prompt sshpass is matching and actual SSH stderr |
Measure clock offset before correcting it
date -u '+%Y-%m-%dT%H:%M:%SZ'
timedatectl status
ntpdate -q dc01.example.test
klist
ntpdate -q queries without changing the clock. The server might not provide NTP, and UDP/123 may not cross a TCP-only pivot. Compare with an independently known DC UTC timestamp rather than guessing an offset from displayed local time.
Apply an offset to a process consistently
# Example measured correction: local clock is 90 seconds behind the DC
FAKETIME_DONT_FAKE_MONOTONIC=1 faketime -f '+90s' date -u
FAKETIME_DONT_FAKE_MONOTONIC=1 faketime -f '+90s' \
getTGT.py -dc-ip 192.0.2.10 'example.test/labuser'
Verify that the first command shows the intended UTC instant. Use the same measured correction when consuming the new ticket. Runtime/static-binary behaviour can bypass libfaketime; a changed date output does not guarantee every application uses that clock. See the libfaketime documentation for compatibility details.
If your system time service immediately undoes a manual adjustment, investigate its configured source. Restore the original time-service state after the lab; do not leave a workstation synchronising to an unrelated DC.
See Also
- Evil-WinRM · Impacket — the Kerberos tooling that needs the clock fixed.
- Foothold: shells & payloads — reverse-shell catching and TTY upgrades.
- File Transfers — moving tools onto the target (scp alternative methods).