Autarch/modules/android_sms.py
DigiJ ffe47c51b5 Initial public release — AUTARCH v1.0.0
Full security platform with web dashboard, 16 Flask blueprints, 26 modules,
autonomous AI agent, WebUSB hardware support, and Archon Android companion app.

Includes Hash Toolkit, debug console, anti-stalkerware shield, Metasploit/RouterSploit
integration, WireGuard VPN, OSINT reconnaissance, and multi-backend LLM support.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 03:57:32 -08:00

360 lines
14 KiB
Python

"""
Android SMS/RCS Manipulation - Insert, delete, spoof messages with custom timestamps
"""
DESCRIPTION = "Android SMS/RCS manipulation (add, remove, spoof dates, RCS inject)"
AUTHOR = "AUTARCH"
VERSION = "1.0"
CATEGORY = "offense"
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
class AndroidSms:
"""Interactive menu for SMS/RCS manipulation."""
def __init__(self):
from core.android_exploit import get_exploit_manager
from core.hardware import get_hardware_manager
self.mgr = get_exploit_manager()
self.hw = get_hardware_manager()
self.serial = None
def _select_device(self):
devices = self.hw.adb_devices()
if not devices:
print(" No ADB devices connected.")
return
if len(devices) == 1:
self.serial = devices[0]['serial']
print(f" Selected: {self.serial}")
return
print("\n Select device:")
for i, d in enumerate(devices, 1):
model = d.get('model', '')
print(f" {i}) {d['serial']} {model}")
try:
choice = int(input(" > ").strip())
if 1 <= choice <= len(devices):
self.serial = devices[choice - 1]['serial']
except (ValueError, EOFError, KeyboardInterrupt):
pass
def _ensure_device(self):
if not self.serial:
self._select_device()
return self.serial is not None
def show_menu(self):
print(f"\n{'='*55}")
print(" SMS / RCS Manipulation")
print(f"{'='*55}")
print(f" Device: {self.serial or '(none)'}")
print()
print(" ── SMS (content provider) ──")
print(" [1] List SMS Messages")
print(" [2] Insert SMS (spoofed)")
print(" [3] Insert Batch SMS")
print(" [4] Edit SMS")
print(" [5] Delete SMS by ID")
print(" [6] Delete SMS by Number")
print(" [7] Delete ALL SMS")
print()
print(" ── RCS (Google Messages) ── [ROOT]")
print(" [8] Check RCS Support")
print(" [9] List RCS Messages")
print(" [a] Insert RCS Message (spoofed)")
print(" [b] Delete RCS Message")
print()
print(" [s] Select Device")
print(" [0] Back")
print()
def list_sms(self):
if not self._ensure_device():
return
try:
addr = input(" Filter by number (Enter for all): ").strip() or None
limit = input(" Limit [50]: ").strip()
limit = int(limit) if limit else 50
except (EOFError, KeyboardInterrupt, ValueError):
return
result = self.mgr.sms_list(self.serial, limit=limit, address=addr)
if not result['success']:
print(f" Error: {result.get('error', 'Failed')}")
return
print(f"\n Found {result['count']} messages:")
print(f" {'ID':<6} {'Type':<8} {'Address':<16} {'Date':<20} Body")
print(f" {'-'*75}")
for m in result['messages']:
body = m.get('body', '')
if len(body) > 40:
body = body[:40] + '...'
date = m.get('date_readable', m.get('date', '?'))
print(f" {m.get('_id','?'):<6} {m.get('type_label','?'):<8} {m.get('address','?'):<16} {date:<20} {body}")
def insert_sms(self):
if not self._ensure_device():
return
try:
print("\n Insert Spoofed SMS")
print(f" {'-'*40}")
address = input(" Phone number: ").strip()
if not address:
return
body = input(" Message body: ").strip()
if not body:
return
print(" Type: 1=inbox (received), 2=sent, 3=draft")
msg_type = input(" Type [inbox]: ").strip() or 'inbox'
date = input(" Date (YYYY-MM-DD) [today]: ").strip() or None
time_val = input(" Time (HH:MM:SS) [now]: ").strip() or None
read = input(" Mark as read? [Y/n]: ").strip().lower() != 'n'
except (EOFError, KeyboardInterrupt):
return
print(" Inserting...")
result = self.mgr.sms_insert(self.serial, address, body,
date_str=date, time_str=time_val,
msg_type=msg_type, read=read)
if result['success']:
print(f" SMS inserted:")
print(f" From/To: {result['address']}")
print(f" Date: {result['date']}")
print(f" Type: {result['type']}")
print(f" Body: {result['body'][:60]}")
else:
print(f" Error: {result.get('error', 'Failed')}")
def insert_batch(self):
if not self._ensure_device():
return
print("\n Batch SMS Insert")
print(" Enter messages one per line. Format:")
print(" number|body|YYYY-MM-DD|HH:MM:SS|type")
print(" Type is inbox/sent. Date/time optional. Empty line to finish.")
print()
messages = []
while True:
try:
line = input(" > ").strip()
except (EOFError, KeyboardInterrupt):
break
if not line:
break
parts = line.split('|')
if len(parts) < 2:
print(" Need at least: number|body")
continue
msg = {'address': parts[0].strip(), 'body': parts[1].strip()}
if len(parts) >= 3 and parts[2].strip():
msg['date'] = parts[2].strip()
if len(parts) >= 4 and parts[3].strip():
msg['time'] = parts[3].strip()
if len(parts) >= 5 and parts[4].strip():
msg['type'] = parts[4].strip()
messages.append(msg)
print(f" Queued: {msg['address']} -> {msg['body'][:30]}")
if not messages:
print(" No messages to insert.")
return
print(f"\n Inserting {len(messages)} messages...")
result = self.mgr.sms_bulk_insert(self.serial, messages)
print(f" Done: {result['inserted']}/{result['total']} inserted successfully.")
def edit_sms(self):
if not self._ensure_device():
return
try:
sms_id = input(" SMS _id to edit: ").strip()
if not sms_id:
return
print(" Leave fields blank to keep current value.")
body = input(" New body (or Enter to skip): ").strip() or None
address = input(" New address (or Enter to skip): ").strip() or None
date = input(" New date YYYY-MM-DD (or Enter): ").strip() or None
time_val = input(" New time HH:MM:SS (or Enter): ").strip() or None
msg_type = input(" New type inbox/sent (or Enter): ").strip() or None
except (EOFError, KeyboardInterrupt):
return
result = self.mgr.sms_update(self.serial, sms_id, body=body, address=address,
date_str=date, time_str=time_val, msg_type=msg_type)
if result['success']:
print(f" SMS {sms_id} updated.")
else:
print(f" Error: {result.get('error', 'Failed')}")
def delete_by_id(self):
if not self._ensure_device():
return
try:
sms_id = input(" SMS _id to delete: ").strip()
except (EOFError, KeyboardInterrupt):
return
if not sms_id:
return
result = self.mgr.sms_delete(self.serial, sms_id=sms_id)
if result['success']:
print(f" Deleted SMS #{sms_id}")
else:
print(f" Error: {result.get('error', result.get('output', 'Failed'))}")
def delete_by_number(self):
if not self._ensure_device():
return
try:
address = input(" Phone number to delete all messages from: ").strip()
except (EOFError, KeyboardInterrupt):
return
if not address:
return
try:
confirm = input(f" Delete ALL SMS from {address}? [y/N]: ").strip().lower()
except (EOFError, KeyboardInterrupt):
return
if confirm != 'y':
print(" Cancelled.")
return
result = self.mgr.sms_delete(self.serial, address=address, delete_all_from=True)
if result['success']:
print(f" Deleted all SMS from {address}")
else:
print(f" Error: {result.get('error', 'Failed')}")
def delete_all(self):
if not self._ensure_device():
return
try:
confirm = input(" DELETE ALL SMS on device? Type 'YES': ").strip()
except (EOFError, KeyboardInterrupt):
return
if confirm != 'YES':
print(" Cancelled.")
return
result = self.mgr.sms_delete_all(self.serial)
if result['success']:
print(" All SMS deleted.")
else:
print(f" Error: {result.get('output', 'Failed')}")
def rcs_check(self):
if not self._ensure_device():
return
print(" Checking RCS support...")
info = self.mgr.rcs_check_support(self.serial)
print(f"\n RCS Available: {'YES' if info['rcs_available'] else 'NO'}")
print(f" Messaging App: {info.get('messaging_app', 'not found')}")
print(f" Database: {info.get('database', 'not found (need root)')}")
def rcs_list_msgs(self):
if not self._ensure_device():
return
try:
limit = input(" Limit [50]: ").strip()
limit = int(limit) if limit else 50
except (EOFError, KeyboardInterrupt, ValueError):
return
print(" Fetching RCS messages (requires root)...")
result = self.mgr.rcs_list(self.serial, limit=limit)
if not result['success']:
print(f" Error: {result.get('error', 'Failed')}")
return
print(f"\n Found {result['count']} messages:")
print(f" {'ID':<6} {'Proto':<6} {'Date':<20} {'Conv':<20} Text")
print(f" {'-'*80}")
for m in result['messages']:
text = m.get('text', '')
if len(text) > 35:
text = text[:35] + '...'
conv = m.get('conversation_name', '')[:18]
print(f" {m.get('message_id','?'):<6} {m.get('protocol','?'):<6} {m.get('timestamp_readable','?'):<20} {conv:<20} {text}")
def rcs_insert_msg(self):
if not self._ensure_device():
return
try:
print("\n Insert Spoofed RCS Message (requires root)")
print(f" {'-'*45}")
address = input(" Phone number / contact: ").strip()
if not address:
return
body = input(" Message body: ").strip()
if not body:
return
sender = input(" Sender display name (or Enter for number): ").strip() or None
direction = input(" Direction - incoming/outgoing [incoming]: ").strip().lower()
is_out = direction.startswith('out')
date = input(" Date (YYYY-MM-DD) [today]: ").strip() or None
time_val = input(" Time (HH:MM:SS) [now]: ").strip() or None
except (EOFError, KeyboardInterrupt):
return
print(" Injecting RCS message...")
result = self.mgr.rcs_insert(self.serial, address, body,
date_str=date, time_str=time_val,
sender_name=sender, is_outgoing=is_out)
if result['success']:
print(f" RCS message injected:")
print(f" Address: {result['address']}")
print(f" Date: {result['date']}")
print(f" Protocol: {result['protocol']}")
print(f" Dir: {'outgoing' if result['is_outgoing'] else 'incoming'}")
print(f" Body: {result['body'][:60]}")
else:
print(f" Error: {result.get('error', 'Failed')}")
def rcs_delete_msg(self):
if not self._ensure_device():
return
try:
msg_id = input(" RCS message _id to delete: ").strip()
except (EOFError, KeyboardInterrupt):
return
if not msg_id:
return
print(" Deleting RCS message (requires root)...")
result = self.mgr.rcs_delete(self.serial, int(msg_id))
if result['success']:
print(f" Deleted RCS message #{msg_id}")
else:
print(f" Error: {result.get('error', 'Failed')}")
def run_interactive(self):
while True:
self.show_menu()
try:
choice = input(" Select > ").strip().lower()
except (EOFError, KeyboardInterrupt):
break
if choice == '0':
break
actions = {
'1': self.list_sms,
'2': self.insert_sms,
'3': self.insert_batch,
'4': self.edit_sms,
'5': self.delete_by_id,
'6': self.delete_by_number,
'7': self.delete_all,
'8': self.rcs_check,
'9': self.rcs_list_msgs,
'a': self.rcs_insert_msg,
'b': self.rcs_delete_msg,
's': self._select_device,
}
action = actions.get(choice)
if action:
action()
else:
print(" Invalid choice.")
def run():
m = AndroidSms()
m.run_interactive()