exploitfarm 1.7.8__tar.gz → 2.0.0__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.8/exploitfarm.egg-info → exploitfarm-2.0.0}/PKG-INFO +116 -16
- exploitfarm-1.7.8/PKG-INFO → exploitfarm-2.0.0/README.md +106 -43
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/__init__.py +1 -1
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/_init_exposed.py +38 -28
- exploitfarm-2.0.0/exploitfarm/attack_storage.py +225 -0
- exploitfarm-2.0.0/exploitfarm/autotune.py +165 -0
- exploitfarm-2.0.0/exploitfarm/connection.py +252 -0
- exploitfarm-2.0.0/exploitfarm/core_orchestration.py +709 -0
- exploitfarm-2.0.0/exploitfarm/local_executor.py +940 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/models/enums.py +4 -2
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/models/exploit.py +6 -6
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/models/groups.py +8 -3
- exploitfarm-2.0.0/exploitfarm/team_provider.py +93 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/tui/config.py +1 -13
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/tui/exploitinit.py +13 -12
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/tui/group_prejoin.py +26 -7
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/tui/group_select.py +3 -3
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/tui/shared_attack_group.py +1 -1
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/tui/startxploit.py +184 -72
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/utils/__init__.py +59 -15
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/utils/config.py +22 -11
- exploitfarm-2.0.0/exploitfarm/utils/paths.py +69 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/utils/reqs.py +102 -12
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/utils/templates.py +2 -1
- exploitfarm-2.0.0/exploitfarm/utils/threadpool.py +90 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/xfarm.py +238 -74
- exploitfarm-2.0.0/exploitfarm/xploit.py +590 -0
- exploitfarm-1.7.8/README.md → exploitfarm-2.0.0/exploitfarm.egg-info/PKG-INFO +143 -7
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm.egg-info/SOURCES.txt +8 -0
- exploitfarm-2.0.0/exploitfarm.egg-info/requires.txt +15 -0
- exploitfarm-2.0.0/requirements.txt +16 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/setup.py +1 -1
- exploitfarm-1.7.8/exploitfarm/xploit.py +0 -1237
- exploitfarm-1.7.8/exploitfarm.egg-info/requires.txt +0 -14
- exploitfarm-1.7.8/requirements.txt +0 -14
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/MANIFEST.in +0 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/__main__.py +0 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/models/__init__.py +0 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/models/client.py +0 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/models/dbtypes.py +0 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/models/exploit_template.py +0 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/models/flags.py +0 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/models/response.py +0 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/models/service.py +0 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/models/submitter.py +0 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/models/teams.py +0 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/tui/__init__.py +0 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/tui/exploitdownload.py +0 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/tui/login.py +0 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/tui/template.py +0 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/utils/cmd.py +0 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/utils/exploit.py +0 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm/utils/windows_close_fix.py +0 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm.egg-info/dependency_links.txt +0 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/exploitfarm.egg-info/top_level.txt +0 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/setup.cfg +0 -0
- {exploitfarm-1.7.8 → exploitfarm-2.0.0}/xfarm +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: exploitfarm
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: Exploit Farm client
|
|
5
5
|
Home-page: https://github.com/pwnzer0tt1/exploitfarm
|
|
6
6
|
Author: Pwnzer0tt1
|
|
@@ -12,18 +12,19 @@ Requires-Python: >=3.10
|
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
Requires-Dist: requests>=2.32.5
|
|
14
14
|
Requires-Dist: urllib3>=2.5.0
|
|
15
|
-
Requires-Dist: python-dateutil
|
|
15
|
+
Requires-Dist: python-dateutil>=2.9.0.post0
|
|
16
16
|
Requires-Dist: pydantic>=2
|
|
17
17
|
Requires-Dist: typing-extensions>=4.7.1
|
|
18
|
-
Requires-Dist: fasteners
|
|
19
|
-
Requires-Dist: toml
|
|
20
|
-
Requires-Dist: psutil
|
|
21
|
-
Requires-Dist: dirhash
|
|
22
|
-
Requires-Dist: requests-toolbelt
|
|
23
|
-
Requires-Dist: python-socketio[
|
|
18
|
+
Requires-Dist: fasteners>=0.20
|
|
19
|
+
Requires-Dist: toml>=0.10.2
|
|
20
|
+
Requires-Dist: psutil>=7.2.2
|
|
21
|
+
Requires-Dist: dirhash>=0.5.0
|
|
22
|
+
Requires-Dist: requests-toolbelt>=1.0.0
|
|
23
|
+
Requires-Dist: python-socketio[asyncio_client]>=5.14.1
|
|
24
|
+
Requires-Dist: aiohttp>=3.9.0
|
|
24
25
|
Requires-Dist: textual>=3.0.0
|
|
25
26
|
Requires-Dist: typer>=0.16
|
|
26
|
-
Requires-Dist:
|
|
27
|
+
Requires-Dist: platformdirs>=4.0
|
|
27
28
|
Dynamic: author
|
|
28
29
|
Dynamic: author-email
|
|
29
30
|
Dynamic: classifier
|
|
@@ -202,6 +203,14 @@ xfarm start [OPTIONS] PATH
|
|
|
202
203
|
xfarm start ./my_exploit --pool-size 20 --test
|
|
203
204
|
```
|
|
204
205
|
|
|
206
|
+
### Exploit Execution Environment
|
|
207
|
+
|
|
208
|
+
To protect your exploit source code and maintain a clean workspace, exploits are never executed directly in their project directory. Instead, `xfarm` starts the execution by copying your exploit files into a temporary `__xfarm_run__` folder and runs the exploit from there. This guarantees:
|
|
209
|
+
- **Clean Execution**: Your original directory isn't polluted by runtime artifacts, logs, or temporary files generated by the exploit.
|
|
210
|
+
- **Isolation**: Changes made by the exploit script (e.g., dropping files, compiling binaries) remain isolated.
|
|
211
|
+
|
|
212
|
+
A Git-like ignores system is available: You can use a `.ignore` (only in the root of the exploit folder) to specify files/directories that shouldn't be copied into the `__xfarm_run__` directory and when using `xfarm push`.
|
|
213
|
+
|
|
205
214
|
---
|
|
206
215
|
|
|
207
216
|
### **Configuration Commands**
|
|
@@ -267,12 +276,11 @@ xfarm config logout
|
|
|
267
276
|
Set up a new exploit project:
|
|
268
277
|
|
|
269
278
|
```bash
|
|
270
|
-
xfarm
|
|
279
|
+
xfarm init [OPTIONS]
|
|
271
280
|
```
|
|
272
281
|
|
|
273
282
|
**Options**:
|
|
274
283
|
|
|
275
|
-
- `--edit, -e`: Edit the configuration interactively.
|
|
276
284
|
- `--name`: Exploit name.
|
|
277
285
|
- `--service`: Associated service UUID.
|
|
278
286
|
- `--language`: Programming language.
|
|
@@ -282,7 +290,7 @@ xfarm exploit init [OPTIONS]
|
|
|
282
290
|
Upload the exploit source code to the server:
|
|
283
291
|
|
|
284
292
|
```bash
|
|
285
|
-
xfarm
|
|
293
|
+
xfarm push [OPTIONS]
|
|
286
294
|
```
|
|
287
295
|
|
|
288
296
|
**Options**:
|
|
@@ -295,7 +303,7 @@ xfarm exploit push [OPTIONS]
|
|
|
295
303
|
Get details about the exploit source:
|
|
296
304
|
|
|
297
305
|
```bash
|
|
298
|
-
xfarm
|
|
306
|
+
xfarm log [OPTIONS]
|
|
299
307
|
```
|
|
300
308
|
|
|
301
309
|
**Options**:
|
|
@@ -307,7 +315,7 @@ xfarm exploit info [OPTIONS]
|
|
|
307
315
|
Update to the latest commit:
|
|
308
316
|
|
|
309
317
|
```bash
|
|
310
|
-
xfarm
|
|
318
|
+
xfarm pull [OPTIONS]
|
|
311
319
|
```
|
|
312
320
|
|
|
313
321
|
**Options**:
|
|
@@ -319,13 +327,55 @@ xfarm exploit update [OPTIONS]
|
|
|
319
327
|
Download the exploit source:
|
|
320
328
|
|
|
321
329
|
```bash
|
|
322
|
-
xfarm
|
|
330
|
+
xfarm clone [OPTIONS] [exploit_id] [commit_uuid]
|
|
323
331
|
```
|
|
324
332
|
|
|
333
|
+
**Arguments**:
|
|
334
|
+
|
|
335
|
+
- `exploit_id`: The exploit ID to download.
|
|
336
|
+
- `commit_uuid`: The commit UUID to take the source from (default: latest).
|
|
337
|
+
|
|
325
338
|
**Options**:
|
|
326
339
|
|
|
327
340
|
- `--folder, -f`: Specify target folder.
|
|
328
|
-
|
|
341
|
+
|
|
342
|
+
#### **Edit Exploit Configuration**
|
|
343
|
+
|
|
344
|
+
Edit the exploit configuration (e.g. language, service):
|
|
345
|
+
|
|
346
|
+
```bash
|
|
347
|
+
xfarm edit [OPTIONS]
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
**Options**:
|
|
351
|
+
|
|
352
|
+
- `--name`: The name of the exploit.
|
|
353
|
+
- `--service`: The service UUID of the exploit.
|
|
354
|
+
- `--language`: The programming language of the exploit.
|
|
355
|
+
|
|
356
|
+
#### **Checkout Exploit Commit**
|
|
357
|
+
|
|
358
|
+
Download the specified exploit commit and switch to it:
|
|
359
|
+
|
|
360
|
+
```bash
|
|
361
|
+
xfarm checkout [OPTIONS] {commit_uuid}
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
**Options**:
|
|
365
|
+
|
|
366
|
+
- `--force, -f`: Force the move even if the current commit is not pushed.
|
|
367
|
+
|
|
368
|
+
#### **Flush Flag Queue**
|
|
369
|
+
|
|
370
|
+
Flush the local flag queue to the backend (used if manual submissions were queued locally due to network failure):
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
xfarm flush [OPTIONS] [path]
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
**Options**:
|
|
377
|
+
|
|
378
|
+
- `path`: Optional path to a specific directory or `.flag_queue.json` file.
|
|
329
379
|
|
|
330
380
|
---
|
|
331
381
|
|
|
@@ -342,6 +392,7 @@ xfarm group create [OPTIONS]
|
|
|
342
392
|
**Options**:
|
|
343
393
|
|
|
344
394
|
- `--name`: Group name.
|
|
395
|
+
- `--submit-pool-timeout`: The timeout for the submit pool to wait for new attack results and send flags (default: 3).
|
|
345
396
|
|
|
346
397
|
|
|
347
398
|
#### **Join Attack Group**
|
|
@@ -373,6 +424,55 @@ Shows a table with all existing groups, their IDs, and if there is a worker runn
|
|
|
373
424
|
|
|
374
425
|
---
|
|
375
426
|
|
|
427
|
+
### **Template Commands**
|
|
428
|
+
|
|
429
|
+
Manage exploit templates for quickly starting new exploits:
|
|
430
|
+
|
|
431
|
+
#### **List Templates**
|
|
432
|
+
|
|
433
|
+
```bash
|
|
434
|
+
xfarm template list
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
#### **Add Template**
|
|
438
|
+
|
|
439
|
+
Add a new template from an existing folder:
|
|
440
|
+
|
|
441
|
+
```bash
|
|
442
|
+
xfarm template add [path]
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
#### **Edit Template**
|
|
446
|
+
|
|
447
|
+
Edit an existing template interactively:
|
|
448
|
+
|
|
449
|
+
```bash
|
|
450
|
+
xfarm template edit
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
---
|
|
454
|
+
|
|
455
|
+
### **Submitter Commands**
|
|
456
|
+
|
|
457
|
+
#### **Test Submitter**
|
|
458
|
+
|
|
459
|
+
Test your submitter python script against the backend's flag extraction:
|
|
460
|
+
|
|
461
|
+
```bash
|
|
462
|
+
xfarm submitter-test [OPTIONS] {path} {output}
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
**Arguments**:
|
|
466
|
+
|
|
467
|
+
- `path`: Submitter python script.
|
|
468
|
+
- `output`: Text containing flags according to server REGEX.
|
|
469
|
+
|
|
470
|
+
**Options**:
|
|
471
|
+
|
|
472
|
+
- `--kwargs`: Submitter key-words args (json) (default: {}).
|
|
473
|
+
|
|
474
|
+
---
|
|
475
|
+
|
|
376
476
|
## **Environment Variables**
|
|
377
477
|
|
|
378
478
|
Environment variables can simplify configuration:
|
|
@@ -1,39 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: exploitfarm
|
|
3
|
-
Version: 1.7.8
|
|
4
|
-
Summary: Exploit Farm client
|
|
5
|
-
Home-page: https://github.com/pwnzer0tt1/exploitfarm
|
|
6
|
-
Author: Pwnzer0tt1
|
|
7
|
-
Author-email: pwnzer0tt1@poliba.it
|
|
8
|
-
Classifier: Programming Language :: Python :: 3
|
|
9
|
-
Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
|
|
10
|
-
Classifier: Operating System :: OS Independent
|
|
11
|
-
Requires-Python: >=3.10
|
|
12
|
-
Description-Content-Type: text/markdown
|
|
13
|
-
Requires-Dist: requests>=2.32.5
|
|
14
|
-
Requires-Dist: urllib3>=2.5.0
|
|
15
|
-
Requires-Dist: python-dateutil==2.9.0.post0
|
|
16
|
-
Requires-Dist: pydantic>=2
|
|
17
|
-
Requires-Dist: typing-extensions>=4.7.1
|
|
18
|
-
Requires-Dist: fasteners==0.20
|
|
19
|
-
Requires-Dist: toml==0.10.2
|
|
20
|
-
Requires-Dist: psutil==7.2.1
|
|
21
|
-
Requires-Dist: dirhash==0.5.0
|
|
22
|
-
Requires-Dist: requests-toolbelt==1.0.0
|
|
23
|
-
Requires-Dist: python-socketio[client]>=5.14.1
|
|
24
|
-
Requires-Dist: textual>=3.0.0
|
|
25
|
-
Requires-Dist: typer>=0.16
|
|
26
|
-
Requires-Dist: xfarm
|
|
27
|
-
Dynamic: author
|
|
28
|
-
Dynamic: author-email
|
|
29
|
-
Dynamic: classifier
|
|
30
|
-
Dynamic: description
|
|
31
|
-
Dynamic: description-content-type
|
|
32
|
-
Dynamic: home-page
|
|
33
|
-
Dynamic: requires-dist
|
|
34
|
-
Dynamic: requires-python
|
|
35
|
-
Dynamic: summary
|
|
36
|
-
|
|
37
1
|
# ExploitFarm Python Library and CLI
|
|
38
2
|
|
|
39
3
|
**ExploitFarm** is an advanced tool designed to manage exploits and flag submissions in Attack-Defense CTF competitions. It combines a Python library with a command-line interface (CLI), providing flexibility and efficiency for managing CTF tasks. This documentation provides a comprehensive overview of its features, installation, and usage.
|
|
@@ -202,6 +166,14 @@ xfarm start [OPTIONS] PATH
|
|
|
202
166
|
xfarm start ./my_exploit --pool-size 20 --test
|
|
203
167
|
```
|
|
204
168
|
|
|
169
|
+
### Exploit Execution Environment
|
|
170
|
+
|
|
171
|
+
To protect your exploit source code and maintain a clean workspace, exploits are never executed directly in their project directory. Instead, `xfarm` starts the execution by copying your exploit files into a temporary `__xfarm_run__` folder and runs the exploit from there. This guarantees:
|
|
172
|
+
- **Clean Execution**: Your original directory isn't polluted by runtime artifacts, logs, or temporary files generated by the exploit.
|
|
173
|
+
- **Isolation**: Changes made by the exploit script (e.g., dropping files, compiling binaries) remain isolated.
|
|
174
|
+
|
|
175
|
+
A Git-like ignores system is available: You can use a `.ignore` (only in the root of the exploit folder) to specify files/directories that shouldn't be copied into the `__xfarm_run__` directory and when using `xfarm push`.
|
|
176
|
+
|
|
205
177
|
---
|
|
206
178
|
|
|
207
179
|
### **Configuration Commands**
|
|
@@ -267,12 +239,11 @@ xfarm config logout
|
|
|
267
239
|
Set up a new exploit project:
|
|
268
240
|
|
|
269
241
|
```bash
|
|
270
|
-
xfarm
|
|
242
|
+
xfarm init [OPTIONS]
|
|
271
243
|
```
|
|
272
244
|
|
|
273
245
|
**Options**:
|
|
274
246
|
|
|
275
|
-
- `--edit, -e`: Edit the configuration interactively.
|
|
276
247
|
- `--name`: Exploit name.
|
|
277
248
|
- `--service`: Associated service UUID.
|
|
278
249
|
- `--language`: Programming language.
|
|
@@ -282,7 +253,7 @@ xfarm exploit init [OPTIONS]
|
|
|
282
253
|
Upload the exploit source code to the server:
|
|
283
254
|
|
|
284
255
|
```bash
|
|
285
|
-
xfarm
|
|
256
|
+
xfarm push [OPTIONS]
|
|
286
257
|
```
|
|
287
258
|
|
|
288
259
|
**Options**:
|
|
@@ -295,7 +266,7 @@ xfarm exploit push [OPTIONS]
|
|
|
295
266
|
Get details about the exploit source:
|
|
296
267
|
|
|
297
268
|
```bash
|
|
298
|
-
xfarm
|
|
269
|
+
xfarm log [OPTIONS]
|
|
299
270
|
```
|
|
300
271
|
|
|
301
272
|
**Options**:
|
|
@@ -307,7 +278,7 @@ xfarm exploit info [OPTIONS]
|
|
|
307
278
|
Update to the latest commit:
|
|
308
279
|
|
|
309
280
|
```bash
|
|
310
|
-
xfarm
|
|
281
|
+
xfarm pull [OPTIONS]
|
|
311
282
|
```
|
|
312
283
|
|
|
313
284
|
**Options**:
|
|
@@ -319,13 +290,55 @@ xfarm exploit update [OPTIONS]
|
|
|
319
290
|
Download the exploit source:
|
|
320
291
|
|
|
321
292
|
```bash
|
|
322
|
-
xfarm
|
|
293
|
+
xfarm clone [OPTIONS] [exploit_id] [commit_uuid]
|
|
323
294
|
```
|
|
324
295
|
|
|
296
|
+
**Arguments**:
|
|
297
|
+
|
|
298
|
+
- `exploit_id`: The exploit ID to download.
|
|
299
|
+
- `commit_uuid`: The commit UUID to take the source from (default: latest).
|
|
300
|
+
|
|
325
301
|
**Options**:
|
|
326
302
|
|
|
327
303
|
- `--folder, -f`: Specify target folder.
|
|
328
|
-
|
|
304
|
+
|
|
305
|
+
#### **Edit Exploit Configuration**
|
|
306
|
+
|
|
307
|
+
Edit the exploit configuration (e.g. language, service):
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
xfarm edit [OPTIONS]
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
**Options**:
|
|
314
|
+
|
|
315
|
+
- `--name`: The name of the exploit.
|
|
316
|
+
- `--service`: The service UUID of the exploit.
|
|
317
|
+
- `--language`: The programming language of the exploit.
|
|
318
|
+
|
|
319
|
+
#### **Checkout Exploit Commit**
|
|
320
|
+
|
|
321
|
+
Download the specified exploit commit and switch to it:
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
xfarm checkout [OPTIONS] {commit_uuid}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
**Options**:
|
|
328
|
+
|
|
329
|
+
- `--force, -f`: Force the move even if the current commit is not pushed.
|
|
330
|
+
|
|
331
|
+
#### **Flush Flag Queue**
|
|
332
|
+
|
|
333
|
+
Flush the local flag queue to the backend (used if manual submissions were queued locally due to network failure):
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
xfarm flush [OPTIONS] [path]
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
**Options**:
|
|
340
|
+
|
|
341
|
+
- `path`: Optional path to a specific directory or `.flag_queue.json` file.
|
|
329
342
|
|
|
330
343
|
---
|
|
331
344
|
|
|
@@ -342,6 +355,7 @@ xfarm group create [OPTIONS]
|
|
|
342
355
|
**Options**:
|
|
343
356
|
|
|
344
357
|
- `--name`: Group name.
|
|
358
|
+
- `--submit-pool-timeout`: The timeout for the submit pool to wait for new attack results and send flags (default: 3).
|
|
345
359
|
|
|
346
360
|
|
|
347
361
|
#### **Join Attack Group**
|
|
@@ -373,6 +387,55 @@ Shows a table with all existing groups, their IDs, and if there is a worker runn
|
|
|
373
387
|
|
|
374
388
|
---
|
|
375
389
|
|
|
390
|
+
### **Template Commands**
|
|
391
|
+
|
|
392
|
+
Manage exploit templates for quickly starting new exploits:
|
|
393
|
+
|
|
394
|
+
#### **List Templates**
|
|
395
|
+
|
|
396
|
+
```bash
|
|
397
|
+
xfarm template list
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
#### **Add Template**
|
|
401
|
+
|
|
402
|
+
Add a new template from an existing folder:
|
|
403
|
+
|
|
404
|
+
```bash
|
|
405
|
+
xfarm template add [path]
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
#### **Edit Template**
|
|
409
|
+
|
|
410
|
+
Edit an existing template interactively:
|
|
411
|
+
|
|
412
|
+
```bash
|
|
413
|
+
xfarm template edit
|
|
414
|
+
```
|
|
415
|
+
|
|
416
|
+
---
|
|
417
|
+
|
|
418
|
+
### **Submitter Commands**
|
|
419
|
+
|
|
420
|
+
#### **Test Submitter**
|
|
421
|
+
|
|
422
|
+
Test your submitter python script against the backend's flag extraction:
|
|
423
|
+
|
|
424
|
+
```bash
|
|
425
|
+
xfarm submitter-test [OPTIONS] {path} {output}
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
**Arguments**:
|
|
429
|
+
|
|
430
|
+
- `path`: Submitter python script.
|
|
431
|
+
- `output`: Text containing flags according to server REGEX.
|
|
432
|
+
|
|
433
|
+
**Options**:
|
|
434
|
+
|
|
435
|
+
- `--kwargs`: Submitter key-words args (json) (default: {}).
|
|
436
|
+
|
|
437
|
+
---
|
|
438
|
+
|
|
376
439
|
## **Environment Variables**
|
|
377
440
|
|
|
378
441
|
Environment variables can simplify configuration:
|
|
@@ -1,24 +1,18 @@
|
|
|
1
|
-
import
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
2
3
|
import functools
|
|
3
4
|
import random
|
|
4
5
|
import os
|
|
5
|
-
from exploitfarm.utils.config import ClientConfig
|
|
6
|
-
from exploitfarm.tui.config import inital_config_setup
|
|
7
|
-
from exploitfarm.tui.login import login_required
|
|
8
6
|
from enum import Enum
|
|
9
|
-
import psutil
|
|
10
7
|
import traceback
|
|
11
8
|
import pickle
|
|
12
|
-
from exploitfarm.utils import DEV_MODE
|
|
13
9
|
from posixpath import join as urljoin
|
|
14
|
-
from exploitfarm.utils.reqs import (
|
|
15
|
-
requests_check_json,
|
|
16
|
-
HTTP_TIMEOUT,
|
|
17
|
-
check_req,
|
|
18
|
-
get_session,
|
|
19
|
-
)
|
|
20
|
-
from requests import Session
|
|
21
10
|
import re
|
|
11
|
+
from typing import TYPE_CHECKING
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
import requests
|
|
15
|
+
from requests import Session
|
|
22
16
|
|
|
23
17
|
os_windows = os.name == "nt"
|
|
24
18
|
os_unix = os.name == "posix"
|
|
@@ -39,6 +33,7 @@ class Prio(Enum):
|
|
|
39
33
|
|
|
40
34
|
def nicenessify(priority: Prio = Prio.low, pid: int | None = None):
|
|
41
35
|
try:
|
|
36
|
+
import psutil
|
|
42
37
|
pid = os.getpid() if pid is None else pid
|
|
43
38
|
ps = psutil.Process(pid)
|
|
44
39
|
if not isinstance(priority, Prio):
|
|
@@ -67,12 +62,16 @@ def nicenessify(priority: Prio = Prio.low, pid: int | None = None):
|
|
|
67
62
|
nice_value = psutil.BELOW_NORMAL_PRIORITY_CLASS
|
|
68
63
|
ps.nice(nice_value)
|
|
69
64
|
except Exception as e:
|
|
65
|
+
from exploitfarm.utils import DEV_MODE
|
|
70
66
|
error = traceback.format_exc() if DEV_MODE else ""
|
|
71
67
|
print(f"Error setting priority: {e} {error}")
|
|
72
68
|
pass
|
|
73
69
|
|
|
74
70
|
|
|
75
71
|
def get_config():
|
|
72
|
+
from exploitfarm.utils.config import ClientConfig
|
|
73
|
+
from exploitfarm.tui.config import inital_config_setup
|
|
74
|
+
from exploitfarm.tui.login import login_required
|
|
76
75
|
config = ClientConfig.read()
|
|
77
76
|
if not inital_config_setup(config):
|
|
78
77
|
raise ValueError("It's required to setup the client first")
|
|
@@ -137,6 +136,7 @@ def session(
|
|
|
137
136
|
"Accept-Language": "en-GB,en;q=0.8,it;q=0.7,en-US;q=0.6",
|
|
138
137
|
**additional_headers,
|
|
139
138
|
}
|
|
139
|
+
import requests
|
|
140
140
|
s = requests.Session()
|
|
141
141
|
s.headers.update(headers)
|
|
142
142
|
return s
|
|
@@ -155,7 +155,9 @@ class Store:
|
|
|
155
155
|
if not self.exploit_id:
|
|
156
156
|
raise ValueError("this exploit has to be run with xfarm")
|
|
157
157
|
self.login_token = os.getenv("XFARM_LOGIN_TOKEN", None)
|
|
158
|
-
self.
|
|
158
|
+
self.default_context_id = default_context_id
|
|
159
|
+
from exploitfarm.utils.reqs import get_session
|
|
160
|
+
self.session = get_session(self.login_token)
|
|
159
161
|
if default_context_id is not None:
|
|
160
162
|
self._keycheck(default_context_id, "default_context_id")
|
|
161
163
|
self.default_context_id = default_context_id
|
|
@@ -168,6 +170,14 @@ class Store:
|
|
|
168
170
|
return self.default_context_id
|
|
169
171
|
return None
|
|
170
172
|
|
|
173
|
+
def _requests_check_json(self, *args, **kwargs):
|
|
174
|
+
from exploitfarm.utils.reqs import requests_check_json
|
|
175
|
+
return requests_check_json(*args, **kwargs)
|
|
176
|
+
|
|
177
|
+
def _check_req(self, *args, **kwargs):
|
|
178
|
+
from exploitfarm.utils.reqs import check_req
|
|
179
|
+
return check_req(*args, **kwargs)
|
|
180
|
+
|
|
171
181
|
def _keycheck(self, key: str, what: str = "key"):
|
|
172
182
|
if not isinstance(key, str):
|
|
173
183
|
raise ValueError(f"{what} must be a string")
|
|
@@ -176,7 +186,7 @@ class Store:
|
|
|
176
186
|
if not re.match(r"^[A-Za-z0-9\-\._~()'!*:@,;]+$", key):
|
|
177
187
|
raise ValueError(rf"{what} must match this regex: ^[A-Za-z0-9\-\._~()'!*:@,;$]+$")
|
|
178
188
|
|
|
179
|
-
def get_bytes(self, key: str, default=None, context_id: str | None = None, timeout: int =
|
|
189
|
+
def get_bytes(self, key: str, default=None, context_id: str | None = None, timeout: int = 30) -> bytes:
|
|
180
190
|
context_id = self._get_context_id(context_id)
|
|
181
191
|
self._keycheck(key)
|
|
182
192
|
r = self.session.get(
|
|
@@ -186,9 +196,9 @@ class Store:
|
|
|
186
196
|
)
|
|
187
197
|
if r.status_code == 404:
|
|
188
198
|
return default
|
|
189
|
-
return
|
|
199
|
+
return self._check_req(r).content
|
|
190
200
|
|
|
191
|
-
def get(self, key: str, default=None, context_id: str | None = None, timeout: int =
|
|
201
|
+
def get(self, key: str, default=None, context_id: str | None = None, timeout: int = 30) -> bytes:
|
|
192
202
|
class TmpNotFound:
|
|
193
203
|
pass
|
|
194
204
|
data = self.get_bytes(key, context_id=context_id, default=TmpNotFound, timeout=timeout)
|
|
@@ -196,10 +206,10 @@ class Store:
|
|
|
196
206
|
return default
|
|
197
207
|
return pickle.loads(data)
|
|
198
208
|
|
|
199
|
-
def set_bytes(self, key: str, value: bytes, context_id: str | None = None, timeout: int =
|
|
209
|
+
def set_bytes(self, key: str, value: bytes, context_id: str | None = None, timeout: int = 30):
|
|
200
210
|
self._keycheck(key)
|
|
201
211
|
context_id = self._get_context_id(context_id)
|
|
202
|
-
return
|
|
212
|
+
return self._requests_check_json(
|
|
203
213
|
self.session.put(
|
|
204
214
|
urljoin(self.base_url, f"exploits/{self.exploit_id}/store/key/{key}"),
|
|
205
215
|
data=value,
|
|
@@ -209,14 +219,14 @@ class Store:
|
|
|
209
219
|
)
|
|
210
220
|
)
|
|
211
221
|
|
|
212
|
-
def set(self, key: str, value, context_id: str | None = None, timeout: int =
|
|
222
|
+
def set(self, key: str, value, context_id: str | None = None, timeout: int = 30):
|
|
213
223
|
value = pickle.dumps(value)
|
|
214
224
|
return self.set_bytes(key, value, context_id=context_id, timeout=timeout)
|
|
215
225
|
|
|
216
|
-
def delete(self, key: str, context_id: str | None = None, timeout: int =
|
|
226
|
+
def delete(self, key: str, context_id: str | None = None, timeout: int = 30):
|
|
217
227
|
self._keycheck(key)
|
|
218
228
|
context_id = self._get_context_id(context_id)
|
|
219
|
-
return
|
|
229
|
+
return self._requests_check_json(
|
|
220
230
|
self.session.delete(
|
|
221
231
|
urljoin(self.base_url, f"exploits/{self.exploit_id}/store/key/{key}"),
|
|
222
232
|
params={"context_id": context_id} if context_id else None,
|
|
@@ -224,9 +234,9 @@ class Store:
|
|
|
224
234
|
)
|
|
225
235
|
)
|
|
226
236
|
|
|
227
|
-
def keys(self, timeout: int =
|
|
237
|
+
def keys(self, timeout: int = 30, context_id: str | None = None) -> list[str]:
|
|
228
238
|
context_id = self._get_context_id(context_id)
|
|
229
|
-
return
|
|
239
|
+
return self._requests_check_json(
|
|
230
240
|
self.session.get(
|
|
231
241
|
urljoin(self.base_url, f"exploits/{self.exploit_id}/store/keys"),
|
|
232
242
|
params={ "context_id": context_id } if context_id else None,
|
|
@@ -234,20 +244,20 @@ class Store:
|
|
|
234
244
|
)
|
|
235
245
|
)
|
|
236
246
|
|
|
237
|
-
def contexts(self, timeout: int =
|
|
238
|
-
return
|
|
247
|
+
def contexts(self, timeout: int = 30) -> list[str]:
|
|
248
|
+
return self._requests_check_json(
|
|
239
249
|
self.session.get(
|
|
240
250
|
urljoin(self.base_url, f"exploits/{self.exploit_id}/store/contexts"),
|
|
241
251
|
timeout=timeout,
|
|
242
252
|
)
|
|
243
253
|
)
|
|
244
254
|
|
|
245
|
-
def delete_context(self, context_id: str | None = None, timeout: int =
|
|
255
|
+
def delete_context(self, context_id: str | None = None, timeout: int = 30):
|
|
246
256
|
context_id = self._get_context_id(context_id)
|
|
247
257
|
if not context_id:
|
|
248
258
|
raise ValueError("context_id must be provided to delete it")
|
|
249
259
|
self._keycheck(context_id, "context_id")
|
|
250
|
-
return
|
|
260
|
+
return self._requests_check_json(
|
|
251
261
|
self.session.delete(
|
|
252
262
|
urljoin(self.base_url, f"exploits/{self.exploit_id}/store/context/{context_id}"),
|
|
253
263
|
timeout=timeout,
|