exploitfarm 1.7.7__tar.gz → 1.7.8__tar.gz
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.
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/PKG-INFO +1 -2
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/__init__.py +1 -1
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/tui/startxploit.py +9 -2
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/utils/reqs.py +14 -3
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/xfarm.py +2 -2
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/xploit.py +32 -13
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm.egg-info/PKG-INFO +1 -2
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm.egg-info/requires.txt +0 -1
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/requirements.txt +0 -1
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/setup.py +1 -1
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/MANIFEST.in +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/README.md +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/__main__.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/_init_exposed.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/models/__init__.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/models/client.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/models/dbtypes.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/models/enums.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/models/exploit.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/models/exploit_template.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/models/flags.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/models/groups.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/models/response.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/models/service.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/models/submitter.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/models/teams.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/tui/__init__.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/tui/config.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/tui/exploitdownload.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/tui/exploitinit.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/tui/group_prejoin.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/tui/group_select.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/tui/login.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/tui/shared_attack_group.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/tui/template.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/utils/__init__.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/utils/cmd.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/utils/config.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/utils/exploit.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/utils/templates.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm/utils/windows_close_fix.py +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm.egg-info/SOURCES.txt +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm.egg-info/dependency_links.txt +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/exploitfarm.egg-info/top_level.txt +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/setup.cfg +0 -0
- {exploitfarm-1.7.7 → exploitfarm-1.7.8}/xfarm +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: exploitfarm
|
|
3
|
-
Version: 1.7.
|
|
3
|
+
Version: 1.7.8
|
|
4
4
|
Summary: Exploit Farm client
|
|
5
5
|
Home-page: https://github.com/pwnzer0tt1/exploitfarm
|
|
6
6
|
Author: Pwnzer0tt1
|
|
@@ -24,7 +24,6 @@ Requires-Dist: python-socketio[client]>=5.14.1
|
|
|
24
24
|
Requires-Dist: textual>=3.0.0
|
|
25
25
|
Requires-Dist: typer>=0.16
|
|
26
26
|
Requires-Dist: xfarm
|
|
27
|
-
Requires-Dist: orjson
|
|
28
27
|
Dynamic: author
|
|
29
28
|
Dynamic: author-email
|
|
30
29
|
Dynamic: classifier
|
|
@@ -155,8 +155,15 @@ class XploitRun(App[int]):
|
|
|
155
155
|
time_delta = last_execution_time = last_attack_status = None
|
|
156
156
|
executing = team_info.executing
|
|
157
157
|
if team_info.last:
|
|
158
|
-
|
|
159
|
-
|
|
158
|
+
if team_info.last.end_time:
|
|
159
|
+
time_delta = str(dt.now(datetime.timezone.utc) - team_info.last.end_time).split(".")[0]
|
|
160
|
+
last_execution_time = str(team_info.last.end_time - team_info.last.start_time).split(".")[0]
|
|
161
|
+
else:
|
|
162
|
+
time_delta = "N/A"
|
|
163
|
+
if team_info.last.start_time:
|
|
164
|
+
last_execution_time = str(dt.now(datetime.timezone.utc) - team_info.last.start_time).split(".")[0]
|
|
165
|
+
else:
|
|
166
|
+
last_execution_time = "N/A"
|
|
160
167
|
last_attack_status = team_info.last.status
|
|
161
168
|
|
|
162
169
|
match last_attack_status:
|
|
@@ -8,7 +8,7 @@ from uuid import UUID
|
|
|
8
8
|
from typing import Dict, Any
|
|
9
9
|
from exploitfarm.utils.config import ClientConfig, ExploitConfig
|
|
10
10
|
from exploitfarm.utils import ExploitFarmClientError
|
|
11
|
-
import
|
|
11
|
+
import json
|
|
12
12
|
from datetime import datetime as dt
|
|
13
13
|
from exploitfarm.models.enums import AttackMode, SetupStatus
|
|
14
14
|
from posixpath import join as urljoin
|
|
@@ -30,8 +30,19 @@ def get_url(path: str, config: ClientConfig | None = None) -> str:
|
|
|
30
30
|
return result
|
|
31
31
|
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
from enum import Enum
|
|
34
|
+
|
|
35
|
+
def _custom_serializer(obj):
|
|
36
|
+
if isinstance(obj, UUID):
|
|
37
|
+
return str(obj)
|
|
38
|
+
if isinstance(obj, dt):
|
|
39
|
+
return obj.isoformat()
|
|
40
|
+
if isinstance(obj, Enum):
|
|
41
|
+
return obj.value
|
|
42
|
+
raise TypeError(f"Object of type {obj.__class__.__name__} is not JSON serializable")
|
|
43
|
+
|
|
44
|
+
def jsonify(data: Any) -> Any:
|
|
45
|
+
return json.loads(json.dumps(data, default=_custom_serializer))
|
|
35
46
|
|
|
36
47
|
|
|
37
48
|
def get_session(auth: str | None | ClientConfig = None) -> requests.Session:
|
|
@@ -24,7 +24,7 @@ from exploitfarm.utils.config import (
|
|
|
24
24
|
)
|
|
25
25
|
import getpass
|
|
26
26
|
import re
|
|
27
|
-
import
|
|
27
|
+
import json
|
|
28
28
|
import sys
|
|
29
29
|
from pydantic import PositiveInt
|
|
30
30
|
from typing import Optional
|
|
@@ -640,7 +640,7 @@ def submitter_test(
|
|
|
640
640
|
):
|
|
641
641
|
initial_setup()
|
|
642
642
|
try:
|
|
643
|
-
kwargs =
|
|
643
|
+
kwargs = json.loads(kwargs)
|
|
644
644
|
except Exception as e:
|
|
645
645
|
print(f"[bold red]Invalid kwargs json: {e}")
|
|
646
646
|
close_cli()
|
|
@@ -8,7 +8,8 @@ And that's one of the reasons why this attacker/submitter is called "exploitfarm
|
|
|
8
8
|
import dateutil.parser
|
|
9
9
|
import os
|
|
10
10
|
import re
|
|
11
|
-
import
|
|
11
|
+
import json
|
|
12
|
+
import shlex
|
|
12
13
|
import math
|
|
13
14
|
import subprocess
|
|
14
15
|
import time
|
|
@@ -285,7 +286,7 @@ def once_in_a_period(period):
|
|
|
285
286
|
def repush_flags():
|
|
286
287
|
try:
|
|
287
288
|
with open(".flag_queue.json", "rt") as f:
|
|
288
|
-
old_queue_data =
|
|
289
|
+
old_queue_data = json.loads(f.read())
|
|
289
290
|
if old_queue_data["server_id"] != g.server_id:
|
|
290
291
|
raise Exception("Server ID mismatch")
|
|
291
292
|
for ele in old_queue_data["queue"]:
|
|
@@ -497,11 +498,16 @@ def read_and_print(stdout: io.BytesIO, buffer: io.BytesIO):
|
|
|
497
498
|
stdout.close()
|
|
498
499
|
|
|
499
500
|
|
|
501
|
+
_exploit_config_cache = {}
|
|
502
|
+
|
|
500
503
|
def get_or_download_exploit(exploit_id: str, commit_id: str) -> ExploitConfig:
|
|
501
504
|
# Construct the absolute path for the exploit cache
|
|
502
505
|
base_dir = os.path.expanduser(f"~/.exploitfarm/cache/{exploit_id}/{commit_id}")
|
|
503
506
|
|
|
504
507
|
with g.exploit_cache_lock:
|
|
508
|
+
if base_dir in _exploit_config_cache:
|
|
509
|
+
return _exploit_config_cache[base_dir]
|
|
510
|
+
|
|
505
511
|
# Check if the exploit configuration file exists in the cache
|
|
506
512
|
if not check_exploit_config_exists(base_dir):
|
|
507
513
|
# If the directory exists but is incomplete/corrupted, we might need to clear it,
|
|
@@ -514,7 +520,9 @@ def get_or_download_exploit(exploit_id: str, commit_id: str) -> ExploitConfig:
|
|
|
514
520
|
tar.extractall(base_dir)
|
|
515
521
|
tar.close()
|
|
516
522
|
|
|
517
|
-
|
|
523
|
+
config = ExploitConfig.read(base_dir)
|
|
524
|
+
_exploit_config_cache[base_dir] = config
|
|
525
|
+
return config
|
|
518
526
|
|
|
519
527
|
|
|
520
528
|
def launch_sploit(
|
|
@@ -532,7 +540,8 @@ def launch_sploit(
|
|
|
532
540
|
env = os.environ.copy()
|
|
533
541
|
env["PYTHONUNBUFFERED"] = "1"
|
|
534
542
|
env["XFARM_HOST"] = team["host"]
|
|
535
|
-
|
|
543
|
+
team_json = json.dumps(team)
|
|
544
|
+
env["XFARM_TEAM"] = team_json.decode() if isinstance(team_json, bytes) else team_json
|
|
536
545
|
env["XFARM_EXPLOIT_ID"] = str(config.uuid)
|
|
537
546
|
env["XFARM_REMOTE_URL"] = get_url_from_config("", g.exec.config)
|
|
538
547
|
if g.exec.config.server.auth_key:
|
|
@@ -540,32 +549,33 @@ def launch_sploit(
|
|
|
540
549
|
|
|
541
550
|
# Command to run the exploit
|
|
542
551
|
command = f"{config.interpreter} {config.run}".strip()
|
|
552
|
+
cmd_args = shlex.split(command)
|
|
543
553
|
need_close_fds = not os_windows
|
|
544
554
|
|
|
545
555
|
proc = None
|
|
546
556
|
if os_windows:
|
|
547
557
|
with g.ctrl_c_win.skip_ctrl_c_handling():
|
|
548
558
|
proc = subprocess.Popen(
|
|
549
|
-
|
|
559
|
+
cmd_args,
|
|
550
560
|
stdout=subprocess.PIPE,
|
|
551
561
|
stderr=subprocess.STDOUT,
|
|
552
562
|
close_fds=need_close_fds,
|
|
553
563
|
env=env,
|
|
554
564
|
cwd=config._ExploitConfig__folder,
|
|
555
|
-
shell=
|
|
565
|
+
shell=False,
|
|
556
566
|
)
|
|
557
567
|
nicenessify(pid=proc.pid)
|
|
558
568
|
else:
|
|
559
569
|
proc = subprocess.Popen(
|
|
560
|
-
|
|
570
|
+
cmd_args,
|
|
561
571
|
stdout=subprocess.PIPE,
|
|
562
572
|
stderr=subprocess.STDOUT,
|
|
563
573
|
close_fds=need_close_fds,
|
|
564
574
|
env=env,
|
|
565
575
|
cwd=config._ExploitConfig__folder,
|
|
566
|
-
shell=
|
|
567
|
-
preexec_fn=nicenessify,
|
|
576
|
+
shell=False,
|
|
568
577
|
)
|
|
578
|
+
nicenessify(pid=proc.pid)
|
|
569
579
|
|
|
570
580
|
read_function = None
|
|
571
581
|
if stream_output:
|
|
@@ -582,12 +592,21 @@ def launch_sploit(
|
|
|
582
592
|
return value
|
|
583
593
|
|
|
584
594
|
read_function = func
|
|
585
|
-
|
|
586
|
-
|
|
595
|
+
else:
|
|
596
|
+
pipe = proc.stdout
|
|
597
|
+
buffer = io.BytesIO()
|
|
598
|
+
|
|
599
|
+
def silent_read():
|
|
600
|
+
buffer.write(pipe.read())
|
|
601
|
+
|
|
602
|
+
thr = threading.Thread(target=silent_read)
|
|
603
|
+
thr.start()
|
|
587
604
|
|
|
588
605
|
def func():
|
|
589
|
-
|
|
606
|
+
thr.join()
|
|
590
607
|
proc.stdout.close()
|
|
608
|
+
value = buffer.getvalue()
|
|
609
|
+
buffer.close()
|
|
591
610
|
return value
|
|
592
611
|
|
|
593
612
|
read_function = func
|
|
@@ -1046,7 +1065,7 @@ def shutdown(restart: bool = False):
|
|
|
1046
1065
|
attacks = g.attack_storage.pick_attacks()
|
|
1047
1066
|
if attacks:
|
|
1048
1067
|
with open(".flag_queue.json", "wb") as f:
|
|
1049
|
-
f.write(
|
|
1068
|
+
f.write(json.dumps({"server_id": g.server_id, "queue": attacks}))
|
|
1050
1069
|
elif os.path.exists(".flag_queue.json"):
|
|
1051
1070
|
os.remove(".flag_queue.json")
|
|
1052
1071
|
except Exception:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: exploitfarm
|
|
3
|
-
Version: 1.7.
|
|
3
|
+
Version: 1.7.8
|
|
4
4
|
Summary: Exploit Farm client
|
|
5
5
|
Home-page: https://github.com/pwnzer0tt1/exploitfarm
|
|
6
6
|
Author: Pwnzer0tt1
|
|
@@ -24,7 +24,6 @@ Requires-Dist: python-socketio[client]>=5.14.1
|
|
|
24
24
|
Requires-Dist: textual>=3.0.0
|
|
25
25
|
Requires-Dist: typer>=0.16
|
|
26
26
|
Requires-Dist: xfarm
|
|
27
|
-
Requires-Dist: orjson
|
|
28
27
|
Dynamic: author
|
|
29
28
|
Dynamic: author-email
|
|
30
29
|
Dynamic: classifier
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|