authfinder 1.0.1__py3-none-any.whl → 1.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
authfinder/__init__.py CHANGED
@@ -1,3 +1,3 @@
1
- """authfinder: Execute commands across Windows systems using multiple RCE methods"""
1
+ """authfinder: Execute commands across Windows and Linux systems using multiple RCE methods"""
2
2
 
3
- __version__ = "1.0.1"
3
+ __version__ = "1.1.0"
authfinder/authfinder.py CHANGED
@@ -19,6 +19,7 @@ OUTPUT = False
19
19
  RUN_ALL = False
20
20
  SKIP_PORTSCAN = False
21
21
  TOOLS_SPECIFIED = False
22
+ LINUX_MODE = False
22
23
 
23
24
  VALID_TOOLS = ["winrm", "smbexec", "wmi", "ssh", "mssql", "psexec", "atexec", "rdp"]
24
25
  NXC_TOOLS = {"smbexec", "wmi", "ssh", "rdp"}
@@ -235,6 +236,9 @@ def build_cmd(tool, user, target, credential, command):
235
236
  f"{NXC_CMD} wmi {target} -p {credential} -u \"{user}\" -x 'powershell -enc {b64}'")
236
237
 
237
238
  if tool == "ssh":
239
+ if LINUX_MODE:
240
+ b64 = base64.b64encode(command.encode("utf-8")).decode()
241
+ return f"{NXC_CMD} ssh {target} -p {credential} -u \"{user}\" -x 'echo {b64} | base64 -d | $0'{nxc_output_flag}"
238
242
  return f"{NXC_CMD} ssh {target} -p {credential} -u \"{user}\" -x 'powershell -enc {b64}'{nxc_output_flag}"
239
243
 
240
244
  if tool == "rdp":
@@ -327,6 +331,10 @@ def run_chain(user, ip, credential, command, tool_list=None):
327
331
  else:
328
332
  safe_print(f" [-] For {ip}: {tool} failed.")
329
333
  continue
334
+ if tool == "ssh" and 'Linux - Shell' in out and not LINUX_MODE:
335
+ safe_print(f" \033[33m[!]\033[0m For {ip}: {tool} AUTHENTICATION succeeded as {user} with {credential}, but this seems like a Linux machine, so the command didn't run.")
336
+ safe_print(" \033[33m[!]\033[0m Use \033[33m--linux\033[0m to run command across Linux machines.")
337
+ continue
330
338
  if '[+]' in out and 'Executed command' not in out:
331
339
  safe_print(f" \033[33m[!]\033[0m For {ip}: {tool} AUTHENTICATION succeeded as {user} with {credential}, but seemingly failed to run command. Does the user have the necessary permissions?")
332
340
  continue
@@ -410,6 +418,8 @@ def parse_args():
410
418
  parser.add_argument("--skip-portscan", action="store_true", help="Skip port scanning and attempt all tools")
411
419
  parser.add_argument("-f", "--file", metavar="CRED_FILE", help="Credential file (newline-separated user/password pairs)")
412
420
 
421
+ parser.add_argument("--linux", action="store_true", help="Linux-only mode - automates SSH, ignores other tools")
422
+
413
423
  parser.add_argument("ip_range", help="IP range (e.g., 192.168.1.1-254)")
414
424
  parser.add_argument("username", nargs="?", help="Username")
415
425
  parser.add_argument("credential", nargs="?", help="Password or NT hash")
@@ -438,7 +448,7 @@ def check_dependencies():
438
448
  IMPACKET_PREFIX = "impacket-"
439
449
  elif r2:
440
450
  IMPACKET_PREFIX = ""
441
- else:
451
+ elif not LINUX_MODE:
442
452
  print("[-] impacket not found. Install with: pipx install impacket")
443
453
  sys.exit(1)
444
454
 
@@ -465,7 +475,7 @@ def check_dependencies():
465
475
  for d in os.listdir(base):
466
476
  if d.endswith("@evil-winrm"):
467
477
  WINRM_CMD = f"{base}/{d}/wrappers/evil-winrm"
468
- if not WINRM_CMD:
478
+ if not WINRM_CMD and not LINUX_MODE:
469
479
  print("[-] evil-winrm not found. Please install with gem install evil-winrm")
470
480
  sys.exit(1)
471
481
 
@@ -476,7 +486,7 @@ def impacket_cmd(tool):
476
486
  return f"{tool}.py"
477
487
 
478
488
  def main():
479
- global VERBOSE, OUTPUT, MAX_THREADS, EXEC_TIMEOUT, RUN_ALL, SKIP_PORTSCAN, TOOLS_SPECIFIED
489
+ global VERBOSE, OUTPUT, MAX_THREADS, EXEC_TIMEOUT, RUN_ALL, SKIP_PORTSCAN, TOOLS_SPECIFIED, LINUX_MODE
480
490
 
481
491
  check_dependencies()
482
492
 
@@ -484,28 +494,17 @@ def main():
484
494
 
485
495
  VERBOSE = args.v
486
496
  OUTPUT = args.o
487
- MAX_THREADS = args.threads
497
+ MAX_THREADS = args.threads if args.threads > 0 else 1
488
498
  EXEC_TIMEOUT = args.timeout
489
499
  RUN_ALL = args.run_all
490
500
  SKIP_PORTSCAN = args.skip_portscan
491
-
492
- if args.tools:
493
- tool_list = parse_tools_list(args.tools)
494
- TOOLS_SPECIFIED = True
495
- print(f"[*] Using tools: {', '.join(tool_list)}")
496
- else:
497
- tool_list = None
498
-
499
- if args.skip_portscan:
500
- print("\033[33m[!] Port scanning disabled (--skip-portscan). All tools will be attempted.\033[0m")
501
-
502
- command = " ".join(args.command) if args.command else "whoami"
501
+ LINUX_MODE = args.linux
503
502
 
504
503
  if args.file:
505
504
  credential_list = load_credential_file(args.file)
506
505
  else:
507
506
  credential_list = [(args.username, args.credential)]
508
-
507
+
509
508
  if args.ip_range.endswith('.txt'):
510
509
  ips = []
511
510
  with open(args.ip_range) as f:
@@ -516,12 +515,32 @@ def main():
516
515
  else:
517
516
  ips = parse_ip_range(args.ip_range)
518
517
 
518
+ if len(ips) < MAX_THREADS:
519
+ MAX_THREADS = len(ips)
520
+
519
521
  print(f"[*] Loaded {len(credential_list)} credential set(s)")
520
522
  print(f"[*] Processing {len(ips)} IPs with {MAX_THREADS} threads...")
523
+
524
+ if args.linux:
525
+ if args.tools:
526
+ print("\033[31m[!] Tools (--tools) cannot be specified alongside Linux-mode (--linux), as only SSH is supported. Continuing with SSH...\033[0m")
527
+ args.tools = "ssh"
528
+
529
+ if args.tools:
530
+ tool_list = parse_tools_list(args.tools)
531
+ TOOLS_SPECIFIED = True
532
+ print(f"[*] Using tools: {', '.join(tool_list)}")
533
+ else:
534
+ tool_list = None
535
+
536
+ if args.skip_portscan:
537
+ print("\033[33m[!] Port scanning disabled (--skip-portscan). All tools will be attempted.\033[0m")
538
+
539
+ command = " ".join(args.command) if args.command else "whoami"
521
540
 
522
541
  if not OUTPUT:
523
542
  print("\033[33m[!] Output Disabled. Run with -o to see successful command output\033[0m")
524
- else:
543
+ elif not LINUX_MODE:
525
544
  print("-" * 20)
526
545
  print("\033[33m[!] WARNING: Output Enabled. This WILL trip AV for certain tools\033[0m")
527
546
  print("-" * 20)
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: authfinder
3
- Version: 1.0.1
4
- Summary: Execute commands across Windows systems using multiple RCE methods (WinRM, SMB, WMI, RDP, SSH, MSSQL)
3
+ Version: 1.1.0
4
+ Summary: Execute commands across Windows and Linux systems using multiple RCE methods (WinRM, SMB, WMI, RDP, SSH, MSSQL)
5
5
  Author: Khael
6
6
  Project-URL: Homepage, https://github.com/KhaelK138/authfinder
7
7
  Project-URL: Repository, https://github.com/KhaelK138/authfinder
@@ -28,7 +28,7 @@ Dynamic: license-file
28
28
 
29
29
  # AuthFinder
30
30
 
31
- A tool for executing commands across multiple Windows systems using various remote execution methods. Automatically tries multiple techniques until one succeeds, based on return codes and output. Makes executing commands given credentials a hell of a lot easier.
31
+ A tool for executing commands across Windows (and Linux) systems using various remote execution methods. Automatically tries multiple techniques until one succeeds, based on return codes and output. Makes executing commands given credentials a hell of a lot easier.
32
32
 
33
33
  Big thanks to NetExec, Impacket, and Evil-Winrm, as this tool just essentially acts as a wrapper around those (making it more of a script, I suppose).
34
34
 
@@ -45,6 +45,7 @@ Big thanks to NetExec, Impacket, and Evil-Winrm, as this tool just essentially a
45
45
  - MSSQL (Impacket)
46
46
  - **Multi-threaded**: Execute commands across multiple hosts simultaneously
47
47
  - **Automatic Pass-the-Hash**: Just paste the NTLM hash as the credential
48
+ - **Linux Support**: Use `--linux` to attempt to run commands across linux machines instead, via SSH
48
49
 
49
50
  ## Installation
50
51
 
@@ -118,6 +119,7 @@ Options:
118
119
  --timeout <seconds> Command timeout in seconds (default: 15)
119
120
  --run-all Run all tools instead of stopping at first success
120
121
  --skip-portscan Skip port scanning and attempt all tools
122
+ --linux Enables Linux-only mode, which uses SSH and ignores other tools
121
123
  ```
122
124
 
123
125
 
@@ -0,0 +1,8 @@
1
+ authfinder/__init__.py,sha256=VHsLEb_v1vOh7ztHlnIfTE5ADM0lXPqC9vK5Oac5wl8,121
2
+ authfinder/authfinder.py,sha256=-hPWugovB5v7q9vt-axjgEXx0AYFHL_3IFdCiqQmZVc,22654
3
+ authfinder-1.1.0.dist-info/licenses/LICENSE,sha256=Kw_kDNp7vsEauRb1Al1Urf1pe0EZWYB0HGK8PvT4FV0,1060
4
+ authfinder-1.1.0.dist-info/METADATA,sha256=2lh46fk3BvbTye3IF09bXpB86CyoX6Mmo1-SixwkPAw,4614
5
+ authfinder-1.1.0.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
6
+ authfinder-1.1.0.dist-info/entry_points.txt,sha256=9ChuQL6PNJlPHW_hSXvoFffcHCbpE0M8RHk8cz7yaIo,58
7
+ authfinder-1.1.0.dist-info/top_level.txt,sha256=tBEVwAMMMn0YcpoXt_lO1xiT-uznaCGrp7184swWocg,11
8
+ authfinder-1.1.0.dist-info/RECORD,,
@@ -1,8 +0,0 @@
1
- authfinder/__init__.py,sha256=c8p5Dp-gq4c7FFrY7J2y5z8safxiJeQxfYyRfhd0XOY,111
2
- authfinder/authfinder.py,sha256=7AiltrKyYMLdubdWfxtjthFQviIHhAnDWGA11nb5J9M,21471
3
- authfinder-1.0.1.dist-info/licenses/LICENSE,sha256=Kw_kDNp7vsEauRb1Al1Urf1pe0EZWYB0HGK8PvT4FV0,1060
4
- authfinder-1.0.1.dist-info/METADATA,sha256=iOuuyHEJLno_yhPIDkfezHQwpNmR-UYT9lph24P0RCY,4408
5
- authfinder-1.0.1.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
6
- authfinder-1.0.1.dist-info/entry_points.txt,sha256=9ChuQL6PNJlPHW_hSXvoFffcHCbpE0M8RHk8cz7yaIo,58
7
- authfinder-1.0.1.dist-info/top_level.txt,sha256=tBEVwAMMMn0YcpoXt_lO1xiT-uznaCGrp7184swWocg,11
8
- authfinder-1.0.1.dist-info/RECORD,,