-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathshellforge.py
More file actions
158 lines (137 loc) · 6.08 KB
/
shellforge.py
File metadata and controls
158 lines (137 loc) · 6.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#!/usr/bin/env python3
import argparse
import sys
import time
from rich.console import Console
console = Console()
BANNER = r"""
____ _ _ _ _____
/ ___|| |__ ___| | | ___|__ _ __ __ _ ___
\___ \| '_ \ / _ \ | | |_ / _ \| '__/ _` |/ _ \
___) | | | | __/ | | _| (_) | | | (_| | __/
|____/|_| |_|\___|_|_|_| \___/|_| \__, |\___|
|___/
"""
def main():
console.print(f'[bold red]{BANNER}[/bold red]')
console.print('[dim] Offensive Payload Generator — For authorized use only[/dim]\n')
parser = argparse.ArgumentParser(
prog='shellforge',
description='ShellForge — Offensive payload generation toolkit',
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog='''Examples:
python shellforge.py --revshell --lhost 10.10.10.1 --lport 4444
python shellforge.py --revshell --lhost 10.10.10.1 --lport 4444 --shell bash_tcp
python shellforge.py --webshell
python shellforge.py --webshell php_basic --output ./shells/
python shellforge.py --payload xss
python shellforge.py --payload sqli --encode base64
python shellforge.py --payload lfi --encode url
python shellforge.py --encode-text "hello world" --all-encodings
'''
)
# Reverse shell
rev = parser.add_argument_group('Reverse Shells')
rev.add_argument('--revshell', '-r', action='store_true',
help='Generate reverse shell payloads')
rev.add_argument('--lhost', metavar='IP',
help='Attacker IP for reverse shell')
rev.add_argument('--lport', metavar='PORT', type=int,
help='Attacker port for reverse shell')
rev.add_argument('--shell', metavar='TYPE',
help='Specific shell type (e.g. bash_tcp, python3, php_exec)')
rev.add_argument('--b64', action='store_true',
help='Base64-encode the reverse shell output')
# Web shells
web = parser.add_argument_group('Web Shells')
web.add_argument('--webshell', '-w', metavar='TYPE', nargs='?', const='list',
help='Generate web shell (omit TYPE to list all)')
# Payloads
pay = parser.add_argument_group('Payloads (XSS / SQLi / CMDi / LFI)')
pay.add_argument('--payload', '-p', metavar='CATEGORY',
help='Payload category: xss | sqli | cmdi | lfi')
pay.add_argument('--encode', '-e', metavar='ENCODING', default='plain',
help='Encoding: plain | base64 | url | double_url | hex | html | unicode | js_hex')
pay.add_argument('--all-encodings', action='store_true',
help='Show all encodings for the first payload in category')
# Encoder
enc = parser.add_argument_group('Encoder / Decoder')
enc.add_argument('--encode-text', metavar='TEXT',
help='Encode a custom string')
enc.add_argument('--decode-b64', metavar='TEXT',
help='Decode a base64 string')
# Output
out = parser.add_argument_group('Output')
out.add_argument('--output', '-o', metavar='PATH',
help='Output directory (web shells) or file prefix (payloads)')
out.add_argument('--export', metavar='FORMAT', choices=['json','html','txt'],
help='Export results: json | html | txt')
args = parser.parse_args()
if not any([args.revshell, args.webshell, args.payload, args.encode_text, args.decode_b64]):
parser.print_help()
sys.exit(0)
export_data = {}
# --- Reverse shells ---
if args.revshell:
if not args.lhost or not args.lport:
console.print('[red][!] --revshell requires --lhost and --lport[/red]')
sys.exit(1)
from modules.revshell import RevShell
rs = RevShell()
results = rs.run(args.lhost, args.lport, shell_type=args.shell, encode=args.b64)
if results:
export_data['reverse_shells'] = results if isinstance(results, list) else [results]
# --- Web shells ---
if args.webshell:
from modules.webshell import WebShell
ws = WebShell()
key = None if args.webshell == 'list' else args.webshell
ws.run(shell_type=key, output_dir=args.output)
# --- Payloads ---
if args.payload:
from modules.payloads import PayloadGen
pg = PayloadGen()
results = pg.run(
category=args.payload,
encoding=args.encode,
show_all_encodings=args.all_encodings
)
if results:
export_data[f'payloads_{args.payload}'] = results
# --- Encode text ---
if args.encode_text:
from modules.encoder import all_encodings, apply
console.print('\n[bold cyan]=== ENCODER ===[/bold cyan]\n')
text = args.encode_text
if args.all_encodings:
from modules.payloads import PayloadGen
pg = PayloadGen()
pg._print_all_encodings(text, 'Custom')
else:
result = apply(text, args.encode)
console.print(f'[dim]Input:[/dim] {text}')
console.print(f'[dim]Encoding:[/dim] {args.encode}')
console.print(f'[green]Result:[/green] {result}\n')
# --- Decode base64 ---
if args.decode_b64:
import base64
console.print('\n[bold cyan]=== BASE64 DECODER ===[/bold cyan]\n')
try:
decoded = base64.b64decode(args.decode_b64).decode('utf-8', errors='replace')
console.print(f'[green]Decoded:[/green] {decoded}\n')
except Exception as e:
console.print(f'[red][!] Decode error: {e}[/red]')
# --- Export ---
if args.export and export_data:
stamp = time.strftime('%Y%m%d_%H%M%S')
prefix = args.output or f'shellforge_{stamp}'
from modules.reporter import Reporter
rep = Reporter(export_data)
if args.export == 'json':
rep.export_json(f'{prefix}.json')
elif args.export == 'html':
rep.export_html(f'{prefix}.html')
elif args.export == 'txt':
rep.export_txt(f'{prefix}.txt')
if __name__ == '__main__':
main()